From 8d42f42ef207e3aff64a37bb41aa1d2e63e5ec21 Mon Sep 17 00:00:00 2001 From: Harshit Bansal Date: Wed, 11 Oct 2017 20:41:19 +0000 Subject: [PATCH] notifications: Correctly convert relative narrow links to absolute URLs. --- zerver/lib/notifications.py | 23 ++++++++++++++++++++--- zerver/tests/test_notifications.py | 8 ++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/zerver/lib/notifications.py b/zerver/lib/notifications.py index a80201f94a..5afe0e786d 100644 --- a/zerver/lib/notifications.py +++ b/zerver/lib/notifications.py @@ -71,9 +71,26 @@ def topic_narrow_url(realm, stream, topic): def relative_to_full_url(base_url, content): # type: (Text, Text) -> Text # Convert relative URLs to absolute URLs. - elem = lxml.html.fromstring(content) # type: ignore # https://github.com/python/typeshed/issues/525 - elem.make_links_absolute(base_url) - content = lxml.html.tostring(elem).decode("utf-8") # type: ignore # https://github.com/python/typeshed/issues/525 + fragment = lxml.html.fromstring(content) # type: ignore # https://github.com/python/typeshed/issues/525 + + # We handle narrow URLs separately because of two reasons: + # 1: 'lxml' seems to be having an issue in dealing with URLs that begin + # `#` due to which it doesn't add a `/` before joining the base_url to + # the relative URL. + # 2: We also need to update the title attribute in the narrow links which + # is not possible with `make_links_absolute()`. + for link_info in fragment.iterlinks(): + elem, attrib, link, pos = link_info + match = re.match("/?#narrow/", link) + if match is not None: + link = re.sub(r"^/?#narrow/", base_url + "/#narrow/", link) + elem.set(attrib, link) + # Only manually linked narrow URLs have title attribute set. + if elem.get('title') is not None: + elem.set('title', link) + + fragment.make_links_absolute(base_url) + content = lxml.html.tostring(fragment).decode("utf-8") # type: ignore # https://github.com/python/typeshed/issues/525 # Inline images can't be displayed in the emails as the request # from the mail server can't be authenticated because it has no diff --git a/zerver/tests/test_notifications.py b/zerver/tests/test_notifications.py index 12f1a4b2da..69acf4bada 100644 --- a/zerver/tests/test_notifications.py +++ b/zerver/tests/test_notifications.py @@ -420,6 +420,14 @@ class TestMissedMessages(ZulipTestCase): expected_output = '

Set src="/avatar/username@example.com?s=30"

' self.assertEqual(actual_output, expected_output) + # A narrow URL which begins with a '#'. + test_data = '

Conversation

' + actual_output = relative_to_full_url("http://example.com", test_data) + expected_output = '

Conversation

' + self.assertEqual(actual_output, expected_output) + def test_fix_emoji(self): # type: () -> None # An emoji.