--------------------------------------------------------------------------------
    PYLE - A WikiClone in Python
    Copyright (C) 1999, 2000  Tony Garnock-Jones <tonyg@kcbbs.gen.nz>

    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 2 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, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
--------------------------------------------------------------------------------

0. Contents:

This program is free software, covered by the GNU GPL. "Share and
enjoy!"  Please see the file "COPYING" in this directory for
details. This program is copyright 1999, 2000 to Tony Garnock-Jones
<tonyg@kcbbs.gen.nz>.

1. Installation
	1.1 Example 1.
	1.2 Example 2.
	1.3 Example 3, using the CVS backend.
	1.4 Problems you might run into
2. Configuration
	2.1 Variables in Config.py
	2.2 Content of the template-* files
	2.3 The Superuser(s)
3. WikiFormatting
4. A note about security
5. Contributing changes back

--------------------------------------------------------------------------------

1. Installation

You will need:
	* a working webserver (Apache works for me...)
	* a working python interpreter, version 1.5 or better, with the
		standard set of libraries, including cgi.py and shelve.py
		among others
	* a decent implementation of DBM databases - see below, section 1.3
	* optionally, access to a CVS repository
	* optionally, an installation of cvsweb

Untar the package into a directory of your choice. The files *.py and
*.cgi have to be together in a directory which can run CGI
programs. Only the files pyle.cgi and user.cgi should have execute
permissions - the others (*.py) are library files.

The program needs to have write permissions on a directory somewhere
in the file system. In this directory will be stored the DBM database
of WikiPages itself, and the HTML template header/footer/redirect
files. If you are using the CVS backend, you will need to have an
empty CVS module checked out somewhere for use as the database,
readable and writable by your httpd user (usually 'nobody').

If you want a logo to be displayed, the logo needs to be stored
somewhere within the DocumentRoot of your webserver.

If you are using the CVS backend, and want to get diffs between
versions of PylePages, you will need to install cvsweb. You can get
Henner Zeller's version of cvsweb from
http://linux.stud.fh-heilbronn.de/~zeller/cgi/cvsweb.cgi/.

The executable files dbcreate, dbdump and dbpack should *NOT* be
placed in your cgi-bin directory (or if they are, they should have
execute-permissions switched off). They are administrative tools only.

1.1 Example 1.

In this example:
	* DocumentRoot is /home/httpd/html (default RedHat style)
	* pyle.cgi and *.py live in /home/httpd/cgi-bin
	* the database and other files live in /usr/local/pylewiki/
	* the logo lives in DocumentRoot/.

As root, I did this:
	* mkdir /usr/local/pylewiki
	* chmod a+w /usr/local/pylewiki
	* cp template-* /usr/local/pylewiki
	* mkdir /home/httpd/cgi-bin/pyle
	* chmod a+w /home/httpd/cgi-bin/pyle
	* cp pyle.cgi *.py /home/httpd/cgi-bin/pyle
	* cp pylelogo.png /home/httpd/html

Then I edited /home/httpd/cgi-bin/Config.py so that "pyledir" pointed
to /usr/local/pylewiki and "logo_url" read "/pylelogo.png".

1.2 Example 2.

In this example:
	* Pyle is running out of my public_html directory

As myself, I did this:
	* mkdir ~/public_html/pyle
	* chmod a+w ~/public_html/pyle
	* cp pyle.cgi *.py template-* ~/public_html/pyle

Because the datafiles are in the same directory as the CGI program, I
left the settings for "pyledir" and "logo_url" in Config.py alone, at
the default.

Note that this setup requires the webserver to allow users to execute
CGI applications out of their own directories. You'll have to consult
your webserver documentation for how to set this up.

1.3 Example 3, using the CVS backend.

In this example:
	* Pyle is running using the CVS backend
	* pyle.cgi and *.py live in /home/httpd/html/pyle/
	* the database is a checked-out CVS module at /home/httpd/html/pyledb
	* cvsweb is used to generate nice colourised diffs

As myself, I did this:
	* cd /home/httpd/html/
	* tar -zxvf pyle.tar.gz

Then I edited Config.py:
	* use_cvs = 1
	* pyledb = pyledir + '/../pyledb'
	* cvsweb_path = '/cvsweb/index.cgi/pyledb/'

Then I installed cvsweb in /home/httpd/html/cvsweb.

Then I created an empty CVS module called 'pyledb', and checked it out
as user 'nobody' into /home/httpd/html:
	* cd /home/httpd/html
	* cvs co pyledb
	* chown -R nobody pyledb

1.4 Problems you might run into

If you're using the CVS backend, it can be tricky to get Pyle to come
up initially. Usually the problem is insufficient permissions on the
relevant directories - remember that all the Pyle code is run as your
httpd user ('nobody', usually) so checking out the pyledb module as
yourself won't work, in general. If you do have difficulty, please
consider taking notes as you fix the problem, and when you've fixed
it, mail me the notes on what happened and how you fixed it, and I'll
include them in this document.

Note that the 'users' record is NOT stored in the CVS repository. (All
the passwords are stored in plaintext.)

If you're using the DBM backend, you will need to use gdbm - the code
as shipped relies on the gdbm.py Python module to work properly. If
you wish to use a different module, import it into Utils.py instead of
gdbm, and change the line

	internal_db = gdbm.open(pyledb, 'r', 0666)

to read

	internal_db = <whatever module you chose>.open(pyledb, 'r', 0666)

Before I changed from using anydbm.py to using gdbm.py directly, I
wrote the following:

	------------------------------------------------------------
	I developed this program on RedHat Linux, versions 5.1, 6.0
	and 6.1. There is an important discrepancy between version 6.1
	and the others - the database formats seem incompatible between 6.1
	and earlier versions!

	I wrote the script 'dbcreate' to get a working database
	created on RedHat 6.1 - leaving it up to the CGI script works
	fine on the other platforms, but 6.1 seems to need to be told
	to use gdbm explicitly.

	YMMV, basically. Once the database is initialised (by whatever
	method) the script should be okay. Until that point, however,
	you may see the symptoms I saw with RH6.1:

	* initially, the database does not exist.
	* the first hit on the CGI script creates the database, and the
		front page comes up as usual.
	* any subsequent hits fail with Error 500, because the script
		doesn't know how to read the database it created
		during the first hit.

	I didn't spend much time on figuring out what was wrong, just
	worked around it with the db* scripts.
	------------------------------------------------------------

2. Configuration

This section will go through the variables and files involved in
configuring PyleWiki.

2.1 Variables in Config.py

pyledir		This is the directory in which the program's data files,
		including the DBM database, are stored by default.

use_cvs		Boolean; nonzero to use the CVS backend, zero for the DBM
		backend.

pyledb		the path to the DBM database file

cvsweb_path	Only relevant if use_cvs is nonzero. Set to None to
		disable cvsweb support, else set to a URL prefix which
		points to the pyledb module in the cvsweb URL-space.

templatehead	the path to an HTML header template
templatetail	the path to an HTML trailer template
templateredir	the path to an HTML template sent when redirecting the user
		- the content of these three files is discussed below

header_formatting
		An array of 2-tuples containing open- and close-tags for
		successive levels of header formatting, for use with
		"headre" in Utils.py. Set this to your preferred HTML
		fragments for header markup.

logo_url	URL to a logo graphic, provided as a variable to the
		HTML template files

anonymous_user	the name to use when recording actions of a user who has
		not logged in.

allow_anonymous_edit
allow_anonymous_view
		if nonzero, anonymous users may edit or view pages,
		respectively (if they are permitted to on a
		page-by-page basis by the page's creator/owner)

allow_user_create
		if nonzero, allows users who do not have a user account
		to create one themselves, via the web interface. If zero,
		the administrator will have to either use the makefile
		or log in as the super-user to create one for them.

default_rights	a structure describing the default set of per-page
		permissions to apply to new pages.

user_cookie_name
		the name of the cookie sent by the scripts back to the
		user for the purpose of user identification.

frontpage	the name of the WikiPage to display by default

linkpattern	the regular-expression describing the form of a WikiWord

mimetypes	an array of mimetypes that this CGI knows about for when
		dealing with attachments to WikiPages.
		Note that the array contains pairs of (mimetype, extension) -
		only the mimetype is used in day-to-day operation; the
		extension is used when making a static copy of the database
		('make webtree')

inlinepattern	the regexp selecting mimetypes which are to be inlined using
		an HTML <IMG> tag, rather than direct inclusion

textarea_cols	the width of the textarea used to edit a WikiPage
textarea_rows	the height of the textarea used to edit a WikiPage

email_notification_message
		the text of the message to email to a user when one of the
		user's subscribed pages is altered by someone other than
		the user him/herself.

2.2 Content of the template-* files

The files named by Config.py's template* variables are supposed to
contain HTML fragments - templatehead is to contain the standard
header put on (almost) every response page sent by pyle.cgi,
templatetail is to contain the standard trailer, and templateredir is
to contain a complete page, used by pyle.cgi when it wishes to
redirect the user to another page internal to itself.

Certain strings in the template files are considered 'special', and
are variable-expanded (by Python's string '%' operator,
internally). If you wish to substitute in one of the expanded
variables, use the syntax '%(variablename)s'. The 's' on the end is
important - it tells Python to expect a string there.

Variables available are:
	In templatehead:
		title		The intended <TITLE> of the page
		heading		usually empty, or an <H1> heading element
		logo		the contents of Config.py's logo_url variable

	In templatetail:
		logo		the contents of Config.py's logo_url variable

	In templateredir:
		redir		the URL to redirect the user to, by way of
				a <META> tag, usually
		pagename	the WikiPage to redirect to
		action		the action that caused the redirection to
				take place
		logo		the contents of Config.py's logo_url variable

2.3 The Superuser(s)

In order to administer users via the web interface, you must be logged
in as a user with /superuser/ permissions. You can't create superusers
via the web interface - it must be done by hand at the shell
prompt. In the pyle directory, run 'make newuser', and you will be
prompted for the user details. Make sure you answer 'yes' to the
question about superuser status!

In addition to all the things regular users can do, the superuser can -
	* read and edit any page
	* edit any page's attachments or permissions
	* change the owner of any page
	* add and remove users
	* list users by regular-expression
	* create users (this is only special if Config.allow_user_create is false)

3. WikiFormatting

This section describes the formatting language used when editing WikiPages.

	* lines ending with '\' are considered continuation lines, and are
		interpreted as flowing straight on into the next line - the
		newline is elided, basically
	* fragments of text that look like URLs are made active as links

	* blank lines separate paragraphs

	* lines starting with tabs and then an asterisk, '*', make a bulleted list
	* lines starting with tabs and then a series of digits make a numbered list
	* lines starting with tabs followed by some text, a colon, and another tab
		make a "definition list" as per HTML tags <DL>, <DT> and <DD>.
	* the number of tabs at the start of these lines controls the nesting of
		the various kinds of list.
	* other lines starting with whitespace are considered to be 'preformatted'
		and are displayed using the HTML <PRE> tag.

	* words matching Config.py's "linkpattern" regexp are turned into internal
		WikiPage links
	* text of the form [:arbitrary string:] is converted to refer to an attachment
		named "arbitrary string", if such an attachment exists.

	* text surrounded by _underscores_ is underlined
	* text surrounded by ''a pair of single-quotes'' is italicised
	* text surrounded by '''three sets of single-quotes''' is made bold
	* a line consisting entirely of dashes, '-', with at least four dashes on
		the line, is converted into an HTML horizontal rule (<HR>) tag.

	* lines beginning with one or more stars, with no whitespace to the left,
		are converted into a numbered section header, with the section
		level controlled by the number of stars (eg. 1 star is a major
		section header, 6 stars is a very minor subsubsection header).
		The section headers are styled using header_formatting from Config.py
		and a table of contents is generated and rendered at the head
		of the page.

	* If you enter the text [TimeNow] into a WikiPage, it is substituted with the
		current date and time in GMT. Once saved, the text is actually
		replaced in the document, so subsequent edits will see a string
		representing the time, and *not* the string [TimeNow].

	* The text [Search] in a WikiPage is replaced with a small search form,
		that when triggered will search the entire set of WikiPages for
		matches. The pattern entered into the form is to be a regular
		expression.

NOTE: All of this formatting can be escaped, by making use of the [-
... -] "HTML escape" brackets. Any text entered in a WikiPage enclosed
in a pair of '[-' and '-]' will be interpreted as HTML and inserted
directly into the resulting HTML display of the page without any
alteration.

If you want to escape the escapes, you can use text like:
	[-[--]		=> expands to =>	[-
	[--]-]		=> expands to =>	-]

4. A note about security

THIS SCRIPT HAS NOT BEEN ANALYZED FOR SECURITY FLAWS at all. As far as
I know there are no serious holes in it - the only real thing anyone
can do is destroy a carefully built Wiki database (you backed it up,
though, right?) - but then I HAVEN'T THOUGHT TOO MUCH ABOUT IT. If you
have a problem with this, you're basically on your own, I'm afraid -
be sure to read and fully understand the section about the lack of
WARRANTY at the top of this file and in the GNU GPL.

On the other hand, I'd really love to hear about it if anyone casts a
security-minded eye over it - are there any blatant holes I've missed?
Please let me know what you discover!

NOTE: A recent addition has been cookie-based user login. This scheme
is more-or-less completely insecure. It raises the barrier slightly,
but could be substantially improved. Comments and improvements
welcome! (It's best used at the moment as a means of distinguishing
various users while still permitting anonymous viewing/editing.)

5. Contributing changes back

If you modify this program so it does something funky, new, and/or
exciting, I'd really like to hear about it. If I ever release another
version, your new feature could well become part of it :-)

You can contact me at the email address given at the top of this
message. I hope you enjoy this program.

	- Tony Garnock-Jones
	  November 1999
