def makeurl(self, base_url, name, query, fragment): """ This is the same as what urlparse.urlunsplit does, except that it knows 'base_url' should be used as-is, and to add .html to name. """ url = base_url + name + '.html' url += ifelse(query and len(query), '?' + query, '') url += ifelse(fragment and len(fragment), '#' + fragment, '') return url
def span(context, classname=None, style=None, id=None, text=None): """ |!Usage|{{{<<span class style id text>>}}}| |!Description|Create an inline element (like <span>).| |!Example|{{{<<span "foo" "color:red; font-weight: bold;" "id456" "I am //italic// here">>}}}| |!Result|<<span "foo" "color:red; font-weight: bold;" "id456" "I am //italic// here">>| |!Notes|Generally speaking, this is meant to be used to create empty elements that are subsequently populated via Javascript. However, the {{{text}}} argument will be evaluated as wikitext so you can insert content directly, if desired.<br><br>Use an empty string to leave an attribute undefined.| """ classname = ifelse(classname is not None, classname.text, None) style = ifelse(style is not None, style.text, None) id = ifelse(id is not None, id.text, None) span = SPAN(classname, style, id) if text is not None: span.append(eval_wiki_text(context, text.text)) return span
def div(context, classname=None, style=None, id=None, text=None): """ |!Usage|{{{<<div class style id text>>}}}| |!Description|Create a block element (like <div>).| |!Example|{{{<<div "foo" "color:green; border: 1px solid red;" "id123" "I am //italic// here">>}}}| |!Result|<<div "foo" "color:green; border: 1px solid red;" "id123" "I am //italic// here">>| |!Notes|Generally speaking, this is meant to be used to create empty elements that are subsequently populated via Javascript. However, the {{{text}}} argument will be evaluated as wikitext so you can insert content directly, if desired.<br><br>Use an empty string to leave an attribute undefined.| """ classname = ifelse(classname is not None, classname.text, None) style = ifelse(style is not None, style.text, None) id = ifelse(id is not None, id.text, None) div = DIV(classname, style, id) if text is not None: div.append(eval_wiki_text(context, text.text)) return div
def HEAD(encoding='utf-8', title=None, stylesheet='css/wikklytext.css', styletext=u'', pre_head=u'', post_head=u'', baseurl=u'', sitename=u'', reqheaders={}): head = u'' #head += u"""<?xml version="1.0" encoding="UTF-8"?>\n""" head += u"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> %s <!-- Generated by WikklyText, http://wikklytext.com --> <meta http-equiv="Content-Type" content="%s; charset=%s"/> """ % (pre_head, content_type_for_xhtml(reqheaders), encoding) # add stylesheet head += u'<link href="%s" rel="stylesheet" type="text/css"/>' % \ ifelse(len(baseurl), '%s/%s' % (baseurl,stylesheet), stylesheet) # add extra styling head += u'<style type="text/css">%s</style>' % styletext # add favicon head += u'<link rel="shortcut icon" href="%sfavicon.png" type="image/png"/>' % \ ifelse(len(baseurl), '%s/' % baseurl, '') head += u'<link rel="icon" href="%sfavicon.png" type="image/png"/>' % \ ifelse(len(baseurl), '%s/' % baseurl, '') # add RSS feed pointer head += '<link rel="alternate" type="application/rss+xml" title="%s RSS" href="%srss.xml" />' % \ (sitename, ifelse(len(baseurl), '%s/' % baseurl, '')) # <title> required, even if empty, for XHTML head += u'<title>%s</title>' % (title or '') head += post_head head += u'</head>' return head.encode(encoding)
def get_cell_alignment(self, node): "Calculate text alignment for TableCell node. Returns 'left', 'center', or 'right'" head = self.cell_leading_text(node) tail = self.cell_trailing_text(node) headsp = ifelse(re.match('^\s+', head), True, False) tailsp = ifelse(re.match('.*\s+$', tail), True, False) if self.is_header_cell(node): # per tiddlywiki, nospace == center justify (for headers) if (not headsp and not tailsp) or (headsp and tailsp): return 'center' elif not headsp and tailsp: return 'left' else: return 'right' else: # per tiddlywiki, nospace == left justify (for data cells) if headsp and tailsp: return 'center' elif (not headsp and tailsp) or (not headsp and not tailsp): return 'left' else: return 'right'
def layoutEditUser(wiki, loginUID, editUID=None): """ Layout a page to edit a user. loginUID = UID of logged-in user editUID = UID to create/edit (if None, create new user) Page must provide a form with actions as shown below. """ h = pageHeader(wiki, None, 'Edit User', loginUID=loginUID) h += '<div class="wikkly-item-header"><span class="wikkly-item-title">Editing User</span></div>' h += '<div class="wikkly-item-content">' # note: All unicode strings will be converted to UTF-8 in the process of wikifying, # so no explicit encoding is needed here. the server has to remember to decode them. f = u'' if '0' not in wiki.user_all_UIDs(): f += u'@@You are the first user, and will therefore be the root user.<br><br>You must set a username and password before continuing.<br><br>@@\n' f += u'<html>' f += u'<form action="DoServerCmd.html" method="post">' f += u'<fieldset class="wikkly-form">' if editUID is None or not wiki.user_valid_UID(editUID): name = u'' email = u'' else: name = wiki.user_get_username(editUID) email = wiki.user_get_email(editUID) f += u'<table>' f += u'<tr><td>Username:</td><td colspan="2"><input class="wikkly-edit-input" type="text" name="username" value="%s"/></td></tr>' % \ safehtml(name) f += u'<tr><td>Email address:</td><td colspan="2"><input class="wikkly-edit-input" type="text" name="email" value="%s"/></td></tr>' % \ safehtml(email) f += u'<tr><td>Password:</td><td colspan="2"><input class="wikkly-edit-input" type="password" name="password1" value=""/></td></tr>' f += u'<tr><td>Confirm Password:</td><td colspan="2"><input class="wikkly-edit-input" type="password" name="password2" value=""/></td></tr>' # only root user can change safe_mode settings if loginUID == '0': f += u'<tr><td>Layout mode:</td><td>' f += u'<select name="safe_mode">' f += u' <option %s value="Safe">Safe Mode</option>' % \ ifelse(wiki.user_get_safemode(editUID), u'selected="selected"', u'') f += u' <option %s value="Full">Full Mode</option>' % \ ifelse(not wiki.user_get_safemode(editUID), u'selected="selected"', u'') f += u'</select></td></tr>' f += u'</table>' f += u'<input type="hidden" name="cmd" value="saveUser"/>' # this is checked vs. logged-in UID, but this is needed here so the root user can # edit other users profiles if editUID is not None: f += u'<input type="hidden" name="uid" value="%s"/>' % editUID else: f += u'<input type="hidden" name="uid" value=""/>' if editUID is None or not wiki.user_valid_UID(editUID): f += u'<input type="submit" value="Create User"/>' else: f += u'<input type="submit" value="Save Settings"/>' f += u'</fieldset>' f += u'</form>' f += u'</html>' # need to run w/safe_mode=False so use 'AutoContent' user # (I escaped text above to make sure it was safe) h += render(wiki, f, UID=wiki.user_getUIDs('AutoContent')[0]) h += '</div>' h += pageFooter(wiki, None) return h
def layoutEditItem(wiki, itemname, defaultItem, loginUID): """ Layout a page for editing the named item. Page must provide a form with action as shown below. """ from wikklytext.store import tags_join item = wiki.getitem(itemname) if item is None: item = defaultItem oldname = '' else: oldname = item.name if item is defaultItem: h = pageHeader(wiki, 'newitem', 'New Item', loginUID=loginUID) else: h = pageHeader(wiki, None, 'Editing Item', loginUID=loginUID) if wiki.user_valid_UID(itemname): name = wiki.user_get_username(itemname) h += '<div class="wikkly-item-header"><span class="wikkly-item-title">Editing: %s</span></div>' % \ utf8(safehtml(name)) else: h += '<div class="wikkly-item-header"><span class="wikkly-item-title">Editing: %s</span></div>' % \ utf8(safehtml(itemname)) h += '<div class="wikkly-item-content">' # note: All unicode strings will be converted to UTF-8 in the process of wikifying, # so no explicit encoding is needed here. the server has to remember to decode them. f = u'<html>' f += u'<form action="DoServerCmd.html" method="post">' f += u'<fieldset class="wikkly-form">' # if name is a UID, show author name instead (and make it non-editable) if wiki.user_valid_UID(itemname): name = wiki.user_get_username(itemname) f += u'Name: <b>%s</b><br/>' % safehtml(name) # put name in hidden item instead f += u'<input type="hidden" name="itemName" value="%s"/>' % safehtml( itemname) else: f += u'Name: <input class="wikkly-edit-input" type="text" name="itemName" value="%s"/><br/>' % \ safehtml(itemname) f += u'<textarea class="wikkly-edit-textarea" name="content" cols="80" rows="25">' txt = item.content # escape any </html> tags so won't end early txt = txt.replace('</html>', '</html>') f += txt f += u'</textarea><br/>' f += u'Tags: <input class="wikkly-edit-input" type="text" name="tags" value="%s"/><br/>' % \ safehtml(tags_join(item.tag_list())) f += u' ' * 10 + '<sup>Enter space-separate tags, using [[braces if needed]].</sup><br/>' f += u'Markup style: <select name="content_type">' f += u' <option %s value="WikklyText">WikklyText</option>' % \ ifelse(item.content_type=='WikklyText', u'selected="selected"', u'') f += u' <option %s value="TiddlyWiki">TiddlyWiki</option>' % \ ifelse(item.content_type=='TiddlyWiki', u'selected="selected"', u'') f += u'</select><br/><br/>' f += u'<input type="hidden" name="oldItemName" value="%s"/>' % oldname f += u'<input type="hidden" name="cmd" value="completeEdit"/>' f += u'<input type="hidden" name="ctime" value="%s"/>' % item.ctime.to_store( ) f += u'<input type="submit" name="btn_save" value="Save"/> ' if len(oldname): # don't show delete button on new items f += u'<input type="submit" name="btn_delete" value="Delete Item"/><br/>' f += u'</fieldset>' f += u'</form>' f += u'</html>' h += render(wiki, f, UID='0') h += '</div>' h += pageFooter(wiki, None) return h
def layoutAdminPage(wiki, loginUID, need_restart=False): """ Layout main admin page. Page must provide a form with actions as shown below. """ import wikklytext.version as VER import boodebr.version as BVER import wsgifront.version as WSVER import sys h = pageHeader(wiki, 'admin', 'Administration', loginUID=loginUID) h += '<div class="wikkly-item-header"><span class="wikkly-item-title">Wiki Administration</span></div>' h += '<div class="wikkly-item-content">' # note: All unicode strings will be converted to UTF-8 in the process of wikifying, # so no explicit encoding is needed here. the server has to remember to decode them. t = u'' t += u'!!!Site Configuration\n' # provide links for commonly edited configuration items for name in [ 'DefaultTiddlers', 'MainMenu', 'SiteTitle', 'SiteSubtitle', 'MarkupPreHead', 'MarkupPostHead', 'MarkupPreBody', 'MarkupPostBody', 'StyleSheet' ]: if wiki.getitem(name) is None: extra = '<br>^^@@No ~%s currently defined. Click above link to create it.@@^^' % name else: extra = '' t += u'* [[%s|DoServerCmd?%s]]%s\n' % \ (name, urlencode({'cmd':'editItem', 'name': name}), extra) t += '!!!Logs\n' t += '* [[Recent hits|DoServerCmd?cmd=logRecentHits]] ' t += '^^' p = {'cmd': 'logRecentHits', 'type': metadata.LOG_PAGEVIEW} t += '([[Content|DoServerCmd?%s]]) ' % urlencode(p) p = {'cmd': 'logRecentHits', 'type': metadata.LOG_ERRORMSG} t += '([[Errors|DoServerCmd?%s]]) ' % urlencode(p) p = {'cmd': 'logRecentHits', 'type': metadata.LOG_SETUID} t += '([[Set UID|DoServerCmd?%s]]) ' % urlencode(p) p = {'cmd': 'logRecentHits', 'type': metadata.LOG_FEED} t += '([[RSS|DoServerCmd?%s]]) ' % urlencode(p) t += '^^\n' t += '* [[Hits by page|DoServerCmd?cmd=logHitsByPage]]\n' t += '* [[Hits by days|DoServerCmd?cmd=logHitsByDates]]\n' t += '\n' t += u'!!!!!User-defined filters\n\n' t += u'* [[Hits on user filters|DoServerCmd?cmd=logHitsByUserFilters]]\n' t += u'Enter filters, one per line, into the following box. Filters are SQL "{{tt{LIKE}}}" clauses to ' t += u'be matched against server requests. For example, the filter {{{%.png%}}} would match ' t += u'the requests: {{{\n' t += u'GET /favicon.png HTTP/1.1\n' t += u'GET /files/image.png HTTP/1.1\n' t += u'}}}\n' t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<textarea name="filters" rows="10" cols="40">%s</textarea><br/>' % \ '\n'.join(wiki.get_request_log_filters()) t += u'<input type="hidden" name="cmd" value="setUserLogFilters"/>' t += u'<input type="submit" name="Set" value="Save Filters"/>' t += u'</fieldset>' t += u'</form></html>\n' t += '!!!Users\n' p = {'cmd': 'editUser', 'uid': ''} t += '* [[Create new user|DoServerCmd?%s]]\n\n' % urlencode(p) users = [(uid, wiki.user_get_username(uid)) for uid in wiki.user_all_UIDs()] users.sort(lambda a, b: cmp(a[1], b[1])) t += "|Existing Users|c\n" t += '|!Username|!Can login?|!Safe mode?|!Email|!Edit|\n' for uid, name in users: p = {'cmd': 'editUser', 'uid': uid} if wiki.user_get_safemode(uid): safe = 'True' else: safe = '@@False@@' # highlight users who run in full mode if uid == '0': fname = '!{{{%s}}}<br>{{grayout{^^(Root User)^^}}}' % safe_code( name) else: fname = '!{{{%s}}}' % safe_code(name) if wiki.user_can_login(uid): canlog = '@@Yes@@' else: canlog = 'No' t += '|%s | %s | %s | {{{%s}}} | [[edit|DoServerCmd?%s]] |\n' % \ (fname, canlog, safe, safe_code(wiki.user_get_email(uid)), urlencode(p)) t += u"<<set storage_form <quote>" t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<select name="storage_type">' t += u'<option %s value="ram">ram</option>' % \ ifelse(wiki.get_session_storage() == 'ram', 'selected="selected"', '') t += u'<option %s value="file">file</option>' % \ ifelse(wiki.get_session_storage() == 'file', 'selected="selected"', '') t += u'</select>' + ' ' * 2 t += u'<input type="hidden" name="cmd" value="setSessionStorage"/>' t += u'<input type="submit" name="Set" value="Set Storage Type"/>' t += u'</fieldset>' t += u'</form></html>\n' t += u'</quote>>>\n' t += u"<<set timeout_form <quote>" t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<input type="text" name="timeout" value="%s"/>' % str( wiki.get_session_timeout()) t += ' ' * 2 t += u'<input type="hidden" name="cmd" value="setSessionTimeout"/>' t += u'<input type="submit" name="Set" value="Set Timeout"/>' t += u'</fieldset>' t += u'</form></html>\n' t += u'</quote>>>\n' t += u"<<set timelimit_form <quote>" t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<input type="text" name="timelimit" value="%s"/>' % str( wiki.get_safemode_timelimit()) t += ' ' * 2 t += u'<input type="hidden" name="cmd" value="setSafemodeTimelimit"/>' t += u'<input type="submit" name="Set" value="Set Time Limit"/>' t += u'</fieldset>' t += u'</form></html>\n' t += u'</quote>>>\n' t += u'<<set debug_form <quote>' t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<select name="debug_flag">' t += u'<option %s value="off">Off</option>' % \ ifelse(wiki.get_debug_flag(), '', 'selected="selected"') t += u'<option %s value="on">On</option>' % \ ifelse(wiki.get_debug_flag(), 'selected="selected"', '') t += '</select>' + ' ' * 2 t += u'<input type="submit" name="Set" value="Set debug flag"/>' t += u'<input type="hidden" name="cmd" value="setDebugFlag"/>' t += u'</fieldset>' t += u'</form></html>' t += u'</quote>>>\n' t += u'<<set cache_form <quote>' t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'Enable? <select name="cache_flag">' t += u'<option %s value="off">Off</option>' % \ ifelse(wiki.get_cache_flag(), '', 'selected="selected"') t += u'<option %s value="on">On</option>' % \ ifelse(wiki.get_cache_flag(), 'selected="selected"', '') t += '</select>' + ' ' * 2 t += u'<br/>Expiration (seconds): <input type="text" name="expire_time" value="%s" size="6"/>' % str( wiki.get_cache_expire_time()) t += u'<br/>Clean interval (accesses): <input type="text" name="clean_interval" value="%s" size="6"/><br/>' % str( wiki.get_cache_clean_interval()) t += u'<input type="submit" name="Set" value="Save cache settings"/>' t += u'<input type="hidden" name="cmd" value="setCacheConfig"/>' t += u'</fieldset>' t += u'</form></html>' t += u'</quote>>>\n' t += u'<<set cache_help <quote>' t += u'<<div "" "font-size: .8em" "" """\n' t += u'* //Enable//: Turn cache on/off\n' t += u'* //Expiration//: Expiration time (seconds) for items added to the cache\n' t += u'* //Clean interval//: Clear out expired items (approximately) once per this many cache accesses\n' t += u'You may want to turn caching off when running on a USB drive, to minimize writes.\n' t += u'""">>' t += u'</quote> >>' t += u'<<set metadb_form <quote>' t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<select name="metadb_flag">' t += u'<option %s value="off">Off</option>' % \ ifelse(wiki.get_metadb_flag(), '', 'selected="selected"') t += u'<option %s value="on">On</option>' % \ ifelse(wiki.get_metadb_flag(), 'selected="selected"', '') t += '</select>' + ' ' * 2 t += u'<input type="submit" name="Set" value="Set metadb flag"/>' t += u'<input type="hidden" name="cmd" value="setMetadbFlag"/>' t += u'</fieldset>' t += u'</form></html>' t += u'</quote>>>\n' t += u'<<set unknown_camelword_form <quote>' t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<select name="unknown_camelword_flag">' t += u'<option %s value="off">Off</option>' % \ ifelse(wiki.get_link_unknown_camelwords(), '', 'selected="selected"') t += u'<option %s value="on">On</option>' % \ ifelse(wiki.get_link_unknown_camelwords(), 'selected="selected"', '') t += '</select>' + ' ' * 2 t += u'<input type="submit" name="Set" value="Set camelwords flag"/>' t += u'<input type="hidden" name="cmd" value="setUnknownCamelwordsFlag"/>' t += u'</fieldset>' t += u'</form></html>' t += u'</quote>>>\n' t += u'!!!Plugins\n' t += '[[Plugins|%s/api/plugins]]\n' % wiki.getRT_baseurl() t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'Enter additional directories to search for plugins, in addition to ' t += u'the default location (<tt>%s</tt>). Enter one directory per line.<br/>' % wiki.get_plugin_path( ) t += u'<textarea name="plugindirs" rows="10" cols="40">%s</textarea><br/>' % \ ('\n'.join(wiki.get_user_plugin_dirs())) t += u'<input type="hidden" name="cmd" value="setUserPluginDirs"/>' t += u'<input type="submit" name="Set" value="Save Plugin Directories"/>' t += u'</fieldset>' t += u'</form></html>\n' t += u'!!!Server Configuration\n' if need_restart: t += '<<warnbox "Need Restart" "You must restart the server for changes to take effect.">>\n' t += '|!Parameter|!Current Value|!Adjust|\n' t += '|!Session storage<br>~~@@CAUTION@@: I do not recommend using "file" sessions if your wiki is stored on a network drive.<br>For USB drives, you may want to set this to {{{ram}}} to minimize writes.~~| %s |<<get storage_form>>|\n' % wiki.get_session_storage( ) t += '|!Session timeout<br>~~(minutes)~~| %s |<<get timeout_form>>|\n' % wiki.get_session_timeout( ) t += '|!Rendering time limit<br>~~(seconds)<br>This affects restricted users only; full users have no limit. Use -1 for no limit.~~| %d |<<get timelimit_form>>|\n' % wiki.get_safemode_timelimit( ) t += '|!Rendering Cache<br><<get cache_help>>| %s |<<get cache_form>>|\n' % \ ifelse(wiki.get_cache_flag(), 'On', 'Off') t += '|!~MetaDb flag<br>~~You may want to turn this off when running on a USB drive, to minimize writes. Currently, this disables logging, but more features will be turned on/off in the future.~~| %s |<<get metadb_form>>|\n' % \ ifelse(wiki.get_metadb_flag(), 'On', 'Off') t += '|!Make links to unknown ~CamelWords| %s |<<get unknown_camelword_form>>|\n ' % \ ifelse(wiki.get_link_unknown_camelwords(), 'On', 'Off') t += '|!Debugging flag<br>~~@@I recommend leaving this OFF since it exposes server information.@@<br>To use, pass {{{cmd=debug}}}.~~| %s |<<get debug_form>>|\n' % \ ifelse(wiki.get_debug_flag(), 'On', 'Off') t += "!!!Statistics\n" st = wiki.rendercache().stats() t += '|>|>|>|!Caching|\n' t += '|!type|>|>| %s |\n' % st['type'] t += '|!puts|>|>| %d |\n' % st['puts'] t += '|!gets|>|>| %d |\n' % st['gets'] t += '|!hits|>|>| %d (%.1f%%) |\n' % (st['hits'], (st['hits'] * 100.0 / st['gets'])) t += '|!objects|>|>| %d |\n' % st['objects'] t += '|!bytes|>|>| %d |\n' % st['bytes'] t += '|!expiration_time|>|>| %d |\n' % st['expiration_time'] t += '|!clean_interval|>|>| %d |\n' % st['clean_interval'] t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<input type="submit" name="Set" value="Clear cache (no prompting!)"/>' t += u'<input type="hidden" name="cmd" value="clearRenderCache"/>' t += u'</fieldset>' t += u'</form></html>\n' t += u'!!!Server Information\n' t += u";~WikklyText version\n:{{{%s}}}\n" % VER.VSTR t += u";boodebr version\n:{{{%s}}}\n" % BVER.VSTR t += u";wsgifront version\n:{{{%s}}}\n" % WSVER.VSTR t += u";Python version\n:{{{%s}}}\n" % sys.version # this module is (in general) not allowed to touch cherrypy.*, but this # is just to get the version string. import cherrypy t += u';~CherryPy version\n:{{{%s}}}\n' % cherrypy.__version__ t += u';Server command\n:{{{' t += u' '.join(sys.argv) t += '}}}\n' t += u';sys.path\n:{{{' for p in sys.path: t += p + '\n' t += '}}}\n' h += render(wiki, t, UID='0') h += '</div>' h += pageFooter(wiki, None) return h
def sanitize_classname(name): # allow spaces so caller can attach multiple classes return ifelse(re.match(r"^[a-z_-][a-z0-9_\- ]+$", name, re.I), name, '')
def layoutAdminPage(wiki, loginUID, need_restart=False): """ Layout main admin page. Page must provide a form with actions as shown below. """ import wikklytext.version as VER import boodebr.version as BVER import wsgifront.version as WSVER import sys h = pageHeader(wiki, 'admin', 'Administration', loginUID=loginUID) h += '<div class="wikkly-item-header"><span class="wikkly-item-title">Wiki Administration</span></div>' h += '<div class="wikkly-item-content">' # note: All unicode strings will be converted to UTF-8 in the process of wikifying, # so no explicit encoding is needed here. the server has to remember to decode them. t = u'' t += u'!!!Site Configuration\n' # provide links for commonly edited configuration items for name in ['DefaultTiddlers', 'MainMenu', 'SiteTitle', 'SiteSubtitle', 'MarkupPreHead', 'MarkupPostHead', 'MarkupPreBody', 'MarkupPostBody', 'StyleSheet']: if wiki.getitem(name) is None: extra = '<br>^^@@No ~%s currently defined. Click above link to create it.@@^^' % name else: extra = '' t += u'* [[%s|DoServerCmd?%s]]%s\n' % \ (name, urlencode({'cmd':'editItem', 'name': name}), extra) t += '!!!Logs\n' t += '* [[Recent hits|DoServerCmd?cmd=logRecentHits]] ' t += '^^' p = {'cmd': 'logRecentHits', 'type': metadata.LOG_PAGEVIEW} t += '([[Content|DoServerCmd?%s]]) ' % urlencode(p) p = {'cmd': 'logRecentHits', 'type': metadata.LOG_ERRORMSG} t += '([[Errors|DoServerCmd?%s]]) ' % urlencode(p) p = {'cmd': 'logRecentHits', 'type': metadata.LOG_SETUID} t += '([[Set UID|DoServerCmd?%s]]) ' % urlencode(p) p = {'cmd': 'logRecentHits', 'type': metadata.LOG_FEED} t += '([[RSS|DoServerCmd?%s]]) ' % urlencode(p) t += '^^\n' t += '* [[Hits by page|DoServerCmd?cmd=logHitsByPage]]\n' t += '* [[Hits by days|DoServerCmd?cmd=logHitsByDates]]\n' t += '\n' t += u'!!!!!User-defined filters\n\n' t += u'* [[Hits on user filters|DoServerCmd?cmd=logHitsByUserFilters]]\n' t += u'Enter filters, one per line, into the following box. Filters are SQL "{{tt{LIKE}}}" clauses to ' t += u'be matched against server requests. For example, the filter {{{%.png%}}} would match ' t += u'the requests: {{{\n' t += u'GET /favicon.png HTTP/1.1\n' t += u'GET /files/image.png HTTP/1.1\n' t += u'}}}\n' t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<textarea name="filters" rows="10" cols="40">%s</textarea><br/>' % \ '\n'.join(wiki.get_request_log_filters()) t += u'<input type="hidden" name="cmd" value="setUserLogFilters"/>' t += u'<input type="submit" name="Set" value="Save Filters"/>' t += u'</fieldset>' t += u'</form></html>\n' t += '!!!Users\n' p = {'cmd': 'editUser', 'uid': ''} t += '* [[Create new user|DoServerCmd?%s]]\n\n' % urlencode(p) users = [(uid,wiki.user_get_username(uid)) for uid in wiki.user_all_UIDs()] users.sort(lambda a,b: cmp(a[1],b[1])) t += "|Existing Users|c\n" t += '|!Username|!Can login?|!Safe mode?|!Email|!Edit|\n' for uid,name in users: p = {'cmd': 'editUser', 'uid': uid} if wiki.user_get_safemode(uid): safe = 'True' else: safe = '@@False@@' # highlight users who run in full mode if uid == '0': fname = '!{{{%s}}}<br>{{grayout{^^(Root User)^^}}}' % safe_code(name) else: fname = '!{{{%s}}}' % safe_code(name) if wiki.user_can_login(uid): canlog = '@@Yes@@' else: canlog = 'No' t += '|%s | %s | %s | {{{%s}}} | [[edit|DoServerCmd?%s]] |\n' % \ (fname, canlog, safe, safe_code(wiki.user_get_email(uid)), urlencode(p)) t += u"<<set storage_form <quote>" t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<select name="storage_type">' t += u'<option %s value="ram">ram</option>' % \ ifelse(wiki.get_session_storage() == 'ram', 'selected="selected"', '') t += u'<option %s value="file">file</option>' % \ ifelse(wiki.get_session_storage() == 'file', 'selected="selected"', '') t += u'</select>' + ' '*2 t += u'<input type="hidden" name="cmd" value="setSessionStorage"/>' t += u'<input type="submit" name="Set" value="Set Storage Type"/>' t += u'</fieldset>' t += u'</form></html>\n' t += u'</quote>>>\n' t += u"<<set timeout_form <quote>" t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<input type="text" name="timeout" value="%s"/>' % str(wiki.get_session_timeout()) t += ' '*2 t += u'<input type="hidden" name="cmd" value="setSessionTimeout"/>' t += u'<input type="submit" name="Set" value="Set Timeout"/>' t += u'</fieldset>' t += u'</form></html>\n' t += u'</quote>>>\n' t += u"<<set timelimit_form <quote>" t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<input type="text" name="timelimit" value="%s"/>' % str(wiki.get_safemode_timelimit()) t += ' '*2 t += u'<input type="hidden" name="cmd" value="setSafemodeTimelimit"/>' t += u'<input type="submit" name="Set" value="Set Time Limit"/>' t += u'</fieldset>' t += u'</form></html>\n' t += u'</quote>>>\n' t += u'<<set debug_form <quote>' t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<select name="debug_flag">' t += u'<option %s value="off">Off</option>' % \ ifelse(wiki.get_debug_flag(), '', 'selected="selected"') t += u'<option %s value="on">On</option>' % \ ifelse(wiki.get_debug_flag(), 'selected="selected"', '') t += '</select>' + ' '*2 t += u'<input type="submit" name="Set" value="Set debug flag"/>' t += u'<input type="hidden" name="cmd" value="setDebugFlag"/>' t += u'</fieldset>' t += u'</form></html>' t += u'</quote>>>\n' t += u'<<set cache_form <quote>' t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'Enable? <select name="cache_flag">' t += u'<option %s value="off">Off</option>' % \ ifelse(wiki.get_cache_flag(), '', 'selected="selected"') t += u'<option %s value="on">On</option>' % \ ifelse(wiki.get_cache_flag(), 'selected="selected"', '') t += '</select>' + ' '*2 t += u'<br/>Expiration (seconds): <input type="text" name="expire_time" value="%s" size="6"/>' % str(wiki.get_cache_expire_time()) t += u'<br/>Clean interval (accesses): <input type="text" name="clean_interval" value="%s" size="6"/><br/>' % str(wiki.get_cache_clean_interval()) t += u'<input type="submit" name="Set" value="Save cache settings"/>' t += u'<input type="hidden" name="cmd" value="setCacheConfig"/>' t += u'</fieldset>' t += u'</form></html>' t += u'</quote>>>\n' t += u'<<set cache_help <quote>' t += u'<<div "" "font-size: .8em" "" """\n' t += u'* //Enable//: Turn cache on/off\n' t += u'* //Expiration//: Expiration time (seconds) for items added to the cache\n' t += u'* //Clean interval//: Clear out expired items (approximately) once per this many cache accesses\n' t += u'You may want to turn caching off when running on a USB drive, to minimize writes.\n' t += u'""">>' t += u'</quote> >>' t += u'<<set metadb_form <quote>' t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<select name="metadb_flag">' t += u'<option %s value="off">Off</option>' % \ ifelse(wiki.get_metadb_flag(), '', 'selected="selected"') t += u'<option %s value="on">On</option>' % \ ifelse(wiki.get_metadb_flag(), 'selected="selected"', '') t += '</select>' + ' '*2 t += u'<input type="submit" name="Set" value="Set metadb flag"/>' t += u'<input type="hidden" name="cmd" value="setMetadbFlag"/>' t += u'</fieldset>' t += u'</form></html>' t += u'</quote>>>\n' t += u'<<set unknown_camelword_form <quote>' t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<select name="unknown_camelword_flag">' t += u'<option %s value="off">Off</option>' % \ ifelse(wiki.get_link_unknown_camelwords(), '', 'selected="selected"') t += u'<option %s value="on">On</option>' % \ ifelse(wiki.get_link_unknown_camelwords(), 'selected="selected"', '') t += '</select>' + ' '*2 t += u'<input type="submit" name="Set" value="Set camelwords flag"/>' t += u'<input type="hidden" name="cmd" value="setUnknownCamelwordsFlag"/>' t += u'</fieldset>' t += u'</form></html>' t += u'</quote>>>\n' t += u'!!!Plugins\n' t += '[[Plugins|%s/api/plugins]]\n' % wiki.getRT_baseurl() t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'Enter additional directories to search for plugins, in addition to ' t += u'the default location (<tt>%s</tt>). Enter one directory per line.<br/>' % wiki.get_plugin_path() t += u'<textarea name="plugindirs" rows="10" cols="40">%s</textarea><br/>' % \ ('\n'.join(wiki.get_user_plugin_dirs())) t += u'<input type="hidden" name="cmd" value="setUserPluginDirs"/>' t += u'<input type="submit" name="Set" value="Save Plugin Directories"/>' t += u'</fieldset>' t += u'</form></html>\n' t += u'!!!Server Configuration\n' if need_restart: t += '<<warnbox "Need Restart" "You must restart the server for changes to take effect.">>\n' t += '|!Parameter|!Current Value|!Adjust|\n' t += '|!Session storage<br>~~@@CAUTION@@: I do not recommend using "file" sessions if your wiki is stored on a network drive.<br>For USB drives, you may want to set this to {{{ram}}} to minimize writes.~~| %s |<<get storage_form>>|\n' % wiki.get_session_storage() t += '|!Session timeout<br>~~(minutes)~~| %s |<<get timeout_form>>|\n' % wiki.get_session_timeout() t += '|!Rendering time limit<br>~~(seconds)<br>This affects restricted users only; full users have no limit. Use -1 for no limit.~~| %d |<<get timelimit_form>>|\n' % wiki.get_safemode_timelimit() t += '|!Rendering Cache<br><<get cache_help>>| %s |<<get cache_form>>|\n' % \ ifelse(wiki.get_cache_flag(), 'On', 'Off') t += '|!~MetaDb flag<br>~~You may want to turn this off when running on a USB drive, to minimize writes. Currently, this disables logging, but more features will be turned on/off in the future.~~| %s |<<get metadb_form>>|\n' % \ ifelse(wiki.get_metadb_flag(), 'On', 'Off') t += '|!Make links to unknown ~CamelWords| %s |<<get unknown_camelword_form>>|\n ' % \ ifelse(wiki.get_link_unknown_camelwords(), 'On', 'Off') t += '|!Debugging flag<br>~~@@I recommend leaving this OFF since it exposes server information.@@<br>To use, pass {{{cmd=debug}}}.~~| %s |<<get debug_form>>|\n' % \ ifelse(wiki.get_debug_flag(), 'On', 'Off') t += "!!!Statistics\n" st = wiki.rendercache().stats() t += '|>|>|>|!Caching|\n' t += '|!type|>|>| %s |\n' % st['type'] t += '|!puts|>|>| %d |\n' % st['puts'] t += '|!gets|>|>| %d |\n' % st['gets'] t += '|!hits|>|>| %d (%.1f%%) |\n' % (st['hits'], (st['hits']*100.0/st['gets'])) t += '|!objects|>|>| %d |\n' % st['objects'] t += '|!bytes|>|>| %d |\n' % st['bytes'] t += '|!expiration_time|>|>| %d |\n' % st['expiration_time'] t += '|!clean_interval|>|>| %d |\n' % st['clean_interval'] t += u'<html><form action="DoServerCmd.html" method="post">' t += u'<fieldset class="wikkly-form">' t += u'<input type="submit" name="Set" value="Clear cache (no prompting!)"/>' t += u'<input type="hidden" name="cmd" value="clearRenderCache"/>' t += u'</fieldset>' t += u'</form></html>\n' t += u'!!!Server Information\n' t += u";~WikklyText version\n:{{{%s}}}\n" % VER.VSTR t += u";boodebr version\n:{{{%s}}}\n" % BVER.VSTR t += u";wsgifront version\n:{{{%s}}}\n" % WSVER.VSTR t += u";Python version\n:{{{%s}}}\n" % sys.version # this module is (in general) not allowed to touch cherrypy.*, but this # is just to get the version string. import cherrypy t += u';~CherryPy version\n:{{{%s}}}\n' % cherrypy.__version__ t += u';Server command\n:{{{' t += u' '.join(sys.argv) t += '}}}\n' t += u';sys.path\n:{{{' for p in sys.path: t += p + '\n' t += '}}}\n' h += render(wiki, t, UID='0') h += '</div>' h += pageFooter(wiki, None) return h
def do_main(): global OPTS # parse command line from wikklytext.cmdline import BasicOptParser op = BasicOptParser('wikkly2html.py', 'Converts WikklyText to HTML') op.add_stropt('o', 'output', 'outname', 'Set output filename', '*stdout*') op.add_stropt('m', 'mode', 'mode', 'Set mode (full|safe)', 'full') op.add_intopt('t', 'maxtime', 'maxtime', 'Set maximum run time (-1 for unlimited)', -1) op.add_boolopt('h', 'help', 'help', 'Display this help') op.add_boolopt( 'c', 'css', 'copy_css', 'Copy .CSS file to destination directory (unless it already exists)') OPTS, args = op.process(sys.argv[1:]) # check args if OPTS.help or len(args) != 1 or OPTS.mode not in ['safe', 'full']: op.show_usage('filename.txt') sys.exit(0) if OPTS.copy_css and OPTS.outname == '*stdout*': print "** ERROR: When using '-c' you must also use '-o'" sys.exit(1) # make outname absolute in case of chdir later if OPTS.outname != '*stdout*': OPTS.outname = os.path.abspath(OPTS.outname) # change if desired ... ENCODING = 'utf-8' t_begin = time() # enable logging (in case an exception happens) wikklytext.base.enable_logging(True) # set full/safe mode safe_mode = ifelse(OPTS.mode == 'full', False, True) # make infilename absolute path in case of chdir later infilename = os.path.abspath(args[0]) # vars to set in WikContext setvars = { '$FS_CWD': os.path.split(infilename)[0], } # add document path to sys.path -- ONLY if not in safe mode to prevent # untrusted users from overriding standard modules if not safe_mode: sys.path.insert(0, os.path.split(infilename)[0]) buf = load_wikitext(infilename) in_bytes = len(buf) inner, context = WikklyText_to_InnerHTML(buf, ENCODING, safe_mode, setvars, max_runtime=OPTS.maxtime, tree_posthook=treehook) # see if wikitext set a $TITLE doc_title = context.var_get_text('$TITLE') if not len(doc_title): doc_title = None # don't set a title if empty # log in case an error occurred (so test case can be reproduced) wikklytext.base.log_content(buf, inner) out_bytes = len(inner) t_end = time() # add "Processed by ..." tag. I find it annoying to have the banner on short content, so only # add if content is of significant length. It's the OUTPUT length that matters here, since # even a short input like <<help>> can generate a lot of output. if out_bytes > 1000: ptag = u"WikklyText %s on %s" % (wikklytext.base.get_version(), ctime(time())) ptag += " [%s, %.1fs] " % (bytes_to_str(out_bytes), t_end - t_begin) tag = u'' tag += u"<div class='wikkly-generated-by'>" tag += u"Written in <a class='wikkly-a-www' title='%s' href='http://wikklytext.com'>WikklyText</a>." % ptag tag += "</div>" tag = tag.encode(ENCODING) else: tag = ''.encode(ENCODING) output = HTML_PRE( ENCODING, doc_title, include_navmenu=False) + inner + tag + HTML_POST(ENCODING) if OPTS.outname == '*stdout*': print output else: outname = OPTS.outname open(outname, 'wb').write(output) # does user want the .css file copied as well? if OPTS.copy_css: path = os.path.split(os.path.abspath(outname))[0] path = os.path.join(path, 'css') if not os.path.isdir(path): os.makedirs(path) copy_CSS_elements(os.path.join(path))
def only_spaces(txt): "Does text contain ONLY spaces (or is empty)?" return ifelse(len(txt) and re.search('[^ \t]', txt), False, True)
def layoutEditItem(wiki, itemname, defaultItem, loginUID): """ Layout a page for editing the named item. Page must provide a form with action as shown below. """ from wikklytext.store import tags_join item = wiki.getitem(itemname) if item is None: item = defaultItem oldname = '' else: oldname = item.name if item is defaultItem: h = pageHeader(wiki, 'newitem', 'New Item', loginUID=loginUID) else: h = pageHeader(wiki, None, 'Editing Item', loginUID=loginUID) if wiki.user_valid_UID(itemname): name = wiki.user_get_username(itemname) h += '<div class="wikkly-item-header"><span class="wikkly-item-title">Editing: %s</span></div>' % \ utf8(safehtml(name)) else: h += '<div class="wikkly-item-header"><span class="wikkly-item-title">Editing: %s</span></div>' % \ utf8(safehtml(itemname)) h += '<div class="wikkly-item-content">' # note: All unicode strings will be converted to UTF-8 in the process of wikifying, # so no explicit encoding is needed here. the server has to remember to decode them. f = u'<html>' f += u'<form action="DoServerCmd.html" method="post">' f += u'<fieldset class="wikkly-form">' # if name is a UID, show author name instead (and make it non-editable) if wiki.user_valid_UID(itemname): name = wiki.user_get_username(itemname) f += u'Name: <b>%s</b><br/>' % safehtml(name) # put name in hidden item instead f += u'<input type="hidden" name="itemName" value="%s"/>' % safehtml(itemname) else: f += u'Name: <input class="wikkly-edit-input" type="text" name="itemName" value="%s"/><br/>' % \ safehtml(itemname) f += u'<textarea class="wikkly-edit-textarea" name="content" cols="80" rows="25">' txt = item.content # escape any </html> tags so won't end early txt = txt.replace('</html>', '</html>') f += txt f += u'</textarea><br/>' f += u'Tags: <input class="wikkly-edit-input" type="text" name="tags" value="%s"/><br/>' % \ safehtml(tags_join(item.tag_list())) f += u' '*10 + '<sup>Enter space-separate tags, using [[braces if needed]].</sup><br/>' f += u'Markup style: <select name="content_type">' f += u' <option %s value="WikklyText">WikklyText</option>' % \ ifelse(item.content_type=='WikklyText', u'selected="selected"', u'') f += u' <option %s value="TiddlyWiki">TiddlyWiki</option>' % \ ifelse(item.content_type=='TiddlyWiki', u'selected="selected"', u'') f += u'</select><br/><br/>' f += u'<input type="hidden" name="oldItemName" value="%s"/>' % oldname f += u'<input type="hidden" name="cmd" value="completeEdit"/>' f += u'<input type="hidden" name="ctime" value="%s"/>' % item.ctime.to_store() f += u'<input type="submit" name="btn_save" value="Save"/> ' if len(oldname): # don't show delete button on new items f += u'<input type="submit" name="btn_delete" value="Delete Item"/><br/>' f += u'</fieldset>' f += u'</form>' f += u'</html>' h += render(wiki, f, UID='0') h += '</div>' h += pageFooter(wiki, None) return h
def sanitize_text_align(align): return ifelse(align in ['left', 'center', 'right'], align, '')
def sanitize_id(id_): # per HTML spec, element ids must conform to this ... return ifelse(re.match(r'[A-Za-z][A-Za-z0-9\-_:\.]*', id_), id_, '')