X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;ds=sidebyside;f=geekigeeki.py;h=79dda63e2c463df56b6e9790985b4005d727f2b4;hb=46efe19f353d79e0be12da32980ef1457a97d749;hp=1dda0ca341bb94b37a32a68dcfeb7f6262dfdb4f;hpb=ab69b32156a6a5b814b825762fed199d11632938;p=geekigeeki.git
diff --git a/geekigeeki.py b/geekigeeki.py
index 1dda0ca..79dda63 100755
--- a/geekigeeki.py
+++ b/geekigeeki.py
@@ -8,23 +8,17 @@
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
+# (at your option) any later version. You should have received a copy
+# of the GNU General Public License along with this program.
+# If not, see .
__version__ = '4.0-' + '$Id$'[4:11]
-from time import clock
+from time import clock, localtime, gmtime, strftime
start_time = clock()
title_done = False
-import cgi, sys, os, re, errno, stat
+import cgi, sys, os, re, errno, stat, glob
image_ext = 'png|gif|jpg|jpeg|bmp|ico'
video_ext = "ogg|ogv|oga" # Not supported by Firefox 3.5: mkv|mpg|mpeg|mp4|avi|asf|flv|wmv|qt
@@ -42,6 +36,9 @@ def config_get(key, default=None):
def script_name():
return os.environ.get('SCRIPT_NAME', '')
+def script_path():
+ return os.path.split(os.environ.get('SCRIPT_FILENAME', ''))[0]
+
def query_string():
path_info = os.environ.get('PATH_INFO', '')
if len(path_info) and path_info[0] == '/':
@@ -108,7 +105,9 @@ def url_args(kvargs):
return ''
# Formatting stuff --------------------------------------------------
-def emit_header(mime_type="text/html"):
+def emit_header(mtime=None, mime_type="text/html"):
+ if mtime:
+ print("Last-Modified: " + strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime(mtime)))
print("Content-type: " + mime_type + "; charset=utf-8\n")
def send_guru(msg_text, msg_type):
@@ -116,18 +115,18 @@ def send_guru(msg_text, msg_type):
print('
')
if msg_type == 'error':
print(' Software Failure. Press left mouse button to continue.\n')
- print(msg_text)
+ print(cgi.escape(msg_text))
if msg_type == 'error':
print '\n Guru Meditation #DEADBEEF.ABADC0DE'
print('
' \
% relative_url('sys/GuruMeditation.js'))
-def send_title(name, text="Limbo", msg_text=None, msg_type='error', writable=False):
+def send_title(name, text="Limbo", msg_text=None, msg_type='error', writable=False, mtime=None):
global title_done
if title_done: return
# Head
- emit_header()
+ emit_header(mtime)
print('')
print('')
@@ -147,7 +146,7 @@ def send_title(name, text="Limbo", msg_text=None, msg_type='error', writable=Fal
editable = name and writable and config_get('privileged_url') is not None
if editable:
print(' ' \
- % (privileged_path() + '?a=edit&q=' + name))
+ % relative_url('?a=edit&q=' + name, privileged=True))
history = config_get('history_url')
if history is not None:
@@ -158,7 +157,7 @@ def send_title(name, text="Limbo", msg_text=None, msg_type='error', writable=Fal
# Body
if editable:
- print('')
+ print('')
else:
print('')
@@ -227,15 +226,25 @@ def link_inline(name, descr=None, kvargs={}):
if not descr: descr = humanlink(name)
url = relative_url(name)
if video_re.match(name):
- return '' % url
+ return '' % url
elif image_re.match(name):
return '' % (url, url + url_args(kvargs), descr)
elif file_re.match(name) and not ext_re.search(name): # FIXME: this guesses a wiki page
- return Page(name).send_naked(kvargs)
+ Page(name).send_naked(kvargs) # FIXME: we should return the page as a string rather than print it
+ return ''
else:
return '' \
% (url, url, name)
+def link_inline_glob(pattern, descr=None, kvargs={}):
+ if not url_re.match(pattern) and bool(set(pattern) & set('?*[')):
+ s = ''
+ for name in glob.glob(pattern):
+ s += link_inline(name, descr, kvargs)
+ return s
+ else:
+ return link_inline(pattern, descr, kvargs)
+
# Search ---------------------------------------------------
def print_search_stats(hits, searched):
@@ -325,7 +334,7 @@ def handle_get(pagename, form):
else:
send_httperror("403 Forbidden", pagename)
-# Used by macros/WordIndex and macros/TitleIndex
+# Used by sys/macros/WordIndex and sys/macros/TitleIndex
def make_index_key():
links = ['%s' % (ch, ch) for ch in 'abcdefghijklmnopqrstuvwxyz']
return '
' + ' | '.join(links) + '
'
@@ -334,14 +343,16 @@ def page_list(dirname=None, search_re=None):
if search_re is None:
# FIXME: WikiWord is too restrictive now!
search_re = re.compile(r"^\b((([A-Z][a-z0-9]+){2,}/)*([A-Z][a-z0-9]+){2,})\b$")
- return sorted(filter(search_re.match, os.listdir(dirname or config_get('data_dir', 'data'))))
+ return sorted(filter(search_re.match, os.listdir(dirname or '.')))
-def send_footer(mod_string=None):
+def send_footer(mtime=None):
if config_get('debug_cgi', False):
cgi.print_arguments()
cgi.print_form(form)
cgi.print_environ()
- link_inline("sys/footer", kvargs = { 'LAST_MODIFIED': mod_string })
+ link_inline("sys/footer", kvargs = {
+ 'LAST_MODIFIED': strftime(config_get('datetime_fmt', '%a %d %b %Y %I:%M %p'), localtime(mtime))
+ })
print("")
def _macro_ELAPSED_TIME(*args, **kvargs):
@@ -362,7 +373,7 @@ class WikiFormatter:
self.h_level = 0
self.in_pre = self.in_html = self.in_table = self.in_li = False
self.in_header = True
- self.list_indents = []
+ self.list_indents = [] # a list of pairs (indent_level, list_type) to track nested lists
self.tr_cnt = 0
self.styles = {
#wiki html enabled?
@@ -400,7 +411,7 @@ class WikiFormatter:
return ' '
def _rule_repl(self, word):
- return self._undent() + '\n\n' % (len(word) - 2)
+ return '\n\n' % (len(word) - 2)
def _macro_repl(self, word):
try:
@@ -409,11 +420,11 @@ class WikiFormatter:
return self.kvargs[args[0]]
macro = globals().get('_macro_' + args[0])
if not macro:
- exec(open("macros/" + args[0] + ".py").read(), globals())
+ exec(open("sys/macros/" + args[0] + ".py").read(), globals())
macro = globals().get('_macro_' + args[0])
return macro(*args, **kvargs)
except Exception, e:
- msg = cgi.escape(word) + ": " + cgi.escape(e.message)
+ msg = cgi.escape(word) + ": " + cgi.escape(str(e))
if not self.in_html:
msg = '' + msg + ''
return msg
@@ -430,10 +441,10 @@ class WikiFormatter:
# This double div nonsense works around a limitation of the HTML block model
return '
'
else:
- return link_inline(name, None, kvargs)
+ return link_inline_glob(name, None, kvargs)
def _html_repl(self, word):
if not self.in_html and word.startswith('
new_level:
- del(self.list_indents[-1])
if self.in_li:
s += ''
self.in_li = False # FIXME
- s += '\n'
+ s += '' + self.list_indents[-1][1] + '>\n'
+ del(self.list_indents[-1])
+
+ list_type = ('ul', 'ol')[list_type == '#']
while self._indent_level() < new_level:
- self.list_indents.append(new_level)
- s += '
\n'
+ self.list_indents.append((new_level, list_type))
+ s += '<' + list_type + '>\n'
s += '
'
return s
- def _undent(self):
- res = '
'
- res += '
' * len(self.list_indents)
- res += '
'
- self.list_indents = []
- return res
-
def replace(self, match):
for rule, hit in list(match.groupdict().items()):
if hit:
@@ -583,7 +589,7 @@ class WikiFormatter:
| (?P[<>&])"
)""", re.VERBOSE)
blank_re = re.compile(r"^\s*$")
- indent_re = re.compile(r"^\s*")
+ indent_re = re.compile(r"^(\s*)(\*|\#|)")
tr_re = re.compile(r"^\s*\|\|")
eol_re = re.compile(r"\r?\n")
# For each line, we scan through looking for magic strings, outputting verbatim any intervening text
@@ -606,13 +612,13 @@ class WikiFormatter:
print('
')
else:
indent = indent_re.match(self.line)
- #3.0: print(self._indent_to(len(indent.group(0))), end=' ')
- print(self._indent_to(len(indent.group(0))))
+ print(self._indent_to(len(indent.group(1)), indent.group(2)))
+ # Stand back! Here we apply the monster regex that does all the parsing
print(re.sub(scan_re, self.replace, self.line))
if self.in_pre: print('')
if self.in_table: print('