diff options
Diffstat (limited to 'lib-python/3/cgi.py')
-rwxr-xr-x | lib-python/3/cgi.py | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/lib-python/3/cgi.py b/lib-python/3/cgi.py index 90a33450bc..0f50d0e705 100755 --- a/lib-python/3/cgi.py +++ b/lib-python/3/cgi.py @@ -32,10 +32,12 @@ __version__ = "2.6" # ======= from io import StringIO, BytesIO, TextIOWrapper +from collections import Mapping import sys import os import urllib.parse from email.parser import FeedParser +from email.message import Message from warnings import warn import html import locale @@ -76,7 +78,7 @@ def initlog(*allargs): send an error message). """ - global logfp, log + global log, logfile, logfp if logfile and not logfp: try: logfp = open(logfile, "a") @@ -96,6 +98,15 @@ def nolog(*allargs): """Dummy function, assigned to log when logging is disabled.""" pass +def closelog(): + """Close the log file.""" + global log, logfile, logfp + logfile = '' + if logfp: + logfp.close() + logfp = None + log = initlog + log = initlog # The current logging function @@ -214,17 +225,17 @@ def parse_multipart(fp, pdict): """ import http.client - boundary = "" + boundary = b"" if 'boundary' in pdict: boundary = pdict['boundary'] if not valid_boundary(boundary): raise ValueError('Invalid boundary in multipart form: %r' % (boundary,)) - nextpart = "--" + boundary - lastpart = "--" + boundary + "--" + nextpart = b"--" + boundary + lastpart = b"--" + boundary + b"--" partdict = {} - terminator = "" + terminator = b"" while terminator != lastpart: bytes = -1 @@ -243,7 +254,7 @@ def parse_multipart(fp, pdict): raise ValueError('Maximum content length exceeded') data = fp.read(bytes) else: - data = "" + data = b"" # Read lines until end of part. lines = [] while 1: @@ -251,7 +262,7 @@ def parse_multipart(fp, pdict): if not line: terminator = lastpart # End outer loop break - if line.startswith("--"): + if line.startswith(b"--"): terminator = line.rstrip() if terminator in (nextpart, lastpart): break @@ -263,12 +274,12 @@ def parse_multipart(fp, pdict): if lines: # Strip final line terminator line = lines[-1] - if line[-2:] == "\r\n": + if line[-2:] == b"\r\n": line = line[:-2] - elif line[-1:] == "\n": + elif line[-1:] == b"\n": line = line[:-1] lines[-1] = line - data = "".join(lines) + data = b"".join(lines) line = headers['content-disposition'] if not line: continue @@ -463,18 +474,24 @@ class FieldStorage: self.qs_on_post = environ['QUERY_STRING'] if 'CONTENT_LENGTH' in environ: headers['content-length'] = environ['CONTENT_LENGTH'] + else: + if not (isinstance(headers, (Mapping, Message))): + raise TypeError("headers must be mapping or an instance of " + "email.message.Message") + self.headers = headers if fp is None: self.fp = sys.stdin.buffer # self.fp.read() must return bytes elif isinstance(fp, TextIOWrapper): self.fp = fp.buffer else: + if not (hasattr(fp, 'read') and hasattr(fp, 'readline')): + raise TypeError("fp must be file pointer") self.fp = fp self.encoding = encoding self.errors = errors - self.headers = headers if not isinstance(outerboundary, bytes): raise TypeError('outerboundary must be bytes, not %s' % type(outerboundary).__name__) @@ -627,7 +644,9 @@ class FieldStorage: """Dictionary style len(x) support.""" return len(self.keys()) - def __nonzero__(self): + def __bool__(self): + if self.list is None: + raise TypeError("Cannot be converted to bool.") return bool(self.list) def read_urlencoded(self): @@ -690,7 +709,7 @@ class FieldStorage: self.encoding, self.errors) self.bytes_read += part.bytes_read self.list.append(part) - if self.bytes_read >= self.length: + if part.done or self.bytes_read >= self.length > 0: break self.skip_lines() @@ -777,6 +796,9 @@ class FieldStorage: if not line: self.done = -1 break + if delim == b"\r": + line = delim + line + delim = b"" if line.startswith(b"--") and last_line_lfend: strippedline = line.rstrip() if strippedline == next_boundary: @@ -793,6 +815,12 @@ class FieldStorage: delim = b"\n" line = line[:-1] last_line_lfend = True + elif line.endswith(b"\r"): + # We may interrupt \r\n sequences if they span the 2**16 + # byte boundary + delim = b"\r" + line = line[:-1] + last_line_lfend = False else: delim = b"" last_line_lfend = False @@ -1003,7 +1031,7 @@ environment as well. Here are some common variable names: def escape(s, quote=None): """Deprecated API.""" warn("cgi.escape is deprecated, use html.escape instead", - PendingDeprecationWarning, stacklevel=2) + DeprecationWarning, stacklevel=2) s = s.replace("&", "&") # Must be done first! s = s.replace("<", "<") s = s.replace(">", ">") |