diff captchamiddleware/middleware.py @ 0:21ec6325ae0e

initial import of CAPTCHA middleware; unfinished
author k0s <k0scist@gmail.com>
date Sun, 24 Jan 2010 23:15:57 -0500
parents
children 478d13061336
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/captchamiddleware/middleware.py	Sun Jan 24 23:15:57 2010 -0500
@@ -0,0 +1,73 @@
+"""
+CAPTCHA middleware
+"""
+
+import os
+import random
+import sys
+from lxml import etree
+from lxmlmiddleware import LXMLMiddleware
+from skimpyGimpy import skimpyAPI
+from urllib2 import urlopen
+from webob import Request, exc
+
+
+class CAPTCHAmiddleware(LXMLMiddleware):
+    """
+    put CAPTCHAs on forms for unauthorized users
+    """
+
+    ### class level variables
+    defaults = { 
+                 'dictionary': '/usr/share/dict/words',
+                 'error': '<span class="error">Please type the CAPTCHA</span>',
+                 'minimum_length': 5, 
+                 'path': "/input[@type='submit']",
+                 }
+
+    def __init__(self, app, **kw):
+        self.app = app
+
+        # set instance parameters from kw and defaults
+        for key in self.defaults:
+            setattr(self, key, kw.get(key, self.defaults[key]))
+        self.minimum_length = int(self.minimum_length)
+        assert os.path.exists(self.dictionary)
+        
+        # get dictionary
+        if self.dictionary.startswith('http://') or self.dictionary.startswith('https://'):
+            f = urlopen(self.dictionary)
+        else:
+            f = file(self.dictionary)
+        self.words = [ i.strip() for i in f.readlines()
+                       if len(i.strip()) > self.minimum_length ]
+        random.shuffle(self.words)
+
+
+    def __call__(self, environ, start_response):
+        request = Request(environ)
+        if request.method == 'post' and not request.remote_user:
+            pass # TODO: check CAPTCHA
+
+        return LXMLMiddleware.__call__(self, environ, start_response)
+
+    def manipulate(self, environ, tree):
+        """manipulate the DOM; should return an etree._Element"""
+
+        request = Request(environ)
+
+        # don't use CAPTCHAs for authorized users
+        if request.remote_user:
+            return tree 
+
+        for element in tree.findall(".//form[@method='post']"):
+            key = random.Random().randint(0, len(self.words))
+            word = self.words[key]
+            captcha = skimpyAPI.Pre(word).data()
+            string = '<div class="captcha">%s<input type="hidden" value="%s"/></div>' % (captcha, key)
+            addition = etree.fromstring(string)
+            insertion_point = element.find('.' + self.path)
+            insertion_point.addprevious(addition)
+
+        return tree
+