Captcha::reCAPTCHA Is Fun And Easy

awwaiid on 2008-03-06T05:40:49

I just wrote a reCAPTCHA Extension for Oddmuse. I started out with the current version of my QuestionAsker Extension, threw in just a touch of Captcha::reCAPTCHA, and voi-la! Easy as pie.

If you are ever in the Captcha business, definitely check out Captcha::reCAPTCHA. It was extremely straightforward.

I very much enjoy writing Oddmuse modules. Oddmuse itself is this 4000-line beastie in a single file. Extensions, at least the interesting ones, build on the core by replacing internal functions with custom versions. So to add this captcha technology, for example, I overwrite the doEdit function with one of my own, calling the old doEdit function and then manipulating the generated HTML.

It's your standard sick and wonderful form of Aspect-Oriented aka Self-Modifying programming that makes me happy.

You can see the result over on the Continuity Wiki, just edit a page. Feel free to add some useful content while you're at it :)


Hey, I know that name!

scrottie on 2008-03-07T23:05:07

Hello awwaiid!

I hope this means you'll continue to share ideas more, in the spirit of those PM presentations of yore.

By the way, here's my ReCAPTCHA client implementation for TinyWiki (just fixed a problem with this the other day, where their server was no longer defaulting to that Content-Type):

sub captcha {   # optional -- uses recaptcha.net's free service; this is called from RetroWikiHeader when $actioneq 'save'; the privatekey file emits the private key (without trailing newline) when run and has its execut bits set but not read bits
    socket my $s, 2, 1, 6 or die $!; connect $s, "\x00\x02\x00\x50\x40\x22\xfb\x98\x00\x00\x00\x00\x00\x00\x00\x00" or die $!; # little endian
    $recaptcha_response_field =~ s/ /\+/g; my $postdata = join '', 'privatekey=', `/home/httpd/privatekey`, '&remoteip=', $rip, '&challenge=', $recaptcha_challenge_field, '&response=', $recaptcha_response_field;
    syswrite $s, "POST /verify HTTP/1.0\r\nContent-type: application/x-www-form-urlencoded\r\nContent-Length: " . length($postdata) . "\r\n\r\n" . $postdata; return join '', <$s>; }
Of course, you'll have to re-pre-compute the sockaddr struct for big endian machines. (Or is it the other way around? I can never keep those straight.)

The template for editing includes a call to the recaptcha thingie, and a call to this is inserted before save.

-scott

Re:Hey, I know that name!

awwaiid on 2008-03-08T00:13:30

Yeah, one day I realized that I have a bigger audience of people who might actually care here than on my own site. I'll probably cross-post some stuff.

Interesting implementation. It shows how simple the protocol is. But I think I'll just stick with what I have (call it the lazy way, if you like) :)

Hmm... maybe TinyWiky should have a mechanism for page-scripts to use CPAN modules... make them automatically cached or something...

awwaiid.use.perl

scrottie on 2008-03-08T01:44:45

Yeah, wouldn't suggest my actual implementation to anyone. Telling people to swap bytes around depending on the CPU in their server doesn't belong in install instructions anywhere ;)

CPAN modules would be interesting and do-able but it would break the 100 line limit I set for myself. Maybe in a larger version. The current protection model, banishing most ops with 'use ops', just wouldn't work. You couldn't do the first step. I think buu has his bot forking then chrooting itself and setting ulimits and a bunch of other stuff, doing computations in that sandbox, and then returing the results over the one filehandle it has open to the outside world. Entire user scripts could be run that way, chroot'ed into a place where modules are installed. Hmm.

-scott