Design sheet

The handler (CGI / mod_python) handles the connections in the following
steps:

1. PATH_INFO is divided in the prefix and the rest (separated by the
   first `/').  Prefixes `show' and `edit' are handled internally and
   always work the same; other prefixes are treated as scripts and
   fetched from the script base.  The script is imported and a function
   handle() is called from its namespace.
2. handle() gets the rest of PATH_INFO and all of QUERY_STRING
   (preparsed into a dictionary).  It may do whatever it wants with
   those.  Additionally, it gets the script base and the filesystem as
   arguments (should these be combined?).
3. exceptions thrown by handle() are written to the client by the
   handler, together with links to `show' / `edit' to correct the
   problem.

The script base and the filesystem are dictionaries from arbitrary
strings to files.  The files should provide at least these services:

1. reading in whole or line by line
2. importing, for the script base
3. committing (or trying to ~) changes wrt a certain revision (this
   should raise an exception in case of conflicting changes)
4. access to previous revisions and diffs

Okay, here it is in more detailed form:

File.contents( [rev] ) - the whole contents of the file, as a string.
File.lines() - the lines of the file for iteration but not for random
  access (xreadlines).
File.exists() - whether the file exists and is nonempty.  (Empty files
  are considered not to exist but they're listed in FS.keys() anyway)
File.current() - the current revision of the file.
File.quickdiff( [rev] ) - compare the file to the last revision.
File.write( text, rev ) - commit changes relative to revision rev,
  possibly merging changes with already-committed simultaneous edits.
  If the merge causes a conflict, a MergeConflict exception is raised
  with the familiar conflict-marked merged text as an argument.  No
  commit is made.
File.append( text ) - does a commit which only appends text to the end
  of file.  Always relative to the current revision.
File.import() - the file as a module

The authorisation system of the File class requires read permissions for
the first five, and write permissions for the next two.  The last one
requires the execute permission.

The authorisation system, by the way, works by looking at the first few
lines of the file.  If they have lines containing the strings "allow:"
or "deny:", then these are treated as modifications to default site
auth. policy.  The exact syntax is:

auth_line :== auth_cmd ":" user_or_group [ "(" priv_type ")" ]
auth_cmd :== "allow" | "deny"
user_or_group :== string
priv_type :== "read" | "write" | "execute"

The lines are scanned until a matching line is found or a non-privilege
line is found.

