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
RevLine 
[2058]1from DateTime import DateTime
2
[2799]3try:
4    from zope.site.hooks import getSite
[3137]5    getSite()
[2799]6except ImportError:
7    from zope.app.component.hooks import getSite
[2058]8from zope.app.form.browser import ASCIIWidget
9from zope.app.form.interfaces import ConversionError
[3098]10from zope.app.form.browser.widget import renderElement
[2058]11from zope.i18n import MessageFactory
12
[3124]13from Acquisition import aq_parent
[2058]14
15from Products.CMFCore.utils import getToolByName
[2799]16from Products.CMFCore.interfaces import ISiteRoot
[2058]17
[3688]18from quintagroup.captcha.core.utils import (decrypt, parseKey,
19                                            encrypt1, getWord,
20                                            detectInlineValidation)
[2058]21
[3688]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
[3696]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
[3688]34
[2058]35_ = MessageFactory('quintagroup.formlib.captcha')
36
[2799]37import logging
[2058]38
[2799]39logger = logging.getLogger('quintagroup.formlib.captcha')
40
[3121]41
[2058]42class CaptchaWidget(ASCIIWidget):
[2799]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
[2058]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
[2799]60        site = self.get_site()
[3121]61        portal_url = getToolByName(site, 'portal_url')()
[2799]62        key = site.getCaptcha()
[2058]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
[3121]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
[3690]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. """
[3691]89        # The original method isn't suitable when the captcha field
[3690]90        # is omitted from the request.
91        return self.request.get(self.name, u'')
92
[2058]93    def _toFieldValue(self, input):
[3688]94        # Captcha validation is one-time process to prevent hacking
95        # This is the reason for in-line validation to be disabled.
[3696]96        if inline_validation and detectInlineValidation(inline_validation):
[3710]97            return super(CaptchaWidget, self)._toFieldValue(input)
[2799]98
[3688]99        # Verify the user input against the captcha.
100        # Get captcha type (static or dynamic)
[2799]101        site = self.get_site()
102        captcha_type = site.getCaptchaType()
[3121]103
[2058]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 = ''
[3121]111
[2799]112            hashkey = self.request.get('%shashkey' % prefix, '')
113            decrypted_key = decrypt(site.captcha_key, hashkey)
[2058]114            parsed_key = parseKey(decrypted_key)
[3121]115
[2058]116            index = parsed_key['key']
117            date = parsed_key['date']
[3121]118
[2058]119            if captcha_type == 'static':
[2799]120                img = getattr(site, '%s.jpg' % index)
[2058]121                solution = img.title
122                enc = encrypt1(input)
123            else:
124                enc = input
125                solution = getWord(int(index))
[3121]126
[2799]127            captcha_tool = getToolByName(site, 'portal_captchas')
[3122]128            if (enc != solution) or (decrypted_key in captcha_tool.keys()) or \
[3121]129               (DateTime().timeTime() - float(date) > 3600):
[2058]130                raise ConversionError(_(u'Please re-enter validation code.'))
131            else:
132                captcha_tool.addExpiredKey(decrypted_key)
[3121]133
[2058]134        return super(CaptchaWidget, self)._toFieldValue(input)
Note: See TracBrowser for help on using the repository browser.