Index: quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/__init__.py
===================================================================
--- quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/__init__.py	(revision 2055)
+++ quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/__init__.py	(revision 2058)
@@ -1,1 +1,2 @@
-#
+from widget import CaptchaWidget
+from field import Captcha
Index: quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/captcha.txt
===================================================================
--- quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/captcha.txt	(revision 2058)
+++ quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/captcha.txt	(revision 2058)
@@ -0,0 +1,17 @@
+--------------------------
+Captchas in a formlib form
+--------------------------
+
+Using quintagroup.formlib.captcha in a formlib form is simple. Just add a
+Captcha field to your schema, and away you go:
+
+  >>> from zope.interface import Interface
+  >>> from quintagroup.formlib.captcha.form import Captcha
+  >>> class CaptchaSchema(Interface):
+  ...     captcha = Captcha(
+  ...         title=_(u'Type the code'),
+  ...         description=_(u'Type the code from the picture shown below.'))
+
+and formlib will take care of the rest. The widget associated with this field 
+will render the captcha and verify the use input automatically.
+
Index: quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/configure.zcml
===================================================================
--- quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/configure.zcml	(revision 2055)
+++ quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/configure.zcml	(revision 2058)
@@ -2,11 +2,16 @@
     xmlns="http://namespaces.zope.org/zope"
     xmlns:zcml="http://namespaces.zope.org/zcml"
+    xmlns:browser="http://namespaces.zope.org/browser"
     i18n_domain="quintagroup.formlib.captcha">
 
-    <include package="quintagroup.captcha.core" />
+  <include package="quintagroup.captcha.core" />
 
-    <include package=".form"
-             zcml:condition="installed zope.app.form"/>
-
+  <view
+      type="zope.publisher.interfaces.browser.IBrowserRequest"
+      for=".interfaces.ICaptcha"
+      provides="zope.app.form.interfaces.IInputWidget"
+      factory=".widget.CaptchaWidget"
+      permission="zope.Public"
+      />
 
 </configure>
Index: quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/field.py
===================================================================
--- quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/field.py	(revision 2058)
+++ quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/field.py	(revision 2058)
@@ -0,0 +1,6 @@
+from zope.interface import implements
+from zope.schema import ASCIILine
+from interfaces import ICaptcha
+
+class Captcha(ASCIILine):
+    implements(ICaptcha)
Index: quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/interfaces.py
===================================================================
--- quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/interfaces.py	(revision 2058)
+++ quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/interfaces.py	(revision 2058)
@@ -0,0 +1,4 @@
+from zope.schema.interfaces import IASCIILine
+
+class ICaptcha(IASCIILine):
+    u"""A field for captcha validation"""
Index: quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/widget.py
===================================================================
--- quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/widget.py	(revision 2058)
+++ quintagroup.formlib.captcha/branches/captchas-refactoring/quintagroup/formlib/captcha/widget.py	(revision 2058)
@@ -0,0 +1,83 @@
+from DateTime import DateTime
+
+from zope.component import getMultiAdapter
+from zope.app.form.browser import ASCIIWidget
+from zope.app.form.interfaces import ConversionError
+from zope.app.form.browser.textwidgets import renderElement
+from zope.i18n import MessageFactory
+
+from Acquisition import aq_inner
+
+from Products.CMFCore.utils import getToolByName
+
+from quintagroup.captcha.core.utils import decrypt, parseKey, encrypt1, getWord
+
+_ = MessageFactory('quintagroup.formlib.captcha')
+
+
+class CaptchaWidget(ASCIIWidget):
+    def __call__(self):
+        context = self.context.context
+
+        kwargs = {'type': self.type,
+                  'name': self.name,
+                  'id': self.name,
+                  'cssClass': self.cssClass,
+                  'style': self.style,
+                  'size': self.displayWidth,
+                  'extra': self.extra}
+
+        portal_url = getToolByName(context, 'portal_url')()
+        key = context.getCaptcha()
+
+        if self._prefix:
+            prefix = '%s.' % self._prefix
+        else:
+            prefix = ''
+
+        return u"""<input type="hidden" value="%s" name="%shashkey" />
+                   %s
+                   <img src="%s/getCaptchaImage/%s" alt="Enter the word"/>""" % (key,
+                                                                                 prefix,
+                                                                                 renderElement(self.tag, **kwargs),
+                                                                                 portal_url,
+                                                                                 key)
+         
+    def _toFieldValue(self, input):
+        # Verify the user input against the captcha
+        context = self.context.context
+        request = context.REQUEST
+        
+        # get captcha type (static or dynamic)
+        captcha_type = context.getCaptchaType()
+        
+        # validate captcha input
+        if input and captcha_type in ['static', 'dynamic']:
+            # make up form prefix
+            if self._prefix:
+                prefix = '%s.' % self._prefix
+            else:
+                prefix = ''
+            
+            hashkey = request.get('%shashkey' % prefix, '')
+            decrypted_key = decrypt(context.captcha_key, hashkey)
+            parsed_key = parseKey(decrypted_key)
+            
+            index = parsed_key['key']
+            date = parsed_key['date']
+            
+            if captcha_type == 'static':
+                img = getattr(context, '%s.jpg' % index)
+                solution = img.title
+                enc = encrypt1(input)
+            else:
+                enc = input
+                solution = getWord(int(index))
+            
+            captcha_tool = getToolByName(context, 'portal_captchas')
+            if (enc != solution) or (captcha_tool.has_key(decrypted_key)) or (DateTime().timeTime() - float(date) > 3600):
+                raise ConversionError(_(u'Please re-enter validation code.'))
+            else:
+                captcha_tool.addExpiredKey(decrypted_key)
+        
+        return super(CaptchaWidget, self)._toFieldValue(input)
