2012-04-25 22:29:19 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2013-03-11 22:38:39 +01:00
|
|
|
import bleach
|
2012-07-10 13:19:12 +02:00
|
|
|
from django import forms
|
2013-09-25 10:01:01 +02:00
|
|
|
from django.utils.translation import ugettext as _
|
|
|
|
from django.utils.translation import ugettext_lazy
|
2012-07-10 13:19:12 +02:00
|
|
|
|
2013-03-11 22:38:39 +01:00
|
|
|
# Allowed tags, attributes and styles allowed in textareas edited with a JS
|
|
|
|
# editor. Everything not in these whitelists is stripped.
|
|
|
|
HTML_TAG_WHITELIST = ('a',
|
|
|
|
'i',
|
2013-04-16 10:04:28 +02:00
|
|
|
'em',
|
2013-03-11 22:38:39 +01:00
|
|
|
'b',
|
2013-04-16 10:04:28 +02:00
|
|
|
'strong',
|
2013-03-11 22:38:39 +01:00
|
|
|
'ul',
|
|
|
|
'ol',
|
|
|
|
'li',
|
|
|
|
'p',
|
|
|
|
'br',
|
|
|
|
'span',
|
|
|
|
'strike',
|
|
|
|
'u',
|
|
|
|
'pre',
|
|
|
|
'h1',
|
|
|
|
'h2',
|
|
|
|
'h3',)
|
|
|
|
|
|
|
|
HTML_ATTRIBUTES_WHITELIST = {
|
|
|
|
'a': ['href'],
|
2013-11-09 22:32:52 +01:00
|
|
|
'*': ['style'],
|
2013-03-11 22:38:39 +01:00
|
|
|
}
|
|
|
|
|
2013-11-09 22:32:52 +01:00
|
|
|
HTML_STYLES_WHITELIST = ('color', 'background-color', 'list-style')
|
2013-03-11 22:38:39 +01:00
|
|
|
|
|
|
|
|
2012-02-20 18:44:38 +01:00
|
|
|
class CssClassMixin(object):
|
|
|
|
error_css_class = 'error'
|
|
|
|
required_css_class = 'required'
|
2012-07-10 13:19:12 +02:00
|
|
|
|
|
|
|
|
2013-06-09 16:41:58 +02:00
|
|
|
class LocalizedModelChoiceField(forms.ModelChoiceField):
|
|
|
|
"""
|
|
|
|
Subclass of Django's ModelChoiceField to translate the labels of the
|
|
|
|
model's objects.
|
|
|
|
"""
|
|
|
|
def label_from_instance(self, *args, **kwargs):
|
|
|
|
"""
|
|
|
|
Translates the output from Django's label_from_instance method.
|
|
|
|
"""
|
|
|
|
return _(super(LocalizedModelChoiceField, self).label_from_instance(*args, **kwargs))
|
|
|
|
|
|
|
|
|
2012-07-10 13:19:12 +02:00
|
|
|
class LocalizedModelMultipleChoiceField(forms.ModelMultipleChoiceField):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
self.to_field_name = kwargs.get('to_field_name', None)
|
|
|
|
super(LocalizedModelMultipleChoiceField, self).__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
def _localized_get_choices(self):
|
|
|
|
if hasattr(self, '_choices'):
|
|
|
|
return self._choices
|
|
|
|
|
|
|
|
c = []
|
|
|
|
for (id, text) in super(LocalizedModelMultipleChoiceField, self)._get_choices():
|
|
|
|
text = text.split(' | ')[-1]
|
2013-04-16 10:04:28 +02:00
|
|
|
c.append((id, ugettext_lazy(text)))
|
2012-07-10 13:19:12 +02:00
|
|
|
return c
|
|
|
|
|
|
|
|
choices = property(_localized_get_choices, forms.ChoiceField._set_choices)
|
2013-03-11 22:38:39 +01:00
|
|
|
|
|
|
|
|
2013-04-16 10:04:28 +02:00
|
|
|
class CleanHtmlFormMixin(object):
|
|
|
|
"""
|
2013-03-11 22:38:39 +01:00
|
|
|
A form mixin that pre-processes the form, cleaning up the HTML code found
|
|
|
|
in the fields in clean_html. All HTML tags, attributes and styles not in the
|
|
|
|
whitelists are stripped from the output, leaving only the text content:
|
|
|
|
|
|
|
|
<table><tr><td>foo</td></tr></table> simply becomes 'foo'
|
2013-04-16 10:04:28 +02:00
|
|
|
"""
|
|
|
|
clean_html_fields = ()
|
2013-03-11 22:38:39 +01:00
|
|
|
|
|
|
|
def get_clean_html_fields(self):
|
2013-04-16 10:04:28 +02:00
|
|
|
"""
|
|
|
|
The list of elements to strip of potential malicious HTML.
|
|
|
|
"""
|
|
|
|
return self.clean_html_fields
|
2013-03-11 22:38:39 +01:00
|
|
|
|
|
|
|
def clean(self):
|
|
|
|
cleaned_data = super(CleanHtmlFormMixin, self).clean()
|
2013-04-15 21:12:29 +02:00
|
|
|
for field in self.get_clean_html_fields():
|
2013-04-28 10:19:05 +02:00
|
|
|
try:
|
|
|
|
cleaned_data[field] = bleach.clean(
|
|
|
|
cleaned_data[field],
|
|
|
|
tags=HTML_TAG_WHITELIST,
|
|
|
|
attributes=HTML_ATTRIBUTES_WHITELIST,
|
|
|
|
styles=HTML_STYLES_WHITELIST,
|
|
|
|
strip=True)
|
|
|
|
except KeyError:
|
|
|
|
# The field 'field' is not pressent. Do not change cleaned_data
|
|
|
|
pass
|
2013-03-11 22:38:39 +01:00
|
|
|
return cleaned_data
|