From c65dc279d1d8370701a98083c206822e866c84ad Mon Sep 17 00:00:00 2001 From: Paulo Henrique Rodrigues Pinheiro Date: Tue, 1 Nov 2016 05:41:21 -0200 Subject: [PATCH] Drop-in html.escape in place of cgi.escape for python3.2+ (#1513) Fix #1330 Define `escape_html` function with signature same as for `cgi.escape` and `html.escape` having `quote=False` default param. --- cherrypy/_cpcompat.py | 16 ++++++++++++++++ cherrypy/_cperror.py | 4 ++-- cherrypy/test/test_compat.py | 8 ++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/cherrypy/_cpcompat.py b/cherrypy/_cpcompat.py index 9dd1a2fdd..fd67e0c86 100644 --- a/cherrypy/_cpcompat.py +++ b/cherrypy/_cpcompat.py @@ -332,3 +332,19 @@ def _args_from_interpreter_flags(): args.append('-W' + opt) return args + +# html module come in 3.2 version +try: + from html import escape +except ImportError: + from cgi import escape + +# html module needed the argument quote=False because in cgi the default +# is False. With quote=True the results differ. + +def escape_html(s, escape_quote=False): + """Replace special characters "&", "<" and ">" to HTML-safe sequences. + + When escape_quote=True, escape (') and (") chars. + """ + return escape(s, quote=escape_quote) diff --git a/cherrypy/_cperror.py b/cherrypy/_cperror.py index 205aa33b4..4ee2a2216 100644 --- a/cherrypy/_cperror.py +++ b/cherrypy/_cperror.py @@ -116,13 +116,13 @@ class Root: """ import contextlib -from cgi import escape as _escape from sys import exc_info as _exc_info from traceback import format_exception as _format_exception from xml.sax import saxutils import six +from cherrypy._cpcompat import escape_html from cherrypy._cpcompat import text_or_bytes, iteritems, ntob from cherrypy._cpcompat import tonative, urljoin as _urljoin from cherrypy.lib import httputil as _httputil @@ -502,7 +502,7 @@ def get_error_page(status, **kwargs): if v is None: kwargs[k] = '' else: - kwargs[k] = _escape(kwargs[k]) + kwargs[k] = escape_html(kwargs[k]) # Use a custom template or callable for the error page? pages = cherrypy.serving.request.error_page diff --git a/cherrypy/test/test_compat.py b/cherrypy/test/test_compat.py index bfb86e13a..e61944095 100644 --- a/cherrypy/test/test_compat.py +++ b/cherrypy/test/test_compat.py @@ -21,3 +21,11 @@ def test_ntob_non_native(self): if six.PY3: raise nose.SkipTest('Only useful on Python 2') self.assertRaises(Exception, compat.ntob, 'fight') + + +class EscapeTester(unittest.TestCase): + """Class to test escape_html function from _cpcompat.""" + + def test_escape_quote(self): + """test_escape_quote - Verify the output for &<>"' chars.""" + self.assertEqual("""xx&<>"aa'""", compat.escape_html("""xx&<>"aa'"""))