diff --git a/swift/common/middleware/staticweb.py b/swift/common/middleware/staticweb.py index 43815c820f..76314efc99 100644 --- a/swift/common/middleware/staticweb.py +++ b/swift/common/middleware/staticweb.py @@ -123,13 +123,13 @@ Example usage of this middleware via ``swift``: """ -import cgi import json import six import time from six.moves.urllib.parse import urlparse +from swift.common.request_helpers import html_escape from swift.common.utils import human_readable, split_path, config_true_value, \ quote, register_swift_info, get_logger from swift.common.wsgi import make_env, WSGIContext @@ -243,7 +243,7 @@ class _StaticWebContext(WSGIContext): 'Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n' \ '\n' \ '\n' \ - 'Listing of %s\n' % cgi.escape(label) + 'Listing of %s\n' % html_escape(label) if self._listings_css: body += ' \n' % self._build_css_path(prefix or '') @@ -290,7 +290,7 @@ class _StaticWebContext(WSGIContext): '\n' \ ' \n' \ ' Listing of %s\n' % \ - cgi.escape(label) + html_escape(label) if self._listings_css: body += ' \n' % (self._build_css_path(prefix)) @@ -309,7 +309,7 @@ class _StaticWebContext(WSGIContext): ' Name\n' \ ' Size\n' \ ' Date\n' \ - ' \n' % cgi.escape(label) + ' \n' % html_escape(label) if prefix: body += ' \n' \ ' ../\n' \ @@ -327,7 +327,7 @@ class _StaticWebContext(WSGIContext): '  \n' \ '  \n' \ ' \n' % \ - (quote(subdir), cgi.escape(subdir)) + (quote(subdir), html_escape(subdir)) for item in listing: if 'name' in item: name = item['name'] if six.PY3 else \ @@ -338,17 +338,17 @@ class _StaticWebContext(WSGIContext): item['content_type'].encode('utf-8') bytes = human_readable(item['bytes']) last_modified = ( - cgi.escape(item['last_modified'] if six.PY3 else - item['last_modified'].encode('utf-8')). + html_escape(item['last_modified'] if six.PY3 else + item['last_modified'].encode('utf-8')). split('.')[0].replace('T', ' ')) body += ' \n' \ ' %s\n' \ ' %s\n' \ ' %s\n' \ ' \n' % \ - (' '.join('type-' + cgi.escape(t.lower(), quote=True) + (' '.join('type-' + html_escape(t.lower()) for t in content_type.split('/')), - quote(name), cgi.escape(name), + quote(name), html_escape(name), bytes, last_modified) body += ' \n' \ ' \n' \ diff --git a/swift/common/middleware/x_profile/html_viewer.py b/swift/common/middleware/x_profile/html_viewer.py index b7582e222a..c603fcd36d 100644 --- a/swift/common/middleware/x_profile/html_viewer.py +++ b/swift/common/middleware/x_profile/html_viewer.py @@ -13,7 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import cgi import os import random import re @@ -28,6 +27,7 @@ from swift.common.middleware.x_profile.exceptions import MethodNotAllowed from swift.common.middleware.x_profile.exceptions import DataLoadFailure from swift.common.middleware.x_profile.exceptions import ProfileException from swift.common.middleware.x_profile.profile_model import Stats2 +from swift.common.request_helpers import html_escape PLOTLIB_INSTALLED = True try: @@ -454,7 +454,7 @@ class HTMLViewer(object): fmt = '%' + max_width\ + 'd|%s' for line in lines: - l = cgi.escape(line, quote=None) + l = html_escape(line) i = i + 1 if i == lineno: fmt2 = '\ @@ -532,5 +532,5 @@ class HTMLViewer(object): -->' % (app_path, profile_id, nfls)) except Exception as ex: - html.append("Exception:" % str(ex)) + html.append("Exception:" + str(ex)) return ''.join(html) diff --git a/swift/common/request_helpers.py b/swift/common/request_helpers.py index 03d571f1f8..e4ab41d3b6 100644 --- a/swift/common/request_helpers.py +++ b/swift/common/request_helpers.py @@ -48,6 +48,15 @@ OBJECT_SYSMETA_CONTAINER_UPDATE_OVERRIDE_PREFIX = \ 'x-object-sysmeta-container-update-override-' +if six.PY2: + import cgi + + def html_escape(s, quote=True): + return cgi.escape(s, quote=quote) +else: + from html import escape as html_escape # noqa: F401 + + def get_param(req, name, default=None): """ Get parameters from an HTTP request ensuring proper handling UTF-8 diff --git a/test/unit/common/middleware/s3api/test_bucket.py b/test/unit/common/middleware/s3api/test_bucket.py index f021368740..68c47c2f05 100644 --- a/test/unit/common/middleware/s3api/test_bucket.py +++ b/test/unit/common/middleware/s3api/test_bucket.py @@ -14,11 +14,10 @@ # limitations under the License. import unittest -import cgi import mock import six -from six.moves.urllib.parse import quote +from six.moves.urllib.parse import quote, parse_qsl from swift.common import swob from swift.common.swob import Request @@ -357,7 +356,7 @@ class TestS3ApiBucket(S3ApiTestCase): self.assertEqual(elem.find('./MaxKeys').text, '5') _, path = self.swift.calls[-1] _, query_string = path.split('?') - args = dict(cgi.parse_qsl(query_string)) + args = dict(parse_qsl(query_string)) self.assertEqual(args['limit'], '6') req = Request.blank('/%s?max-keys=5000' % bucket_name, @@ -369,7 +368,7 @@ class TestS3ApiBucket(S3ApiTestCase): self.assertEqual(elem.find('./MaxKeys').text, '5000') _, path = self.swift.calls[-1] _, query_string = path.split('?') - args = dict(cgi.parse_qsl(query_string)) + args = dict(parse_qsl(query_string)) self.assertEqual(args['limit'], '1001') def test_bucket_GET_str_max_keys(self): @@ -416,7 +415,7 @@ class TestS3ApiBucket(S3ApiTestCase): self.assertEqual(elem.find('./Delimiter').text, 'a') _, path = self.swift.calls[-1] _, query_string = path.split('?') - args = dict(cgi.parse_qsl(query_string)) + args = dict(parse_qsl(query_string)) self.assertEqual(args['delimiter'], 'a') self.assertEqual(args['marker'], 'b') self.assertEqual(args['prefix'], 'c') @@ -435,7 +434,7 @@ class TestS3ApiBucket(S3ApiTestCase): self.assertEqual(elem.find('./Delimiter').text, 'a') _, path = self.swift.calls[-1] _, query_string = path.split('?') - args = dict(cgi.parse_qsl(query_string)) + args = dict(parse_qsl(query_string)) self.assertEqual(args['delimiter'], 'a') # "start-after" is converted to "marker" self.assertEqual(args['marker'], 'b') @@ -456,7 +455,7 @@ class TestS3ApiBucket(S3ApiTestCase): self.assertEqual(elem.find('./Delimiter').text, '\xef\xbc\xa1') _, path = self.swift.calls[-1] _, query_string = path.split('?') - args = dict(cgi.parse_qsl(query_string)) + args = dict(parse_qsl(query_string)) self.assertEqual(args['delimiter'], '\xef\xbc\xa1') self.assertEqual(args['marker'], '\xef\xbc\xa2') self.assertEqual(args['prefix'], '\xef\xbc\xa3') @@ -476,7 +475,7 @@ class TestS3ApiBucket(S3ApiTestCase): self.assertEqual(elem.find('./Delimiter').text, '\xef\xbc\xa1') _, path = self.swift.calls[-1] _, query_string = path.split('?') - args = dict(cgi.parse_qsl(query_string)) + args = dict(parse_qsl(query_string)) self.assertEqual(args['delimiter'], '\xef\xbc\xa1') self.assertEqual(args['marker'], '\xef\xbc\xa2') self.assertEqual(args['prefix'], '\xef\xbc\xa3')