1
#!/usr/bin/env python -tt
3
from django.forms import *
7
# Code was taken from http://smileychris.tactful.co.nz/static/uploads/recaptcha.py
8
# Thanks for implementing!
10
class RecaptchaWidget(Widget):
11
def __init__(self, theme=None, tabindex=None):
13
From http://recaptcha.net/apidocs/captcha/#look-n-feel:
15
theme: 'red' | 'white' | 'blackglass'
17
Defines which theme to use for reCAPTCHA.
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
27
options['theme'] = theme
29
options['tabindex'] = tabindex
30
self.options = options
31
super(RecaptchaWidget, self).__init__()
33
def render(self, name, value, attrs=None):
34
args = dict(public_key=settings.RECAPTCHA_PUBLIC_KEY)
36
args['options'] = '''<script type="text/javascript">
37
var RecaptchaOptions = %r;
40
return '''%(options)s<script type="text/javascript"
41
src="http://api.recaptcha.net/challenge?k=%(public_key)s">
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">
49
<input type="hidden" name="recaptcha_response_field"
50
value="manual_challenge">
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)
58
def id_for_label(self, id_):
62
class RecaptchaField(Field):
63
widget = RecaptchaWidget
65
def __init__(self, remote_ip, *args, **kwargs):
66
self.remote_ip = remote_ip
67
super(RecaptchaField, self).__init__(*args, **kwargs)
69
def clean(self, value):
70
value = super(RecaptchaField, self).clean(value)
71
challenge, response = value
73
raise ValidationError(u'An error occured with the CAPTCHA service. Please try again.')
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.')
82
class RecaptchaFieldPlaceholder(Field):
84
Placeholder field for use with RecaptchaBaseForm which gets replaced with
85
RecaptchaField (which is passed the remote_ip) when RecaptchaBaseForm is
88
def __init__(self, *args, **kwargs):
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)
101
class RecaptchaForm(RecaptchaBaseForm, Form):
105
def validate_recaptcha(remote_ip, challenge, response):
106
# Request validation from recaptcha.net
108
params = urllib.urlencode(dict(privatekey=settings.RECAPTCHA_PRIVATE_KEY,
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()
121
# Validate based on response data
122
result = data.startswith('true')
125
bits = data.split('\n', 2)
129
return dict(result=result,
130
error_code=error_code)