~widelands-dev/widelands-website/trunk

« back to all changes in this revision

Viewing changes to wlrecaptcha/forms.py

  • Committer: Holger Rapp
  • Date: 2019-06-21 18:34:42 UTC
  • mfrom: (540.1.3 update_ops_script)
  • Revision ID: sirver@gmx.de-20190621183442-y2ulybzr0rdvfefd
Adapt the update script for the new server.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python -tt
2
 
# encoding: utf-8
3
 
from django.forms import *
4
 
import settings
5
 
import httplib, urllib
6
 
 
7
 
# Code was taken from http://smileychris.tactful.co.nz/static/uploads/recaptcha.py
8
 
# Thanks for implementing!
9
 
 
10
 
class RecaptchaWidget(Widget):
11
 
    def __init__(self, theme=None, tabindex=None):
12
 
        '''
13
 
        From http://recaptcha.net/apidocs/captcha/#look-n-feel:
14
 
 
15
 
        theme:      'red' | 'white' | 'blackglass'
16
 
 
17
 
            Defines which theme to use for reCAPTCHA.
18
 
 
19
 
        tabindex:   any integer
20
 
 
21
 
            Sets a tabindex for the reCAPTCHA text box. If other elements in
22
 
            the form use a tabindex, this should be set so that navigation is
23
 
            easier for the user.
24
 
        '''
25
 
        options = {}
26
 
        if theme:
27
 
            options['theme'] = theme
28
 
        if tabindex:
29
 
            options['tabindex'] = tabindex
30
 
        self.options = options
31
 
        super(RecaptchaWidget, self).__init__()
32
 
 
33
 
    def render(self, name, value, attrs=None):
34
 
        args = dict(public_key=settings.RECAPTCHA_PUBLIC_KEY)
35
 
        if self.options:
36
 
            args['options'] = '''<script type="text/javascript">
37
 
   var RecaptchaOptions = %r;
38
 
</script>
39
 
''' % self.options
40
 
        return '''%(options)s<script type="text/javascript"
41
 
   src="http://api.recaptcha.net/challenge?k=%(public_key)s">
42
 
</script>
43
 
 
44
 
<noscript>
45
 
   <iframe src="http://api.recaptcha.net/noscript?k=%(public_key)s"
46
 
       height="300" width="500" frameborder="0"></iframe><br />
47
 
   <textarea name="recaptcha_challenge_field" rows="3" cols="40">
48
 
   </textarea>
49
 
   <input type="hidden" name="recaptcha_response_field" 
50
 
       value="manual_challenge">
51
 
</noscript>''' % args
52
 
 
53
 
    def value_from_datadict(self, data, files, name):
54
 
        challenge = data.get('recaptcha_challenge_field')
55
 
        response = data.get('recaptcha_response_field')
56
 
        return (challenge, response)
57
 
 
58
 
    def id_for_label(self, id_):
59
 
        return None
60
 
 
61
 
 
62
 
class RecaptchaField(Field):
63
 
    widget = RecaptchaWidget
64
 
 
65
 
    def __init__(self, remote_ip, *args, **kwargs):
66
 
        self.remote_ip = remote_ip
67
 
        super(RecaptchaField, self).__init__(*args, **kwargs)
68
 
    
69
 
    def clean(self, value):
70
 
        value = super(RecaptchaField, self).clean(value)
71
 
        challenge, response = value
72
 
        if not challenge:
73
 
            raise ValidationError(u'An error occured with the CAPTCHA service. Please try again.')
74
 
        if not response:
75
 
            raise ValidationError(u'Please enter the CAPTCHA solution.')
76
 
        value = validate_recaptcha(self.remote_ip, challenge, response)
77
 
        if not value.get('result'):
78
 
            raise ValidationError(u'An incorrect CAPTCHA solution was entered.')
79
 
        return value
80
 
 
81
 
 
82
 
class RecaptchaFieldPlaceholder(Field):
83
 
    '''
84
 
    Placeholder field for use with RecaptchaBaseForm which gets replaced with
85
 
    RecaptchaField (which is passed the remote_ip) when RecaptchaBaseForm is
86
 
    initialised.
87
 
    '''
88
 
    def __init__(self, *args, **kwargs):
89
 
        self.args = args
90
 
        self.kwargs = kwargs
91
 
 
92
 
 
93
 
class RecaptchaBaseForm(BaseForm):
94
 
    def __init__(self, remote_ip, *args, **kwargs):
95
 
        for key, field in self.base_fields.items():
96
 
            if isinstance(field, RecaptchaFieldPlaceholder):
97
 
                self.base_fields[key] = RecaptchaField(remote_ip, *field.args, **field.kwargs)
98
 
        super(RecaptchaBaseForm, self).__init__(*args, **kwargs)
99
 
 
100
 
 
101
 
class RecaptchaForm(RecaptchaBaseForm, Form):
102
 
    pass
103
 
 
104
 
 
105
 
def validate_recaptcha(remote_ip, challenge, response):
106
 
    # Request validation from recaptcha.net
107
 
    if challenge:
108
 
        params = urllib.urlencode(dict(privatekey=settings.RECAPTCHA_PRIVATE_KEY,
109
 
                                       remoteip=remote_ip,
110
 
                                       challenge=challenge,
111
 
                                       response=response))
112
 
        headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
113
 
        conn = httplib.HTTPConnection("api-verify.recaptcha.net")
114
 
        conn.request("POST", "/verify", params, headers)
115
 
        response = conn.getresponse()
116
 
        if response.status == 200:
117
 
            data = response.read()
118
 
        else:
119
 
            data = ''
120
 
        conn.close()
121
 
    # Validate based on response data
122
 
    result = data.startswith('true')
123
 
    error_code = ''
124
 
    if not result:
125
 
        bits = data.split('\n', 2)
126
 
        if len(bits) > 1:
127
 
            error_code = bits[1]
128
 
    # Return dictionary
129
 
    return dict(result=result,
130
 
                error_code=error_code)
131