Pyblosxom Recaptcha Plugin

I think maybe the world has moved on from Pyblosxom and, as my logs can attest, spammers seem to have moved on past Recaptcha (even if it is manual).

However, maybe there are some other holdouts like myself who will find this plugin useful. In reality, this will do nothing for stopping spam — for that I am currently having good luck with Akismet. However, I like that in displaying the captcha it costs the spammers presumably something to crack it so they can even attempt to submit the comment.

JavaScript Captcha

Comment spam recently started annoying me, again. Even though it only takes a few clicks to kill, some crappy robot is still taking up my time. Archreality has a nice little JavaScript based Captcha which has the potential to be completely useless as you can see if you click here.

However, I think I've managed to plug it into PyBlosxom and have it be useful. The trick was to make the form submission write a hidden field value in the form with a password after passing the Captcha test.

So, you set up your form like this

<form action="$base_url/$file_path.html" method="post"
name="comments_form" id="comments_form"
onsubmit="try {
           var myValidator = validate_comments_form;
          } catch(e) { return true; }
         return myValidator(this);
         "
>
 ... blah ...
 <input type="hidden" name="secret" value="" />
 ... blah ...
</form>

Then in validate_comments_form do something like

function validate_comments_form(frm) {

  captcha = jcap();
  if ( captcha  ) {
        frm.elements['secret'].value = "you_may_pass";
  }
  return captcha;
}

Then, finally modify comments.py from PyBlosxom to check for this value in cb_prepare.

def cb_prepare(args):
    ... somewhere near the top ...
    #captcha
    if (not form.has_key('secret')):
        return False
    if (form['secret'].value != 'you_may_pass'):
        return False

Now, if the spammer is human they will pass anyway, so we don't have to worry about that. Any bot stupidly submitting the form won't have filled out the secret key, so will get dropped. If the bot somehow interprets the javascript, then it's going to have to have enough logic to somehow parse the code and realise it needs to put in that secret value for anything to happen. If your bot can do that then I'm willing to let your spam remain.

I don't like the fact that these things lock out people without great eyesight. I don't see why a alt tag with "Put the value blah into the next box" wouldn't be sufficient, but currently it writes the image in with javascript so I don't know how that would work with a screen reader. In the todo list...

setting up pyblosxom

i've used blosxom before, and seeing as all the cool people use pyblosxom and I'm much more familiar with python than I am with perl, I've got it all going. I've had a few issues that I've got workarounds happening for.

Firstly is the redirects so that you can't actually see the pyblosxom.cgi file that is doing all the work. My naive first attempt at writing a global catch all rewrite rule was just

RewriteRule ^(.*)$ /pyblosxom.cgi/$1 [L]

But I think the issue with that is that it ends up recursevly matching and you end up with a 500 error. The solution (for me) was to modify this to break out when it matches the cgi file, so my .htaccess looks like

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /pyblosxom.cgi/$1

this seems to work quite well

Then there's the issue of only being able to upload to wienand.org (where technovelty.org lives) via ftp ... since pybloxsom relies on timestamps things were going to get tricky. luckily there is a hardcodedates.py plugin already written by Nathan Bullock. So now I can create entries with a little scripts like

#!/bin/bash
if [ $# -lt 1 ]; then
    echo usage: ./newentry.sh path/to/filename.txt
    exit 1
fi

ENTRY_DATE=`date '+%Y-%m-%d-%H-%M'`

#make directory heirarchy
NEWFILE=$1

if [ ! -d "`dirname $NEWFILE`" ];then
    echo making `dirname $NEWFILE` ...
    mkdir -v  -p `dirname $NEWFILE`
fi

emacs -nw $NEWFILE

echo $ENTRY_DATE $NEWFILE >> timestamps

and upload them with which is a poor-mans ftp rsync.