blob: 93747ce6c7b270ce1c5a9bff6edf4ec7b407e1f3 [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
Guido van Rossum72755611996-03-06 07:20:06 +000035import sys
36import os
Guido van Rossuma5e9fb61997-08-12 18:18:13 +000037import urllib
Armin Rigo3a703b62005-09-19 09:11:04 +000038import mimetools
39import rfc822
Raymond Hettinger2add3522008-02-04 22:43:27 +000040import collections
Guido van Rossum68937b42007-05-18 00:51:22 +000041from io import StringIO
Guido van Rossum72755611996-03-06 07:20:06 +000042
Georg Brandl49d1b4f2008-05-11 21:42:51 +000043__all__ = ["MiniFieldStorage", "FieldStorage",
Guido van Rossuma8423a92001-03-19 13:40:44 +000044 "parse", "parse_qs", "parse_qsl", "parse_multipart",
45 "parse_header", "print_exception", "print_environ",
46 "print_form", "print_directory", "print_arguments",
47 "print_environ_usage", "escape"]
Guido van Rossumc204c701996-09-05 19:07:11 +000048
49# Logging support
50# ===============
51
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000052logfile = "" # Filename to log to, if not empty
53logfp = None # File object to log to, if not None
Guido van Rossumc204c701996-09-05 19:07:11 +000054
55def initlog(*allargs):
56 """Write a log message, if there is a log file.
57
58 Even though this function is called initlog(), you should always
59 use log(); log is a variable that is set either to initlog
60 (initially), to dolog (once the log file has been opened), or to
61 nolog (when logging is disabled).
62
63 The first argument is a format string; the remaining arguments (if
64 any) are arguments to the % operator, so e.g.
65 log("%s: %s", "a", "b")
66 will write "a: b" to the log file, followed by a newline.
67
68 If the global logfp is not None, it should be a file object to
69 which log data is written.
70
71 If the global logfp is None, the global logfile may be a string
72 giving a filename to open, in append mode. This file should be
73 world writable!!! If the file can't be opened, logging is
74 silently disabled (since there is no safe place where we could
75 send an error message).
76
77 """
78 global logfp, log
79 if logfile and not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000080 try:
81 logfp = open(logfile, "a")
82 except IOError:
83 pass
Guido van Rossumc204c701996-09-05 19:07:11 +000084 if not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000085 log = nolog
Guido van Rossumc204c701996-09-05 19:07:11 +000086 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000087 log = dolog
Guido van Rossum68468eb2003-02-27 20:14:51 +000088 log(*allargs)
Guido van Rossumc204c701996-09-05 19:07:11 +000089
90def dolog(fmt, *args):
91 """Write a log message to the log file. See initlog() for docs."""
92 logfp.write(fmt%args + "\n")
93
94def nolog(*allargs):
95 """Dummy function, assigned to log when logging is disabled."""
96 pass
97
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000098log = initlog # The current logging function
Guido van Rossumc204c701996-09-05 19:07:11 +000099
100
Guido van Rossum72755611996-03-06 07:20:06 +0000101# Parsing functions
102# =================
103
Guido van Rossumad164711997-05-13 19:03:23 +0000104# Maximum input we will accept when REQUEST_METHOD is POST
105# 0 ==> unlimited input
106maxlen = 0
107
Guido van Rossume08c04c1996-11-11 19:29:11 +0000108def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum773ab271996-07-23 03:46:24 +0000109 """Parse a query in the environment or from a file (default stdin)
110
111 Arguments, all optional:
112
113 fp : file pointer; default: sys.stdin
114
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000115 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000116
117 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000118 URL encoded forms should be treated as blank strings.
119 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000120 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000121 blank values are to be ignored and treated as if they were
122 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000123
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000124 strict_parsing: flag indicating what to do with parsing errors.
125 If false (the default), errors are silently ignored.
126 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000127 """
Raymond Hettingera1449002002-05-31 23:54:44 +0000128 if fp is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000129 fp = sys.stdin
Raymond Hettinger54f02222002-06-01 14:18:47 +0000130 if not 'REQUEST_METHOD' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000131 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
Guido van Rossum7aee3841996-03-07 18:00:44 +0000132 if environ['REQUEST_METHOD'] == 'POST':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000133 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
134 if ctype == 'multipart/form-data':
135 return parse_multipart(fp, pdict)
136 elif ctype == 'application/x-www-form-urlencoded':
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000137 clength = int(environ['CONTENT_LENGTH'])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000138 if maxlen and clength > maxlen:
Collin Winterce36ad82007-08-30 01:19:48 +0000139 raise ValueError('Maximum content length exceeded')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000140 qs = fp.read(clength)
141 else:
142 qs = '' # Unknown content-type
Raymond Hettinger54f02222002-06-01 14:18:47 +0000143 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000144 if qs: qs = qs + '&'
145 qs = qs + environ['QUERY_STRING']
Tim Peters88869f92001-01-14 23:36:06 +0000146 elif sys.argv[1:]:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000147 if qs: qs = qs + '&'
148 qs = qs + sys.argv[1]
149 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Raymond Hettinger54f02222002-06-01 14:18:47 +0000150 elif 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000151 qs = environ['QUERY_STRING']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000152 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000153 if sys.argv[1:]:
154 qs = sys.argv[1]
155 else:
156 qs = ""
157 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossume08c04c1996-11-11 19:29:11 +0000158 return parse_qs(qs, keep_blank_values, strict_parsing)
Guido van Rossume7808771995-08-07 20:12:09 +0000159
160
Guido van Rossume08c04c1996-11-11 19:29:11 +0000161def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
162 """Parse a query given as a string argument.
Guido van Rossum773ab271996-07-23 03:46:24 +0000163
164 Arguments:
165
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000166 qs: URL-encoded query string to be parsed
Guido van Rossum773ab271996-07-23 03:46:24 +0000167
168 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000169 URL encoded queries should be treated as blank strings.
170 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000171 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000172 blank values are to be ignored and treated as if they were
173 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000174
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000175 strict_parsing: flag indicating what to do with parsing errors.
176 If false (the default), errors are silently ignored.
177 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000178 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000179 dict = {}
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000180 for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000181 if name in dict:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000182 dict[name].append(value)
183 else:
184 dict[name] = [value]
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000185 return dict
186
187def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
188 """Parse a query given as a string argument.
189
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000190 Arguments:
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000191
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000192 qs: URL-encoded query string to be parsed
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000193
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000194 keep_blank_values: flag indicating whether blank values in
195 URL encoded queries should be treated as blank strings. A
196 true value indicates that blanks should be retained as blank
197 strings. The default false value indicates that blank values
198 are to be ignored and treated as if they were not included.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000199
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000200 strict_parsing: flag indicating what to do with parsing errors. If
201 false (the default), errors are silently ignored. If true,
Tim Peters88869f92001-01-14 23:36:06 +0000202 errors raise a ValueError exception.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000203
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000204 Returns a list, as G-d intended.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000205 """
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000206 pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
207 r = []
208 for name_value in pairs:
Neil Schemenauer66edb622004-07-19 15:38:11 +0000209 if not name_value and not strict_parsing:
210 continue
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000211 nv = name_value.split('=', 1)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000212 if len(nv) != 2:
213 if strict_parsing:
Collin Winterce36ad82007-08-30 01:19:48 +0000214 raise ValueError("bad query field: %r" % (name_value,))
Brett Cannon8d9b60f2004-03-21 22:16:15 +0000215 # Handle case of a control-name with no equal sign
216 if keep_blank_values:
217 nv.append('')
218 else:
219 continue
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000220 if len(nv[1]) or keep_blank_values:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000221 name = urllib.unquote(nv[0].replace('+', ' '))
222 value = urllib.unquote(nv[1].replace('+', ' '))
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000223 r.append((name, value))
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000224
225 return r
Guido van Rossum9a22de11995-01-12 12:29:47 +0000226
227
Guido van Rossum0147db01996-03-09 03:16:04 +0000228def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000229 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000230
Guido van Rossum7aee3841996-03-07 18:00:44 +0000231 Arguments:
232 fp : input file
Johannes Gijsbersc7fc10a2005-01-08 13:56:36 +0000233 pdict: dictionary containing other parameters of content-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000234
Tim Peters88869f92001-01-14 23:36:06 +0000235 Returns a dictionary just like parse_qs(): keys are the field names, each
236 value is a list of values for that field. This is easy to use but not
237 much good if you are expecting megabytes to be uploaded -- in that case,
238 use the FieldStorage class instead which is much more flexible. Note
239 that content-type is the raw, unparsed contents of the content-type
Guido van Rossum0147db01996-03-09 03:16:04 +0000240 header.
Tim Peters88869f92001-01-14 23:36:06 +0000241
242 XXX This does not parse nested multipart parts -- use FieldStorage for
Guido van Rossum0147db01996-03-09 03:16:04 +0000243 that.
Tim Peters88869f92001-01-14 23:36:06 +0000244
245 XXX This should really be subsumed by FieldStorage altogether -- no
Guido van Rossum0147db01996-03-09 03:16:04 +0000246 point in having two implementations of the same parsing algorithm.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000247 Also, FieldStorage protects itself better against certain DoS attacks
248 by limiting the size of the data read in one chunk. The API here
249 does not support that kind of protection. This also affects parse()
250 since it can call parse_multipart().
Guido van Rossum72755611996-03-06 07:20:06 +0000251
Guido van Rossum7aee3841996-03-07 18:00:44 +0000252 """
Guido van Rossum2e441f72001-07-25 21:00:19 +0000253 boundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000254 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000255 boundary = pdict['boundary']
Guido van Rossum2e441f72001-07-25 21:00:19 +0000256 if not valid_boundary(boundary):
Collin Winterce36ad82007-08-30 01:19:48 +0000257 raise ValueError('Invalid boundary in multipart form: %r'
Walter Dörwald70a6b492004-02-12 17:35:32 +0000258 % (boundary,))
Tim Petersab9ba272001-08-09 21:40:30 +0000259
Guido van Rossum7aee3841996-03-07 18:00:44 +0000260 nextpart = "--" + boundary
261 lastpart = "--" + boundary + "--"
262 partdict = {}
263 terminator = ""
264
265 while terminator != lastpart:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000266 bytes = -1
267 data = None
268 if terminator:
269 # At start of next part. Read headers first.
Armin Rigo3a703b62005-09-19 09:11:04 +0000270 headers = mimetools.Message(fp)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000271 clength = headers.getheader('content-length')
272 if clength:
273 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000274 bytes = int(clength)
275 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000276 pass
277 if bytes > 0:
278 if maxlen and bytes > maxlen:
Collin Winterce36ad82007-08-30 01:19:48 +0000279 raise ValueError('Maximum content length exceeded')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000280 data = fp.read(bytes)
281 else:
282 data = ""
283 # Read lines until end of part.
284 lines = []
285 while 1:
286 line = fp.readline()
287 if not line:
288 terminator = lastpart # End outer loop
289 break
290 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000291 terminator = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000292 if terminator in (nextpart, lastpart):
293 break
294 lines.append(line)
295 # Done with part.
296 if data is None:
297 continue
298 if bytes < 0:
299 if lines:
300 # Strip final line terminator
301 line = lines[-1]
302 if line[-2:] == "\r\n":
303 line = line[:-2]
304 elif line[-1:] == "\n":
305 line = line[:-1]
306 lines[-1] = line
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000307 data = "".join(lines)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000308 line = headers['content-disposition']
309 if not line:
310 continue
311 key, params = parse_header(line)
312 if key != 'form-data':
313 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000314 if 'name' in params:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000315 name = params['name']
316 else:
317 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000318 if name in partdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000319 partdict[name].append(data)
320 else:
321 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000322
Guido van Rossum7aee3841996-03-07 18:00:44 +0000323 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000324
325
Guido van Rossum72755611996-03-06 07:20:06 +0000326def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000327 """Parse a Content-type like header.
328
329 Return the main content-type and a dictionary of options.
330
331 """
Raymond Hettingerf871d832004-12-31 21:59:02 +0000332 plist = [x.strip() for x in line.split(';')]
Raymond Hettinger46ac8eb2002-06-30 03:39:14 +0000333 key = plist.pop(0).lower()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000334 pdict = {}
335 for p in plist:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000336 i = p.find('=')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000337 if i >= 0:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000338 name = p[:i].strip().lower()
339 value = p[i+1:].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000340 if len(value) >= 2 and value[0] == value[-1] == '"':
341 value = value[1:-1]
Johannes Gijsbers9e15dd62004-08-14 15:39:34 +0000342 value = value.replace('\\\\', '\\').replace('\\"', '"')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000343 pdict[name] = value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000344 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000345
346
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000347# Classes for field storage
348# =========================
349
350class MiniFieldStorage:
351
Guido van Rossum0147db01996-03-09 03:16:04 +0000352 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000353
Guido van Rossum7aee3841996-03-07 18:00:44 +0000354 # Dummy attributes
355 filename = None
356 list = None
357 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000358 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000359 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000360 disposition = None
361 disposition_options = {}
362 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000363
Guido van Rossum7aee3841996-03-07 18:00:44 +0000364 def __init__(self, name, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000365 """Constructor from field name and value."""
366 self.name = name
367 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000368 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000369
370 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000371 """Return printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000372 return "MiniFieldStorage(%r, %r)" % (self.name, self.value)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000373
374
375class FieldStorage:
376
Guido van Rossum7aee3841996-03-07 18:00:44 +0000377 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000378
Guido van Rossum7aee3841996-03-07 18:00:44 +0000379 This class provides naming, typing, files stored on disk, and
380 more. At the top level, it is accessible like a dictionary, whose
381 keys are the field names. (Note: None can occur as a field name.)
382 The items are either a Python list (if there's multiple values) or
383 another FieldStorage or MiniFieldStorage object. If it's a single
384 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000385
Guido van Rossum7aee3841996-03-07 18:00:44 +0000386 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000387
Guido van Rossum7aee3841996-03-07 18:00:44 +0000388 filename: the filename, if specified; otherwise None; this is the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000389 client side filename, *not* the file name on which it is
390 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000391
Guido van Rossum7aee3841996-03-07 18:00:44 +0000392 value: the value as a *string*; for file uploads, this
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000393 transparently reads the file every time you request the value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000394
395 file: the file(-like) object from which you can read the data;
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000396 None if the data is stored a simple string
Guido van Rossum7aee3841996-03-07 18:00:44 +0000397
398 type: the content-type, or None if not specified
399
400 type_options: dictionary of options specified on the content-type
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000401 line
Guido van Rossum7aee3841996-03-07 18:00:44 +0000402
403 disposition: content-disposition, or None if not specified
404
405 disposition_options: dictionary of corresponding options
406
Armin Rigo3a703b62005-09-19 09:11:04 +0000407 headers: a dictionary(-like) object (sometimes rfc822.Message or a
408 subclass thereof) containing *all* headers
Guido van Rossum7aee3841996-03-07 18:00:44 +0000409
410 The class is subclassable, mostly for the purpose of overriding
411 the make_file() method, which is called internally to come up with
412 a file open for reading and writing. This makes it possible to
413 override the default choice of storing all files in a temporary
414 directory and unlinking them as soon as they have been opened.
415
416 """
417
Guido van Rossum773ab271996-07-23 03:46:24 +0000418 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000419 environ=os.environ, keep_blank_values=0, strict_parsing=0):
420 """Constructor. Read multipart/* until last part.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000421
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000422 Arguments, all optional:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000423
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000424 fp : file pointer; default: sys.stdin
Guido van Rossumb1b4f941998-05-08 19:55:51 +0000425 (not used when the request method is GET)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000426
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000427 headers : header dictionary-like object; default:
428 taken from environ as per CGI spec
Guido van Rossum7aee3841996-03-07 18:00:44 +0000429
Guido van Rossum773ab271996-07-23 03:46:24 +0000430 outerboundary : terminating multipart boundary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000431 (for internal use only)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000432
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000433 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000434
435 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000436 URL encoded forms should be treated as blank strings.
437 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000438 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000439 blank values are to be ignored and treated as if they were
440 not included.
Guido van Rossum773ab271996-07-23 03:46:24 +0000441
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000442 strict_parsing: flag indicating what to do with parsing errors.
443 If false (the default), errors are silently ignored.
444 If true, errors raise a ValueError exception.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000445
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000446 """
447 method = 'GET'
448 self.keep_blank_values = keep_blank_values
449 self.strict_parsing = strict_parsing
Raymond Hettinger54f02222002-06-01 14:18:47 +0000450 if 'REQUEST_METHOD' in environ:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000451 method = environ['REQUEST_METHOD'].upper()
Guido van Rossum01852831998-06-25 02:40:17 +0000452 if method == 'GET' or method == 'HEAD':
Raymond Hettinger54f02222002-06-01 14:18:47 +0000453 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000454 qs = environ['QUERY_STRING']
455 elif sys.argv[1:]:
456 qs = sys.argv[1]
457 else:
458 qs = ""
459 fp = StringIO(qs)
460 if headers is None:
461 headers = {'content-type':
462 "application/x-www-form-urlencoded"}
463 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000464 headers = {}
465 if method == 'POST':
466 # Set default content-type for POST to what's traditional
467 headers['content-type'] = "application/x-www-form-urlencoded"
Raymond Hettinger54f02222002-06-01 14:18:47 +0000468 if 'CONTENT_TYPE' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000469 headers['content-type'] = environ['CONTENT_TYPE']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000470 if 'CONTENT_LENGTH' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000471 headers['content-length'] = environ['CONTENT_LENGTH']
472 self.fp = fp or sys.stdin
473 self.headers = headers
474 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000475
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000476 # Process content-disposition header
477 cdisp, pdict = "", {}
Raymond Hettinger54f02222002-06-01 14:18:47 +0000478 if 'content-disposition' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000479 cdisp, pdict = parse_header(self.headers['content-disposition'])
480 self.disposition = cdisp
481 self.disposition_options = pdict
482 self.name = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000483 if 'name' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000484 self.name = pdict['name']
485 self.filename = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000486 if 'filename' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000487 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000488
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000489 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000490 #
491 # Honor any existing content-type header. But if there is no
492 # content-type header, use some sensible defaults. Assume
493 # outerboundary is "" at the outer level, but something non-false
494 # inside a multi-part. The default for an inner part is text/plain,
495 # but for an outer part it should be urlencoded. This should catch
496 # bogus clients which erroneously forget to include a content-type
497 # header.
498 #
499 # See below for what we do if there does exist a content-type header,
500 # but it happens to be something we don't understand.
Raymond Hettinger54f02222002-06-01 14:18:47 +0000501 if 'content-type' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000502 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000503 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000504 ctype, pdict = "text/plain", {}
505 else:
506 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000507 self.type = ctype
508 self.type_options = pdict
509 self.innerboundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000510 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000511 self.innerboundary = pdict['boundary']
512 clen = -1
Raymond Hettinger54f02222002-06-01 14:18:47 +0000513 if 'content-length' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000514 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000515 clen = int(self.headers['content-length'])
Skip Montanarodb5d1442002-03-23 05:50:17 +0000516 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000517 pass
518 if maxlen and clen > maxlen:
Collin Winterce36ad82007-08-30 01:19:48 +0000519 raise ValueError('Maximum content length exceeded')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000520 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000521
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000522 self.list = self.file = None
523 self.done = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000524 if ctype == 'application/x-www-form-urlencoded':
525 self.read_urlencoded()
526 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000527 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000528 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000529 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000530
531 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000532 """Return a printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000533 return "FieldStorage(%r, %r, %r)" % (
534 self.name, self.filename, self.value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000535
Guido van Rossum4061cbe2002-09-11 18:20:34 +0000536 def __iter__(self):
537 return iter(self.keys())
538
Guido van Rossum7aee3841996-03-07 18:00:44 +0000539 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000540 if name != 'value':
Collin Winterce36ad82007-08-30 01:19:48 +0000541 raise AttributeError(name)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000542 if self.file:
543 self.file.seek(0)
544 value = self.file.read()
545 self.file.seek(0)
546 elif self.list is not None:
547 value = self.list
548 else:
549 value = None
550 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000551
552 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000553 """Dictionary style indexing."""
554 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000555 raise TypeError("not indexable")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000556 found = []
557 for item in self.list:
558 if item.name == key: found.append(item)
559 if not found:
Collin Winterce36ad82007-08-30 01:19:48 +0000560 raise KeyError(key)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000561 if len(found) == 1:
562 return found[0]
563 else:
564 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000565
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000566 def getvalue(self, key, default=None):
567 """Dictionary style get() method, including 'value' lookup."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000568 if key in self:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000569 value = self[key]
570 if type(value) is type([]):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000571 return [x.value for x in value]
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000572 else:
573 return value.value
574 else:
575 return default
576
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000577 def getfirst(self, key, default=None):
578 """ Return the first value received."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000579 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000580 value = self[key]
581 if type(value) is type([]):
582 return value[0].value
583 else:
584 return value.value
585 else:
586 return default
587
588 def getlist(self, key):
589 """ Return list of received values."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000590 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000591 value = self[key]
592 if type(value) is type([]):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000593 return [x.value for x in value]
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000594 else:
595 return [value.value]
596 else:
597 return []
598
Guido van Rossum7aee3841996-03-07 18:00:44 +0000599 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000600 """Dictionary style keys() method."""
601 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000602 raise TypeError("not indexable")
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000603 return list(set(item.name for item in self.list))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000604
Raymond Hettinger54f02222002-06-01 14:18:47 +0000605 def __contains__(self, key):
606 """Dictionary style __contains__ method."""
607 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000608 raise TypeError("not indexable")
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000609 return any(item.name == key for item in self.list)
Raymond Hettinger54f02222002-06-01 14:18:47 +0000610
Guido van Rossum88b85d41997-01-11 19:21:33 +0000611 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000612 """Dictionary style len(x) support."""
613 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000614
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000615 def __nonzero__(self):
616 return bool(self.list)
617
Guido van Rossum7aee3841996-03-07 18:00:44 +0000618 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000619 """Internal: read data in query string format."""
620 qs = self.fp.read(self.length)
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000621 self.list = list = []
622 for key, value in parse_qsl(qs, self.keep_blank_values,
623 self.strict_parsing):
624 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000625 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000626
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000627 FieldStorageClass = None
628
Guido van Rossumf5745001998-10-20 14:43:02 +0000629 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000630 """Internal: read a part that is itself multipart."""
Guido van Rossum2e441f72001-07-25 21:00:19 +0000631 ib = self.innerboundary
632 if not valid_boundary(ib):
Collin Winterce36ad82007-08-30 01:19:48 +0000633 raise ValueError('Invalid boundary in multipart form: %r' % (ib,))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000634 self.list = []
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000635 klass = self.FieldStorageClass or self.__class__
Guido van Rossum2e441f72001-07-25 21:00:19 +0000636 part = klass(self.fp, {}, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000637 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000638 # Throw first part away
639 while not part.done:
Armin Rigo3a703b62005-09-19 09:11:04 +0000640 headers = rfc822.Message(self.fp)
Guido van Rossum2e441f72001-07-25 21:00:19 +0000641 part = klass(self.fp, headers, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000642 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000643 self.list.append(part)
644 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000645
646 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000647 """Internal: read an atomic part."""
648 if self.length >= 0:
649 self.read_binary()
650 self.skip_lines()
651 else:
652 self.read_lines()
653 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000654
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000655 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000656
657 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000658 """Internal: read binary data."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000659 self.file = self.make_file()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000660 todo = self.length
661 if todo >= 0:
662 while todo > 0:
663 data = self.fp.read(min(todo, self.bufsize))
664 if not data:
665 self.done = -1
666 break
667 self.file.write(data)
668 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000669
670 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000671 """Internal: read lines until EOF or outerboundary."""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000672 self.file = self.__file = StringIO()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000673 if self.outerboundary:
674 self.read_lines_to_outerboundary()
675 else:
676 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000677
Guido van Rossum52b8c292001-06-29 13:06:06 +0000678 def __write(self, line):
679 if self.__file is not None:
680 if self.__file.tell() + len(line) > 1000:
Guido van Rossuma1a68522007-08-28 03:11:34 +0000681 self.file = self.make_file()
682 data = self.__file.getvalue()
683 self.file.write(data)
Guido van Rossum52b8c292001-06-29 13:06:06 +0000684 self.__file = None
685 self.file.write(line)
686
Guido van Rossum7aee3841996-03-07 18:00:44 +0000687 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000688 """Internal: read lines until EOF."""
689 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000690 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000691 if not line:
692 self.done = -1
693 break
Guido van Rossum52b8c292001-06-29 13:06:06 +0000694 self.__write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000695
696 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000697 """Internal: read lines until outerboundary."""
698 next = "--" + self.outerboundary
699 last = next + "--"
700 delim = ""
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000701 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000702 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000703 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000704 if not line:
705 self.done = -1
706 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000707 if line[:2] == "--" and last_line_lfend:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000708 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000709 if strippedline == next:
710 break
711 if strippedline == last:
712 self.done = 1
713 break
714 odelim = delim
715 if line[-2:] == "\r\n":
716 delim = "\r\n"
717 line = line[:-2]
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000718 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000719 elif line[-1] == "\n":
720 delim = "\n"
721 line = line[:-1]
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000722 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000723 else:
724 delim = ""
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000725 last_line_lfend = False
Guido van Rossum52b8c292001-06-29 13:06:06 +0000726 self.__write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000727
728 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000729 """Internal: skip lines until outer boundary if defined."""
730 if not self.outerboundary or self.done:
731 return
732 next = "--" + self.outerboundary
733 last = next + "--"
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000734 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000735 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000736 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000737 if not line:
738 self.done = -1
739 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000740 if line[:2] == "--" and last_line_lfend:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000741 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000742 if strippedline == next:
743 break
744 if strippedline == last:
745 self.done = 1
746 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000747 last_line_lfend = line.endswith('\n')
Guido van Rossum7aee3841996-03-07 18:00:44 +0000748
Guido van Rossuma1a68522007-08-28 03:11:34 +0000749 def make_file(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000750 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000751
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000752 The file will be used as follows:
753 - data is written to it
754 - seek(0)
755 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +0000756
Guido van Rossuma1a68522007-08-28 03:11:34 +0000757 The file is always opened in text mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000758
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000759 This version opens a temporary file for reading and writing,
760 and immediately deletes (unlinks) it. The trick (on Unix!) is
761 that the file can still be used, but it can't be opened by
762 another process, and it will automatically be deleted when it
763 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000764
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000765 If you want a more permanent file, you derive a class which
766 overrides this method. If you want a visible temporary file
767 that is nevertheless automatically deleted when the script
768 terminates, try defining a __del__ method in a derived class
769 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000770
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000771 """
772 import tempfile
Guido van Rossum92bab812007-08-28 03:32:38 +0000773 return tempfile.TemporaryFile("w+", encoding="utf-8", newline="\n")
Tim Peters88869f92001-01-14 23:36:06 +0000774
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000775
Guido van Rossum72755611996-03-06 07:20:06 +0000776# Test/debug code
777# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +0000778
Guido van Rossum773ab271996-07-23 03:46:24 +0000779def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000780 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000781
Guido van Rossum7aee3841996-03-07 18:00:44 +0000782 Write minimal HTTP headers and dump all information provided to
783 the script in HTML form.
784
785 """
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000786 print("Content-type: text/html")
787 print()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000788 sys.stderr = sys.stdout
789 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000790 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000791 print_directory()
792 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000793 print_form(form)
794 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000795 print_environ_usage()
796 def f():
Georg Brandl7cae87c2006-09-06 06:51:57 +0000797 exec("testing print_exception() -- <I>italics?</I>")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000798 def g(f=f):
799 f()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000800 print("<H3>What follows is a test, not an actual exception:</H3>")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000801 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000802 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000803 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000804
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000805 print("<H1>Second try with a small maxlen...</H1>")
Guido van Rossum57d51f22000-09-16 21:16:01 +0000806
Guido van Rossumad164711997-05-13 19:03:23 +0000807 global maxlen
808 maxlen = 50
809 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000810 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000811 print_directory()
812 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000813 print_form(form)
814 print_environ(environ)
Guido van Rossumad164711997-05-13 19:03:23 +0000815 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000816 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +0000817
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000818def print_exception(type=None, value=None, tb=None, limit=None):
819 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000820 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000821 import traceback
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000822 print()
823 print("<H3>Traceback (most recent call last):</H3>")
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000824 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000825 traceback.format_exception_only(type, value)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000826 print("<PRE>%s<B>%s</B></PRE>" % (
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000827 escape("".join(list[:-1])),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000828 escape(list[-1]),
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000829 ))
Guido van Rossumf15d1591997-09-29 23:22:12 +0000830 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +0000831
Guido van Rossum773ab271996-07-23 03:46:24 +0000832def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000833 """Dump the shell environment as HTML."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000834 keys = sorted(environ.keys())
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000835 print()
836 print("<H3>Shell Environment:</H3>")
837 print("<DL>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000838 for key in keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000839 print("<DT>", escape(key), "<DD>", escape(environ[key]))
840 print("</DL>")
841 print()
Guido van Rossum72755611996-03-06 07:20:06 +0000842
843def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000844 """Dump the contents of a form as HTML."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000845 keys = sorted(form.keys())
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000846 print()
847 print("<H3>Form Contents:</H3>")
Guido van Rossum57d51f22000-09-16 21:16:01 +0000848 if not keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000849 print("<P>No form fields.")
850 print("<DL>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000851 for key in keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000852 print("<DT>" + escape(key) + ":", end=' ')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000853 value = form[key]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000854 print("<i>" + escape(repr(type(value))) + "</i>")
855 print("<DD>" + escape(repr(value)))
856 print("</DL>")
857 print()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000858
859def print_directory():
860 """Dump the current directory as HTML."""
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000861 print()
862 print("<H3>Current Working Directory:</H3>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000863 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000864 pwd = os.getcwd()
Guido van Rossumb940e112007-01-10 16:19:56 +0000865 except os.error as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000866 print("os.error:", escape(str(msg)))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000867 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000868 print(escape(pwd))
869 print()
Guido van Rossum9a22de11995-01-12 12:29:47 +0000870
Guido van Rossuma8738a51996-03-14 21:30:28 +0000871def print_arguments():
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000872 print()
873 print("<H3>Command Line Arguments:</H3>")
874 print()
875 print(sys.argv)
876 print()
Guido van Rossuma8738a51996-03-14 21:30:28 +0000877
Guido van Rossum9a22de11995-01-12 12:29:47 +0000878def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +0000879 """Dump a list of environment variables used by CGI as HTML."""
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000880 print("""
Guido van Rossum72755611996-03-06 07:20:06 +0000881<H3>These environment variables could have been set:</H3>
882<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +0000883<LI>AUTH_TYPE
884<LI>CONTENT_LENGTH
885<LI>CONTENT_TYPE
886<LI>DATE_GMT
887<LI>DATE_LOCAL
888<LI>DOCUMENT_NAME
889<LI>DOCUMENT_ROOT
890<LI>DOCUMENT_URI
891<LI>GATEWAY_INTERFACE
892<LI>LAST_MODIFIED
893<LI>PATH
894<LI>PATH_INFO
895<LI>PATH_TRANSLATED
896<LI>QUERY_STRING
897<LI>REMOTE_ADDR
898<LI>REMOTE_HOST
899<LI>REMOTE_IDENT
900<LI>REMOTE_USER
901<LI>REQUEST_METHOD
902<LI>SCRIPT_NAME
903<LI>SERVER_NAME
904<LI>SERVER_PORT
905<LI>SERVER_PROTOCOL
906<LI>SERVER_ROOT
907<LI>SERVER_SOFTWARE
908</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +0000909In addition, HTTP headers sent by the server may be passed in the
910environment as well. Here are some common variable names:
911<UL>
912<LI>HTTP_ACCEPT
913<LI>HTTP_CONNECTION
914<LI>HTTP_HOST
915<LI>HTTP_PRAGMA
916<LI>HTTP_REFERER
917<LI>HTTP_USER_AGENT
918</UL>
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000919""")
Guido van Rossum9a22de11995-01-12 12:29:47 +0000920
Guido van Rossum9a22de11995-01-12 12:29:47 +0000921
Guido van Rossum72755611996-03-06 07:20:06 +0000922# Utilities
923# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +0000924
Guido van Rossum64c66201997-07-19 20:11:53 +0000925def escape(s, quote=None):
Skip Montanaro97b2fa22005-08-02 02:50:25 +0000926 '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
927 If the optional flag quote is true, the quotation mark character (")
928 is also translated.'''
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000929 s = s.replace("&", "&amp;") # Must be done first!
930 s = s.replace("<", "&lt;")
931 s = s.replace(">", "&gt;")
Guido van Rossum64c66201997-07-19 20:11:53 +0000932 if quote:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000933 s = s.replace('"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000934 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +0000935
Guido van Rossum2e441f72001-07-25 21:00:19 +0000936def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
937 import re
938 return re.match(_vb_pattern, s)
Guido van Rossum9a22de11995-01-12 12:29:47 +0000939
Guido van Rossum72755611996-03-06 07:20:06 +0000940# Invoke mainline
941# ===============
942
943# Call test() when this file is run as a script (not imported as a module)
Tim Peters88869f92001-01-14 23:36:06 +0000944if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +0000945 test()