Skip to content

Commit

Permalink
included glamkit-stopspam for simplicity
Browse files Browse the repository at this point in the history
  • Loading branch information
maccesch committed Jul 22, 2011
1 parent 6527de3 commit 7846a38
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 3 deletions.
2 changes: 1 addition & 1 deletion README.rst
Expand Up @@ -53,7 +53,7 @@ Unzip the file you downloaded. Then go in your terminal and ``cd`` into the unpa
Setup
-----

Put ``"cmsplugin_contact"`` in your ``INSTALLED_APPS`` section in settings.py. Don't forget to syncdb your database or migrate if you're using South.
Put ``'cmsplugin_contact'`` in your ``INSTALLED_APPS`` section in settings.py. Don't forget to syncdb your database or migrate if you're using South.

Settings
========
Expand Down
2 changes: 1 addition & 1 deletion cmsplugin_contact/forms.py
@@ -1,6 +1,6 @@
from django import forms
#import settings
from stopspam.forms import HoneyPotForm, RecaptchaForm, AkismetForm
from nospam.forms import HoneyPotForm, RecaptchaForm, AkismetForm

class HoneyPotContactForm(HoneyPotForm):
email = forms.EmailField()
Expand Down
2 changes: 1 addition & 1 deletion cmsplugin_contact/models.py
@@ -1,6 +1,6 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from cms.models.pluginmodel import CMSPlugin
from cms.models import CMSPlugin

class Contact(CMSPlugin):
SPAM_PROTECTION_CHOICES = (
Expand Down
5 changes: 5 additions & 0 deletions cmsplugin_contact/nospam/__init__.py
@@ -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
20 changes: 20 additions & 0 deletions cmsplugin_contact/nospam/fields.py
@@ -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
106 changes: 106 additions & 0 deletions cmsplugin_contact/nospam/forms.py
@@ -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
49 changes: 49 additions & 0 deletions cmsplugin_contact/nospam/utils.py
@@ -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
31 changes: 31 additions & 0 deletions cmsplugin_contact/nospam/widgets.py
@@ -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))

0 comments on commit 7846a38

Please sign in to comment.