Skip to content

Commit

Permalink
Source.embed_post(): URL-escape url since it's rendered in HTML
Browse files Browse the repository at this point in the history
  • Loading branch information
snarfed committed Jul 16, 2019
1 parent cd94992 commit 560ebef
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
20 changes: 18 additions & 2 deletions granary/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
import logging
import re
import urllib.parse
import html2text

from bs4 import BeautifulSoup
import html2text
from oauth_dropins.webutil import util

from . import appengine_config
Expand Down Expand Up @@ -798,11 +798,27 @@ def changed(b, a, field, label):

@classmethod
def embed_post(cls, obj):
"""Returns the HTML string for embedding a post object."""
"""Returns the HTML string for embedding a post object.
Args:
obj: AS1 dict with at least url, and optionally also content.
Returns: string, HTML
Raises: ValueError, if obj['content'] contains raw < or > characters.
"""
obj = copy.copy(obj)
for field in 'url', 'content':
if field not in obj:
obj.setdefault(field, obj.get('object', {}).get(field, ''))

if '<' in obj['content'] or '>' in obj['content']:
raise ValueError("obj['content'] has unescaped < or > characters!")

# escape URL, but not with urllib.parse.quote, because it quotes a ton of
# chars we want to pass through, including most unicode chars.
obj['url'] = obj['url'].replace('<', '%3C').replace('>', '%3E')

return cls.EMBED_POST % obj

@classmethod
Expand Down
9 changes: 9 additions & 0 deletions granary/tests/test_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@

class FakeSource(Source):
DOMAIN = 'fake.com'
EMBED_POST = 'foo %(url)s bar'


class SourceTest(testutil.TestCase):
Expand Down Expand Up @@ -547,3 +548,11 @@ def test_is_public(self):
):
self.assertFalse(Source.is_public(obj), repr(obj))
self.assertFalse(Source.is_public({'object': obj}), repr(obj))

def test_embed_post_escapes_url(self):
self.assert_equals('foo http://%3Ca%3Eb bar',
self.source.embed_post({'url': 'http://<a>b'}))

def test_embed_post_checks_content_for_html(self):
with self.assertRaises(ValueError):
self.source.embed_post({'content': '<xyz>'})

0 comments on commit 560ebef

Please sign in to comment.