Hello and welcome to my new WordPress-powered site!

Rather than move my venerable Blosxom site here I am starting again with WordPress. Don’t get me wrong, I think Blosxom’s a fantastic tool and using it to run my site was both great fun and a valuable learning experience, but I really need something a bit more sophisticated now that doesn’t require quite the level of tinkering and hacking that Blosxom did.

My plan is to move all the old content into the new WordPress installation, hopefully preserving the URL structure either directly or by using some mod_rewrite hackery. I’m not sure when I’ll get the time to do this so in the meantime if anyone wants any of the old content (e.g. any of the Blosxom plugins I wrote or modified) please drop me a line at sam at sgp.me.uk and I’ll send you copies.

To be honest I’m not sure whether I’ll get back into blogging, but as this site has been up for six years I can’t imagine abandoning it completely. I often think that I should write more and that I should get over some of the inhibitions I have about blogging longer and more thoughtful stuff, but a big reason at the moment is lack of time – a full-time job that’s not particularly amenable to personal blogging plus two small children keep my life pretty full!

Basic version control with wikieditish

At the St Werburghs Community Centre, we use Blosxom to power our website. As the other staff needed to be able to update and add content quickly and with the minimum of fuss, I combined the wikieditish plugin with TinyMCE and a couple of other scripts to create a simple rich-text web interface to the site.

During testing and the initial setup period, it became apparent that having the ability to roll an entry back to its original state after a dodgy edit would be a useful feature, so I added a few lines of code to wikieditish that supports a very simple kind of version control: every time a change is made, the plugin saves a copy of the current state of the post into a backup file. This file is over-written each time so you can only revert to the last saved version, but this allowed staff some scope for experimentation with the knowledge that they could undo any serious mistakes quickly.

I thought that I’d make this version of the plugin available here in case any other blosxom users might find it useful, so download wikieditishvc.zip, which contains the plugin and some basic flavour templates. I have not renamed the plugin itself, it is still simply named wikieditish, but I’ve added a bit of extra documentation and updated the version number to differentiate it. The version control behaviour is all optional and is off by default.

Atom 1.0 Support for Blosxom

Here is an updated atomfeed plugin that supports Atom 1.0: download atomfeed.

Changes since the last beta version:

  • Moved variable configuration to head sub
  • Added simple entity-unescaping in generation of the element
  • Adjusted the xml:base attribute to reflect $id_domain rather than $blosxom::url, and added the attribute at feed-level as well as for each entry

This plugin offers basic support for most of the specification, which should be enough for the vast majority of users. Not currently supported are the and elements. has been excluded as it seems an element more aimed at those publishing feeds aggregated from other feeds. probably could be supported, but would have been a bit of a kludge without the use of metadata – so anyone who needs this element could use the meta plugin and a custom template.

Of course, Atom is designed to be flexible and extensible and there are already people out there imagining losts of uses for the format – see this article at IBM Developer Works for some ideas (via Tim Bray). This plugin can never hope to cater for all possible uses, but it should be enough to provide the bare bones that others can build upon to meet their own needs.

The plugin comes with flavour templates and extensive documentation, including a list of all the variables it makes available for use in templates, notes on compatibility issues with other plugins and suchlike. I’ve extracted some of the major points below, but see the plugin itself for more complete notes.

  • The plugin has a large number of configurable variables and generates an even larger number of template variables. However, it is designed to be usable with only minimal configuration: set the variables $default_author and $feed_yr, drop the plugin into your $plugins_dir and off you go.
  • The plugin is intended to work with nothing but blosxom.cgi and a standard perl installation, but it will perform better if the XML::Parser and LWP modules are installed, and if you are using a plugin like entries_cache that stores the creation times of your posts.
  • If you are modifying the content of your entries using other plugins, particularly any that escape characters or add markup (like some of these), you should have them run before the atomfeed plugin. You want atomfeed to get each post in the state that it would be sent to a normal web browser.
  • Similarly, if you intend to use the config or prefs plugins to modify any of the variables generated by the plugin, they will need to run before it.
  • Podcasters: enclosures are supported. You need to link to your enclosure in the body of your weblog post, and provide the anchor tag with a rel attrubute of “enclosure”. For example: <a rel="enclosure" href="http://example.com/podcasts/august-05.mp3">Podcast for 5th August</a>. If you have the LWP module and you change the $use_full_enclosures configurable variable to “1”, the plugin will also include data on the length and content type of the enclosure (this is recommended as good practice).
  • You can include “related” and “via” links using a similar method – just ensure the anchor tags have an appropriate rel attribute for these links to be included in your feed as corresponding s.

Please post any feedback you have to the blosxom mailing list, maybe as a follow-up to this post.

Beta support for Atom 1.0 in blosxom

atomfeed released!

It’s finished! See this post for more information, docs and download.


Download: atomfeed-beta-6

This is now pretty much ready for release: just a last check for suggestions and bugs. It now supports the whole spec apart from , which seems aimed at aggregators rather than bloggers, and , which could easily be implemented if desired using the meta plugin.


  • Moved from using class to rel attributes in HTML anchors to identify enclosure/via/related links to include in the feed. Just use the appropriate rel value – there’s no need to include the “atom-” prefix any longer.
  • Support for
    . This uses a technique similar to that used by the foreshortened plugin. It is excluded from the default templates in favour of a full-text element. I’ve temporarily placed the

    inside a comment in my feed if you’re interested in how it looks.
  • and are now available as user-configurable variables.
  • Documentation is now included in the plugin – use perldoc or read directly.
  • Includes support for a stylesheet, like in the original 0.3 version. Excluded by default. You can also specify the MIME tpye of the stylesheet.

As before, comments to the mailing list please.


Download atomfeed-beta-5

Changes in this version: support for rel attributes in elements, including enclosures (based on Dave Slusher‘s and Keith Irwin‘s enclosures plugin for RSS 2).

  • enlcosure: In the body of your post, link to a file you would like to appear in your atom feed as an enclosure. Make sure this link has a class attribute of “atom-enclosure”. For extra points: if you have access to the LWP perl module, set the configurable variable $use_full_enclosures to “1” and atomfeed will attempt to find the content-type and length of your enclosure. (Test: This little audio file should appear in my post as an enclosure. The code for this link looks like this: This little audio file)
  • via: To include a link from your post in your atom feed as , give it a class attribute of “atom-via”
  • related: similar to via, simply give a link a class attribute of “atom-related” for it to appear in your atom feed as an appropriate element.

Note: using the class attribute to identify these links may change in future versions.


Download atomfeed-beta-4

Changes in this version (also posted to mailing list) based on suggestions from Stu MacKenzie:

  • typo corrected
  • XML::Parser is now a require rather than a use – those who don’t have this module can now use the plugin with the consequence that their entries will never be labelled as xhtml, only text or html, regardless of validity/well-formedness.
  • Regular expression for guessing text vs. mark-up is now: m!! This should hopefully catch pretty much anything that resembles mark-up.
  • The check in the start() sub for preloaded templates is now or‘d with the call to _load_templates. I’m not even sure if this check is necessary, as it doesn’t appear possible for any user-defined templates to have been loaded by this stage anyway, unless someone else knows better?

Major Revision: atomfeed-beta-3

Since posting this entry, I have made a number of changes to the plugin. It now contains support for the following additional elements:

  • and for

Also, it checks $blog_title, $blog_description and each post’s $title for markup by looking for left-side angle brackets anything matching the regular expression /<[a-zA-Z0-9]+>/. If it finds a match, it assumes that the variable contains markup and parses it as such, labelling it either html or xhtml depending on well-formedness.

You can download the new version here. The link below continues to point to the original version. Documentation is still not finished, but the code is commented. I’m particularly interested in feedback on the _parse_markup subroutine.

Original post

I’ve updated the atomfeed plugin for Blosxom to emit a basic Atom 1.0 feed. It’s in beta; you can download it here. I’m running the plugin, so if you like you can see it in action by checking my Atom feed; the feed’s been checked with feedvalidator.org‘s new Atom 1.0 support. Here are the notes I posted to the blosxom mailing list:

The feed is very basic: only the required elements along with a feed-level pointing at the feed, a based on $blog_description, a element (updated 2005-07-21, but it was always in there), and each has a as well as an element.

I have not yet updated documentation in the plugin. I’m making it available so that anyone interested can take a look and make suggestions before I start looking at adding more support for optional elements and doing some other bugfixes. When I’m happy with it I’ll re-write the docs, remove the BETA flag and post some instructions on my site. Until then, use these notes as guidance if you want to use or test the plugin:

  • $feed_yr is now a configurable variable that MUST to be set to the year you want to see in your feed level element. This should be set once and then never changed.
  • is derived from the timestamp in %blosxom::files, and (entry level) is derived from a stat()->mtime on the actual file. For these two elements to work as intended, you really should be running entries_cache or similar, otherwise they will be the same.
  • entry level ‘s are derived from %blosxom::files. Again, for maximum conformance – to guarantee the tags never change – is currently to use entries_cache or similar.
  • I decided not to worry about sniffing for plaintext entries as it seems to me that most blosxom users will have markup in their entries, so the mechanism for determining the type of has remained bascially the same (UPDATED – see below).
  • I am still assuming that $blog_title and $blog_description contain only plaintext and no mark-up whatsoever.
  • the feed-level element must appear before the s, so I’ve taken the method used in the rss10 plugin to insert it in $blosxom::output in the foot subroutine using a placeholder.

Update 2005-07-21 (1)

I’ve removed the code that conditionally placed some HTML content into a CDATA section. ALL content identfied as HTML will now be escaped.


Please direct comments to the blosxom mailing list.

Technical Notes

This website is constructed with the help of Apache, Blosxom (with several plugins), a bit of javascript and Web Standards. It is very much a work in progress, but then point me to a weblog that isn’t. Here are some notes on the techniques used here.

Apache tricks

I use a couple of simple .htaccess tricks to help create more human-friendly URLs. Most of these hacks use mod_rewrite, and none are particularly esoteric. The comments in the following extract from the site-wide .htaccess should explain what’s going on:

# This little trick allows me to rename the blosxom
# script from the cumbersome script.cgi format to
# something simpler (in this case, 'sam'):

  SetHandler cgi-script

# Rewrite rules:
RewriteEngine On

# As I prefer to use just 'sgp.me.uk' as the base
# domain, this rule redirects requests for
# 'www.sgp.me.uk'.  This both allows the use of the
# 'www.' prefix while hopefully encouraging people
# not to use it by visibly redirecting rather than
# simply rewriting.
RewriteCond %{HTTP_HOST} ^www\.sgp\.me\.uk$ [NC]
RewriteRule ^(.*)$ http://sgp.me.uk/$1 [R=301,L]

# Pages devoted to baby photos have been integrated
# into my blog. This rule preserves the old
# hierarchy and provides me with a really simple
# URL to point family to for these photos:
RewriteRule ^uma(.*)$ /sam/uma$1

# I liked the idea of losing the required
# 'index.$flavour' suffixes for rss feeds:
RewriteRule ^sam(.*)/rss$ /sam$1/index.rss
RewriteRule ^sam(.*)/rdf$ /sam$1/index.rdf

Blosxom configuration

The site uses Blosxom 2.0. The script has been slightly modified to remove the code used to escape HTML when outputting RSS (see this post for more information on this and a patch). I also use the following plugins, some of which I wrote myself:


The website is designed to be accessible in all of the major browsers (having said that, it does render best in Firefox because of -moz-border-radius). It uses vaguely semantic HTML for structure and CSS for layout. The HTML template is written to validate against the XHTML 1.0 Strict Doctype, and the xhtmlmime plugin means that non-well-formed entries quickly get picked up. The RSS feeds are all validated against the Feed Validator from time to time.

To do

  • application/xhtml+xmldone!
  • Sort out some better page titlesdone!
  • Comments/Writebacks
  • Tags (think del.icio.us). Probably implement this using a hacked version of the meta plugin
  • Atom feed, once the spec is finaliseddone!
  • More stuff as I think of it
  • Oh yeah, actually post some real content

Blosxom and application/xhtml+xml

Since this website is written to the XHTML 1.0 Strict Doctype, I thought it would be nice to serve it with the correct MIME type to conforming user-agents. I remembered hearing about a plugin called xhtml that would do this, but after a cursory search came up with nothing I decided that I’d just write my own.

So here’s xhtmlmime. It uses CGI.pm to sniff the Accept: HTTP header from the user-agent and then serves blosxom with the preferred MIME type. There are two variables that need to be set:

  • $flavours needs to be set to a list of flavours upon which to act. This defaults to empty, and the plugin will exit quietly until you set it.
  • $charset should be set to the character encoding used on your weblog. This defaults to utf-8.

You can force the plugin to send the application/xhtml+xml MIME type by specifying a URL parameter of mime=xhtml. Setting mime to anything else will result in the user getting text/html.

Update 2005-07-21

The plugin now exports a variable – $xhtmlmime::meta_http_equiv – for use in your head templates. If you use the http-equiv element, set it as follows:

And the plugin will ensure that it is set correctly.


As noted by Bill Lovett, serving as application/xhtml+xml raises a couple of issues. The most important one is that this will lead to very strict interpretation of your pages by the web browser, so unless your pages are well-formed – contain no mistakes in the markup – your visitors will just get error messages! Bad plugin!

So, before using this plugin you need to be confident that this is the case, and that you have some method for ensuring that only well-formed, valid markup ends up on your pages.


If you have any feedback, either contact me directly or post a message to the blosxom mailing list.

Hide plugin and date-based URLs

The hide plugin allows you to conceal certain posts and/or categories from the standard blosxom index pages – this works for either path or date based URLs. A side effect of this is that if you are using date-based links like me – http://example.com/YYYY/MM/DD/filename – then the posts won’t show up when you visit their permalinks – they’ll only display when referenced with a URL like http://example.com/path/to/filename.flavour.

A solution is to add quick test to the start subroutine in the hide plugin that checks to see whether blosxom knows about any date-based path information:

sub start {
  $blosxom::path_info_yr and return 0;

As I don’t want posts in about/ to display in the monthly archives, I used the $path_info_da variable, but you could just as easily use $path_info_yr or $path_info_mo instead to allow the posts to display on less specific date-based index pages.

Stripping out <script> tags from RSS feeds

It’s good practice not to include <script> tags inside your RSS feeds, and feedvalidator.org will react if you include them, so here’s a plugin that will do this for you.

By default, the plugin will attempt to strip <script> tags from the $body of your posts when $blosxom::flavour equals “rss”. This is configurable, of course.

Note that the plugin is not designed as a security precaution and so the regular expression used to try and find the tags isn’t particularly sophisticated. It is case-insensitive but expects to find the actual tags themselves to be unbroken by white space or line breaks, however the contents of the tags can be arranged in any way you please.

Auto escaping HTML in RSS with blosxom

Out of the box, blosxom comes with simple HTML and RSS formats built in. In order to get the RSS 0.91 feed set-up correctly, blosxom escapes HTML tags during the story generation phase where is finds an XML content-type (specifically: $content_type =~ m{\Wxml$}).

This feature is fine until you start experimenting with your RSS feeds when it can become a bug. For example, if you decide to provide the full text for each story in a feed enclosed in a CDATA section, you don’t want this escaping to take place. So I recommend that you move the escaping section from blosxom itself and place it into a plugin where you can then call it if you need it.

The escaping code is lines 378-384 in the standard blosxom 2.0 script. Just for fun I’ve made a patch, but it’s probably simpler to just open a text editor and do it by hand. Here’s a simple plugin that allows you to control whether or not the code is called during the story generation phase.

Untainting blosxom

If you want to run Blosxom in taint mode (using the -T switch), you’ll hit some problems with 2.0 as it comes out of the box. Joe Landman posted a patch dealing with one issue on the mailing list over the weekend, but if you’re using any plugins then you’ll immediately encounter another problem when blosxom does a readdir() on your $plugins_dir. Here’s a patch that solves both these issues.