From b557b94d0be9007351c991c4fcda0cc2aeff5fab Mon Sep 17 00:00:00 2001
From: Tim Abbott
Date: Wed, 28 Aug 2013 16:45:26 -0400
Subject: [PATCH] bugdown: Rewrite image urls to avoid mixed-content warnings.
(imported from commit fc0a41befb04f2a8aad2937a856366ac3cadb192)
---
zerver/lib/bugdown/__init__.py | 19 +++++++++++++++++--
zerver/tests.py | 7 ++++++-
zproject/settings.py | 3 +++
3 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/zerver/lib/bugdown/__init__.py b/zerver/lib/bugdown/__init__.py
index 7e21ae3473..4d1a2e53fa 100644
--- a/zerver/lib/bugdown/__init__.py
+++ b/zerver/lib/bugdown/__init__.py
@@ -11,7 +11,8 @@ import time
import HTMLParser
import httplib2
-from hashlib import sha1
+import hashlib
+import hmac
from django.core import mail
from django.conf import settings
@@ -73,7 +74,7 @@ def add_a(root, url, link, height=None):
img.set("src", url)
def hash_embedly_url(link):
- return 'embedly:' + sha1(link).hexdigest()
+ return 'embedly:' + hashlib.sha1(link).hexdigest()
@cache_with_key(lambda tweet_id: tweet_id, cache_name="database", with_statsd_key="tweet_data")
def fetch_tweet_data(tweet_id):
@@ -145,6 +146,19 @@ def get_tweet_id(url):
return False
return tweet_id_match.group("tweetid")
+class InlineHttpsProcessor(markdown.treeprocessors.Treeprocessor):
+ def run(self, root):
+ # Get all URLs from the blob
+ found_imgs = walk_tree(root, lambda e: e if e.tag == "img" else None)
+ for img in found_imgs:
+ url = img.get("src")
+ # We rewrite all HTTP URLs as well as all HTTPs URLs for mit.edu
+ if not url.startswith("http://"):
+ # Don't rewrite images on our own site (e.g. emoji).
+ continue
+ digest = hmac.new(settings.CAMO_KEY, url, hashlib.sha1).hexdigest()
+ encoded_url = url.encode("hex")
+ img.set("src", "https://external-content.zulipcdn.net/%s/%s" % (digest, encoded_url))
class InlineInterestingLinkProcessor(markdown.treeprocessors.Treeprocessor):
def is_image(self, url):
@@ -651,6 +665,7 @@ class Bugdown(markdown.Extension):
"_begin")
md.treeprocessors.add("inline_interesting_links", InlineInterestingLinkProcessor(md), "_end")
+ md.treeprocessors.add("rewrite_to_https", InlineHttpsProcessor(md), "_end")
if self.getConfig("realm") == "mit.edu/zephyr_mirror":
# Disable almost all inline patterns for mit.edu users' traffic that is mirrored
diff --git a/zerver/tests.py b/zerver/tests.py
index bc11987fce..afd333ef3e 100644
--- a/zerver/tests.py
+++ b/zerver/tests.py
@@ -2610,12 +2610,17 @@ xxxxxxx
\nxxxxxxx xxxxx xxxx xxxxx:
\nxxxxxx
: xxx
self.assertEqual(converted, '
Google logo today: https://www.google.com/images/srpr/logo4w.png
\nKinda boring
\n')
- # If thre are two images, both should be previewed.
+ # If there are two images, both should be previewed.
msg = 'Google logo today: https://www.google.com/images/srpr/logo4w.png\nKinda boringGoogle logo today: https://www.google.com/images/srpr/logo4w.png\nKinda boring'
converted = bugdown_convert(msg)
self.assertEqual(converted, 'Google logo today: https://www.google.com/images/srpr/logo4w.png
\nKinda boringGoogle logo today: https://www.google.com/images/srpr/logo4w.png
\nKinda boring
\n')
+ # http images should be converted to https via our Camo integration
+ msg = 'Google logo today: http://www.google.com/images/srpr/logo4w.png'
+ converted = bugdown_convert(msg)
+
+ self.assertEqual(converted, 'Google logo today: http://www.google.com/images/srpr/logo4w.png
\n')
def test_inline_youtube(self):
msg = 'Check out the debate: http://www.youtube.com/watch?v=hx1mjT73xYE'
diff --git a/zproject/settings.py b/zproject/settings.py
index 46f63af9a4..16c6b61abb 100644
--- a/zproject/settings.py
+++ b/zproject/settings.py
@@ -580,6 +580,9 @@ OPENID_RENDER_FAILURE = openid_failure_handler
MAILCHIMP_API_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-us4'
ZULIP_FRIENDS_LIST_ID = '84b2f3da6b'
+# This should be synced with our camo installation
+CAMO_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
+
# Client-side polling timeout for get_events, in milliseconds.
# We configure this here so that the client test suite can override it.
# We already kill the connection server-side with heartbeat events,