blob: 9e16a1df6237d20f567990c6f70793538503b3b6 [file] [log] [blame]
Guido van Rossum51914632000-10-03 13:51:09 +00001#! /usr/local/bin/python
Guido van Rossum1c9daa81995-09-18 21:52:37 +00002
Guido van Rossum467d7232001-02-13 13:13:33 +00003# NOTE: the above "/usr/local/bin/python" is NOT a mistake. It is
4# intentionally NOT "/usr/bin/env python". On many systems
5# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI
6# scripts, and /usr/local/bin is the default directory where Python is
7# installed, so /usr/bin/env would be unable to find python. Granted,
8# binary installations by Linux vendors often install Python in
9# /usr/bin. So let those vendors patch cgi.py to match their choice
10# of installation.
11
Guido van Rossum72755611996-03-06 07:20:06 +000012"""Support module for CGI (Common Gateway Interface) scripts.
Guido van Rossum1c9daa81995-09-18 21:52:37 +000013
Guido van Rossum7aee3841996-03-07 18:00:44 +000014This module defines a number of utilities for use by CGI scripts
15written in Python.
Guido van Rossum72755611996-03-06 07:20:06 +000016"""
17
Guido van Rossum98d9fd32000-02-28 15:12:25 +000018# History
19# -------
Tim Peters88869f92001-01-14 23:36:06 +000020#
Guido van Rossum98d9fd32000-02-28 15:12:25 +000021# Michael McLay started this module. Steve Majewski changed the
22# interface to SvFormContentDict and FormContentDict. The multipart
23# parsing was inspired by code submitted by Andreas Paepcke. Guido van
24# Rossum rewrote, reformatted and documented the module and is currently
25# responsible for its maintenance.
Tim Peters88869f92001-01-14 23:36:06 +000026#
Guido van Rossum98d9fd32000-02-28 15:12:25 +000027
Guido van Rossum52b8c292001-06-29 13:06:06 +000028__version__ = "2.6"
Guido van Rossum0147db01996-03-09 03:16:04 +000029
Guido van Rossum72755611996-03-06 07:20:06 +000030
31# Imports
32# =======
33
Raymond Hettingerf871d832004-12-31 21:59:02 +000034from operator import attrgetter
Barry Warsaw596097e2008-06-12 02:38:51 +000035from io import StringIO
Guido van Rossum72755611996-03-06 07:20:06 +000036import sys
37import os
Jeremy Hylton1afc1692008-06-18 20:49:58 +000038import urllib.parse
Barry Warsaw596097e2008-06-12 02:38:51 +000039import email.parser
Facundo Batistac469d4c2008-09-03 22:49:01 +000040from warnings import warn
Guido van Rossum72755611996-03-06 07:20:06 +000041
Georg Brandl49d1b4f2008-05-11 21:42:51 +000042__all__ = ["MiniFieldStorage", "FieldStorage",
Guido van Rossuma8423a92001-03-19 13:40:44 +000043 "parse", "parse_qs", "parse_qsl", "parse_multipart",
44 "parse_header", "print_exception", "print_environ",
45 "print_form", "print_directory", "print_arguments",
46 "print_environ_usage", "escape"]
Guido van Rossumc204c701996-09-05 19:07:11 +000047
48# Logging support
49# ===============
50
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000051logfile = "" # Filename to log to, if not empty
52logfp = None # File object to log to, if not None
Guido van Rossumc204c701996-09-05 19:07:11 +000053
54def initlog(*allargs):
55 """Write a log message, if there is a log file.
56
57 Even though this function is called initlog(), you should always
58 use log(); log is a variable that is set either to initlog
59 (initially), to dolog (once the log file has been opened), or to
60 nolog (when logging is disabled).
61
62 The first argument is a format string; the remaining arguments (if
63 any) are arguments to the % operator, so e.g.
64 log("%s: %s", "a", "b")
65 will write "a: b" to the log file, followed by a newline.
66
67 If the global logfp is not None, it should be a file object to
68 which log data is written.
69
70 If the global logfp is None, the global logfile may be a string
71 giving a filename to open, in append mode. This file should be
72 world writable!!! If the file can't be opened, logging is
73 silently disabled (since there is no safe place where we could
74 send an error message).
75
76 """
77 global logfp, log
78 if logfile and not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000079 try:
80 logfp = open(logfile, "a")
81 except IOError:
82 pass
Guido van Rossumc204c701996-09-05 19:07:11 +000083 if not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000084 log = nolog
Guido van Rossumc204c701996-09-05 19:07:11 +000085 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000086 log = dolog
Guido van Rossum68468eb2003-02-27 20:14:51 +000087 log(*allargs)
Guido van Rossumc204c701996-09-05 19:07:11 +000088
89def dolog(fmt, *args):
90 """Write a log message to the log file. See initlog() for docs."""
91 logfp.write(fmt%args + "\n")
92
93def nolog(*allargs):
94 """Dummy function, assigned to log when logging is disabled."""
95 pass
96
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000097log = initlog # The current logging function
Guido van Rossumc204c701996-09-05 19:07:11 +000098
99
Guido van Rossum72755611996-03-06 07:20:06 +0000100# Parsing functions
101# =================
102
Guido van Rossumad164711997-05-13 19:03:23 +0000103# Maximum input we will accept when REQUEST_METHOD is POST
104# 0 ==> unlimited input
105maxlen = 0
106
Guido van Rossume08c04c1996-11-11 19:29:11 +0000107def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum773ab271996-07-23 03:46:24 +0000108 """Parse a query in the environment or from a file (default stdin)
109
110 Arguments, all optional:
111
112 fp : file pointer; default: sys.stdin
113
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000114 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000115
116 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000117 URL encoded forms should be treated as blank strings.
118 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000119 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000120 blank values are to be ignored and treated as if they were
121 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000122
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000123 strict_parsing: flag indicating what to do with parsing errors.
124 If false (the default), errors are silently ignored.
125 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000126 """
Raymond Hettingera1449002002-05-31 23:54:44 +0000127 if fp is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000128 fp = sys.stdin
Raymond Hettinger54f02222002-06-01 14:18:47 +0000129 if not 'REQUEST_METHOD' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000130 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
Guido van Rossum7aee3841996-03-07 18:00:44 +0000131 if environ['REQUEST_METHOD'] == 'POST':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000132 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
133 if ctype == 'multipart/form-data':
134 return parse_multipart(fp, pdict)
135 elif ctype == 'application/x-www-form-urlencoded':
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000136 clength = int(environ['CONTENT_LENGTH'])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000137 if maxlen and clength > maxlen:
Collin Winterce36ad82007-08-30 01:19:48 +0000138 raise ValueError('Maximum content length exceeded')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000139 qs = fp.read(clength)
140 else:
141 qs = '' # Unknown content-type
Raymond Hettinger54f02222002-06-01 14:18:47 +0000142 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000143 if qs: qs = qs + '&'
144 qs = qs + environ['QUERY_STRING']
Tim Peters88869f92001-01-14 23:36:06 +0000145 elif sys.argv[1:]:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000146 if qs: qs = qs + '&'
147 qs = qs + sys.argv[1]
148 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Raymond Hettinger54f02222002-06-01 14:18:47 +0000149 elif 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000150 qs = environ['QUERY_STRING']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000151 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000152 if sys.argv[1:]:
153 qs = sys.argv[1]
154 else:
155 qs = ""
156 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Facundo Batistac469d4c2008-09-03 22:49:01 +0000157 return urllib.parse.parse_qs(qs, keep_blank_values, strict_parsing)
Guido van Rossume7808771995-08-07 20:12:09 +0000158
159
Facundo Batistac469d4c2008-09-03 22:49:01 +0000160# parse query string function called from urlparse,
161# this is done in order to maintain backward compatiblity.
162
Guido van Rossume08c04c1996-11-11 19:29:11 +0000163def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
Facundo Batistac469d4c2008-09-03 22:49:01 +0000164 """Parse a query given as a string argument."""
165 warn("cgi.parse_qs is deprecated, use urllib.parse.parse_qs instead",
Philip Jenveya394f2d2009-05-08 03:57:12 +0000166 DeprecationWarning, 2)
Facundo Batistac469d4c2008-09-03 22:49:01 +0000167 return urllib.parse.parse_qs(qs, keep_blank_values, strict_parsing)
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000168
169def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
Facundo Batistac469d4c2008-09-03 22:49:01 +0000170 """Parse a query given as a string argument."""
Facundo Batistaa27244b2008-09-09 02:43:19 +0000171 warn("cgi.parse_qsl is deprecated, use urllib.parse.parse_qsl instead",
Philip Jenveya394f2d2009-05-08 03:57:12 +0000172 DeprecationWarning, 2)
Facundo Batistac469d4c2008-09-03 22:49:01 +0000173 return urllib.parse.parse_qsl(qs, keep_blank_values, strict_parsing)
Guido van Rossum9a22de11995-01-12 12:29:47 +0000174
Guido van Rossum0147db01996-03-09 03:16:04 +0000175def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000176 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000177
Guido van Rossum7aee3841996-03-07 18:00:44 +0000178 Arguments:
179 fp : input file
Johannes Gijsbersc7fc10a2005-01-08 13:56:36 +0000180 pdict: dictionary containing other parameters of content-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000181
Tim Peters88869f92001-01-14 23:36:06 +0000182 Returns a dictionary just like parse_qs(): keys are the field names, each
183 value is a list of values for that field. This is easy to use but not
184 much good if you are expecting megabytes to be uploaded -- in that case,
185 use the FieldStorage class instead which is much more flexible. Note
186 that content-type is the raw, unparsed contents of the content-type
Guido van Rossum0147db01996-03-09 03:16:04 +0000187 header.
Tim Peters88869f92001-01-14 23:36:06 +0000188
189 XXX This does not parse nested multipart parts -- use FieldStorage for
Guido van Rossum0147db01996-03-09 03:16:04 +0000190 that.
Tim Peters88869f92001-01-14 23:36:06 +0000191
192 XXX This should really be subsumed by FieldStorage altogether -- no
Guido van Rossum0147db01996-03-09 03:16:04 +0000193 point in having two implementations of the same parsing algorithm.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000194 Also, FieldStorage protects itself better against certain DoS attacks
195 by limiting the size of the data read in one chunk. The API here
196 does not support that kind of protection. This also affects parse()
197 since it can call parse_multipart().
Guido van Rossum72755611996-03-06 07:20:06 +0000198
Guido van Rossum7aee3841996-03-07 18:00:44 +0000199 """
Barry Warsaw820c1202008-06-12 04:06:45 +0000200 import http.client
201
Guido van Rossum2e441f72001-07-25 21:00:19 +0000202 boundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000203 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000204 boundary = pdict['boundary']
Guido van Rossum2e441f72001-07-25 21:00:19 +0000205 if not valid_boundary(boundary):
Collin Winterce36ad82007-08-30 01:19:48 +0000206 raise ValueError('Invalid boundary in multipart form: %r'
Walter Dörwald70a6b492004-02-12 17:35:32 +0000207 % (boundary,))
Tim Petersab9ba272001-08-09 21:40:30 +0000208
Guido van Rossum7aee3841996-03-07 18:00:44 +0000209 nextpart = "--" + boundary
210 lastpart = "--" + boundary + "--"
211 partdict = {}
212 terminator = ""
213
214 while terminator != lastpart:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000215 bytes = -1
216 data = None
217 if terminator:
218 # At start of next part. Read headers first.
Barry Warsaw820c1202008-06-12 04:06:45 +0000219 headers = http.client.parse_headers(fp)
220 clength = headers.get('content-length')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000221 if clength:
222 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000223 bytes = int(clength)
224 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000225 pass
226 if bytes > 0:
227 if maxlen and bytes > maxlen:
Collin Winterce36ad82007-08-30 01:19:48 +0000228 raise ValueError('Maximum content length exceeded')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000229 data = fp.read(bytes)
230 else:
231 data = ""
232 # Read lines until end of part.
233 lines = []
234 while 1:
235 line = fp.readline()
236 if not line:
237 terminator = lastpart # End outer loop
238 break
239 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000240 terminator = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000241 if terminator in (nextpart, lastpart):
242 break
243 lines.append(line)
244 # Done with part.
245 if data is None:
246 continue
247 if bytes < 0:
248 if lines:
249 # Strip final line terminator
250 line = lines[-1]
251 if line[-2:] == "\r\n":
252 line = line[:-2]
253 elif line[-1:] == "\n":
254 line = line[:-1]
255 lines[-1] = line
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000256 data = "".join(lines)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000257 line = headers['content-disposition']
258 if not line:
259 continue
260 key, params = parse_header(line)
261 if key != 'form-data':
262 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000263 if 'name' in params:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000264 name = params['name']
265 else:
266 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000267 if name in partdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000268 partdict[name].append(data)
269 else:
270 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000271
Guido van Rossum7aee3841996-03-07 18:00:44 +0000272 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000273
274
Fred Drake9a0a65b2008-12-04 19:24:50 +0000275def _parseparam(s):
276 while s[:1] == ';':
277 s = s[1:]
278 end = s.find(';')
279 while end > 0 and s.count('"', 0, end) % 2:
280 end = s.find(';', end + 1)
281 if end < 0:
282 end = len(s)
283 f = s[:end]
284 yield f.strip()
285 s = s[end:]
286
Guido van Rossum72755611996-03-06 07:20:06 +0000287def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000288 """Parse a Content-type like header.
289
290 Return the main content-type and a dictionary of options.
291
292 """
Fred Drake9a0a65b2008-12-04 19:24:50 +0000293 parts = _parseparam(';' + line)
294 key = parts.__next__()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000295 pdict = {}
Fred Drake9a0a65b2008-12-04 19:24:50 +0000296 for p in parts:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000297 i = p.find('=')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000298 if i >= 0:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000299 name = p[:i].strip().lower()
300 value = p[i+1:].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000301 if len(value) >= 2 and value[0] == value[-1] == '"':
302 value = value[1:-1]
Johannes Gijsbers9e15dd62004-08-14 15:39:34 +0000303 value = value.replace('\\\\', '\\').replace('\\"', '"')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000304 pdict[name] = value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000305 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000306
307
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000308# Classes for field storage
309# =========================
310
311class MiniFieldStorage:
312
Guido van Rossum0147db01996-03-09 03:16:04 +0000313 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000314
Guido van Rossum7aee3841996-03-07 18:00:44 +0000315 # Dummy attributes
316 filename = None
317 list = None
318 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000319 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000320 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000321 disposition = None
322 disposition_options = {}
323 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000324
Guido van Rossum7aee3841996-03-07 18:00:44 +0000325 def __init__(self, name, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000326 """Constructor from field name and value."""
327 self.name = name
328 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000329 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000330
331 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000332 """Return printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000333 return "MiniFieldStorage(%r, %r)" % (self.name, self.value)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000334
335
336class FieldStorage:
337
Guido van Rossum7aee3841996-03-07 18:00:44 +0000338 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000339
Guido van Rossum7aee3841996-03-07 18:00:44 +0000340 This class provides naming, typing, files stored on disk, and
341 more. At the top level, it is accessible like a dictionary, whose
342 keys are the field names. (Note: None can occur as a field name.)
343 The items are either a Python list (if there's multiple values) or
344 another FieldStorage or MiniFieldStorage object. If it's a single
345 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000346
Guido van Rossum7aee3841996-03-07 18:00:44 +0000347 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000348
Guido van Rossum7aee3841996-03-07 18:00:44 +0000349 filename: the filename, if specified; otherwise None; this is the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000350 client side filename, *not* the file name on which it is
351 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000352
Guido van Rossum7aee3841996-03-07 18:00:44 +0000353 value: the value as a *string*; for file uploads, this
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000354 transparently reads the file every time you request the value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000355
356 file: the file(-like) object from which you can read the data;
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000357 None if the data is stored a simple string
Guido van Rossum7aee3841996-03-07 18:00:44 +0000358
359 type: the content-type, or None if not specified
360
361 type_options: dictionary of options specified on the content-type
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000362 line
Guido van Rossum7aee3841996-03-07 18:00:44 +0000363
364 disposition: content-disposition, or None if not specified
365
366 disposition_options: dictionary of corresponding options
367
Barry Warsaw596097e2008-06-12 02:38:51 +0000368 headers: a dictionary(-like) object (sometimes email.message.Message or a
Armin Rigo3a703b62005-09-19 09:11:04 +0000369 subclass thereof) containing *all* headers
Guido van Rossum7aee3841996-03-07 18:00:44 +0000370
371 The class is subclassable, mostly for the purpose of overriding
372 the make_file() method, which is called internally to come up with
373 a file open for reading and writing. This makes it possible to
374 override the default choice of storing all files in a temporary
375 directory and unlinking them as soon as they have been opened.
376
377 """
378
Guido van Rossum773ab271996-07-23 03:46:24 +0000379 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000380 environ=os.environ, keep_blank_values=0, strict_parsing=0):
381 """Constructor. Read multipart/* until last part.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000382
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000383 Arguments, all optional:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000384
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000385 fp : file pointer; default: sys.stdin
Guido van Rossumb1b4f941998-05-08 19:55:51 +0000386 (not used when the request method is GET)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000387
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000388 headers : header dictionary-like object; default:
389 taken from environ as per CGI spec
Guido van Rossum7aee3841996-03-07 18:00:44 +0000390
Guido van Rossum773ab271996-07-23 03:46:24 +0000391 outerboundary : terminating multipart boundary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000392 (for internal use only)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000393
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000394 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000395
396 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000397 URL encoded forms should be treated as blank strings.
398 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000399 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000400 blank values are to be ignored and treated as if they were
401 not included.
Guido van Rossum773ab271996-07-23 03:46:24 +0000402
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000403 strict_parsing: flag indicating what to do with parsing errors.
404 If false (the default), errors are silently ignored.
405 If true, errors raise a ValueError exception.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000406
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000407 """
408 method = 'GET'
409 self.keep_blank_values = keep_blank_values
410 self.strict_parsing = strict_parsing
Raymond Hettinger54f02222002-06-01 14:18:47 +0000411 if 'REQUEST_METHOD' in environ:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000412 method = environ['REQUEST_METHOD'].upper()
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000413 self.qs_on_post = None
Guido van Rossum01852831998-06-25 02:40:17 +0000414 if method == 'GET' or method == 'HEAD':
Raymond Hettinger54f02222002-06-01 14:18:47 +0000415 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000416 qs = environ['QUERY_STRING']
417 elif sys.argv[1:]:
418 qs = sys.argv[1]
419 else:
420 qs = ""
421 fp = StringIO(qs)
422 if headers is None:
423 headers = {'content-type':
424 "application/x-www-form-urlencoded"}
425 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000426 headers = {}
427 if method == 'POST':
428 # Set default content-type for POST to what's traditional
429 headers['content-type'] = "application/x-www-form-urlencoded"
Raymond Hettinger54f02222002-06-01 14:18:47 +0000430 if 'CONTENT_TYPE' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000431 headers['content-type'] = environ['CONTENT_TYPE']
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000432 if 'QUERY_STRING' in environ:
433 self.qs_on_post = environ['QUERY_STRING']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000434 if 'CONTENT_LENGTH' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000435 headers['content-length'] = environ['CONTENT_LENGTH']
436 self.fp = fp or sys.stdin
437 self.headers = headers
438 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000439
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000440 # Process content-disposition header
441 cdisp, pdict = "", {}
Raymond Hettinger54f02222002-06-01 14:18:47 +0000442 if 'content-disposition' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000443 cdisp, pdict = parse_header(self.headers['content-disposition'])
444 self.disposition = cdisp
445 self.disposition_options = pdict
446 self.name = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000447 if 'name' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000448 self.name = pdict['name']
449 self.filename = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000450 if 'filename' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000451 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000452
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000453 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000454 #
455 # Honor any existing content-type header. But if there is no
456 # content-type header, use some sensible defaults. Assume
457 # outerboundary is "" at the outer level, but something non-false
458 # inside a multi-part. The default for an inner part is text/plain,
459 # but for an outer part it should be urlencoded. This should catch
460 # bogus clients which erroneously forget to include a content-type
461 # header.
462 #
463 # See below for what we do if there does exist a content-type header,
464 # but it happens to be something we don't understand.
Raymond Hettinger54f02222002-06-01 14:18:47 +0000465 if 'content-type' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000466 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000467 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000468 ctype, pdict = "text/plain", {}
469 else:
470 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000471 self.type = ctype
472 self.type_options = pdict
473 self.innerboundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000474 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000475 self.innerboundary = pdict['boundary']
476 clen = -1
Raymond Hettinger54f02222002-06-01 14:18:47 +0000477 if 'content-length' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000478 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000479 clen = int(self.headers['content-length'])
Skip Montanarodb5d1442002-03-23 05:50:17 +0000480 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000481 pass
482 if maxlen and clen > maxlen:
Collin Winterce36ad82007-08-30 01:19:48 +0000483 raise ValueError('Maximum content length exceeded')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000484 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000485
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000486 self.list = self.file = None
487 self.done = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000488 if ctype == 'application/x-www-form-urlencoded':
489 self.read_urlencoded()
490 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000491 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000492 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000493 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000494
495 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000496 """Return a printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000497 return "FieldStorage(%r, %r, %r)" % (
498 self.name, self.filename, self.value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000499
Guido van Rossum4061cbe2002-09-11 18:20:34 +0000500 def __iter__(self):
501 return iter(self.keys())
502
Guido van Rossum7aee3841996-03-07 18:00:44 +0000503 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000504 if name != 'value':
Collin Winterce36ad82007-08-30 01:19:48 +0000505 raise AttributeError(name)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000506 if self.file:
507 self.file.seek(0)
508 value = self.file.read()
509 self.file.seek(0)
510 elif self.list is not None:
511 value = self.list
512 else:
513 value = None
514 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000515
516 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000517 """Dictionary style indexing."""
518 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000519 raise TypeError("not indexable")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000520 found = []
521 for item in self.list:
522 if item.name == key: found.append(item)
523 if not found:
Collin Winterce36ad82007-08-30 01:19:48 +0000524 raise KeyError(key)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000525 if len(found) == 1:
526 return found[0]
527 else:
528 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000529
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000530 def getvalue(self, key, default=None):
531 """Dictionary style get() method, including 'value' lookup."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000532 if key in self:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000533 value = self[key]
534 if type(value) is type([]):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000535 return [x.value for x in value]
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000536 else:
537 return value.value
538 else:
539 return default
540
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000541 def getfirst(self, key, default=None):
542 """ Return the first value received."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000543 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000544 value = self[key]
545 if type(value) is type([]):
546 return value[0].value
547 else:
548 return value.value
549 else:
550 return default
551
552 def getlist(self, key):
553 """ Return list of received values."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000554 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000555 value = self[key]
556 if type(value) is type([]):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000557 return [x.value for x in value]
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000558 else:
559 return [value.value]
560 else:
561 return []
562
Guido van Rossum7aee3841996-03-07 18:00:44 +0000563 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000564 """Dictionary style keys() method."""
565 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000566 raise TypeError("not indexable")
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000567 return list(set(item.name for item in self.list))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000568
Raymond Hettinger54f02222002-06-01 14:18:47 +0000569 def __contains__(self, key):
570 """Dictionary style __contains__ method."""
571 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000572 raise TypeError("not indexable")
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000573 return any(item.name == key for item in self.list)
Raymond Hettinger54f02222002-06-01 14:18:47 +0000574
Guido van Rossum88b85d41997-01-11 19:21:33 +0000575 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000576 """Dictionary style len(x) support."""
577 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000578
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000579 def __nonzero__(self):
580 return bool(self.list)
581
Guido van Rossum7aee3841996-03-07 18:00:44 +0000582 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000583 """Internal: read data in query string format."""
584 qs = self.fp.read(self.length)
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000585 if self.qs_on_post:
586 qs += '&' + self.qs_on_post
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000587 self.list = list = []
Facundo Batistac469d4c2008-09-03 22:49:01 +0000588 for key, value in urllib.parse.parse_qsl(qs, self.keep_blank_values,
589 self.strict_parsing):
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000590 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000591 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000592
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000593 FieldStorageClass = None
594
Guido van Rossumf5745001998-10-20 14:43:02 +0000595 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000596 """Internal: read a part that is itself multipart."""
Guido van Rossum2e441f72001-07-25 21:00:19 +0000597 ib = self.innerboundary
598 if not valid_boundary(ib):
Collin Winterce36ad82007-08-30 01:19:48 +0000599 raise ValueError('Invalid boundary in multipart form: %r' % (ib,))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000600 self.list = []
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000601 if self.qs_on_post:
Facundo Batistac469d4c2008-09-03 22:49:01 +0000602 for key, value in urllib.parse.parse_qsl(self.qs_on_post,
603 self.keep_blank_values, self.strict_parsing):
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000604 self.list.append(MiniFieldStorage(key, value))
605 FieldStorageClass = None
606
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000607 klass = self.FieldStorageClass or self.__class__
Barry Warsaw596097e2008-06-12 02:38:51 +0000608 parser = email.parser.FeedParser()
609 # Create bogus content-type header for proper multipart parsing
610 parser.feed('Content-Type: %s; boundary=%s\r\n\r\n' % (self.type, ib))
611 parser.feed(self.fp.read())
612 full_msg = parser.close()
613 # Get subparts
614 msgs = full_msg.get_payload()
615 for msg in msgs:
616 fp = StringIO(msg.get_payload())
617 part = klass(fp, msg, ib, environ, keep_blank_values,
618 strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000619 self.list.append(part)
620 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000621
622 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000623 """Internal: read an atomic part."""
624 if self.length >= 0:
625 self.read_binary()
626 self.skip_lines()
627 else:
628 self.read_lines()
629 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000630
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000631 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000632
633 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000634 """Internal: read binary data."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000635 self.file = self.make_file()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000636 todo = self.length
637 if todo >= 0:
638 while todo > 0:
639 data = self.fp.read(min(todo, self.bufsize))
640 if not data:
641 self.done = -1
642 break
643 self.file.write(data)
644 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000645
646 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000647 """Internal: read lines until EOF or outerboundary."""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000648 self.file = self.__file = StringIO()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000649 if self.outerboundary:
650 self.read_lines_to_outerboundary()
651 else:
652 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000653
Guido van Rossum52b8c292001-06-29 13:06:06 +0000654 def __write(self, line):
655 if self.__file is not None:
656 if self.__file.tell() + len(line) > 1000:
Guido van Rossuma1a68522007-08-28 03:11:34 +0000657 self.file = self.make_file()
658 data = self.__file.getvalue()
659 self.file.write(data)
Guido van Rossum52b8c292001-06-29 13:06:06 +0000660 self.__file = None
661 self.file.write(line)
662
Guido van Rossum7aee3841996-03-07 18:00:44 +0000663 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000664 """Internal: read lines until EOF."""
665 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000666 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000667 if not line:
668 self.done = -1
669 break
Guido van Rossum52b8c292001-06-29 13:06:06 +0000670 self.__write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000671
672 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000673 """Internal: read lines until outerboundary."""
674 next = "--" + self.outerboundary
675 last = next + "--"
676 delim = ""
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000677 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000678 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000679 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000680 if not line:
681 self.done = -1
682 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000683 if line[:2] == "--" and last_line_lfend:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000684 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000685 if strippedline == next:
686 break
687 if strippedline == last:
688 self.done = 1
689 break
690 odelim = delim
691 if line[-2:] == "\r\n":
692 delim = "\r\n"
693 line = line[:-2]
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000694 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000695 elif line[-1] == "\n":
696 delim = "\n"
697 line = line[:-1]
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000698 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000699 else:
700 delim = ""
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000701 last_line_lfend = False
Guido van Rossum52b8c292001-06-29 13:06:06 +0000702 self.__write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000703
704 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000705 """Internal: skip lines until outer boundary if defined."""
706 if not self.outerboundary or self.done:
707 return
708 next = "--" + self.outerboundary
709 last = next + "--"
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000710 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000711 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000712 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000713 if not line:
714 self.done = -1
715 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000716 if line[:2] == "--" and last_line_lfend:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000717 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000718 if strippedline == next:
719 break
720 if strippedline == last:
721 self.done = 1
722 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000723 last_line_lfend = line.endswith('\n')
Guido van Rossum7aee3841996-03-07 18:00:44 +0000724
Guido van Rossuma1a68522007-08-28 03:11:34 +0000725 def make_file(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000726 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000727
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000728 The file will be used as follows:
729 - data is written to it
730 - seek(0)
731 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +0000732
Guido van Rossuma1a68522007-08-28 03:11:34 +0000733 The file is always opened in text mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000734
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000735 This version opens a temporary file for reading and writing,
736 and immediately deletes (unlinks) it. The trick (on Unix!) is
737 that the file can still be used, but it can't be opened by
738 another process, and it will automatically be deleted when it
739 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000740
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000741 If you want a more permanent file, you derive a class which
742 overrides this method. If you want a visible temporary file
743 that is nevertheless automatically deleted when the script
744 terminates, try defining a __del__ method in a derived class
745 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000746
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000747 """
748 import tempfile
Guido van Rossum92bab812007-08-28 03:32:38 +0000749 return tempfile.TemporaryFile("w+", encoding="utf-8", newline="\n")
Tim Peters88869f92001-01-14 23:36:06 +0000750
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000751
Guido van Rossum72755611996-03-06 07:20:06 +0000752# Test/debug code
753# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +0000754
Guido van Rossum773ab271996-07-23 03:46:24 +0000755def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000756 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000757
Guido van Rossum7aee3841996-03-07 18:00:44 +0000758 Write minimal HTTP headers and dump all information provided to
759 the script in HTML form.
760
761 """
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000762 print("Content-type: text/html")
763 print()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000764 sys.stderr = sys.stdout
765 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000766 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000767 print_directory()
768 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000769 print_form(form)
770 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000771 print_environ_usage()
772 def f():
Georg Brandl7cae87c2006-09-06 06:51:57 +0000773 exec("testing print_exception() -- <I>italics?</I>")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000774 def g(f=f):
775 f()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000776 print("<H3>What follows is a test, not an actual exception:</H3>")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000777 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000778 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000779 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000780
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000781 print("<H1>Second try with a small maxlen...</H1>")
Guido van Rossum57d51f22000-09-16 21:16:01 +0000782
Guido van Rossumad164711997-05-13 19:03:23 +0000783 global maxlen
784 maxlen = 50
785 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000786 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000787 print_directory()
788 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000789 print_form(form)
790 print_environ(environ)
Guido van Rossumad164711997-05-13 19:03:23 +0000791 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000792 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +0000793
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000794def print_exception(type=None, value=None, tb=None, limit=None):
795 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000796 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000797 import traceback
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000798 print()
799 print("<H3>Traceback (most recent call last):</H3>")
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000800 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000801 traceback.format_exception_only(type, value)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000802 print("<PRE>%s<B>%s</B></PRE>" % (
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000803 escape("".join(list[:-1])),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000804 escape(list[-1]),
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000805 ))
Guido van Rossumf15d1591997-09-29 23:22:12 +0000806 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +0000807
Guido van Rossum773ab271996-07-23 03:46:24 +0000808def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000809 """Dump the shell environment as HTML."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000810 keys = sorted(environ.keys())
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000811 print()
812 print("<H3>Shell Environment:</H3>")
813 print("<DL>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000814 for key in keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000815 print("<DT>", escape(key), "<DD>", escape(environ[key]))
816 print("</DL>")
817 print()
Guido van Rossum72755611996-03-06 07:20:06 +0000818
819def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000820 """Dump the contents of a form as HTML."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000821 keys = sorted(form.keys())
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000822 print()
823 print("<H3>Form Contents:</H3>")
Guido van Rossum57d51f22000-09-16 21:16:01 +0000824 if not keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000825 print("<P>No form fields.")
826 print("<DL>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000827 for key in keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000828 print("<DT>" + escape(key) + ":", end=' ')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000829 value = form[key]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000830 print("<i>" + escape(repr(type(value))) + "</i>")
831 print("<DD>" + escape(repr(value)))
832 print("</DL>")
833 print()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000834
835def print_directory():
836 """Dump the current directory as HTML."""
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000837 print()
838 print("<H3>Current Working Directory:</H3>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000839 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000840 pwd = os.getcwd()
Guido van Rossumb940e112007-01-10 16:19:56 +0000841 except os.error as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000842 print("os.error:", escape(str(msg)))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000843 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000844 print(escape(pwd))
845 print()
Guido van Rossum9a22de11995-01-12 12:29:47 +0000846
Guido van Rossuma8738a51996-03-14 21:30:28 +0000847def print_arguments():
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000848 print()
849 print("<H3>Command Line Arguments:</H3>")
850 print()
851 print(sys.argv)
852 print()
Guido van Rossuma8738a51996-03-14 21:30:28 +0000853
Guido van Rossum9a22de11995-01-12 12:29:47 +0000854def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +0000855 """Dump a list of environment variables used by CGI as HTML."""
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000856 print("""
Guido van Rossum72755611996-03-06 07:20:06 +0000857<H3>These environment variables could have been set:</H3>
858<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +0000859<LI>AUTH_TYPE
860<LI>CONTENT_LENGTH
861<LI>CONTENT_TYPE
862<LI>DATE_GMT
863<LI>DATE_LOCAL
864<LI>DOCUMENT_NAME
865<LI>DOCUMENT_ROOT
866<LI>DOCUMENT_URI
867<LI>GATEWAY_INTERFACE
868<LI>LAST_MODIFIED
869<LI>PATH
870<LI>PATH_INFO
871<LI>PATH_TRANSLATED
872<LI>QUERY_STRING
873<LI>REMOTE_ADDR
874<LI>REMOTE_HOST
875<LI>REMOTE_IDENT
876<LI>REMOTE_USER
877<LI>REQUEST_METHOD
878<LI>SCRIPT_NAME
879<LI>SERVER_NAME
880<LI>SERVER_PORT
881<LI>SERVER_PROTOCOL
882<LI>SERVER_ROOT
883<LI>SERVER_SOFTWARE
884</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +0000885In addition, HTTP headers sent by the server may be passed in the
886environment as well. Here are some common variable names:
887<UL>
888<LI>HTTP_ACCEPT
889<LI>HTTP_CONNECTION
890<LI>HTTP_HOST
891<LI>HTTP_PRAGMA
892<LI>HTTP_REFERER
893<LI>HTTP_USER_AGENT
894</UL>
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000895""")
Guido van Rossum9a22de11995-01-12 12:29:47 +0000896
Guido van Rossum9a22de11995-01-12 12:29:47 +0000897
Guido van Rossum72755611996-03-06 07:20:06 +0000898# Utilities
899# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +0000900
Guido van Rossum64c66201997-07-19 20:11:53 +0000901def escape(s, quote=None):
Skip Montanaro97b2fa22005-08-02 02:50:25 +0000902 '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
903 If the optional flag quote is true, the quotation mark character (")
904 is also translated.'''
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000905 s = s.replace("&", "&amp;") # Must be done first!
906 s = s.replace("<", "&lt;")
907 s = s.replace(">", "&gt;")
Guido van Rossum64c66201997-07-19 20:11:53 +0000908 if quote:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000909 s = s.replace('"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000910 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +0000911
Guido van Rossum2e441f72001-07-25 21:00:19 +0000912def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
913 import re
914 return re.match(_vb_pattern, s)
Guido van Rossum9a22de11995-01-12 12:29:47 +0000915
Guido van Rossum72755611996-03-06 07:20:06 +0000916# Invoke mainline
917# ===============
918
919# Call test() when this file is run as a script (not imported as a module)
Tim Peters88869f92001-01-14 23:36:06 +0000920if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +0000921 test()