diff --git a/comment/templates/comment/comments/content.html b/comment/templates/comment/comments/content.html index 44ad95e..6cbbab7 100644 --- a/comment/templates/comment/comments/content.html +++ b/comment/templates/comment/comments/content.html @@ -4,10 +4,10 @@ {% include "comment/comments/urlhash.html" with urlhash=urlhash %} {% endblock comment_urlhash %} {% if text_2 %} - {{ text_1|safe }} - {{ text_2|safe }} + {{ text_1 }} + {{ text_2 }} {% else %} - {{ text_1|safe }} + {{ text_1 }} {% endif %}

diff --git a/comment/templatetags/comment_tags.py b/comment/templatetags/comment_tags.py index f85f1f0..6e73fdb 100644 --- a/comment/templatetags/comment_tags.py +++ b/comment/templatetags/comment_tags.py @@ -1,6 +1,8 @@ import re from django import template +from django.utils.html import conditional_escape +from django.utils.safestring import mark_safe from comment.models import ReactionInstance, FlagInstance, Follower, BlockedUser from comment.forms import CommentForm @@ -88,15 +90,21 @@ def render_comments(obj, request, oauth=False): register.inclusion_tag('comment/base.html')(render_comments) +def _restrict_line_breaks(content): + # Restrict 2 or more line breaks to 2
+ content = MULTIPLE_NEW_LINE_RE.sub(r'\1

\3', content) + return SINGLE_NEW_LINE_RE.sub(r'\1
\3', content) + + def render_content(comment, number=None): try: number = int(number) except (ValueError, TypeError): number = get_wrapped_words_number() - # Restrict 2 or more line breaks to 2
- content = MULTIPLE_NEW_LINE_RE.sub(r'\1

\3', comment.content) - content = SINGLE_NEW_LINE_RE.sub(r'\1
\3', content) + # this is necessary to avoid XSS attacks + escaped_content = conditional_escape(comment.content) + content = _restrict_line_breaks(escaped_content) content_words = content.split() if not number or len(content_words) <= number: text_1 = content @@ -106,8 +114,8 @@ def render_content(comment, number=None): text_2 = ' '.join(content_words[number:]) return { - 'text_1': text_1, - 'text_2': text_2, + 'text_1': mark_safe(text_1), + 'text_2': mark_safe(text_2) if text_2 else None, 'urlhash': comment.urlhash } diff --git a/comment/tests/test_template_tags.py b/comment/tests/test_template_tags.py index 9e32f40..ec0d184 100644 --- a/comment/tests/test_template_tags.py +++ b/comment/tests/test_template_tags.py @@ -158,13 +158,13 @@ def test_urlhash(self): result = render_content(self.comment) self.assertEqual(result['urlhash'], self.comment.urlhash) - @patch.object(settings, 'COMMENT_WRAP_CONTENT_WORDS', 10) - def test_content_wrapping(self): + @patch.object(settings, 'COMMENT_WRAP_CONTENT_WORDS', 20) + def test_content_wrapping_with_large_truncate_number(self): content_words = self.comment.content.split() - self.assertEqual(len(content_words), len(self.content.split())) + self.assertIs(len(content_words) < 20, True) result = render_content(self.comment) - # truncate number is bigger than self.contentwords + self.assertEqual(result['text_1'], self.comment.content) self.assertIsNone(result['text_2']) @@ -190,17 +190,17 @@ def test_multiple_line_breaks(self): self.assertIn('

', result['text_1']) self.assertNotIn('


', result['text_1']) - def test_wrapping_after_certain_length(self): + @patch.object(settings, 'COMMENT_WRAP_CONTENT_WORDS', 5) + def test_content_wrapping_with_small_truncate_number(self): self.comment.refresh_from_db() content_words = self.comment.content.split() self.assertEqual(len(content_words), len(self.content.split())) - truncate_words_after = 5 - result = render_content(self.comment, truncate_words_after) + result = render_content(self.comment) # truncate number is smaller than words in content - self.assertEqual(result['text_1'], ' '.join(content_words[:truncate_words_after])) - self.assertEqual(result['text_2'], ' '.join(content_words[truncate_words_after:])) + self.assertEqual(result['text_1'], ' '.join(content_words[:5])) + self.assertEqual(result['text_2'], ' '.join(content_words[5:])) class GetUsernameForCommentTest(BaseTemplateTagsTest):