summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2010-10-15 15:57:45 (GMT)
committerGeorg Brandl <georg@python.org>2010-10-15 15:57:45 (GMT)
commit1f7fffb308390d10a2c6a4ec624f18cfeef97aeb (patch)
tree65e2437904ba089004c69c77b49e5059623b83fb /Lib
parent70543acfa1bce2e5f448d8d0085df595bfa9a2f9 (diff)
downloadcpython-1f7fffb308390d10a2c6a4ec624f18cfeef97aeb.zip
cpython-1f7fffb308390d10a2c6a4ec624f18cfeef97aeb.tar.gz
cpython-1f7fffb308390d10a2c6a4ec624f18cfeef97aeb.tar.bz2
#2830: add html.escape() helper and move cgi.escape() uses in the standard library to it. It defaults to quote=True and also escapes single quotes, which makes casual use safer. The cgi.escape() interface is not touched, but emits a (silent) PendingDeprecationWarning.
Diffstat (limited to 'Lib')
-rwxr-xr-xLib/cgi.py25
-rw-r--r--Lib/html/__init__.py21
-rw-r--r--Lib/http/server.py6
-rw-r--r--Lib/lib2to3/tests/test_util.py4
-rw-r--r--Lib/test/test_html.py24
-rw-r--r--Lib/test/test_xml_etree.py4
6 files changed, 64 insertions, 20 deletions
diff --git a/Lib/cgi.py b/Lib/cgi.py
index 7da2b23..8786e58 100755
--- a/Lib/cgi.py
+++ b/Lib/cgi.py
@@ -31,13 +31,13 @@ __version__ = "2.6"
# Imports
# =======
-from operator import attrgetter
from io import StringIO
import sys
import os
import urllib.parse
import email.parser
from warnings import warn
+import html
__all__ = ["MiniFieldStorage", "FieldStorage",
"parse", "parse_qs", "parse_qsl", "parse_multipart",
@@ -800,8 +800,8 @@ def print_exception(type=None, value=None, tb=None, limit=None):
list = traceback.format_tb(tb, limit) + \
traceback.format_exception_only(type, value)
print("<PRE>%s<B>%s</B></PRE>" % (
- escape("".join(list[:-1])),
- escape(list[-1]),
+ html.escape("".join(list[:-1])),
+ html.escape(list[-1]),
))
del tb
@@ -812,7 +812,7 @@ def print_environ(environ=os.environ):
print("<H3>Shell Environment:</H3>")
print("<DL>")
for key in keys:
- print("<DT>", escape(key), "<DD>", escape(environ[key]))
+ print("<DT>", html.escape(key), "<DD>", html.escape(environ[key]))
print("</DL>")
print()
@@ -825,10 +825,10 @@ def print_form(form):
print("<P>No form fields.")
print("<DL>")
for key in keys:
- print("<DT>" + escape(key) + ":", end=' ')
+ print("<DT>" + html.escape(key) + ":", end=' ')
value = form[key]
- print("<i>" + escape(repr(type(value))) + "</i>")
- print("<DD>" + escape(repr(value)))
+ print("<i>" + html.escape(repr(type(value))) + "</i>")
+ print("<DD>" + html.escape(repr(value)))
print("</DL>")
print()
@@ -839,9 +839,9 @@ def print_directory():
try:
pwd = os.getcwd()
except os.error as msg:
- print("os.error:", escape(str(msg)))
+ print("os.error:", html.escape(str(msg)))
else:
- print(escape(pwd))
+ print(html.escape(pwd))
print()
def print_arguments():
@@ -899,9 +899,9 @@ environment as well. Here are some common variable names:
# =========
def escape(s, quote=None):
- '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
- If the optional flag quote is true, the quotation mark character (")
- is also translated.'''
+ """Deprecated API."""
+ warn("cgi.escape is deprecated, use html.escape instead",
+ PendingDeprecationWarning, stacklevel=2)
s = s.replace("&", "&amp;") # Must be done first!
s = s.replace("<", "&lt;")
s = s.replace(">", "&gt;")
@@ -909,6 +909,7 @@ def escape(s, quote=None):
s = s.replace('"', "&quot;")
return s
+
def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
import re
return re.match(_vb_pattern, s)
diff --git a/Lib/html/__init__.py b/Lib/html/__init__.py
index 196d378..335d214 100644
--- a/Lib/html/__init__.py
+++ b/Lib/html/__init__.py
@@ -1 +1,20 @@
-# This directory is a Python package.
+"""
+General functions for HTML manipulation.
+"""
+
+
+_escape_map = {ord('&'): '&amp;', ord('<'): '&lt;', ord('>'): '&gt;'}
+_escape_map_full = {ord('&'): '&amp;', ord('<'): '&lt;', ord('>'): '&gt;',
+ ord('"'): '&quot;', ord('\''): '&#x27;'}
+
+# NB: this is a candidate for a bytes/string polymorphic interface
+
+def escape(s, quote=True):
+ """
+ Replace special characters "&", "<" and ">" to HTML-safe sequences.
+ If the optional flag quote is true (the default), the quotation mark
+ character (") is also translated.
+ """
+ if quote:
+ return s.translate(_escape_map_full)
+ return s.translate(_escape_map)
diff --git a/Lib/http/server.py b/Lib/http/server.py
index 894342a..f6d0db4 100644
--- a/Lib/http/server.py
+++ b/Lib/http/server.py
@@ -84,7 +84,7 @@ __version__ = "0.6"
__all__ = ["HTTPServer", "BaseHTTPRequestHandler"]
-import cgi
+import html
import email.message
import email.parser
import http.client
@@ -705,7 +705,7 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
return None
list.sort(key=lambda a: a.lower())
r = []
- displaypath = cgi.escape(urllib.parse.unquote(self.path))
+ displaypath = html.escape(urllib.parse.unquote(self.path))
r.append('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
r.append("<html>\n<title>Directory listing for %s</title>\n" % displaypath)
r.append("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath)
@@ -721,7 +721,7 @@ class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
displayname = name + "@"
# Note: a link to a directory displays with @ and links with /
r.append('<li><a href="%s">%s</a>\n'
- % (urllib.parse.quote(linkname), cgi.escape(displayname)))
+ % (urllib.parse.quote(linkname), html.escape(displayname)))
r.append("</ul>\n<hr>\n</body>\n</html>\n")
enc = sys.getfilesystemencoding()
encoded = ''.join(r).encode(enc)
diff --git a/Lib/lib2to3/tests/test_util.py b/Lib/lib2to3/tests/test_util.py
index 0ab7537..d2be82c 100644
--- a/Lib/lib2to3/tests/test_util.py
+++ b/Lib/lib2to3/tests/test_util.py
@@ -568,8 +568,8 @@ class Test_touch_import(support.TestCase):
def test_from_import(self):
node = parse('bar()')
- fixer_util.touch_import("cgi", "escape", node)
- self.assertEqual(str(node), 'from cgi import escape\nbar()\n\n')
+ fixer_util.touch_import("html", "escape", node)
+ self.assertEqual(str(node), 'from html import escape\nbar()\n\n')
def test_name_import(self):
node = parse('bar()')
diff --git a/Lib/test/test_html.py b/Lib/test/test_html.py
new file mode 100644
index 0000000..30dac58
--- /dev/null
+++ b/Lib/test/test_html.py
@@ -0,0 +1,24 @@
+"""
+Tests for the html module functions.
+"""
+
+import html
+import unittest
+from test.support import run_unittest
+
+
+class HtmlTests(unittest.TestCase):
+ def test_escape(self):
+ self.assertEqual(
+ html.escape('\'<script>"&foo;"</script>\''),
+ '&#x27;&lt;script&gt;&quot;&amp;foo;&quot;&lt;/script&gt;&#x27;')
+ self.assertEqual(
+ html.escape('\'<script>"&foo;"</script>\'', False),
+ '\'&lt;script&gt;"&amp;foo;"&lt;/script&gt;\'')
+
+
+def test_main():
+ run_unittest(HtmlTests)
+
+if __name__ == '__main__':
+ test_main()
diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py
index 7914d1f..e802359 100644
--- a/Lib/test/test_xml_etree.py
+++ b/Lib/test/test_xml_etree.py
@@ -12,7 +12,7 @@
# except if the test is specific to the Python implementation.
import sys
-import cgi
+import html
import unittest
from test import support
@@ -1328,7 +1328,7 @@ XINCLUDE["default.xml"] = """\
<p>Example.</p>
<xi:include href="{}"/>
</document>
-""".format(cgi.escape(SIMPLE_XMLFILE, True))
+""".format(html.escape(SIMPLE_XMLFILE, True))
def xinclude_loader(href, parse="xml", encoding=None):
try: