# --------------------------------------------------------
# license
# --------------------------------------------------------
#
# Copyright (c) 2007 Craig J M Turner
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# --------------------------------------------------------
# imports
# --------------------------------------------------------
import os
import re
import traceback
import shutil
import cherrypy
import RenderUtils
import SimpleXmlTools
# --------------------------------------------------------
# todo
# --------------------------------------------------------
#
# In requesthandler:
#
# xxx go through the received paths and trim all leading dots.
#
# xxx strip slashes from paths as well
#
# --------------------------------------------------------
# webserver
# --------------------------------------------------------
CSS_URL = '/static/steamdoc.css'
#PROCESSING_URL = '/static/processing.js'
PROCESSING_URL = 'http://ejohn.org/apps/processing.js/processing.js'
INIT_URL = '/static/init.js'
class RequestHandler(object):
def __init__(self, path_to_document_dir, path_to_static_dir):
if not os.path.exists(path_to_document_dir):
raise Exception, "No directory at %s."%path_to_document_dir
self.path_to_document_dir = path_to_document_dir
if not os.path.exists(path_to_static_dir):
raise Exception, "No directory at %s."%path_to_static_dir
self.path_to_static_dir = path_to_static_dir
@cherrypy.expose
def directory(self, *lst_path, **http_args):
path = os.sep.join(lst_path)
path = strip_path(path)
path_components = [self.path_to_document_dir]
path_components.append( path )
target_dir = os.sep.join(path_components)
if not os.path.exists(target_dir) or not os.path.isdir(target_dir):
return "No directory for '%s'."%'/'.join( lst_path )
return html_display_dir(target_dir, path)
@cherrypy.expose
def go(self, *lst_path, **http_args):
"""This is what gets called when the user uses the input
at the top of the page."""
if 's' not in http_args.keys():
raise cherrypy.HTTPRedirect('/')
path = http_args['s'].strip()
path = strip_path(path)
if len(path) == 0:
raise cherrypy.HTTPRedirect('/')
if not os.path.exists('%s/%s'%(self.path_to_document_dir, path)):
return html_create_page(self.path_to_document_dir, path)
try:
return html_display_page(self.path_to_document_dir, self.path_to_static_dir, path)
except:
traceback.print_exc()
raise cherrypy.HTTPError(500)
@cherrypy.expose
def create(self, *lst_path, **http_args):
if len(lst_path) == 0:
raise HTTPError(404)
path = os.sep.join(lst_path)
path = strip_path(path)
if os.path.exists('%s/%s'%(self.path_to_document_dir, path)):
raise cherrypy.HTTPRedirect('/%s'%path)
f_ptr = None
try:
path_to_doc = "%s%s%s"%(self.path_to_document_dir, os.sep, path)
if 'action_create_file' in http_args.keys():
#
# Check the directory exists and create it if it doesn't
path_tokens = path_to_doc.split(os.sep)[:-1]
dirname = os.sep.join( path_tokens )
if os.path.exists(dirname) and not os.path.isdir(dirname):
print "EE Expecting difficulties: %s exists but is not a directory."%dirname
elif not os.path.exists(dirname):
print "** No dir %s. Attempt to create"%dirname
os.mkdir(dirname)
print "-> Success"
# Now create the file itself
f_ptr = open(path_to_doc, 'w+')
f_ptr.write('\n')
raise cherrypy.HTTPRedirect('/edit/%s'%'/'.join(lst_path))
elif 'action_create_dir' in http_args.keys():
os.mkdir(path_to_doc)
raise cherrypy.HTTPRedirect('/%s'%'/'.join(lst_path))
else:
return "Nothing to do! Problem with form submit?"
except cherrypy.HTTPRedirect, e:
raise e
except:
traceback.print_exc()
raise cherrypy.HTTPError(500)
finally:
if None != f_ptr:
try:
f_ptr.close()
except:
pass
@cherrypy.expose
def edit(self, *lst_path, **http_args):
path = os.sep.join(lst_path)
path = strip_path(path)
if 0==len(lst_path) or not os.path.exists('%s/%s'%(self.path_to_document_dir, path)):
raise cherrypy.HTTPError(404)
try:
return html_edit_page(self.path_to_document_dir, path)
except:
traceback.print_exc()
raise cherrypy.HTTPError(500)
@cherrypy.expose
def save(self, *lst_path, **http_args):
#
# Handle the cancel case.
if 'action_cancel' in http_args.keys():
raise cherrypy.HTTPRedirect('/%s'%'/'.join(lst_path))
#
# If we get this far we assume it's for a save.
path = os.sep.join(lst_path)
path = strip_path(path)
if 0==len(lst_path) or not os.path.exists('%s/%s'%(self.path_to_document_dir, path)):
raise cherrypy.HTTPError(404)
if 'wiki_content' not in http_args.keys():
return "Error: No wiki_content to save."
f_ptr = None
try:
f_ptr = open('%s/%s'%(self.path_to_document_dir, path), 'w+')
f_ptr.write( http_args['wiki_content'] )
except:
traceback.print_exc()
raise cherrypy.HTTPError(500)
finally:
if None != f_ptr:
try:
f_ptr.close()
except:
pass
raise cherrypy.HTTPRedirect('/%s'%'/'.join(lst_path))
@cherrypy.expose
def raw(self, *lst_path, **http_args):
if len(lst_path) == 0:
return "<html><body>Need a filename</body></html"
path = '/'.join(lst_path)
path = strip_path(path)
full_path = '%s/%s'%(self.path_to_document_dir, path)
if not os.path.exists(full_path):
raise cherrypy.HTTPError(404)
return cherrypy.lib.static.serve_file(full_path, 'text/plain', "inline", full_path)
f_ptr = None
try:
f_ptr = open(full_path)
data = f_ptr.read()
return data
except:
traceback.print_exc()
return "<html><body>Error - see logs</body></html"
finally:
if None != f_ptr:
try: f_ptr.close()
except: pass
@cherrypy.expose
def printer(self, *lst_path, **http_args):
if len(lst_path) == 0:
lst_path = ['default']
path = os.sep.join(lst_path)
path = strip_path(path)
if not os.path.exists('%s/%s'%(self.path_to_document_dir, path)):
raise cherrypy.HTTPError(404)
try:
return html_display_page(self.path_to_document_dir, self.path_to_static_dir, path, False)
except:
traceback.print_exc()
raise cherrypy.HTTPError(500)
@cherrypy.expose
def default(self, *lst_path, **http_args):
if len(lst_path) == 0:
lst_path = ['default']
path = os.sep.join(lst_path)
path = strip_path(path)
full_path = '%s%s%s'%(self.path_to_document_dir, os.sep, path)
#
# Create an entrypoint page if it doesn't already exist
if not os.path.exists(full_path) and 1==len(lst_path) and lst_path[0] == 'default':
#
# xxx it's a bit hacky to need to do this. Think about it.
#
f_ptr = open(full_path, 'w+')
f_ptr.write('TITLE: Your new wiki\n= Heading\n\n')
f_ptr.close()
shutil.copyfile('processing.js', os.sep.join( [self.path_to_static_dir, 'processing.js'] ))
shutil.copyfile('steamdoc.css', os.sep.join( [self.path_to_static_dir, 'steamdoc.css'] ))
if not os.path.exists(full_path):
return html_create_page(self.path_to_document_dir, path)
try:
if os.path.isfile(full_path):
return html_display_page(self.path_to_document_dir, self.path_to_static_dir, path)
if os.path.isdir(full_path):
return html_display_dir(full_path, path)
except InvalidDoc, e:
return html_edit_page(self.path_to_document_dir, path, error=e.message)
except:
traceback.print_exc()
raise cherrypy.HTTPError(500)
@cherrypy.expose
def xml(self, *lst_path, **http_args):
content = ''
if 'content' in http_args.keys():
try:
c = '<doc>%s</doc>'%http_args['content']
dt_root = SimpleXmlTools.create_dt_root_from_xml_string(c)
content = SimpleXmlTools.create_formatted_xml( dt_root )
except Exception, e:
content = '\n'.join( [ 'Error in transform: %s'%e.message
, '\n\n'
, content
]
)
return '''<html>
<head><title>Xml Formatted</title></head>
<body>
<h1 class="wordish_h1">Xml Formatter</h1>
<p>
Paste your XML content into the box below and hit format. Make
sure that you're pasting a single xml tree in here, or it
misbehaves and you'll lose tags and get other strangeness.
Err.. sometimes the error messages don't make a whole lot of
sense. It's not particularly robust.
</p>
<form method="POST" action="/xml">
<textarea name="content">%s</textarea>
<br />
<br />
<input type="Submit" value="Format" />
</form>
</body>
</html>'''%content
@cherrypy.expose
def static(self, *lst_path, **http_args):
if len(lst_path) == 0:
lst_path = ['default']
path = os.sep.join(lst_path)
path = strip_path(path)
fs_path = os.sep.join( [self.path_to_static_dir, path] )
if not os.path.exists(fs_path):
print 'failed static', fs_path
raise cherrypy.HTTPError(404)
mime='text/plain'
if path.endswith('.png'):
mime="image/png"
elif path.endswith('.css'):
mime="text/css"
elif path.endswith('.js'):
mime="application/x-javascript"
return cherrypy.lib.static.serve_file(fs_path, mime, "inline", fs_path)
@cherrypy.expose
def download(self, *lst_path, **http_args):
if len(lst_path) == 0:
lst_path = ['default']
path = os.sep.join(lst_path)
path = strip_path(path)
fs_path = '%s%s%s'%(self.path_to_document_dir, os.sep, path)
if not os.path.exists(fs_path):
print 'failed download', fs_path
raise cherrypy.HTTPError(404)
return cherrypy.lib.static.serve_file(fs_path, "application/octet-stream", "inline", fs_path)
def strip_path(str):
while str.startswith('.'):
str = str[1:]
# we don't want people jumping up to higher directories
while len(str.split('..')) > 1:
sb = str.split('..')
if len(sb) > 2:
str = ''.join(sb)
return str
def html_create_page(doc_path, fname):
path = os.sep.join( [doc_path, fname] )
html="""<html><head>
<link href="%s" rel="stylesheet" type="text/css"></link>
</head>
<body>
%s
<br />
<div style="border: 1px blue dotted; padding: 4px;">
<form method="POST" action="/create/%s" enctype="multipart/form-data">
<h1 class="wordish_h1">%s</h1>
There is no resource called '%s'. You can create one
if you like.
<br />
<input type="Submit" name="action_create_file" value="Create file %s!" />
<input type="Submit" name="action_create_dir" value="Create directory %s!" />
<br />
</form>
</div>
</body></html>
"""%(CSS_URL, header_view(path, fname), fname, fname, fname, fname, fname)
return html
class InvalidDoc(Exception):
pass
def parse_document_into_doc_parts(document_data):
"""Throws InvalidDoc"""
# example of a doc:
"""
Stuff here is in STATE_DEFAULT. Assumed to be mnml.
{{{
#!type goes here and ends STATE_BLOCK_OPENING. This line is optional. Assumed to be mnml.
STATE_BLOCK_MAIN
}}}
"""
STATE_DEFAULT=1
STATE_BLOCK_OPENING=2
STATE_BLOCK_MAIN=3
state = [STATE_DEFAULT]
def get_state():
return state[0]
def to_state_default():
reset_current_item_data()
set_current_item_doctype('mnml')
state.pop()
state.append(STATE_DEFAULT)
def to_state_block_opening():
reset_current_item_data()
set_current_item_doctype('mnml')
state.pop()
state.append(STATE_BLOCK_OPENING)
def to_state_block_main():
state.pop()
state.append(STATE_BLOCK_MAIN)
ret_lst = [] # each item in the list will be a tpl of form (doctype, docdata)
current_item_doctype=['mnml'] # mnml is default
def get_current_item_doctype():
return current_item_doctype[0]
def set_current_item_doctype(s):
current_item_doctype.pop()
current_item_doctype.append(s)
sb_current_item_data=[]
def reset_current_item_data():
while len(sb_current_item_data) > 0:
sb_current_item_data.pop()
def fn_state_default(line):
if line.strip()=='{{{':
tpl = (get_current_item_doctype(), '\n'.join(sb_current_item_data))
ret_lst.append( tpl )
to_state_block_opening()
elif line.strip()=='}}}':
raise InvalidDoc, "Encountered '}}}' when not in a block."
else:
sb_current_item_data.append(line)
def fn_block_opening(line):
if line.strip().startswith('#!'):
set_current_item_doctype(line.strip()[2:])
elif line.strip()=='{{{':
raise InvalidDoc, "Blocks can't be nested."
elif line.strip()=='}}}':
tpl = (get_current_item_doctype(), '\n'.join(sb_current_item_data))
ret_lst.append( tpl )
to_state_default()
else:
sb_current_item_data.append(line)
to_state_block_main()
def fn_block_main(line):
if line.strip()=='}}}':
tpl = (get_current_item_doctype(), '\n'.join(sb_current_item_data))
ret_lst.append( tpl )
to_state_default()
elif line.strip()=='{{{':
raise InvalidDoc, "Blocks can't be nested."
else:
sb_current_item_data.append(line)
state_fn_map = { STATE_DEFAULT:fn_state_default
, STATE_BLOCK_OPENING:fn_block_opening
, STATE_BLOCK_MAIN:fn_block_main
}
for line in document_data.split('\n'):
fn = state_fn_map[get_state()]
fn(line)
if get_state() != STATE_DEFAULT:
raise InvalidDoc, "There's an empty block at the end of the document."
# for the final block
tpl = (get_current_item_doctype(), '\n'.join(sb_current_item_data))
ret_lst.append( tpl )
return ret_lst
def html_display_dir(target_dir, url_relpath):
lst_contents = [fname for fname
in os.listdir(target_dir)
if not fname.startswith('.')
]
lst_contents.sort()
sb = []
sb.append(html_header())
title_str = app_properties()['title_string']
directory_link = url_relpath
sb.append(u"""
<div class="grayheading">
<table width="100%%">
<tr>
<td>%s</td>
<td align="right">
<form method="GET" action="/go" style="display:inline;">
<a class="headinglink" href="/">home</a>
|
<a class="headinglink" href="/directory/%s">directory</a>
|
<input name="s"></input>
<input type="submit" value="go"></input>
</form>
</td>
</tr>
</table>
</div>
<div class="blackbar">
</div>
"""%(title_str, url_relpath))
sb.append( html_breadcrumb(url_relpath) )
sb.append('<br />')
sb.append('<div class="contentbox">')
sb.append('<p class="wordish_title">/%s</p>'%url_relpath)
sb.append('<hr />')
sb.append('<h1>Files</h1>')
sb.append('<ul>')
for i in [fn for fn in lst_contents if os.path.isfile("%s%s%s"%(target_dir, os.sep, fn))]:
link = '/'.join( [url_relpath, i] )
if not link.startswith('/'):
link = '/%s'%link
sb.append('<li><a href="%s">./%s</a></li>'%(link, i))
sb.append('</ul>')
sb.append('<h1>Subdirectories</h1>')
sb.append('<ul>')
for i in [fn for fn in lst_contents if os.path.isdir("%s%s%s"%(target_dir, os.sep, fn))]:
link = '/'.join( [url_relpath, i] )
if not link.startswith('/'):
link = '/%s'%link
sb.append('<li><a href="%s">./%s/</a></li>'%(link, i))
sb.append('</ul>')
sb.append('</div>')
sb.append('</body>')
sb.append('</html>')
return '\n'.join( sb )
def html_display_page(doc_path, static_path, fname, print_header=True):
path = "%s%s%s"%(doc_path, os.sep, fname)
# dir handling
if os.path.isdir(path):
return html_display_dir('/'.join([doc_path, fname]), fname)
# file handling
data = None
f_ptr = None
try:
f_ptr = open(path)
data = f_ptr.read()
if len(data.strip()) == 0:
data = "[document is empty]"
except:
traceback.print_exc()
raise Exception, 'Something wrong opening %s.'%path
finally:
if None != f_ptr:
f_ptr.close()
sb = [ html_header() ]
if print_header:
sb.append( header_view(path, fname) )
sb.append( '<br />')
sb.append('<div class="contentbox">')
#
# doc_parts will be a list of tuples of form
# [ (doc_type, doc_data), (doc_type, doc_data), ... ]
# See the valid doc_type listings from further down. xxx give better comment
doc_parts = parse_document_into_doc_parts(data)
for doctype, content in doc_parts:
if doctype == 'raw':
sb.append(content)
elif doctype == 'processing':
sb.append('''<script type="application/processing">
%s
</script><canvas width="800" height="600"></canvas>'''%content)
elif doctype == 'rst':
try:
html_from_renderutils = RenderUtils.render_html(content)
lines_for_page = []
b_ignore_for_now = True
for line in html_from_renderutils.split('\n'):
if line == '</body>':
b_ignore_for_now = True
if not b_ignore_for_now:
h = header_view(path, fname)
if line.startswith('<table border="1" class="docutils">'):
sb.append('<table class="docutils">')
else:
sb.append(line)
if line == '<body>':
b_ignore_for_now = False
except Exception, e:
sb.append('<p style="color: #ff0000">Error with rst: %s</p>'%e.message)
elif doctype == 'table':
sb_new_content = []
sb_new_content.append('<table class="docutils">')
for line in content.split('\n'):
cells = line.split('|')
for idx, cell in enumerate(cells):
cell = cell.strip()
if cell.startswith('*'):
cell = ''.join(cell.split('*'))
tag = 'th'
else:
tag = 'td'
if cell.startswith('http:'):
cell = '<a href="%s">%s</a>'%(cell, cell)
cells[idx]= '<%s>%s</%s>'%(tag, cell, tag)
sb_new_content.append('<tr>')
sb_new_content.append('<td>')
sb_new_content.append(' '.join(cells))
sb_new_content.append('</td>')
sb_new_content.append('</tr>')
sb_new_content.append('</table>')
sb.append( '\n'.join(sb_new_content) )
elif doctype == 'code':
# convert the angle brackets to symbols
new_content = None
sb_new_content = []
for line in content.split('\n'):
line = '&'.join( line.split('&') )
line = '>'.join( line.split('>') )
line = '<'.join( line.split('<') )
sb_new_content.append(line)
new_content = '\n'.join( sb_new_content )
# now print out
sb.append('<div class="code"><pre>%s</pre></div>'%new_content)
elif doctype == 'note':
# convert the angle brackets to symbols
new_content = None
sb_new_content = []
just_had_blank = True
first_p = True
for line in content.split('\n'):
if 0 == len(line.strip()):
just_had_blank = True
else:
if just_had_blank:
if first_p:
sb_new_content.append('<p>')
first_p = False
else:
sb_new_content.append('</p><p>')
just_had_blank = False
line = '&'.join( line.split('&') )
line = '>'.join( line.split('>') )
line = '<'.join( line.split('<') )
sb_new_content.append(line)
sb_new_content.append("<br />")
sb_new_content.append('</p>')
new_content = '\n'.join( sb_new_content )
# now print out
sb.append('<div class="noteinsert">%s</div>'%new_content)
elif doctype == 'pre':
try:
sb.append('<tt>')
sb.append('<font color="orange">')
sb.append('<pre>')
sb.append(content)
sb.append('</pre>')
sb.append('</font>')
sb.append('</tt>')
except Exception, e:
sb.append('<p style="color: #ff0000">Error with pre: %s</p>'%e.message)
elif doctype == 'mnml':
try:
class ParagraphTracker(object):
def __init__(self):
self.b_new_para=True
self.b_in_para=False
self.listlevel=0
pt = ParagraphTracker()
mnml_lines = content.split('\n')
def unwrap():
"This is what we do to close off a block."
while pt.listlevel>0:
sb.append('</ul>')
pt.listlevel-=1
if pt.b_in_para:
sb.append('</p>')
pt.b_new_para = True
pt.b_in_para = False
for idx, line in enumerate(mnml_lines):
if line.startswith('TITLE: '):
sb.append('<p class="wordish_title">%s</p>'%' '.join(line.split(' ')[1:]))
sb.append("<hr />")
elif line.startswith('= '):
sb.append('<h1 class="wordish_h1">%s</h1>'%' '.join(line.split(' ')[1:]))
elif line.startswith('== '):
sb.append('<h2 class="wordish_h2">%s</h2>'%' '.join(line.split(' ')[1:]))
elif line.startswith('=== '):
sb.append('<h3 class="wordish_h3">%s</h3>'%' '.join(line.split(' ')[1:]))
elif line.startswith('==== '):
sb.append('<h4 class="wordish_h4">%s</h4>'%' '.join(line.split(' ')[1:]))
elif line.startswith('===== '):
sb.append('<h5 class="wordish_h5">%s</h5>'%' '.join(line.split(' ')[1:]))
elif line.startswith('*'):
#
# Use voodoo to get the ul indent to be right
w_listlevel = pt.listlevel
new_listlevel = 0
split_on_stars = line.split('*')
while split_on_stars[0] == '':
new_listlevel+=1
split_on_stars=split_on_stars[1:]
while new_listlevel>w_listlevel:
sb.append('<ul>')
w_listlevel+=1
while w_listlevel>new_listlevel:
sb.append('</ul>')
w_listlevel-=1
pt.listlevel = new_listlevel
#
# Now that the listlevel is right, output this line in it
sb.append('<li>%s</li>'%line[pt.listlevel:].strip())
elif line.strip() == '':
unwrap()
else:
pt.b_in_para = True
if pt.b_new_para:
pt.b_new_para = False
sb.append('<p style="wordish_p">')
wiki_simple_links_pattern = re.compile('\[\[.*\]\]')
wiki_bar_links_pattern = re.compile('\[\[.*|.*\]\]')
if wiki_simple_links_pattern.match(line) or wiki_bar_links_pattern.match(line):
sb_line = []
remainder = line[:]
while '[[' in remainder:
cidx = remainder.index('[[')
beg, remainder = remainder[:cidx], remainder[cidx+2:]
sb_line.append(beg)
if '|' in remainder and remainder.index('|') < remainder.index(']]'):
bar_idx = remainder.index('|')
clos_idx = remainder.index(']]')
link_fname, link_name = remainder[:bar_idx], remainder[bar_idx+1:clos_idx]
sb_line.append('<a href="%s">%s</a>'%(link_fname, link_name))
remainder = remainder[clos_idx+2:]
else:
clos_idx = remainder.index(']]')
link_n = remainder[:clos_idx]
sb_line.append('<a href="%s">%s</a>'%(link_n, link_n))
remainder = remainder[clos_idx+2:]
sb_line.append(remainder)
line = ''.join(sb_line)
sb.append(line)
# Make sure we've closed everything off in this block
unwrap()
except Exception, e:
# xxx
print dir(e)
traceback.print_exc()
sb.append('<p style="color: #ff0000">Error with diagram: %s</p>'%e.message)
elif doctype == 'dot':
try:
img_fname = RenderUtils.render_dot(content, static_path)
sb.append('<img src="/static/%s" />'%img_fname)
except Exception, e:
# xxx
print dir(e)
traceback.print_exc()
sb.append('<p style="color: #ff0000">Error with diagram: %s</p>'%e.message)
elif doctype == 'list':
sb.append('<ul>')
item_buffer = []
li_open = False
for line in content.split('\n'):
if line.startswith('* '):
if li_open:
sb.append(' '.join(item_buffer))
sb.append('</li>')
li_open=False
sb.append('<li>')
li_open = True
item_buffer = [line[2:].strip()]
elif len(line.strip()) > 0:
item_buffer.append(line.strip())
else:
if len(item_buffer) > 0:
sb.append(' '.join(item_buffer))
if li_open:
sb.append('</li>')
li_open = False
item_buffer = []
if len(item_buffer) > 0:
sb.append(' '.join(item_buffer))
if li_open:
sb.append('</li>')
li_open=False
sb.append('</ul>')
else:
sb.append('<br /><hr /><p style="color: red;">No renderer for type "%s".</p><hr /><br />'%doctype)
sb.append('</div>')
sb.append('</body></html>')
return '\n'.join( [str(s) for s in sb] )
def html_edit_page(doc_path, fname, error=None):
path = "%s%s%s"%(doc_path, os.sep, fname)
data = None
f_ptr = None
try:
f_ptr = open(path)
data = f_ptr.read()
except:
traceback.print_exc()
raise Exception, 'Something wrong opening %s.'%path
finally:
if None != f_ptr:
f_ptr.close()
error_text=''
if None != error:
error_text = error
html = """<html>
<head>
<link href="%s" rel="stylesheet" type="text/css"></link>
</head>
<body>
%s
<h1 class="wordish_h1">Editing %s</h1>
<form method="POST" action="/save/%s" enctype="multipart/form-data">
<textarea rows="20" cols="100" name="wiki_content">%s</textarea>
<br />
<input name="action_save" type="submit" value="Save" />
<input name="action_cancel" type="submit" value="Cancel" />
</form>
</body></html>
"""%(CSS_URL, error_text, fname, fname, data)
return html
def header_view(path, url_relpath):
title_str = app_properties()['title_string']
directory_link = '/'.join( url_relpath.split(os.sep)[:-1] )
main="""<div class="grayheading">
<table width="100%%">
<tr>
<td>%s</td>
<td align="right">
<form method="GET" action="/go" style="display:inline;">
<a class="headinglink" href="/">home</a>
|
<a class="headinglink" href="/printer/%s">printer</a>
|
<a class="headinglink" href="/raw/%s">raw</a>
|
<a class="headinglink" href="/edit/%s">edit</a>
|
<a class="headinglink" href="/directory/%s">directory</a>
|
<input name="s"></input>
<input type="submit" value="go"></input>
</form>
</td>
</tr>
</table>
</div>
<div class="blackbar">
</div>
"""%(title_str, url_relpath, url_relpath, url_relpath, directory_link)
sb = []
sb.append(main.strip())
sb.append(html_breadcrumb(url_relpath))
return '\n'.join( sb )
def html_breadcrumb(url_relpath):
sb = ['<div class="breadcrumb">']
sb.append('\n<a href="/">home</a>')
path_as_list = url_relpath.split('/')
for idx, path_component in enumerate(path_as_list):
cumulative_path = '/'.join( path_as_list[0:idx+1] )
sb.append(' > <a href="/%s">%s</a>'%(cumulative_path, path_component))
sb.append('</div>')
return '\n'.join( sb )
def html_header():
"""Goodger's license allowed me to copy and modify this block. But there's a hell
of a lot of cleaning up that needs to be done to strip this down."""
return """<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/"></meta>
<title></title>
<link href="%s" rel="stylesheet" type="text/css"></link>
<script type="text/javascript" src="%s"></script>
<script type="text/javascript" src="%s"></script>
</head>
<body>
"""%(CSS_URL, PROCESSING_URL, INIT_URL)
# --------------------------------------------------------
# app properties
# --------------------------------------------------------
g_app_properties=None
def app_properties():
global g_app_properties
return g_app_properties
def load_properties():
global g_app_properties
CONFIG_FNAME='steamdoc.properties'
if not os.path.exists(CONFIG_FNAME):
raise Exception, 'Need a file "%s".'%CONFIG_FNAME
if not os.path.isfile(CONFIG_FNAME):
raise Exception, 'Need a *file* "%s".'%CONFIG_FNAME
f_ptr=None
try:
f_ptr = open(CONFIG_FNAME)
prop_lines = [line for line in f_ptr.readlines() if not line.startswith('#')]
except:
traceback.print_exc()
raise
finally:
if None != f_ptr:
try: f_ptr.close()
except: pass
prop_dict = {}
for line in prop_lines:
try:
key, value = line.split('=')
prop_dict[key.strip()] = value.strip()
except:
raise Exception, "Bad line in %s, '%s'."%(CONFIG_FNAME, line)
g_app_properties = prop_dict
# --------------------------------------------------------
# bootstrap
# --------------------------------------------------------
def main():
load_properties()
properties = app_properties()
request_manager = RequestHandler( properties['content_dir']
, properties['static_dir']
)
cherrypy.response.timeout = 20000
cherrypy.config.update('cherrypy.conf')
cherrypy.quickstart(request_manager)
def dexmlise(data):
"""Returns a version of data with stuff like > and <
changed into the appropriate symbols."""
sb = []
for line in data.split('\n'):
line = '<'.join( line.split('${lt}') )
line = '>'.join( line.split('${gt}') )
sb.append(line)
return '\n'.join( sb )
if __name__ == '__main__':
main()