| 
									
										
										
										
											2000-10-03 13:51:09 +00:00
										 |  |  | #! /usr/local/bin/python | 
					
						
							| 
									
										
										
										
											1995-09-18 21:52:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-02-13 13:13:33 +00:00
										 |  |  | # NOTE: the above "/usr/local/bin/python" is NOT a mistake.  It is | 
					
						
							|  |  |  | # intentionally NOT "/usr/bin/env python".  On many systems | 
					
						
							|  |  |  | # (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI | 
					
						
							|  |  |  | # scripts, and /usr/local/bin is the default directory where Python is | 
					
						
							|  |  |  | # installed, so /usr/bin/env would be unable to find python.  Granted, | 
					
						
							|  |  |  | # binary installations by Linux vendors often install Python in | 
					
						
							|  |  |  | # /usr/bin.  So let those vendors patch cgi.py to match their choice | 
					
						
							|  |  |  | # of installation. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | """Support module for CGI (Common Gateway Interface) scripts.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | This module defines a number of utilities for use by CGI scripts | 
					
						
							|  |  |  | written in Python. | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-03 20:57:44 +00:00
										 |  |  | # XXX Perhaps there should be a slimmed version that doesn't contain | 
					
						
							|  |  |  | # all those backwards compatible and debugging classes and functions? | 
					
						
							| 
									
										
										
										
											2000-02-28 15:12:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # History | 
					
						
							|  |  |  | # ------- | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2000-02-28 15:12:25 +00:00
										 |  |  | # Michael McLay started this module.  Steve Majewski changed the | 
					
						
							|  |  |  | # interface to SvFormContentDict and FormContentDict.  The multipart | 
					
						
							|  |  |  | # parsing was inspired by code submitted by Andreas Paepcke.  Guido van | 
					
						
							|  |  |  | # Rossum rewrote, reformatted and documented the module and is currently | 
					
						
							|  |  |  | # responsible for its maintenance. | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2000-02-28 15:12:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-06-29 13:06:06 +00:00
										 |  |  | __version__ = "2.6" | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Imports | 
					
						
							|  |  |  | # ======= | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-31 21:59:02 +00:00
										 |  |  | from operator import attrgetter | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | import sys | 
					
						
							|  |  |  | import os | 
					
						
							| 
									
										
										
										
											1997-08-12 18:18:13 +00:00
										 |  |  | import urllib | 
					
						
							| 
									
										
										
										
											2000-08-25 21:47:56 +00:00
										 |  |  | import UserDict | 
					
						
							| 
									
										
										
										
											2008-09-02 01:25:16 +00:00
										 |  |  | from warnings import filterwarnings, catch_warnings | 
					
						
							|  |  |  | with catch_warnings(): | 
					
						
							|  |  |  |     if sys.py3kwarning: | 
					
						
							|  |  |  |         filterwarnings("ignore", ".*mimetools has been removed", | 
					
						
							|  |  |  |                         DeprecationWarning) | 
					
						
							| 
									
										
										
										
											2008-08-16 22:00:27 +00:00
										 |  |  |     import mimetools | 
					
						
							| 
									
										
										
										
											2008-09-02 01:25:16 +00:00
										 |  |  |     if sys.py3kwarning: | 
					
						
							|  |  |  |         filterwarnings("ignore", ".*rfc822 has been removed", DeprecationWarning) | 
					
						
							| 
									
										
										
										
											2008-08-16 22:00:27 +00:00
										 |  |  |     import rfc822 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-12-31 19:15:26 +00:00
										 |  |  | try: | 
					
						
							|  |  |  |     from cStringIO import StringIO | 
					
						
							|  |  |  | except ImportError: | 
					
						
							|  |  |  |     from StringIO import StringIO | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-03-19 13:40:44 +00:00
										 |  |  | __all__ = ["MiniFieldStorage", "FieldStorage", "FormContentDict", | 
					
						
							|  |  |  |            "SvFormContentDict", "InterpFormContentDict", "FormContent", | 
					
						
							|  |  |  |            "parse", "parse_qs", "parse_qsl", "parse_multipart", | 
					
						
							|  |  |  |            "parse_header", "print_exception", "print_environ", | 
					
						
							|  |  |  |            "print_form", "print_directory", "print_arguments", | 
					
						
							|  |  |  |            "print_environ_usage", "escape"] | 
					
						
							| 
									
										
										
										
											1996-09-05 19:07:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Logging support | 
					
						
							|  |  |  | # =============== | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  | logfile = ""            # Filename to log to, if not empty | 
					
						
							|  |  |  | logfp = None            # File object to log to, if not None | 
					
						
							| 
									
										
										
										
											1996-09-05 19:07:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def initlog(*allargs): | 
					
						
							|  |  |  |     """Write a log message, if there is a log file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Even though this function is called initlog(), you should always | 
					
						
							|  |  |  |     use log(); log is a variable that is set either to initlog | 
					
						
							|  |  |  |     (initially), to dolog (once the log file has been opened), or to | 
					
						
							|  |  |  |     nolog (when logging is disabled). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The first argument is a format string; the remaining arguments (if | 
					
						
							|  |  |  |     any) are arguments to the % operator, so e.g. | 
					
						
							|  |  |  |         log("%s: %s", "a", "b") | 
					
						
							|  |  |  |     will write "a: b" to the log file, followed by a newline. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If the global logfp is not None, it should be a file object to | 
					
						
							|  |  |  |     which log data is written. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If the global logfp is None, the global logfile may be a string | 
					
						
							|  |  |  |     giving a filename to open, in append mode.  This file should be | 
					
						
							|  |  |  |     world writable!!!  If the file can't be opened, logging is | 
					
						
							|  |  |  |     silently disabled (since there is no safe place where we could | 
					
						
							|  |  |  |     send an error message). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     global logfp, log | 
					
						
							|  |  |  |     if logfile and not logfp: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             logfp = open(logfile, "a") | 
					
						
							|  |  |  |         except IOError: | 
					
						
							|  |  |  |             pass | 
					
						
							| 
									
										
										
										
											1996-09-05 19:07:11 +00:00
										 |  |  |     if not logfp: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         log = nolog | 
					
						
							| 
									
										
										
										
											1996-09-05 19:07:11 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         log = dolog | 
					
						
							| 
									
										
										
										
											2003-02-27 20:14:51 +00:00
										 |  |  |     log(*allargs) | 
					
						
							| 
									
										
										
										
											1996-09-05 19:07:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def dolog(fmt, *args): | 
					
						
							|  |  |  |     """Write a log message to the log file.  See initlog() for docs.""" | 
					
						
							|  |  |  |     logfp.write(fmt%args + "\n") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def nolog(*allargs): | 
					
						
							|  |  |  |     """Dummy function, assigned to log when logging is disabled.""" | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  | log = initlog           # The current logging function | 
					
						
							| 
									
										
										
										
											1996-09-05 19:07:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  | # Parsing functions | 
					
						
							|  |  |  | # ================= | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-13 19:03:23 +00:00
										 |  |  | # Maximum input we will accept when REQUEST_METHOD is POST | 
					
						
							|  |  |  | # 0 ==> unlimited input | 
					
						
							|  |  |  | maxlen = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-11-11 19:29:11 +00:00
										 |  |  | def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0): | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |     """Parse a query in the environment or from a file (default stdin)
 | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |         Arguments, all optional: | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |         fp              : file pointer; default: sys.stdin | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         environ         : environment dictionary; default: os.environ | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |         keep_blank_values: flag indicating whether blank values in | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  |             URL encoded forms should be treated as blank strings. | 
					
						
							|  |  |  |             A true value indicates that blanks should be retained as | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |             blank strings.  The default false value indicates that | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             blank values are to be ignored and treated as if they were | 
					
						
							|  |  |  |             not included. | 
					
						
							| 
									
										
										
										
											1996-11-11 19:29:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         strict_parsing: flag indicating what to do with parsing errors. | 
					
						
							|  |  |  |             If false (the default), errors are silently ignored. | 
					
						
							|  |  |  |             If true, errors raise a ValueError exception. | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2002-05-31 23:54:44 +00:00
										 |  |  |     if fp is None: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         fp = sys.stdin | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |     if not 'REQUEST_METHOD' in environ: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         environ['REQUEST_METHOD'] = 'GET'       # For testing stand-alone | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     if environ['REQUEST_METHOD'] == 'POST': | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         ctype, pdict = parse_header(environ['CONTENT_TYPE']) | 
					
						
							|  |  |  |         if ctype == 'multipart/form-data': | 
					
						
							|  |  |  |             return parse_multipart(fp, pdict) | 
					
						
							|  |  |  |         elif ctype == 'application/x-www-form-urlencoded': | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |             clength = int(environ['CONTENT_LENGTH']) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             if maxlen and clength > maxlen: | 
					
						
							|  |  |  |                 raise ValueError, 'Maximum content length exceeded' | 
					
						
							|  |  |  |             qs = fp.read(clength) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             qs = ''                     # Unknown content-type | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if 'QUERY_STRING' in environ: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             if qs: qs = qs + '&' | 
					
						
							|  |  |  |             qs = qs + environ['QUERY_STRING'] | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  |         elif sys.argv[1:]: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             if qs: qs = qs + '&' | 
					
						
							|  |  |  |             qs = qs + sys.argv[1] | 
					
						
							|  |  |  |         environ['QUERY_STRING'] = qs    # XXX Shouldn't, really | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |     elif 'QUERY_STRING' in environ: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         qs = environ['QUERY_STRING'] | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         if sys.argv[1:]: | 
					
						
							|  |  |  |             qs = sys.argv[1] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             qs = "" | 
					
						
							|  |  |  |         environ['QUERY_STRING'] = qs    # XXX Shouldn't, really | 
					
						
							| 
									
										
										
										
											1996-11-11 19:29:11 +00:00
										 |  |  |     return parse_qs(qs, keep_blank_values, strict_parsing) | 
					
						
							| 
									
										
										
										
											1995-08-07 20:12:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-11-11 19:29:11 +00:00
										 |  |  | def parse_qs(qs, keep_blank_values=0, strict_parsing=0): | 
					
						
							|  |  |  |     """Parse a query given as a string argument.
 | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         Arguments: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         qs: URL-encoded query string to be parsed | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         keep_blank_values: flag indicating whether blank values in | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  |             URL encoded queries should be treated as blank strings. | 
					
						
							|  |  |  |             A true value indicates that blanks should be retained as | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |             blank strings.  The default false value indicates that | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             blank values are to be ignored and treated as if they were | 
					
						
							|  |  |  |             not included. | 
					
						
							| 
									
										
										
										
											1996-11-11 19:29:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         strict_parsing: flag indicating what to do with parsing errors. | 
					
						
							|  |  |  |             If false (the default), errors are silently ignored. | 
					
						
							|  |  |  |             If true, errors raise a ValueError exception. | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     dict = {} | 
					
						
							| 
									
										
										
										
											1999-06-04 17:54:39 +00:00
										 |  |  |     for name, value in parse_qsl(qs, keep_blank_values, strict_parsing): | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if name in dict: | 
					
						
							| 
									
										
										
										
											2000-08-25 21:47:56 +00:00
										 |  |  |             dict[name].append(value) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             dict[name] = [value] | 
					
						
							| 
									
										
										
										
											1999-06-04 17:54:39 +00:00
										 |  |  |     return dict | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def parse_qsl(qs, keep_blank_values=0, strict_parsing=0): | 
					
						
							|  |  |  |     """Parse a query given as a string argument.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-15 20:06:57 +00:00
										 |  |  |     Arguments: | 
					
						
							| 
									
										
										
										
											1999-06-04 17:54:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-15 20:06:57 +00:00
										 |  |  |     qs: URL-encoded query string to be parsed | 
					
						
							| 
									
										
										
										
											1999-06-04 17:54:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-15 20:06:57 +00:00
										 |  |  |     keep_blank_values: flag indicating whether blank values in | 
					
						
							|  |  |  |         URL encoded queries should be treated as blank strings.  A | 
					
						
							|  |  |  |         true value indicates that blanks should be retained as blank | 
					
						
							|  |  |  |         strings.  The default false value indicates that blank values | 
					
						
							|  |  |  |         are to be ignored and treated as if they were  not included. | 
					
						
							| 
									
										
										
										
											1999-06-04 17:54:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-15 20:06:57 +00:00
										 |  |  |     strict_parsing: flag indicating what to do with parsing errors. If | 
					
						
							|  |  |  |         false (the default), errors are silently ignored. If true, | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  |         errors raise a ValueError exception. | 
					
						
							| 
									
										
										
										
											1999-06-04 17:54:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-15 20:06:57 +00:00
										 |  |  |     Returns a list, as G-d intended. | 
					
						
							| 
									
										
										
										
											1999-06-04 17:54:39 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2000-09-15 20:06:57 +00:00
										 |  |  |     pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')] | 
					
						
							|  |  |  |     r = [] | 
					
						
							|  |  |  |     for name_value in pairs: | 
					
						
							| 
									
										
										
										
											2004-07-19 15:38:11 +00:00
										 |  |  |         if not name_value and not strict_parsing: | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2000-09-15 20:06:57 +00:00
										 |  |  |         nv = name_value.split('=', 1) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         if len(nv) != 2: | 
					
						
							|  |  |  |             if strict_parsing: | 
					
						
							| 
									
										
										
										
											2004-02-12 17:35:32 +00:00
										 |  |  |                 raise ValueError, "bad query field: %r" % (name_value,) | 
					
						
							| 
									
										
										
										
											2004-03-21 22:16:15 +00:00
										 |  |  |             # Handle case of a control-name with no equal sign | 
					
						
							|  |  |  |             if keep_blank_values: | 
					
						
							|  |  |  |                 nv.append('') | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2000-08-25 21:47:56 +00:00
										 |  |  |         if len(nv[1]) or keep_blank_values: | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |             name = urllib.unquote(nv[0].replace('+', ' ')) | 
					
						
							|  |  |  |             value = urllib.unquote(nv[1].replace('+', ' ')) | 
					
						
							| 
									
										
										
										
											2000-08-25 21:47:56 +00:00
										 |  |  |             r.append((name, value)) | 
					
						
							| 
									
										
										
										
											1999-06-04 17:54:39 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return r | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  | def parse_multipart(fp, pdict): | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     """Parse multipart input.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Arguments: | 
					
						
							|  |  |  |     fp   : input file | 
					
						
							| 
									
										
										
										
											2005-01-08 13:56:36 +00:00
										 |  |  |     pdict: dictionary containing other parameters of content-type header | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  |     Returns a dictionary just like parse_qs(): keys are the field names, each | 
					
						
							|  |  |  |     value is a list of values for that field.  This is easy to use but not | 
					
						
							|  |  |  |     much good if you are expecting megabytes to be uploaded -- in that case, | 
					
						
							|  |  |  |     use the FieldStorage class instead which is much more flexible.  Note | 
					
						
							|  |  |  |     that content-type is the raw, unparsed contents of the content-type | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  |     header. | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     XXX This does not parse nested multipart parts -- use FieldStorage for | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  |     that. | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     XXX This should really be subsumed by FieldStorage altogether -- no | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  |     point in having two implementations of the same parsing algorithm. | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |     Also, FieldStorage protects itself better against certain DoS attacks | 
					
						
							|  |  |  |     by limiting the size of the data read in one chunk.  The API here | 
					
						
							|  |  |  |     does not support that kind of protection.  This also affects parse() | 
					
						
							|  |  |  |     since it can call parse_multipart(). | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2001-07-25 21:00:19 +00:00
										 |  |  |     boundary = "" | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |     if 'boundary' in pdict: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         boundary = pdict['boundary'] | 
					
						
							| 
									
										
										
										
											2001-07-25 21:00:19 +00:00
										 |  |  |     if not valid_boundary(boundary): | 
					
						
							| 
									
										
										
										
											2004-02-12 17:35:32 +00:00
										 |  |  |         raise ValueError,  ('Invalid boundary in multipart form: %r' | 
					
						
							|  |  |  |                             % (boundary,)) | 
					
						
							| 
									
										
										
										
											2001-08-09 21:40:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     nextpart = "--" + boundary | 
					
						
							|  |  |  |     lastpart = "--" + boundary + "--" | 
					
						
							|  |  |  |     partdict = {} | 
					
						
							|  |  |  |     terminator = "" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while terminator != lastpart: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         bytes = -1 | 
					
						
							|  |  |  |         data = None | 
					
						
							|  |  |  |         if terminator: | 
					
						
							|  |  |  |             # At start of next part.  Read headers first. | 
					
						
							| 
									
										
										
										
											2005-09-19 09:11:04 +00:00
										 |  |  |             headers = mimetools.Message(fp) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             clength = headers.getheader('content-length') | 
					
						
							|  |  |  |             if clength: | 
					
						
							|  |  |  |                 try: | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |                     bytes = int(clength) | 
					
						
							|  |  |  |                 except ValueError: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |                     pass | 
					
						
							|  |  |  |             if bytes > 0: | 
					
						
							|  |  |  |                 if maxlen and bytes > maxlen: | 
					
						
							|  |  |  |                     raise ValueError, 'Maximum content length exceeded' | 
					
						
							|  |  |  |                 data = fp.read(bytes) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 data = "" | 
					
						
							|  |  |  |         # Read lines until end of part. | 
					
						
							|  |  |  |         lines = [] | 
					
						
							|  |  |  |         while 1: | 
					
						
							|  |  |  |             line = fp.readline() | 
					
						
							|  |  |  |             if not line: | 
					
						
							|  |  |  |                 terminator = lastpart # End outer loop | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             if line[:2] == "--": | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |                 terminator = line.strip() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |                 if terminator in (nextpart, lastpart): | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |             lines.append(line) | 
					
						
							|  |  |  |         # Done with part. | 
					
						
							|  |  |  |         if data is None: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         if bytes < 0: | 
					
						
							|  |  |  |             if lines: | 
					
						
							|  |  |  |                 # Strip final line terminator | 
					
						
							|  |  |  |                 line = lines[-1] | 
					
						
							|  |  |  |                 if line[-2:] == "\r\n": | 
					
						
							|  |  |  |                     line = line[:-2] | 
					
						
							|  |  |  |                 elif line[-1:] == "\n": | 
					
						
							|  |  |  |                     line = line[:-1] | 
					
						
							|  |  |  |                 lines[-1] = line | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |                 data = "".join(lines) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         line = headers['content-disposition'] | 
					
						
							|  |  |  |         if not line: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         key, params = parse_header(line) | 
					
						
							|  |  |  |         if key != 'form-data': | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if 'name' in params: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             name = params['name'] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if name in partdict: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             partdict[name].append(data) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             partdict[name] = [data] | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return partdict | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def parse_header(line): | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     """Parse a Content-type like header.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Return the main content-type and a dictionary of options. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2004-12-31 21:59:02 +00:00
										 |  |  |     plist = [x.strip() for x in line.split(';')] | 
					
						
							| 
									
										
										
										
											2002-06-30 03:39:14 +00:00
										 |  |  |     key = plist.pop(0).lower() | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     pdict = {} | 
					
						
							|  |  |  |     for p in plist: | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |         i = p.find('=') | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         if i >= 0: | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |             name = p[:i].strip().lower() | 
					
						
							|  |  |  |             value = p[i+1:].strip() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             if len(value) >= 2 and value[0] == value[-1] == '"': | 
					
						
							|  |  |  |                 value = value[1:-1] | 
					
						
							| 
									
										
										
										
											2004-08-14 15:39:34 +00:00
										 |  |  |                 value = value.replace('\\\\', '\\').replace('\\"', '"') | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             pdict[name] = value | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     return key, pdict | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-07 06:33:07 +00:00
										 |  |  | # Classes for field storage | 
					
						
							|  |  |  | # ========================= | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MiniFieldStorage: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  |     """Like FieldStorage, for use when no file uploads are possible.""" | 
					
						
							| 
									
										
										
										
											1996-03-07 06:33:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     # Dummy attributes | 
					
						
							|  |  |  |     filename = None | 
					
						
							|  |  |  |     list = None | 
					
						
							|  |  |  |     type = None | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |     file = None | 
					
						
							| 
									
										
										
										
											1996-03-09 04:04:35 +00:00
										 |  |  |     type_options = {} | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     disposition = None | 
					
						
							|  |  |  |     disposition_options = {} | 
					
						
							|  |  |  |     headers = {} | 
					
						
							| 
									
										
										
										
											1996-03-07 06:33:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     def __init__(self, name, value): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Constructor from field name and value.""" | 
					
						
							|  |  |  |         self.name = name | 
					
						
							|  |  |  |         self.value = value | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |         # self.file = StringIO(value) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Return printable representation.""" | 
					
						
							| 
									
										
										
										
											2004-02-12 17:35:32 +00:00
										 |  |  |         return "MiniFieldStorage(%r, %r)" % (self.name, self.value) | 
					
						
							| 
									
										
										
										
											1996-03-07 06:33:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FieldStorage: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     """Store a sequence of fields, reading multipart/form-data.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This class provides naming, typing, files stored on disk, and | 
					
						
							|  |  |  |     more.  At the top level, it is accessible like a dictionary, whose | 
					
						
							|  |  |  |     keys are the field names.  (Note: None can occur as a field name.) | 
					
						
							|  |  |  |     The items are either a Python list (if there's multiple values) or | 
					
						
							|  |  |  |     another FieldStorage or MiniFieldStorage object.  If it's a single | 
					
						
							|  |  |  |     object, it has the following attributes: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     name: the field name, if specified; otherwise None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     filename: the filename, if specified; otherwise None; this is the | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         client side filename, *not* the file name on which it is | 
					
						
							|  |  |  |         stored (that's a temporary file you don't deal with) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     value: the value as a *string*; for file uploads, this | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         transparently reads the file every time you request the value | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     file: the file(-like) object from which you can read the data; | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         None if the data is stored a simple string | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     type: the content-type, or None if not specified | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     type_options: dictionary of options specified on the content-type | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         line | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     disposition: content-disposition, or None if not specified | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     disposition_options: dictionary of corresponding options | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-09-19 09:11:04 +00:00
										 |  |  |     headers: a dictionary(-like) object (sometimes rfc822.Message or a | 
					
						
							|  |  |  |         subclass thereof) containing *all* headers | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     The class is subclassable, mostly for the purpose of overriding | 
					
						
							|  |  |  |     the make_file() method, which is called internally to come up with | 
					
						
							|  |  |  |     a file open for reading and writing.  This makes it possible to | 
					
						
							|  |  |  |     override the default choice of storing all files in a temporary | 
					
						
							|  |  |  |     directory and unlinking them as soon as they have been opened. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |     def __init__(self, fp=None, headers=None, outerboundary="", | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |                  environ=os.environ, keep_blank_values=0, strict_parsing=0): | 
					
						
							|  |  |  |         """Constructor.  Read multipart/* until last part.
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         Arguments, all optional: | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         fp              : file pointer; default: sys.stdin | 
					
						
							| 
									
										
										
										
											1998-05-08 19:55:51 +00:00
										 |  |  |             (not used when the request method is GET) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         headers         : header dictionary-like object; default: | 
					
						
							|  |  |  |             taken from environ as per CGI spec | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |         outerboundary   : terminating multipart boundary | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             (for internal use only) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         environ         : environment dictionary; default: os.environ | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         keep_blank_values: flag indicating whether blank values in | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  |             URL encoded forms should be treated as blank strings. | 
					
						
							|  |  |  |             A true value indicates that blanks should be retained as | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  |             blank strings.  The default false value indicates that | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             blank values are to be ignored and treated as if they were | 
					
						
							|  |  |  |             not included. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         strict_parsing: flag indicating what to do with parsing errors. | 
					
						
							|  |  |  |             If false (the default), errors are silently ignored. | 
					
						
							|  |  |  |             If true, errors raise a ValueError exception. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         method = 'GET' | 
					
						
							|  |  |  |         self.keep_blank_values = keep_blank_values | 
					
						
							|  |  |  |         self.strict_parsing = strict_parsing | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if 'REQUEST_METHOD' in environ: | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |             method = environ['REQUEST_METHOD'].upper() | 
					
						
							| 
									
										
										
										
											2008-06-21 18:58:04 +00:00
										 |  |  |         self.qs_on_post = None | 
					
						
							| 
									
										
										
										
											1998-06-25 02:40:17 +00:00
										 |  |  |         if method == 'GET' or method == 'HEAD': | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |             if 'QUERY_STRING' in environ: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |                 qs = environ['QUERY_STRING'] | 
					
						
							|  |  |  |             elif sys.argv[1:]: | 
					
						
							|  |  |  |                 qs = sys.argv[1] | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 qs = "" | 
					
						
							|  |  |  |             fp = StringIO(qs) | 
					
						
							|  |  |  |             if headers is None: | 
					
						
							|  |  |  |                 headers = {'content-type': | 
					
						
							|  |  |  |                            "application/x-www-form-urlencoded"} | 
					
						
							|  |  |  |         if headers is None: | 
					
						
							| 
									
										
										
										
											1998-06-11 14:06:59 +00:00
										 |  |  |             headers = {} | 
					
						
							|  |  |  |             if method == 'POST': | 
					
						
							|  |  |  |                 # Set default content-type for POST to what's traditional | 
					
						
							|  |  |  |                 headers['content-type'] = "application/x-www-form-urlencoded" | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |             if 'CONTENT_TYPE' in environ: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |                 headers['content-type'] = environ['CONTENT_TYPE'] | 
					
						
							| 
									
										
										
										
											2008-06-21 18:58:04 +00:00
										 |  |  |             if 'QUERY_STRING' in environ: | 
					
						
							|  |  |  |                 self.qs_on_post = environ['QUERY_STRING'] | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |             if 'CONTENT_LENGTH' in environ: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |                 headers['content-length'] = environ['CONTENT_LENGTH'] | 
					
						
							|  |  |  |         self.fp = fp or sys.stdin | 
					
						
							|  |  |  |         self.headers = headers | 
					
						
							|  |  |  |         self.outerboundary = outerboundary | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Process content-disposition header | 
					
						
							|  |  |  |         cdisp, pdict = "", {} | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if 'content-disposition' in self.headers: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             cdisp, pdict = parse_header(self.headers['content-disposition']) | 
					
						
							|  |  |  |         self.disposition = cdisp | 
					
						
							|  |  |  |         self.disposition_options = pdict | 
					
						
							|  |  |  |         self.name = None | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if 'name' in pdict: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             self.name = pdict['name'] | 
					
						
							|  |  |  |         self.filename = None | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if 'filename' in pdict: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             self.filename = pdict['filename'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Process content-type header | 
					
						
							| 
									
										
										
										
											1999-01-08 17:42:03 +00:00
										 |  |  |         # | 
					
						
							|  |  |  |         # Honor any existing content-type header.  But if there is no | 
					
						
							|  |  |  |         # content-type header, use some sensible defaults.  Assume | 
					
						
							|  |  |  |         # outerboundary is "" at the outer level, but something non-false | 
					
						
							|  |  |  |         # inside a multi-part.  The default for an inner part is text/plain, | 
					
						
							|  |  |  |         # but for an outer part it should be urlencoded.  This should catch | 
					
						
							|  |  |  |         # bogus clients which erroneously forget to include a content-type | 
					
						
							|  |  |  |         # header. | 
					
						
							|  |  |  |         # | 
					
						
							|  |  |  |         # See below for what we do if there does exist a content-type header, | 
					
						
							|  |  |  |         # but it happens to be something we don't understand. | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if 'content-type' in self.headers: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             ctype, pdict = parse_header(self.headers['content-type']) | 
					
						
							| 
									
										
										
										
											1999-06-02 18:44:22 +00:00
										 |  |  |         elif self.outerboundary or method != 'POST': | 
					
						
							| 
									
										
										
										
											1999-01-08 17:42:03 +00:00
										 |  |  |             ctype, pdict = "text/plain", {} | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             ctype, pdict = 'application/x-www-form-urlencoded', {} | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         self.type = ctype | 
					
						
							|  |  |  |         self.type_options = pdict | 
					
						
							|  |  |  |         self.innerboundary = "" | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if 'boundary' in pdict: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             self.innerboundary = pdict['boundary'] | 
					
						
							|  |  |  |         clen = -1 | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if 'content-length' in self.headers: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             try: | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |                 clen = int(self.headers['content-length']) | 
					
						
							| 
									
										
										
										
											2002-03-23 05:50:17 +00:00
										 |  |  |             except ValueError: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |                 pass | 
					
						
							|  |  |  |             if maxlen and clen > maxlen: | 
					
						
							|  |  |  |                 raise ValueError, 'Maximum content length exceeded' | 
					
						
							|  |  |  |         self.length = clen | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.list = self.file = None | 
					
						
							|  |  |  |         self.done = 0 | 
					
						
							|  |  |  |         if ctype == 'application/x-www-form-urlencoded': | 
					
						
							|  |  |  |             self.read_urlencoded() | 
					
						
							|  |  |  |         elif ctype[:10] == 'multipart/': | 
					
						
							| 
									
										
										
										
											1998-10-20 14:43:02 +00:00
										 |  |  |             self.read_multi(environ, keep_blank_values, strict_parsing) | 
					
						
							| 
									
										
										
										
											1999-01-08 17:42:03 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											1999-06-11 18:26:09 +00:00
										 |  |  |             self.read_single() | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __repr__(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Return a printable representation.""" | 
					
						
							| 
									
										
										
										
											2004-02-12 17:35:32 +00:00
										 |  |  |         return "FieldStorage(%r, %r, %r)" % ( | 
					
						
							|  |  |  |                 self.name, self.filename, self.value) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-09-11 18:20:34 +00:00
										 |  |  |     def __iter__(self): | 
					
						
							|  |  |  |         return iter(self.keys()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     def __getattr__(self, name): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         if name != 'value': | 
					
						
							|  |  |  |             raise AttributeError, name | 
					
						
							|  |  |  |         if self.file: | 
					
						
							|  |  |  |             self.file.seek(0) | 
					
						
							|  |  |  |             value = self.file.read() | 
					
						
							|  |  |  |             self.file.seek(0) | 
					
						
							|  |  |  |         elif self.list is not None: | 
					
						
							|  |  |  |             value = self.list | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             value = None | 
					
						
							|  |  |  |         return value | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __getitem__(self, key): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Dictionary style indexing.""" | 
					
						
							|  |  |  |         if self.list is None: | 
					
						
							|  |  |  |             raise TypeError, "not indexable" | 
					
						
							|  |  |  |         found = [] | 
					
						
							|  |  |  |         for item in self.list: | 
					
						
							|  |  |  |             if item.name == key: found.append(item) | 
					
						
							|  |  |  |         if not found: | 
					
						
							|  |  |  |             raise KeyError, key | 
					
						
							|  |  |  |         if len(found) == 1: | 
					
						
							|  |  |  |             return found[0] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return found | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-25 21:47:56 +00:00
										 |  |  |     def getvalue(self, key, default=None): | 
					
						
							|  |  |  |         """Dictionary style get() method, including 'value' lookup.""" | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if key in self: | 
					
						
							| 
									
										
										
										
											2000-08-25 21:47:56 +00:00
										 |  |  |             value = self[key] | 
					
						
							|  |  |  |             if type(value) is type([]): | 
					
						
							| 
									
										
										
										
											2004-12-31 21:59:02 +00:00
										 |  |  |                 return map(attrgetter('value'), value) | 
					
						
							| 
									
										
										
										
											2000-08-25 21:47:56 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 return value.value | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return default | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-09-05 19:45:34 +00:00
										 |  |  |     def getfirst(self, key, default=None): | 
					
						
							|  |  |  |         """ Return the first value received.""" | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if key in self: | 
					
						
							| 
									
										
										
										
											2001-09-05 19:45:34 +00:00
										 |  |  |             value = self[key] | 
					
						
							|  |  |  |             if type(value) is type([]): | 
					
						
							|  |  |  |                 return value[0].value | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 return value.value | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return default | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def getlist(self, key): | 
					
						
							|  |  |  |         """ Return list of received values.""" | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if key in self: | 
					
						
							| 
									
										
										
										
											2001-09-05 19:45:34 +00:00
										 |  |  |             value = self[key] | 
					
						
							|  |  |  |             if type(value) is type([]): | 
					
						
							| 
									
										
										
										
											2004-12-31 21:59:02 +00:00
										 |  |  |                 return map(attrgetter('value'), value) | 
					
						
							| 
									
										
										
										
											2001-09-05 19:45:34 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 return [value.value] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     def keys(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Dictionary style keys() method.""" | 
					
						
							|  |  |  |         if self.list is None: | 
					
						
							|  |  |  |             raise TypeError, "not indexable" | 
					
						
							| 
									
										
										
										
											2007-09-20 16:06:07 +00:00
										 |  |  |         return list(set(item.name for item in self.list)) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  |     def has_key(self, key): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Dictionary style has_key() method.""" | 
					
						
							|  |  |  |         if self.list is None: | 
					
						
							|  |  |  |             raise TypeError, "not indexable" | 
					
						
							| 
									
										
										
										
											2007-09-20 16:06:07 +00:00
										 |  |  |         return any(item.name == key for item in self.list) | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |     def __contains__(self, key): | 
					
						
							|  |  |  |         """Dictionary style __contains__ method.""" | 
					
						
							|  |  |  |         if self.list is None: | 
					
						
							|  |  |  |             raise TypeError, "not indexable" | 
					
						
							| 
									
										
										
										
											2007-09-20 16:06:07 +00:00
										 |  |  |         return any(item.name == key for item in self.list) | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-01-11 19:21:33 +00:00
										 |  |  |     def __len__(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Dictionary style len(x) support.""" | 
					
						
							|  |  |  |         return len(self.keys()) | 
					
						
							| 
									
										
										
										
											1997-01-11 19:21:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 16:06:07 +00:00
										 |  |  |     def __nonzero__(self): | 
					
						
							|  |  |  |         return bool(self.list) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     def read_urlencoded(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Internal: read data in query string format.""" | 
					
						
							|  |  |  |         qs = self.fp.read(self.length) | 
					
						
							| 
									
										
										
										
											2008-06-21 18:58:04 +00:00
										 |  |  |         if self.qs_on_post: | 
					
						
							|  |  |  |             qs += '&' + self.qs_on_post | 
					
						
							| 
									
										
										
										
											1999-06-04 17:54:39 +00:00
										 |  |  |         self.list = list = [] | 
					
						
							|  |  |  |         for key, value in parse_qsl(qs, self.keep_blank_values, | 
					
						
							|  |  |  |                                     self.strict_parsing): | 
					
						
							|  |  |  |             list.append(MiniFieldStorage(key, value)) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         self.skip_lines() | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-12-09 22:16:46 +00:00
										 |  |  |     FieldStorageClass = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-10-20 14:43:02 +00:00
										 |  |  |     def read_multi(self, environ, keep_blank_values, strict_parsing): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Internal: read a part that is itself multipart.""" | 
					
						
							| 
									
										
										
										
											2001-07-25 21:00:19 +00:00
										 |  |  |         ib = self.innerboundary | 
					
						
							|  |  |  |         if not valid_boundary(ib): | 
					
						
							| 
									
										
										
										
											2004-02-12 17:35:32 +00:00
										 |  |  |             raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         self.list = [] | 
					
						
							| 
									
										
										
										
											2008-06-21 18:58:04 +00:00
										 |  |  |         if self.qs_on_post: | 
					
						
							|  |  |  |             for key, value in parse_qsl(self.qs_on_post, self.keep_blank_values, | 
					
						
							|  |  |  |                                         self.strict_parsing): | 
					
						
							|  |  |  |                 self.list.append(MiniFieldStorage(key, value)) | 
					
						
							|  |  |  |             FieldStorageClass = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-12-09 22:16:46 +00:00
										 |  |  |         klass = self.FieldStorageClass or self.__class__ | 
					
						
							| 
									
										
										
										
											2001-07-25 21:00:19 +00:00
										 |  |  |         part = klass(self.fp, {}, ib, | 
					
						
							| 
									
										
										
										
											1998-12-09 22:16:46 +00:00
										 |  |  |                      environ, keep_blank_values, strict_parsing) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         # Throw first part away | 
					
						
							|  |  |  |         while not part.done: | 
					
						
							| 
									
										
										
										
											2005-09-19 09:11:04 +00:00
										 |  |  |             headers = rfc822.Message(self.fp) | 
					
						
							| 
									
										
										
										
											2001-07-25 21:00:19 +00:00
										 |  |  |             part = klass(self.fp, headers, ib, | 
					
						
							| 
									
										
										
										
											1998-12-09 22:16:46 +00:00
										 |  |  |                          environ, keep_blank_values, strict_parsing) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             self.list.append(part) | 
					
						
							|  |  |  |         self.skip_lines() | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def read_single(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Internal: read an atomic part.""" | 
					
						
							|  |  |  |         if self.length >= 0: | 
					
						
							|  |  |  |             self.read_binary() | 
					
						
							|  |  |  |             self.skip_lines() | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.read_lines() | 
					
						
							|  |  |  |         self.file.seek(0) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |     bufsize = 8*1024            # I/O buffering size for copy to file | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def read_binary(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Internal: read binary data.""" | 
					
						
							|  |  |  |         self.file = self.make_file('b') | 
					
						
							|  |  |  |         todo = self.length | 
					
						
							|  |  |  |         if todo >= 0: | 
					
						
							|  |  |  |             while todo > 0: | 
					
						
							|  |  |  |                 data = self.fp.read(min(todo, self.bufsize)) | 
					
						
							|  |  |  |                 if not data: | 
					
						
							|  |  |  |                     self.done = -1 | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |                 self.file.write(data) | 
					
						
							|  |  |  |                 todo = todo - len(data) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def read_lines(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Internal: read lines until EOF or outerboundary.""" | 
					
						
							| 
									
										
										
										
											2001-06-29 13:06:06 +00:00
										 |  |  |         self.file = self.__file = StringIO() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         if self.outerboundary: | 
					
						
							|  |  |  |             self.read_lines_to_outerboundary() | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self.read_lines_to_eof() | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-06-29 13:06:06 +00:00
										 |  |  |     def __write(self, line): | 
					
						
							|  |  |  |         if self.__file is not None: | 
					
						
							|  |  |  |             if self.__file.tell() + len(line) > 1000: | 
					
						
							|  |  |  |                 self.file = self.make_file('') | 
					
						
							|  |  |  |                 self.file.write(self.__file.getvalue()) | 
					
						
							|  |  |  |                 self.__file = None | 
					
						
							|  |  |  |         self.file.write(line) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     def read_lines_to_eof(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Internal: read lines until EOF.""" | 
					
						
							|  |  |  |         while 1: | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |             line = self.fp.readline(1<<16) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             if not line: | 
					
						
							|  |  |  |                 self.done = -1 | 
					
						
							|  |  |  |                 break | 
					
						
							| 
									
										
										
										
											2001-06-29 13:06:06 +00:00
										 |  |  |             self.__write(line) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def read_lines_to_outerboundary(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Internal: read lines until outerboundary.""" | 
					
						
							|  |  |  |         next = "--" + self.outerboundary | 
					
						
							|  |  |  |         last = next + "--" | 
					
						
							|  |  |  |         delim = "" | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |         last_line_lfend = True | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         while 1: | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |             line = self.fp.readline(1<<16) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             if not line: | 
					
						
							|  |  |  |                 self.done = -1 | 
					
						
							|  |  |  |                 break | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |             if line[:2] == "--" and last_line_lfend: | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |                 strippedline = line.strip() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |                 if strippedline == next: | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |                 if strippedline == last: | 
					
						
							|  |  |  |                     self.done = 1 | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |             odelim = delim | 
					
						
							|  |  |  |             if line[-2:] == "\r\n": | 
					
						
							|  |  |  |                 delim = "\r\n" | 
					
						
							|  |  |  |                 line = line[:-2] | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |                 last_line_lfend = True | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             elif line[-1] == "\n": | 
					
						
							|  |  |  |                 delim = "\n" | 
					
						
							|  |  |  |                 line = line[:-1] | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |                 last_line_lfend = True | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 delim = "" | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |                 last_line_lfend = False | 
					
						
							| 
									
										
										
										
											2001-06-29 13:06:06 +00:00
										 |  |  |             self.__write(odelim + line) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def skip_lines(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Internal: skip lines until outer boundary if defined.""" | 
					
						
							|  |  |  |         if not self.outerboundary or self.done: | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         next = "--" + self.outerboundary | 
					
						
							|  |  |  |         last = next + "--" | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |         last_line_lfend = True | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         while 1: | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |             line = self.fp.readline(1<<16) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             if not line: | 
					
						
							|  |  |  |                 self.done = -1 | 
					
						
							|  |  |  |                 break | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |             if line[:2] == "--" and last_line_lfend: | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |                 strippedline = line.strip() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |                 if strippedline == next: | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  |                 if strippedline == last: | 
					
						
							|  |  |  |                     self.done = 1 | 
					
						
							|  |  |  |                     break | 
					
						
							| 
									
										
										
										
											2006-08-10 17:41:07 +00:00
										 |  |  |             last_line_lfend = line.endswith('\n') | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-08-12 18:18:13 +00:00
										 |  |  |     def make_file(self, binary=None): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """Overridable: return a readable & writable file.
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         The file will be used as follows: | 
					
						
							|  |  |  |         - data is written to it | 
					
						
							|  |  |  |         - seek(0) | 
					
						
							|  |  |  |         - data is read from it | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         The 'binary' argument is unused -- the file is always opened | 
					
						
							|  |  |  |         in binary mode. | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         This version opens a temporary file for reading and writing, | 
					
						
							|  |  |  |         and immediately deletes (unlinks) it.  The trick (on Unix!) is | 
					
						
							|  |  |  |         that the file can still be used, but it can't be opened by | 
					
						
							|  |  |  |         another process, and it will automatically be deleted when it | 
					
						
							|  |  |  |         is closed or when the current process terminates. | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         If you want a more permanent file, you derive a class which | 
					
						
							|  |  |  |         overrides this method.  If you want a visible temporary file | 
					
						
							|  |  |  |         that is nevertheless automatically deleted when the script | 
					
						
							|  |  |  |         terminates, try defining a __del__ method in a derived class | 
					
						
							|  |  |  |         which unlinks the temporary files you have created. | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         """
 | 
					
						
							|  |  |  |         import tempfile | 
					
						
							|  |  |  |         return tempfile.TemporaryFile("w+b") | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-07 06:33:07 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-09 04:04:35 +00:00
										 |  |  | # Backwards Compatibility Classes | 
					
						
							|  |  |  | # =============================== | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-08-25 21:47:56 +00:00
										 |  |  | class FormContentDict(UserDict.UserDict): | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |     """Form content as dictionary with a list of values per field.
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     form = FormContentDict() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     form[key] -> [value, value, ...] | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |     key in form -> Boolean | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     form.keys() -> [key, key, ...] | 
					
						
							|  |  |  |     form.values() -> [[val, val, ...], [val, val, ...], ...] | 
					
						
							|  |  |  |     form.items() ->  [(key, [val, val, ...]), (key, [val, val, ...]), ...] | 
					
						
							|  |  |  |     form.dict == {key: [val, val, ...], ...} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2006-09-30 10:58:01 +00:00
										 |  |  |     def __init__(self, environ=os.environ, keep_blank_values=0, strict_parsing=0): | 
					
						
							|  |  |  |         self.dict = self.data = parse(environ=environ, | 
					
						
							|  |  |  |                                       keep_blank_values=keep_blank_values, | 
					
						
							|  |  |  |                                       strict_parsing=strict_parsing) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         self.query_string = environ['QUERY_STRING'] | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SvFormContentDict(FormContentDict): | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |     """Form content as dictionary expecting a single value per field.
 | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |     If you only expect a single value for each field, then form[key] | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     will return that single value.  It will raise an IndexError if | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |     that expectation is not true.  If you expect a field to have | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     possible multiple values, than you can use form.getlist(key) to | 
					
						
							|  |  |  |     get all of the values.  values() and items() are a compromise: | 
					
						
							|  |  |  |     they return single strings where there is a single value, and | 
					
						
							|  |  |  |     lists of strings otherwise. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     def __getitem__(self, key): | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  |         if len(self.dict[key]) > 1: | 
					
						
							|  |  |  |             raise IndexError, 'expecting a single value' | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         return self.dict[key][0] | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     def getlist(self, key): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         return self.dict[key] | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     def values(self): | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |         result = [] | 
					
						
							|  |  |  |         for value in self.dict.values(): | 
					
						
							|  |  |  |             if len(value) == 1: | 
					
						
							|  |  |  |                 result.append(value[0]) | 
					
						
							|  |  |  |             else: result.append(value) | 
					
						
							|  |  |  |         return result | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     def items(self): | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |         result = [] | 
					
						
							|  |  |  |         for key, value in self.dict.items(): | 
					
						
							|  |  |  |             if len(value) == 1: | 
					
						
							|  |  |  |                 result.append((key, value[0])) | 
					
						
							|  |  |  |             else: result.append((key, value)) | 
					
						
							|  |  |  |         return result | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class InterpFormContentDict(SvFormContentDict): | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  |     """This class is present for backwards compatibility only.""" | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |     def __getitem__(self, key): | 
					
						
							|  |  |  |         v = SvFormContentDict.__getitem__(self, key) | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |         if v[0] in '0123456789+-.': | 
					
						
							|  |  |  |             try: return int(v) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             except ValueError: | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |                 try: return float(v) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |                 except ValueError: pass | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |         return v.strip() | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |     def values(self): | 
					
						
							|  |  |  |         result = [] | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         for key in self.keys(): | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |                 result.append(self[key]) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             except IndexError: | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |                 result.append(self.dict[key]) | 
					
						
							|  |  |  |         return result | 
					
						
							|  |  |  |     def items(self): | 
					
						
							|  |  |  |         result = [] | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         for key in self.keys(): | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |                 result.append((key, self[key])) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |             except IndexError: | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |                 result.append((key, self.dict[key])) | 
					
						
							|  |  |  |         return result | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FormContent(FormContentDict): | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  |     """This class is present for backwards compatibility only.""" | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  |     def values(self, key): | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if key in self.dict :return self.dict[key] | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         else: return None | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  |     def indexed_value(self, key, location): | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if key in self.dict: | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |             if len(self.dict[key]) > location: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |                 return self.dict[key][location] | 
					
						
							|  |  |  |             else: return None | 
					
						
							|  |  |  |         else: return None | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  |     def value(self, key): | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if key in self.dict: return self.dict[key][0] | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         else: return None | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  |     def length(self, key): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         return len(self.dict[key]) | 
					
						
							| 
									
										
										
										
											1996-03-09 03:16:04 +00:00
										 |  |  |     def stripped(self, key): | 
					
						
							| 
									
										
										
										
											2002-06-01 14:18:47 +00:00
										 |  |  |         if key in self.dict: return self.dict[key][0].strip() | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         else: return None | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     def pars(self): | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         return self.dict | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | # Test/debug code | 
					
						
							|  |  |  | # =============== | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  | def test(environ=os.environ): | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     """Robust test CGI script, usable as main program.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Write minimal HTTP headers and dump all information provided to | 
					
						
							|  |  |  |     the script in HTML form. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     print "Content-type: text/html" | 
					
						
							|  |  |  |     print | 
					
						
							|  |  |  |     sys.stderr = sys.stdout | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         form = FieldStorage()   # Replace with other classes to test those | 
					
						
							|  |  |  |         print_directory() | 
					
						
							|  |  |  |         print_arguments() | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |         print_form(form) | 
					
						
							|  |  |  |         print_environ(environ) | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         print_environ_usage() | 
					
						
							|  |  |  |         def f(): | 
					
						
							|  |  |  |             exec "testing print_exception() -- <I>italics?</I>" | 
					
						
							|  |  |  |         def g(f=f): | 
					
						
							|  |  |  |             f() | 
					
						
							|  |  |  |         print "<H3>What follows is a test, not an actual exception:</H3>" | 
					
						
							|  |  |  |         g() | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     except: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         print_exception() | 
					
						
							| 
									
										
										
										
											1996-08-20 20:22:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-09-16 21:16:01 +00:00
										 |  |  |     print "<H1>Second try with a small maxlen...</H1>" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-05-13 19:03:23 +00:00
										 |  |  |     global maxlen | 
					
						
							|  |  |  |     maxlen = 50 | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         form = FieldStorage()   # Replace with other classes to test those | 
					
						
							|  |  |  |         print_directory() | 
					
						
							|  |  |  |         print_arguments() | 
					
						
							| 
									
										
										
										
											2000-09-19 04:11:46 +00:00
										 |  |  |         print_form(form) | 
					
						
							|  |  |  |         print_environ(environ) | 
					
						
							| 
									
										
										
										
											1997-05-13 19:03:23 +00:00
										 |  |  |     except: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         print_exception() | 
					
						
							| 
									
										
										
										
											1997-05-13 19:03:23 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-08-20 20:22:39 +00:00
										 |  |  | def print_exception(type=None, value=None, tb=None, limit=None): | 
					
						
							|  |  |  |     if type is None: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         type, value, tb = sys.exc_info() | 
					
						
							| 
									
										
										
										
											1996-08-20 20:22:39 +00:00
										 |  |  |     import traceback | 
					
						
							|  |  |  |     print | 
					
						
							| 
									
										
										
										
											2000-12-27 19:12:58 +00:00
										 |  |  |     print "<H3>Traceback (most recent call last):</H3>" | 
					
						
							| 
									
										
										
										
											1996-08-20 20:22:39 +00:00
										 |  |  |     list = traceback.format_tb(tb, limit) + \ | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |            traceback.format_exception_only(type, value) | 
					
						
							| 
									
										
										
										
											1996-08-20 20:22:39 +00:00
										 |  |  |     print "<PRE>%s<B>%s</B></PRE>" % ( | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |         escape("".join(list[:-1])), | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         escape(list[-1]), | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											1997-09-29 23:22:12 +00:00
										 |  |  |     del tb | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-07-23 03:46:24 +00:00
										 |  |  | def print_environ(environ=os.environ): | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     """Dump the shell environment as HTML.""" | 
					
						
							|  |  |  |     keys = environ.keys() | 
					
						
							|  |  |  |     keys.sort() | 
					
						
							|  |  |  |     print | 
					
						
							| 
									
										
										
										
											1996-05-28 22:57:20 +00:00
										 |  |  |     print "<H3>Shell Environment:</H3>" | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     print "<DL>" | 
					
						
							|  |  |  |     for key in keys: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         print "<DT>", escape(key), "<DD>", escape(environ[key]) | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  |     print "</DL>" | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     print | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def print_form(form): | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     """Dump the contents of a form as HTML.""" | 
					
						
							|  |  |  |     keys = form.keys() | 
					
						
							|  |  |  |     keys.sort() | 
					
						
							|  |  |  |     print | 
					
						
							| 
									
										
										
										
											1996-05-28 22:57:20 +00:00
										 |  |  |     print "<H3>Form Contents:</H3>" | 
					
						
							| 
									
										
										
										
											2000-09-16 21:16:01 +00:00
										 |  |  |     if not keys: | 
					
						
							|  |  |  |         print "<P>No form fields." | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     print "<DL>" | 
					
						
							|  |  |  |     for key in keys: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         print "<DT>" + escape(key) + ":", | 
					
						
							|  |  |  |         value = form[key] | 
					
						
							| 
									
										
										
										
											2004-02-12 17:35:32 +00:00
										 |  |  |         print "<i>" + escape(repr(type(value))) + "</i>" | 
					
						
							|  |  |  |         print "<DD>" + escape(repr(value)) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     print "</DL>" | 
					
						
							|  |  |  |     print | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def print_directory(): | 
					
						
							|  |  |  |     """Dump the current directory as HTML.""" | 
					
						
							|  |  |  |     print | 
					
						
							|  |  |  |     print "<H3>Current Working Directory:</H3>" | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         pwd = os.getcwd() | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     except os.error, msg: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         print "os.error:", escape(str(msg)) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											1998-03-26 21:13:24 +00:00
										 |  |  |         print escape(pwd) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     print | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-14 21:30:28 +00:00
										 |  |  | def print_arguments(): | 
					
						
							|  |  |  |     print | 
					
						
							| 
									
										
										
										
											1996-05-28 22:57:20 +00:00
										 |  |  |     print "<H3>Command Line Arguments:</H3>" | 
					
						
							| 
									
										
										
										
											1996-03-14 21:30:28 +00:00
										 |  |  |     print | 
					
						
							|  |  |  |     print sys.argv | 
					
						
							|  |  |  |     print | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | def print_environ_usage(): | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     """Dump a list of environment variables used by CGI as HTML.""" | 
					
						
							|  |  |  |     print """
 | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | <H3>These environment variables could have been set:</H3> | 
					
						
							|  |  |  | <UL> | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | <LI>AUTH_TYPE | 
					
						
							|  |  |  | <LI>CONTENT_LENGTH | 
					
						
							|  |  |  | <LI>CONTENT_TYPE | 
					
						
							|  |  |  | <LI>DATE_GMT | 
					
						
							|  |  |  | <LI>DATE_LOCAL | 
					
						
							|  |  |  | <LI>DOCUMENT_NAME | 
					
						
							|  |  |  | <LI>DOCUMENT_ROOT | 
					
						
							|  |  |  | <LI>DOCUMENT_URI | 
					
						
							|  |  |  | <LI>GATEWAY_INTERFACE | 
					
						
							|  |  |  | <LI>LAST_MODIFIED | 
					
						
							|  |  |  | <LI>PATH | 
					
						
							|  |  |  | <LI>PATH_INFO | 
					
						
							|  |  |  | <LI>PATH_TRANSLATED | 
					
						
							|  |  |  | <LI>QUERY_STRING | 
					
						
							|  |  |  | <LI>REMOTE_ADDR | 
					
						
							|  |  |  | <LI>REMOTE_HOST | 
					
						
							|  |  |  | <LI>REMOTE_IDENT | 
					
						
							|  |  |  | <LI>REMOTE_USER | 
					
						
							|  |  |  | <LI>REQUEST_METHOD | 
					
						
							|  |  |  | <LI>SCRIPT_NAME | 
					
						
							|  |  |  | <LI>SERVER_NAME | 
					
						
							|  |  |  | <LI>SERVER_PORT | 
					
						
							|  |  |  | <LI>SERVER_PROTOCOL | 
					
						
							|  |  |  | <LI>SERVER_ROOT | 
					
						
							|  |  |  | <LI>SERVER_SOFTWARE | 
					
						
							|  |  |  | </UL> | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  | In addition, HTTP headers sent by the server may be passed in the | 
					
						
							|  |  |  | environment as well.  Here are some common variable names: | 
					
						
							|  |  |  | <UL> | 
					
						
							|  |  |  | <LI>HTTP_ACCEPT | 
					
						
							|  |  |  | <LI>HTTP_CONNECTION | 
					
						
							|  |  |  | <LI>HTTP_HOST | 
					
						
							|  |  |  | <LI>HTTP_PRAGMA | 
					
						
							|  |  |  | <LI>HTTP_REFERER | 
					
						
							|  |  |  | <LI>HTTP_USER_AGENT | 
					
						
							|  |  |  | </UL> | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Utilities | 
					
						
							|  |  |  | # ========= | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1997-07-19 20:11:53 +00:00
										 |  |  | def escape(s, quote=None): | 
					
						
							| 
									
										
										
										
											2005-08-02 02:50:25 +00:00
										 |  |  |     '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
 | 
					
						
							|  |  |  |     If the optional flag quote is true, the quotation mark character (") | 
					
						
							|  |  |  |     is also translated.'''
 | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |     s = s.replace("&", "&") # Must be done first! | 
					
						
							|  |  |  |     s = s.replace("<", "<") | 
					
						
							|  |  |  |     s = s.replace(">", ">") | 
					
						
							| 
									
										
										
										
											1997-07-19 20:11:53 +00:00
										 |  |  |     if quote: | 
					
						
							| 
									
										
										
										
											2001-02-09 09:59:10 +00:00
										 |  |  |         s = s.replace('"', """) | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     return s | 
					
						
							| 
									
										
										
										
											1995-01-12 12:29:47 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-07-25 21:00:19 +00:00
										 |  |  | def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"): | 
					
						
							|  |  |  |     import re | 
					
						
							|  |  |  |     return re.match(_vb_pattern, s) | 
					
						
							| 
									
										
										
										
											1996-03-06 07:20:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Invoke mainline | 
					
						
							|  |  |  | # =============== | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Call test() when this file is run as a script (not imported as a module) | 
					
						
							| 
									
										
										
										
											2001-01-14 23:36:06 +00:00
										 |  |  | if __name__ == '__main__': | 
					
						
							| 
									
										
										
										
											1996-03-07 18:00:44 +00:00
										 |  |  |     test() |