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

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

pep8 fix

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