forked from rtpm/cmsplugin_contact
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
included glamkit-stopspam for simplicity
- Loading branch information
Showing
8 changed files
with
214 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#Don't use import * - causes all sorts of namespace clashes | ||
|
||
from widgets import RecaptchaResponse, RecaptchaChallenge, HoneypotWidget | ||
from fields import HoneypotField | ||
from forms import BaseForm, AkismetForm, RecaptchaForm, HoneyPotForm, SuperSpamKillerForm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from django import forms | ||
from django.core.exceptions import ValidationError | ||
from django.utils.translation import ugettext as _ | ||
|
||
from widgets import HoneypotWidget | ||
|
||
|
||
class HoneypotField(forms.BooleanField): | ||
def __init__(self, *args, **kwargs): | ||
super(HoneypotField, self).__init__( | ||
widget = HoneypotWidget, | ||
required = False, | ||
error_messages = { 'checked': _("Please don't check this box.") }, | ||
*args, **kwargs) | ||
|
||
def clean(self, value): | ||
val = super(HoneypotField, self).clean(value) | ||
if val: | ||
raise ValidationError(self.error_messages['checked']) | ||
return val |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
from django import forms | ||
from django.conf import settings | ||
|
||
from nospam import utils | ||
|
||
from fields import HoneypotField | ||
from widgets import RecaptchaChallenge, RecaptchaResponse | ||
from django.utils.translation import ugettext as _ | ||
|
||
|
||
|
||
class BaseForm(forms.Form): | ||
|
||
def __init__(self, request, *args, **kwargs): | ||
self._request = request | ||
super(BaseForm, self).__init__(*args, **kwargs) | ||
|
||
|
||
|
||
|
||
class AkismetForm(BaseForm): | ||
|
||
akismet_fields = { | ||
'comment_author': 'name', | ||
'comment_author_email': 'email', | ||
'comment_author_url': 'url', | ||
'comment_content': 'comment', | ||
} | ||
akismet_api_key = None | ||
|
||
def akismet_check(self): | ||
fields = {} | ||
for key, value in self.akismet_fields.items(): | ||
fields[key] = self.cleaned_data[value] | ||
return utils.akismet_check(self._request, akismet_api_key=self.akismet_api_key, **fields) | ||
|
||
|
||
class RecaptchaForm(BaseForm): | ||
recaptcha_challenge_field = forms.CharField(widget=RecaptchaChallenge) | ||
recaptcha_response_field = forms.CharField( | ||
widget = RecaptchaResponse, | ||
label = _('Please enter the two words on the image separated by a space:'), | ||
error_messages = { | ||
'required': _('You did not enter any of the words.') | ||
}) | ||
recaptcha_always_validate = False | ||
|
||
def __init__(self, *args, **kwargs): | ||
# Because the ReCAPTCHA library requires the fields to be named a | ||
# certain way, using a form prefix will break the validation unless we | ||
# modify the received POST and rename the keys accordingly | ||
if ('data' in kwargs or len(args) > 1) and 'prefix' in kwargs: | ||
data = kwargs.get('data', args[1]).__copy__() | ||
data['%s-recaptcha_challenge_field' % kwargs['prefix']] = \ | ||
data.pop('recaptcha_challenge_field', [u''])[0] | ||
data['%s-recaptcha_response_field' % kwargs['prefix']] = \ | ||
data.pop('recaptcha_response_field', [u''])[0] | ||
data._mutable = False | ||
# Since data could have been passed eith as an arg or kwarg, set | ||
# the right one to the new data | ||
if 'data' in kwargs: | ||
kwargs['data'] = data | ||
else: | ||
args = (args[0], data) + args[2:] | ||
|
||
super(RecaptchaForm, self).__init__(*args, **kwargs) | ||
self._recaptcha_public_key = getattr(self, 'recaptcha_public_key', getattr(settings, 'RECAPTCHA_PUBLIC_KEY', None)) | ||
self._recaptcha_private_key = getattr(self, 'recaptcha_private_key', getattr(settings, 'RECAPTCHA_PRIVATE_KEY', None)) | ||
self._recaptcha_theme = getattr(self, 'recaptcha_theme', getattr(settings, 'RECAPTCHA_THEME', 'clean')) | ||
self.fields['recaptcha_response_field'].widget.public_key = self._recaptcha_public_key | ||
self.fields['recaptcha_response_field'].widget.theme = self._recaptcha_theme | ||
# Move the ReCAPTCHA fields to the end of the form | ||
self.fields['recaptcha_challenge_field'] = self.fields.pop('recaptcha_challenge_field') | ||
self.fields['recaptcha_response_field'] = self.fields.pop('recaptcha_response_field') | ||
|
||
|
||
def clean_recaptcha_response_field(self): | ||
if 'recaptcha_challenge_field' in self.cleaned_data: | ||
self._validate_captcha() | ||
return self.cleaned_data['recaptcha_response_field'] | ||
|
||
def clean_recaptcha_challenge_field(self): | ||
if 'recaptcha_response_field' in self.cleaned_data: | ||
self._validate_captcha() | ||
return self.cleaned_data['recaptcha_challenge_field'] | ||
|
||
def _validate_captcha(self): | ||
if not self.recaptcha_always_validate: | ||
rcf = self.cleaned_data['recaptcha_challenge_field'] | ||
rrf = self.cleaned_data['recaptcha_response_field'] | ||
if rrf == '': | ||
raise forms.ValidationError(_('You did not enter the two words shown in the image.')) | ||
else: | ||
from recaptcha.client import captcha as recaptcha | ||
ip = self._request.META['REMOTE_ADDR'] | ||
check = recaptcha.submit(rcf, rrf, self._recaptcha_private_key, ip) | ||
if not check.is_valid: | ||
raise forms.ValidationError(_('The words you entered did not match the image')) | ||
|
||
class HoneyPotForm(BaseForm): | ||
accept_terms = HoneypotField() | ||
|
||
|
||
|
||
class SuperSpamKillerForm(RecaptchaForm, HoneyPotForm, AkismetForm): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
from django.contrib.sites.models import Site | ||
from django.core.exceptions import ImproperlyConfigured | ||
from django.conf import settings | ||
|
||
|
||
def akismet_check(request=None, comment_author='', comment_author_email='', comment_author_url='', comment_content='', akismet_api_key=None): | ||
""" | ||
Connects to Akismet and returns True if Akismet marks this content as | ||
spam. Otherwise returns False. | ||
""" | ||
|
||
# Check if the akismet library is installed | ||
try: | ||
from akismet import Akismet | ||
except ImportError: | ||
raise ImportError('Akismet library is not installed. "easy_install akismet" does the job.') | ||
|
||
# Check if the akismet api key is set, fail silently if | ||
# settings.DEBUG is False and return False (not moderated) | ||
AKISMET_API_KEY = akismet_api_key or getattr(settings, 'AKISMET_API_KEY', False) | ||
if not AKISMET_API_KEY: | ||
raise ImproperlyConfigured('You must set AKISMET_API_KEY with your api key in your settings file.') | ||
|
||
ak = Akismet( | ||
key = AKISMET_API_KEY, | ||
blog_url = 'http://%s/' % Site.objects.get(pk=settings.SITE_ID).domain | ||
) | ||
|
||
if ak.verify_key(): | ||
if request is not None: | ||
data = { | ||
'user_ip': request.META.get('REMOTE_ADDR', '127.0.0.1'), | ||
'user_agent': request.META.get('HTTP_USER_AGENT', ''), | ||
'referrer': request.META.get('HTTP_REFERER', ''), | ||
} | ||
else: | ||
data = { | ||
'user_ip': '', | ||
'user_agent': '', | ||
'referrer': '', | ||
} | ||
data.update({'comment_author': comment_author.encode('utf-8')}) | ||
data.update({'comment_author_email': comment_author_email.encode('utf-8')}) | ||
data.update({'comment_author_url': comment_author_url.encode('utf-8')}) | ||
# Send the request to Akismet | ||
if ak.comment_check(comment_content.encode('utf-8'), data=data, build_data=True): | ||
return True | ||
|
||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from django import forms | ||
from django.utils.translation import ugettext as _, get_language | ||
from django.utils.safestring import mark_safe | ||
|
||
|
||
# RECAPTCHA widgets | ||
class RecaptchaResponse(forms.Widget): | ||
|
||
def render(self, *args, **kwargs): | ||
from recaptcha.client import captcha as recaptcha | ||
recaptcha_options = "<script> var RecaptchaOptions = { theme: '" + self.theme + \ | ||
"', lang: '" + get_language()[0:2] + \ | ||
("', custom_theme_widget: 'recaptcha_widget'" if self.theme == 'custom' else "'") + " }; </script>\n" | ||
return mark_safe(recaptcha_options + recaptcha.displayhtml(self.public_key)) | ||
|
||
|
||
class RecaptchaChallenge(forms.Widget): | ||
is_hidden = True | ||
def render(self, *args, **kwargs): | ||
return "" | ||
# return mark_safe('') | ||
|
||
|
||
|
||
# Honeypot widget -- most automated spam posters will check any checkbox | ||
# assuming it's an "I accept terms and conditions" box | ||
class HoneypotWidget(forms.CheckboxInput): | ||
is_hidden = True | ||
def render(self, *args, **kwargs): | ||
wrapper_html = '<div style="display:none"><label for="id_accept_terms">' + _('Are you a robot?') + '</label>%s</div>' | ||
return mark_safe(wrapper_html % super(HoneypotWidget, self).render(*args, **kwargs)) |