Handling Anonymous Questions and Answers

This page serves as documentation for the anonymous Q+A scripts/etc. that turn questions and answers into nicely formatted web-pages. Also includes some things on auto-processing replies now.


1. What it generates

The CO631 (2004) Anon Q+A pages are a good example. This is one of the `year index' files, that are built for each year. Questions can have optional keywords associated with them, that are used to build a keyword index. CO631 has several years worth of Q+A's so makes a pretty good example. Each keyword also gets its own page containing all the questions that refer to it, for example the alternation keyword. A top-level index is also generated, linking to the various years.

If desired, the software will also generate an RSS feed containing the last 20 questions. See the CO631 anonymous questions' RSS feed for an example. Best processed using a suitable RSS aggregator (such as rawdog) or other XML processing tools.

Questions (or answers) may also refer to other questions. The script builds `backward links' for these, such that the forward references are visible in older questions. See Question 24 (2003), for example.

2. What it eats

The individual questions and answers are organised into pairs of files in `year' sub-directories. The naming of these files is quite important, e.g. `2003/Q1' and `2003/A1' -- the script will keep going until it can't find any more (starting from 1). To prevent a question being displayed, change the name of its answer file to something else, e.g. `2003/x-A1'.

The question and answer files should be XHTML (1.0). Only minimal formatting required, though. A simple question file is:

<!-- keywords: foo bar -->
<p>
    How do I make my foo bar ?
</p>

This has two keywords, `foo' and `bar'. Keywords may contain dashes and periods. The answer to this question is:

<p>
    Poke it with a stick.  See also @2003:1@.
</p>

This answer refers to question 1 in the year 2003 (whatever that might be). The script will turn this into a more practical description (and link).

Sometimes, it's useful to be able to link to keywords from the text. The answer referred to in the above example does this, for example:

<p>
    Try asking the shopkeeper, north of the village.  You can trade silver
    for various items, including sticks.  The shopkeeper may also try
    and sell you a @foo@.
</p>

So, within the text of a question or answer, ``@yyyy:qq@'' links to question/answer qq in the year yyyy; and ``@keyword@'' links to the entry for keyword in the keyword index. Such keyword links only link to the keyword index -- they are not used to create it.

3. Software

The whole lot comes in a tarball. Unpack this in a suitable location then do some editing.

First, edit the `AnonConfig.sh' file. Some of the more important entries are (by default):

UMASK=002
FCMODE=0664
SOURCEDIRS="2005 2004 2003"
THISYEAR=2005
QPERPAGE=20

The `UMASK' and `FCMODE' variables define the mask and mode for generated files. By default this generates group-writable files (which is probably what you want).

The `SOURCEDIRS' variable gives a list of source directories that contain question and answer files; these should just be simple 4-digit year values, not anything else (e.g. a full path). The software stores years internally as integers, so ... The `THISYEAR' variable identifies the current year. The current year has questions output in most-recent first order. Other years have questions ordered earliest first. The `QPERPAGE' variable defines how many questions will be displayed per page.

Other entries in the file define various other (less interesting) things, such as the header/footer files, etc. and some settings for RSS generation.

Once `AnonConfig.sh' is sorted, you should edit the various header and footer files to suit the particular course. The ones supplied are based on the CO631 anonymous Q+A's (stripped down a bit).

3.1. Scripts/Building

The generation process is kick-started by running `makeanon.sh'. This should be run from the directory where it resides -- it expects everything else to be around too. The actual generator is `makeanon', compiled from `makeanon.c'. This compiles fine on Linux and Solaris, and ought to work on other UNIX/POSIX systems too. `makeanon.sh' will compile/re-compile `makeanon.c' as necessary.

The `makeanon.sh' script should be run after adding or editing questions/answers. The program that generates the various output files is not as efficient as it could be, but runs in reasonable time (seconds). Everything is re-built each time the script is run.

So, there it all is; enjoy! :-). The default questions and answers (examples!) can be accessed via the top-level index.

3.2. Back-End Stuff

The back-end processing is handled by a Perl CGI script, originally by David Barnes, but hacked quite a bit since. The example "anonymous question" pages point to the right CGI script by default (in my CGI area on the web-server). This is (currently) setup with:

<form action="http://www.cs.kent.ac.uk/people/staff/frmb/cgi-bin/anon.pl" method="post">

The body of the form should contain at least a text-area with the name "Question", "Submit" and "Cancel" buttons, as well as the following hidden fields:

<input type="hidden" name="Recipients" value="f.r.m.barnes" />
<input type="hidden" name="PageTitle" value="example anonymous question" />
<input type="hidden" name="PagePathBase" value="/web/cs/docs/people/staff/frmb/anon-test" />
<input type="hidden" name="CourseCode" value="AB123" />

The first, "Recipients" should be a space separated list of recipients email addresses. Only "approved" recipients will be emailed (where the approved list is defined in the CGI script). "PageTitle" is a descriptive line that appears in the outgoing email. Third, "PagePathBase" tells the CGI script where to find the header/footer templates when producing the reply page (these files must have the names "tmpl-header.html" and "tmpl-footer.html"). Finally, "CourseCode" sets the course-code, as used in outgoing email subject lines. The course-code is also used in automatic processing of answers (below), and must conform to the accepted style (e.g. "AB123", "COxyz", "CO632", etc.).

When submitted, the question will be emailed to recipients, who can then copy the question, with their response, into Q+A files, and rebuild the pages (above).

4. Auto Processing

To aid in the fast(er) processing of queries, the submission system now supports a kind of email reply. To enable, set the additional hidden fields:

<input type="hidden" name="PathAnsTree" value="/web/cs/docs/people/staff/frmb/anonqa" />
<input type="hidden" name="PathYear" value="2005" />
<input type="hidden" name="PGPMail" value="yes" />

"PathAnsTree" defines the path to where the questions/answers are stored; "PathYear" specifies the current year (which is appended to "PathAnsTree" to get the directory where the actual Q+A files live). The setting in "PGPMail" determines how the questions will be answered. If this is yes, an email is emitted, PGP signed, described here. There's also a mechanism for web-based replies, if the "PGPMail" setting is set to "no" (or not set at all).

When a question is submitted with these, the outgoing email includes this information, along with the question, in a PGP signed message. A copy of the original question is also stored in a "holding" directory (defined by the CGI script). To provide an answer, one of the recipients replies to the mail, including the body of the original message prefixed with "". Thus far, I've used NMH, mutt and pine successfully (you may want to filter these emails off to a different mailbox specifically for dealing with them in a compatible mailer).

The "Reply-To: " field of these emails is set to me (Fred), where appropriate procmail filtering exists to catch these and process them. There are a couple of implications from this:

If the received reply looks good (has a good signature and whose question reference matches one of the ones held), the response is taken out of the email (plain-text before or after the ""'d PGP body), combined with the held question and placed in the target directory (selected with "PathAnsTree" and "PathYear"). Note, however, that the Q+A pages are not automatically rebuilt, you must still do this yourself -- it provides a good opportunity to check the generated Q/A for samity before publishing.

If you don't reply to the automated message, you can still create the Q+A files in the normal way -- a "holding" message will linger, cleaned up after it's aged a while. To set keywords from an automated reply, include a line with space separated keywords that looks something like "Keywords: foo bar".

The web-reply mechanism is much simpler. When a question is submitted, you'll get an email containing a URL to visit to answer the question. This is actually the same for all courses using this system (although you can filter to only show questions for a particular course). The web-reply system is available to authenticated users only, at http://www.cs.kent.ac.uk/people/staff/frmb/cgi-bin/secure-only/anon-pending.pl.

4.1. Auto Filtering

To deal with anonymous questions outside of your normal mail-traffic, perhaps to use a mailer that can reply in the Right Way, use filtering. I currently use procmail to do mail filtering, although not for anonymous questions; but if you wanted to re-direct anonymous questions to a "anonqabox" file in your home-directory; in procmail:

:0
* ^Subject: [A-Z][A-Z][0-9a-z]+ Anonymous Question \[IN[0-9]+\.[0-9]+\]
anonqabox

If you don't like procmail, use a normal exim filter (your "~/.forward" file), e.g.:

# Exim filter

if $header_subject matches "^[A-Z][A-Z][0-9a-z]+ Anonymous Question \[IN[0-9]+\.[0-9]+\]"
then
	save "${home}/anonqabox"
	seen finish
endif

To read (and generate replies) I'd suggest mutt or pine, e.g.: "mutt -f ~/anonqabox", "pine -f ~/anonqabox". For more information on exim filtering, see the Systems Group's documentation and the exim filtering documentation.

4.2. Bash-isms For Auto Processing

I've also setup a bash alias for "AQ" (in line with other mail-ish aliases), that launches mutt on the anon-qa mailbox. In my "~/.bash_profile":

PATH="$PATH:$HOME/bin"
MAILPATH="$HOME/.mail:$HOME/anonqabox"
MAILCHECK=30

export PATH

alias AQ='anonqahandle'

And in "~/bin/anonqahandle" (download):

#! /bin/sh

if [ "$TERM" = "xterm" ] || [ "$TERM" = "kterm" ] || [ "$TERM" = "xvt-color" ]; then
	TERM=xterm-color
	export TERM
fi

exec mutt -f $HOME/anonqabox

So, when new mail arrives in the anonymous mailbox, bash tells me (set in "MAILPATH"), and to deal with them run "AQ". Replies get processed resulting in new question/answer files.


Last modified 5th September 2005 by Fred Barnes.