Index: piki.cgi
===================================================================
RCS file: /home/atehwa/cvs/code/python/piki/piki.cgi,v
retrieving revision 1.1.1.1
retrieving revision 1.6.2.1
diff -u -r1.1.1.1 -r1.6.2.1
--- piki.cgi	6 Aug 2003 22:39:51 -0000	1.1.1.1
+++ piki.cgi	7 Aug 2003 22:56:56 -0000	1.6.2.1
@@ -20,26 +20,26 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 # USA
 
-__version__ = '$Revision: 1.1.1.1 $'[11:-2];
+__version__ = '$Revision: 1.6.2.1 $'[11:-2];
 
 
-import cgi, sys, string, os, re, errno, time, stat
+import cgi, sys, string, os, re, errno, time, stat, urllib
 from cgi import log
 from os import path, environ
 from socket import gethostbyaddr
 from time import localtime, strftime
 from cStringIO import StringIO
 
-sys.stderr = open('/tmp/mbp_piki_err', 'at')
+data_dir = '/tmp'
+sys.stderr = open(path.join(data_dir, 'mbp_piki_err'), 'at')
 
 def emit_header():
     print "Content-type: text/html"
     print
 
 
-# Regular expression defining a WikiWord (but this definition
-# is also assumed in other places.
-word_re_str = r"\b([A-Z][a-z]+){2,}\b"
+# What kind of words are allowed in queries.
+word_re_str = r"[A-Za-z-������0-9 _.,+'!#%&=?;:><]+"
 word_anchored_re = re.compile('^' + word_re_str + '$')
 command_re_str = "(search|edit|fullsearch|titlesearch)\=(.*)"
 
@@ -99,9 +99,9 @@
     else:
         print text
     print '</h1>'
-    if msg: print msg
-    print '<hr>'
-
+    if msg:
+	print msg
+	print '<hr>'
 
 
 def link_tag(params, text=None, ss_class=None):
@@ -191,7 +191,10 @@
 
 
 def page_list():
-    return filter(word_anchored_re.match, os.listdir(text_dir))
+    return [page.replace( '_', ' ' )
+		for page in os.listdir(text_dir) 
+		if word_anchored_re.match(page) and
+		path.isfile(path.join(text_dir, page))]
 
 
 def print_footer(name, editable=1, mod_string=None):
@@ -225,6 +228,23 @@
     <input type=submit value="Go">
     </form>""" % (type, default)
 
+def _macro_WantedPages():
+	s = "<ul>\n"
+	link_re = re.compile( r"\[(" + word_re_str + r")\]" )
+	wanted = {}
+	for page in page_list():
+		body = Page( page ).get_raw_body()
+		for match in link_re.findall( body ):
+			name = match.lower()
+			try: wanted[name].append( page )
+			except KeyError:
+				if Page( name ).exists(): continue
+				wanted[name] = [page]
+	for (name, reflist) in wanted.items():
+		s = s + "<li> %s (%s) </li>\n" % \
+			(Page( name ).link_to(), '; '.join( reflist ))
+	return s + "</ul>\n"
+
 def _macro_GoTo():
     return """<form method=get><input name=goto size=30>
     <input type=submit value="Go">
@@ -235,7 +255,7 @@
     s = make_index_key()
     pages = list(page_list())
     map = {}
-    word_re = re.compile('[A-Z][a-z]+')
+    word_re = re.compile('\b[A-Z���a-z���]+\b')
     for name in pages:
         for word in word_re.findall(name):
             try:
@@ -382,6 +402,11 @@
         return apply(globals()['_macro_' + macro_name], ())
 
 
+    def _link_repl(self, word):
+	link_word = word[1:-1]
+	return Page(link_word).link_to()
+
+
     def _indent_level(self):
         return len(self.list_indents) and self.list_indents[-1]
 
@@ -415,14 +440,15 @@
         scan_re = re.compile(
             r"(?:(?P<emph>'{2,3})"
             + r"|(?P<ent>[<>&])"
-            + r"|(?P<word>\b(?:[A-Z][a-z]+){2,}\b)"
+            + r"|(?P<word>\b(?:[A-Z���][a-z���]+){2,}\b)"
             + r"|(?P<rule>-{4,})"
-            + r"|(?P<url>(http|ftp|nntp|news|mailto)\:[^\s'\"]+\S)"
+            + r"|(?P<url>(http|ftp|nntp|news|mailto)\:[^\s')(\"]+)"
             + r"|(?P<email>[-\w._+]+\@[\w.-]+)"
             + r"|(?P<li>^\s+\*)"
             + r"|(?P<pre>(\{\{\{|\}\}\}))"
-            + r"|(?P<macro>\[\[(TitleSearch|FullSearch|WordIndex"
+            + r"|(?P<macro>\[\[(TitleSearch|FullSearch|WantedPages|WordIndex"
                             + r"|TitleIndex|RecentChanges|GoTo)\]\])"
+	    + r"|(?P<link>\[" + word_re_str + r"\])"
             + r")")
         blank_re = re.compile("^\s*$")
         bullet_re = re.compile("^\s+\*")
@@ -445,13 +471,11 @@
 # ----------------------------------------------------------
 class Page:
     def __init__(self, page_name):
-        self.page_name = page_name
+        self.page_name = urllib.unquote(page_name)
 
     def split_title(self):
-        # look for the end of words and the start of a new word,
-        # and insert a space there
-        return re.sub('([a-z])([A-Z])', r'\1 \2', self.page_name)
-
+	# Most titles are correct already, so we just capitalize
+	return self.page_name[0].upper() + self.page_name[1:]
 
     def _text_filename(self):
         return path.join(text_dir, self.page_name)
@@ -474,13 +498,14 @@
 
     def link_to(self):
         word = self.page_name
+	q = urllib.quote
         if self.exists():
-            return link_tag(word)
+            return link_tag(q(word), word)
         else:
             if nonexist_qm:
-                return link_tag(word, '?', 'nonexistent') + word
+                return link_tag(q(word), '?', 'nonexistent') + word
             else:
-                return link_tag(word, word, 'nonexistent')
+                return link_tag(q(word), word, 'nonexistent')
 
 
     def get_raw_body(self):
@@ -495,7 +520,7 @@
     
 
     def send_page(self, msg=None):
-        link = get_scriptname() + '?fullsearch=' + self.page_name
+        link = get_scriptname() + '?fullsearch=' + urllib.quote( self.page_name )
         send_title(self.split_title(), link, msg)
         PageFormatter(self.get_raw_body()).print_html()
         print_footer(self.page_name, 1, self._last_modified())
@@ -507,6 +532,8 @@
         modtime = localtime(os.stat(self._text_filename())[stat.ST_MTIME])
         return strftime(datetime_fmt, modtime)
 
+    def quotehtmlent(self, body):
+        return body.replace( '&', '&amp;' ).replace( '<', '&lt;' ).replace( '>', '&gt;' )
 
     def send_editor(self):
         send_title('Edit ' + self.split_title())
@@ -514,14 +541,10 @@
         print '<input type=hidden name="savepage" value="%s">' % (self.page_name)
         raw_body = string.replace(self.get_raw_body(), '\r\n', '\n')
         print """<textarea wrap="virtual" name="savetext" rows="17"
-                 cols="80">%s</textarea>""" % raw_body
+                 cols="80">%s</textarea>""" % self.quotehtmlent( raw_body )
         print """<br><input type=submit value="Save">
                  <input type=reset value="Reset">
                  """
-        print "<br>"
-        print Page("UploadFile").link_to()
-        print "<input type=file name=imagefile>"
-        print "(not enabled yet)"
         print "</form>"
         print "<p>" + Page('EditingTips').link_to()
                  
@@ -548,7 +571,7 @@
 emit_header()
 
 # Configurable parts ------------------------------------------
-data_dir = '/home/mbp/piki-data/'
+
 text_dir = path.join(data_dir, 'text')
 editlog_name = path.join(data_dir, 'editlog')
 cgi.logfile = path.join(data_dir, 'cgi_log')
