From 4d14b028ffb091b58e5d62bb160e9c09907ebc63 Mon Sep 17 00:00:00 2001 From: rembo10 Date: Thu, 20 Apr 2023 14:59:25 +0530 Subject: [PATCH] update cherrypy to v18.8.0 --- lib/cherrypy/_cpdispatch.py | 8 ++------ lib/cherrypy/_cperror.py | 5 +++-- lib/cherrypy/_cpmodpy.py | 5 +---- lib/cherrypy/_cprequest.py | 7 +++++-- lib/cherrypy/lib/auth_digest.py | 13 ++++++------- lib/cherrypy/lib/covercp.py | 5 +++-- lib/cherrypy/lib/httputil.py | 30 ++++++++++++++++++++++++++++++ lib/cherrypy/lib/reprconf.py | 5 +---- lib/cherrypy/lib/sessions.py | 10 ++-------- lib/cherrypy/process/plugins.py | 3 ++- 10 files changed, 55 insertions(+), 36 deletions(-) diff --git a/lib/cherrypy/_cpdispatch.py b/lib/cherrypy/_cpdispatch.py index 83eb79cb..5c506e99 100644 --- a/lib/cherrypy/_cpdispatch.py +++ b/lib/cherrypy/_cpdispatch.py @@ -206,12 +206,8 @@ except ImportError: def test_callable_spec(callable, args, kwargs): # noqa: F811 return None else: - getargspec = inspect.getargspec - # Python 3 requires using getfullargspec if - # keyword-only arguments are present - if hasattr(inspect, 'getfullargspec'): - def getargspec(callable): - return inspect.getfullargspec(callable)[:4] + def getargspec(callable): + return inspect.getfullargspec(callable)[:4] class LateParamPageHandler(PageHandler): diff --git a/lib/cherrypy/_cperror.py b/lib/cherrypy/_cperror.py index 4e727682..f6ff2913 100644 --- a/lib/cherrypy/_cperror.py +++ b/lib/cherrypy/_cperror.py @@ -466,7 +466,7 @@ _HTTPErrorTemplate = '''%(traceback)s
- Powered by CherryPy %(version)s + Powered by CherryPy %(version)s
@@ -532,7 +532,8 @@ def get_error_page(status, **kwargs): return result else: # Load the template from this path. - template = io.open(error_page, newline='').read() + with io.open(error_page, newline='') as f: + template = f.read() except Exception: e = _format_exception(*_exc_info())[-1] m = kwargs['message'] diff --git a/lib/cherrypy/_cpmodpy.py b/lib/cherrypy/_cpmodpy.py index 0e608c48..a08f0ed9 100644 --- a/lib/cherrypy/_cpmodpy.py +++ b/lib/cherrypy/_cpmodpy.py @@ -339,11 +339,8 @@ LoadModule python_module modules/mod_python.so } mpconf = os.path.join(os.path.dirname(__file__), 'cpmodpy.conf') - f = open(mpconf, 'wb') - try: + with open(mpconf, 'wb') as f: f.write(conf_data) - finally: - f.close() response = read_process(self.apache_path, '-k start -f %s' % mpconf) self.ready = True diff --git a/lib/cherrypy/_cprequest.py b/lib/cherrypy/_cprequest.py index 9b86bd67..a661112c 100644 --- a/lib/cherrypy/_cprequest.py +++ b/lib/cherrypy/_cprequest.py @@ -169,7 +169,7 @@ def request_namespace(k, v): def response_namespace(k, v): """Attach response attributes declared in config.""" # Provides config entries to set default response headers - # http://cherrypy.org/ticket/889 + # http://cherrypy.dev/ticket/889 if k[:8] == 'headers.': cherrypy.serving.response.headers[k.split('.', 1)[1]] = v else: @@ -252,7 +252,7 @@ class Request(object): The query component of the Request-URI, a string of information to be interpreted by the resource. The query portion of a URI follows the path component, and is separated by a '?'. For example, the URI - 'http://www.cherrypy.org/wiki?a=3&b=4' has the query component, + 'http://www.cherrypy.dev/wiki?a=3&b=4' has the query component, 'a=3&b=4'.""" query_string_encoding = 'utf8' @@ -742,6 +742,9 @@ class Request(object): if self.protocol >= (1, 1): msg = "HTTP/1.1 requires a 'Host' request header." raise cherrypy.HTTPError(400, msg) + else: + headers['Host'] = httputil.SanitizedHost(dict.get(headers, 'Host')) + host = dict.get(headers, 'Host') if not host: host = self.local.name or self.local.ip diff --git a/lib/cherrypy/lib/auth_digest.py b/lib/cherrypy/lib/auth_digest.py index fbb5df64..981e9a5d 100644 --- a/lib/cherrypy/lib/auth_digest.py +++ b/lib/cherrypy/lib/auth_digest.py @@ -101,13 +101,12 @@ def get_ha1_file_htdigest(filename): """ def get_ha1(realm, username): result = None - f = open(filename, 'r') - for line in f: - u, r, ha1 = line.rstrip().split(':') - if u == username and r == realm: - result = ha1 - break - f.close() + with open(filename, 'r') as f: + for line in f: + u, r, ha1 = line.rstrip().split(':') + if u == username and r == realm: + result = ha1 + break return result return get_ha1 diff --git a/lib/cherrypy/lib/covercp.py b/lib/cherrypy/lib/covercp.py index 3e219713..6c3871fc 100644 --- a/lib/cherrypy/lib/covercp.py +++ b/lib/cherrypy/lib/covercp.py @@ -334,9 +334,10 @@ class CoverStats(object): yield '' def annotated_file(self, filename, statements, excluded, missing): - source = open(filename, 'r') + with open(filename, 'r') as source: + lines = source.readlines() buffer = [] - for lineno, line in enumerate(source.readlines()): + for lineno, line in enumerate(lines): lineno += 1 line = line.strip('\n\r') empty_the_buffer = True diff --git a/lib/cherrypy/lib/httputil.py b/lib/cherrypy/lib/httputil.py index eedf8d89..ced310a0 100644 --- a/lib/cherrypy/lib/httputil.py +++ b/lib/cherrypy/lib/httputil.py @@ -516,3 +516,33 @@ class Host(object): def __repr__(self): return 'httputil.Host(%r, %r, %r)' % (self.ip, self.port, self.name) + + +class SanitizedHost(str): + r""" + Wraps a raw host header received from the network in + a sanitized version that elides dangerous characters. + + >>> SanitizedHost('foo\nbar') + 'foobar' + >>> SanitizedHost('foo\nbar').raw + 'foo\nbar' + + A SanitizedInstance is only returned if sanitization was performed. + + >>> isinstance(SanitizedHost('foobar'), SanitizedHost) + False + """ + dangerous = re.compile(r'[\n\r]') + + def __new__(cls, raw): + sanitized = cls._sanitize(raw) + if sanitized == raw: + return raw + instance = super().__new__(cls, sanitized) + instance.raw = raw + return instance + + @classmethod + def _sanitize(cls, raw): + return cls.dangerous.sub('', raw) diff --git a/lib/cherrypy/lib/reprconf.py b/lib/cherrypy/lib/reprconf.py index 3976652e..76381d7b 100644 --- a/lib/cherrypy/lib/reprconf.py +++ b/lib/cherrypy/lib/reprconf.py @@ -163,11 +163,8 @@ class Parser(configparser.ConfigParser): # fp = open(filename) # except IOError: # continue - fp = open(filename) - try: + with open(filename) as fp: self._read(fp, filename) - finally: - fp.close() def as_dict(self, raw=False, vars=None): """Convert an INI file to a dictionary""" diff --git a/lib/cherrypy/lib/sessions.py b/lib/cherrypy/lib/sessions.py index 5b3328f2..0f56a4fa 100644 --- a/lib/cherrypy/lib/sessions.py +++ b/lib/cherrypy/lib/sessions.py @@ -516,11 +516,8 @@ class FileSession(Session): if path is None: path = self._get_file_path() try: - f = open(path, 'rb') - try: + with open(path, 'rb') as f: return pickle.load(f) - finally: - f.close() except (IOError, EOFError): e = sys.exc_info()[1] if self.debug: @@ -531,11 +528,8 @@ class FileSession(Session): def _save(self, expiration_time): assert self.locked, ('The session was saved without being locked. ' "Check your tools' priority levels.") - f = open(self._get_file_path(), 'wb') - try: + with open(self._get_file_path(), 'wb') as f: pickle.dump((self._data, expiration_time), f, self.pickle_protocol) - finally: - f.close() def _delete(self): assert self.locked, ('The session deletion without being locked. ' diff --git a/lib/cherrypy/process/plugins.py b/lib/cherrypy/process/plugins.py index 2a9952de..e96fb1ce 100644 --- a/lib/cherrypy/process/plugins.py +++ b/lib/cherrypy/process/plugins.py @@ -436,7 +436,8 @@ class PIDFile(SimplePlugin): if self.finalized: self.bus.log('PID %r already written to %r.' % (pid, self.pidfile)) else: - open(self.pidfile, 'wb').write(ntob('%s\n' % pid, 'utf8')) + with open(self.pidfile, 'wb') as f: + f.write(ntob('%s\n' % pid, 'utf8')) self.bus.log('PID %r written to %r.' % (pid, self.pidfile)) self.finalized = True start.priority = 70