Ticket #13704: 13704-4.patch

File 13704-4.patch, 4.1 KB (added by Aymeric Augustin, 13 years ago)
  • django/utils/html.py

     
    22
    33import re
    44import string
     5import urlparse
    56
    67from django.utils.safestring import SafeData, mark_safe
    78from django.utils.encoding import force_unicode
     
    2223punctuation_re = re.compile('^(?P<lead>(?:%s)*)(?P<middle>.*?)(?P<trail>(?:%s)*)$' % \
    2324    ('|'.join([re.escape(x) for x in LEADING_PUNCTUATION]),
    2425    '|'.join([re.escape(x) for x in TRAILING_PUNCTUATION])))
    25 simple_email_re = re.compile(r'^\S+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+$')
     26simple_email_re = re.compile(r'^\S+@\S+\.\S+$')
    2627link_target_attribute_re = re.compile(r'(<a [^>]*?)target=[^\s>]+')
    2728html_gunk_re = re.compile(r'(?:<br clear="all">|<i><\/i>|<b><\/b>|<em><\/em>|<strong><\/strong>|<\/?smallcaps>|<\/?uppercase>)', re.IGNORECASE)
    2829hard_coded_bullets_re = re.compile(r'((?:<p>(?:%s).*?[a-zA-Z].*?</p>\s*)+)' % '|'.join([re.escape(x) for x in DOTS]), re.DOTALL)
     
    103104
    104105def smart_urlquote(url):
    105106    """Quotes an URL if it isn't already quoted."""
     107    # Handle IDN first
     108    scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
     109    try:
     110        netloc = netloc.encode('idna') # IDN -> ACE
     111    except UnicodeError: # invalid domain part
     112        pass
     113    else:
     114        url = urlparse.urlunsplit((scheme, netloc, path, query, fragment))
     115
    106116    # An URL is considered unquoted if it contains no % character, or if it
    107117    # contains a % not followed by two hexadecimal digits. See #9655.
    108118    if '%' not in url or unquoted_percents_re.search(url):
    109119        # See http://bugs.python.org/issue2637
    110         return urlquote(url, safe='!*\'();:@&=+$,/?#[]~')
     120        url = urlquote(url, safe='!*\'();:@&=+$,/?#[]~')
     121
    111122    return url
    112123
    113124def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
     
    145156                    middle and middle[0] in string.ascii_letters + string.digits and \
    146157                    (middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))):
    147158                url = smart_urlquote('http://%s' % middle)
    148             elif '@' in middle and not ':' in middle and simple_email_re.match(middle):
    149                 url = 'mailto:%s' % middle
     159            elif not ':' in middle and simple_email_re.match(middle):
     160                local, domain = middle.rsplit('@', 1)
     161                domain = domain.encode('idna')
     162                url = 'mailto:%s@%s' % (local, domain)
    150163                nofollow_attr = ''
    151164            # Make link.
    152165            if url:
  • tests/regressiontests/defaultfilters/tests.py

     
    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
    241242        # Check urlize doesn't overquote already quoted urls - see #9655
    242243        self.assertEqual(urlize('http://hi.baidu.com/%D6%D8%D0%C2%BF'),
    243244            u'<a href="http://hi.baidu.com/%D6%D8%D0%C2%BF" rel="nofollow">'
     
    252253            u'<a href="http://en.wikipedia.org/wiki/Caf%C3%A9" rel="nofollow">'
    253254            u'http://en.wikipedia.org/wiki/Café</a>')
    254255
     256        # Check urlize handles IDN correctly - see #13704
     257        self.assertEqual(urlize('http://c✶.ws'),
     258            u'<a href="http://xn--c-lgq.ws" rel="nofollow">http://c✶.ws</a>')
     259        self.assertEqual(urlize('www.c✶.ws'),
     260            u'<a href="http://www.xn--c-lgq.ws" rel="nofollow">www.c✶.ws</a>')
     261        self.assertEqual(urlize('c✶.org'),
     262            u'<a href="http://xn--c-lgq.org" rel="nofollow">c✶.org</a>')
     263        self.assertEqual(urlize('info@c✶.org'),
     264            u'<a href="mailto:info@xn--c-lgq.org">info@c✶.org</a>')
     265
    255266    def test_wordcount(self):
    256267        self.assertEqual(wordcount(''), 0)
    257268        self.assertEqual(wordcount(u'oneword'), 1)
Back to Top