[damned-lies] Use format_html/format_html_join to build html fragments in people template tags



commit 7b72c275e2cd03e4caaededb53b5eee5a88653eb
Author: Claude Paroz <claude 2xlibre net>
Date:   Sat Sep 26 16:51:45 2015 +0200

    Use format_html/format_html_join to build html fragments in people template tags

 people/templatetags/people.py |   28 +++++++++++++++++-----------
 people/tests.py               |   27 +++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 11 deletions(-)
---
diff --git a/people/templatetags/people.py b/people/templatetags/people.py
index a981ea8..49a4e37 100644
--- a/people/templatetags/people.py
+++ b/people/templatetags/people.py
@@ -2,21 +2,23 @@ import hashlib
 
 from django import template
 from django.conf import settings
+from django.utils.html import format_html, format_html_join
 from django.utils.http import urlencode
-from django.utils.safestring import mark_safe
 from django.utils.translation import ugettext as _
 
 register = template.Library()
 
+
 @register.filter
 def people_list(lst):
     """
     Format a people list, with clickable person name.
     """
     # Translators: string used as separator in person list
-    result = _(", ").join('<a href="%s">%s</a>' % (pers.get_absolute_url(), pers.name)
-                          for pers in lst)
-    return mark_safe(result)
+    return format_html_join(
+        _(", "), '<a href="{}">{}</a>',
+        ((pers.get_absolute_url(), pers.name) for pers in lst)
+    )
 
 
 @register.filter
@@ -24,13 +26,17 @@ def people_image(person):
     nobody = settings.STATIC_URL + "img/nobody.png"
     if person.use_gravatar:
         digest = hashlib.md5(person.email.lower().encode("utf-8")).hexdigest()
-        tag = '<img src="https://secure.gravatar.com/avatar/%(hash)s.jpg?%(qs)s" alt="gravatar icon">' % {
-            'hash': digest,
+        tag = format_html(
+            '<img src="https://secure.gravatar.com/avatar/{hash}.jpg?{qs}"; alt="gravatar icon">',
+            hash=digest,
             # Size, default image, rating
-            'qs': urlencode({'s': '80', 'd': 'identicon', 'r': 'g'}),
-        }
+            qs=urlencode({'s': '80', 'd': 'identicon', 'r': 'g'}),
+        )
     elif person.image:
-        tag = '<img src="%s" alt="%s" onerror="this.onerror = null; this.src=\'%s\'">' % (person.image, 
person.name, nobody)
+        tag = format_html(
+            '<img src="{}" alt="{}" onerror="this.onerror = null; this.src=\'{}\'">',
+            person.image, person.name, nobody
+        )
     else:
-        tag = '<img src="%s" alt="generic person icon">' % nobody
-    return mark_safe(tag)
+        tag = format_html('<img src="{}" alt="generic person icon">', nobody)
+    return tag
diff --git a/people/tests.py b/people/tests.py
index b9446fd..71e8aa5 100644
--- a/people/tests.py
+++ b/people/tests.py
@@ -128,6 +128,33 @@ class PeopleTestCase(TestCase):
             'You&nbsp;&lt;some-address&nbsp;at&nbsp;example&nbsp;dot&nbsp;com&gt;'
         )
 
+    def test_people_image_tag(self):
+        """
+        Test the people_image template tag.
+        """
+        from people.templatetags import people
+        pn = self._create_person()
+        self.assertHTMLEqual(
+            people.people_image(pn),
+            '<img src="/static/img/nobody.png" alt="generic person icon">'
+        )
+        pn.image = 'http://www.example.org/my_image.png'
+        self.assertHTMLEqual(
+            people.people_image(pn),
+            '<img alt="John Nothing" onerror="this.onerror = null; this.src=\'/static/img/nobody.png\'" 
src="http://www.example.org/my_image.png"; />'
+        )
+        pn.last_name = "<script>Some XSS content</script>"
+        self.assertIn("&lt;script&gt;Some XSS content&lt;/script&gt;", people.people_image(pn))
+        self.assertHTMLEqual(
+            people.people_image(pn),
+            '<img alt="John &lt;script&gt;Some XSS content&lt;/script&gt;" onerror="this.onerror = null; 
this.src=\'/static/img/nobody.png\'" src="http://www.example.org/my_image.png"; />'
+        )
+        pn.use_gravatar = True
+        self.assertHTMLEqual(
+            people.people_image(pn),
+            '<img alt="gravatar icon" 
src="https://secure.gravatar.com/avatar/618b8b6c1c973c780ec218242c49cbe7.jpg?s=80&r=g&d=identicon"; />'
+        )
+
     @skipUnless(pyicu_present, "PyICU package is required for this test")
     def test_all_languages_list_order(self):
         """


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]