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