Ticket #9655: 9655-2.diff

File 9655-2.diff, 3.2 KB (added by Claude Paroz, 13 years ago)

Same patch with test

  • django/utils/html.py

    diff --git a/django/utils/html.py b/django/utils/html.py
    index 2687eb5..4f74a74 100644
    a b TRAILING_PUNCTUATION = ['.', ',', ')', '>', '\n', '>']  
    1717DOTS = [u'·', u'*', u'\u2022', u'•', u'•', u'•']
    1818
    1919unencoded_ampersands_re = re.compile(r'&(?!(\w+|#\d+);)')
     20unquoted_percents_re = re.compile(r'%(?![0-9A-Fa-f]{2})')
    2021word_split_re = re.compile(r'(\s+)')
    2122punctuation_re = re.compile('^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % \
    2223    ('|'.join([re.escape(x) for x in LEADING_PUNCTUATION]),
    def fix_ampersands(value):  
    100101    return unencoded_ampersands_re.sub('&amp;', force_unicode(value))
    101102fix_ampersands = allow_lazy(fix_ampersands, unicode)
    102103
     104def smart_urlquote(url):
     105    """Quotes an URL if it isn't already quoted."""
     106    # An URL is considered unquoted if it contains no % character, or if it
     107    # contains a % not followed by two hexadecimal digits. See #9655.
     108    if '%' not in url or unquoted_percents_re.search(url):
     109        # See http://bugs.python.org/issue2637
     110        return urlquote(url, safe='!*\'();:@&=+$,/?#[]~')
     111    return url
     112
    103113def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
    104114    """
    105115    Converts any URLs in text into clickable links.
    def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):  
    130140            # Make URL we want to point to.
    131141            url = None
    132142            if middle.startswith('http://') or middle.startswith('https://'):
    133                 url = urlquote(middle, safe='/&=:;#?+*')
     143                url = smart_urlquote(middle)
    134144            elif middle.startswith('www.') or ('@' not in middle and \
    135145                    middle and middle[0] in string.ascii_letters + string.digits and \
    136146                    (middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))):
    137                 url = urlquote('http://%s' % middle, safe='/&=:;#?+*')
     147                url = smart_urlquote('http://%s' % middle)
    138148            elif '@' in middle and not ':' in middle and simple_email_re.match(middle):
    139149                url = 'mailto:%s' % middle
    140150                nofollow_attr = ''
  • tests/regressiontests/defaultfilters/tests.py

    diff --git a/tests/regressiontests/defaultfilters/tests.py b/tests/regressiontests/defaultfilters/tests.py
    index 5e8c8f1..b27b1df 100644
    a b class DefaultFiltersTests(TestCase):  
    238238        # Check urlize with https addresses
    239239        self.assertEqual(urlize('https://google.com'),
    240240            u'<a href="https://google.com" rel="nofollow">https://google.com</a>')
     241        # Check urlize doesn't overquote already quoted urls
     242        self.assertEqual(urlize('http://hi.baidu.com/%D6%D8%D0%C2%BF'),
     243            u'<a href="http://hi.baidu.com/%D6%D8%D0%C2%BF" rel="nofollow">'
     244            u'http://hi.baidu.com/%D6%D8%D0%C2%BF</a>')
     245        self.assertEqual(urlize('www.mystore.com/30%OffCoupons!'),
     246            u'<a href="http://www.mystore.com/30%25OffCoupons!" rel="nofollow">'
     247            u'www.mystore.com/30%OffCoupons!</a>')
    241248
    242249    def test_wordcount(self):
    243250        self.assertEqual(wordcount(''), 0)
Back to Top