From 0c4ea9b922206219c73a0de18620b79f2b24b5e1 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Sun, 3 Feb 2008 08:54:26 +0000 Subject: [PATCH] Fixed #6279, #6514 -- Fixed some HTML escaping problems in the urlize filter. Based on a patch from SmileyChris with some test additions from Rob Hudson. Thanks, both. git-svn-id: http://code.djangoproject.com/svn/django/trunk@7079 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/utils/html.py | 23 +++++++++++++--------- tests/regressiontests/templates/filters.py | 14 ++++++++----- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/django/utils/html.py b/django/utils/html.py index 33e2ee3856..17ff78a2b5 100644 --- a/django/utils/html.py +++ b/django/utils/html.py @@ -102,18 +102,23 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False): if middle.startswith('www.') or ('@' not in middle and not middle.startswith('http://') and \ len(middle) > 0 and middle[0] in string.ascii_letters + string.digits and \ (middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))): - middle = '%s' % ( - urlquote(middle, safe='/&=:;#?+'), nofollow_attr, - trim_url(middle)) + middle = 'http://%s' % middle if middle.startswith('http://') or middle.startswith('https://'): - middle = '%s' % ( - urlquote(middle, safe='/&=:;#?+'), nofollow_attr, - trim_url(middle)) - if '@' in middle and not middle.startswith('www.') and \ - not ':' in middle and simple_email_re.match(middle): + url = urlquote(middle, safe='/&=:;#?+*') + if autoescape and not safe_input: + url = escape(url) + trimmed_url = trim_url(middle) + middle = '%s' % (url, nofollow_attr, + trimmed_url) + elif '@' in middle and not middle.startswith('www.') and \ + not ':' in middle and simple_email_re.match(middle): + if autoescape: + middle = conditional_escape(middle) middle = '%s' % (middle, middle) if lead + middle + trail != word: - words[i] = lead + middle + trail + if autoescape and not safe_input: + lead, trail = escape(lead), escape(trail) + words[i] = mark_safe('%s%s%s' % (lead, middle, trail)) elif autoescape and not safe_input: words[i] = escape(word) elif safe_input: diff --git a/tests/regressiontests/templates/filters.py b/tests/regressiontests/templates/filters.py index fd73dc57ba..c780a64baf 100644 --- a/tests/regressiontests/templates/filters.py +++ b/tests/regressiontests/templates/filters.py @@ -98,8 +98,8 @@ def get_filter_tests(): 'filter-upper01': ('{% autoescape off %}{{ a|upper }} {{ b|upper }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a & b")}, u"A & B A & B"), 'filter-upper02': ('{{ a|upper }} {{ b|upper }}', {"a": "a & b", "b": mark_safe("a & b")}, u"A & B A &AMP; B"), - 'filter-urlize01': ('{% autoescape off %}{{ a|urlize }} {{ b|urlize }}{% endautoescape %}', {"a": "http://example.com/x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'http://example.com/x=&y= http://example.com?x=&y='), - 'filter-urlize02': ('{{ a|urlize }} {{ b|urlize }}', {"a": "http://example.com/x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'http://example.com/x=&y= http://example.com?x=&y='), + 'filter-urlize01': ('{% autoescape off %}{{ a|urlize }} {{ b|urlize }}{% endautoescape %}', {"a": "http://example.com/?x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'http://example.com/?x=&y= http://example.com?x=&y='), + 'filter-urlize02': ('{{ a|urlize }} {{ b|urlize }}', {"a": "http://example.com/?x=&y=", "b": mark_safe("http://example.com?x=&y=")}, u'http://example.com/?x=&y= http://example.com?x=&y='), 'filter-urlize03': ('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": mark_safe("a & b")}, 'a & b'), 'filter-urlize04': ('{{ a|urlize }}', {"a": mark_safe("a & b")}, 'a & b'), @@ -108,8 +108,12 @@ def get_filter_tests(): 'filter-urlize05': ('{% autoescape off %}{{ a|urlize }}{% endautoescape %}', {"a": ""}, ""), 'filter-urlize06': ('{{ a|urlize }}', {"a": ""}, '<script>alert('foo')</script>'), - 'filter-urlizetrunc01': ('{% autoescape off %}{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}{% endautoescape %}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('"Safe" http://example.com?x=&y=')}, u'"Unsafe" http:... "Safe" http:...'), - 'filter-urlizetrunc02': ('{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('"Safe" http://example.com?x=&y=')}, u'"Unsafe" http:... "Safe" http:...'), + # mailto: testing for urlize + 'filter-urlize07': ('{{ a|urlize }}', {"a": "Email me at me@example.com"}, 'Email me at me@example.com'), + 'filter-urlize08': ('{{ a|urlize }}', {"a": "Email me at "}, 'Email me at <me@example.com>'), + + 'filter-urlizetrunc01': ('{% autoescape off %}{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}{% endautoescape %}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('"Safe" http://example.com?x=&y=')}, u'"Unsafe" http:... "Safe" http:...'), + 'filter-urlizetrunc02': ('{{ a|urlizetrunc:"8" }} {{ b|urlizetrunc:"8" }}', {"a": '"Unsafe" http://example.com/x=&y=', "b": mark_safe('"Safe" http://example.com?x=&y=')}, u'"Unsafe" http:... "Safe" http:...'), 'filter-wordcount01': ('{% autoescape off %}{{ a|wordcount }} {{ b|wordcount }}{% endautoescape %}', {"a": "a & b", "b": mark_safe("a & b")}, "3 3"), 'filter-wordcount02': ('{{ a|wordcount }} {{ b|wordcount }}', {"a": "a & b", "b": mark_safe("a & b")}, "3 3"), @@ -240,7 +244,7 @@ def get_filter_tests(): 'chaining13': ('{{ a|safe|force_escape }}', {"a": "a < b"}, "a < b"), 'chaining14': ('{% autoescape off %}{{ a|safe|force_escape }}{% endautoescape %}', {"a": "a < b"}, "a < b"), - # Filters decorated with stringfilter still respect is_safe. + # Filters decorated with stringfilter still respect is_safe. 'autoescape-stringfilter01': (r'{{ unsafe|capfirst }}', {'unsafe': UnsafeClass()}, 'You & me'), 'autoescape-stringfilter02': (r'{% autoescape off %}{{ unsafe|capfirst }}{% endautoescape %}', {'unsafe': UnsafeClass()}, 'You & me'), 'autoescape-stringfilter03': (r'{{ safe|capfirst }}', {'safe': SafeClass()}, 'You > me'),