From 77bece5eb07b690ca3cbb387c7c9c93182141d00 Mon Sep 17 00:00:00 2001
From: Sarah Sharp <sarah.a.sharp@intel.com>
Date: Sun, 30 Nov 2008 16:49:20 -0800
Subject: [PATCH] Add reCaptcha spam filtering to comments.py

Use the reCaptcha project to filter spam comments.  See http://recaptcha.net for
more details.

Modify comments.py plugin to import the recaptcha file captcha.py.
reCaptcha only handles ipv4 addresses, so convert ipv6 remote ip addresses into
ipv4 format.

You will need to add the following lines to your pyblosxom config.py file:

py['comment_recaptcha_public']     = "Your reCaptcha Public API key"
py['comment_recaptcha_private']     = "Your reCaptcha Private API key"

You will also need to change your comment-form template for your flavor to
include $recaptcha_html before the submit button.

The reCaptcha python library is provided by the Debian package python-recaptcha.
Make sure to upgrade python-support to 0.8.7 (currently in Debian unstable).

Signed-off-by: Sarah Sharp <sarah.a.sharp@intel.com>
---
 plugins/comments.py |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/plugins/comments.py b/plugins/comments.py
index c7f9dbe..088fb46 100644
--- a/plugins/comments.py
+++ b/plugins/comments.py
@@ -203,6 +203,7 @@ from xml.sax.saxutils import escape
 from Pyblosxom import tools
 from Pyblosxom.entries.base import EntryBase
 from Pyblosxom.renderers import blosxom
+from recaptcha.client import captcha
 
 LATEST_PICKLE_FILE = 'LATEST.cmt'
 
@@ -767,12 +768,16 @@ def cb_prepare(args):
             cdict['email'] = form['email'].value
 
         cdict['ipaddress'] = pyhttp.get('REMOTE_ADDR', '')
+        recaptcha_ipaddr = cdict['ipaddress']
+        if recaptcha_ipaddr.startswith("::ffff:"):
+            recaptcha_ipaddr = recaptcha_ipaddr[7:len(recaptcha_ipaddr)-1]
 
         # record the comment's timestamp, so we can extract it and send it
         # back alone, without the rest of the page, if the request was ajax.
         data['cmt_time'] = float(cdict['pubDate'])
 
         argdict = { "request": request, "comment": cdict }
+	# sas - XXX - probably want to check with recaptcha here.
         reject = tools.run_callback("comment_reject",
                                     argdict,
                                     donefunc=lambda x:x != 0)
@@ -781,9 +786,19 @@ def cb_prepare(args):
             reject_code, reject_message = reject
         else:
             reject_code, reject_message = reject, "Comment rejected."
+
+        recaptcha_reject = captcha.submit(
+                form['recaptcha_challenge_field'].value,
+                form['recaptcha_response_field'].value,
+                config['comment_recaptcha_private'],
+                recaptcha_ipaddr)
+
         if reject_code == 1:
             data["comment_message"] = reject_message
             data["rejected"] = True
+        elif recaptcha_reject.is_valid == False:
+            data["comment_message"] = recaptcha_reject.error_code
+            data["rejected"] = True
         else:
             data["comment_message"] = writeComment(request, config, data, \
                                                    cdict, encoding)
@@ -1009,6 +1024,7 @@ def cb_story_end(args):
             rejected['cmt_description'] = msg
             rejected['cmt_description_escaped'] = escape(msg)
             renderer.outputTemplate(output, rejected, 'comment')
+        entry['recaptcha_html'] = captcha.displayhtml(config['comment_recaptcha_public'], True)
         renderer.outputTemplate(output, entry, 'comment-form')
         args['template'] = template +u"".join(output)
 
-- 
1.5.3.4


