Commit f0c310e3 authored by Raphaël Hertzog's avatar Raphaël Hertzog

Strip control characters from News in the RSS feed

Without this we could get an UnserializableContentError exception like this:

Traceback:

File "/usr/lib/python3/dist-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)
File "/usr/lib/python3/dist-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)
File "/usr/lib/python3/dist-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3/dist-packages/django/contrib/syndication/views.py" in __call__
  48.         feedgen.write(response, 'utf-8')
File "/usr/lib/python3/dist-packages/django/utils/feedgenerator.py" in write
  248.         self.write_items(handler)
File "/usr/lib/python3/dist-packages/django/utils/feedgenerator.py" in write_items
  259.             self.add_item_elements(handler, item)
File "/usr/lib/python3/dist-packages/django/utils/feedgenerator.py" in add_item_elements
  309.             handler.addQuickElement("description", item['description'])
File "/usr/lib/python3/dist-packages/django/utils/xmlutils.py" in addQuickElement
  20.             self.characters(contents)
File "/usr/lib/python3/dist-packages/django/utils/xmlutils.py" in characters
  27.             raise UnserializableContentError("Control characters are not supported in XML 1.0")

Exception Type: UnserializableContentError at /pkg/tob/rss
Exception Value: Control characters are not supported in XML 1.0
parent b95fd62b
Pipeline #1647 passed with stages
in 9 minutes and 29 seconds
# Copyright 2013 The Distro Tracker Developers
# Copyright 2013-2018 The Distro Tracker Developers
# See the COPYRIGHT file at the top-level directory of this distribution and
# at https://deb.li/DTAuthors
#
......@@ -9,14 +9,26 @@
# except according to the terms contained in the LICENSE file.
"""Implements the RSS news feed."""
from itertools import chain
import re
from django.conf import settings
from django.http import Http404
from django.contrib.syndication.views import Feed
from distro_tracker.core.models import get_web_package
from distro_tracker.core.models import News
from distro_tracker.core.models import NewsRenderer
from distro_tracker.core.models import ActionItem
from itertools import chain
def filter_control_chars(method):
# We have to filter out control chars otherwise the FeedGenerator
# raises UnserializableContentError (see django/utils/xmlutils.py)
def wrapped(self, obj):
result = method(self, obj)
return re.sub(r'[\x00-\x08\x0B-\x0C\x0E-\x1F]', '', result)
return wrapped
class PackageNewsFeed(Feed):
......@@ -29,14 +41,17 @@ class PackageNewsFeed(Feed):
return package
@filter_control_chars
def title(self, obj):
return "{vendor} package news for {pkg}".format(
vendor=settings.DISTRO_TRACKER_VENDOR_NAME,
pkg=obj.name)
@filter_control_chars
def link(self, obj):
return obj.get_absolute_url()
@filter_control_chars
def description(self, obj):
return (
"Latest developer's news for {vendor} source package {pkg}"
......@@ -59,12 +74,14 @@ class PackageNewsFeed(Feed):
all_items = chain(news, action_items)
return sorted(all_items, key=item_key, reverse=True)[:item_limit]
@filter_control_chars
def item_title(self, item):
if isinstance(item, News):
return item.title
elif isinstance(item, ActionItem):
return item.short_description
@filter_control_chars
def item_description(self, item):
if isinstance(item, News):
renderer_class = NewsRenderer.get_renderer_for_content_type(
......
......@@ -192,6 +192,22 @@ class NewsFeedTests(TestCase):
# Ensure the name is correctly decoded
self.assertContains(response, 'David Martínez Moreno')
def test_news_feed_filters_out_control_characters(self):
content = ('This is a test entry with control chars\n'
'\x00\x01\x08 \x0B\x0C \x0E\x1F')
title = 'This is a title with control chars \x01'
News.objects.create(
title=title,
content=content,
package=self.package)
response = self.get_rss_feed_response(self.package.name)
# Ensure the name is correctly decoded
self.assertContains(response, 'This is a test entry with control chars')
self.assertContains(response, 'This is a title with control chars')
self.assertNotContains(response, '\x01')
def test_action_items_and_news(self):
"""
Tests that both action items and news are included in the same feed.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment