Fixed #23269 -- Deprecated django.utils.remove_tags() and removetags filter.

Also the unused, undocumented django.utils.html.strip_entities() function.
This commit is contained in:
Tim Graham 2014-08-11 07:24:51 -04:00
parent deed00c0d8
commit e122facbd8
8 changed files with 62 additions and 10 deletions

View File

@ -4,7 +4,9 @@ from __future__ import unicode_literals
import re import re
import sys import sys
import warnings
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import force_text, force_str from django.utils.encoding import force_text, force_str
from django.utils.functional import allow_lazy from django.utils.functional import allow_lazy
from django.utils.http import RFC3986_GENDELIMS, RFC3986_SUBDELIMS from django.utils.http import RFC3986_GENDELIMS, RFC3986_SUBDELIMS
@ -177,6 +179,11 @@ strip_tags = allow_lazy(strip_tags)
def remove_tags(html, tags): def remove_tags(html, tags):
"""Returns the given HTML with given tags removed.""" """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.",
RemovedInDjango20Warning, stacklevel=3
)
tags = [re.escape(tag) for tag in tags.split()] tags = [re.escape(tag) for tag in tags.split()]
tags_re = '(%s)' % '|'.join(tags) tags_re = '(%s)' % '|'.join(tags)
starttag_re = re.compile(r'<%s(/?>|(\s+[^>]*>))' % tags_re, re.U) starttag_re = re.compile(r'<%s(/?>|(\s+[^>]*>))' % tags_re, re.U)
@ -195,6 +202,10 @@ strip_spaces_between_tags = allow_lazy(strip_spaces_between_tags, six.text_type)
def strip_entities(value): def strip_entities(value):
"""Returns the given HTML with all entities (&something;) stripped.""" """Returns the given HTML with all entities (&something;) stripped."""
warnings.warn(
"django.utils.html.strip_entities() is deprecated.",
RemovedInDjango20Warning, stacklevel=2
)
return re.sub(r'&(?:\w+|#\d+);', '', force_text(value)) return re.sub(r'&(?:\w+|#\d+);', '', force_text(value))
strip_entities = allow_lazy(strip_entities, six.text_type) strip_entities = allow_lazy(strip_entities, six.text_type)

View File

@ -49,6 +49,11 @@ about each item can often be found in the release notes of two versions prior.
* The backward compatible shim to rename ``django.forms.Form._has_changed()`` * The backward compatible shim to rename ``django.forms.Form._has_changed()``
to ``has_changed()`` will be removed. to ``has_changed()`` will be removed.
* The ``removetags`` template filter will be removed.
* The ``remove_tags()`` and ``strip_entities()`` functions in
``django.utils.html`` will be removed.
.. _deprecation-removed-in-1.9: .. _deprecation-removed-in-1.9:
1.9 1.9

View File

@ -1918,6 +1918,13 @@ If ``value`` is the list ``['a', 'b', 'c', 'd']``, the output could be ``"b"``.
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. Removes a space-separated list of [X]HTML tags from the output.
For example:: For example::

View File

@ -630,10 +630,13 @@ escaping HTML.
If you are looking for a more robust solution, take a look at the `bleach`_ If you are looking for a more robust solution, take a look at the `bleach`_
Python library. Python library.
.. _bleach: https://pypi.python.org/pypi/bleach
.. function:: remove_tags(value, tags) .. 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. Removes a space-separated list of [X]HTML tag names from the output.
Absolutely NO guarantee is provided about the resulting string being HTML Absolutely NO guarantee is provided about the resulting string being HTML
@ -656,6 +659,7 @@ escaping HTML.
the return value will be ``"<B>Joel</B> <button>is</button> a slug"``. the return value will be ``"<B>Joel</B> <button>is</button> a slug"``.
.. _str.format: http://docs.python.org/library/stdtypes.html#str.format .. _str.format: http://docs.python.org/library/stdtypes.html#str.format
.. _bleach: https://pypi.python.org/pypi/bleach
``django.utils.http`` ``django.utils.http``
===================== =====================

View File

@ -682,3 +682,14 @@ Using the new syntax, this becomes::
Rename this method to :meth:`~django.forms.Field.has_changed` by removing the Rename this method to :meth:`~django.forms.Field.has_changed` by removing the
leading underscore. The old name will still work until Django 2.0. leading underscore. The old name will still work until Django 2.0.
``django.utils.html.remove_tags()`` and ``removetags`` template filter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``django.utils.html.remove_tags()`` as well as the template filter
``removetags`` have been deprecated as they cannot guarantee safe output. Their
existence is likely to lead to their use in security-sensitive contexts where
they are not actually safe.
The unused and undocumented ``django.utils.html.strip_entities()`` function has
also been deprecated.

View File

@ -433,9 +433,13 @@ class DefaultFiltersTests(TestCase):
'line 1<br />line 2') 'line 1<br />line 2')
def test_removetags(self): def test_removetags(self):
self.assertEqual(removetags('some <b>html</b> with <script>alert' with warnings.catch_warnings(record=True):
'("You smell")</script> disallowed <img /> tags', 'script img'), warnings.simplefilter("always")
'some <b>html</b> with alert("You smell") disallowed tags') 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_striptags(self):
self.assertEqual(striptags('some <b>html</b> with <script>alert' self.assertEqual(striptags('some <b>html</b> with <script>alert'
'("You smell")</script> disallowed <img /> tags'), '("You smell")</script> disallowed <img /> tags'),
'some html with alert("You smell") disallowed tags') 'some html with alert("You smell") disallowed tags')
@ -713,7 +717,9 @@ class DefaultFiltersTests(TestCase):
self.assertEqual(escape(123), '123') self.assertEqual(escape(123), '123')
self.assertEqual(linebreaks_filter(123), '<p>123</p>') self.assertEqual(linebreaks_filter(123), '<p>123</p>')
self.assertEqual(linebreaksbr(123), '123') self.assertEqual(linebreaksbr(123), '123')
self.assertEqual(removetags(123, 'a'), '123') with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
self.assertEqual(removetags(123, 'a'), '123')
self.assertEqual(striptags(123), '123') self.assertEqual(striptags(123), '123')

View File

@ -590,7 +590,8 @@ class TemplateTests(TestCase):
# Ignore deprecations of using the wrong number of variables with the 'for' tag. # Ignore deprecations of using the wrong number of variables with the 'for' tag.
# and warnings for {% url %} reversing by dotted path # and warnings for {% url %} reversing by dotted path
warnings.filterwarnings("ignore", category=RemovedInDjango20Warning, module="django.template.defaulttags") warnings.filterwarnings("ignore", category=RemovedInDjango20Warning, module="django.template.defaulttags")
# Ignore deprecations of old style unordered_list. # Ignore deprecations of old style unordered_list
# and removetags.
warnings.filterwarnings("ignore", category=RemovedInDjango20Warning, module="django.template.defaultfilters") warnings.filterwarnings("ignore", category=RemovedInDjango20Warning, module="django.template.defaultfilters")
output = self.render(test_template, vals) output = self.render(test_template, vals)
except ShouldNotExecuteException: except ShouldNotExecuteException:

View File

@ -4,6 +4,7 @@ from __future__ import unicode_literals
from datetime import datetime from datetime import datetime
import os import os
from unittest import TestCase from unittest import TestCase
import warnings
from django.utils import html, safestring from django.utils import html, safestring
from django.utils._os import upath from django.utils._os import upath
@ -124,7 +125,9 @@ class TestUtilsHtml(TestCase):
# Strings that should come out untouched. # Strings that should come out untouched.
values = ("&", "&a", "&a", "a&#a") values = ("&", "&a", "&a", "a&#a")
for value in values: for value in values:
self.check_output(f, value) with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
self.check_output(f, value)
# Valid entities that should be stripped from the patterns. # Valid entities that should be stripped from the patterns.
entities = ("&#1;", "&#12;", "&a;", "&fdasdfasdfasdf;") entities = ("&#1;", "&#12;", "&a;", "&fdasdfasdfasdf;")
patterns = ( patterns = (
@ -135,7 +138,9 @@ class TestUtilsHtml(TestCase):
) )
for entity in entities: for entity in entities:
for in_pattern, output in patterns: for in_pattern, output in patterns:
self.check_output(f, in_pattern % {'entity': entity}, output) with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
self.check_output(f, in_pattern % {'entity': entity}, output)
def test_escapejs(self): def test_escapejs(self):
f = html.escapejs f = html.escapejs
@ -156,7 +161,9 @@ class TestUtilsHtml(TestCase):
("<a>x</a> <p><b>y</b></p>", "a b", "x <p>y</p>"), ("<a>x</a> <p><b>y</b></p>", "a b", "x <p>y</p>"),
) )
for value, tags, output in items: for value, tags, output in items:
self.assertEqual(f(value, tags), output) with warnings.catch_warnings(record=True):
warnings.simplefilter("always")
self.assertEqual(f(value, tags), output)
def test_smart_urlquote(self): def test_smart_urlquote(self):
quote = html.smart_urlquote quote = html.smart_urlquote