blob: bc60c1d8489c104dc823d6a3ca7922acfe211638 [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
Guido van Rossum72755611996-03-06 07:20:06 +000040
Georg Brandl49d1b4f2008-05-11 21:42:51 +000041__all__ = ["MiniFieldStorage", "FieldStorage",
Guido van Rossuma8423a92001-03-19 13:40:44 +000042 "parse", "parse_qs", "parse_qsl", "parse_multipart",
43 "parse_header", "print_exception", "print_environ",
44 "print_form", "print_directory", "print_arguments",
45 "print_environ_usage", "escape"]
Guido van Rossumc204c701996-09-05 19:07:11 +000046
47# Logging support
48# ===============
49
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000050logfile = "" # Filename to log to, if not empty
51logfp = None # File object to log to, if not None
Guido van Rossumc204c701996-09-05 19:07:11 +000052
53def initlog(*allargs):
54 """Write a log message, if there is a log file.
55
56 Even though this function is called initlog(), you should always
57 use log(); log is a variable that is set either to initlog
58 (initially), to dolog (once the log file has been opened), or to
59 nolog (when logging is disabled).
60
61 The first argument is a format string; the remaining arguments (if
62 any) are arguments to the % operator, so e.g.
63 log("%s: %s", "a", "b")
64 will write "a: b" to the log file, followed by a newline.
65
66 If the global logfp is not None, it should be a file object to
67 which log data is written.
68
69 If the global logfp is None, the global logfile may be a string
70 giving a filename to open, in append mode. This file should be
71 world writable!!! If the file can't be opened, logging is
72 silently disabled (since there is no safe place where we could
73 send an error message).
74
75 """
76 global logfp, log
77 if logfile and not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000078 try:
79 logfp = open(logfile, "a")
80 except IOError:
81 pass
Guido van Rossumc204c701996-09-05 19:07:11 +000082 if not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000083 log = nolog
Guido van Rossumc204c701996-09-05 19:07:11 +000084 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000085 log = dolog
Guido van Rossum68468eb2003-02-27 20:14:51 +000086 log(*allargs)
Guido van Rossumc204c701996-09-05 19:07:11 +000087
88def dolog(fmt, *args):
89 """Write a log message to the log file. See initlog() for docs."""
90 logfp.write(fmt%args + "\n")
91
92def nolog(*allargs):
93 """Dummy function, assigned to log when logging is disabled."""
94 pass
95
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000096log = initlog # The current logging function
Guido van Rossumc204c701996-09-05 19:07:11 +000097
98
Guido van Rossum72755611996-03-06 07:20:06 +000099# Parsing functions
100# =================
101
Guido van Rossumad164711997-05-13 19:03:23 +0000102# Maximum input we will accept when REQUEST_METHOD is POST
103# 0 ==> unlimited input
104maxlen = 0
105
Guido van Rossume08c04c1996-11-11 19:29:11 +0000106def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum773ab271996-07-23 03:46:24 +0000107 """Parse a query in the environment or from a file (default stdin)
108
109 Arguments, all optional:
110
111 fp : file pointer; default: sys.stdin
112
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000113 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000114
115 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000116 URL encoded forms should be treated as blank strings.
117 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000118 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000119 blank values are to be ignored and treated as if they were
120 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000121
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000122 strict_parsing: flag indicating what to do with parsing errors.
123 If false (the default), errors are silently ignored.
124 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000125 """
Raymond Hettingera1449002002-05-31 23:54:44 +0000126 if fp is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000127 fp = sys.stdin
Raymond Hettinger54f02222002-06-01 14:18:47 +0000128 if not 'REQUEST_METHOD' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000129 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
Guido van Rossum7aee3841996-03-07 18:00:44 +0000130 if environ['REQUEST_METHOD'] == 'POST':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000131 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
132 if ctype == 'multipart/form-data':
133 return parse_multipart(fp, pdict)
134 elif ctype == 'application/x-www-form-urlencoded':
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000135 clength = int(environ['CONTENT_LENGTH'])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000136 if maxlen and clength > maxlen:
Collin Winterce36ad82007-08-30 01:19:48 +0000137 raise ValueError('Maximum content length exceeded')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000138 qs = fp.read(clength)
139 else:
140 qs = '' # Unknown content-type
Raymond Hettinger54f02222002-06-01 14:18:47 +0000141 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000142 if qs: qs = qs + '&'
143 qs = qs + environ['QUERY_STRING']
Tim Peters88869f92001-01-14 23:36:06 +0000144 elif sys.argv[1:]:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000145 if qs: qs = qs + '&'
146 qs = qs + sys.argv[1]
147 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Raymond Hettinger54f02222002-06-01 14:18:47 +0000148 elif 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000149 qs = environ['QUERY_STRING']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000150 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000151 if sys.argv[1:]:
152 qs = sys.argv[1]
153 else:
154 qs = ""
155 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossume08c04c1996-11-11 19:29:11 +0000156 return parse_qs(qs, keep_blank_values, strict_parsing)
Guido van Rossume7808771995-08-07 20:12:09 +0000157
158
Guido van Rossume08c04c1996-11-11 19:29:11 +0000159def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
160 """Parse a query given as a string argument.
Guido van Rossum773ab271996-07-23 03:46:24 +0000161
162 Arguments:
163
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000164 qs: URL-encoded query string to be parsed
Guido van Rossum773ab271996-07-23 03:46:24 +0000165
166 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000167 URL encoded queries should be treated as blank strings.
168 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000169 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000170 blank values are to be ignored and treated as if they were
171 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000172
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000173 strict_parsing: flag indicating what to do with parsing errors.
174 If false (the default), errors are silently ignored.
175 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000176 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000177 dict = {}
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000178 for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000179 if name in dict:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000180 dict[name].append(value)
181 else:
182 dict[name] = [value]
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000183 return dict
184
185def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
186 """Parse a query given as a string argument.
187
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000188 Arguments:
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000189
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000190 qs: URL-encoded query string to be parsed
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000191
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000192 keep_blank_values: flag indicating whether blank values in
193 URL encoded queries should be treated as blank strings. A
194 true value indicates that blanks should be retained as blank
195 strings. The default false value indicates that blank values
196 are to be ignored and treated as if they were not included.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000197
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000198 strict_parsing: flag indicating what to do with parsing errors. If
199 false (the default), errors are silently ignored. If true,
Tim Peters88869f92001-01-14 23:36:06 +0000200 errors raise a ValueError exception.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000201
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000202 Returns a list, as G-d intended.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000203 """
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000204 pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
205 r = []
206 for name_value in pairs:
Neil Schemenauer66edb622004-07-19 15:38:11 +0000207 if not name_value and not strict_parsing:
208 continue
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000209 nv = name_value.split('=', 1)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000210 if len(nv) != 2:
211 if strict_parsing:
Collin Winterce36ad82007-08-30 01:19:48 +0000212 raise ValueError("bad query field: %r" % (name_value,))
Brett Cannon8d9b60f2004-03-21 22:16:15 +0000213 # Handle case of a control-name with no equal sign
214 if keep_blank_values:
215 nv.append('')
216 else:
217 continue
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000218 if len(nv[1]) or keep_blank_values:
Jeremy Hylton1afc1692008-06-18 20:49:58 +0000219 name = urllib.parse.unquote(nv[0].replace('+', ' '))
220 value = urllib.parse.unquote(nv[1].replace('+', ' '))
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000221 r.append((name, value))
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000222
223 return r
Guido van Rossum9a22de11995-01-12 12:29:47 +0000224
225
Guido van Rossum0147db01996-03-09 03:16:04 +0000226def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000227 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000228
Guido van Rossum7aee3841996-03-07 18:00:44 +0000229 Arguments:
230 fp : input file
Johannes Gijsbersc7fc10a2005-01-08 13:56:36 +0000231 pdict: dictionary containing other parameters of content-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000232
Tim Peters88869f92001-01-14 23:36:06 +0000233 Returns a dictionary just like parse_qs(): keys are the field names, each
234 value is a list of values for that field. This is easy to use but not
235 much good if you are expecting megabytes to be uploaded -- in that case,
236 use the FieldStorage class instead which is much more flexible. Note
237 that content-type is the raw, unparsed contents of the content-type
Guido van Rossum0147db01996-03-09 03:16:04 +0000238 header.
Tim Peters88869f92001-01-14 23:36:06 +0000239
240 XXX This does not parse nested multipart parts -- use FieldStorage for
Guido van Rossum0147db01996-03-09 03:16:04 +0000241 that.
Tim Peters88869f92001-01-14 23:36:06 +0000242
243 XXX This should really be subsumed by FieldStorage altogether -- no
Guido van Rossum0147db01996-03-09 03:16:04 +0000244 point in having two implementations of the same parsing algorithm.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000245 Also, FieldStorage protects itself better against certain DoS attacks
246 by limiting the size of the data read in one chunk. The API here
247 does not support that kind of protection. This also affects parse()
248 since it can call parse_multipart().
Guido van Rossum72755611996-03-06 07:20:06 +0000249
Guido van Rossum7aee3841996-03-07 18:00:44 +0000250 """
Barry Warsaw820c1202008-06-12 04:06:45 +0000251 import http.client
252
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.
Barry Warsaw820c1202008-06-12 04:06:45 +0000270 headers = http.client.parse_headers(fp)
271 clength = headers.get('content-length')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000272 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
Barry Warsaw596097e2008-06-12 02:38:51 +0000407 headers: a dictionary(-like) object (sometimes email.message.Message or a
Armin Rigo3a703b62005-09-19 09:11:04 +0000408 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()
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000452 self.qs_on_post = None
Guido van Rossum01852831998-06-25 02:40:17 +0000453 if method == 'GET' or method == 'HEAD':
Raymond Hettinger54f02222002-06-01 14:18:47 +0000454 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000455 qs = environ['QUERY_STRING']
456 elif sys.argv[1:]:
457 qs = sys.argv[1]
458 else:
459 qs = ""
460 fp = StringIO(qs)
461 if headers is None:
462 headers = {'content-type':
463 "application/x-www-form-urlencoded"}
464 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000465 headers = {}
466 if method == 'POST':
467 # Set default content-type for POST to what's traditional
468 headers['content-type'] = "application/x-www-form-urlencoded"
Raymond Hettinger54f02222002-06-01 14:18:47 +0000469 if 'CONTENT_TYPE' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000470 headers['content-type'] = environ['CONTENT_TYPE']
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000471 if 'QUERY_STRING' in environ:
472 self.qs_on_post = environ['QUERY_STRING']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000473 if 'CONTENT_LENGTH' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000474 headers['content-length'] = environ['CONTENT_LENGTH']
475 self.fp = fp or sys.stdin
476 self.headers = headers
477 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000478
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000479 # Process content-disposition header
480 cdisp, pdict = "", {}
Raymond Hettinger54f02222002-06-01 14:18:47 +0000481 if 'content-disposition' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000482 cdisp, pdict = parse_header(self.headers['content-disposition'])
483 self.disposition = cdisp
484 self.disposition_options = pdict
485 self.name = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000486 if 'name' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000487 self.name = pdict['name']
488 self.filename = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000489 if 'filename' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000490 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000491
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000492 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000493 #
494 # Honor any existing content-type header. But if there is no
495 # content-type header, use some sensible defaults. Assume
496 # outerboundary is "" at the outer level, but something non-false
497 # inside a multi-part. The default for an inner part is text/plain,
498 # but for an outer part it should be urlencoded. This should catch
499 # bogus clients which erroneously forget to include a content-type
500 # header.
501 #
502 # See below for what we do if there does exist a content-type header,
503 # but it happens to be something we don't understand.
Raymond Hettinger54f02222002-06-01 14:18:47 +0000504 if 'content-type' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000505 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000506 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000507 ctype, pdict = "text/plain", {}
508 else:
509 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000510 self.type = ctype
511 self.type_options = pdict
512 self.innerboundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000513 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000514 self.innerboundary = pdict['boundary']
515 clen = -1
Raymond Hettinger54f02222002-06-01 14:18:47 +0000516 if 'content-length' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000517 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000518 clen = int(self.headers['content-length'])
Skip Montanarodb5d1442002-03-23 05:50:17 +0000519 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000520 pass
521 if maxlen and clen > maxlen:
Collin Winterce36ad82007-08-30 01:19:48 +0000522 raise ValueError('Maximum content length exceeded')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000523 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000524
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000525 self.list = self.file = None
526 self.done = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000527 if ctype == 'application/x-www-form-urlencoded':
528 self.read_urlencoded()
529 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000530 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000531 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000532 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000533
534 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000535 """Return a printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000536 return "FieldStorage(%r, %r, %r)" % (
537 self.name, self.filename, self.value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000538
Guido van Rossum4061cbe2002-09-11 18:20:34 +0000539 def __iter__(self):
540 return iter(self.keys())
541
Guido van Rossum7aee3841996-03-07 18:00:44 +0000542 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000543 if name != 'value':
Collin Winterce36ad82007-08-30 01:19:48 +0000544 raise AttributeError(name)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000545 if self.file:
546 self.file.seek(0)
547 value = self.file.read()
548 self.file.seek(0)
549 elif self.list is not None:
550 value = self.list
551 else:
552 value = None
553 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000554
555 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000556 """Dictionary style indexing."""
557 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000558 raise TypeError("not indexable")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000559 found = []
560 for item in self.list:
561 if item.name == key: found.append(item)
562 if not found:
Collin Winterce36ad82007-08-30 01:19:48 +0000563 raise KeyError(key)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000564 if len(found) == 1:
565 return found[0]
566 else:
567 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000568
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000569 def getvalue(self, key, default=None):
570 """Dictionary style get() method, including 'value' lookup."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000571 if key in self:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000572 value = self[key]
573 if type(value) is type([]):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000574 return [x.value for x in value]
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000575 else:
576 return value.value
577 else:
578 return default
579
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000580 def getfirst(self, key, default=None):
581 """ Return the first value received."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000582 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000583 value = self[key]
584 if type(value) is type([]):
585 return value[0].value
586 else:
587 return value.value
588 else:
589 return default
590
591 def getlist(self, key):
592 """ Return list of received values."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000593 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000594 value = self[key]
595 if type(value) is type([]):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000596 return [x.value for x in value]
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000597 else:
598 return [value.value]
599 else:
600 return []
601
Guido van Rossum7aee3841996-03-07 18:00:44 +0000602 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000603 """Dictionary style keys() method."""
604 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000605 raise TypeError("not indexable")
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000606 return list(set(item.name for item in self.list))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000607
Raymond Hettinger54f02222002-06-01 14:18:47 +0000608 def __contains__(self, key):
609 """Dictionary style __contains__ method."""
610 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000611 raise TypeError("not indexable")
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000612 return any(item.name == key for item in self.list)
Raymond Hettinger54f02222002-06-01 14:18:47 +0000613
Guido van Rossum88b85d41997-01-11 19:21:33 +0000614 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000615 """Dictionary style len(x) support."""
616 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000617
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000618 def __nonzero__(self):
619 return bool(self.list)
620
Guido van Rossum7aee3841996-03-07 18:00:44 +0000621 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000622 """Internal: read data in query string format."""
623 qs = self.fp.read(self.length)
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000624 if self.qs_on_post:
625 qs += '&' + self.qs_on_post
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000626 self.list = list = []
627 for key, value in parse_qsl(qs, self.keep_blank_values,
628 self.strict_parsing):
629 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000630 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000631
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000632 FieldStorageClass = None
633
Guido van Rossumf5745001998-10-20 14:43:02 +0000634 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000635 """Internal: read a part that is itself multipart."""
Guido van Rossum2e441f72001-07-25 21:00:19 +0000636 ib = self.innerboundary
637 if not valid_boundary(ib):
Collin Winterce36ad82007-08-30 01:19:48 +0000638 raise ValueError('Invalid boundary in multipart form: %r' % (ib,))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000639 self.list = []
Benjamin Petersondcf97b92008-07-02 17:30:14 +0000640 if self.qs_on_post:
641 for key, value in parse_qsl(self.qs_on_post, self.keep_blank_values,
642 self.strict_parsing):
643 self.list.append(MiniFieldStorage(key, value))
644 FieldStorageClass = None
645
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000646 klass = self.FieldStorageClass or self.__class__
Barry Warsaw596097e2008-06-12 02:38:51 +0000647 parser = email.parser.FeedParser()
648 # Create bogus content-type header for proper multipart parsing
649 parser.feed('Content-Type: %s; boundary=%s\r\n\r\n' % (self.type, ib))
650 parser.feed(self.fp.read())
651 full_msg = parser.close()
652 # Get subparts
653 msgs = full_msg.get_payload()
654 for msg in msgs:
655 fp = StringIO(msg.get_payload())
656 part = klass(fp, msg, ib, environ, keep_blank_values,
657 strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000658 self.list.append(part)
659 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000660
661 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000662 """Internal: read an atomic part."""
663 if self.length >= 0:
664 self.read_binary()
665 self.skip_lines()
666 else:
667 self.read_lines()
668 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000669
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000670 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000671
672 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000673 """Internal: read binary data."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000674 self.file = self.make_file()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000675 todo = self.length
676 if todo >= 0:
677 while todo > 0:
678 data = self.fp.read(min(todo, self.bufsize))
679 if not data:
680 self.done = -1
681 break
682 self.file.write(data)
683 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000684
685 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000686 """Internal: read lines until EOF or outerboundary."""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000687 self.file = self.__file = StringIO()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000688 if self.outerboundary:
689 self.read_lines_to_outerboundary()
690 else:
691 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000692
Guido van Rossum52b8c292001-06-29 13:06:06 +0000693 def __write(self, line):
694 if self.__file is not None:
695 if self.__file.tell() + len(line) > 1000:
Guido van Rossuma1a68522007-08-28 03:11:34 +0000696 self.file = self.make_file()
697 data = self.__file.getvalue()
698 self.file.write(data)
Guido van Rossum52b8c292001-06-29 13:06:06 +0000699 self.__file = None
700 self.file.write(line)
701
Guido van Rossum7aee3841996-03-07 18:00:44 +0000702 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000703 """Internal: read lines until EOF."""
704 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000705 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000706 if not line:
707 self.done = -1
708 break
Guido van Rossum52b8c292001-06-29 13:06:06 +0000709 self.__write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000710
711 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000712 """Internal: read lines until outerboundary."""
713 next = "--" + self.outerboundary
714 last = next + "--"
715 delim = ""
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000716 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000717 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000718 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000719 if not line:
720 self.done = -1
721 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000722 if line[:2] == "--" and last_line_lfend:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000723 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000724 if strippedline == next:
725 break
726 if strippedline == last:
727 self.done = 1
728 break
729 odelim = delim
730 if line[-2:] == "\r\n":
731 delim = "\r\n"
732 line = line[:-2]
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000733 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000734 elif line[-1] == "\n":
735 delim = "\n"
736 line = line[:-1]
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000737 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000738 else:
739 delim = ""
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000740 last_line_lfend = False
Guido van Rossum52b8c292001-06-29 13:06:06 +0000741 self.__write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000742
743 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000744 """Internal: skip lines until outer boundary if defined."""
745 if not self.outerboundary or self.done:
746 return
747 next = "--" + self.outerboundary
748 last = next + "--"
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000749 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000750 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000751 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000752 if not line:
753 self.done = -1
754 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000755 if line[:2] == "--" and last_line_lfend:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000756 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000757 if strippedline == next:
758 break
759 if strippedline == last:
760 self.done = 1
761 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000762 last_line_lfend = line.endswith('\n')
Guido van Rossum7aee3841996-03-07 18:00:44 +0000763
Guido van Rossuma1a68522007-08-28 03:11:34 +0000764 def make_file(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000765 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000766
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000767 The file will be used as follows:
768 - data is written to it
769 - seek(0)
770 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +0000771
Guido van Rossuma1a68522007-08-28 03:11:34 +0000772 The file is always opened in text mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000773
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000774 This version opens a temporary file for reading and writing,
775 and immediately deletes (unlinks) it. The trick (on Unix!) is
776 that the file can still be used, but it can't be opened by
777 another process, and it will automatically be deleted when it
778 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000779
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000780 If you want a more permanent file, you derive a class which
781 overrides this method. If you want a visible temporary file
782 that is nevertheless automatically deleted when the script
783 terminates, try defining a __del__ method in a derived class
784 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000785
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000786 """
787 import tempfile
Guido van Rossum92bab812007-08-28 03:32:38 +0000788 return tempfile.TemporaryFile("w+", encoding="utf-8", newline="\n")
Tim Peters88869f92001-01-14 23:36:06 +0000789
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000790
Guido van Rossum72755611996-03-06 07:20:06 +0000791# Test/debug code
792# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +0000793
Guido van Rossum773ab271996-07-23 03:46:24 +0000794def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000795 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000796
Guido van Rossum7aee3841996-03-07 18:00:44 +0000797 Write minimal HTTP headers and dump all information provided to
798 the script in HTML form.
799
800 """
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000801 print("Content-type: text/html")
802 print()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000803 sys.stderr = sys.stdout
804 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000805 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000806 print_directory()
807 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000808 print_form(form)
809 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000810 print_environ_usage()
811 def f():
Georg Brandl7cae87c2006-09-06 06:51:57 +0000812 exec("testing print_exception() -- <I>italics?</I>")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000813 def g(f=f):
814 f()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000815 print("<H3>What follows is a test, not an actual exception:</H3>")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000816 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000817 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000818 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000819
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000820 print("<H1>Second try with a small maxlen...</H1>")
Guido van Rossum57d51f22000-09-16 21:16:01 +0000821
Guido van Rossumad164711997-05-13 19:03:23 +0000822 global maxlen
823 maxlen = 50
824 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000825 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000826 print_directory()
827 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000828 print_form(form)
829 print_environ(environ)
Guido van Rossumad164711997-05-13 19:03:23 +0000830 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000831 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +0000832
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000833def print_exception(type=None, value=None, tb=None, limit=None):
834 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000835 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000836 import traceback
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000837 print()
838 print("<H3>Traceback (most recent call last):</H3>")
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000839 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000840 traceback.format_exception_only(type, value)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000841 print("<PRE>%s<B>%s</B></PRE>" % (
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000842 escape("".join(list[:-1])),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000843 escape(list[-1]),
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000844 ))
Guido van Rossumf15d1591997-09-29 23:22:12 +0000845 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +0000846
Guido van Rossum773ab271996-07-23 03:46:24 +0000847def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000848 """Dump the shell environment as HTML."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000849 keys = sorted(environ.keys())
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000850 print()
851 print("<H3>Shell Environment:</H3>")
852 print("<DL>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000853 for key in keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000854 print("<DT>", escape(key), "<DD>", escape(environ[key]))
855 print("</DL>")
856 print()
Guido van Rossum72755611996-03-06 07:20:06 +0000857
858def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000859 """Dump the contents of a form as HTML."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000860 keys = sorted(form.keys())
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000861 print()
862 print("<H3>Form Contents:</H3>")
Guido van Rossum57d51f22000-09-16 21:16:01 +0000863 if not keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000864 print("<P>No form fields.")
865 print("<DL>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000866 for key in keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000867 print("<DT>" + escape(key) + ":", end=' ')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000868 value = form[key]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000869 print("<i>" + escape(repr(type(value))) + "</i>")
870 print("<DD>" + escape(repr(value)))
871 print("</DL>")
872 print()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000873
874def print_directory():
875 """Dump the current directory as HTML."""
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000876 print()
877 print("<H3>Current Working Directory:</H3>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000878 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000879 pwd = os.getcwd()
Guido van Rossumb940e112007-01-10 16:19:56 +0000880 except os.error as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000881 print("os.error:", escape(str(msg)))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000882 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000883 print(escape(pwd))
884 print()
Guido van Rossum9a22de11995-01-12 12:29:47 +0000885
Guido van Rossuma8738a51996-03-14 21:30:28 +0000886def print_arguments():
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000887 print()
888 print("<H3>Command Line Arguments:</H3>")
889 print()
890 print(sys.argv)
891 print()
Guido van Rossuma8738a51996-03-14 21:30:28 +0000892
Guido van Rossum9a22de11995-01-12 12:29:47 +0000893def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +0000894 """Dump a list of environment variables used by CGI as HTML."""
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000895 print("""
Guido van Rossum72755611996-03-06 07:20:06 +0000896<H3>These environment variables could have been set:</H3>
897<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +0000898<LI>AUTH_TYPE
899<LI>CONTENT_LENGTH
900<LI>CONTENT_TYPE
901<LI>DATE_GMT
902<LI>DATE_LOCAL
903<LI>DOCUMENT_NAME
904<LI>DOCUMENT_ROOT
905<LI>DOCUMENT_URI
906<LI>GATEWAY_INTERFACE
907<LI>LAST_MODIFIED
908<LI>PATH
909<LI>PATH_INFO
910<LI>PATH_TRANSLATED
911<LI>QUERY_STRING
912<LI>REMOTE_ADDR
913<LI>REMOTE_HOST
914<LI>REMOTE_IDENT
915<LI>REMOTE_USER
916<LI>REQUEST_METHOD
917<LI>SCRIPT_NAME
918<LI>SERVER_NAME
919<LI>SERVER_PORT
920<LI>SERVER_PROTOCOL
921<LI>SERVER_ROOT
922<LI>SERVER_SOFTWARE
923</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +0000924In addition, HTTP headers sent by the server may be passed in the
925environment as well. Here are some common variable names:
926<UL>
927<LI>HTTP_ACCEPT
928<LI>HTTP_CONNECTION
929<LI>HTTP_HOST
930<LI>HTTP_PRAGMA
931<LI>HTTP_REFERER
932<LI>HTTP_USER_AGENT
933</UL>
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000934""")
Guido van Rossum9a22de11995-01-12 12:29:47 +0000935
Guido van Rossum9a22de11995-01-12 12:29:47 +0000936
Guido van Rossum72755611996-03-06 07:20:06 +0000937# Utilities
938# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +0000939
Guido van Rossum64c66201997-07-19 20:11:53 +0000940def escape(s, quote=None):
Skip Montanaro97b2fa22005-08-02 02:50:25 +0000941 '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
942 If the optional flag quote is true, the quotation mark character (")
943 is also translated.'''
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000944 s = s.replace("&", "&amp;") # Must be done first!
945 s = s.replace("<", "&lt;")
946 s = s.replace(">", "&gt;")
Guido van Rossum64c66201997-07-19 20:11:53 +0000947 if quote:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000948 s = s.replace('"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000949 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +0000950
Guido van Rossum2e441f72001-07-25 21:00:19 +0000951def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
952 import re
953 return re.match(_vb_pattern, s)
Guido van Rossum9a22de11995-01-12 12:29:47 +0000954
Guido van Rossum72755611996-03-06 07:20:06 +0000955# Invoke mainline
956# ===============
957
958# Call test() when this file is run as a script (not imported as a module)
Tim Peters88869f92001-01-14 23:36:06 +0000959if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +0000960 test()