I've made some more changes/fixes to this, in case anyone's
interested.  Here's what's changed from the original:

- updated for compatibility w/ django-1.1
- using sha1 instead of md5 to store captcha image (theoretically more
secure)
- added expire_time config variable
- added imagetype variable (defaults to jpg)
- fixed bug where .svn dirs (or any other files in the fonts dir)
messed up the font loading

And here's the patch:

--- cut here ---
diff -x .svn -Nur captcha/__init__.py captcha.new/__init__.py
--- captcha/__init__.py 2007-06-14 12:53:55.000000000 -0500
+++ captcha.new/__init__.py     2009-03-16 10:15:43.000000000 -0500
@@ -6,18 +6,21 @@
 """

 from os import listdir, sep, access, mkdir, W_OK, R_OK, remove,
chmod, path, rmdir, stat
+from glob import glob
 from urllib import basejoin
-import md5
+import sha
 from random import choice, randrange
 from sys import modules
 import tempfile
 import datetime
 from PIL import Image, ImageColor, ImageFont, ImageDraw
-from django.newforms import *
-from django.newforms.fields import CharField
+from django.forms import Widget, Field, ValidationError
+from django.forms.fields import CharField
 from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
 from django.utils.translation import gettext
 from django.utils.datastructures import MultiValueDict
+from django.utils.safestring import mark_safe

 def clean_old_entries(captchas_dir, max_age=1200):
     """maintainance function for deleting all expired captchas
@@ -40,7 +43,7 @@
                     pass

 def mycrypt(value, salt):
-    return md5.new(value.lower() + salt +
settings.SECRET_KEY).hexdigest()
+    return sha.new(value.lower() + salt +
settings.SECRET_KEY).hexdigest()

 class CaptchaWidget(Widget):
     """generate a captcha image and display the image along with
@@ -53,6 +56,7 @@
         'upload_url': None, # default:  None (uses MEDIA_URL/
captchas)
         'captchaconf_dir': None, # default:  None  (uses the
directory of the captcha module)
         'auto_cleanup': True, # default:  True (delete all captchas
older than 20 minutes)
+        'expire_time' : 1200, # default: 1200 (time in seconds after
which old captchas are deleted)
         'minmaxvpos': (8, 15), # default:  (8, 15) (vertical position
of characters)
         'minmaxrotations': (-30,31), # default:  (-30,31) (rotate
characters)
         'minmaxheight': (30,45), # default:  (30,45) (font size)
@@ -63,6 +67,7 @@
         'imagesize': (200,60), # default: (200,60)
         'iterations': 1, # default 1 (change to a high value (200 is
a good choice)
                          # for trying out new settings)
+        'imagetype' : 'jpg',
         }
         # change colors to tuples if possible
         try:
@@ -83,17 +88,21 @@
         if not self.csettings['captchaconf_dir']:
             myfile = modules[self.__module__].__file__
             self.csettings['captchaconf_dir'] = myfile[:myfile.rfind
(sep)]
+
         super(CaptchaWidget, self).__init__(*args, **kwargs)

     def render(self, name, value, attrs=None):
         img = Image.new('RGB',self.csettings['imagesize'],
self.csettings['bgcolor'])
         for dummy in range(self.csettings['iterations']):
             img = self.generate_image(img)
-        return u'''<input type="hidden" name="%(name)s"
value="captcha.%(hiddentext)s"
-/><img src="%(imageurl)s" alt="" /><br
-/><input type="text" name="%(name)s" id="id_%(name)s" />''' %
{'name':name,
-        'hiddentext': self.hiddentext,
-        'imageurl': self.imageurl }
+        html = u'''<input type="hidden" name="%(name)s"
value="captcha.%(hiddentext)s"/>
+                   <img src="%(imageurl)s" alt="" class="captcha" />
+                   <input type="text" name="%(name)s" id="id_%(name)
s" class="text" />
+                   ''' % {'name':name,
+                          'hiddentext': self.hiddentext,
+                          'imageurl': self.imageurl }
+
+        return mark_safe(html)

     def generate_image(self, bgimage):
         """ create a image file.
@@ -102,13 +111,13 @@
         HASH is the hashed solution.
         """
         if self.csettings['auto_cleanup']:
-            clean_old_entries(self.csettings['captchas_dir'])
+            clean_old_entries(self.csettings['captchas_dir'],
self.csettings['expire_time'])

         cs = self.csettings
         imagesize = cs['imagesize']
         posnew = 7
         fontdir = path.join(cs['captchaconf_dir'], 'fonts')
-        fontnames = [path.join(fontdir, x) for x in listdir
(fontdir) ]
+        fontnames = [path.join(fontdir, x) for x in glob('%s/*.ttf' %
fontdir) ]


         # generate characters
@@ -161,17 +170,21 @@
         self.imageurl = '%s/%s/%s' % (cs['upload_url'],
                 self.hiddentext, plainfilename)
         imagepath = path.join(dirpath, plainfilename)
-        try:
-            bgimage.convert('P', palette=Image.ADAPTIVE,
colors=4).save(imagepath + '.gif')
-            ext = '.gif'
-        except:
-            bgimage.save(imagepath + '.jpg')
-            ext = '.jpg'
-        self.imageurl += ext
-        chmod(imagepath + ext, 0644)
+
+        imagetype = cs.get('imagetype')
+
+        if imagetype == 'gif':
+            bgimage.convert('P', palette=Image.ADAPTIVE,
colors=4).save(imagepath + imagetype)
+        elif imagetype in ('jpg', 'png'):
+            bgimage.save('%s.%s' % (imagepath, imagetype))
+        else:
+            raise ImproperlyConfigured('Invalid captcha image
imagetype: %s' % imagetype)
+
+        self.imageurl = '%s.%s' % (self.imageurl, imagetype)
+        chmod('%s.%s' % (imagepath, imagetype), 0644)
         return bgimage

-    def value_from_datadict(self, data, name):
+    def value_from_datadict(self, data, files, name):
         if isinstance(data, MultiValueDict):
             return data.getlist(name)
         return data.get(name, None)
@@ -200,6 +213,7 @@
             settingcaptchas_dir = None
         self.captchas_dir = options.get('captchas_dir') or
settingcaptchas_dir or \
                 path.join(settings.MEDIA_ROOT, 'captchas')
+
         super(CaptchaField, self).__init__(required=required,
             widget=CaptchaWidget(options=options),
             label=label, help_text=help_text, *args, **kwargs

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to