Adding a recaptcha to the Factor pastebin
Thursday, March 11, 2010
Lately the Factor pastebin has been flooded with penis enlargement spam. The pastebin had its own very weak captcha that worked well enough for a while: there was a form field that was required to be left blank, and if it was not blank validation would fail. However, spammers have started working around it so we needed something stronger. I decided to solve the problem once and for all by integrating Doug Coleman’s furnace.recaptcha vocabulary into the pastebin. Doing this was surprisingly easy.
First, I changed the USING:
form in
webapps.pastebin
to reference the furnace.recaptcha
vocabulary:
USING: namespaces assocs sorting sequences kernel accessors
hashtables db.types db.tuples db combinators
calendar calendar.format math.parser math.order syndication urls
xml.writer xmode.catalog validators
html.forms
html.components
html.templates.chloe
http.server
http.server.dispatchers
http.server.redirection
http.server.responses
furnace
furnace.actions
furnace.redirection
furnace.auth
furnace.auth.login
furnace.boilerplate
furnace.recaptcha
furnace.syndication
furnace.conversations ;
Next, I changed the validate-entity
word. This word is used to
validate a form submission when adding a new paste or a new annotation.
Instead of validating a captcha using the old simple scheme, it now
calls validate-recaptcha
:
: validate-entity ( -- )
{
{ "summary" [ v-one-line ] }
{ "author" [ v-one-line ] }
{ "mode" [ v-mode ] }
{ "contents" [ v-required ] }
} validate-params
validate-recaptcha ;
Finally, I edited the
new-paste.xml
and
new-annotation.xml
templates to add a recaptcha component inside the t:form
tag:
<tr><td colspan="2"><t:recaptcha /></td></tr>
The implementation of the
furnace.recaptcha
vocabulary is very straightforward and takes advantage of several
features of Factor’s web framework. It uses
http.client
to communicate with the recaptcha server, and
furnace.conversations
to pass the validation error between requests. Finally, it uses the
CHLOE:
parsing word to define the t:recaptcha
tag for use in
templates:
CHLOE: recaptcha drop [ render-recaptcha ] [xml-code] ;