Fixed #6948 -- The join filter was escaping the literal value that was

passed in for the connector. This was contrary to what the documentation
for autoescaping said and to what every other filter does with literal
strings as arguments.

This is backwards incompatible for the situation of the literal string
containing one of the five special HTML characters: if you were writing
{{ foo|join:"&" }}, you now have to write {{ foo| join:"&" }}.
Previous behaviour was, as noted, a bug and contrary to what was
documented and expected.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@9442 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2008-11-15 01:16:20 +00:00
parent bca14cd3c8
commit 0349d83289
2 changed files with 24 additions and 18 deletions

View File

@ -99,10 +99,10 @@ fix_ampersands = stringfilter(fix_ampersands)
# Values for testing floatformat input against infinity and NaN representations, # Values for testing floatformat input against infinity and NaN representations,
# which differ across platforms and Python versions. Some (i.e. old Windows # which differ across platforms and Python versions. Some (i.e. old Windows
# ones) are not recognized by Decimal but we want to return them unchanged vs. # ones) are not recognized by Decimal but we want to return them unchanged vs.
# returning an empty string as we do for completley invalid input. Note these # returning an empty string as we do for completley invalid input. Note these
# need to be built up from values that are not inf/nan, since inf/nan values do # need to be built up from values that are not inf/nan, since inf/nan values do
# not reload properly from .pyc files on Windows prior to some level of Python 2.5 # not reload properly from .pyc files on Windows prior to some level of Python 2.5
# (see Python Issue757815 and Issue1080440). # (see Python Issue757815 and Issue1080440).
pos_inf = 1e200 * 1e200 pos_inf = 1e200 * 1e200
neg_inf = -1e200 * 1e200 neg_inf = -1e200 * 1e200
@ -136,11 +136,11 @@ def floatformat(text, arg=-1):
* {{ num1|floatformat:"-3" }} displays "34.232" * {{ num1|floatformat:"-3" }} displays "34.232"
* {{ num2|floatformat:"-3" }} displays "34" * {{ num2|floatformat:"-3" }} displays "34"
* {{ num3|floatformat:"-3" }} displays "34.260" * {{ num3|floatformat:"-3" }} displays "34.260"
If the input float is infinity or NaN, the (platform-dependent) string If the input float is infinity or NaN, the (platform-dependent) string
representation of that value will be displayed. representation of that value will be displayed.
""" """
try: try:
input_val = force_unicode(text) input_val = force_unicode(text)
d = Decimal(input_val) d = Decimal(input_val)
@ -155,15 +155,15 @@ def floatformat(text, arg=-1):
p = int(arg) p = int(arg)
except ValueError: except ValueError:
return input_val return input_val
try: try:
m = int(d) - d m = int(d) - d
except (OverflowError, InvalidOperation): except (OverflowError, InvalidOperation):
return input_val return input_val
if not m and p < 0: if not m and p < 0:
return mark_safe(u'%d' % (int(d))) return mark_safe(u'%d' % (int(d)))
if p == 0: if p == 0:
exp = Decimal(1) exp = Decimal(1)
else: else:
@ -481,19 +481,20 @@ def first(value):
return u'' return u''
first.is_safe = False first.is_safe = False
def join(value, arg): def join(value, arg, autoescape=None):
"""Joins a list with a string, like Python's ``str.join(list)``.""" """
Joins a list with a string, like Python's ``str.join(list)``.
"""
if autoescape:
from django.utils.html import conditional_escape
value = [conditional_escape(v) for v in value]
try: try:
data = arg.join(map(force_unicode, value)) data = arg.join(value)
except AttributeError: # fail silently but nicely except AttributeError: # fail silently but nicely
return value return value
safe_args = reduce(lambda lhs, rhs: lhs and isinstance(rhs, SafeData), return mark_safe(data)
value, True)
if safe_args:
return mark_safe(data)
else:
return data
join.is_safe = True join.is_safe = True
join.needs_autoescape = True
def last(value): def last(value):
"Returns the last item in a list" "Returns the last item in a list"

View File

@ -277,9 +277,14 @@ def get_filter_tests():
'escapejs01': (r'{{ a|escapejs }}', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'}, 'testing\\x0D\\x0Ajavascript \\x27string\\x22 \\x3Cb\\x3Eescaping\\x3C/b\\x3E'), 'escapejs01': (r'{{ a|escapejs }}', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'}, 'testing\\x0D\\x0Ajavascript \\x27string\\x22 \\x3Cb\\x3Eescaping\\x3C/b\\x3E'),
'escapejs02': (r'{% autoescape off %}{{ a|escapejs }}{% endautoescape %}', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'}, 'testing\\x0D\\x0Ajavascript \\x27string\\x22 \\x3Cb\\x3Eescaping\\x3C/b\\x3E'), 'escapejs02': (r'{% autoescape off %}{{ a|escapejs }}{% endautoescape %}', {'a': 'testing\r\njavascript \'string" <b>escaping</b>'}, 'testing\\x0D\\x0Ajavascript \\x27string\\x22 \\x3Cb\\x3Eescaping\\x3C/b\\x3E'),
# Boolean return value from length_is should not be coerced to a string # Boolean return value from length_is should not be coerced to a string
'lengthis01': (r'{% if "X"|length_is:0 %}Length is 0{% else %}Length not 0{% endif %}', {}, 'Length not 0'), 'lengthis01': (r'{% if "X"|length_is:0 %}Length is 0{% else %}Length not 0{% endif %}', {}, 'Length not 0'),
'lengthis02': (r'{% if "X"|length_is:1 %}Length is 1{% else %}Length not 1{% endif %}', {}, 'Length is 1'), 'lengthis02': (r'{% if "X"|length_is:1 %}Length is 1{% else %}Length not 1{% endif %}', {}, 'Length is 1'),
'join01': (r'{{ a|join:", " }}', {'a': ['alpha', 'beta & me']}, 'alpha, beta &amp; me'),
'join02': (r'{% autoescape off %}{{ a|join:", " }}{% endautoescape %}', {'a': ['alpha', 'beta & me']}, 'alpha, beta & me'),
'join03': (r'{{ a|join:" &amp; " }}', {'a': ['alpha', 'beta & me']}, 'alpha &amp; beta &amp; me'),
'join04': (r'{% autoescape off %}{{ a|join:" &amp; " }}{% endautoescape %}', {'a': ['alpha', 'beta & me']}, 'alpha &amp; beta & me'),
} }