Index: qPloneCaptchaField/tags/0.2.2/README.txt
===================================================================
--- qPloneCaptchaField/tags/0.2.2/README.txt	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/README.txt	(revision 939)
@@ -0,0 +1,34 @@
+Plone Capcha Field
+
+    qPloneCaptchaField is a Plone product that allows to add captcha field to the form, created with PloneFormGen product.
+
+Supported Plone versions:
+
+    * 3.x
+
+Dependencies
+
+    * PloneFormGen
+    * qPloneCaptchas
+
+Installation:
+
+    Please make sure that the following products are intalled in the following order:
+
+    * PloneFormGen
+
+    * qPloneCaptchas
+
+    * qPloneCaptchaField
+
+Documentation:
+
+    http://projects.quintagroup.com/products/wiki/qPloneCaptchaField
+
+Authors:
+
+    The product is developed by Quintagroup.com team:
+
+    * Volodymyr Cherepanyak - chervol@quintagroup.com
+
+    * Taras Melnychuk - fenix@quintagroup.com
Index: qPloneCaptchaField/tags/0.2.2/__init__.py
===================================================================
--- qPloneCaptchaField/tags/0.2.2/__init__.py	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/__init__.py	(revision 939)
@@ -0,0 +1,34 @@
+from Products.CMFCore import utils
+from Products.CMFCore.interfaces import ISiteRoot
+from Products.CMFCore.DirectoryView import registerDirectory
+from Products.Archetypes.atapi import process_types, listTypes
+from Products.GenericSetup import EXTENSION, profile_registry
+
+from permissions import ADD_PERMISSION
+from config import *
+import validators
+import content
+
+registerDirectory(SKINS_DIR, GLOBALS)
+
+def initialize(context):
+
+    content_types, constructors, ftis = process_types(listTypes(PROJECTNAME), PROJECTNAME)
+
+    utils.ContentInit(
+        PROJECTNAME + ' Content',
+        content_types      = content_types,
+        permission         = ADD_PERMISSION,
+        extra_constructors = constructors,
+        fti                = ftis,
+        ).initialize(context)
+
+    profile_desc = "Installs CaptchaField content type."
+    profile_registry.registerProfile('default',
+                                      PROJECTNAME,
+                                      profile_desc,
+                                     'profiles/default',
+                                      PROJECTNAME,
+                                      EXTENSION,
+                                      for_=ISiteRoot,
+                                    )
Index: qPloneCaptchaField/tags/0.2.2/config.py
===================================================================
--- qPloneCaptchaField/tags/0.2.2/config.py	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/config.py	(revision 939)
@@ -0,0 +1,3 @@
+PROJECTNAME = "qPloneCaptchaField"
+SKINS_DIR = "skins"
+GLOBALS = globals()
Index: qPloneCaptchaField/tags/0.2.2/content/CaptchaField.py
===================================================================
--- qPloneCaptchaField/tags/0.2.2/content/CaptchaField.py	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/content/CaptchaField.py	(revision 939)
@@ -0,0 +1,59 @@
+from zope.event import notify
+from zope.lifecycleevent import ObjectCreatedEvent, ObjectModifiedEvent
+from Products.CMFCore.permissions import View
+
+from Products.Archetypes.atapi import *
+from Products.ATContentTypes.content.base import registerATCT
+
+from Products.PloneFormGen.content.fieldsBase import BareFieldSchema, BaseFormField, BaseFieldSchemaStringDefault
+from Products.PloneFormGen.content.fields import FGStringField
+
+from Products.qPloneCaptchaField.config import PROJECTNAME
+from Products.qPloneCaptchaField.widgets.CaptchaWidget import CaptchaWidget
+
+CAPTCHA_ID = 'key'
+
+def finalizeCaptchaFieldSchema( schema ):
+    schema['title'].default= 'key'
+    for field in ('title', 
+                  'description',
+                  'required', 
+                  'hidden', 
+                  'fgTDefault', 
+                  'fgTEnabled', 
+                  'fgDefault',
+                  'fgTValidator'):
+        schema[field].widget.visible = {'view':'invisible','edit':'invisible'}
+
+CaptchaFieldSchema = BaseFieldSchemaStringDefault.copy()
+finalizeCaptchaFieldSchema( CaptchaFieldSchema )
+
+def addCaptchaField(self, id, **kwargs):
+    id = CAPTCHA_ID 
+    obj = CaptchaField(id)
+    notify(ObjectCreatedEvent(obj))
+    self._setObject(id, obj)
+    obj = self._getOb(id)
+    obj.initializeArchetype(**kwargs)
+    notify(ObjectModifiedEvent(obj))
+    return obj.getId()
+
+class CaptchaField(FGStringField):
+
+    _at_rename_after_creation = False
+    schema = CaptchaFieldSchema
+
+    def __init__(self, oid, **kwargs):
+        """ initialize class """
+        BaseFormField.__init__(self, oid, **kwargs)
+
+        # set a preconfigured field as an instance attribute
+        self.fgField = StringField('fg_string_field',
+            searchable=0,
+            required=1,
+            write_permission = View,
+            validators=('isCaptchaCorrect',),
+            widget=CaptchaWidget(),
+            )
+
+registerATCT(CaptchaField, PROJECTNAME)
Index: qPloneCaptchaField/tags/0.2.2/content/__init__.py
===================================================================
--- qPloneCaptchaField/tags/0.2.2/content/__init__.py	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/content/__init__.py	(revision 939)
@@ -0,0 +1,1 @@
+import CaptchaField
Index: qPloneCaptchaField/tags/0.2.2/permissions.py
===================================================================
--- qPloneCaptchaField/tags/0.2.2/permissions.py	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/permissions.py	(revision 939)
@@ -0,0 +1,5 @@
+from Products.CMFCore import permissions as cmfcore_permissions
+
+## This file is used to set up permissions for product.
+
+ADD_PERMISSION = cmfcore_permissions.AddPortalContent
Index: qPloneCaptchaField/tags/0.2.2/profiles/default/factorytool.xml
===================================================================
--- qPloneCaptchaField/tags/0.2.2/profiles/default/factorytool.xml	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/profiles/default/factorytool.xml	(revision 939)
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<object name="portal_factory" meta_type="Plone Factory Tool">
+ <factorytypes>
+  <type portal_type="CaptchaField"/>
+ </factorytypes>
+</object>
Index: qPloneCaptchaField/tags/0.2.2/profiles/default/propertiestool.xml
===================================================================
--- qPloneCaptchaField/tags/0.2.2/profiles/default/propertiestool.xml	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/profiles/default/propertiestool.xml	(revision 939)
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<object name="portal_properties" meta_type="Plone Properties Tool">
+ <object name="navtree_properties" meta_type="Plone Property Sheet">
+  <property name="metaTypesNotToList" type="lines" purge="False">
+   <element value="CaptchaField"/>
+  </property>
+ </object>
+</object>
Index: qPloneCaptchaField/tags/0.2.2/profiles/default/skins.xml
===================================================================
--- qPloneCaptchaField/tags/0.2.2/profiles/default/skins.xml	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/profiles/default/skins.xml	(revision 939)
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<object name="portal_skins" meta_type="Plone Skins Tool">
+    <object name="qplonecaptchafield" meta_type="Filesystem Directory View"
+            directory="qPloneCaptchaField/skins/qplonecaptchafield"/>
+    <skin-path name="*">
+        <layer name="qplonecaptchafield" insert-after="custom" />
+    </skin-path>
+</object>
Index: qPloneCaptchaField/tags/0.2.2/profiles/default/types.xml
===================================================================
--- qPloneCaptchaField/tags/0.2.2/profiles/default/types.xml	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/profiles/default/types.xml	(revision 939)
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<object name="portal_types" meta_type="Plone Types Tool">
+    <object name="CaptchaField"
+          meta_type="Factory-based Type Information with dynamic views" />
+</object>
Index: qPloneCaptchaField/tags/0.2.2/profiles/default/types/CaptchaField.xml
===================================================================
--- qPloneCaptchaField/tags/0.2.2/profiles/default/types/CaptchaField.xml	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/profiles/default/types/CaptchaField.xml	(revision 939)
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<object name="CaptchaField"
+        meta_type="Factory-based Type Information with dynamic views"
+        xmlns:i18n="http://xml.zope.org/namespaces/i18n">
+    <property name="title">Captcha Field</property>
+    <property
+             name="description">Extension for PloneFormGen. Field that prevents automatic page submit.</property>
+    <property name="content_icon">captcha_field.gif</property>
+    <property name="content_meta_type">CaptchaField</property>
+    <property name="product">qPloneCaptchaField</property>
+    <property name="factory">addCaptchaField</property>
+    <property name="immediate_view">base_view</property>
+    <property name="global_allow">False</property>
+    <property name="filter_content_types">True</property>
+    <property name="allowed_content_types"/>
+    <property name="allow_discussion">False</property>
+    <property name="default_view">base_view</property>
+    <property name="view_methods">
+        <element value="base_view"/>
+    </property>
+    <property name="default_view_fallback">False</property>
+    <alias from="(Default)" to="(dynamic view)"/>
+    <alias from="edit" to="atct_edit"/>
+    <alias from="index.html" to="(dynamic view)"/>
+    <alias from="properties" to="base_metadata"/>
+    <alias from="sharing" to="folder_localrole_form"/>
+    <alias from="view" to="(selected layout)"/>
+    <action title="View" action_id="view" category="object" condition_expr=""
+            url_expr="string:${object_url}" visible="True">
+        <permission value="View"/>
+    </action>
+    <action title="Edit" action_id="edit" category="object" condition_expr=""
+            url_expr="string:${object_url}/edit" visible="True">
+        <permission value="Modify portal content"/>
+    </action>
+</object>
Index: qPloneCaptchaField/tags/0.2.2/profiles/default/types/FormFolder.xml
===================================================================
--- qPloneCaptchaField/tags/0.2.2/profiles/default/types/FormFolder.xml	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/profiles/default/types/FormFolder.xml	(revision 939)
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<object name="FormFolder" meta_type="Factory-based Type Information"
+        xmlns:i18n="http://xml.zope.org/namespaces/i18n">
+    <property name="allowed_content_types">
+        <element value="Document" />
+        <element value="FieldsetFolder" />
+        <element value="FormBooleanField" />
+        <element value="FormCustomScriptAdapter" />
+        <element value="FormDateField" />
+        <element value="FormFileField" />
+        <element value="FormFixedPointField" />
+        <element value="FormIntegerField" />
+        <element value="FormLabelField" />
+        <element value="FormLinesField" />
+        <element value="FormMailerAdapter" />
+        <element value="FormMultiSelectionField" />
+        <element value="FormPasswordField" />
+        <element value="FormRichLabelField" />
+        <element value="FormRichTextField" />
+        <element value="FormSaveDataAdapter" />
+        <element value="FormSelectionField" />
+        <element value="FormStringField" />
+        <element value="FormTextField" />
+        <element value="FormThanksPage" />
+        <element value="Image" />
+        <element value="CaptchaField" />
+    </property>
+</object>
Index: qPloneCaptchaField/tags/0.2.2/profiles/default/workflows.xml
===================================================================
--- qPloneCaptchaField/tags/0.2.2/profiles/default/workflows.xml	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/profiles/default/workflows.xml	(revision 939)
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<object name="portal_workflow" meta_type="Plone Workflow Tool">
+ <bindings>
+  <type type_id="CaptchaField">
+    <bound-workflow workflow_id=""/>
+  </type>
+ </bindings>
+</object>
Index: qPloneCaptchaField/tags/0.2.2/skins/qplonecaptchafield/captchaField_widget.pt
===================================================================
--- qPloneCaptchaField/tags/0.2.2/skins/qplonecaptchafield/captchaField_widget.pt	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/skins/qplonecaptchafield/captchaField_widget.pt	(revision 939)
@@ -0,0 +1,3 @@
+<metal:view_macro define-macro="edit">
+    <div metal:use-macro="here/captcha_widget/macros/captcha"></div>
+</metal:view_macro>
Index: qPloneCaptchaField/tags/0.2.2/skins/qplonecaptchafield/createObject.cpy
===================================================================
--- qPloneCaptchaField/tags/0.2.2/skins/qplonecaptchafield/createObject.cpy	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/skins/qplonecaptchafield/createObject.cpy	(revision 939)
@@ -0,0 +1,59 @@
+## Controller Python Script "createObject"
+##bind container=container
+##bind context=context
+##bind namespace=
+##bind script=script
+##bind state=state
+##bind subpath=traverse_subpath
+##parameters=id=None,type_name=None,script_id=None
+##title=
+##
+
+from DateTime import DateTime
+from Products.CMFPlone.utils import transaction_note
+from Products.CMFPlone import PloneMessageFactory as _
+from Products.CMFCore.utils import getToolByName
+REQUEST=context.REQUEST
+
+if type_name == 'CaptchaField':
+    id = 'key'
+
+if id is None:
+    id=context.generateUniqueId(type_name)
+
+if type_name is None:
+    raise Exception, 'Type name not specified'
+
+types_tool = getToolByName(context, 'portal_types')
+
+fti = types_tool.getTypeInfo(type_name)
+
+if not fti.queryMethodID('edit') and \
+   not fti.getActionObject('object/edit'):
+    state.setStatus('success_no_edit')
+
+if context.portal_factory.getFactoryTypes().has_key(type_name):
+    new_url = 'portal_factory/' + type_name + '/' + id
+    if state.getStatus() != 'success_no_edit':
+        new_url = new_url + '/edit'
+    state.set(status='factory', next_action='redirect_to:string:%s'%new_url)
+    # If there's an issue with object creation, let the factory handle it
+    return state
+else:
+    new_id = context.invokeFactory(id=id, type_name=type_name)
+    if new_id is None or new_id == '':
+       new_id = id
+    o=getattr(context, new_id, None)
+    tname = o.getTypeInfo().Title()
+    message = _(u'${tname} has been created.', mapping={u'tname' : tname})
+    transaction_note('Created %s with id %s in %s' % (o.getTypeInfo().getId(), new_id, context.absolute_url()))
+
+if o is None:
+    raise Exception
+
+if script_id:
+    state.setId(script_id)
+
+if message:
+    context.plone_utils.addPortalMessage(message)
+return state.set(context=o)
Index: qPloneCaptchaField/tags/0.2.2/validators/__init__.py
===================================================================
--- qPloneCaptchaField/tags/0.2.2/validators/__init__.py	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/validators/__init__.py	(revision 939)
@@ -0,0 +1,1 @@
+import captcha_validator
Index: qPloneCaptchaField/tags/0.2.2/validators/captcha_validator.py
===================================================================
--- qPloneCaptchaField/tags/0.2.2/validators/captcha_validator.py	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/validators/captcha_validator.py	(revision 939)
@@ -0,0 +1,27 @@
+from Products.CMFCore.utils import getToolByName
+from Products.validation import validation, interfaces
+
+from Products.CMFPlone.utils import safe_hasattr
+
+class CaptchaValidator:
+
+    __implements__ = (interfaces.ivalidator,)
+
+    name = 'CaptchaValidator'
+
+    def __init__(self, name, title='', description=''):
+        self.name = name
+        self.title = title or name
+        self.description = description
+
+    def __call__(self, value, *args, **kwargs):
+
+        form  = kwargs.get('instance')
+        portal = getToolByName(form, 'portal_url').getPortalObject()
+        result = portal.captcha_validator()
+        if result.status == 'failure':
+            return ("%(problem)s" % {'problem' : result.errors['key'][0]})
+        else:
+            return 1
+
+validation.register(CaptchaValidator('isCaptchaCorrect'))
Index: qPloneCaptchaField/tags/0.2.2/version.txt
===================================================================
--- qPloneCaptchaField/tags/0.2.2/version.txt	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/version.txt	(revision 939)
@@ -0,0 +1,1 @@
+0.2.2
Index: qPloneCaptchaField/tags/0.2.2/widgets/CaptchaWidget.py
===================================================================
--- qPloneCaptchaField/tags/0.2.2/widgets/CaptchaWidget.py	(revision 939)
+++ qPloneCaptchaField/tags/0.2.2/widgets/CaptchaWidget.py	(revision 939)
@@ -0,0 +1,13 @@
+from Products.Archetypes.Widget import StringWidget
+from Products.Archetypes.Registry import registerWidget
+
+class CaptchaWidget(StringWidget):
+    _properties = StringWidget._properties.copy()
+    _properties.update( {'macro' : "captchaField_widget"} )
+
+
+registerWidget(CaptchaWidget,
+               title = 'Captcha widget',
+               description= ('Renders captcha image and string input',),
+               used_for = ('Products.qPloneCaptchaField.content.CaptchaField',)
+              )
