xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/cgi.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker#! /usr/local/bin/python
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard Worker# NOTE: the above "/usr/local/bin/python" is NOT a mistake.  It is
4*cda5da8dSAndroid Build Coastguard Worker# intentionally NOT "/usr/bin/env python".  On many systems
5*cda5da8dSAndroid Build Coastguard Worker# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI
6*cda5da8dSAndroid Build Coastguard Worker# scripts, and /usr/local/bin is the default directory where Python is
7*cda5da8dSAndroid Build Coastguard Worker# installed, so /usr/bin/env would be unable to find python.  Granted,
8*cda5da8dSAndroid Build Coastguard Worker# binary installations by Linux vendors often install Python in
9*cda5da8dSAndroid Build Coastguard Worker# /usr/bin.  So let those vendors patch cgi.py to match their choice
10*cda5da8dSAndroid Build Coastguard Worker# of installation.
11*cda5da8dSAndroid Build Coastguard Worker
12*cda5da8dSAndroid Build Coastguard Worker"""Support module for CGI (Common Gateway Interface) scripts.
13*cda5da8dSAndroid Build Coastguard Worker
14*cda5da8dSAndroid Build Coastguard WorkerThis module defines a number of utilities for use by CGI scripts
15*cda5da8dSAndroid Build Coastguard Workerwritten in Python.
16*cda5da8dSAndroid Build Coastguard Worker
17*cda5da8dSAndroid Build Coastguard WorkerThe global variable maxlen can be set to an integer indicating the maximum size
18*cda5da8dSAndroid Build Coastguard Workerof a POST request. POST requests larger than this size will result in a
19*cda5da8dSAndroid Build Coastguard WorkerValueError being raised during parsing. The default value of this variable is 0,
20*cda5da8dSAndroid Build Coastguard Workermeaning the request size is unlimited.
21*cda5da8dSAndroid Build Coastguard Worker"""
22*cda5da8dSAndroid Build Coastguard Worker
23*cda5da8dSAndroid Build Coastguard Worker# History
24*cda5da8dSAndroid Build Coastguard Worker# -------
25*cda5da8dSAndroid Build Coastguard Worker#
26*cda5da8dSAndroid Build Coastguard Worker# Michael McLay started this module.  Steve Majewski changed the
27*cda5da8dSAndroid Build Coastguard Worker# interface to SvFormContentDict and FormContentDict.  The multipart
28*cda5da8dSAndroid Build Coastguard Worker# parsing was inspired by code submitted by Andreas Paepcke.  Guido van
29*cda5da8dSAndroid Build Coastguard Worker# Rossum rewrote, reformatted and documented the module and is currently
30*cda5da8dSAndroid Build Coastguard Worker# responsible for its maintenance.
31*cda5da8dSAndroid Build Coastguard Worker#
32*cda5da8dSAndroid Build Coastguard Worker
33*cda5da8dSAndroid Build Coastguard Worker__version__ = "2.6"
34*cda5da8dSAndroid Build Coastguard Worker
35*cda5da8dSAndroid Build Coastguard Worker
36*cda5da8dSAndroid Build Coastguard Worker# Imports
37*cda5da8dSAndroid Build Coastguard Worker# =======
38*cda5da8dSAndroid Build Coastguard Worker
39*cda5da8dSAndroid Build Coastguard Workerfrom io import StringIO, BytesIO, TextIOWrapper
40*cda5da8dSAndroid Build Coastguard Workerfrom collections.abc import Mapping
41*cda5da8dSAndroid Build Coastguard Workerimport sys
42*cda5da8dSAndroid Build Coastguard Workerimport os
43*cda5da8dSAndroid Build Coastguard Workerimport urllib.parse
44*cda5da8dSAndroid Build Coastguard Workerfrom email.parser import FeedParser
45*cda5da8dSAndroid Build Coastguard Workerfrom email.message import Message
46*cda5da8dSAndroid Build Coastguard Workerimport html
47*cda5da8dSAndroid Build Coastguard Workerimport locale
48*cda5da8dSAndroid Build Coastguard Workerimport tempfile
49*cda5da8dSAndroid Build Coastguard Workerimport warnings
50*cda5da8dSAndroid Build Coastguard Worker
51*cda5da8dSAndroid Build Coastguard Worker__all__ = ["MiniFieldStorage", "FieldStorage", "parse", "parse_multipart",
52*cda5da8dSAndroid Build Coastguard Worker           "parse_header", "test", "print_exception", "print_environ",
53*cda5da8dSAndroid Build Coastguard Worker           "print_form", "print_directory", "print_arguments",
54*cda5da8dSAndroid Build Coastguard Worker           "print_environ_usage"]
55*cda5da8dSAndroid Build Coastguard Worker
56*cda5da8dSAndroid Build Coastguard Worker
57*cda5da8dSAndroid Build Coastguard Workerwarnings._deprecated(__name__, remove=(3,13))
58*cda5da8dSAndroid Build Coastguard Worker
59*cda5da8dSAndroid Build Coastguard Worker# Logging support
60*cda5da8dSAndroid Build Coastguard Worker# ===============
61*cda5da8dSAndroid Build Coastguard Worker
62*cda5da8dSAndroid Build Coastguard Workerlogfile = ""            # Filename to log to, if not empty
63*cda5da8dSAndroid Build Coastguard Workerlogfp = None            # File object to log to, if not None
64*cda5da8dSAndroid Build Coastguard Worker
65*cda5da8dSAndroid Build Coastguard Workerdef initlog(*allargs):
66*cda5da8dSAndroid Build Coastguard Worker    """Write a log message, if there is a log file.
67*cda5da8dSAndroid Build Coastguard Worker
68*cda5da8dSAndroid Build Coastguard Worker    Even though this function is called initlog(), you should always
69*cda5da8dSAndroid Build Coastguard Worker    use log(); log is a variable that is set either to initlog
70*cda5da8dSAndroid Build Coastguard Worker    (initially), to dolog (once the log file has been opened), or to
71*cda5da8dSAndroid Build Coastguard Worker    nolog (when logging is disabled).
72*cda5da8dSAndroid Build Coastguard Worker
73*cda5da8dSAndroid Build Coastguard Worker    The first argument is a format string; the remaining arguments (if
74*cda5da8dSAndroid Build Coastguard Worker    any) are arguments to the % operator, so e.g.
75*cda5da8dSAndroid Build Coastguard Worker        log("%s: %s", "a", "b")
76*cda5da8dSAndroid Build Coastguard Worker    will write "a: b" to the log file, followed by a newline.
77*cda5da8dSAndroid Build Coastguard Worker
78*cda5da8dSAndroid Build Coastguard Worker    If the global logfp is not None, it should be a file object to
79*cda5da8dSAndroid Build Coastguard Worker    which log data is written.
80*cda5da8dSAndroid Build Coastguard Worker
81*cda5da8dSAndroid Build Coastguard Worker    If the global logfp is None, the global logfile may be a string
82*cda5da8dSAndroid Build Coastguard Worker    giving a filename to open, in append mode.  This file should be
83*cda5da8dSAndroid Build Coastguard Worker    world writable!!!  If the file can't be opened, logging is
84*cda5da8dSAndroid Build Coastguard Worker    silently disabled (since there is no safe place where we could
85*cda5da8dSAndroid Build Coastguard Worker    send an error message).
86*cda5da8dSAndroid Build Coastguard Worker
87*cda5da8dSAndroid Build Coastguard Worker    """
88*cda5da8dSAndroid Build Coastguard Worker    global log, logfile, logfp
89*cda5da8dSAndroid Build Coastguard Worker    warnings.warn("cgi.log() is deprecated as of 3.10. Use logging instead",
90*cda5da8dSAndroid Build Coastguard Worker                  DeprecationWarning, stacklevel=2)
91*cda5da8dSAndroid Build Coastguard Worker    if logfile and not logfp:
92*cda5da8dSAndroid Build Coastguard Worker        try:
93*cda5da8dSAndroid Build Coastguard Worker            logfp = open(logfile, "a", encoding="locale")
94*cda5da8dSAndroid Build Coastguard Worker        except OSError:
95*cda5da8dSAndroid Build Coastguard Worker            pass
96*cda5da8dSAndroid Build Coastguard Worker    if not logfp:
97*cda5da8dSAndroid Build Coastguard Worker        log = nolog
98*cda5da8dSAndroid Build Coastguard Worker    else:
99*cda5da8dSAndroid Build Coastguard Worker        log = dolog
100*cda5da8dSAndroid Build Coastguard Worker    log(*allargs)
101*cda5da8dSAndroid Build Coastguard Worker
102*cda5da8dSAndroid Build Coastguard Workerdef dolog(fmt, *args):
103*cda5da8dSAndroid Build Coastguard Worker    """Write a log message to the log file.  See initlog() for docs."""
104*cda5da8dSAndroid Build Coastguard Worker    logfp.write(fmt%args + "\n")
105*cda5da8dSAndroid Build Coastguard Worker
106*cda5da8dSAndroid Build Coastguard Workerdef nolog(*allargs):
107*cda5da8dSAndroid Build Coastguard Worker    """Dummy function, assigned to log when logging is disabled."""
108*cda5da8dSAndroid Build Coastguard Worker    pass
109*cda5da8dSAndroid Build Coastguard Worker
110*cda5da8dSAndroid Build Coastguard Workerdef closelog():
111*cda5da8dSAndroid Build Coastguard Worker    """Close the log file."""
112*cda5da8dSAndroid Build Coastguard Worker    global log, logfile, logfp
113*cda5da8dSAndroid Build Coastguard Worker    logfile = ''
114*cda5da8dSAndroid Build Coastguard Worker    if logfp:
115*cda5da8dSAndroid Build Coastguard Worker        logfp.close()
116*cda5da8dSAndroid Build Coastguard Worker        logfp = None
117*cda5da8dSAndroid Build Coastguard Worker    log = initlog
118*cda5da8dSAndroid Build Coastguard Worker
119*cda5da8dSAndroid Build Coastguard Workerlog = initlog           # The current logging function
120*cda5da8dSAndroid Build Coastguard Worker
121*cda5da8dSAndroid Build Coastguard Worker
122*cda5da8dSAndroid Build Coastguard Worker# Parsing functions
123*cda5da8dSAndroid Build Coastguard Worker# =================
124*cda5da8dSAndroid Build Coastguard Worker
125*cda5da8dSAndroid Build Coastguard Worker# Maximum input we will accept when REQUEST_METHOD is POST
126*cda5da8dSAndroid Build Coastguard Worker# 0 ==> unlimited input
127*cda5da8dSAndroid Build Coastguard Workermaxlen = 0
128*cda5da8dSAndroid Build Coastguard Worker
129*cda5da8dSAndroid Build Coastguard Workerdef parse(fp=None, environ=os.environ, keep_blank_values=0,
130*cda5da8dSAndroid Build Coastguard Worker          strict_parsing=0, separator='&'):
131*cda5da8dSAndroid Build Coastguard Worker    """Parse a query in the environment or from a file (default stdin)
132*cda5da8dSAndroid Build Coastguard Worker
133*cda5da8dSAndroid Build Coastguard Worker        Arguments, all optional:
134*cda5da8dSAndroid Build Coastguard Worker
135*cda5da8dSAndroid Build Coastguard Worker        fp              : file pointer; default: sys.stdin.buffer
136*cda5da8dSAndroid Build Coastguard Worker
137*cda5da8dSAndroid Build Coastguard Worker        environ         : environment dictionary; default: os.environ
138*cda5da8dSAndroid Build Coastguard Worker
139*cda5da8dSAndroid Build Coastguard Worker        keep_blank_values: flag indicating whether blank values in
140*cda5da8dSAndroid Build Coastguard Worker            percent-encoded forms should be treated as blank strings.
141*cda5da8dSAndroid Build Coastguard Worker            A true value indicates that blanks should be retained as
142*cda5da8dSAndroid Build Coastguard Worker            blank strings.  The default false value indicates that
143*cda5da8dSAndroid Build Coastguard Worker            blank values are to be ignored and treated as if they were
144*cda5da8dSAndroid Build Coastguard Worker            not included.
145*cda5da8dSAndroid Build Coastguard Worker
146*cda5da8dSAndroid Build Coastguard Worker        strict_parsing: flag indicating what to do with parsing errors.
147*cda5da8dSAndroid Build Coastguard Worker            If false (the default), errors are silently ignored.
148*cda5da8dSAndroid Build Coastguard Worker            If true, errors raise a ValueError exception.
149*cda5da8dSAndroid Build Coastguard Worker
150*cda5da8dSAndroid Build Coastguard Worker        separator: str. The symbol to use for separating the query arguments.
151*cda5da8dSAndroid Build Coastguard Worker            Defaults to &.
152*cda5da8dSAndroid Build Coastguard Worker    """
153*cda5da8dSAndroid Build Coastguard Worker    if fp is None:
154*cda5da8dSAndroid Build Coastguard Worker        fp = sys.stdin
155*cda5da8dSAndroid Build Coastguard Worker
156*cda5da8dSAndroid Build Coastguard Worker    # field keys and values (except for files) are returned as strings
157*cda5da8dSAndroid Build Coastguard Worker    # an encoding is required to decode the bytes read from self.fp
158*cda5da8dSAndroid Build Coastguard Worker    if hasattr(fp,'encoding'):
159*cda5da8dSAndroid Build Coastguard Worker        encoding = fp.encoding
160*cda5da8dSAndroid Build Coastguard Worker    else:
161*cda5da8dSAndroid Build Coastguard Worker        encoding = 'latin-1'
162*cda5da8dSAndroid Build Coastguard Worker
163*cda5da8dSAndroid Build Coastguard Worker    # fp.read() must return bytes
164*cda5da8dSAndroid Build Coastguard Worker    if isinstance(fp, TextIOWrapper):
165*cda5da8dSAndroid Build Coastguard Worker        fp = fp.buffer
166*cda5da8dSAndroid Build Coastguard Worker
167*cda5da8dSAndroid Build Coastguard Worker    if not 'REQUEST_METHOD' in environ:
168*cda5da8dSAndroid Build Coastguard Worker        environ['REQUEST_METHOD'] = 'GET'       # For testing stand-alone
169*cda5da8dSAndroid Build Coastguard Worker    if environ['REQUEST_METHOD'] == 'POST':
170*cda5da8dSAndroid Build Coastguard Worker        ctype, pdict = parse_header(environ['CONTENT_TYPE'])
171*cda5da8dSAndroid Build Coastguard Worker        if ctype == 'multipart/form-data':
172*cda5da8dSAndroid Build Coastguard Worker            return parse_multipart(fp, pdict, separator=separator)
173*cda5da8dSAndroid Build Coastguard Worker        elif ctype == 'application/x-www-form-urlencoded':
174*cda5da8dSAndroid Build Coastguard Worker            clength = int(environ['CONTENT_LENGTH'])
175*cda5da8dSAndroid Build Coastguard Worker            if maxlen and clength > maxlen:
176*cda5da8dSAndroid Build Coastguard Worker                raise ValueError('Maximum content length exceeded')
177*cda5da8dSAndroid Build Coastguard Worker            qs = fp.read(clength).decode(encoding)
178*cda5da8dSAndroid Build Coastguard Worker        else:
179*cda5da8dSAndroid Build Coastguard Worker            qs = ''                     # Unknown content-type
180*cda5da8dSAndroid Build Coastguard Worker        if 'QUERY_STRING' in environ:
181*cda5da8dSAndroid Build Coastguard Worker            if qs: qs = qs + '&'
182*cda5da8dSAndroid Build Coastguard Worker            qs = qs + environ['QUERY_STRING']
183*cda5da8dSAndroid Build Coastguard Worker        elif sys.argv[1:]:
184*cda5da8dSAndroid Build Coastguard Worker            if qs: qs = qs + '&'
185*cda5da8dSAndroid Build Coastguard Worker            qs = qs + sys.argv[1]
186*cda5da8dSAndroid Build Coastguard Worker        environ['QUERY_STRING'] = qs    # XXX Shouldn't, really
187*cda5da8dSAndroid Build Coastguard Worker    elif 'QUERY_STRING' in environ:
188*cda5da8dSAndroid Build Coastguard Worker        qs = environ['QUERY_STRING']
189*cda5da8dSAndroid Build Coastguard Worker    else:
190*cda5da8dSAndroid Build Coastguard Worker        if sys.argv[1:]:
191*cda5da8dSAndroid Build Coastguard Worker            qs = sys.argv[1]
192*cda5da8dSAndroid Build Coastguard Worker        else:
193*cda5da8dSAndroid Build Coastguard Worker            qs = ""
194*cda5da8dSAndroid Build Coastguard Worker        environ['QUERY_STRING'] = qs    # XXX Shouldn't, really
195*cda5da8dSAndroid Build Coastguard Worker    return urllib.parse.parse_qs(qs, keep_blank_values, strict_parsing,
196*cda5da8dSAndroid Build Coastguard Worker                                 encoding=encoding, separator=separator)
197*cda5da8dSAndroid Build Coastguard Worker
198*cda5da8dSAndroid Build Coastguard Worker
199*cda5da8dSAndroid Build Coastguard Workerdef parse_multipart(fp, pdict, encoding="utf-8", errors="replace", separator='&'):
200*cda5da8dSAndroid Build Coastguard Worker    """Parse multipart input.
201*cda5da8dSAndroid Build Coastguard Worker
202*cda5da8dSAndroid Build Coastguard Worker    Arguments:
203*cda5da8dSAndroid Build Coastguard Worker    fp   : input file
204*cda5da8dSAndroid Build Coastguard Worker    pdict: dictionary containing other parameters of content-type header
205*cda5da8dSAndroid Build Coastguard Worker    encoding, errors: request encoding and error handler, passed to
206*cda5da8dSAndroid Build Coastguard Worker        FieldStorage
207*cda5da8dSAndroid Build Coastguard Worker
208*cda5da8dSAndroid Build Coastguard Worker    Returns a dictionary just like parse_qs(): keys are the field names, each
209*cda5da8dSAndroid Build Coastguard Worker    value is a list of values for that field. For non-file fields, the value
210*cda5da8dSAndroid Build Coastguard Worker    is a list of strings.
211*cda5da8dSAndroid Build Coastguard Worker    """
212*cda5da8dSAndroid Build Coastguard Worker    # RFC 2046, Section 5.1 : The "multipart" boundary delimiters are always
213*cda5da8dSAndroid Build Coastguard Worker    # represented as 7bit US-ASCII.
214*cda5da8dSAndroid Build Coastguard Worker    boundary = pdict['boundary'].decode('ascii')
215*cda5da8dSAndroid Build Coastguard Worker    ctype = "multipart/form-data; boundary={}".format(boundary)
216*cda5da8dSAndroid Build Coastguard Worker    headers = Message()
217*cda5da8dSAndroid Build Coastguard Worker    headers.set_type(ctype)
218*cda5da8dSAndroid Build Coastguard Worker    try:
219*cda5da8dSAndroid Build Coastguard Worker        headers['Content-Length'] = pdict['CONTENT-LENGTH']
220*cda5da8dSAndroid Build Coastguard Worker    except KeyError:
221*cda5da8dSAndroid Build Coastguard Worker        pass
222*cda5da8dSAndroid Build Coastguard Worker    fs = FieldStorage(fp, headers=headers, encoding=encoding, errors=errors,
223*cda5da8dSAndroid Build Coastguard Worker        environ={'REQUEST_METHOD': 'POST'}, separator=separator)
224*cda5da8dSAndroid Build Coastguard Worker    return {k: fs.getlist(k) for k in fs}
225*cda5da8dSAndroid Build Coastguard Worker
226*cda5da8dSAndroid Build Coastguard Workerdef _parseparam(s):
227*cda5da8dSAndroid Build Coastguard Worker    while s[:1] == ';':
228*cda5da8dSAndroid Build Coastguard Worker        s = s[1:]
229*cda5da8dSAndroid Build Coastguard Worker        end = s.find(';')
230*cda5da8dSAndroid Build Coastguard Worker        while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
231*cda5da8dSAndroid Build Coastguard Worker            end = s.find(';', end + 1)
232*cda5da8dSAndroid Build Coastguard Worker        if end < 0:
233*cda5da8dSAndroid Build Coastguard Worker            end = len(s)
234*cda5da8dSAndroid Build Coastguard Worker        f = s[:end]
235*cda5da8dSAndroid Build Coastguard Worker        yield f.strip()
236*cda5da8dSAndroid Build Coastguard Worker        s = s[end:]
237*cda5da8dSAndroid Build Coastguard Worker
238*cda5da8dSAndroid Build Coastguard Workerdef parse_header(line):
239*cda5da8dSAndroid Build Coastguard Worker    """Parse a Content-type like header.
240*cda5da8dSAndroid Build Coastguard Worker
241*cda5da8dSAndroid Build Coastguard Worker    Return the main content-type and a dictionary of options.
242*cda5da8dSAndroid Build Coastguard Worker
243*cda5da8dSAndroid Build Coastguard Worker    """
244*cda5da8dSAndroid Build Coastguard Worker    parts = _parseparam(';' + line)
245*cda5da8dSAndroid Build Coastguard Worker    key = parts.__next__()
246*cda5da8dSAndroid Build Coastguard Worker    pdict = {}
247*cda5da8dSAndroid Build Coastguard Worker    for p in parts:
248*cda5da8dSAndroid Build Coastguard Worker        i = p.find('=')
249*cda5da8dSAndroid Build Coastguard Worker        if i >= 0:
250*cda5da8dSAndroid Build Coastguard Worker            name = p[:i].strip().lower()
251*cda5da8dSAndroid Build Coastguard Worker            value = p[i+1:].strip()
252*cda5da8dSAndroid Build Coastguard Worker            if len(value) >= 2 and value[0] == value[-1] == '"':
253*cda5da8dSAndroid Build Coastguard Worker                value = value[1:-1]
254*cda5da8dSAndroid Build Coastguard Worker                value = value.replace('\\\\', '\\').replace('\\"', '"')
255*cda5da8dSAndroid Build Coastguard Worker            pdict[name] = value
256*cda5da8dSAndroid Build Coastguard Worker    return key, pdict
257*cda5da8dSAndroid Build Coastguard Worker
258*cda5da8dSAndroid Build Coastguard Worker
259*cda5da8dSAndroid Build Coastguard Worker# Classes for field storage
260*cda5da8dSAndroid Build Coastguard Worker# =========================
261*cda5da8dSAndroid Build Coastguard Worker
262*cda5da8dSAndroid Build Coastguard Workerclass MiniFieldStorage:
263*cda5da8dSAndroid Build Coastguard Worker
264*cda5da8dSAndroid Build Coastguard Worker    """Like FieldStorage, for use when no file uploads are possible."""
265*cda5da8dSAndroid Build Coastguard Worker
266*cda5da8dSAndroid Build Coastguard Worker    # Dummy attributes
267*cda5da8dSAndroid Build Coastguard Worker    filename = None
268*cda5da8dSAndroid Build Coastguard Worker    list = None
269*cda5da8dSAndroid Build Coastguard Worker    type = None
270*cda5da8dSAndroid Build Coastguard Worker    file = None
271*cda5da8dSAndroid Build Coastguard Worker    type_options = {}
272*cda5da8dSAndroid Build Coastguard Worker    disposition = None
273*cda5da8dSAndroid Build Coastguard Worker    disposition_options = {}
274*cda5da8dSAndroid Build Coastguard Worker    headers = {}
275*cda5da8dSAndroid Build Coastguard Worker
276*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, name, value):
277*cda5da8dSAndroid Build Coastguard Worker        """Constructor from field name and value."""
278*cda5da8dSAndroid Build Coastguard Worker        self.name = name
279*cda5da8dSAndroid Build Coastguard Worker        self.value = value
280*cda5da8dSAndroid Build Coastguard Worker        # self.file = StringIO(value)
281*cda5da8dSAndroid Build Coastguard Worker
282*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
283*cda5da8dSAndroid Build Coastguard Worker        """Return printable representation."""
284*cda5da8dSAndroid Build Coastguard Worker        return "MiniFieldStorage(%r, %r)" % (self.name, self.value)
285*cda5da8dSAndroid Build Coastguard Worker
286*cda5da8dSAndroid Build Coastguard Worker
287*cda5da8dSAndroid Build Coastguard Workerclass FieldStorage:
288*cda5da8dSAndroid Build Coastguard Worker
289*cda5da8dSAndroid Build Coastguard Worker    """Store a sequence of fields, reading multipart/form-data.
290*cda5da8dSAndroid Build Coastguard Worker
291*cda5da8dSAndroid Build Coastguard Worker    This class provides naming, typing, files stored on disk, and
292*cda5da8dSAndroid Build Coastguard Worker    more.  At the top level, it is accessible like a dictionary, whose
293*cda5da8dSAndroid Build Coastguard Worker    keys are the field names.  (Note: None can occur as a field name.)
294*cda5da8dSAndroid Build Coastguard Worker    The items are either a Python list (if there's multiple values) or
295*cda5da8dSAndroid Build Coastguard Worker    another FieldStorage or MiniFieldStorage object.  If it's a single
296*cda5da8dSAndroid Build Coastguard Worker    object, it has the following attributes:
297*cda5da8dSAndroid Build Coastguard Worker
298*cda5da8dSAndroid Build Coastguard Worker    name: the field name, if specified; otherwise None
299*cda5da8dSAndroid Build Coastguard Worker
300*cda5da8dSAndroid Build Coastguard Worker    filename: the filename, if specified; otherwise None; this is the
301*cda5da8dSAndroid Build Coastguard Worker        client side filename, *not* the file name on which it is
302*cda5da8dSAndroid Build Coastguard Worker        stored (that's a temporary file you don't deal with)
303*cda5da8dSAndroid Build Coastguard Worker
304*cda5da8dSAndroid Build Coastguard Worker    value: the value as a *string*; for file uploads, this
305*cda5da8dSAndroid Build Coastguard Worker        transparently reads the file every time you request the value
306*cda5da8dSAndroid Build Coastguard Worker        and returns *bytes*
307*cda5da8dSAndroid Build Coastguard Worker
308*cda5da8dSAndroid Build Coastguard Worker    file: the file(-like) object from which you can read the data *as
309*cda5da8dSAndroid Build Coastguard Worker        bytes* ; None if the data is stored a simple string
310*cda5da8dSAndroid Build Coastguard Worker
311*cda5da8dSAndroid Build Coastguard Worker    type: the content-type, or None if not specified
312*cda5da8dSAndroid Build Coastguard Worker
313*cda5da8dSAndroid Build Coastguard Worker    type_options: dictionary of options specified on the content-type
314*cda5da8dSAndroid Build Coastguard Worker        line
315*cda5da8dSAndroid Build Coastguard Worker
316*cda5da8dSAndroid Build Coastguard Worker    disposition: content-disposition, or None if not specified
317*cda5da8dSAndroid Build Coastguard Worker
318*cda5da8dSAndroid Build Coastguard Worker    disposition_options: dictionary of corresponding options
319*cda5da8dSAndroid Build Coastguard Worker
320*cda5da8dSAndroid Build Coastguard Worker    headers: a dictionary(-like) object (sometimes email.message.Message or a
321*cda5da8dSAndroid Build Coastguard Worker        subclass thereof) containing *all* headers
322*cda5da8dSAndroid Build Coastguard Worker
323*cda5da8dSAndroid Build Coastguard Worker    The class is subclassable, mostly for the purpose of overriding
324*cda5da8dSAndroid Build Coastguard Worker    the make_file() method, which is called internally to come up with
325*cda5da8dSAndroid Build Coastguard Worker    a file open for reading and writing.  This makes it possible to
326*cda5da8dSAndroid Build Coastguard Worker    override the default choice of storing all files in a temporary
327*cda5da8dSAndroid Build Coastguard Worker    directory and unlinking them as soon as they have been opened.
328*cda5da8dSAndroid Build Coastguard Worker
329*cda5da8dSAndroid Build Coastguard Worker    """
330*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, fp=None, headers=None, outerboundary=b'',
331*cda5da8dSAndroid Build Coastguard Worker                 environ=os.environ, keep_blank_values=0, strict_parsing=0,
332*cda5da8dSAndroid Build Coastguard Worker                 limit=None, encoding='utf-8', errors='replace',
333*cda5da8dSAndroid Build Coastguard Worker                 max_num_fields=None, separator='&'):
334*cda5da8dSAndroid Build Coastguard Worker        """Constructor.  Read multipart/* until last part.
335*cda5da8dSAndroid Build Coastguard Worker
336*cda5da8dSAndroid Build Coastguard Worker        Arguments, all optional:
337*cda5da8dSAndroid Build Coastguard Worker
338*cda5da8dSAndroid Build Coastguard Worker        fp              : file pointer; default: sys.stdin.buffer
339*cda5da8dSAndroid Build Coastguard Worker            (not used when the request method is GET)
340*cda5da8dSAndroid Build Coastguard Worker            Can be :
341*cda5da8dSAndroid Build Coastguard Worker            1. a TextIOWrapper object
342*cda5da8dSAndroid Build Coastguard Worker            2. an object whose read() and readline() methods return bytes
343*cda5da8dSAndroid Build Coastguard Worker
344*cda5da8dSAndroid Build Coastguard Worker        headers         : header dictionary-like object; default:
345*cda5da8dSAndroid Build Coastguard Worker            taken from environ as per CGI spec
346*cda5da8dSAndroid Build Coastguard Worker
347*cda5da8dSAndroid Build Coastguard Worker        outerboundary   : terminating multipart boundary
348*cda5da8dSAndroid Build Coastguard Worker            (for internal use only)
349*cda5da8dSAndroid Build Coastguard Worker
350*cda5da8dSAndroid Build Coastguard Worker        environ         : environment dictionary; default: os.environ
351*cda5da8dSAndroid Build Coastguard Worker
352*cda5da8dSAndroid Build Coastguard Worker        keep_blank_values: flag indicating whether blank values in
353*cda5da8dSAndroid Build Coastguard Worker            percent-encoded forms should be treated as blank strings.
354*cda5da8dSAndroid Build Coastguard Worker            A true value indicates that blanks should be retained as
355*cda5da8dSAndroid Build Coastguard Worker            blank strings.  The default false value indicates that
356*cda5da8dSAndroid Build Coastguard Worker            blank values are to be ignored and treated as if they were
357*cda5da8dSAndroid Build Coastguard Worker            not included.
358*cda5da8dSAndroid Build Coastguard Worker
359*cda5da8dSAndroid Build Coastguard Worker        strict_parsing: flag indicating what to do with parsing errors.
360*cda5da8dSAndroid Build Coastguard Worker            If false (the default), errors are silently ignored.
361*cda5da8dSAndroid Build Coastguard Worker            If true, errors raise a ValueError exception.
362*cda5da8dSAndroid Build Coastguard Worker
363*cda5da8dSAndroid Build Coastguard Worker        limit : used internally to read parts of multipart/form-data forms,
364*cda5da8dSAndroid Build Coastguard Worker            to exit from the reading loop when reached. It is the difference
365*cda5da8dSAndroid Build Coastguard Worker            between the form content-length and the number of bytes already
366*cda5da8dSAndroid Build Coastguard Worker            read
367*cda5da8dSAndroid Build Coastguard Worker
368*cda5da8dSAndroid Build Coastguard Worker        encoding, errors : the encoding and error handler used to decode the
369*cda5da8dSAndroid Build Coastguard Worker            binary stream to strings. Must be the same as the charset defined
370*cda5da8dSAndroid Build Coastguard Worker            for the page sending the form (content-type : meta http-equiv or
371*cda5da8dSAndroid Build Coastguard Worker            header)
372*cda5da8dSAndroid Build Coastguard Worker
373*cda5da8dSAndroid Build Coastguard Worker        max_num_fields: int. If set, then __init__ throws a ValueError
374*cda5da8dSAndroid Build Coastguard Worker            if there are more than n fields read by parse_qsl().
375*cda5da8dSAndroid Build Coastguard Worker
376*cda5da8dSAndroid Build Coastguard Worker        """
377*cda5da8dSAndroid Build Coastguard Worker        method = 'GET'
378*cda5da8dSAndroid Build Coastguard Worker        self.keep_blank_values = keep_blank_values
379*cda5da8dSAndroid Build Coastguard Worker        self.strict_parsing = strict_parsing
380*cda5da8dSAndroid Build Coastguard Worker        self.max_num_fields = max_num_fields
381*cda5da8dSAndroid Build Coastguard Worker        self.separator = separator
382*cda5da8dSAndroid Build Coastguard Worker        if 'REQUEST_METHOD' in environ:
383*cda5da8dSAndroid Build Coastguard Worker            method = environ['REQUEST_METHOD'].upper()
384*cda5da8dSAndroid Build Coastguard Worker        self.qs_on_post = None
385*cda5da8dSAndroid Build Coastguard Worker        if method == 'GET' or method == 'HEAD':
386*cda5da8dSAndroid Build Coastguard Worker            if 'QUERY_STRING' in environ:
387*cda5da8dSAndroid Build Coastguard Worker                qs = environ['QUERY_STRING']
388*cda5da8dSAndroid Build Coastguard Worker            elif sys.argv[1:]:
389*cda5da8dSAndroid Build Coastguard Worker                qs = sys.argv[1]
390*cda5da8dSAndroid Build Coastguard Worker            else:
391*cda5da8dSAndroid Build Coastguard Worker                qs = ""
392*cda5da8dSAndroid Build Coastguard Worker            qs = qs.encode(locale.getpreferredencoding(), 'surrogateescape')
393*cda5da8dSAndroid Build Coastguard Worker            fp = BytesIO(qs)
394*cda5da8dSAndroid Build Coastguard Worker            if headers is None:
395*cda5da8dSAndroid Build Coastguard Worker                headers = {'content-type':
396*cda5da8dSAndroid Build Coastguard Worker                           "application/x-www-form-urlencoded"}
397*cda5da8dSAndroid Build Coastguard Worker        if headers is None:
398*cda5da8dSAndroid Build Coastguard Worker            headers = {}
399*cda5da8dSAndroid Build Coastguard Worker            if method == 'POST':
400*cda5da8dSAndroid Build Coastguard Worker                # Set default content-type for POST to what's traditional
401*cda5da8dSAndroid Build Coastguard Worker                headers['content-type'] = "application/x-www-form-urlencoded"
402*cda5da8dSAndroid Build Coastguard Worker            if 'CONTENT_TYPE' in environ:
403*cda5da8dSAndroid Build Coastguard Worker                headers['content-type'] = environ['CONTENT_TYPE']
404*cda5da8dSAndroid Build Coastguard Worker            if 'QUERY_STRING' in environ:
405*cda5da8dSAndroid Build Coastguard Worker                self.qs_on_post = environ['QUERY_STRING']
406*cda5da8dSAndroid Build Coastguard Worker            if 'CONTENT_LENGTH' in environ:
407*cda5da8dSAndroid Build Coastguard Worker                headers['content-length'] = environ['CONTENT_LENGTH']
408*cda5da8dSAndroid Build Coastguard Worker        else:
409*cda5da8dSAndroid Build Coastguard Worker            if not (isinstance(headers, (Mapping, Message))):
410*cda5da8dSAndroid Build Coastguard Worker                raise TypeError("headers must be mapping or an instance of "
411*cda5da8dSAndroid Build Coastguard Worker                                "email.message.Message")
412*cda5da8dSAndroid Build Coastguard Worker        self.headers = headers
413*cda5da8dSAndroid Build Coastguard Worker        if fp is None:
414*cda5da8dSAndroid Build Coastguard Worker            self.fp = sys.stdin.buffer
415*cda5da8dSAndroid Build Coastguard Worker        # self.fp.read() must return bytes
416*cda5da8dSAndroid Build Coastguard Worker        elif isinstance(fp, TextIOWrapper):
417*cda5da8dSAndroid Build Coastguard Worker            self.fp = fp.buffer
418*cda5da8dSAndroid Build Coastguard Worker        else:
419*cda5da8dSAndroid Build Coastguard Worker            if not (hasattr(fp, 'read') and hasattr(fp, 'readline')):
420*cda5da8dSAndroid Build Coastguard Worker                raise TypeError("fp must be file pointer")
421*cda5da8dSAndroid Build Coastguard Worker            self.fp = fp
422*cda5da8dSAndroid Build Coastguard Worker
423*cda5da8dSAndroid Build Coastguard Worker        self.encoding = encoding
424*cda5da8dSAndroid Build Coastguard Worker        self.errors = errors
425*cda5da8dSAndroid Build Coastguard Worker
426*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(outerboundary, bytes):
427*cda5da8dSAndroid Build Coastguard Worker            raise TypeError('outerboundary must be bytes, not %s'
428*cda5da8dSAndroid Build Coastguard Worker                            % type(outerboundary).__name__)
429*cda5da8dSAndroid Build Coastguard Worker        self.outerboundary = outerboundary
430*cda5da8dSAndroid Build Coastguard Worker
431*cda5da8dSAndroid Build Coastguard Worker        self.bytes_read = 0
432*cda5da8dSAndroid Build Coastguard Worker        self.limit = limit
433*cda5da8dSAndroid Build Coastguard Worker
434*cda5da8dSAndroid Build Coastguard Worker        # Process content-disposition header
435*cda5da8dSAndroid Build Coastguard Worker        cdisp, pdict = "", {}
436*cda5da8dSAndroid Build Coastguard Worker        if 'content-disposition' in self.headers:
437*cda5da8dSAndroid Build Coastguard Worker            cdisp, pdict = parse_header(self.headers['content-disposition'])
438*cda5da8dSAndroid Build Coastguard Worker        self.disposition = cdisp
439*cda5da8dSAndroid Build Coastguard Worker        self.disposition_options = pdict
440*cda5da8dSAndroid Build Coastguard Worker        self.name = None
441*cda5da8dSAndroid Build Coastguard Worker        if 'name' in pdict:
442*cda5da8dSAndroid Build Coastguard Worker            self.name = pdict['name']
443*cda5da8dSAndroid Build Coastguard Worker        self.filename = None
444*cda5da8dSAndroid Build Coastguard Worker        if 'filename' in pdict:
445*cda5da8dSAndroid Build Coastguard Worker            self.filename = pdict['filename']
446*cda5da8dSAndroid Build Coastguard Worker        self._binary_file = self.filename is not None
447*cda5da8dSAndroid Build Coastguard Worker
448*cda5da8dSAndroid Build Coastguard Worker        # Process content-type header
449*cda5da8dSAndroid Build Coastguard Worker        #
450*cda5da8dSAndroid Build Coastguard Worker        # Honor any existing content-type header.  But if there is no
451*cda5da8dSAndroid Build Coastguard Worker        # content-type header, use some sensible defaults.  Assume
452*cda5da8dSAndroid Build Coastguard Worker        # outerboundary is "" at the outer level, but something non-false
453*cda5da8dSAndroid Build Coastguard Worker        # inside a multi-part.  The default for an inner part is text/plain,
454*cda5da8dSAndroid Build Coastguard Worker        # but for an outer part it should be urlencoded.  This should catch
455*cda5da8dSAndroid Build Coastguard Worker        # bogus clients which erroneously forget to include a content-type
456*cda5da8dSAndroid Build Coastguard Worker        # header.
457*cda5da8dSAndroid Build Coastguard Worker        #
458*cda5da8dSAndroid Build Coastguard Worker        # See below for what we do if there does exist a content-type header,
459*cda5da8dSAndroid Build Coastguard Worker        # but it happens to be something we don't understand.
460*cda5da8dSAndroid Build Coastguard Worker        if 'content-type' in self.headers:
461*cda5da8dSAndroid Build Coastguard Worker            ctype, pdict = parse_header(self.headers['content-type'])
462*cda5da8dSAndroid Build Coastguard Worker        elif self.outerboundary or method != 'POST':
463*cda5da8dSAndroid Build Coastguard Worker            ctype, pdict = "text/plain", {}
464*cda5da8dSAndroid Build Coastguard Worker        else:
465*cda5da8dSAndroid Build Coastguard Worker            ctype, pdict = 'application/x-www-form-urlencoded', {}
466*cda5da8dSAndroid Build Coastguard Worker        self.type = ctype
467*cda5da8dSAndroid Build Coastguard Worker        self.type_options = pdict
468*cda5da8dSAndroid Build Coastguard Worker        if 'boundary' in pdict:
469*cda5da8dSAndroid Build Coastguard Worker            self.innerboundary = pdict['boundary'].encode(self.encoding,
470*cda5da8dSAndroid Build Coastguard Worker                                                          self.errors)
471*cda5da8dSAndroid Build Coastguard Worker        else:
472*cda5da8dSAndroid Build Coastguard Worker            self.innerboundary = b""
473*cda5da8dSAndroid Build Coastguard Worker
474*cda5da8dSAndroid Build Coastguard Worker        clen = -1
475*cda5da8dSAndroid Build Coastguard Worker        if 'content-length' in self.headers:
476*cda5da8dSAndroid Build Coastguard Worker            try:
477*cda5da8dSAndroid Build Coastguard Worker                clen = int(self.headers['content-length'])
478*cda5da8dSAndroid Build Coastguard Worker            except ValueError:
479*cda5da8dSAndroid Build Coastguard Worker                pass
480*cda5da8dSAndroid Build Coastguard Worker            if maxlen and clen > maxlen:
481*cda5da8dSAndroid Build Coastguard Worker                raise ValueError('Maximum content length exceeded')
482*cda5da8dSAndroid Build Coastguard Worker        self.length = clen
483*cda5da8dSAndroid Build Coastguard Worker        if self.limit is None and clen >= 0:
484*cda5da8dSAndroid Build Coastguard Worker            self.limit = clen
485*cda5da8dSAndroid Build Coastguard Worker
486*cda5da8dSAndroid Build Coastguard Worker        self.list = self.file = None
487*cda5da8dSAndroid Build Coastguard Worker        self.done = 0
488*cda5da8dSAndroid Build Coastguard Worker        if ctype == 'application/x-www-form-urlencoded':
489*cda5da8dSAndroid Build Coastguard Worker            self.read_urlencoded()
490*cda5da8dSAndroid Build Coastguard Worker        elif ctype[:10] == 'multipart/':
491*cda5da8dSAndroid Build Coastguard Worker            self.read_multi(environ, keep_blank_values, strict_parsing)
492*cda5da8dSAndroid Build Coastguard Worker        else:
493*cda5da8dSAndroid Build Coastguard Worker            self.read_single()
494*cda5da8dSAndroid Build Coastguard Worker
495*cda5da8dSAndroid Build Coastguard Worker    def __del__(self):
496*cda5da8dSAndroid Build Coastguard Worker        try:
497*cda5da8dSAndroid Build Coastguard Worker            self.file.close()
498*cda5da8dSAndroid Build Coastguard Worker        except AttributeError:
499*cda5da8dSAndroid Build Coastguard Worker            pass
500*cda5da8dSAndroid Build Coastguard Worker
501*cda5da8dSAndroid Build Coastguard Worker    def __enter__(self):
502*cda5da8dSAndroid Build Coastguard Worker        return self
503*cda5da8dSAndroid Build Coastguard Worker
504*cda5da8dSAndroid Build Coastguard Worker    def __exit__(self, *args):
505*cda5da8dSAndroid Build Coastguard Worker        self.file.close()
506*cda5da8dSAndroid Build Coastguard Worker
507*cda5da8dSAndroid Build Coastguard Worker    def __repr__(self):
508*cda5da8dSAndroid Build Coastguard Worker        """Return a printable representation."""
509*cda5da8dSAndroid Build Coastguard Worker        return "FieldStorage(%r, %r, %r)" % (
510*cda5da8dSAndroid Build Coastguard Worker                self.name, self.filename, self.value)
511*cda5da8dSAndroid Build Coastguard Worker
512*cda5da8dSAndroid Build Coastguard Worker    def __iter__(self):
513*cda5da8dSAndroid Build Coastguard Worker        return iter(self.keys())
514*cda5da8dSAndroid Build Coastguard Worker
515*cda5da8dSAndroid Build Coastguard Worker    def __getattr__(self, name):
516*cda5da8dSAndroid Build Coastguard Worker        if name != 'value':
517*cda5da8dSAndroid Build Coastguard Worker            raise AttributeError(name)
518*cda5da8dSAndroid Build Coastguard Worker        if self.file:
519*cda5da8dSAndroid Build Coastguard Worker            self.file.seek(0)
520*cda5da8dSAndroid Build Coastguard Worker            value = self.file.read()
521*cda5da8dSAndroid Build Coastguard Worker            self.file.seek(0)
522*cda5da8dSAndroid Build Coastguard Worker        elif self.list is not None:
523*cda5da8dSAndroid Build Coastguard Worker            value = self.list
524*cda5da8dSAndroid Build Coastguard Worker        else:
525*cda5da8dSAndroid Build Coastguard Worker            value = None
526*cda5da8dSAndroid Build Coastguard Worker        return value
527*cda5da8dSAndroid Build Coastguard Worker
528*cda5da8dSAndroid Build Coastguard Worker    def __getitem__(self, key):
529*cda5da8dSAndroid Build Coastguard Worker        """Dictionary style indexing."""
530*cda5da8dSAndroid Build Coastguard Worker        if self.list is None:
531*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("not indexable")
532*cda5da8dSAndroid Build Coastguard Worker        found = []
533*cda5da8dSAndroid Build Coastguard Worker        for item in self.list:
534*cda5da8dSAndroid Build Coastguard Worker            if item.name == key: found.append(item)
535*cda5da8dSAndroid Build Coastguard Worker        if not found:
536*cda5da8dSAndroid Build Coastguard Worker            raise KeyError(key)
537*cda5da8dSAndroid Build Coastguard Worker        if len(found) == 1:
538*cda5da8dSAndroid Build Coastguard Worker            return found[0]
539*cda5da8dSAndroid Build Coastguard Worker        else:
540*cda5da8dSAndroid Build Coastguard Worker            return found
541*cda5da8dSAndroid Build Coastguard Worker
542*cda5da8dSAndroid Build Coastguard Worker    def getvalue(self, key, default=None):
543*cda5da8dSAndroid Build Coastguard Worker        """Dictionary style get() method, including 'value' lookup."""
544*cda5da8dSAndroid Build Coastguard Worker        if key in self:
545*cda5da8dSAndroid Build Coastguard Worker            value = self[key]
546*cda5da8dSAndroid Build Coastguard Worker            if isinstance(value, list):
547*cda5da8dSAndroid Build Coastguard Worker                return [x.value for x in value]
548*cda5da8dSAndroid Build Coastguard Worker            else:
549*cda5da8dSAndroid Build Coastguard Worker                return value.value
550*cda5da8dSAndroid Build Coastguard Worker        else:
551*cda5da8dSAndroid Build Coastguard Worker            return default
552*cda5da8dSAndroid Build Coastguard Worker
553*cda5da8dSAndroid Build Coastguard Worker    def getfirst(self, key, default=None):
554*cda5da8dSAndroid Build Coastguard Worker        """ Return the first value received."""
555*cda5da8dSAndroid Build Coastguard Worker        if key in self:
556*cda5da8dSAndroid Build Coastguard Worker            value = self[key]
557*cda5da8dSAndroid Build Coastguard Worker            if isinstance(value, list):
558*cda5da8dSAndroid Build Coastguard Worker                return value[0].value
559*cda5da8dSAndroid Build Coastguard Worker            else:
560*cda5da8dSAndroid Build Coastguard Worker                return value.value
561*cda5da8dSAndroid Build Coastguard Worker        else:
562*cda5da8dSAndroid Build Coastguard Worker            return default
563*cda5da8dSAndroid Build Coastguard Worker
564*cda5da8dSAndroid Build Coastguard Worker    def getlist(self, key):
565*cda5da8dSAndroid Build Coastguard Worker        """ Return list of received values."""
566*cda5da8dSAndroid Build Coastguard Worker        if key in self:
567*cda5da8dSAndroid Build Coastguard Worker            value = self[key]
568*cda5da8dSAndroid Build Coastguard Worker            if isinstance(value, list):
569*cda5da8dSAndroid Build Coastguard Worker                return [x.value for x in value]
570*cda5da8dSAndroid Build Coastguard Worker            else:
571*cda5da8dSAndroid Build Coastguard Worker                return [value.value]
572*cda5da8dSAndroid Build Coastguard Worker        else:
573*cda5da8dSAndroid Build Coastguard Worker            return []
574*cda5da8dSAndroid Build Coastguard Worker
575*cda5da8dSAndroid Build Coastguard Worker    def keys(self):
576*cda5da8dSAndroid Build Coastguard Worker        """Dictionary style keys() method."""
577*cda5da8dSAndroid Build Coastguard Worker        if self.list is None:
578*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("not indexable")
579*cda5da8dSAndroid Build Coastguard Worker        return list(set(item.name for item in self.list))
580*cda5da8dSAndroid Build Coastguard Worker
581*cda5da8dSAndroid Build Coastguard Worker    def __contains__(self, key):
582*cda5da8dSAndroid Build Coastguard Worker        """Dictionary style __contains__ method."""
583*cda5da8dSAndroid Build Coastguard Worker        if self.list is None:
584*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("not indexable")
585*cda5da8dSAndroid Build Coastguard Worker        return any(item.name == key for item in self.list)
586*cda5da8dSAndroid Build Coastguard Worker
587*cda5da8dSAndroid Build Coastguard Worker    def __len__(self):
588*cda5da8dSAndroid Build Coastguard Worker        """Dictionary style len(x) support."""
589*cda5da8dSAndroid Build Coastguard Worker        return len(self.keys())
590*cda5da8dSAndroid Build Coastguard Worker
591*cda5da8dSAndroid Build Coastguard Worker    def __bool__(self):
592*cda5da8dSAndroid Build Coastguard Worker        if self.list is None:
593*cda5da8dSAndroid Build Coastguard Worker            raise TypeError("Cannot be converted to bool.")
594*cda5da8dSAndroid Build Coastguard Worker        return bool(self.list)
595*cda5da8dSAndroid Build Coastguard Worker
596*cda5da8dSAndroid Build Coastguard Worker    def read_urlencoded(self):
597*cda5da8dSAndroid Build Coastguard Worker        """Internal: read data in query string format."""
598*cda5da8dSAndroid Build Coastguard Worker        qs = self.fp.read(self.length)
599*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(qs, bytes):
600*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("%s should return bytes, got %s" \
601*cda5da8dSAndroid Build Coastguard Worker                             % (self.fp, type(qs).__name__))
602*cda5da8dSAndroid Build Coastguard Worker        qs = qs.decode(self.encoding, self.errors)
603*cda5da8dSAndroid Build Coastguard Worker        if self.qs_on_post:
604*cda5da8dSAndroid Build Coastguard Worker            qs += '&' + self.qs_on_post
605*cda5da8dSAndroid Build Coastguard Worker        query = urllib.parse.parse_qsl(
606*cda5da8dSAndroid Build Coastguard Worker            qs, self.keep_blank_values, self.strict_parsing,
607*cda5da8dSAndroid Build Coastguard Worker            encoding=self.encoding, errors=self.errors,
608*cda5da8dSAndroid Build Coastguard Worker            max_num_fields=self.max_num_fields, separator=self.separator)
609*cda5da8dSAndroid Build Coastguard Worker        self.list = [MiniFieldStorage(key, value) for key, value in query]
610*cda5da8dSAndroid Build Coastguard Worker        self.skip_lines()
611*cda5da8dSAndroid Build Coastguard Worker
612*cda5da8dSAndroid Build Coastguard Worker    FieldStorageClass = None
613*cda5da8dSAndroid Build Coastguard Worker
614*cda5da8dSAndroid Build Coastguard Worker    def read_multi(self, environ, keep_blank_values, strict_parsing):
615*cda5da8dSAndroid Build Coastguard Worker        """Internal: read a part that is itself multipart."""
616*cda5da8dSAndroid Build Coastguard Worker        ib = self.innerboundary
617*cda5da8dSAndroid Build Coastguard Worker        if not valid_boundary(ib):
618*cda5da8dSAndroid Build Coastguard Worker            raise ValueError('Invalid boundary in multipart form: %r' % (ib,))
619*cda5da8dSAndroid Build Coastguard Worker        self.list = []
620*cda5da8dSAndroid Build Coastguard Worker        if self.qs_on_post:
621*cda5da8dSAndroid Build Coastguard Worker            query = urllib.parse.parse_qsl(
622*cda5da8dSAndroid Build Coastguard Worker                self.qs_on_post, self.keep_blank_values, self.strict_parsing,
623*cda5da8dSAndroid Build Coastguard Worker                encoding=self.encoding, errors=self.errors,
624*cda5da8dSAndroid Build Coastguard Worker                max_num_fields=self.max_num_fields, separator=self.separator)
625*cda5da8dSAndroid Build Coastguard Worker            self.list.extend(MiniFieldStorage(key, value) for key, value in query)
626*cda5da8dSAndroid Build Coastguard Worker
627*cda5da8dSAndroid Build Coastguard Worker        klass = self.FieldStorageClass or self.__class__
628*cda5da8dSAndroid Build Coastguard Worker        first_line = self.fp.readline() # bytes
629*cda5da8dSAndroid Build Coastguard Worker        if not isinstance(first_line, bytes):
630*cda5da8dSAndroid Build Coastguard Worker            raise ValueError("%s should return bytes, got %s" \
631*cda5da8dSAndroid Build Coastguard Worker                             % (self.fp, type(first_line).__name__))
632*cda5da8dSAndroid Build Coastguard Worker        self.bytes_read += len(first_line)
633*cda5da8dSAndroid Build Coastguard Worker
634*cda5da8dSAndroid Build Coastguard Worker        # Ensure that we consume the file until we've hit our inner boundary
635*cda5da8dSAndroid Build Coastguard Worker        while (first_line.strip() != (b"--" + self.innerboundary) and
636*cda5da8dSAndroid Build Coastguard Worker                first_line):
637*cda5da8dSAndroid Build Coastguard Worker            first_line = self.fp.readline()
638*cda5da8dSAndroid Build Coastguard Worker            self.bytes_read += len(first_line)
639*cda5da8dSAndroid Build Coastguard Worker
640*cda5da8dSAndroid Build Coastguard Worker        # Propagate max_num_fields into the sub class appropriately
641*cda5da8dSAndroid Build Coastguard Worker        max_num_fields = self.max_num_fields
642*cda5da8dSAndroid Build Coastguard Worker        if max_num_fields is not None:
643*cda5da8dSAndroid Build Coastguard Worker            max_num_fields -= len(self.list)
644*cda5da8dSAndroid Build Coastguard Worker
645*cda5da8dSAndroid Build Coastguard Worker        while True:
646*cda5da8dSAndroid Build Coastguard Worker            parser = FeedParser()
647*cda5da8dSAndroid Build Coastguard Worker            hdr_text = b""
648*cda5da8dSAndroid Build Coastguard Worker            while True:
649*cda5da8dSAndroid Build Coastguard Worker                data = self.fp.readline()
650*cda5da8dSAndroid Build Coastguard Worker                hdr_text += data
651*cda5da8dSAndroid Build Coastguard Worker                if not data.strip():
652*cda5da8dSAndroid Build Coastguard Worker                    break
653*cda5da8dSAndroid Build Coastguard Worker            if not hdr_text:
654*cda5da8dSAndroid Build Coastguard Worker                break
655*cda5da8dSAndroid Build Coastguard Worker            # parser takes strings, not bytes
656*cda5da8dSAndroid Build Coastguard Worker            self.bytes_read += len(hdr_text)
657*cda5da8dSAndroid Build Coastguard Worker            parser.feed(hdr_text.decode(self.encoding, self.errors))
658*cda5da8dSAndroid Build Coastguard Worker            headers = parser.close()
659*cda5da8dSAndroid Build Coastguard Worker
660*cda5da8dSAndroid Build Coastguard Worker            # Some clients add Content-Length for part headers, ignore them
661*cda5da8dSAndroid Build Coastguard Worker            if 'content-length' in headers:
662*cda5da8dSAndroid Build Coastguard Worker                del headers['content-length']
663*cda5da8dSAndroid Build Coastguard Worker
664*cda5da8dSAndroid Build Coastguard Worker            limit = None if self.limit is None \
665*cda5da8dSAndroid Build Coastguard Worker                else self.limit - self.bytes_read
666*cda5da8dSAndroid Build Coastguard Worker            part = klass(self.fp, headers, ib, environ, keep_blank_values,
667*cda5da8dSAndroid Build Coastguard Worker                         strict_parsing, limit,
668*cda5da8dSAndroid Build Coastguard Worker                         self.encoding, self.errors, max_num_fields, self.separator)
669*cda5da8dSAndroid Build Coastguard Worker
670*cda5da8dSAndroid Build Coastguard Worker            if max_num_fields is not None:
671*cda5da8dSAndroid Build Coastguard Worker                max_num_fields -= 1
672*cda5da8dSAndroid Build Coastguard Worker                if part.list:
673*cda5da8dSAndroid Build Coastguard Worker                    max_num_fields -= len(part.list)
674*cda5da8dSAndroid Build Coastguard Worker                if max_num_fields < 0:
675*cda5da8dSAndroid Build Coastguard Worker                    raise ValueError('Max number of fields exceeded')
676*cda5da8dSAndroid Build Coastguard Worker
677*cda5da8dSAndroid Build Coastguard Worker            self.bytes_read += part.bytes_read
678*cda5da8dSAndroid Build Coastguard Worker            self.list.append(part)
679*cda5da8dSAndroid Build Coastguard Worker            if part.done or self.bytes_read >= self.length > 0:
680*cda5da8dSAndroid Build Coastguard Worker                break
681*cda5da8dSAndroid Build Coastguard Worker        self.skip_lines()
682*cda5da8dSAndroid Build Coastguard Worker
683*cda5da8dSAndroid Build Coastguard Worker    def read_single(self):
684*cda5da8dSAndroid Build Coastguard Worker        """Internal: read an atomic part."""
685*cda5da8dSAndroid Build Coastguard Worker        if self.length >= 0:
686*cda5da8dSAndroid Build Coastguard Worker            self.read_binary()
687*cda5da8dSAndroid Build Coastguard Worker            self.skip_lines()
688*cda5da8dSAndroid Build Coastguard Worker        else:
689*cda5da8dSAndroid Build Coastguard Worker            self.read_lines()
690*cda5da8dSAndroid Build Coastguard Worker        self.file.seek(0)
691*cda5da8dSAndroid Build Coastguard Worker
692*cda5da8dSAndroid Build Coastguard Worker    bufsize = 8*1024            # I/O buffering size for copy to file
693*cda5da8dSAndroid Build Coastguard Worker
694*cda5da8dSAndroid Build Coastguard Worker    def read_binary(self):
695*cda5da8dSAndroid Build Coastguard Worker        """Internal: read binary data."""
696*cda5da8dSAndroid Build Coastguard Worker        self.file = self.make_file()
697*cda5da8dSAndroid Build Coastguard Worker        todo = self.length
698*cda5da8dSAndroid Build Coastguard Worker        if todo >= 0:
699*cda5da8dSAndroid Build Coastguard Worker            while todo > 0:
700*cda5da8dSAndroid Build Coastguard Worker                data = self.fp.read(min(todo, self.bufsize)) # bytes
701*cda5da8dSAndroid Build Coastguard Worker                if not isinstance(data, bytes):
702*cda5da8dSAndroid Build Coastguard Worker                    raise ValueError("%s should return bytes, got %s"
703*cda5da8dSAndroid Build Coastguard Worker                                     % (self.fp, type(data).__name__))
704*cda5da8dSAndroid Build Coastguard Worker                self.bytes_read += len(data)
705*cda5da8dSAndroid Build Coastguard Worker                if not data:
706*cda5da8dSAndroid Build Coastguard Worker                    self.done = -1
707*cda5da8dSAndroid Build Coastguard Worker                    break
708*cda5da8dSAndroid Build Coastguard Worker                self.file.write(data)
709*cda5da8dSAndroid Build Coastguard Worker                todo = todo - len(data)
710*cda5da8dSAndroid Build Coastguard Worker
711*cda5da8dSAndroid Build Coastguard Worker    def read_lines(self):
712*cda5da8dSAndroid Build Coastguard Worker        """Internal: read lines until EOF or outerboundary."""
713*cda5da8dSAndroid Build Coastguard Worker        if self._binary_file:
714*cda5da8dSAndroid Build Coastguard Worker            self.file = self.__file = BytesIO() # store data as bytes for files
715*cda5da8dSAndroid Build Coastguard Worker        else:
716*cda5da8dSAndroid Build Coastguard Worker            self.file = self.__file = StringIO() # as strings for other fields
717*cda5da8dSAndroid Build Coastguard Worker        if self.outerboundary:
718*cda5da8dSAndroid Build Coastguard Worker            self.read_lines_to_outerboundary()
719*cda5da8dSAndroid Build Coastguard Worker        else:
720*cda5da8dSAndroid Build Coastguard Worker            self.read_lines_to_eof()
721*cda5da8dSAndroid Build Coastguard Worker
722*cda5da8dSAndroid Build Coastguard Worker    def __write(self, line):
723*cda5da8dSAndroid Build Coastguard Worker        """line is always bytes, not string"""
724*cda5da8dSAndroid Build Coastguard Worker        if self.__file is not None:
725*cda5da8dSAndroid Build Coastguard Worker            if self.__file.tell() + len(line) > 1000:
726*cda5da8dSAndroid Build Coastguard Worker                self.file = self.make_file()
727*cda5da8dSAndroid Build Coastguard Worker                data = self.__file.getvalue()
728*cda5da8dSAndroid Build Coastguard Worker                self.file.write(data)
729*cda5da8dSAndroid Build Coastguard Worker                self.__file = None
730*cda5da8dSAndroid Build Coastguard Worker        if self._binary_file:
731*cda5da8dSAndroid Build Coastguard Worker            # keep bytes
732*cda5da8dSAndroid Build Coastguard Worker            self.file.write(line)
733*cda5da8dSAndroid Build Coastguard Worker        else:
734*cda5da8dSAndroid Build Coastguard Worker            # decode to string
735*cda5da8dSAndroid Build Coastguard Worker            self.file.write(line.decode(self.encoding, self.errors))
736*cda5da8dSAndroid Build Coastguard Worker
737*cda5da8dSAndroid Build Coastguard Worker    def read_lines_to_eof(self):
738*cda5da8dSAndroid Build Coastguard Worker        """Internal: read lines until EOF."""
739*cda5da8dSAndroid Build Coastguard Worker        while 1:
740*cda5da8dSAndroid Build Coastguard Worker            line = self.fp.readline(1<<16) # bytes
741*cda5da8dSAndroid Build Coastguard Worker            self.bytes_read += len(line)
742*cda5da8dSAndroid Build Coastguard Worker            if not line:
743*cda5da8dSAndroid Build Coastguard Worker                self.done = -1
744*cda5da8dSAndroid Build Coastguard Worker                break
745*cda5da8dSAndroid Build Coastguard Worker            self.__write(line)
746*cda5da8dSAndroid Build Coastguard Worker
747*cda5da8dSAndroid Build Coastguard Worker    def read_lines_to_outerboundary(self):
748*cda5da8dSAndroid Build Coastguard Worker        """Internal: read lines until outerboundary.
749*cda5da8dSAndroid Build Coastguard Worker        Data is read as bytes: boundaries and line ends must be converted
750*cda5da8dSAndroid Build Coastguard Worker        to bytes for comparisons.
751*cda5da8dSAndroid Build Coastguard Worker        """
752*cda5da8dSAndroid Build Coastguard Worker        next_boundary = b"--" + self.outerboundary
753*cda5da8dSAndroid Build Coastguard Worker        last_boundary = next_boundary + b"--"
754*cda5da8dSAndroid Build Coastguard Worker        delim = b""
755*cda5da8dSAndroid Build Coastguard Worker        last_line_lfend = True
756*cda5da8dSAndroid Build Coastguard Worker        _read = 0
757*cda5da8dSAndroid Build Coastguard Worker        while 1:
758*cda5da8dSAndroid Build Coastguard Worker
759*cda5da8dSAndroid Build Coastguard Worker            if self.limit is not None and 0 <= self.limit <= _read:
760*cda5da8dSAndroid Build Coastguard Worker                break
761*cda5da8dSAndroid Build Coastguard Worker            line = self.fp.readline(1<<16) # bytes
762*cda5da8dSAndroid Build Coastguard Worker            self.bytes_read += len(line)
763*cda5da8dSAndroid Build Coastguard Worker            _read += len(line)
764*cda5da8dSAndroid Build Coastguard Worker            if not line:
765*cda5da8dSAndroid Build Coastguard Worker                self.done = -1
766*cda5da8dSAndroid Build Coastguard Worker                break
767*cda5da8dSAndroid Build Coastguard Worker            if delim == b"\r":
768*cda5da8dSAndroid Build Coastguard Worker                line = delim + line
769*cda5da8dSAndroid Build Coastguard Worker                delim = b""
770*cda5da8dSAndroid Build Coastguard Worker            if line.startswith(b"--") and last_line_lfend:
771*cda5da8dSAndroid Build Coastguard Worker                strippedline = line.rstrip()
772*cda5da8dSAndroid Build Coastguard Worker                if strippedline == next_boundary:
773*cda5da8dSAndroid Build Coastguard Worker                    break
774*cda5da8dSAndroid Build Coastguard Worker                if strippedline == last_boundary:
775*cda5da8dSAndroid Build Coastguard Worker                    self.done = 1
776*cda5da8dSAndroid Build Coastguard Worker                    break
777*cda5da8dSAndroid Build Coastguard Worker            odelim = delim
778*cda5da8dSAndroid Build Coastguard Worker            if line.endswith(b"\r\n"):
779*cda5da8dSAndroid Build Coastguard Worker                delim = b"\r\n"
780*cda5da8dSAndroid Build Coastguard Worker                line = line[:-2]
781*cda5da8dSAndroid Build Coastguard Worker                last_line_lfend = True
782*cda5da8dSAndroid Build Coastguard Worker            elif line.endswith(b"\n"):
783*cda5da8dSAndroid Build Coastguard Worker                delim = b"\n"
784*cda5da8dSAndroid Build Coastguard Worker                line = line[:-1]
785*cda5da8dSAndroid Build Coastguard Worker                last_line_lfend = True
786*cda5da8dSAndroid Build Coastguard Worker            elif line.endswith(b"\r"):
787*cda5da8dSAndroid Build Coastguard Worker                # We may interrupt \r\n sequences if they span the 2**16
788*cda5da8dSAndroid Build Coastguard Worker                # byte boundary
789*cda5da8dSAndroid Build Coastguard Worker                delim = b"\r"
790*cda5da8dSAndroid Build Coastguard Worker                line = line[:-1]
791*cda5da8dSAndroid Build Coastguard Worker                last_line_lfend = False
792*cda5da8dSAndroid Build Coastguard Worker            else:
793*cda5da8dSAndroid Build Coastguard Worker                delim = b""
794*cda5da8dSAndroid Build Coastguard Worker                last_line_lfend = False
795*cda5da8dSAndroid Build Coastguard Worker            self.__write(odelim + line)
796*cda5da8dSAndroid Build Coastguard Worker
797*cda5da8dSAndroid Build Coastguard Worker    def skip_lines(self):
798*cda5da8dSAndroid Build Coastguard Worker        """Internal: skip lines until outer boundary if defined."""
799*cda5da8dSAndroid Build Coastguard Worker        if not self.outerboundary or self.done:
800*cda5da8dSAndroid Build Coastguard Worker            return
801*cda5da8dSAndroid Build Coastguard Worker        next_boundary = b"--" + self.outerboundary
802*cda5da8dSAndroid Build Coastguard Worker        last_boundary = next_boundary + b"--"
803*cda5da8dSAndroid Build Coastguard Worker        last_line_lfend = True
804*cda5da8dSAndroid Build Coastguard Worker        while True:
805*cda5da8dSAndroid Build Coastguard Worker            line = self.fp.readline(1<<16)
806*cda5da8dSAndroid Build Coastguard Worker            self.bytes_read += len(line)
807*cda5da8dSAndroid Build Coastguard Worker            if not line:
808*cda5da8dSAndroid Build Coastguard Worker                self.done = -1
809*cda5da8dSAndroid Build Coastguard Worker                break
810*cda5da8dSAndroid Build Coastguard Worker            if line.endswith(b"--") and last_line_lfend:
811*cda5da8dSAndroid Build Coastguard Worker                strippedline = line.strip()
812*cda5da8dSAndroid Build Coastguard Worker                if strippedline == next_boundary:
813*cda5da8dSAndroid Build Coastguard Worker                    break
814*cda5da8dSAndroid Build Coastguard Worker                if strippedline == last_boundary:
815*cda5da8dSAndroid Build Coastguard Worker                    self.done = 1
816*cda5da8dSAndroid Build Coastguard Worker                    break
817*cda5da8dSAndroid Build Coastguard Worker            last_line_lfend = line.endswith(b'\n')
818*cda5da8dSAndroid Build Coastguard Worker
819*cda5da8dSAndroid Build Coastguard Worker    def make_file(self):
820*cda5da8dSAndroid Build Coastguard Worker        """Overridable: return a readable & writable file.
821*cda5da8dSAndroid Build Coastguard Worker
822*cda5da8dSAndroid Build Coastguard Worker        The file will be used as follows:
823*cda5da8dSAndroid Build Coastguard Worker        - data is written to it
824*cda5da8dSAndroid Build Coastguard Worker        - seek(0)
825*cda5da8dSAndroid Build Coastguard Worker        - data is read from it
826*cda5da8dSAndroid Build Coastguard Worker
827*cda5da8dSAndroid Build Coastguard Worker        The file is opened in binary mode for files, in text mode
828*cda5da8dSAndroid Build Coastguard Worker        for other fields
829*cda5da8dSAndroid Build Coastguard Worker
830*cda5da8dSAndroid Build Coastguard Worker        This version opens a temporary file for reading and writing,
831*cda5da8dSAndroid Build Coastguard Worker        and immediately deletes (unlinks) it.  The trick (on Unix!) is
832*cda5da8dSAndroid Build Coastguard Worker        that the file can still be used, but it can't be opened by
833*cda5da8dSAndroid Build Coastguard Worker        another process, and it will automatically be deleted when it
834*cda5da8dSAndroid Build Coastguard Worker        is closed or when the current process terminates.
835*cda5da8dSAndroid Build Coastguard Worker
836*cda5da8dSAndroid Build Coastguard Worker        If you want a more permanent file, you derive a class which
837*cda5da8dSAndroid Build Coastguard Worker        overrides this method.  If you want a visible temporary file
838*cda5da8dSAndroid Build Coastguard Worker        that is nevertheless automatically deleted when the script
839*cda5da8dSAndroid Build Coastguard Worker        terminates, try defining a __del__ method in a derived class
840*cda5da8dSAndroid Build Coastguard Worker        which unlinks the temporary files you have created.
841*cda5da8dSAndroid Build Coastguard Worker
842*cda5da8dSAndroid Build Coastguard Worker        """
843*cda5da8dSAndroid Build Coastguard Worker        if self._binary_file:
844*cda5da8dSAndroid Build Coastguard Worker            return tempfile.TemporaryFile("wb+")
845*cda5da8dSAndroid Build Coastguard Worker        else:
846*cda5da8dSAndroid Build Coastguard Worker            return tempfile.TemporaryFile("w+",
847*cda5da8dSAndroid Build Coastguard Worker                encoding=self.encoding, newline = '\n')
848*cda5da8dSAndroid Build Coastguard Worker
849*cda5da8dSAndroid Build Coastguard Worker
850*cda5da8dSAndroid Build Coastguard Worker# Test/debug code
851*cda5da8dSAndroid Build Coastguard Worker# ===============
852*cda5da8dSAndroid Build Coastguard Worker
853*cda5da8dSAndroid Build Coastguard Workerdef test(environ=os.environ):
854*cda5da8dSAndroid Build Coastguard Worker    """Robust test CGI script, usable as main program.
855*cda5da8dSAndroid Build Coastguard Worker
856*cda5da8dSAndroid Build Coastguard Worker    Write minimal HTTP headers and dump all information provided to
857*cda5da8dSAndroid Build Coastguard Worker    the script in HTML form.
858*cda5da8dSAndroid Build Coastguard Worker
859*cda5da8dSAndroid Build Coastguard Worker    """
860*cda5da8dSAndroid Build Coastguard Worker    print("Content-type: text/html")
861*cda5da8dSAndroid Build Coastguard Worker    print()
862*cda5da8dSAndroid Build Coastguard Worker    sys.stderr = sys.stdout
863*cda5da8dSAndroid Build Coastguard Worker    try:
864*cda5da8dSAndroid Build Coastguard Worker        form = FieldStorage()   # Replace with other classes to test those
865*cda5da8dSAndroid Build Coastguard Worker        print_directory()
866*cda5da8dSAndroid Build Coastguard Worker        print_arguments()
867*cda5da8dSAndroid Build Coastguard Worker        print_form(form)
868*cda5da8dSAndroid Build Coastguard Worker        print_environ(environ)
869*cda5da8dSAndroid Build Coastguard Worker        print_environ_usage()
870*cda5da8dSAndroid Build Coastguard Worker        def f():
871*cda5da8dSAndroid Build Coastguard Worker            exec("testing print_exception() -- <I>italics?</I>")
872*cda5da8dSAndroid Build Coastguard Worker        def g(f=f):
873*cda5da8dSAndroid Build Coastguard Worker            f()
874*cda5da8dSAndroid Build Coastguard Worker        print("<H3>What follows is a test, not an actual exception:</H3>")
875*cda5da8dSAndroid Build Coastguard Worker        g()
876*cda5da8dSAndroid Build Coastguard Worker    except:
877*cda5da8dSAndroid Build Coastguard Worker        print_exception()
878*cda5da8dSAndroid Build Coastguard Worker
879*cda5da8dSAndroid Build Coastguard Worker    print("<H1>Second try with a small maxlen...</H1>")
880*cda5da8dSAndroid Build Coastguard Worker
881*cda5da8dSAndroid Build Coastguard Worker    global maxlen
882*cda5da8dSAndroid Build Coastguard Worker    maxlen = 50
883*cda5da8dSAndroid Build Coastguard Worker    try:
884*cda5da8dSAndroid Build Coastguard Worker        form = FieldStorage()   # Replace with other classes to test those
885*cda5da8dSAndroid Build Coastguard Worker        print_directory()
886*cda5da8dSAndroid Build Coastguard Worker        print_arguments()
887*cda5da8dSAndroid Build Coastguard Worker        print_form(form)
888*cda5da8dSAndroid Build Coastguard Worker        print_environ(environ)
889*cda5da8dSAndroid Build Coastguard Worker    except:
890*cda5da8dSAndroid Build Coastguard Worker        print_exception()
891*cda5da8dSAndroid Build Coastguard Worker
892*cda5da8dSAndroid Build Coastguard Workerdef print_exception(type=None, value=None, tb=None, limit=None):
893*cda5da8dSAndroid Build Coastguard Worker    if type is None:
894*cda5da8dSAndroid Build Coastguard Worker        type, value, tb = sys.exc_info()
895*cda5da8dSAndroid Build Coastguard Worker    import traceback
896*cda5da8dSAndroid Build Coastguard Worker    print()
897*cda5da8dSAndroid Build Coastguard Worker    print("<H3>Traceback (most recent call last):</H3>")
898*cda5da8dSAndroid Build Coastguard Worker    list = traceback.format_tb(tb, limit) + \
899*cda5da8dSAndroid Build Coastguard Worker           traceback.format_exception_only(type, value)
900*cda5da8dSAndroid Build Coastguard Worker    print("<PRE>%s<B>%s</B></PRE>" % (
901*cda5da8dSAndroid Build Coastguard Worker        html.escape("".join(list[:-1])),
902*cda5da8dSAndroid Build Coastguard Worker        html.escape(list[-1]),
903*cda5da8dSAndroid Build Coastguard Worker        ))
904*cda5da8dSAndroid Build Coastguard Worker    del tb
905*cda5da8dSAndroid Build Coastguard Worker
906*cda5da8dSAndroid Build Coastguard Workerdef print_environ(environ=os.environ):
907*cda5da8dSAndroid Build Coastguard Worker    """Dump the shell environment as HTML."""
908*cda5da8dSAndroid Build Coastguard Worker    keys = sorted(environ.keys())
909*cda5da8dSAndroid Build Coastguard Worker    print()
910*cda5da8dSAndroid Build Coastguard Worker    print("<H3>Shell Environment:</H3>")
911*cda5da8dSAndroid Build Coastguard Worker    print("<DL>")
912*cda5da8dSAndroid Build Coastguard Worker    for key in keys:
913*cda5da8dSAndroid Build Coastguard Worker        print("<DT>", html.escape(key), "<DD>", html.escape(environ[key]))
914*cda5da8dSAndroid Build Coastguard Worker    print("</DL>")
915*cda5da8dSAndroid Build Coastguard Worker    print()
916*cda5da8dSAndroid Build Coastguard Worker
917*cda5da8dSAndroid Build Coastguard Workerdef print_form(form):
918*cda5da8dSAndroid Build Coastguard Worker    """Dump the contents of a form as HTML."""
919*cda5da8dSAndroid Build Coastguard Worker    keys = sorted(form.keys())
920*cda5da8dSAndroid Build Coastguard Worker    print()
921*cda5da8dSAndroid Build Coastguard Worker    print("<H3>Form Contents:</H3>")
922*cda5da8dSAndroid Build Coastguard Worker    if not keys:
923*cda5da8dSAndroid Build Coastguard Worker        print("<P>No form fields.")
924*cda5da8dSAndroid Build Coastguard Worker    print("<DL>")
925*cda5da8dSAndroid Build Coastguard Worker    for key in keys:
926*cda5da8dSAndroid Build Coastguard Worker        print("<DT>" + html.escape(key) + ":", end=' ')
927*cda5da8dSAndroid Build Coastguard Worker        value = form[key]
928*cda5da8dSAndroid Build Coastguard Worker        print("<i>" + html.escape(repr(type(value))) + "</i>")
929*cda5da8dSAndroid Build Coastguard Worker        print("<DD>" + html.escape(repr(value)))
930*cda5da8dSAndroid Build Coastguard Worker    print("</DL>")
931*cda5da8dSAndroid Build Coastguard Worker    print()
932*cda5da8dSAndroid Build Coastguard Worker
933*cda5da8dSAndroid Build Coastguard Workerdef print_directory():
934*cda5da8dSAndroid Build Coastguard Worker    """Dump the current directory as HTML."""
935*cda5da8dSAndroid Build Coastguard Worker    print()
936*cda5da8dSAndroid Build Coastguard Worker    print("<H3>Current Working Directory:</H3>")
937*cda5da8dSAndroid Build Coastguard Worker    try:
938*cda5da8dSAndroid Build Coastguard Worker        pwd = os.getcwd()
939*cda5da8dSAndroid Build Coastguard Worker    except OSError as msg:
940*cda5da8dSAndroid Build Coastguard Worker        print("OSError:", html.escape(str(msg)))
941*cda5da8dSAndroid Build Coastguard Worker    else:
942*cda5da8dSAndroid Build Coastguard Worker        print(html.escape(pwd))
943*cda5da8dSAndroid Build Coastguard Worker    print()
944*cda5da8dSAndroid Build Coastguard Worker
945*cda5da8dSAndroid Build Coastguard Workerdef print_arguments():
946*cda5da8dSAndroid Build Coastguard Worker    print()
947*cda5da8dSAndroid Build Coastguard Worker    print("<H3>Command Line Arguments:</H3>")
948*cda5da8dSAndroid Build Coastguard Worker    print()
949*cda5da8dSAndroid Build Coastguard Worker    print(sys.argv)
950*cda5da8dSAndroid Build Coastguard Worker    print()
951*cda5da8dSAndroid Build Coastguard Worker
952*cda5da8dSAndroid Build Coastguard Workerdef print_environ_usage():
953*cda5da8dSAndroid Build Coastguard Worker    """Dump a list of environment variables used by CGI as HTML."""
954*cda5da8dSAndroid Build Coastguard Worker    print("""
955*cda5da8dSAndroid Build Coastguard Worker<H3>These environment variables could have been set:</H3>
956*cda5da8dSAndroid Build Coastguard Worker<UL>
957*cda5da8dSAndroid Build Coastguard Worker<LI>AUTH_TYPE
958*cda5da8dSAndroid Build Coastguard Worker<LI>CONTENT_LENGTH
959*cda5da8dSAndroid Build Coastguard Worker<LI>CONTENT_TYPE
960*cda5da8dSAndroid Build Coastguard Worker<LI>DATE_GMT
961*cda5da8dSAndroid Build Coastguard Worker<LI>DATE_LOCAL
962*cda5da8dSAndroid Build Coastguard Worker<LI>DOCUMENT_NAME
963*cda5da8dSAndroid Build Coastguard Worker<LI>DOCUMENT_ROOT
964*cda5da8dSAndroid Build Coastguard Worker<LI>DOCUMENT_URI
965*cda5da8dSAndroid Build Coastguard Worker<LI>GATEWAY_INTERFACE
966*cda5da8dSAndroid Build Coastguard Worker<LI>LAST_MODIFIED
967*cda5da8dSAndroid Build Coastguard Worker<LI>PATH
968*cda5da8dSAndroid Build Coastguard Worker<LI>PATH_INFO
969*cda5da8dSAndroid Build Coastguard Worker<LI>PATH_TRANSLATED
970*cda5da8dSAndroid Build Coastguard Worker<LI>QUERY_STRING
971*cda5da8dSAndroid Build Coastguard Worker<LI>REMOTE_ADDR
972*cda5da8dSAndroid Build Coastguard Worker<LI>REMOTE_HOST
973*cda5da8dSAndroid Build Coastguard Worker<LI>REMOTE_IDENT
974*cda5da8dSAndroid Build Coastguard Worker<LI>REMOTE_USER
975*cda5da8dSAndroid Build Coastguard Worker<LI>REQUEST_METHOD
976*cda5da8dSAndroid Build Coastguard Worker<LI>SCRIPT_NAME
977*cda5da8dSAndroid Build Coastguard Worker<LI>SERVER_NAME
978*cda5da8dSAndroid Build Coastguard Worker<LI>SERVER_PORT
979*cda5da8dSAndroid Build Coastguard Worker<LI>SERVER_PROTOCOL
980*cda5da8dSAndroid Build Coastguard Worker<LI>SERVER_ROOT
981*cda5da8dSAndroid Build Coastguard Worker<LI>SERVER_SOFTWARE
982*cda5da8dSAndroid Build Coastguard Worker</UL>
983*cda5da8dSAndroid Build Coastguard WorkerIn addition, HTTP headers sent by the server may be passed in the
984*cda5da8dSAndroid Build Coastguard Workerenvironment as well.  Here are some common variable names:
985*cda5da8dSAndroid Build Coastguard Worker<UL>
986*cda5da8dSAndroid Build Coastguard Worker<LI>HTTP_ACCEPT
987*cda5da8dSAndroid Build Coastguard Worker<LI>HTTP_CONNECTION
988*cda5da8dSAndroid Build Coastguard Worker<LI>HTTP_HOST
989*cda5da8dSAndroid Build Coastguard Worker<LI>HTTP_PRAGMA
990*cda5da8dSAndroid Build Coastguard Worker<LI>HTTP_REFERER
991*cda5da8dSAndroid Build Coastguard Worker<LI>HTTP_USER_AGENT
992*cda5da8dSAndroid Build Coastguard Worker</UL>
993*cda5da8dSAndroid Build Coastguard Worker""")
994*cda5da8dSAndroid Build Coastguard Worker
995*cda5da8dSAndroid Build Coastguard Worker
996*cda5da8dSAndroid Build Coastguard Worker# Utilities
997*cda5da8dSAndroid Build Coastguard Worker# =========
998*cda5da8dSAndroid Build Coastguard Worker
999*cda5da8dSAndroid Build Coastguard Workerdef valid_boundary(s):
1000*cda5da8dSAndroid Build Coastguard Worker    import re
1001*cda5da8dSAndroid Build Coastguard Worker    if isinstance(s, bytes):
1002*cda5da8dSAndroid Build Coastguard Worker        _vb_pattern = b"^[ -~]{0,200}[!-~]$"
1003*cda5da8dSAndroid Build Coastguard Worker    else:
1004*cda5da8dSAndroid Build Coastguard Worker        _vb_pattern = "^[ -~]{0,200}[!-~]$"
1005*cda5da8dSAndroid Build Coastguard Worker    return re.match(_vb_pattern, s)
1006*cda5da8dSAndroid Build Coastguard Worker
1007*cda5da8dSAndroid Build Coastguard Worker# Invoke mainline
1008*cda5da8dSAndroid Build Coastguard Worker# ===============
1009*cda5da8dSAndroid Build Coastguard Worker
1010*cda5da8dSAndroid Build Coastguard Worker# Call test() when this file is run as a script (not imported as a module)
1011*cda5da8dSAndroid Build Coastguard Workerif __name__ == '__main__':
1012*cda5da8dSAndroid Build Coastguard Worker    test()
1013