Fixed #33245 -- Made django.utils.html.urlize() thread-safe.

Regression in e567670b1a.
This commit is contained in:
Timothy McCurrach 2021-10-31 01:00:40 +01:00 committed by Mariusz Felisiak
parent f38458fe56
commit ad81b606a2
1 changed files with 21 additions and 16 deletions

View File

@ -250,17 +250,22 @@ class Urlizer:
If autoescape is True, autoescape the link text and URLs.
"""
self.trim_url_limit = trim_url_limit
self.nofollow = nofollow
self.autoescape = autoescape
self.safe_input = isinstance(text, SafeData)
safe_input = isinstance(text, SafeData)
words = self.word_split_re.split(str(text))
return ''.join([
self.handle_word(word) for word in words
self.handle_word(
word,
safe_input=safe_input,
trim_url_limit=trim_url_limit,
nofollow=nofollow,
autoescape=autoescape,
) for word in words
])
def handle_word(self, word):
def handle_word(
self, word, safe_input, trim_url_limit=None, nofollow=False, autoescape=False,
):
if '.' in word or '@' in word or ':' in word:
# lead: Punctuation trimmed from the beginning of the word.
# middle: State of the word.
@ -268,7 +273,7 @@ class Urlizer:
lead, middle, trail = self.trim_punctuation(word)
# Make URL we want to point to.
url = None
nofollow_attr = ' rel="nofollow"' if self.nofollow else ''
nofollow_attr = ' rel="nofollow"' if nofollow else ''
if self.simple_url_re.match(middle):
url = smart_urlquote(html.unescape(middle))
elif self.simple_url_2_re.match(middle):
@ -283,8 +288,8 @@ class Urlizer:
nofollow_attr = ''
# Make link.
if url:
trimmed = self.trim_url(middle)
if self.autoescape and not self.safe_input:
trimmed = self.trim_url(middle, trim_url_limit=trim_url_limit)
if autoescape and not safe_input:
lead, trail = escape(lead), escape(trail)
trimmed = escape(trimmed)
middle = self.url_template.format(
@ -294,20 +299,20 @@ class Urlizer:
)
return mark_safe(f'{lead}{middle}{trail}')
else:
if self.safe_input:
if safe_input:
return mark_safe(word)
elif self.autoescape:
elif autoescape:
return escape(word)
elif self.safe_input:
elif safe_input:
return mark_safe(word)
elif self.autoescape:
elif autoescape:
return escape(word)
return word
def trim_url(self, x):
if self.trim_url_limit is None or len(x) <= self.trim_url_limit:
def trim_url(self, x, trim_url_limit):
if trim_url_limit is None or len(x) <= trim_url_limit:
return x
return '%s' % x[:max(0, self.trim_url_limit - 1)]
return '%s' % x[:max(0, trim_url_limit - 1)]
def trim_punctuation(self, word):
"""