import re from captcha.fields import CaptchaField from django import forms from django.forms.util import ErrorList from django.utils.translation import ugettext_lazy as _ import time from boards.models import TITLE_MAX_LENGTH, User from neboard import settings from boards import utils LAST_POST_TIME = "last_post_time" LAST_LOGIN_TIME = "last_login_time" LOGIN_DELAY = 60 * 60 MAX_TEXT_LENGTH = 30000 MAX_IMAGE_SIZE = 8 * 1024 * 1024 class PlainErrorList(ErrorList): def __unicode__(self): return self.as_text() def as_text(self): return ''.join([u'(!) %s ' % e for e in self]) class NeboardForm(forms.Form): def as_p(self): "Returns this form rendered as HTML

s." return self._html_output( normal_row='

' '
' '%(label)s' '
' '
' '%(field)s' '
' '%(help_text)s' '
', error_row='
%s
', row_ender='

', help_text_html=' %s', errors_on_separate_row=True) class PostForm(NeboardForm): title = forms.CharField(max_length=TITLE_MAX_LENGTH, required=False) text = forms.CharField(widget=forms.Textarea, required=False) image = forms.ImageField(required=False) # This field is for spam prevention only email = forms.CharField(max_length=100, required=False) session = None def clean_title(self): title = self.cleaned_data['title'] if title: if len(title) > TITLE_MAX_LENGTH: raise forms.ValidationError(_('Title must have less than %s ' 'characters') % str(TITLE_MAX_LENGTH)) return title def clean_text(self): text = self.cleaned_data['text'] if text: if len(text) > MAX_TEXT_LENGTH: raise forms.ValidationError(_('Text must have less than %s ' 'characters') % str(MAX_TEXT_LENGTH)) return text def clean_image(self): image = self.cleaned_data['image'] if image: if image._size > MAX_IMAGE_SIZE: raise forms.ValidationError(_('Image must be less than %s ' 'bytes') % str(MAX_IMAGE_SIZE)) return image def clean(self): cleaned_data = super(PostForm, self).clean() if not self.session: raise forms.ValidationError('Humans have sessions') if cleaned_data['email']: raise forms.ValidationError('A human cannot enter a hidden field') if not self.errors: self._clean_text_image() if not self.errors and self.session: self._validate_posting_speed() return cleaned_data def _clean_text_image(self): text = self.cleaned_data.get('text') image = self.cleaned_data.get('image') if (not text) and (not image): error_message = _('Either text or image must be entered.') self._errors['text'] = self.error_class([error_message]) def _validate_posting_speed(self): can_post = True if LAST_POST_TIME in self.session: now = time.time() last_post_time = self.session[LAST_POST_TIME] current_delay = int(now - last_post_time) if current_delay < settings.POSTING_DELAY: error_message = _('Wait %s seconds after last posting') % str( settings.POSTING_DELAY - current_delay) self._errors['text'] = self.error_class([error_message]) can_post = False if can_post: self.session[LAST_POST_TIME] = time.time() class ThreadForm(PostForm): regex_tags = re.compile(ur'^[\w\s\d]+$', re.UNICODE) tags = forms.CharField(max_length=100) def clean_tags(self): tags = self.cleaned_data['tags'] if tags: if not self.regex_tags.match(tags): raise forms.ValidationError( _('Inappropriate characters in tags.')) return tags def clean(self): cleaned_data = super(ThreadForm, self).clean() return cleaned_data class PostCaptchaForm(PostForm): captcha = CaptchaField() def __init__(self, *args, **kwargs): self.request = kwargs['request'] del kwargs['request'] super(PostCaptchaForm, self).__init__(*args, **kwargs) def clean(self): cleaned_data = super(PostCaptchaForm, self).clean() success = self.is_valid() utils.update_captcha_access(self.request, success) if success: return cleaned_data else: raise forms.ValidationError(_("Captcha validation failed")) class ThreadCaptchaForm(ThreadForm): captcha = CaptchaField() def __init__(self, *args, **kwargs): self.request = kwargs['request'] del kwargs['request'] super(ThreadCaptchaForm, self).__init__(*args, **kwargs) def clean(self): cleaned_data = super(ThreadCaptchaForm, self).clean() success = self.is_valid() utils.update_captcha_access(self.request, success) if success: return cleaned_data else: raise forms.ValidationError(_("Captcha validation failed")) class SettingsForm(NeboardForm): theme = forms.ChoiceField(choices=settings.THEMES, label=_('Theme')) class ModeratorSettingsForm(SettingsForm): moderate = forms.BooleanField(required=False, label=_('Enable moderation ' 'panel')) class LoginForm(NeboardForm): user_id = forms.CharField() session = None def clean_user_id(self): user_id = self.cleaned_data['user_id'] if user_id: users = User.objects.filter(user_id=user_id) if len(users) == 0: raise forms.ValidationError(_('No such user found')) return user_id def _validate_login_speed(self): can_post = True if LAST_LOGIN_TIME in self.session: now = time.time() last_login_time = self.session[LAST_LOGIN_TIME] current_delay = int(now - last_login_time) if current_delay < LOGIN_DELAY: error_message = _('Wait %s minutes after last login') % str( (LOGIN_DELAY - current_delay) / 60) self._errors['user_id'] = self.error_class([error_message]) can_post = False if can_post: self.session[LAST_LOGIN_TIME] = time.time() def clean(self): if not self.session: raise forms.ValidationError('Humans have sessions') self._validate_login_speed() cleaned_data = super(LoginForm, self).clean() return cleaned_data