diff options
author | supriya <supriya@dragbox.(none)> | 2012-09-26 15:49:52 +0530 |
---|---|---|
committer | supriya <supriya@dragbox.(none)> | 2012-09-26 15:49:52 +0530 |
commit | 94535d4adc3a4960795d22e3b229a8375de10b74 (patch) | |
tree | 8d77de86b443495d67360dcd40786f2b8208d334 /recaptcha | |
parent | cad11e2f7ed848cdfd7779451bb0f4f931e062c3 (diff) | |
download | gnowsys-94535d4adc3a4960795d22e3b229a8375de10b74.tar.gz |
all modules integrated
Diffstat (limited to 'recaptcha')
-rw-r--r-- | recaptcha/__init__.py | 1 | ||||
-rw-r--r-- | recaptcha/client/__init__.py | 0 | ||||
-rw-r--r-- | recaptcha/client/captcha.py | 94 | ||||
-rw-r--r-- | recaptcha/client/mailhide.py | 68 | ||||
-rw-r--r-- | recaptcha/fields.py | 27 | ||||
-rw-r--r-- | recaptcha/widgets.py | 15 |
6 files changed, 205 insertions, 0 deletions
diff --git a/recaptcha/__init__.py b/recaptcha/__init__.py new file mode 100644 index 0000000..de40ea7 --- /dev/null +++ b/recaptcha/__init__.py @@ -0,0 +1 @@ +__import__('pkg_resources').declare_namespace(__name__) diff --git a/recaptcha/client/__init__.py b/recaptcha/client/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/recaptcha/client/__init__.py diff --git a/recaptcha/client/captcha.py b/recaptcha/client/captcha.py new file mode 100644 index 0000000..1213fc4 --- /dev/null +++ b/recaptcha/client/captcha.py @@ -0,0 +1,94 @@ +import urllib2, urllib + +API_SSL_SERVER="https://www.google.com/recaptcha/api" +API_SERVER="http://www.google.com/recaptcha/api" +VERIFY_SERVER="www.google.com" + +class RecaptchaResponse(object): + def __init__(self, is_valid, error_code=None): + self.is_valid = is_valid + self.error_code = error_code + +def displayhtml (public_key, + use_ssl = False, + error = None): + """Gets the HTML to display for reCAPTCHA + + public_key -- The public api key + use_ssl -- Should the request be sent over ssl? + error -- An error message to display (from RecaptchaResponse.error_code)""" + + error_param = '' + if error: + error_param = '&error=%s' % error + + if use_ssl: + server = API_SSL_SERVER + else: + server = API_SERVER + + return """<script type="text/javascript" src="%(ApiServer)s/challenge?k=%(PublicKey)s%(ErrorParam)s"></script> + +<noscript> + <iframe src="%(ApiServer)s/noscript?k=%(PublicKey)s%(ErrorParam)s" height="300" width="500" frameborder="0"></iframe><br /> + <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea> + <input type='hidden' name='recaptcha_response_field' value='manual_challenge' /> +</noscript> +""" % { + 'ApiServer' : server, + 'PublicKey' : public_key, + 'ErrorParam' : error_param, + } + + +def submit (recaptcha_challenge_field, + recaptcha_response_field, + private_key, + remoteip): + """ + Submits a reCAPTCHA request for verification. Returns RecaptchaResponse + for the request + + recaptcha_challenge_field -- The value of recaptcha_challenge_field from the form + recaptcha_response_field -- The value of recaptcha_response_field from the form + private_key -- your reCAPTCHA private key + remoteip -- the user's ip address + """ + + if not (recaptcha_response_field and recaptcha_challenge_field and + len (recaptcha_response_field) and len (recaptcha_challenge_field)): + return RecaptchaResponse (is_valid = False, error_code = 'incorrect-captcha-sol') + + + def encode_if_necessary(s): + if isinstance(s, unicode): + return s.encode('utf-8') + return s + + params = urllib.urlencode ({ + 'privatekey': encode_if_necessary(private_key), + 'remoteip' : encode_if_necessary(remoteip), + 'challenge': encode_if_necessary(recaptcha_challenge_field), + 'response' : encode_if_necessary(recaptcha_response_field), + }) + + request = urllib2.Request ( + url = "http://%s/recaptcha/api/verify" % VERIFY_SERVER, + data = params, + headers = { + "Content-type": "application/x-www-form-urlencoded", + "User-agent": "reCAPTCHA Python" + } + ) + + httpresp = urllib2.urlopen (request) + + return_values = httpresp.read ().splitlines (); + httpresp.close(); + + return_code = return_values [0] + + if (return_code == "true"): + return RecaptchaResponse (is_valid=True) + else: + return RecaptchaResponse (is_valid=False, error_code = return_values [1]) diff --git a/recaptcha/client/mailhide.py b/recaptcha/client/mailhide.py new file mode 100644 index 0000000..437b2c2 --- /dev/null +++ b/recaptcha/client/mailhide.py @@ -0,0 +1,68 @@ +import base64 +import cgi + +try: + from Crypto.Cipher import AES +except: + raise Exception ("You need the pycrpyto library: http://cheeseshop.python.org/pypi/pycrypto/") + +MAIL_HIDE_BASE="http://www.google.com/recaptcha/mailhide" + +def asurl (email, + public_key, + private_key): + """Wraps an email address with reCAPTCHA mailhide and + returns the url. public_key is the public key from reCAPTCHA + (in the base 64 encoded format). Private key is the AES key, and should + be 32 hex chars.""" + + cryptmail = _encrypt_string (email, base64.b16decode (private_key, casefold=True), '\0' * 16) + base64crypt = base64.urlsafe_b64encode (cryptmail) + + return "%s/d?k=%s&c=%s" % (MAIL_HIDE_BASE, public_key, base64crypt) + +def ashtml (email, + public_key, + private_key): + """Wraps an email address with reCAPTCHA Mailhide and + returns html that displays the email""" + + url = asurl (email, public_key, private_key) + (userpart, domainpart) = _doterizeemail (email) + + return """%(user)s<a href='%(url)s' onclick="window.open('%(url)s', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;" title="Reveal this e-mail address">...</a>@%(domain)s""" % { + 'user' : cgi.escape (userpart), + 'domain' : cgi.escape (domainpart), + 'url' : cgi.escape (url), + } + + +def _pad_string (str, block_size): + numpad = block_size - (len (str) % block_size) + return str + numpad * chr (numpad) + +def _encrypt_string (str, aes_key, aes_iv): + if len (aes_key) != 16: + raise Exception ("expecting key of length 16") + if len (aes_iv) != 16: + raise Exception ("expecting iv of length 16") + return AES.new (aes_key, AES.MODE_CBC, aes_iv).encrypt (_pad_string (str, 16)) + +def _doterizeemail (email): + """replaces part of the username with dots""" + + try: + [user, domain] = email.split ('@') + except: + # handle invalid emails... sorta + user = email + domain = "" + + if len(user) <= 4: + user_prefix = user[:1] + elif len(user) <= 6: + user_prefix = user[:3] + else: + user_prefix = user[:4] + + return (user_prefix, domain) diff --git a/recaptcha/fields.py b/recaptcha/fields.py new file mode 100644 index 0000000..ce79a6d --- /dev/null +++ b/recaptcha/fields.py @@ -0,0 +1,27 @@ +from django.conf import settings +from django import forms +from django.utils.encoding import smart_unicode +from django.utils.translation import ugettext_lazy as _ + +from recaptcha.widgets import ReCaptcha +from recaptcha.client import captcha + +class ReCaptchaField(forms.CharField): + default_error_messages = { + 'captcha_invalid': _(u'Invalid captcha') + } + + def __init__(self, *args, **kwargs): + self.widget = ReCaptcha + self.required = True + super(ReCaptchaField, self).__init__(*args, **kwargs) + + def clean(self, values): + super(ReCaptchaField, self).clean(values[1]) + recaptcha_challenge_value = smart_unicode(values[0]) + recaptcha_response_value = smart_unicode(values[1]) + check_captcha = captcha.submit(recaptcha_challenge_value, + recaptcha_response_value, settings.RECAPTCHA_PRIVATE_KEY, {}) + if not check_captcha.is_valid: + raise forms.util.ValidationError(self.error_messages['captcha_invalid']) + return values[0] diff --git a/recaptcha/widgets.py b/recaptcha/widgets.py new file mode 100644 index 0000000..45dfd7e --- /dev/null +++ b/recaptcha/widgets.py @@ -0,0 +1,15 @@ +from django import forms +from django.utils.safestring import mark_safe +from django.conf import settings +from recaptcha.client import captcha + +class ReCaptcha(forms.widgets.Widget): + recaptcha_challenge_name = 'recaptcha_challenge_field' + recaptcha_response_name = 'recaptcha_response_field' + + def render(self, name, value, attrs=None): + return mark_safe(u'%s' % captcha.displayhtml(settings.RECAPTCHA_PUBLIC_KEY)) + + def value_from_datadict(self, data, files, name): + return [data.get(self.recaptcha_challenge_name, None), + data.get(self.recaptcha_response_name, None)] |