Fixed #5730: Conditionally escape widget contents in newforms to avoid
inadvertent double-escaping. This still isn't perfect behaviour (since it's unaware of the current context's auto-escaping setting), but that's a larger problem that needs fixing and this change at least makes the existing behaviour consistent. Patch from SmileyChris. git-svn-id: http://code.djangoproject.com/svn/django/trunk@6722 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
dc716112a7
commit
1c87a7bb58
|
@ -11,7 +11,7 @@ import copy
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape, conditional_escape
|
||||||
from django.utils.translation import ugettext
|
from django.utils.translation import ugettext
|
||||||
from django.utils.encoding import StrAndUnicode, force_unicode
|
from django.utils.encoding import StrAndUnicode, force_unicode
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
@ -155,7 +155,7 @@ class Textarea(Widget):
|
||||||
value = force_unicode(value)
|
value = force_unicode(value)
|
||||||
final_attrs = self.build_attrs(attrs, name=name)
|
final_attrs = self.build_attrs(attrs, name=name)
|
||||||
return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
|
return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
|
||||||
escape(value)))
|
conditional_escape(force_unicode(value))))
|
||||||
|
|
||||||
class DateTimeInput(Input):
|
class DateTimeInput(Input):
|
||||||
input_type = 'text'
|
input_type = 'text'
|
||||||
|
@ -217,7 +217,9 @@ class Select(Widget):
|
||||||
for option_value, option_label in chain(self.choices, choices):
|
for option_value, option_label in chain(self.choices, choices):
|
||||||
option_value = force_unicode(option_value)
|
option_value = force_unicode(option_value)
|
||||||
selected_html = (option_value == str_value) and u' selected="selected"' or ''
|
selected_html = (option_value == str_value) and u' selected="selected"' or ''
|
||||||
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(force_unicode(option_label))))
|
output.append(u'<option value="%s"%s>%s</option>' % (
|
||||||
|
escape(option_value), selected_html,
|
||||||
|
conditional_escape(force_unicode(option_label))))
|
||||||
output.append(u'</select>')
|
output.append(u'</select>')
|
||||||
return mark_safe(u'\n'.join(output))
|
return mark_safe(u'\n'.join(output))
|
||||||
|
|
||||||
|
@ -254,7 +256,9 @@ class SelectMultiple(Widget):
|
||||||
for option_value, option_label in chain(self.choices, choices):
|
for option_value, option_label in chain(self.choices, choices):
|
||||||
option_value = force_unicode(option_value)
|
option_value = force_unicode(option_value)
|
||||||
selected_html = (option_value in str_values) and ' selected="selected"' or ''
|
selected_html = (option_value in str_values) and ' selected="selected"' or ''
|
||||||
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(force_unicode(option_label))))
|
output.append(u'<option value="%s"%s>%s</option>' % (
|
||||||
|
escape(option_value), selected_html,
|
||||||
|
conditional_escape(force_unicode(option_label))))
|
||||||
output.append(u'</select>')
|
output.append(u'</select>')
|
||||||
return mark_safe(u'\n'.join(output))
|
return mark_safe(u'\n'.join(output))
|
||||||
|
|
||||||
|
@ -278,7 +282,7 @@ class RadioInput(StrAndUnicode):
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return mark_safe(u'<label>%s %s</label>' % (self.tag(),
|
return mark_safe(u'<label>%s %s</label>' % (self.tag(),
|
||||||
self.choice_label))
|
conditional_escape(force_unicode(self.choice_label))))
|
||||||
|
|
||||||
def is_checked(self):
|
def is_checked(self):
|
||||||
return self.value == self.choice_value
|
return self.value == self.choice_value
|
||||||
|
@ -363,7 +367,8 @@ class CheckboxSelectMultiple(SelectMultiple):
|
||||||
cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
|
cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
|
||||||
option_value = force_unicode(option_value)
|
option_value = force_unicode(option_value)
|
||||||
rendered_cb = cb.render(name, option_value)
|
rendered_cb = cb.render(name, option_value)
|
||||||
output.append(u'<li><label>%s %s</label></li>' % (rendered_cb, escape(force_unicode(option_label))))
|
output.append(u'<li><label>%s %s</label></li>' % (rendered_cb,
|
||||||
|
conditional_escape(force_unicode(option_label))))
|
||||||
output.append(u'</ul>')
|
output.append(u'</ul>')
|
||||||
return mark_safe(u'\n'.join(output))
|
return mark_safe(u'\n'.join(output))
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
tests = r"""
|
tests = r"""
|
||||||
>>> from django.newforms import *
|
>>> from django.newforms import *
|
||||||
>>> from django.newforms.widgets import RadioFieldRenderer
|
>>> from django.newforms.widgets import RadioFieldRenderer
|
||||||
|
>>> from django.utils.safestring import mark_safe
|
||||||
>>> import datetime
|
>>> import datetime
|
||||||
>>> import time
|
>>> import time
|
||||||
>>> import re
|
>>> import re
|
||||||
|
@ -205,6 +206,8 @@ u'<textarea rows="10" cols="40" name="msg"></textarea>'
|
||||||
u'<textarea rows="10" cols="40" name="msg">value</textarea>'
|
u'<textarea rows="10" cols="40" name="msg">value</textarea>'
|
||||||
>>> w.render('msg', 'some "quoted" & ampersanded value')
|
>>> w.render('msg', 'some "quoted" & ampersanded value')
|
||||||
u'<textarea rows="10" cols="40" name="msg">some "quoted" & ampersanded value</textarea>'
|
u'<textarea rows="10" cols="40" name="msg">some "quoted" & ampersanded value</textarea>'
|
||||||
|
>>> w.render('msg', mark_safe('pre "quoted" value'))
|
||||||
|
u'<textarea rows="10" cols="40" name="msg">pre "quoted" value</textarea>'
|
||||||
>>> w.render('msg', 'value', attrs={'class': 'pretty', 'rows': 20})
|
>>> w.render('msg', 'value', attrs={'class': 'pretty', 'rows': 20})
|
||||||
u'<textarea class="pretty" rows="20" cols="40" name="msg">value</textarea>'
|
u'<textarea class="pretty" rows="20" cols="40" name="msg">value</textarea>'
|
||||||
|
|
||||||
|
@ -375,6 +378,17 @@ If 'choices' is passed to both the constructor and render(), then they'll both b
|
||||||
<option value="5">5</option>
|
<option value="5">5</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
# Choices are escaped correctly
|
||||||
|
>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you > me'))))
|
||||||
|
<select name="escape">
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="2">2</option>
|
||||||
|
<option value="3">3</option>
|
||||||
|
<option value="bad">you & me</option>
|
||||||
|
<option value="good">you > me</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
# Unicode choices are correctly rendered as HTML
|
||||||
>>> w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
|
>>> w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
|
||||||
u'<select name="email">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>'
|
u'<select name="email">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>'
|
||||||
|
|
||||||
|
@ -538,6 +552,17 @@ If 'choices' is passed to both the constructor and render(), then they'll both b
|
||||||
<option value="5">5</option>
|
<option value="5">5</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
# Choices are escaped correctly
|
||||||
|
>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you > me'))))
|
||||||
|
<select multiple="multiple" name="escape">
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="2">2</option>
|
||||||
|
<option value="3">3</option>
|
||||||
|
<option value="bad">you & me</option>
|
||||||
|
<option value="good">you > me</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
# Unicode choices are correctly rendered as HTML
|
||||||
>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
|
>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
|
||||||
u'<select multiple="multiple" name="nums">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>'
|
u'<select multiple="multiple" name="nums">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>'
|
||||||
|
|
||||||
|
@ -692,6 +717,14 @@ Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
IndexError: list index out of range
|
IndexError: list index out of range
|
||||||
|
|
||||||
|
# Choices are escaped correctly
|
||||||
|
>>> w = RadioSelect()
|
||||||
|
>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you > me'))))
|
||||||
|
<ul>
|
||||||
|
<li><label><input type="radio" name="escape" value="bad" /> you & me</label></li>
|
||||||
|
<li><label><input type="radio" name="escape" value="good" /> you > me</label></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
# Unicode choices are correctly rendered as HTML
|
# Unicode choices are correctly rendered as HTML
|
||||||
>>> w = RadioSelect()
|
>>> w = RadioSelect()
|
||||||
>>> unicode(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]))
|
>>> unicode(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]))
|
||||||
|
@ -821,6 +854,17 @@ If 'choices' is passed to both the constructor and render(), then they'll both b
|
||||||
<li><label><input type="checkbox" name="nums" value="5" /> 5</label></li>
|
<li><label><input type="checkbox" name="nums" value="5" /> 5</label></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
# Choices are escaped correctly
|
||||||
|
>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you > me'))))
|
||||||
|
<ul>
|
||||||
|
<li><label><input type="checkbox" name="escape" value="1" /> 1</label></li>
|
||||||
|
<li><label><input type="checkbox" name="escape" value="2" /> 2</label></li>
|
||||||
|
<li><label><input type="checkbox" name="escape" value="3" /> 3</label></li>
|
||||||
|
<li><label><input type="checkbox" name="escape" value="bad" /> you & me</label></li>
|
||||||
|
<li><label><input type="checkbox" name="escape" value="good" /> you > me</label></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
# Unicode choices are correctly rendered as HTML
|
||||||
>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
|
>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
|
||||||
u'<ul>\n<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>\n<li><label><input type="checkbox" name="nums" value="2" /> 2</label></li>\n<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>\n<li><label><input checked="checked" type="checkbox" name="nums" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="checkbox" name="nums" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>'
|
u'<ul>\n<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>\n<li><label><input type="checkbox" name="nums" value="2" /> 2</label></li>\n<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>\n<li><label><input checked="checked" type="checkbox" name="nums" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="checkbox" name="nums" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue