mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-24 00:04:16 +03:00
Drop urlize_quoted_links (#7548)
This commit is contained in:
parent
c6e24521da
commit
ae649336b1
|
@ -418,7 +418,7 @@ class BrowsableAPIRenderer(BaseRenderer):
|
|||
if render_style == 'binary':
|
||||
return '[%d bytes of binary content]' % len(content)
|
||||
|
||||
return content
|
||||
return content.decode('utf-8') if isinstance(content, bytes) else content
|
||||
|
||||
def show_form_for_method(self, view, method, request, obj):
|
||||
"""
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
|
||||
<div class="region" aria-label="{% trans "request form" %}">
|
||||
{% block request_forms %}
|
||||
|
||||
|
||||
{% if 'GET' in allowed_methods %}
|
||||
<form id="get-form" class="pull-right">
|
||||
<fieldset>
|
||||
|
@ -176,9 +176,9 @@
|
|||
|
||||
<div class="response-info" aria-label="{% trans "response info" %}">
|
||||
<pre class="prettyprint"><span class="meta nocode"><b>HTTP {{ response.status_code }} {{ response.status_text }}</b>{% for key, val in response_headers|items %}
|
||||
<b>{{ key }}:</b> <span class="lit">{{ val|break_long_headers|urlize_quoted_links }}</span>{% endfor %}
|
||||
<b>{{ key }}:</b> <span class="lit">{{ val|break_long_headers|urlize }}</span>{% endfor %}
|
||||
|
||||
</span>{{ content|urlize_quoted_links }}</pre>
|
||||
</span>{{ content|urlize }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@ from collections import OrderedDict
|
|||
from django import template
|
||||
from django.template import loader
|
||||
from django.urls import NoReverseMatch, reverse
|
||||
from django.utils.encoding import force_str, iri_to_uri
|
||||
from django.utils.encoding import iri_to_uri
|
||||
from django.utils.html import escape, format_html, smart_urlquote
|
||||
from django.utils.safestring import SafeData, mark_safe
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from rest_framework.compat import apply_markdown, pygments_highlight
|
||||
from rest_framework.renderers import HTMLFormRenderer
|
||||
|
@ -311,85 +311,6 @@ def smart_urlquote_wrapper(matched_url):
|
|||
return None
|
||||
|
||||
|
||||
@register.filter(needs_autoescape=True)
|
||||
def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=True):
|
||||
"""
|
||||
Converts any URLs in text into clickable links.
|
||||
|
||||
Works on http://, https://, www. links, and also on links ending in one of
|
||||
the original seven gTLDs (.com, .edu, .gov, .int, .mil, .net, and .org).
|
||||
Links can have trailing punctuation (periods, commas, close-parens) and
|
||||
leading punctuation (opening parens) and it'll still do the right thing.
|
||||
|
||||
If trim_url_limit is not None, the URLs in link text longer than this limit
|
||||
will truncated to trim_url_limit-3 characters and appended with an ellipsis.
|
||||
|
||||
If nofollow is True, the URLs in link text will get a rel="nofollow"
|
||||
attribute.
|
||||
|
||||
If autoescape is True, the link text and URLs will get autoescaped.
|
||||
"""
|
||||
def trim_url(x, limit=trim_url_limit):
|
||||
return limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x
|
||||
|
||||
safe_input = isinstance(text, SafeData)
|
||||
|
||||
# Unfortunately, Django built-in cannot be used here, because escaping
|
||||
# is to be performed on words, which have been forcibly coerced to text
|
||||
def conditional_escape(text):
|
||||
return escape(text) if autoescape and not safe_input else text
|
||||
|
||||
words = word_split_re.split(force_str(text))
|
||||
for i, word in enumerate(words):
|
||||
if '.' in word or '@' in word or ':' in word:
|
||||
# Deal with punctuation.
|
||||
lead, middle, trail = '', word, ''
|
||||
for punctuation in TRAILING_PUNCTUATION:
|
||||
if middle.endswith(punctuation):
|
||||
middle = middle[:-len(punctuation)]
|
||||
trail = punctuation + trail
|
||||
for opening, closing in WRAPPING_PUNCTUATION:
|
||||
if middle.startswith(opening):
|
||||
middle = middle[len(opening):]
|
||||
lead = lead + opening
|
||||
# Keep parentheses at the end only if they're balanced.
|
||||
if (
|
||||
middle.endswith(closing) and
|
||||
middle.count(closing) == middle.count(opening) + 1
|
||||
):
|
||||
middle = middle[:-len(closing)]
|
||||
trail = closing + trail
|
||||
|
||||
# Make URL we want to point to.
|
||||
url = None
|
||||
nofollow_attr = ' rel="nofollow"' if nofollow else ''
|
||||
if simple_url_re.match(middle):
|
||||
url = smart_urlquote_wrapper(middle)
|
||||
elif simple_url_2_re.match(middle):
|
||||
url = smart_urlquote_wrapper('http://%s' % middle)
|
||||
elif ':' not in middle and simple_email_re.match(middle):
|
||||
local, domain = middle.rsplit('@', 1)
|
||||
try:
|
||||
domain = domain.encode('idna').decode('ascii')
|
||||
except UnicodeError:
|
||||
continue
|
||||
url = 'mailto:%s@%s' % (local, domain)
|
||||
nofollow_attr = ''
|
||||
|
||||
# Make link.
|
||||
if url:
|
||||
trimmed = trim_url(middle)
|
||||
lead, trail = conditional_escape(lead), conditional_escape(trail)
|
||||
url, trimmed = conditional_escape(url), conditional_escape(trimmed)
|
||||
middle = '<a href="%s"%s>%s</a>' % (url, nofollow_attr, trimmed)
|
||||
words[i] = '%s%s%s' % (lead, middle, trail)
|
||||
else:
|
||||
words[i] = conditional_escape(word)
|
||||
else:
|
||||
words[i] = conditional_escape(word)
|
||||
return mark_safe(''.join(words))
|
||||
|
||||
|
||||
@register.filter
|
||||
def break_long_headers(header):
|
||||
"""
|
||||
|
|
|
@ -2,13 +2,14 @@ import unittest
|
|||
|
||||
from django.template import Context, Template
|
||||
from django.test import TestCase
|
||||
from django.utils.html import urlize
|
||||
|
||||
from rest_framework.compat import coreapi, coreschema
|
||||
from rest_framework.relations import Hyperlink
|
||||
from rest_framework.templatetags import rest_framework
|
||||
from rest_framework.templatetags.rest_framework import (
|
||||
add_nested_class, add_query_param, as_string, break_long_headers,
|
||||
format_value, get_pagination_html, schema_links, urlize_quoted_links
|
||||
format_value, get_pagination_html, schema_links
|
||||
)
|
||||
from rest_framework.test import APIRequestFactory
|
||||
|
||||
|
@ -246,7 +247,7 @@ class Issue1386Tests(TestCase):
|
|||
|
||||
def test_issue_1386(self):
|
||||
"""
|
||||
Test function urlize_quoted_links with different args
|
||||
Test function urlize with different args
|
||||
"""
|
||||
correct_urls = [
|
||||
"asdf.com",
|
||||
|
@ -255,7 +256,7 @@ class Issue1386Tests(TestCase):
|
|||
"as.d8f.ghj8.gov",
|
||||
]
|
||||
for i in correct_urls:
|
||||
res = urlize_quoted_links(i)
|
||||
res = urlize(i)
|
||||
self.assertNotEqual(res, i)
|
||||
self.assertIn(i, res)
|
||||
|
||||
|
@ -264,11 +265,11 @@ class Issue1386Tests(TestCase):
|
|||
"asdf.netnet",
|
||||
]
|
||||
for i in incorrect_urls:
|
||||
res = urlize_quoted_links(i)
|
||||
res = urlize(i)
|
||||
self.assertEqual(i, res)
|
||||
|
||||
# example from issue #1386, this shouldn't raise an exception
|
||||
urlize_quoted_links("asdf:[/p]zxcv.com")
|
||||
urlize("asdf:[/p]zxcv.com")
|
||||
|
||||
def test_smart_urlquote_wrapper_handles_value_error(self):
|
||||
def mock_smart_urlquote(url):
|
||||
|
@ -289,7 +290,10 @@ class URLizerTests(TestCase):
|
|||
For all items in dict test assert that the value is urlized key
|
||||
"""
|
||||
for original, urlized in data.items():
|
||||
assert urlize_quoted_links(original, nofollow=False) == urlized
|
||||
print('====')
|
||||
print(repr(urlize(original, nofollow=False)))
|
||||
print(repr(urlized))
|
||||
assert urlize(original, nofollow=False) == urlized
|
||||
|
||||
def test_json_with_url(self):
|
||||
"""
|
||||
|
@ -297,26 +301,26 @@ class URLizerTests(TestCase):
|
|||
"""
|
||||
data = {}
|
||||
data['"url": "http://api/users/1/", '] = \
|
||||
'"url": "<a href="http://api/users/1/">http://api/users/1/</a>", '
|
||||
'"url": "<a href="http://api/users/1/">http://api/users/1/</a>", '
|
||||
data['"foo_set": [\n "http://api/foos/1/"\n], '] = \
|
||||
'"foo_set": [\n "<a href="http://api/foos/1/">http://api/foos/1/</a>"\n], '
|
||||
'"foo_set": [\n "<a href="http://api/foos/1/">http://api/foos/1/</a>"\n], '
|
||||
self._urlize_dict_check(data)
|
||||
|
||||
def test_template_render_with_autoescape(self):
|
||||
"""
|
||||
Test that HTML is correctly escaped in Browsable API views.
|
||||
"""
|
||||
template = Template("{% load rest_framework %}{{ content|urlize_quoted_links }}")
|
||||
template = Template("{% load rest_framework %}{{ content|urlize }}")
|
||||
rendered = template.render(Context({'content': '<script>alert()</script> http://example.com'}))
|
||||
assert rendered == '<script>alert()</script>' \
|
||||
' <a href="http://example.com" rel="nofollow">http://example.com</a>'
|
||||
|
||||
def test_template_render_with_noautoescape(self):
|
||||
"""
|
||||
Test if the autoescape value is getting passed to urlize_quoted_links filter.
|
||||
Test if the autoescape value is getting passed to urlize filter.
|
||||
"""
|
||||
template = Template("{% load rest_framework %}"
|
||||
"{% autoescape off %}{{ content|urlize_quoted_links }}"
|
||||
"{% autoescape off %}{{ content|urlize }}"
|
||||
"{% endautoescape %}")
|
||||
rendered = template.render(Context({'content': '<b> "http://example.com" </b>'}))
|
||||
assert rendered == '<b> "<a href="http://example.com" rel="nofollow">http://example.com</a>" </b>'
|
||||
|
|
Loading…
Reference in New Issue
Block a user