10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#! /usr/local/bin/python
20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
30a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# NOTE: the above "/usr/local/bin/python" is NOT a mistake.  It is
40a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# intentionally NOT "/usr/bin/env python".  On many systems
50a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI
60a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# scripts, and /usr/local/bin is the default directory where Python is
70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# installed, so /usr/bin/env would be unable to find python.  Granted,
80a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# binary installations by Linux vendors often install Python in
90a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# /usr/bin.  So let those vendors patch cgi.py to match their choice
100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# of installation.
110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""Support module for CGI (Common Gateway Interface) scripts.
130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
140a8c90248264a8b26970b4473770bcc3df8515fJosh GaoThis module defines a number of utilities for use by CGI scripts
150a8c90248264a8b26970b4473770bcc3df8515fJosh Gaowritten in Python.
160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""
170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# XXX Perhaps there should be a slimmed version that doesn't contain
190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# all those backwards compatible and debugging classes and functions?
200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# History
220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# -------
230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Michael McLay started this module.  Steve Majewski changed the
250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# interface to SvFormContentDict and FormContentDict.  The multipart
260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# parsing was inspired by code submitted by Andreas Paepcke.  Guido van
270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Rossum rewrote, reformatted and documented the module and is currently
280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# responsible for its maintenance.
290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao__version__ = "2.6"
320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Imports
350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# =======
360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
370a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom operator import attrgetter
380a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport sys
390a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport os
400a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport UserDict
410a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport urlparse
420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
430a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom warnings import filterwarnings, catch_warnings, warn
440a8c90248264a8b26970b4473770bcc3df8515fJosh Gaowith catch_warnings():
450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if sys.py3kwarning:
460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        filterwarnings("ignore", ".*mimetools has been removed",
470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                       DeprecationWarning)
480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        filterwarnings("ignore", ".*rfc822 has been removed",
490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                       DeprecationWarning)
500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    import mimetools
510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    import rfc822
520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
530a8c90248264a8b26970b4473770bcc3df8515fJosh Gaotry:
540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    from cStringIO import StringIO
550a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoexcept ImportError:
560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    from StringIO import StringIO
570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao__all__ = ["MiniFieldStorage", "FieldStorage", "FormContentDict",
590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao           "SvFormContentDict", "InterpFormContentDict", "FormContent",
600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao           "parse", "parse_qs", "parse_qsl", "parse_multipart",
610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao           "parse_header", "print_exception", "print_environ",
620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao           "print_form", "print_directory", "print_arguments",
630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao           "print_environ_usage", "escape"]
640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Logging support
660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# ===============
670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
680a8c90248264a8b26970b4473770bcc3df8515fJosh Gaologfile = ""            # Filename to log to, if not empty
690a8c90248264a8b26970b4473770bcc3df8515fJosh Gaologfp = None            # File object to log to, if not None
700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
710a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef initlog(*allargs):
720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Write a log message, if there is a log file.
730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    Even though this function is called initlog(), you should always
750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    use log(); log is a variable that is set either to initlog
760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    (initially), to dolog (once the log file has been opened), or to
770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    nolog (when logging is disabled).
780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    The first argument is a format string; the remaining arguments (if
800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    any) are arguments to the % operator, so e.g.
810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        log("%s: %s", "a", "b")
820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    will write "a: b" to the log file, followed by a newline.
830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    If the global logfp is not None, it should be a file object to
850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    which log data is written.
860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    If the global logfp is None, the global logfile may be a string
880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    giving a filename to open, in append mode.  This file should be
890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    world writable!!!  If the file can't be opened, logging is
900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    silently disabled (since there is no safe place where we could
910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    send an error message).
920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """
940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    global logfp, log
950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if logfile and not logfp:
960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            logfp = open(logfile, "a")
980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except IOError:
990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if not logfp:
1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        log = nolog
1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    else:
1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        log = dolog
1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    log(*allargs)
1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef dolog(fmt, *args):
1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Write a log message to the log file.  See initlog() for docs."""
1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    logfp.write(fmt%args + "\n")
1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef nolog(*allargs):
1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Dummy function, assigned to log when logging is disabled."""
1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    pass
1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gaolog = initlog           # The current logging function
1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Parsing functions
1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# =================
1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Maximum input we will accept when REQUEST_METHOD is POST
1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# 0 ==> unlimited input
1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gaomaxlen = 0
1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Parse a query in the environment or from a file (default stdin)
1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Arguments, all optional:
1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        fp              : file pointer; default: sys.stdin
1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        environ         : environment dictionary; default: os.environ
1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        keep_blank_values: flag indicating whether blank values in
1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            percent-encoded forms should be treated as blank strings.
1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            A true value indicates that blanks should be retained as
1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            blank strings.  The default false value indicates that
1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            blank values are to be ignored and treated as if they were
1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            not included.
1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        strict_parsing: flag indicating what to do with parsing errors.
1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            If false (the default), errors are silently ignored.
1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            If true, errors raise a ValueError exception.
1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """
1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if fp is None:
1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        fp = sys.stdin
1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if not 'REQUEST_METHOD' in environ:
1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        environ['REQUEST_METHOD'] = 'GET'       # For testing stand-alone
1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if environ['REQUEST_METHOD'] == 'POST':
1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        ctype, pdict = parse_header(environ['CONTENT_TYPE'])
1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if ctype == 'multipart/form-data':
1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return parse_multipart(fp, pdict)
1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        elif ctype == 'application/x-www-form-urlencoded':
1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            clength = int(environ['CONTENT_LENGTH'])
1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if maxlen and clength > maxlen:
1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                raise ValueError, 'Maximum content length exceeded'
1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            qs = fp.read(clength)
1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            qs = ''                     # Unknown content-type
1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if 'QUERY_STRING' in environ:
1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if qs: qs = qs + '&'
1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            qs = qs + environ['QUERY_STRING']
1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        elif sys.argv[1:]:
1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if qs: qs = qs + '&'
1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            qs = qs + sys.argv[1]
1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        environ['QUERY_STRING'] = qs    # XXX Shouldn't, really
1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    elif 'QUERY_STRING' in environ:
1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        qs = environ['QUERY_STRING']
1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    else:
1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if sys.argv[1:]:
1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            qs = sys.argv[1]
1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            qs = ""
1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        environ['QUERY_STRING'] = qs    # XXX Shouldn't, really
1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# parse query string function called from urlparse,
1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# this is done in order to maintain backward compatiblity.
1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef parse_qs(qs, keep_blank_values=0, strict_parsing=0):
1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Parse a query given as a string argument."""
1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    warn("cgi.parse_qs is deprecated, use urlparse.parse_qs instead",
1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao         PendingDeprecationWarning, 2)
1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return urlparse.parse_qs(qs, keep_blank_values, strict_parsing)
1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
1880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Parse a query given as a string argument."""
1890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    warn("cgi.parse_qsl is deprecated, use urlparse.parse_qsl instead",
1900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao         PendingDeprecationWarning, 2)
1910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return urlparse.parse_qsl(qs, keep_blank_values, strict_parsing)
1920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1930a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef parse_multipart(fp, pdict):
1940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Parse multipart input.
1950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    Arguments:
1970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    fp   : input file
1980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    pdict: dictionary containing other parameters of content-type header
1990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    Returns a dictionary just like parse_qs(): keys are the field names, each
2010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    value is a list of values for that field.  This is easy to use but not
2020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    much good if you are expecting megabytes to be uploaded -- in that case,
2030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    use the FieldStorage class instead which is much more flexible.  Note
2040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    that content-type is the raw, unparsed contents of the content-type
2050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    header.
2060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    XXX This does not parse nested multipart parts -- use FieldStorage for
2080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    that.
2090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    XXX This should really be subsumed by FieldStorage altogether -- no
2110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    point in having two implementations of the same parsing algorithm.
2120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    Also, FieldStorage protects itself better against certain DoS attacks
2130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    by limiting the size of the data read in one chunk.  The API here
2140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    does not support that kind of protection.  This also affects parse()
2150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    since it can call parse_multipart().
2160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """
2180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    boundary = ""
2190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if 'boundary' in pdict:
2200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        boundary = pdict['boundary']
2210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if not valid_boundary(boundary):
2220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        raise ValueError,  ('Invalid boundary in multipart form: %r'
2230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                            % (boundary,))
2240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    nextpart = "--" + boundary
2260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    lastpart = "--" + boundary + "--"
2270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    partdict = {}
2280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    terminator = ""
2290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    while terminator != lastpart:
2310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        bytes = -1
2320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        data = None
2330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if terminator:
2340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # At start of next part.  Read headers first.
2350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            headers = mimetools.Message(fp)
2360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            clength = headers.getheader('content-length')
2370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if clength:
2380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                try:
2390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    bytes = int(clength)
2400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                except ValueError:
2410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    pass
2420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if bytes > 0:
2430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if maxlen and bytes > maxlen:
2440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    raise ValueError, 'Maximum content length exceeded'
2450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                data = fp.read(bytes)
2460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
2470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                data = ""
2480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Read lines until end of part.
2490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        lines = []
2500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        while 1:
2510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            line = fp.readline()
2520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if not line:
2530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                terminator = lastpart # End outer loop
2540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                break
2550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if line[:2] == "--":
2560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                terminator = line.strip()
2570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if terminator in (nextpart, lastpart):
2580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    break
2590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            lines.append(line)
2600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Done with part.
2610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if data is None:
2620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            continue
2630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if bytes < 0:
2640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if lines:
2650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                # Strip final line terminator
2660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                line = lines[-1]
2670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if line[-2:] == "\r\n":
2680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    line = line[:-2]
2690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                elif line[-1:] == "\n":
2700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    line = line[:-1]
2710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                lines[-1] = line
2720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                data = "".join(lines)
2730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        line = headers['content-disposition']
2740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not line:
2750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            continue
2760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        key, params = parse_header(line)
2770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if key != 'form-data':
2780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            continue
2790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if 'name' in params:
2800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            name = params['name']
2810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
2820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            continue
2830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if name in partdict:
2840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            partdict[name].append(data)
2850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
2860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            partdict[name] = [data]
2870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return partdict
2890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2910a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef _parseparam(s):
2920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    while s[:1] == ';':
2930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        s = s[1:]
2940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        end = s.find(';')
2950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
2960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            end = s.find(';', end + 1)
2970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if end < 0:
2980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            end = len(s)
2990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        f = s[:end]
3000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        yield f.strip()
3010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        s = s[end:]
3020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3030a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef parse_header(line):
3040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Parse a Content-type like header.
3050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    Return the main content-type and a dictionary of options.
3070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """
3090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    parts = _parseparam(';' + line)
3100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    key = parts.next()
3110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    pdict = {}
3120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    for p in parts:
3130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        i = p.find('=')
3140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if i >= 0:
3150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            name = p[:i].strip().lower()
3160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            value = p[i+1:].strip()
3170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if len(value) >= 2 and value[0] == value[-1] == '"':
3180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                value = value[1:-1]
3190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                value = value.replace('\\\\', '\\').replace('\\"', '"')
3200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pdict[name] = value
3210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return key, pdict
3220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Classes for field storage
3250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# =========================
3260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3270a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass MiniFieldStorage:
3280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Like FieldStorage, for use when no file uploads are possible."""
3300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    # Dummy attributes
3320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    filename = None
3330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    list = None
3340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    type = None
3350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    file = None
3360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    type_options = {}
3370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    disposition = None
3380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    disposition_options = {}
3390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    headers = {}
3400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __init__(self, name, value):
3420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Constructor from field name and value."""
3430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.name = name
3440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.value = value
3450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # self.file = StringIO(value)
3460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __repr__(self):
3480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Return printable representation."""
3490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return "MiniFieldStorage(%r, %r)" % (self.name, self.value)
3500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3520a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass FieldStorage:
3530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Store a sequence of fields, reading multipart/form-data.
3550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    This class provides naming, typing, files stored on disk, and
3570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    more.  At the top level, it is accessible like a dictionary, whose
3580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    keys are the field names.  (Note: None can occur as a field name.)
3590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    The items are either a Python list (if there's multiple values) or
3600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    another FieldStorage or MiniFieldStorage object.  If it's a single
3610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    object, it has the following attributes:
3620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    name: the field name, if specified; otherwise None
3640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    filename: the filename, if specified; otherwise None; this is the
3660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        client side filename, *not* the file name on which it is
3670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        stored (that's a temporary file you don't deal with)
3680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    value: the value as a *string*; for file uploads, this
3700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        transparently reads the file every time you request the value
3710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    file: the file(-like) object from which you can read the data;
3730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        None if the data is stored a simple string
3740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    type: the content-type, or None if not specified
3760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    type_options: dictionary of options specified on the content-type
3780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        line
3790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    disposition: content-disposition, or None if not specified
3810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    disposition_options: dictionary of corresponding options
3830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    headers: a dictionary(-like) object (sometimes rfc822.Message or a
3850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        subclass thereof) containing *all* headers
3860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    The class is subclassable, mostly for the purpose of overriding
3880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    the make_file() method, which is called internally to come up with
3890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    a file open for reading and writing.  This makes it possible to
3900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    override the default choice of storing all files in a temporary
3910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    directory and unlinking them as soon as they have been opened.
3920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """
3940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __init__(self, fp=None, headers=None, outerboundary="",
3960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                 environ=os.environ, keep_blank_values=0, strict_parsing=0):
3970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Constructor.  Read multipart/* until last part.
3980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        Arguments, all optional:
4000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        fp              : file pointer; default: sys.stdin
4020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            (not used when the request method is GET)
4030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        headers         : header dictionary-like object; default:
4050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            taken from environ as per CGI spec
4060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        outerboundary   : terminating multipart boundary
4080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            (for internal use only)
4090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        environ         : environment dictionary; default: os.environ
4110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        keep_blank_values: flag indicating whether blank values in
4130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            percent-encoded forms should be treated as blank strings.
4140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            A true value indicates that blanks should be retained as
4150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            blank strings.  The default false value indicates that
4160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            blank values are to be ignored and treated as if they were
4170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            not included.
4180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        strict_parsing: flag indicating what to do with parsing errors.
4200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            If false (the default), errors are silently ignored.
4210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            If true, errors raise a ValueError exception.
4220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """
4240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        method = 'GET'
4250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.keep_blank_values = keep_blank_values
4260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.strict_parsing = strict_parsing
4270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if 'REQUEST_METHOD' in environ:
4280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            method = environ['REQUEST_METHOD'].upper()
4290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.qs_on_post = None
4300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if method == 'GET' or method == 'HEAD':
4310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if 'QUERY_STRING' in environ:
4320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                qs = environ['QUERY_STRING']
4330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            elif sys.argv[1:]:
4340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                qs = sys.argv[1]
4350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
4360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                qs = ""
4370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            fp = StringIO(qs)
4380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if headers is None:
4390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                headers = {'content-type':
4400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                           "application/x-www-form-urlencoded"}
4410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if headers is None:
4420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            headers = {}
4430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if method == 'POST':
4440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                # Set default content-type for POST to what's traditional
4450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                headers['content-type'] = "application/x-www-form-urlencoded"
4460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if 'CONTENT_TYPE' in environ:
4470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                headers['content-type'] = environ['CONTENT_TYPE']
4480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if 'QUERY_STRING' in environ:
4490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.qs_on_post = environ['QUERY_STRING']
4500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if 'CONTENT_LENGTH' in environ:
4510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                headers['content-length'] = environ['CONTENT_LENGTH']
4520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.fp = fp or sys.stdin
4530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.headers = headers
4540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.outerboundary = outerboundary
4550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Process content-disposition header
4570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        cdisp, pdict = "", {}
4580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if 'content-disposition' in self.headers:
4590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            cdisp, pdict = parse_header(self.headers['content-disposition'])
4600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.disposition = cdisp
4610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.disposition_options = pdict
4620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.name = None
4630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if 'name' in pdict:
4640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.name = pdict['name']
4650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.filename = None
4660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if 'filename' in pdict:
4670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.filename = pdict['filename']
4680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Process content-type header
4700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        #
4710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Honor any existing content-type header.  But if there is no
4720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # content-type header, use some sensible defaults.  Assume
4730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # outerboundary is "" at the outer level, but something non-false
4740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # inside a multi-part.  The default for an inner part is text/plain,
4750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # but for an outer part it should be urlencoded.  This should catch
4760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # bogus clients which erroneously forget to include a content-type
4770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # header.
4780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        #
4790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # See below for what we do if there does exist a content-type header,
4800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # but it happens to be something we don't understand.
4810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if 'content-type' in self.headers:
4820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ctype, pdict = parse_header(self.headers['content-type'])
4830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        elif self.outerboundary or method != 'POST':
4840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ctype, pdict = "text/plain", {}
4850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
4860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ctype, pdict = 'application/x-www-form-urlencoded', {}
4870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.type = ctype
4880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.type_options = pdict
4890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.innerboundary = ""
4900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if 'boundary' in pdict:
4910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.innerboundary = pdict['boundary']
4920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        clen = -1
4930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if 'content-length' in self.headers:
4940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            try:
4950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                clen = int(self.headers['content-length'])
4960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            except ValueError:
4970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                pass
4980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if maxlen and clen > maxlen:
4990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                raise ValueError, 'Maximum content length exceeded'
5000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.length = clen
5010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.list = self.file = None
5030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.done = 0
5040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if ctype == 'application/x-www-form-urlencoded':
5050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.read_urlencoded()
5060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        elif ctype[:10] == 'multipart/':
5070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.read_multi(environ, keep_blank_values, strict_parsing)
5080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
5090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.read_single()
5100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __repr__(self):
5120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Return a printable representation."""
5130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return "FieldStorage(%r, %r, %r)" % (
5140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.name, self.filename, self.value)
5150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __iter__(self):
5170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return iter(self.keys())
5180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __getattr__(self, name):
5200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if name != 'value':
5210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise AttributeError, name
5220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.file:
5230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.file.seek(0)
5240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            value = self.file.read()
5250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.file.seek(0)
5260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        elif self.list is not None:
5270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            value = self.list
5280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
5290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            value = None
5300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return value
5310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __getitem__(self, key):
5330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Dictionary style indexing."""
5340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.list is None:
5350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise TypeError, "not indexable"
5360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        found = []
5370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for item in self.list:
5380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if item.name == key: found.append(item)
5390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not found:
5400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise KeyError, key
5410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if len(found) == 1:
5420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return found[0]
5430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
5440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return found
5450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def getvalue(self, key, default=None):
5470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Dictionary style get() method, including 'value' lookup."""
5480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if key in self:
5490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            value = self[key]
5500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if type(value) is type([]):
5510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return map(attrgetter('value'), value)
5520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
5530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return value.value
5540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
5550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return default
5560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def getfirst(self, key, default=None):
5580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """ Return the first value received."""
5590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if key in self:
5600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            value = self[key]
5610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if type(value) is type([]):
5620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return value[0].value
5630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
5640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return value.value
5650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
5660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return default
5670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def getlist(self, key):
5690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """ Return list of received values."""
5700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if key in self:
5710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            value = self[key]
5720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if type(value) is type([]):
5730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return map(attrgetter('value'), value)
5740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
5750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return [value.value]
5760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
5770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return []
5780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def keys(self):
5800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Dictionary style keys() method."""
5810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.list is None:
5820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise TypeError, "not indexable"
5830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return list(set(item.name for item in self.list))
5840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def has_key(self, key):
5860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Dictionary style has_key() method."""
5870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.list is None:
5880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise TypeError, "not indexable"
5890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return any(item.name == key for item in self.list)
5900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __contains__(self, key):
5920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Dictionary style __contains__ method."""
5930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.list is None:
5940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise TypeError, "not indexable"
5950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return any(item.name == key for item in self.list)
5960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
5970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __len__(self):
5980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Dictionary style len(x) support."""
5990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return len(self.keys())
6000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __nonzero__(self):
6020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return bool(self.list)
6030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def read_urlencoded(self):
6050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Internal: read data in query string format."""
6060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        qs = self.fp.read(self.length)
6070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.qs_on_post:
6080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            qs += '&' + self.qs_on_post
6090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.list = list = []
6100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for key, value in urlparse.parse_qsl(qs, self.keep_blank_values,
6110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                            self.strict_parsing):
6120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            list.append(MiniFieldStorage(key, value))
6130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.skip_lines()
6140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    FieldStorageClass = None
6160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def read_multi(self, environ, keep_blank_values, strict_parsing):
6180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Internal: read a part that is itself multipart."""
6190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        ib = self.innerboundary
6200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not valid_boundary(ib):
6210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,)
6220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.list = []
6230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.qs_on_post:
6240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            for key, value in urlparse.parse_qsl(self.qs_on_post,
6250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                self.keep_blank_values, self.strict_parsing):
6260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.list.append(MiniFieldStorage(key, value))
6270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            FieldStorageClass = None
6280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        klass = self.FieldStorageClass or self.__class__
6300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        part = klass(self.fp, {}, ib,
6310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                     environ, keep_blank_values, strict_parsing)
6320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Throw first part away
6330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        while not part.done:
6340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            headers = rfc822.Message(self.fp)
6350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            part = klass(self.fp, headers, ib,
6360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         environ, keep_blank_values, strict_parsing)
6370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.list.append(part)
6380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.skip_lines()
6390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def read_single(self):
6410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Internal: read an atomic part."""
6420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.length >= 0:
6430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.read_binary()
6440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.skip_lines()
6450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
6460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.read_lines()
6470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.file.seek(0)
6480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    bufsize = 8*1024            # I/O buffering size for copy to file
6500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def read_binary(self):
6520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Internal: read binary data."""
6530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.file = self.make_file('b')
6540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        todo = self.length
6550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if todo >= 0:
6560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            while todo > 0:
6570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                data = self.fp.read(min(todo, self.bufsize))
6580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if not data:
6590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    self.done = -1
6600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    break
6610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.file.write(data)
6620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                todo = todo - len(data)
6630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def read_lines(self):
6650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Internal: read lines until EOF or outerboundary."""
6660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.file = self.__file = StringIO()
6670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.outerboundary:
6680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.read_lines_to_outerboundary()
6690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
6700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.read_lines_to_eof()
6710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __write(self, line):
6730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.__file is not None:
6740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if self.__file.tell() + len(line) > 1000:
6750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.file = self.make_file('')
6760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.file.write(self.__file.getvalue())
6770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.__file = None
6780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.file.write(line)
6790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def read_lines_to_eof(self):
6810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Internal: read lines until EOF."""
6820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        while 1:
6830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            line = self.fp.readline(1<<16)
6840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if not line:
6850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.done = -1
6860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                break
6870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.__write(line)
6880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
6890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def read_lines_to_outerboundary(self):
6900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Internal: read lines until outerboundary."""
6910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        next = "--" + self.outerboundary
6920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        last = next + "--"
6930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        delim = ""
6940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        last_line_lfend = True
6950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        while 1:
6960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            line = self.fp.readline(1<<16)
6970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if not line:
6980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.done = -1
6990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                break
7000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if line[:2] == "--" and last_line_lfend:
7010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                strippedline = line.strip()
7020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if strippedline == next:
7030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    break
7040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if strippedline == last:
7050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    self.done = 1
7060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    break
7070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            odelim = delim
7080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if line[-2:] == "\r\n":
7090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                delim = "\r\n"
7100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                line = line[:-2]
7110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                last_line_lfend = True
7120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            elif line[-1] == "\n":
7130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                delim = "\n"
7140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                line = line[:-1]
7150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                last_line_lfend = True
7160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
7170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                delim = ""
7180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                last_line_lfend = False
7190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.__write(odelim + line)
7200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def skip_lines(self):
7220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Internal: skip lines until outer boundary if defined."""
7230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not self.outerboundary or self.done:
7240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return
7250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        next = "--" + self.outerboundary
7260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        last = next + "--"
7270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        last_line_lfend = True
7280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        while 1:
7290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            line = self.fp.readline(1<<16)
7300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if not line:
7310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                self.done = -1
7320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                break
7330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if line[:2] == "--" and last_line_lfend:
7340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                strippedline = line.strip()
7350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if strippedline == next:
7360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    break
7370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if strippedline == last:
7380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    self.done = 1
7390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    break
7400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            last_line_lfend = line.endswith('\n')
7410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def make_file(self, binary=None):
7430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """Overridable: return a readable & writable file.
7440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        The file will be used as follows:
7460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        - data is written to it
7470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        - seek(0)
7480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        - data is read from it
7490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        The 'binary' argument is unused -- the file is always opened
7510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        in binary mode.
7520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        This version opens a temporary file for reading and writing,
7540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        and immediately deletes (unlinks) it.  The trick (on Unix!) is
7550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        that the file can still be used, but it can't be opened by
7560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        another process, and it will automatically be deleted when it
7570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        is closed or when the current process terminates.
7580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        If you want a more permanent file, you derive a class which
7600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        overrides this method.  If you want a visible temporary file
7610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        that is nevertheless automatically deleted when the script
7620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        terminates, try defining a __del__ method in a derived class
7630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        which unlinks the temporary files you have created.
7640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        """
7660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        import tempfile
7670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return tempfile.TemporaryFile("w+b")
7680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Backwards Compatibility Classes
7720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# ===============================
7730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7740a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass FormContentDict(UserDict.UserDict):
7750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Form content as dictionary with a list of values per field.
7760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    form = FormContentDict()
7780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    form[key] -> [value, value, ...]
7800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    key in form -> Boolean
7810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    form.keys() -> [key, key, ...]
7820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    form.values() -> [[val, val, ...], [val, val, ...], ...]
7830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    form.items() ->  [(key, [val, val, ...]), (key, [val, val, ...]), ...]
7840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    form.dict == {key: [val, val, ...], ...}
7850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """
7870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __init__(self, environ=os.environ, keep_blank_values=0, strict_parsing=0):
7880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.dict = self.data = parse(environ=environ,
7890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                      keep_blank_values=keep_blank_values,
7900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                      strict_parsing=strict_parsing)
7910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.query_string = environ['QUERY_STRING']
7920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7940a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass SvFormContentDict(FormContentDict):
7950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Form content as dictionary expecting a single value per field.
7960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
7970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    If you only expect a single value for each field, then form[key]
7980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    will return that single value.  It will raise an IndexError if
7990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    that expectation is not true.  If you expect a field to have
8000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    possible multiple values, than you can use form.getlist(key) to
8010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    get all of the values.  values() and items() are a compromise:
8020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    they return single strings where there is a single value, and
8030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    lists of strings otherwise.
8040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
8050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """
8060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __getitem__(self, key):
8070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if len(self.dict[key]) > 1:
8080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise IndexError, 'expecting a single value'
8090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return self.dict[key][0]
8100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def getlist(self, key):
8110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return self.dict[key]
8120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def values(self):
8130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        result = []
8140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for value in self.dict.values():
8150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if len(value) == 1:
8160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                result.append(value[0])
8170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else: result.append(value)
8180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return result
8190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def items(self):
8200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        result = []
8210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for key, value in self.dict.items():
8220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if len(value) == 1:
8230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                result.append((key, value[0]))
8240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else: result.append((key, value))
8250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return result
8260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
8270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
8280a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass InterpFormContentDict(SvFormContentDict):
8290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """This class is present for backwards compatibility only."""
8300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __getitem__(self, key):
8310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        v = SvFormContentDict.__getitem__(self, key)
8320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if v[0] in '0123456789+-.':
8330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            try: return int(v)
8340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            except ValueError:
8350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                try: return float(v)
8360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                except ValueError: pass
8370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return v.strip()
8380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def values(self):
8390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        result = []
8400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for key in self.keys():
8410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            try:
8420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                result.append(self[key])
8430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            except IndexError:
8440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                result.append(self.dict[key])
8450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return result
8460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def items(self):
8470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        result = []
8480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for key in self.keys():
8490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            try:
8500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                result.append((key, self[key]))
8510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            except IndexError:
8520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                result.append((key, self.dict[key]))
8530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return result
8540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
8550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
8560a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass FormContent(FormContentDict):
8570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """This class is present for backwards compatibility only."""
8580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def values(self, key):
8590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if key in self.dict :return self.dict[key]
8600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else: return None
8610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def indexed_value(self, key, location):
8620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if key in self.dict:
8630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if len(self.dict[key]) > location:
8640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return self.dict[key][location]
8650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else: return None
8660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else: return None
8670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def value(self, key):
8680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if key in self.dict: return self.dict[key][0]
8690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else: return None
8700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def length(self, key):
8710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return len(self.dict[key])
8720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def stripped(self, key):
8730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if key in self.dict: return self.dict[key][0].strip()
8740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else: return None
8750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def pars(self):
8760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return self.dict
8770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
8780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
8790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Test/debug code
8800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# ===============
8810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
8820a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef test(environ=os.environ):
8830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Robust test CGI script, usable as main program.
8840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
8850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    Write minimal HTTP headers and dump all information provided to
8860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    the script in HTML form.
8870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
8880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """
8890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "Content-type: text/html"
8900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print
8910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    sys.stderr = sys.stdout
8920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    try:
8930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        form = FieldStorage()   # Replace with other classes to test those
8940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print_directory()
8950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print_arguments()
8960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print_form(form)
8970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print_environ(environ)
8980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print_environ_usage()
8990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def f():
9000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            exec "testing print_exception() -- <I>italics?</I>"
9010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def g(f=f):
9020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            f()
9030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print "<H3>What follows is a test, not an actual exception:</H3>"
9040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        g()
9050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    except:
9060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print_exception()
9070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
9080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "<H1>Second try with a small maxlen...</H1>"
9090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
9100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    global maxlen
9110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    maxlen = 50
9120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    try:
9130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        form = FieldStorage()   # Replace with other classes to test those
9140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print_directory()
9150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print_arguments()
9160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print_form(form)
9170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print_environ(environ)
9180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    except:
9190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print_exception()
9200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
9210a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef print_exception(type=None, value=None, tb=None, limit=None):
9220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if type is None:
9230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        type, value, tb = sys.exc_info()
9240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    import traceback
9250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print
9260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "<H3>Traceback (most recent call last):</H3>"
9270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    list = traceback.format_tb(tb, limit) + \
9280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao           traceback.format_exception_only(type, value)
9290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "<PRE>%s<B>%s</B></PRE>" % (
9300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        escape("".join(list[:-1])),
9310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        escape(list[-1]),
9320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        )
9330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    del tb
9340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
9350a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef print_environ(environ=os.environ):
9360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Dump the shell environment as HTML."""
9370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    keys = environ.keys()
9380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    keys.sort()
9390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print
9400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "<H3>Shell Environment:</H3>"
9410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "<DL>"
9420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    for key in keys:
9430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print "<DT>", escape(key), "<DD>", escape(environ[key])
9440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "</DL>"
9450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print
9460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
9470a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef print_form(form):
9480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Dump the contents of a form as HTML."""
9490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    keys = form.keys()
9500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    keys.sort()
9510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print
9520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "<H3>Form Contents:</H3>"
9530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if not keys:
9540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print "<P>No form fields."
9550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "<DL>"
9560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    for key in keys:
9570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print "<DT>" + escape(key) + ":",
9580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        value = form[key]
9590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print "<i>" + escape(repr(type(value))) + "</i>"
9600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print "<DD>" + escape(repr(value))
9610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "</DL>"
9620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print
9630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
9640a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef print_directory():
9650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Dump the current directory as HTML."""
9660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print
9670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "<H3>Current Working Directory:</H3>"
9680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    try:
9690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        pwd = os.getcwd()
9700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    except os.error, msg:
9710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print "os.error:", escape(str(msg))
9720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    else:
9730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print escape(pwd)
9740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print
9750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
9760a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef print_arguments():
9770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print
9780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print "<H3>Command Line Arguments:</H3>"
9790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print
9800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print sys.argv
9810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print
9820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
9830a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef print_environ_usage():
9840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    """Dump a list of environment variables used by CGI as HTML."""
9850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    print """
9860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<H3>These environment variables could have been set:</H3>
9870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<UL>
9880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>AUTH_TYPE
9890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>CONTENT_LENGTH
9900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>CONTENT_TYPE
9910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>DATE_GMT
9920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>DATE_LOCAL
9930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>DOCUMENT_NAME
9940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>DOCUMENT_ROOT
9950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>DOCUMENT_URI
9960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>GATEWAY_INTERFACE
9970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>LAST_MODIFIED
9980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>PATH
9990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>PATH_INFO
10000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>PATH_TRANSLATED
10010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>QUERY_STRING
10020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>REMOTE_ADDR
10030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>REMOTE_HOST
10040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>REMOTE_IDENT
10050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>REMOTE_USER
10060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>REQUEST_METHOD
10070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>SCRIPT_NAME
10080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>SERVER_NAME
10090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>SERVER_PORT
10100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>SERVER_PROTOCOL
10110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>SERVER_ROOT
10120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>SERVER_SOFTWARE
10130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao</UL>
10140a8c90248264a8b26970b4473770bcc3df8515fJosh GaoIn addition, HTTP headers sent by the server may be passed in the
10150a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoenvironment as well.  Here are some common variable names:
10160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<UL>
10170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>HTTP_ACCEPT
10180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>HTTP_CONNECTION
10190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>HTTP_HOST
10200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>HTTP_PRAGMA
10210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>HTTP_REFERER
10220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao<LI>HTTP_USER_AGENT
10230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao</UL>
10240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao"""
10250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
10260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
10270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Utilities
10280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# =========
10290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
10300a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef escape(s, quote=None):
10310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
10320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    If the optional flag quote is true, the quotation mark character (")
10330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    is also translated.'''
10340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    s = s.replace("&", "&amp;") # Must be done first!
10350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    s = s.replace("<", "&lt;")
10360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    s = s.replace(">", "&gt;")
10370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if quote:
10380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        s = s.replace('"', "&quot;")
10390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return s
10400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
10410a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
10420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    import re
10430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return re.match(_vb_pattern, s)
10440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
10450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Invoke mainline
10460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# ===============
10470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
10480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Call test() when this file is run as a script (not imported as a module)
10490a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif __name__ == '__main__':
10500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    test()
1051