Refs #23269 -- Removed the removetags template tag and related functions per deprecation timeline.

This commit is contained in:
Tim Graham 2015-08-18 10:09:17 -04:00
parent 785cc71d5b
commit 222d063301
7 changed files with 7 additions and 189 deletions

View File

@ -13,7 +13,7 @@ from django.utils.dateformat import format, time_format
from django.utils.encoding import force_text, iri_to_uri
from django.utils.html import (
avoid_wrapping, conditional_escape, escape, escapejs, linebreaks,
remove_tags, strip_tags, urlize as _urlize,
strip_tags, urlize as _urlize,
)
from django.utils.http import urlquote
from django.utils.safestring import SafeData, mark_for_escaping, mark_safe
@ -500,13 +500,6 @@ def safeseq(value):
return [mark_safe(force_text(obj)) for obj in value]
@register.filter(is_safe=True)
@stringfilter
def removetags(value, tags):
"""Removes a space separated list of [X]HTML tags from the output."""
return remove_tags(value, tags)
@register.filter(is_safe=True)
@stringfilter
def striptags(value):

View File

@ -3,10 +3,8 @@
from __future__ import unicode_literals
import re
import warnings
from django.utils import six
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import force_str, force_text
from django.utils.functional import allow_lazy
from django.utils.http import RFC3986_GENDELIMS, RFC3986_SUBDELIMS
@ -184,39 +182,12 @@ def strip_tags(value):
strip_tags = allow_lazy(strip_tags)
def remove_tags(html, tags):
"""Returns the given HTML with given tags removed."""
warnings.warn(
"django.utils.html.remove_tags() and the removetags template filter "
"are deprecated. Consider using the bleach library instead.",
RemovedInDjango110Warning, stacklevel=3
)
tags = [re.escape(tag) for tag in tags.split()]
tags_re = '(%s)' % '|'.join(tags)
starttag_re = re.compile(r'<%s(/?>|(\s+[^>]*>))' % tags_re, re.U)
endtag_re = re.compile('</%s>' % tags_re)
html = starttag_re.sub('', html)
html = endtag_re.sub('', html)
return html
remove_tags = allow_lazy(remove_tags, six.text_type)
def strip_spaces_between_tags(value):
"""Returns the given HTML with spaces between tags removed."""
return re.sub(r'>\s+<', '><', force_text(value))
strip_spaces_between_tags = allow_lazy(strip_spaces_between_tags, six.text_type)
def strip_entities(value):
"""Returns the given HTML with all entities (&something;) stripped."""
warnings.warn(
"django.utils.html.strip_entities() is deprecated.",
RemovedInDjango110Warning, stacklevel=2
)
return re.sub(r'&(?:\w+|#\d+);', '', force_text(value))
strip_entities = allow_lazy(strip_entities, six.text_type)
def smart_urlquote(url):
"Quotes a URL if it isn't already quoted."
def unquote_quote(segment):

View File

@ -1866,44 +1866,6 @@ For example::
If ``value`` is the list ``['a', 'b', 'c', 'd']``, the output could be ``"b"``.
.. templatefilter:: removetags
removetags
^^^^^^^^^^
.. deprecated:: 1.8
``removetags`` cannot guarantee HTML safe output and has been deprecated due
to security concerns. Consider using `bleach`_ instead.
.. _bleach: http://bleach.readthedocs.org/en/latest/
Removes a space-separated list of [X]HTML tags from the output.
For example::
{{ value|removetags:"b span" }}
If ``value`` is ``"<b>Joel</b> <button>is</button> a <span>slug</span>"`` the
unescaped output will be ``"Joel <button>is</button> a slug"``.
Note that this filter is case-sensitive.
If ``value`` is ``"<B>Joel</B> <button>is</button> a <span>slug</span>"`` the
unescaped output will be ``"<B>Joel</B> <button>is</button> a slug"``.
.. admonition:: No safety guarantee
Note that ``removetags`` doesn't give any guarantee about its output being
HTML safe. In particular, it doesn't work recursively, so an input like
``"<sc<script>ript>alert('XSS')</sc</script>ript>"`` won't be safe even if
you apply ``|removetags:"script"``. So if the input is user provided,
**NEVER** apply the ``safe`` filter to a ``removetags`` output. If you are
looking for something more robust, you can use the ``bleach`` Python
library, notably its `clean`_ method.
.. _clean: http://bleach.readthedocs.org/en/latest/clean.html
.. templatefilter:: rjust
rjust

View File

@ -621,6 +621,8 @@ escaping HTML.
through :func:`conditional_escape` which (ultimately) calls
:func:`~django.utils.encoding.force_text` on the values.
.. _str.format: https://docs.python.org/library/stdtypes.html#str.format
.. function:: format_html_join(sep, format_string, args_generator)
A wrapper of :func:`format_html`, for the common case of a group of
@ -650,39 +652,8 @@ escaping HTML.
If ``value`` is ``"<b>Joel</b> <button>is</button> a <span>slug</span>"``
the return value will be ``"Joel is a slug"``.
If you are looking for a more robust solution, take a look at the `bleach`_
Python library.
.. function:: remove_tags(value, tags)
.. deprecated:: 1.8
``remove_tags()`` cannot guarantee HTML safe output and has been
deprecated due to security concerns. Consider using `bleach`_ instead.
Removes a space-separated list of [X]HTML tag names from the output.
Absolutely NO guarantee is provided about the resulting string being HTML
safe. In particular, it doesn't work recursively, so the output of
``remove_tags("<sc<script>ript>alert('XSS')</sc</script>ript>", "script")``
won't remove the "nested" script tags. So if the ``value`` is untrusted,
NEVER mark safe the result of a ``remove_tags()`` call without escaping it
first, for example with :func:`~django.utils.html.escape`.
For example::
remove_tags(value, "b span")
If ``value`` is ``"<b>Joel</b> <button>is</button> a <span>slug</span>"``
the return value will be ``"Joel <button>is</button> a slug"``.
Note that this filter is case-sensitive.
If ``value`` is ``"<B>Joel</B> <button>is</button> a <span>slug</span>"``
the return value will be ``"<B>Joel</B> <button>is</button> a slug"``.
.. _str.format: https://docs.python.org/library/stdtypes.html#str.format
.. _bleach: https://pypi.python.org/pypi/bleach
If you are looking for a more robust solution, take a look at the `bleach
<https://pypi.python.org/pypi/bleach>`_ Python library.
.. function:: html_safe()

View File

@ -671,7 +671,7 @@ Miscellaneous
* The ``slugify`` template filter is now available as a standard python
function at :func:`django.utils.text.slugify`. Similarly, ``remove_tags`` is
available at :func:`django.utils.html.remove_tags`.
available at ``django.utils.html.remove_tags()``.
* Uploaded files are no longer created as executable by default. If you need
them to be executable change :setting:`FILE_UPLOAD_PERMISSIONS` to your

View File

@ -1,49 +0,0 @@
from django.template.defaultfilters import removetags
from django.test import SimpleTestCase, ignore_warnings
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.safestring import mark_safe
from ..utils import setup
@ignore_warnings(category=RemovedInDjango110Warning)
class RemovetagsTests(SimpleTestCase):
@setup({'removetags01': '{{ a|removetags:"a b" }} {{ b|removetags:"a b" }}'})
def test_removetags01(self):
output = self.engine.render_to_string(
'removetags01',
{
'a': '<a>x</a> <p><b>y</b></p>',
'b': mark_safe('<a>x</a> <p><b>y</b></p>'),
},
)
self.assertEqual(output, 'x &lt;p&gt;y&lt;/p&gt; x <p>y</p>')
@setup({'removetags02':
'{% autoescape off %}{{ a|removetags:"a b" }} {{ b|removetags:"a b" }}{% endautoescape %}'})
def test_removetags02(self):
output = self.engine.render_to_string(
'removetags02',
{
'a': '<a>x</a> <p><b>y</b></p>',
'b': mark_safe('<a>x</a> <p><b>y</b></p>'),
},
)
self.assertEqual(output, 'x <p>y</p> x <p>y</p>')
@ignore_warnings(category=RemovedInDjango110Warning)
class FunctionTests(SimpleTestCase):
def test_removetags(self):
self.assertEqual(
removetags(
'some <b>html</b> with <script>alert("You smell")</script> disallowed <img /> tags',
'script img',
),
'some <b>html</b> with alert("You smell") disallowed tags',
)
def test_non_string_input(self):
self.assertEqual(removetags(123, 'a'), '123')

View File

@ -4,10 +4,9 @@ from __future__ import unicode_literals
import os
from datetime import datetime
from django.test import SimpleTestCase, ignore_warnings
from django.test import SimpleTestCase
from django.utils import html, safestring, six
from django.utils._os import upath
from django.utils.deprecation import RemovedInDjango110Warning
from django.utils.encoding import force_text
@ -123,25 +122,6 @@ class TestUtilsHtml(SimpleTestCase):
for value, output in items:
self.check_output(f, value, output)
@ignore_warnings(category=RemovedInDjango110Warning)
def test_strip_entities(self):
f = html.strip_entities
# Strings that should come out untouched.
values = ("&", "&a", "&a", "a&#a")
for value in values:
self.check_output(f, value)
# Valid entities that should be stripped from the patterns.
entities = ("&#1;", "&#12;", "&a;", "&fdasdfasdfasdf;")
patterns = (
("asdf %(entity)s ", "asdf "),
("%(entity)s%(entity)s", ""),
("&%(entity)s%(entity)s", "&"),
("%(entity)s3", "3"),
)
for entity in entities:
for in_pattern, output in patterns:
self.check_output(f, in_pattern % {'entity': entity}, output)
def test_escapejs(self):
f = html.escapejs
items = (
@ -160,16 +140,6 @@ class TestUtilsHtml(SimpleTestCase):
for value, output in items:
self.check_output(f, value, output)
@ignore_warnings(category=RemovedInDjango110Warning)
def test_remove_tags(self):
f = html.remove_tags
items = (
("<b><i>Yes</i></b>", "b i", "Yes"),
("<a>x</a> <p><b>y</b></p>", "a b", "x <p>y</p>"),
)
for value, tags, output in items:
self.assertEqual(f(value, tags), output)
def test_smart_urlquote(self):
quote = html.smart_urlquote
# Ensure that IDNs are properly quoted