X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=geekigeeki.py;h=5ae1bd3f51d7de73b4a029f3f0ea5505d8231a03;hb=8603419a18f6bee65d7d9bb36dacdac278b2792b;hp=46c61c55ad5343f95bbf6541eb959a6cab0f0638;hpb=25befe4147c23d55b1ef3fc8af45c719e2e39f8c;p=geekigeeki.git diff --git a/geekigeeki.py b/geekigeeki.py index 46c61c5..5ae1bd3 100755 --- a/geekigeeki.py +++ b/geekigeeki.py @@ -1,10 +1,8 @@ #! /usr/bin/env python -"""Quick-quick implementation of WikiWikiWeb in Python -""" # -# Copyright (C) 1999, 2000 Martin Pool -# This version includes additional changes by Gerardo Poggiali (2002) -# This version includes additional changes by Bernardo Innocenti (2007) +# Copyright 1999, 2000 Martin Pool +# Copyright 2002 Gerardo Poggiali +# Copyright 2007 Bernardo Innocenti # # 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 @@ -19,9 +17,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -__version__ = '$Revision: 1.63+gerry+bernie $'[11:-2] +__version__ = '$Id$'[4:12] -import cgi, sys, string, os, re, errno, time, stat +from time import clock +start_time = clock() + +import cgi, sys, string, os, re, errno, stat from os import path, environ # Regular expression defining a WikiWord @@ -102,15 +103,16 @@ def send_title(name, text="Limbo", msg=None, msg_type='error'): # Head emit_header() - print """ - -""" + print '' + print '' + + site_name = globals().get('site_name', 'Unconfigured Site') print "%s: %s" % (site_name, text) print ' ' if not name: print ' ' - if css_url: + if globals().has_key('css_url'): print ' ' % css_url print '' @@ -132,10 +134,12 @@ def send_title(name, text="Limbo", msg=None, msg_type='error'): print text + ' ' print ' | ' + link_tag('FrontPage', 'Front Page', 'navlink') print ' | ' + link_tag('FindPage', 'Find Page', 'navlink') - print ' | Recent Changes' + if globals().has_key('history_url'): + print ' | Recent Changes' + if name: + print ' | Page History' if name: - print ' | Page History' print ' | ' + link_tag('?raw=' + name, 'Raw Text', 'navlink') if privileged_url is not None: print ' | ' + link_tag('?edit=' + name, 'Edit Page', 'navlink', authentication=True) @@ -154,8 +158,7 @@ def link_tag(params, text=None, ss_class=None, authentication=False): classattr = '' if ss_class: classattr += 'class="%s" ' % ss_class - # Prevent crawlers from following links to generated pages - # and links added by potential spammers + # Prevent crawlers from following links potentially added by spammers or to generated pages if ss_class == 'external' or ss_class == 'navlink': classattr += 'rel="nofollow" ' if authentication: @@ -187,13 +190,12 @@ def do_fullsearch(needle): for (count, page_name) in hits: print '
  • ' + Page(page_name).link_to() print ' . . . . ' + `count` - print ['match', 'matches'][count <> 1] + print ['match', 'matches'][count != 1] print '

  • ' print "" print_search_stats(len(hits), len(all_pages)) - def do_titlesearch(needle): # TODO: check needle is legal -- but probably we can just accept any RE send_title(None, "Title search for \"" + needle + '"') @@ -209,10 +211,10 @@ def do_titlesearch(needle): print_search_stats(len(hits), len(all_pages)) - def print_search_stats(hits, searched): print "

    %d hits out of %d pages searched.

    " % (hits, searched) +#TODO: merge into do_savepage() def do_edit(pagename): Page(pagename).send_editor() @@ -220,9 +222,6 @@ def do_raw(pagename): Page(pagename).send_raw() def do_savepage(pagename): - if privileged_url is None: - raise 'editing disallowed for ' + pagename - global form pg = Page(pagename) if 'preview' in form: @@ -231,7 +230,7 @@ def do_savepage(pagename): pg.save_text(form['savetext'].value) pg.send_page() elif 'cancel' in form: - pg.msg = 'Editing cancelled' + pg.msg = 'Editing canceled' pg.msg_type = 'notice' pg.send_page() else: @@ -245,23 +244,23 @@ def make_index_key(): s = s + '

    ' return s - def page_list(): return filter(word_re.match, os.listdir(text_dir)) - def send_footer(name, mod_string=None): - if debug_cgi: + if globals().get('debug_cgi', False): cgi.print_arguments() cgi.print_form(cgi.FieldStorage()) cgi.print_environ() + global __version__ print '' - # ---------------------------------------------------------- # Macros def _macro_TitleSearch(*vargs): @@ -295,7 +294,7 @@ def _macro_WordIndex(*vargs): # set title for word in all_words: letter = string.lower(word[0]) - if letter <> last_letter: + if letter != last_letter: s = s + ';

    %s

    ' % (letter, letter) last_letter = letter @@ -317,7 +316,7 @@ def _macro_TitleIndex(*vargs): current_letter = None for name in pages: letter = string.lower(name[0]) - if letter <> current_letter: + if letter != current_letter: s = s + '

    %s

    ' % (letter, letter) current_letter = letter else: @@ -355,12 +354,12 @@ class PageFormatter: def _tit_repl(self, word): if self.h_level: - result = "" % self.h_level + result = '' % self.h_level self.h_level = 0 else: self.h_level = len(word) - 1 self.h_count += 1 - result = '' % (self.h_count, self.h_level, self.h_count) + result = '* ' % (self.h_level, self.h_count, self.h_count) return result def _rule_repl(self, word): @@ -487,7 +486,7 @@ class PageFormatter: raise "Can't handle match " + `match` def print_html(self): - print "

    " + print '

    ' # For each line, we scan through looking for magic # strings, outputting verbatim any intervening text @@ -552,7 +551,7 @@ class PageFormatter: if self.in_pre: print '' if self.in_table: print '

    ' print self._undent() - print "

    " + print '

    ' # ---------------------------------------------------------- class Page: @@ -576,10 +575,10 @@ class Page: def exists(self): try: os.stat(self._text_filename()) - return 1 + return True except OSError, er: if er.errno == errno.ENOENT: - return 0 + return False else: raise er @@ -588,21 +587,15 @@ class Page: if self.exists(): return link_tag(word, word, 'wikilink') else: - if nonexist_qm: - return link_tag(word, '?', 'nonexistent') + word - else: - return link_tag(word, word, 'nonexistent') - + return link_tag(word, nonexist_pfx + word, 'nonexistent') def get_raw_body(self): try: return open(self._text_filename(), 'rt').read() except IOError, er: if er.errno == errno.ENOENT: - # just doesn't exist, use default - return 'Describe %s here.' % self.page_name - else: - raise er + return '' # just doesn't exist, use default + raise er def get_attrs(self): if self.attrs: @@ -621,38 +614,55 @@ class Page: raise er return self.attrs - def can_edit(self): + def can(self, action, default=True): attrs = self.get_attrs() try: # SomeUser:read,write All:read acl = attrs["acl"] for rule in acl.split(): - (user,perms) = acl.split(':') + (user,perms) = rule.split(':') if user == remote_user() or user == "All": - if 'write' in perms.split(','): + if action in perms.split(','): return True + else: + return False return False - except: + except Exception, er: pass - return True + return default + + def can_write(self): + return self.can("write", True) + + def can_read(self): + return self.can("read", True) def send_page(self): page_name = None - if self.can_edit(): + if self.can_write(): page_name = self.page_name send_title(page_name, self.split_title(), msg=self.msg, msg_type=self.msg_type) - PageFormatter(self.get_raw_body()).print_html() + if self.can_read(): + PageFormatter(self.get_raw_body()).print_html() + else: + send_guru("Read access denied by ACLs", "notice") send_footer(page_name, self._last_modified()) def _last_modified(self): - if not self.exists(): + try: + from time import localtime, strftime + modtime = localtime(os.stat(self._text_filename())[stat.ST_MTIME]) + except OSError, er: + if er.errno != errno.ENOENT: + raise er return None - from time import localtime, strftime - modtime = localtime(os.stat(self._text_filename())[stat.ST_MTIME]) return strftime(datetime_fmt, modtime) def send_editor(self, preview=None): send_title(None, 'Edit ' + self.split_title(), msg=self.msg, msg_type=self.msg_type) + if not self.can_write(): + send_guru("Write access denied by ACLs", "error") + return print ('

    Editing ' + self.page_name + ' for ' + cgi.escape(remote_user()) @@ -677,6 +687,9 @@ class Page: send_footer(self.page_name) def send_raw(self): + if not self.can_read(): + send_title(None, msg='Read access denied by ACLs', msg_type='notice') + return emit_header("text/plain") print self.get_raw_body() @@ -689,10 +702,15 @@ class Page: try: os.remove(text) except OSError, er: - if er.errno <> errno.ENOENT: raise er + if er.errno != errno.ENOENT: raise er os.rename(tmp_filename, text) def save_text(self, newtext): + if not self.can_write(): + self.msg = 'Write access denied by ACLs' + self.msg_type = 'error' + return + self._write_file(newtext) rc = 0 if post_edit_hook: @@ -711,9 +729,10 @@ class Page: if msg: self.msg += 'Output follows:\n' + msg else: - self.msg = 'Thankyou for your contribution. Your attention to detail is appreciated.' + self.msg = 'Thank you for your contribution. Your attention to detail is appreciated.' self.msg_type = 'success' +#TODO: merge into send_raw() def send_verbatim(filename, mime_type='application/octet-stream'): pathname = path.join(text_dir, filename) data = open(pathname, 'rb').read() @@ -722,24 +741,7 @@ def send_verbatim(filename, mime_type='application/octet-stream'): # Main --------------------------------------------------------------- try: - # Configuration values - site_name = 'Codewiz' - - # set to None for read-only sites - # leave empty ('') to allow anonymous edits - # otherwise, set to a URL that requires authentication - privileged_url = 'https://www.codewiz.org/~bernie/wiki' - - data_dir = '/home/bernie/public_html/wiki' - text_dir = path.join(data_dir, 'text') - css_url = '../wikidata/geekigeeki.css' # optional stylesheet link - history_url = '../wikigit/wiki.git' - post_edit_hook = './post_edit_hook.sh' - datetime_fmt = '%a %d %b %Y %I:%M %p' - allow_edit = True # Is it possible to edit pages? - show_hosts = True # show hostnames? - nonexist_qm = False # show '?' for nonexistent? - debug_cgi = False # Set to True for CGI var dump + execfile("geekigeeki.conf.py") form = cgi.FieldStorage() @@ -769,7 +771,7 @@ try: else: send_verbatim(query) else: - # TODO: return 404? + print "Status: 404 Not Found" send_title(None, msg='Can\'t work out query: ' + query) except: import traceback