changeset 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
files captchamiddleware/__init__.py captchamiddleware/example.py captchamiddleware/middleware.py example.ini setup.py
diffstat 5 files changed, 142 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/captchamiddleware/__init__.py	Sun Jan 24 23:15:57 2010 -0500
@@ -0,0 +1,2 @@
+#
+from middleware import CAPTCHAmiddleware
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/captchamiddleware/example.py	Sun Jan 24 23:15:57 2010 -0500
@@ -0,0 +1,16 @@
+from webob import Response
+from captchamiddleware import CAPTCHAmiddleware
+from paste.httpexceptions import HTTPExceptionHandler
+
+def example_app(environ, start_response):
+    return Response('<html><body><form method="post">Hello, world!<input type="submit"/></form></body></html>')(environ, start_response)
+
+
+def factory(global_conf, **app_conf):
+    """create a webob view and wrap it in middleware"""
+    keystring = 'captcha.'
+    args = dict([(key.split(keystr, 1)[-1], value)
+                 for key, value in app_conf.items()
+                 if key.startswith(keystr) ])
+    return HTTPExceptionHandler(CAPTCHAmiddleware(example_app, **args))
+    
--- /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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example.ini	Sun Jan 24 23:15:57 2010 -0500
@@ -0,0 +1,21 @@
+#!/usr/bin/env paster
+
+[DEFAULT]
+debug = true
+email_to = k0scist@gmail.com
+smtp_server = localhost
+error_email_from = paste@localhost
+
+[server:main]
+use = egg:Paste#http
+host = 0.0.0.0
+port = 54954
+
+[composite:main]
+use = egg:Paste#urlmap
+/ = captchamiddleware
+
+set debug = false
+
+[app:captchamiddleware]
+paste.app_factory = captchamiddleware.example:factory
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/setup.py	Sun Jan 24 23:15:57 2010 -0500
@@ -0,0 +1,30 @@
+from setuptools import setup, find_packages
+import sys, os
+
+version = "0.1"
+
+setup(name='CAPTCHAmiddleware',
+      version=version,
+      description="put CAPTCHAs on forms",
+      long_description="""
+""",
+      classifiers=[], # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      author='Jeff Hammel',
+      author_email='k0scist@gmail.com',
+      url='http://k0s.org',
+      license="GPL",
+      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          # -*- Extra requirements: -*-
+         'lxmlmiddleware',
+         'skimpygimpy'
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      [paste.app_factory]
+      example-captcha = captchamiddleware.example:factory
+      """,
+      )
+