source: products/quintagroup.formlib.captcha/trunk/quintagroup/formlib/captcha/widget.py

Last change on this file was 3710, checked in by potar, 11 years ago

The captcha value was decoded (bug fix)

  • Property svn:eol-style set to native
File size: 4.8 KB
Line 
1from DateTime import DateTime
2
3try:
4    from zope.site.hooks import getSite
5    getSite()
6except ImportError:
7    from zope.app.component.hooks import getSite
8from zope.app.form.browser import ASCIIWidget
9from zope.app.form.interfaces import ConversionError
10from zope.app.form.browser.widget import renderElement
11from zope.i18n import MessageFactory
12
13from Acquisition import aq_parent
14
15from Products.CMFCore.utils import getToolByName
16from Products.CMFCore.interfaces import ISiteRoot
17
18from quintagroup.captcha.core.utils import (decrypt, parseKey,
19                                            encrypt1, getWord,
20                                            detectInlineValidation)
21
22try:
23    from plone.app.form import inline_validation
24except ImportError:
25    # BBB Plone < 4.3 compatibility.
26    # The implementation of inline validation was switched
27    # to a non-KSS-based in plone.app.form-2.2.0
28    try:
29        from plone.app.form.kss import validation as inline_validation
30    # BBB: Plone 3.0 compatibility.
31    # The KSS validation was added in plone.app.form-1.1.0.
32    except:
33        inline_validation = None
34
35_ = MessageFactory('quintagroup.formlib.captcha')
36
37import logging
38
39logger = logging.getLogger('quintagroup.formlib.captcha')
40
41
42class CaptchaWidget(ASCIIWidget):
43
44    def get_site(self):
45        # get from plone.app.form.widgets.wysiwygwdget
46        site = getSite()
47        while site is not None and not ISiteRoot.providedBy(site):
48            site = aq_parent(site)
49        return site
50
51    def __call__(self):
52        kwargs = {'type': self.type,
53                  'name': self.name,
54                  'id': self.name,
55                  'cssClass': self.cssClass,
56                  'style': self.style,
57                  'size': self.displayWidth,
58                  'extra': self.extra}
59
60        site = self.get_site()
61        portal_url = getToolByName(site, 'portal_url')()
62        key = site.getCaptcha()
63
64        if self._prefix:
65            prefix = '%s.' % self._prefix
66        else:
67            prefix = ''
68
69        return u"""<input type="hidden" value="%s" name="%shashkey" />
70                   %s
71                   <img src="%s/getCaptchaImage/%s"
72                        alt="Enter the word"/>""" % (key,
73                                                     prefix,
74                                                     renderElement(self.tag,
75                                                                   **kwargs),
76                                                     portal_url,
77                                                     key)
78
79    def hasInput(self):
80        # The validator looks for the captcha only if the captcha field
81        # is present. If the captcha field is omitted from the request,
82        # then the captcha validation never happens. That's why 'required'
83        # option is useless. So, we have to simulate 'required': set up 'True'
84        # for the captcha input.
85        return True
86
87    def _getFormInput(self):
88        """ It returns current form input. """
89        # The original method isn't suitable when the captcha field
90        # is omitted from the request.
91        return self.request.get(self.name, u'')
92
93    def _toFieldValue(self, input):
94        # Captcha validation is one-time process to prevent hacking
95        # This is the reason for in-line validation to be disabled.
96        if inline_validation and detectInlineValidation(inline_validation):
97            return super(CaptchaWidget, self)._toFieldValue(input)
98
99        # Verify the user input against the captcha.
100        # Get captcha type (static or dynamic)
101        site = self.get_site()
102        captcha_type = site.getCaptchaType()
103
104        # validate captcha input
105        if input and captcha_type in ['static', 'dynamic']:
106            # make up form prefix
107            if self._prefix:
108                prefix = '%s.' % self._prefix
109            else:
110                prefix = ''
111
112            hashkey = self.request.get('%shashkey' % prefix, '')
113            decrypted_key = decrypt(site.captcha_key, hashkey)
114            parsed_key = parseKey(decrypted_key)
115
116            index = parsed_key['key']
117            date = parsed_key['date']
118
119            if captcha_type == 'static':
120                img = getattr(site, '%s.jpg' % index)
121                solution = img.title
122                enc = encrypt1(input)
123            else:
124                enc = input
125                solution = getWord(int(index))
126
127            captcha_tool = getToolByName(site, 'portal_captchas')
128            if (enc != solution) or (decrypted_key in captcha_tool.keys()) or \
129               (DateTime().timeTime() - float(date) > 3600):
130                raise ConversionError(_(u'Please re-enter validation code.'))
131            else:
132                captcha_tool.addExpiredKey(decrypted_key)
133
134        return super(CaptchaWidget, self)._toFieldValue(input)
Note: See TracBrowser for help on using the repository browser.