Monthly Archives: April 2006

A More Accessible Alternative to Graphical Capchas

Reading a blog post on comment spam has minded me to describe a solution that I have worked on.

The ability to send postcards from web sites would be nice, if it weren’t for the abuse that such resources get from spammers.

Unbeknown to most who are using graphical “captchas” (a form of Turing Test) in their web content, to prevent automated submissions, captchas are also a good way of saying “we don’t give a damn about all you people with a vision impairment, who are dyslexic or who use non-graphical browsers”.

To summarise the above, spammers suck, but so do graphical captchas. So, what is the solution? Is there a truly accessible way of determining whether you have a bona fide visitor, or a naughty robot? The WorldWide Web Consortium (W3C) has this to say on the issue.

I have a solution, which I applied to a client’s postcard page. It is not perfect, as it could present problems to people with cognitive disabilties. However, put in a context where people with cognitive disabilities are not likely to be in the first place, it has the makings of an accessible solution. Feel free to use it, but code provided in good faith without warranty or implied fitness for purpose, blah, blah, legalistic blah.

My solution, written in Perl, asks two random questions from a list. Both have to be answered correctly for the submission to be accepted. This should be easy to adapt to PHP for those who don’t follow the teachings of St Larry of Wall.

Setting up the Questions


my ($q1,$a1,$qtu1)=randq();
my ($q2,$a2,$qtu2)=randq();

…where $q1, $q2 are the questions that will be asked, $a1,$a2 are the random (possibly wrong, possibly right) answers to the question posed and $qtu1,$qtu2 are “question to use” – the numbers of the random question/answer sets themselves.

In our Form

I have removed most of the <div>s from the following code example, to improve legibility.


<fieldset><legend>Anti-Spam</legend>
<div>
To prevent our postcards from being used for 'spam' by naughty robots,
please answer the following questions. As questions are selected at
random, you may be asked the same one twice.
</div>
<label for="q1">$q1</label>
<select name="q1" id="q1">$a1</select>
</code><code>
<label for="q2">$q2</label>
<select name="q2" id="q2">$a2</select>

<input type="hidden" name="qtu1" value="$qtu1" />
<input type="hidden" name="qtu2" value="$qtu2" />

Checking our Answers

In the example below, we are using Perl’s standard CGI module. $q is our CGI instance. PHP people, this is like $_GET[‘my_variable’]. (or POST).


sub checkqs
{
my $chk1=randq($q->param('qtu1'),$q->param('q1'));
my $chk2=randq($q->param('qtu2'),$q->param('q2'));
unless ($chk1 && $chk2)
{
# page header stuff
start_page();
print "<p>Sorry - you did not answer the questions correctly. You can try again by selecting 'postcards' from the menu.</p>";
# page footer stuff
end_page();
}
}

The Random Question Subroutine


sub randq
{
my ($q,$a);
my @seq=(
[0,2,4,1,3],
[1,2,0,3,4],
[1,0,4,2,3],
[0,2,1,3,4],
[1,0,2,3,4],
[3,4,2,1,0],
[1,2,4,3,0],
[1,0,2,3,4],
[1,2,3,0,4],
[2,0,3,1,4],
);
my %questions;
$questions{0}{q}='Who is the president of the USA?';
$questions{0}{a}[0]='George W. Bush';
$questions{0}{a}[1]='Bill Clinton';
$questions{0}{a}[2]='Ronald Reagan';
$questions{0}{a}[3]='Richard M. Nixon';
$questions{0}{a}[4]='Jimmy Carter';
$questions{1}{q}='Who is Batman's sidekick?';
$questions{1}{a}[0]='Robin';
$questions{1}{a}[1]='The Joker';
$questions{1}{a}[2]='Spiderman';
$questions{1}{a}[3]='Batmobile';
$questions{1}{a}[4]='George W. Bush';
$questions{2}{q}='What is 2 plus 2?';
$questions{2}{a}[0]='4';
$questions{2}{a}[1]='2';
$questions{2}{a}[2]='22';
$questions{2}{a}[3]='0';
$questions{2}{a}[4]='1';
$questions{3}{q}='What day comes after Tuesday?';
$questions{3}{a}[0]='Wednesday';
$questions{3}{a}[1]='Monday';
$questions{3}{a}[2]='Thursday';
$questions{3}{a}[3]='Tuesday';
$questions{3}{a}[4]='Friday';
$questions{4}{q}='What is the capital of France?';
$questions{4}{a}[0]='Paris';
$questions{4}{a}[1]='New York';
$questions{4}{a}[2]='Lyons';
$questions{4}{a}[3]='Jacques Chirac';
$questions{4}{a}[4]='Tours';
$questions{5}{q}='Where does the sun rise?';
$questions{5}{a}[0]='In the East';
$questions{5}{a}[1]='At night';
$questions{5}{a}[2]='In the South';
$questions{5}{a}[3]='In the West';
$questions{5}{a}[4]='In the North';
$questions{6}{q}='The Great Pyramid may be found in...';
$questions{6}{a}[0]='Egypt';
$questions{6}{a}[1]='Rocks';
$questions{6}{a}[2]='Japan';
$questions{6}{a}[3]='Texas';
$questions{6}{a}[4]='North Pole';
$questions{7}{q}='Who is the president of the USA?';
$questions{7}{a}[0]='George W. Bush';
$questions{7}{a}[1]='Bill Clinton';
$questions{7}{a}[2]='Ronald Reagan';
$questions{7}{a}[3]='Richard M. Nixon';
$questions{7}{a}[4]='Jimmy Carter';
$questions{8}{q}='Thorogoods Apple Wines sells...';
$questions{8}{a}[0]='Fine apple wines and vintage ciders';
$questions{8}{a}[1]='Sheep';
$questions{8}{a}[2]='Beer';
$questions{8}{a}[3]='Pasta';
$questions{8}{a}[4]='Whisky';
$questions{9}{q}='Cider is made from...';
$questions{9}{a}[0]='Apples';
$questions{9}{a}[1]='Beer';
$questions{9}{a}[2]='Cheese';
$questions{9}{a}[3]='Potatoes';
$questions{9}{a}[4]='Chicken';
$questions{10}{q}='Apples are...';
$questions{10}{a}[0]='Fruit';
$questions{10}{a}[1]='Spiders';
$questions{10}{a}[2]='Cheese';
$questions{10}{a}[3]='A type of fish';
$questions{10}{a}[4]='Chickens';
$questions{11}{q}='Sharks live in...';
$questions{11}{a}[0]='The Sea';
$questions{11}{a}[1]='Apricots';
$questions{11}{a}[2]='Greenhouses';
$questions{11}{a}[3]='Cider bottles';
$questions{11}{a}[4]='Chickens';
# Do this if there are no arguments -
# in other words, we need new questions
unless ($_[0])
{
my $qtouse=int(rand 10);
$q=$questions{$qtouse}{q};
my $set=int(rand 9);
my @ord=@{$seq[$set]};
for my $row (@ord)
{
$a.="<option>$questions{$qtouse}{a}[$row]</option>";
}
return ($q,$a,$qtouse);
}
else
{
return($questions{$_[0]}{a}[0] eq $_[1] ? 1 : 0);
}
}

Sorry that WordPress has screwed up the code formatting!

Spam, Spam, Spam, Spam!

I am so glad that I have started to use my 'blog again; I had forgotten the joy that deleting all the 'spam' comments can bring!

Checking the WHOIS information, most seem to be coming from the Ukraine at present; Russian Mafia at work?

The balance of products being pushed seems to have changed; the Generic Vagra is still very much in evidence, but there seem to be a lot of mobile phone ring tones on offer as well.

This brings me to something that I cannot understand – why anyone would not only go to the trouble of downloading a ring tone for a mobile phone, but actually pay for that dubious privilege. It's a telephone – you need to know that someone is calling you, not have an uplifting aesthetic experience (a mobile phone ring tune could only be so for someone who has just spent the last decade in a sensory deprivation tank).

Please note – if you should want to comment on this post, the word 'ringtone' is taboo.

See also: De-Spamming WordPress Comments elsewhere on this web log.

Stockland, revisited

Ten years ago, I considered creating a personal web page but could not really think of anything to say about myself; instead, I created a site about Stockland, my local village.

Now living quite some way from Stockland – about 10,100 miles (about 16,000 kilometres) in fact – I have revisited the Stockland web site and have made several “technological” updates.

The most significant update has been made to the Tour; this provides a photographic tour through the village and beyond. The original version, a monstrosity in JavaScript, has been replaced by a far more accessible version, written entirely in Perl, with a MySQL backend. The focus is on the image files – all other parts, titles, adjacent images, are stored as metadata, furthering my aims towards producing fully semantic (web) applications.

Enough of the techo-talk: go have a look at this beautiful village, which will now be in the full bloom of Spring. (In the real world, that is; not on the web site.)

Performancing: 'Blogging from Firefox

No, I don't like the new WordPress editor. This post is being posted using the Performancing plugin for Firefox. Unfortunately, it doesn't do everything that I want it to – for instance, it doesn't have a Post Slug edit facility that I can find. However, not a bad bit of code, at first look. Assuming that it's a XUL app, I'll pull it apart and see what makes it tick.

This has given me an idea – rather than trying to fight the WordPress code, I might just write my own posting programme (in Perl – yippee, no PHP!), leveraging XMLRPC as the Performancing code does.

Update: I've decided that I like the Performancing app sufficiently that I've joined the community. Watch this space.

Mmm – more beer!

The Belgians have a lambic beer called Kriek, containing cherries. It was, therefore, only natural that when I chucked a load of cherries into my beer fermenter, the result would be Kroak.

Kroak nearly went down the drain at bottling time, reeking of aldehydes. However, I bottled it and left it for some months – actually having forgotten that I had made it. When I “found” it again, in the shed, I tasted and was quite smitten with it. It did not take long for the Kroak to disappear.

Today, I brewed up again, but with a revised recipe. As my beers tend to sit in the fermenter longer than the usual homebrew (like up to three months), it will probably be Christmas before I actually get to try today's batch.

Here's what went in it:

  • 2.5kg Munton's light DME
  • 0.5kg Munton's dark DME
  • 870g cherries – pitted and frozen a while back, when they were being sold off cheap.
  • 30g Saaz hop pellets, made into hop tea
  • 5g Saaz hop pellets, straight into the fermenter
  • 20 litres rainwater, filtered to 1 micron (mesh, then charcoal)
  • ½ packet Safale S04 yeast

The original gravity was about 1058.

WordPress 2 Issues

As I had to write patches for WordPress 1.x to address a few issues, I was fully expecting to have to do this all again. One issue, that of identical link names for comments, has been addressed in the new version, so that patch is no longer required. However, the issue right next to it (the Edit link) is still broken and requires the same change, but this time on line 219 of template-functions-links.php.

The above is a fairly minor issue; the new post editor, however is positively ghastly – there's actually a delay in my typing and the text appearing on-screen, like I'm working on a 4800bps connection to a machine in Outer Mongolia. Also, it uses pop-up windows – possibly no worse than the previous JavaScript pop-up dialogues from an accessibility point of view, but slower. My patch for quicktags.js doesn't seem to have any effect (it added a link title dialogue – which has been addressed in the new version – and an abbr dialogue) in the new editor.

As I generally hand-code HTML, I may do nothing about this but, if it really starts to get on my nerves, I will compare the post.php from the old version with the new, make any neccessary changes, and use that.

I may even dump this JavaScript “enhanced” stuff entirely and hand-code in a nice, simple, HTML textarea.

Sufficient to say, I haven't tried accessing this with Lynx yet, otherwise you would probably be able to hear the screams, wherever you are…

UPDATE: The ghastly new editor can be turned off – there's a little check box in the user options (Users->Personal Options->Use the visual rich editor when writing page). The new still lacks of the old, to my mind, so I will probably be using a hacked WP 1.x post.php, when I get the time to do the actual hacking…

Upgrading to WordPress 2

On my third attempt, I have managed to upgrade to WordPress 2. Forget the documented upgrade process – it's broken. In a previous attempt, a forum (sorry, didn't record link) was fully of frustrated users, some with successful hacks, trying to upgrade. Some joker had marked the issue as resolved – which it is not.

Nothing suggested worked for me, so I will share what I have had to do to get my upgrade to work. CAVEAT: This information is provided in good faith but without warranty (blah, blah) – use at your own risk and don't blame me if you trash your 'blog, which you did back up before you started, didn't you?

  • Create a new directory on the same level as your 'wordpress' directory. I called mine wptmp.
  • Untar your WordPress distribution in the temporary directory.
  • (assuming it's called wptmp) mv wordpress ../wp2.
  • Set up wp-config.php in wp2, make sure that your web server will recognise the wp2 directory and proceed to install WordPress anew, USING A NEW DATABASE.
  • Copy over your wp-content and wp-images stuff to wp2.
  • Do a dbdump on your old WordPress database; remove all references to wp_users and wp_usermeta.
  • mysql –user=your_user_name –password=your_user_password –database=your_new_wordpress_database < your_dump_file.sql

After all that, all I had to do was change the /blog/ alias in my Apache config file and it all seems to be fine. So far.