Skip to content

Commit 91c46ed

Browse files
Strip Unicode control characters out of feed content. Fixes ietf-tools#3398. Commit ready for merge.
- Legacy-Id: 19786
1 parent 11b5b8c commit 91c46ed

2 files changed

Lines changed: 32 additions & 4 deletions

File tree

ietf/doc/feeds.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44

55
import datetime
6+
import unicodedata
67

78
from django.contrib.syndication.views import Feed, FeedDoesNotExist
89
from django.utils.feedgenerator import Atom1Feed, Rss201rev2Feed
@@ -15,6 +16,15 @@
1516
from ietf.doc.utils import augment_events_with_revision
1617
from ietf.doc.templatetags.ietf_filters import format_textarea
1718

19+
20+
def strip_control_characters(s):
21+
"""Remove Unicode control / non-printing characters from a string"""
22+
replacement_char = unicodedata.lookup('REPLACEMENT CHARACTER')
23+
return ''.join(
24+
replacement_char if unicodedata.category(c)[0] == 'C' else c
25+
for c in s
26+
)
27+
1828
class DocumentChangesFeed(Feed):
1929
feed_type = Atom1Feed
2030

@@ -38,10 +48,14 @@ def items(self, obj):
3848
return events
3949

4050
def item_title(self, item):
41-
return "[%s] %s [rev. %s]" % (item.by, truncatewords(strip_tags(item.desc), 15), item.rev)
51+
return strip_control_characters("[%s] %s [rev. %s]" % (
52+
item.by,
53+
truncatewords(strip_tags(item.desc), 15),
54+
item.rev,
55+
))
4256

4357
def item_description(self, item):
44-
return truncatewords_html(format_textarea(item.desc), 20)
58+
return strip_control_characters(truncatewords_html(format_textarea(item.desc), 20))
4559

4660
def item_pubdate(self, item):
4761
return item.time
@@ -75,7 +89,7 @@ def item_title(self, item):
7589
datefilter(item.lc_event.expires, "F j, Y"))
7690

7791
def item_description(self, item):
78-
return linebreaks(item.lc_event.desc)
92+
return strip_control_characters(linebreaks(item.lc_event.desc))
7993

8094
def item_pubdate(self, item):
8195
return item.lc_event.time

ietf/doc/tests.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1704,6 +1704,20 @@ def test_document_feed(self):
17041704
self.assertEqual(r.status_code, 200)
17051705
self.assertContains(r, e.desc)
17061706

1707+
def test_document_feed_with_control_character(self):
1708+
doc = IndividualDraftFactory()
1709+
1710+
DocEvent.objects.create(
1711+
doc=doc,
1712+
rev=doc.rev,
1713+
desc="Something happened involving the \x0b character.",
1714+
type="added_comment",
1715+
by=Person.objects.get(name="(System)"))
1716+
1717+
r = self.client.get("/feed/document-changes/%s/" % doc.name)
1718+
self.assertEqual(r.status_code, 200)
1719+
self.assertContains(r, 'Something happened involving the')
1720+
17071721
def test_last_call_feed(self):
17081722
doc = IndividualDraftFactory()
17091723

@@ -1712,7 +1726,7 @@ def test_last_call_feed(self):
17121726
LastCallDocEvent.objects.create(
17131727
doc=doc,
17141728
rev=doc.rev,
1715-
desc="Last call",
1729+
desc="Last call\x0b", # include a control character to be sure it does not break anything
17161730
type="sent_last_call",
17171731
by=Person.objects.get(user__username="secretary"),
17181732
expires=datetime.date.today() + datetime.timedelta(days=7))

0 commit comments

Comments
 (0)