From: Bernie Innocenti
Date: Sat, 11 Apr 2009 15:49:23 +0000 (+0200)
Subject: Merge branch 'master' of ssh://bernie@trinity.codewiz.org/~/public_html/wiki/git...
X-Git-Tag: v4.0~15
X-Git-Url: https://codewiz.org/gitweb?p=geekigeeki.git;a=commitdiff_plain;h=3f737b8a960486cd16aaa4acacc83acb24c7d42f;hp=0a6dbfd05009685e2c6eeb861023cf7da82ef60f
Merge branch 'master' of ssh://bernie@trinity.codewiz.org/~/public_html/wiki/git/geekigeeki into python3
Conflicts:
geekigeeki.py
---
diff --git a/geekigeeki.conf.py b/geekigeeki.conf.py
index 79421c7..d156daa 100644
--- a/geekigeeki.conf.py
+++ b/geekigeeki.conf.py
@@ -1,6 +1,12 @@
# Configuration values
+
+# this is displayed in the page title
site_name = 'Codewiz'
+# this is used for the leftmost button of the navbar.
+# It can be set to an empty string or a text message
+site_icon = 'AmigaBoing16x16.png'
+
# 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.develer.com/~bernie/wiki'
@@ -14,8 +20,8 @@ meta_urls = [
]
link_urls = [
# rel href
- [ 'icon', 'hacker-favicon.ico' ],
- [ 'stylesheet', '../wikidata/geekigeeki.css' ],
+ [ 'icon', 'sys/favicon.png' ],
+ [ 'stylesheet', 'sys/geekigeeki.css' ],
[ 'openid.server', 'https://www.develer.com/openid/bernie' ],
[ 'openid.delegate', 'https://www.develer.com/openid/bernie' ],
[ 'pavatar', 'http://www.codewiz.org/wiki/BernieAvatar80x80.png' ],
diff --git a/geekigeeki.css b/geekigeeki.css
deleted file mode 100755
index 8e7e9cc..0000000
--- a/geekigeeki.css
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * $Id$
- *
- * Author: Gerardo Poggiali
- * Author: Bernardo Innocenti
- */
-
-body {
- font-family: sans-serif;
- background-color: #F0F0F8;
- color: #000000;
- margin-top: 0px;
- margin-left: 0px;
- margin-right: 0px;
-}
-
-a { color: #1010FF; }
-a:visited { color: #501080; }
-a.nonexistent { color: #D04040; }
-a.navlink { color: #000088; font-size: smaller; font-weight: bold}
-a.external { font-style: italic; }
-a.heading { text-decoration: none; color: #aaaaaa; font-size: smaller; }
-
-h1 {
- font-size: x-large;
- font-weight: bold;
- color: #3377FF;
- border: #5599EE;
- background-color: #C2E2FF;
-
- margin-bottom: 0.2em;
- margin-top: 2em;
- padding-right: 10px;
- padding-left: 10px;
-
- border-top-width: 1px;
- border-bottom-width: 1px;
- border-right-width: 0px;
- border-left-width: 0px;
- border-style: solid;
-}
-
-h2 {
- font-size: large;
- font-weight: bold;
- color: #22AA33;
- border: #22AA33;
- background-color: #E8F8F0;
-
- margin-left: 5px;
- margin-right: 5px;
- margin-bottom: 0.1em;
- margin-top: 2em;
- padding-right: 10px;
- padding-left: 10px;
-
- border-top-width: 1px;
- border-bottom-width: 1px;
- border-left-width: 0px;
- border-right-width: 0px;
- border-style: solid;
-}
-
-h3 {
- font-size: large;
- font-weight: bold;
- color: #DD2255;
- border: #BB5599;
-
- margin-left: 10px;
- margin-right: 10px;
- padding-right: 5px;
- padding-left: 5px;
-
- border-top-width: 0px;
- border-bottom-width: 1px;
- border-right-width: 0px;
- border-left-width: 0px;
- border-style: solid;
-}
-
-h4 {
- font-size: medium;
- font-weight: bold;
- color: #2222AA;
-
- margin-left: 10px;
- margin-right: 10px;
- padding-right: 5px;
- padding-left: 5px;
-
- border: #333399;
- border-top-width: 0px;
- border-bottom-width: 1px;
- border-right-width: 0px;
- border-left-width: 0px;
- border-style: solid;
-}
-
-h5 {
- font-size: medium;
- font-weight: bold;
- color: #222288;
-
- margin-left: 10px;
- margin-right: 10px;
- padding-right: 5px;
- padding-left: 5px;
-}
-
-/* Heading anchors */
-.heading:link, .heading:visited {
- border: none;
- color: #d7d7d7;
- font-size: .8em;
- vertical-align: text-top;
-}
-* > .heading:link, * > .heading:visited {
- visibility: hidden;
-}
-
-h1:hover .heading, h2:hover .heading, h3:hover .heading,
-h4:hover .heading, h5:hover .heading, h6:hover .heading {
- visibility: visible;
-}
-
-strong.DONE {
- padding-left: 0.1em;
- background-color: #22ee22;
-}
-
-strong.TODO {
- padding-left: 0.1em;
- background-color: #ffdd44;
-}
-
-strong.FIXME {
- padding-left: 0.1em;
- background-color: #ee2222;
-}
-
-strong.error {
- color: red;
-}
-
-div {
- margin-left: 10px;
- margin-right: 10px;
- text-align: justify;
-}
-
-div.wiki {
- margin-left: 0;
- margin-right: 0;
-}
-
-div.preview {
- border: 2px dashed #FF0000;
-}
-
-div.index {
- border: 1px solid #EEEEEE;
-}
-
-div.nav {
- /*border-color: #88aacc;
- background-color: #aaccee;*/
- border-color: #888888;
- background-color: #cccccc;
- border-style: solid;
- border-top-width: 0px;
- border-bottom-width: 2px;
- border-left-width: 0px;
- border-right-width: 0px;
- padding-top: 5px;
- padding-bottom: 5px;
- padding-left: 5px;
- padding-right: 5px;
- margin-top: 0px;
- margin-bottom: 10px;
- margin-left: 0px;
- margin-right: 0px;
-}
-
-.nav hr {
- display: none;
-}
-
-.nav .login {
- font-size: small;
- color: red;
-}
-
-#footer div {
- margin-top: 1em;
- margin-left: 0;
- margin-right: 0;
-}
-
-#footer hr {
- border: none;
- border-top: 1px solid #bbbbbb;
- margin: 0 0;
-}
-
-#footer :link, #footer :visited {
- color: #666666;
-}
-
-#footer p {
- color: #888888;
- font-size: x-small;
- margin-top: 0;
-}
-
-#footer p.copyright {
- float: left;
- margin-left: 0em;
- padding: 0 1em;
-}
-
-#footer .license {
- border-width: 0;
- vertical-align: top;
- margin-left: 0em;
- margin-right: 1em;
-}
-
-#footer p.modified {
- float: right;
- text-align: right;
- margin-right: 1em;
-}
-
-p.dialog {
- border-color: black;
- background-color: white;
- padding-left: 5px;
- margin-left: 10px;
- margin-right: 10px;
- border-style: solid;
- border-top-width: 1px;
- border-right-width: 1px;
- border-bottom-width: 1px;
- border-left-width: 1px
-}
-
-p {
- margin-left: 10px;
- margin-right: 10px;
- margin-bottom: 10px;
- text-align: justify;
-}
-
-table {
- /*width: 100%;*/
- border: 2px solid #ccc;
- border-collapse: collapse;
- margin-left: 1em;
- margin-right: 1em;
- margin-top: 0.5em;
- margin-bottom: 0.5em;
-}
-
-table tbody thead {
- background: #f7f7f0
-}
-
-/* FIXME: should be thead */
-table tbody th {
- border: 1px solid #d7d7d7;
- border-bottom-color: #999;
- font-weight: bold;
- padding: 2px .5em;
- vertical-align: bottom;
-}
-
-table tbody td {
- border: 1px dotted #ddd;
- padding: .3em .5em;
- vertical-align: top;
-}
-
-table tbody tr { border-top: 1px solid #ddd }
-table tbody tr.even { background-color: #f0f0f0 }
-table tbody tr.odd { background-color: #e7e7e7 }
-table tbody tr:hover { background: #eed !important }
-
-table thead th :link:hover, table thead th :visited:hover table tbody td a:hover, table tbody th a:hover {
- background-color: transparent;
-}
-
-pre {
- color: #222222;
- border-color: #E9E609;
- background: #FFFDD0;
-
- margin-left: 10px;
- margin-right: 10px;
- padding-left: 5px;
- padding-right: 5px;
- padding-top: 5px;
- padding-bottom: 5px;
- border-style: solid;
- border-top-width: 1px;
- border-right-width: 1px;
- border-bottom-width: 1px;
- border-left-width: 1px;
-}
-
-pre.error {
- color: #FF0000;
- background: #000000;
- border-top-color: #FF0000;
- border-color: #FF0000;
- border-style: solid;
- border-width: 6px;
- margin: 0px;
-}
-
-pre.success {
- color: #00FF00;
- background: #000000;
- border-color: #00FF00;
- border-style: solid;
- border-width: 6px;
- margin: 0px;
-}
-
-pre.notice {
- color: #FFCC00;
- background: #000000;
- border-color: #FFCC00;
- border-style: solid;
- border-width: 6px;
- margin: 0px;
-}
-
-#editor {
- font-family: monospace;
- width: 100%;
- color: black;
- background-color: white;
- border: 1px solid #8cacbb;
-}
-
-/* thumbnails */
-
-div.extthumb {
- float: right;
- width: 100%;
-}
-
-div.thumb {
- float: left;
- border: 1px solid #ccc;
- padding: 3px !important;
- margin: 10px;
- margin-bottom: .5em;
- background-color: #f9f9f9;
- text-align: center;
-}
-
-div.thumb a img {
- border: 1px solid #ccc;
- vertical-align:bottom;
-}
-
-div.thumb div.caption {
- border: none;
- overflow: hidden;
- font-size: 94%;
- line-height: 1.4em;
- padding: .3em 0 .1em 0;
- text-align: center;
-}
-
-
-/* Styles for search word highlighting */
-@media screen {
- .searchword0 { background: #ff9 }
- .searchword1 { background: #cfc }
- .searchword2 { background: #cff }
- .searchword3 { background: #ccf }
- .searchword4 { background: #fcf }
-}
-
-@media print {
- #footer { display: none }
- .nav { display: none }
-}
diff --git a/geekigeeki.py b/geekigeeki.py
index 6e1ba6e..d208bb7 100755
--- a/geekigeeki.py
+++ b/geekigeeki.py
@@ -3,7 +3,7 @@
#
# Copyright 1999, 2000 Martin Pool
# Copyright 2002 Gerardo Poggiali
-# Copyright 2007, 2008 Bernie Innocenti
+# Copyright 2007, 2008, 2009 Bernie 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
@@ -30,18 +30,25 @@ import cgi, sys, os, re, errno, stat
word_re = re.compile(r"^\b((([A-Z][a-z0-9]+){2,}/)*([A-Z][a-z0-9]+){2,})\b$")
# FIXME: we accept stuff like foo/../bar and we shouldn't
file_re = re.compile(r"^\b([A-Za-z0-9_\-][A-Za-z0-9_\.\-/]*)\b$")
-img_re = re.compile(r"^.*\.(png|gif|jpg|jpeg|bmp|ico)$", re.IGNORECASE)
+img_re = re.compile(r"^.*\.(png|gif|jpg|jpeg|bmp|ico|ogm|ogg|mkv|mpg|mpeg|mp4|avi|asf|flv|wmv|qt)$", re.IGNORECASE)
+video_re = re.compile(r"^.*\.(ogm|ogg|mkv|mpg|mpeg|mp4|avi|asf|flv|wmv|qt)$", re.IGNORECASE)
url_re = re.compile(r"^[a-z]{3,8}://[^\s'\"]+\S$")
-link_re = re.compile("(?:\[\[|{{)([^\s\|]+)(?:\s*\|\s*([^\]]+)|)(?:\]\]|}})")
+link_re = re.compile(r"(?:\[\[|{{)([^\s\|]+)(?:\s*\|\s*([^\]]+)|)(?:\]\]|}})")
+ext_re = re.compile(r"\.([^\./]+)$")
title_done = False
-
# CGI stuff ---------------------------------------------------------
-
def script_name():
return os.environ.get('SCRIPT_NAME', '')
+def query_string():
+ path_info = os.environ.get('PATH_INFO', '')
+ if len(path_info) and path_info[0] == '/':
+ return path_info[1:] or 'FrontPage'
+ else:
+ return os.environ.get('QUERY_STRING', '') or 'FrontPage'
+
def privileged_path():
return privileged_url or script_name()
@@ -61,14 +68,17 @@ def get_hostname(addr):
except Exception:
return addr
+def is_external_url(pathname):
+ return (url_re.match(pathname) or pathname.startswith('/'))
+
def relative_url(pathname, privileged=False):
- if not (url_re.match(pathname) or pathname.startswith('/')):
+ if not is_external_url(pathname):
if privileged:
url = privileged_path()
else:
url = script_name()
pathname = url + '/' + pathname
- return pathname
+ return cgi.escape(pathname, quote=True)
def permalink(s):
return re.sub(' ', '-', re.sub('[^a-z0-9_ ]', '', s.lower()).strip())
@@ -84,30 +94,9 @@ def send_guru(msg_text, msg_type):
print(' Software Failure. Press left mouse button to continue.\n')
print(msg_text)
if msg_type == 'error':
- print('\n Guru Meditation #DEADBEEF.ABADC0DE')
- print('')
- # FIXME: This little JS snippet is harder to pass than ACID 3.0
- print("""
- """)
+ 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):
global title_done
@@ -153,11 +142,11 @@ def send_title(name, text="Limbo", msg_text=None, msg_type='error', writable=Fal
# Navbar
print('')
+ print link_tag('FrontPage', site_icon or 'Home', 'navlink')
if name:
print('
' + link_tag('?fullsearch=' + name, text, 'navlink') + ' ')
else:
print('
' + text + ' ')
- print(' | ' + link_tag('FrontPage', 'Home', 'navlink'))
print(' | ' + link_tag('FindPage', 'Find Page', 'navlink'))
if 'history_url' in globals():
print(' |
Recent Changes')
@@ -177,7 +166,7 @@ def send_title(name, text="Limbo", msg_text=None, msg_type='error', writable=Fal
user = remote_user()
if user != 'AnonymousCoward':
- print(' |
logged in as ' + cgi.escape(user) + '')
+ print(' |
' + link_tag('User/' + user, user) + '')
print('
')
@@ -186,19 +175,41 @@ def send_httperror(status="403 Not Found", query=""):
send_title(None, msg_text=("%s: on query '%s'" % (status, query)))
send_footer()
-def link_tag(params, text=None, ss_class=None, privileged=False):
+def link_tag(params, text=None, link_class=None, privileged=False):
if text is None:
text = params # default
- classattr = ''
- if ss_class:
- classattr += 'class="%s" ' % ss_class
- # Prevent crawlers from following links potentially added by spammers or to generated pages
- if ss_class == 'external' or ss_class == 'navlink':
- classattr += 'rel="nofollow" '
- elif url_re.match(params):
- classattr += 'rel="nofollow" '
+ elif img_re.match(text):
+ text = ''
+
+ if not link_class:
+ if is_external_url(params):
+ link_class = 'external'
+ elif file_re.match(params) and Page(params).exists():
+ link_class = 'wikilink'
+ else:
+ params = nonexist_pfx + params
+ link_class = 'nonexistent'
+
+ classattr = 'class="%s" ' % link_class
+ # Prevent crawlers from following links potentially added by spammers or to generated pages
+ if link_class == 'external' or link_class == 'navlink':
+ classattr += 'rel="nofollow"'
+
return '%s' % (classattr, relative_url(params, privileged=privileged), text)
+def link_inline(name, descr=None, args=''):
+ if not descr: descr = name
+ url = relative_url(name)
+ if video_re.match(name):
+ return '' % url
+ elif img_re.match(name):
+ return '' % (url, url + args, descr)
+ elif file_re.match(name) and not ext_re.search(name): # FIXME: this guesses a wiki page
+ return Page(name).send_naked()
+ else:
+ return '' \
+ % (url, url, name)
+
# Search ---------------------------------------------------
def handle_fullsearch(needle):
@@ -220,8 +231,8 @@ def handle_fullsearch(needle):
print("")
for (count, page_name) in hits:
- print('' + Page(page_name).link_to())
- print(' . . . . ' + str(count))
+ print('
' + link_tag(page_name))
+ print(' . . . . ' + `count`)
print(['match', 'matches'][count != 1])
print('
')
print("
")
@@ -238,7 +249,7 @@ def handle_titlesearch(needle):
print("")
print_search_stats(len(hits), len(all_pages))
@@ -275,9 +286,10 @@ def handle_edit(pagename):
text = form['savetext'].value
pg.send_editor(text)
+# Used by macros/WordIndex and macros/TitleIndex
def make_index_key():
links = ['%s' % (ch, ch) for ch in 'abcdefghijklmnopqrstuvwxyz']
- return ''+ ' | '.join(links) + '
'
+ return '' + ' | '.join(links) + '
'
def page_list(dirname = None, re = word_re):
return sorted(filter(re.match, os.listdir(dirname or data_dir)))
@@ -290,10 +302,10 @@ def send_footer(mod_string=None):
print('''