zerver: Remove simplejson dependency.

Modified by tabbott to put the third-party code in a new file.

Fixes #6970.
This commit is contained in:
rht 2017-10-17 11:34:37 +02:00 committed by Tim Abbott
parent b4e67fac36
commit e169bb0954
7 changed files with 67 additions and 11 deletions

View File

@ -182,6 +182,10 @@ Files: zerver/lib/decorator.py zerver/management/commands/runtornado.py scripts/
Copyright: Django Software Foundation and individual contributors Copyright: Django Software Foundation and individual contributors
License: BSD-3-Clause License: BSD-3-Clause
Files: zerver/lib/json_encoder_for_html.py zerver/tests/test_json_encoder_for_html.py
Copyright: 2006 Bob Ippolito
License: MIT or Academic Free License v. 2.1
License: Apache-2.0 License: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.

View File

@ -119,9 +119,6 @@ redis==2.10.6
requests_oauthlib==0.8.0 requests_oauthlib==0.8.0
rsa==3.4.2 rsa==3.4.2
# Needed for its HTML encoder for page_params
simplejson==3.11.1
# Needed for Python 2+3 compatibility # Needed for Python 2+3 compatibility
six==1.11.0 six==1.11.0
smmap==0.9.0 smmap==0.9.0
@ -184,6 +181,3 @@ social-auth-app-django==1.2.0
# Needed for messages' rendered content parsing in push notifications. # Needed for messages' rendered content parsing in push notifications.
lxml==4.1.0 lxml==4.1.0
# One occurrence left in home.py
simplejson==3.11.1

View File

@ -134,7 +134,6 @@ scrapy==1.4.0
service-identity==17.0.0 # via scrapy service-identity==17.0.0 # via scrapy
sh==1.11 # via gitlint sh==1.11 # via gitlint
simplegeneric==0.8.1 # via ipython simplegeneric==0.8.1 # via ipython
simplejson==3.11.1
six==1.11.0 six==1.11.0
smmap==0.9.0 smmap==0.9.0
snakeviz==0.4.2 snakeviz==0.4.2

View File

@ -92,7 +92,6 @@ requests-oauthlib==0.8.0
requests==2.18.4 # via premailer, pyoembed, python-gcm, python-twitter, requests-oauthlib, social-auth-core requests==2.18.4 # via premailer, pyoembed, python-gcm, python-twitter, requests-oauthlib, social-auth-core
rsa==3.4.2 rsa==3.4.2
simplegeneric==0.8.1 # via ipython simplegeneric==0.8.1 # via ipython
simplejson==3.11.1
six==1.11.0 six==1.11.0
smmap==0.9.0 smmap==0.9.0
social-auth-app-django==1.2.0 social-auth-app-django==1.2.0

View File

@ -0,0 +1,28 @@
import json
# Taken from
# https://github.com/simplejson/simplejson/blob/8edc82afcf6f7512b05fba32baa536fe756bd273/simplejson/encoder.py#L378-L402
# License: MIT
class JSONEncoderForHTML(json.JSONEncoder):
"""An encoder that produces JSON safe to embed in HTML.
To embed JSON content in, say, a script tag on a web page, the
characters &, < and > should be escaped. They cannot be escaped
with the usual entities (e.g. &amp;) because they are not expanded
within <script> tags.
"""
def encode(self, o):
# type: (Dict[str, Any]) -> str
# Override JSONEncoder.encode because it has hacks for
# performance that make things more complicated.
chunks = self.iterencode(o, True)
return ''.join(chunks)
def iterencode(self, o, _one_shot=False):
# type: (Dict[str, Any], Optional[bool]) -> Iterator[str]
chunks = super().iterencode(o, _one_shot)
for chunk in chunks:
chunk = chunk.replace('&', '\\u0026')
chunk = chunk.replace('<', '\\u003c')
chunk = chunk.replace('>', '\\u003e')
yield chunk

View File

@ -0,0 +1,32 @@
import json
from zerver.lib.json_encoder_for_html import JSONEncoderForHTML
from zerver.lib.test_classes import ZulipTestCase
class TestJSONEncoder(ZulipTestCase):
# Test EncoderForHTML
# Taken from
# https://github.com/simplejson/simplejson/blob/8edc82afcf6f7512b05fba32baa536fe756bd273/simplejson/tests/test_encode_for_html.py
# License: MIT
decoder = json.JSONDecoder()
encoder = JSONEncoderForHTML()
def test_basic_encode(self) -> None:
self.assertEqual(r'"\u0026"', self.encoder.encode('&'))
self.assertEqual(r'"\u003c"', self.encoder.encode('<'))
self.assertEqual(r'"\u003e"', self.encoder.encode('>'))
def test_basic_roundtrip(self) -> None:
for char in '&<>':
self.assertEqual(
char, self.decoder.decode(
self.encoder.encode(char)))
def test_prevent_script_breakout(self) -> None:
bad_string = '</script><script>alert("gotcha")</script>'
self.assertEqual(
r'"\u003c/script\u003e\u003cscript\u003e'
r'alert(\"gotcha\")\u003c/script\u003e"',
self.encoder.encode(bad_string))
self.assertEqual(
bad_string, self.decoder.decode(
self.encoder.encode(bad_string)))

View File

@ -1,4 +1,4 @@
from typing import Any, List, Dict, Optional, Text from typing import Any, List, Dict, Optional, Text, Iterator
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
@ -22,6 +22,7 @@ from zerver.lib.actions import update_user_presence, do_change_tos_version, \
from zerver.lib.avatar import avatar_url from zerver.lib.avatar import avatar_url
from zerver.lib.i18n import get_language_list, get_language_name, \ from zerver.lib.i18n import get_language_list, get_language_name, \
get_language_list_for_templates get_language_list_for_templates
from zerver.lib.json_encoder_for_html import JSONEncoderForHTML
from zerver.lib.push_notifications import num_push_devices_for_user from zerver.lib.push_notifications import num_push_devices_for_user
from zerver.lib.streams import access_stream_by_name from zerver.lib.streams import access_stream_by_name
from zerver.lib.subdomains import get_subdomain from zerver.lib.subdomains import get_subdomain
@ -32,7 +33,6 @@ import datetime
import logging import logging
import os import os
import re import re
import simplejson
import time import time
@zulip_login_required @zulip_login_required
@ -227,7 +227,7 @@ def home_real(request):
request._log_data['extra'] = "[%s]" % (register_ret["queue_id"],) request._log_data['extra'] = "[%s]" % (register_ret["queue_id"],)
response = render(request, 'zerver/index.html', response = render(request, 'zerver/index.html',
context={'user_profile': user_profile, context={'user_profile': user_profile,
'page_params': simplejson.encoder.JSONEncoderForHTML().encode(page_params), 'page_params': JSONEncoderForHTML().encode(page_params),
'nofontface': is_buggy_ua(request.META.get("HTTP_USER_AGENT", "Unspecified")), 'nofontface': is_buggy_ua(request.META.get("HTTP_USER_AGENT", "Unspecified")),
'avatar_url': avatar_url(user_profile), 'avatar_url': avatar_url(user_profile),
'show_debug': 'show_debug':