blob: cf0146f407274ee797cbd548daf8bbc404787420 [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
Jeremy Hyltonc253d9a2000-08-03 20:57:44 +000018# XXX Perhaps there should be a slimmed version that doesn't contain
19# all those backwards compatible and debugging classes and functions?
Guido van Rossum98d9fd32000-02-28 15:12:25 +000020
21# History
22# -------
Tim Peters88869f92001-01-14 23:36:06 +000023#
Guido van Rossum98d9fd32000-02-28 15:12:25 +000024# Michael McLay started this module. Steve Majewski changed the
25# interface to SvFormContentDict and FormContentDict. The multipart
26# parsing was inspired by code submitted by Andreas Paepcke. Guido van
27# Rossum rewrote, reformatted and documented the module and is currently
28# responsible for its maintenance.
Tim Peters88869f92001-01-14 23:36:06 +000029#
Guido van Rossum98d9fd32000-02-28 15:12:25 +000030
Guido van Rossum52b8c292001-06-29 13:06:06 +000031__version__ = "2.6"
Guido van Rossum0147db01996-03-09 03:16:04 +000032
Guido van Rossum72755611996-03-06 07:20:06 +000033
34# Imports
35# =======
36
Guido van Rossum72755611996-03-06 07:20:06 +000037import sys
38import os
Guido van Rossuma5e9fb61997-08-12 18:18:13 +000039import urllib
Guido van Rossuma5e9fb61997-08-12 18:18:13 +000040import mimetools
41import rfc822
Moshe Zadkaa1a4b592000-08-25 21:47:56 +000042import UserDict
Guido van Rossuma5e9fb61997-08-12 18:18:13 +000043from StringIO import StringIO
Guido van Rossum72755611996-03-06 07:20:06 +000044
Guido van Rossuma8423a92001-03-19 13:40:44 +000045__all__ = ["MiniFieldStorage", "FieldStorage", "FormContentDict",
46 "SvFormContentDict", "InterpFormContentDict", "FormContent",
47 "parse", "parse_qs", "parse_qsl", "parse_multipart",
48 "parse_header", "print_exception", "print_environ",
49 "print_form", "print_directory", "print_arguments",
50 "print_environ_usage", "escape"]
Guido van Rossumc204c701996-09-05 19:07:11 +000051
52# Logging support
53# ===============
54
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000055logfile = "" # Filename to log to, if not empty
56logfp = None # File object to log to, if not None
Guido van Rossumc204c701996-09-05 19:07:11 +000057
58def initlog(*allargs):
59 """Write a log message, if there is a log file.
60
61 Even though this function is called initlog(), you should always
62 use log(); log is a variable that is set either to initlog
63 (initially), to dolog (once the log file has been opened), or to
64 nolog (when logging is disabled).
65
66 The first argument is a format string; the remaining arguments (if
67 any) are arguments to the % operator, so e.g.
68 log("%s: %s", "a", "b")
69 will write "a: b" to the log file, followed by a newline.
70
71 If the global logfp is not None, it should be a file object to
72 which log data is written.
73
74 If the global logfp is None, the global logfile may be a string
75 giving a filename to open, in append mode. This file should be
76 world writable!!! If the file can't be opened, logging is
77 silently disabled (since there is no safe place where we could
78 send an error message).
79
80 """
81 global logfp, log
82 if logfile and not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000083 try:
84 logfp = open(logfile, "a")
85 except IOError:
86 pass
Guido van Rossumc204c701996-09-05 19:07:11 +000087 if not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000088 log = nolog
Guido van Rossumc204c701996-09-05 19:07:11 +000089 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000090 log = dolog
Guido van Rossumc204c701996-09-05 19:07:11 +000091 apply(log, allargs)
92
93def dolog(fmt, *args):
94 """Write a log message to the log file. See initlog() for docs."""
95 logfp.write(fmt%args + "\n")
96
97def nolog(*allargs):
98 """Dummy function, assigned to log when logging is disabled."""
99 pass
100
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000101log = initlog # The current logging function
Guido van Rossumc204c701996-09-05 19:07:11 +0000102
103
Guido van Rossum72755611996-03-06 07:20:06 +0000104# Parsing functions
105# =================
106
Guido van Rossumad164711997-05-13 19:03:23 +0000107# Maximum input we will accept when REQUEST_METHOD is POST
108# 0 ==> unlimited input
109maxlen = 0
110
Guido van Rossume08c04c1996-11-11 19:29:11 +0000111def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum773ab271996-07-23 03:46:24 +0000112 """Parse a query in the environment or from a file (default stdin)
113
114 Arguments, all optional:
115
116 fp : file pointer; default: sys.stdin
117
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000118 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000119
120 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000121 URL encoded forms should be treated as blank strings.
122 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000123 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000124 blank values are to be ignored and treated as if they were
125 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000126
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000127 strict_parsing: flag indicating what to do with parsing errors.
128 If false (the default), errors are silently ignored.
129 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000130 """
Raymond Hettingera1449002002-05-31 23:54:44 +0000131 if fp is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000132 fp = sys.stdin
Raymond Hettinger54f02222002-06-01 14:18:47 +0000133 if not 'REQUEST_METHOD' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000134 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
Guido van Rossum7aee3841996-03-07 18:00:44 +0000135 if environ['REQUEST_METHOD'] == 'POST':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000136 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
137 if ctype == 'multipart/form-data':
138 return parse_multipart(fp, pdict)
139 elif ctype == 'application/x-www-form-urlencoded':
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000140 clength = int(environ['CONTENT_LENGTH'])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000141 if maxlen and clength > maxlen:
142 raise ValueError, 'Maximum content length exceeded'
143 qs = fp.read(clength)
144 else:
145 qs = '' # Unknown content-type
Raymond Hettinger54f02222002-06-01 14:18:47 +0000146 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000147 if qs: qs = qs + '&'
148 qs = qs + environ['QUERY_STRING']
Tim Peters88869f92001-01-14 23:36:06 +0000149 elif sys.argv[1:]:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000150 if qs: qs = qs + '&'
151 qs = qs + sys.argv[1]
152 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Raymond Hettinger54f02222002-06-01 14:18:47 +0000153 elif 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000154 qs = environ['QUERY_STRING']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000155 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000156 if sys.argv[1:]:
157 qs = sys.argv[1]
158 else:
159 qs = ""
160 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossume08c04c1996-11-11 19:29:11 +0000161 return parse_qs(qs, keep_blank_values, strict_parsing)
Guido van Rossume7808771995-08-07 20:12:09 +0000162
163
Guido van Rossume08c04c1996-11-11 19:29:11 +0000164def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
165 """Parse a query given as a string argument.
Guido van Rossum773ab271996-07-23 03:46:24 +0000166
167 Arguments:
168
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000169 qs: URL-encoded query string to be parsed
Guido van Rossum773ab271996-07-23 03:46:24 +0000170
171 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000172 URL encoded queries should be treated as blank strings.
173 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000174 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000175 blank values are to be ignored and treated as if they were
176 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000177
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000178 strict_parsing: flag indicating what to do with parsing errors.
179 If false (the default), errors are silently ignored.
180 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000181 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000182 dict = {}
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000183 for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000184 if name in dict:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000185 dict[name].append(value)
186 else:
187 dict[name] = [value]
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000188 return dict
189
190def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
191 """Parse a query given as a string argument.
192
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000193 Arguments:
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000194
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000195 qs: URL-encoded query string to be parsed
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000196
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000197 keep_blank_values: flag indicating whether blank values in
198 URL encoded queries should be treated as blank strings. A
199 true value indicates that blanks should be retained as blank
200 strings. The default false value indicates that blank values
201 are to be ignored and treated as if they were not included.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000202
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000203 strict_parsing: flag indicating what to do with parsing errors. If
204 false (the default), errors are silently ignored. If true,
Tim Peters88869f92001-01-14 23:36:06 +0000205 errors raise a ValueError exception.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000206
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000207 Returns a list, as G-d intended.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000208 """
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000209 pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
210 r = []
211 for name_value in pairs:
212 nv = name_value.split('=', 1)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000213 if len(nv) != 2:
214 if strict_parsing:
215 raise ValueError, "bad query field: %s" % `name_value`
216 continue
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000217 if len(nv[1]) or keep_blank_values:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000218 name = urllib.unquote(nv[0].replace('+', ' '))
219 value = urllib.unquote(nv[1].replace('+', ' '))
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000220 r.append((name, value))
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000221
222 return r
Guido van Rossum9a22de11995-01-12 12:29:47 +0000223
224
Guido van Rossum0147db01996-03-09 03:16:04 +0000225def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000226 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000227
Guido van Rossum7aee3841996-03-07 18:00:44 +0000228 Arguments:
229 fp : input file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000230 pdict: dictionary containing other parameters of conten-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000231
Tim Peters88869f92001-01-14 23:36:06 +0000232 Returns a dictionary just like parse_qs(): keys are the field names, each
233 value is a list of values for that field. This is easy to use but not
234 much good if you are expecting megabytes to be uploaded -- in that case,
235 use the FieldStorage class instead which is much more flexible. Note
236 that content-type is the raw, unparsed contents of the content-type
Guido van Rossum0147db01996-03-09 03:16:04 +0000237 header.
Tim Peters88869f92001-01-14 23:36:06 +0000238
239 XXX This does not parse nested multipart parts -- use FieldStorage for
Guido van Rossum0147db01996-03-09 03:16:04 +0000240 that.
Tim Peters88869f92001-01-14 23:36:06 +0000241
242 XXX This should really be subsumed by FieldStorage altogether -- no
Guido van Rossum0147db01996-03-09 03:16:04 +0000243 point in having two implementations of the same parsing algorithm.
Guido van Rossum72755611996-03-06 07:20:06 +0000244
Guido van Rossum7aee3841996-03-07 18:00:44 +0000245 """
Guido van Rossum2e441f72001-07-25 21:00:19 +0000246 boundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000247 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000248 boundary = pdict['boundary']
Guido van Rossum2e441f72001-07-25 21:00:19 +0000249 if not valid_boundary(boundary):
Tim Petersab9ba272001-08-09 21:40:30 +0000250 raise ValueError, ('Invalid boundary in multipart form: %s'
Fred Drake4c85da42001-10-13 18:38:53 +0000251 % `boundary`)
Tim Petersab9ba272001-08-09 21:40:30 +0000252
Guido van Rossum7aee3841996-03-07 18:00:44 +0000253 nextpart = "--" + boundary
254 lastpart = "--" + boundary + "--"
255 partdict = {}
256 terminator = ""
257
258 while terminator != lastpart:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000259 bytes = -1
260 data = None
261 if terminator:
262 # At start of next part. Read headers first.
263 headers = mimetools.Message(fp)
264 clength = headers.getheader('content-length')
265 if clength:
266 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000267 bytes = int(clength)
268 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000269 pass
270 if bytes > 0:
271 if maxlen and bytes > maxlen:
272 raise ValueError, 'Maximum content length exceeded'
273 data = fp.read(bytes)
274 else:
275 data = ""
276 # Read lines until end of part.
277 lines = []
278 while 1:
279 line = fp.readline()
280 if not line:
281 terminator = lastpart # End outer loop
282 break
283 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000284 terminator = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000285 if terminator in (nextpart, lastpart):
286 break
287 lines.append(line)
288 # Done with part.
289 if data is None:
290 continue
291 if bytes < 0:
292 if lines:
293 # Strip final line terminator
294 line = lines[-1]
295 if line[-2:] == "\r\n":
296 line = line[:-2]
297 elif line[-1:] == "\n":
298 line = line[:-1]
299 lines[-1] = line
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000300 data = "".join(lines)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000301 line = headers['content-disposition']
302 if not line:
303 continue
304 key, params = parse_header(line)
305 if key != 'form-data':
306 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000307 if 'name' in params:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000308 name = params['name']
309 else:
310 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000311 if name in partdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000312 partdict[name].append(data)
313 else:
314 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000315
Guido van Rossum7aee3841996-03-07 18:00:44 +0000316 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000317
318
Guido van Rossum72755611996-03-06 07:20:06 +0000319def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000320 """Parse a Content-type like header.
321
322 Return the main content-type and a dictionary of options.
323
324 """
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000325 plist = map(lambda x: x.strip(), line.split(';'))
Raymond Hettinger46ac8eb2002-06-30 03:39:14 +0000326 key = plist.pop(0).lower()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000327 pdict = {}
328 for p in plist:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000329 i = p.find('=')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000330 if i >= 0:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000331 name = p[:i].strip().lower()
332 value = p[i+1:].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000333 if len(value) >= 2 and value[0] == value[-1] == '"':
334 value = value[1:-1]
335 pdict[name] = value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000336 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000337
338
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000339# Classes for field storage
340# =========================
341
342class MiniFieldStorage:
343
Guido van Rossum0147db01996-03-09 03:16:04 +0000344 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000345
Guido van Rossum7aee3841996-03-07 18:00:44 +0000346 # Dummy attributes
347 filename = None
348 list = None
349 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000350 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000351 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000352 disposition = None
353 disposition_options = {}
354 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000355
Guido van Rossum7aee3841996-03-07 18:00:44 +0000356 def __init__(self, name, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000357 """Constructor from field name and value."""
358 self.name = name
359 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000360 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000361
362 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000363 """Return printable representation."""
364 return "MiniFieldStorage(%s, %s)" % (`self.name`, `self.value`)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000365
366
367class FieldStorage:
368
Guido van Rossum7aee3841996-03-07 18:00:44 +0000369 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000370
Guido van Rossum7aee3841996-03-07 18:00:44 +0000371 This class provides naming, typing, files stored on disk, and
372 more. At the top level, it is accessible like a dictionary, whose
373 keys are the field names. (Note: None can occur as a field name.)
374 The items are either a Python list (if there's multiple values) or
375 another FieldStorage or MiniFieldStorage object. If it's a single
376 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000377
Guido van Rossum7aee3841996-03-07 18:00:44 +0000378 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000379
Guido van Rossum7aee3841996-03-07 18:00:44 +0000380 filename: the filename, if specified; otherwise None; this is the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000381 client side filename, *not* the file name on which it is
382 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000383
Guido van Rossum7aee3841996-03-07 18:00:44 +0000384 value: the value as a *string*; for file uploads, this
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000385 transparently reads the file every time you request the value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000386
387 file: the file(-like) object from which you can read the data;
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000388 None if the data is stored a simple string
Guido van Rossum7aee3841996-03-07 18:00:44 +0000389
390 type: the content-type, or None if not specified
391
392 type_options: dictionary of options specified on the content-type
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000393 line
Guido van Rossum7aee3841996-03-07 18:00:44 +0000394
395 disposition: content-disposition, or None if not specified
396
397 disposition_options: dictionary of corresponding options
398
399 headers: a dictionary(-like) object (sometimes rfc822.Message or a
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000400 subclass thereof) containing *all* headers
Guido van Rossum7aee3841996-03-07 18:00:44 +0000401
402 The class is subclassable, mostly for the purpose of overriding
403 the make_file() method, which is called internally to come up with
404 a file open for reading and writing. This makes it possible to
405 override the default choice of storing all files in a temporary
406 directory and unlinking them as soon as they have been opened.
407
408 """
409
Guido van Rossum773ab271996-07-23 03:46:24 +0000410 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000411 environ=os.environ, keep_blank_values=0, strict_parsing=0):
412 """Constructor. Read multipart/* until last part.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000413
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000414 Arguments, all optional:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000415
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000416 fp : file pointer; default: sys.stdin
Guido van Rossumb1b4f941998-05-08 19:55:51 +0000417 (not used when the request method is GET)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000418
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000419 headers : header dictionary-like object; default:
420 taken from environ as per CGI spec
Guido van Rossum7aee3841996-03-07 18:00:44 +0000421
Guido van Rossum773ab271996-07-23 03:46:24 +0000422 outerboundary : terminating multipart boundary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000423 (for internal use only)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000424
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000425 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000426
427 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000428 URL encoded forms should be treated as blank strings.
429 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000430 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000431 blank values are to be ignored and treated as if they were
432 not included.
Guido van Rossum773ab271996-07-23 03:46:24 +0000433
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000434 strict_parsing: flag indicating what to do with parsing errors.
435 If false (the default), errors are silently ignored.
436 If true, errors raise a ValueError exception.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000437
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000438 """
439 method = 'GET'
440 self.keep_blank_values = keep_blank_values
441 self.strict_parsing = strict_parsing
Raymond Hettinger54f02222002-06-01 14:18:47 +0000442 if 'REQUEST_METHOD' in environ:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000443 method = environ['REQUEST_METHOD'].upper()
Guido van Rossum01852831998-06-25 02:40:17 +0000444 if method == 'GET' or method == 'HEAD':
Raymond Hettinger54f02222002-06-01 14:18:47 +0000445 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000446 qs = environ['QUERY_STRING']
447 elif sys.argv[1:]:
448 qs = sys.argv[1]
449 else:
450 qs = ""
451 fp = StringIO(qs)
452 if headers is None:
453 headers = {'content-type':
454 "application/x-www-form-urlencoded"}
455 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000456 headers = {}
457 if method == 'POST':
458 # Set default content-type for POST to what's traditional
459 headers['content-type'] = "application/x-www-form-urlencoded"
Raymond Hettinger54f02222002-06-01 14:18:47 +0000460 if 'CONTENT_TYPE' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000461 headers['content-type'] = environ['CONTENT_TYPE']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000462 if 'CONTENT_LENGTH' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000463 headers['content-length'] = environ['CONTENT_LENGTH']
464 self.fp = fp or sys.stdin
465 self.headers = headers
466 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000467
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000468 # Process content-disposition header
469 cdisp, pdict = "", {}
Raymond Hettinger54f02222002-06-01 14:18:47 +0000470 if 'content-disposition' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000471 cdisp, pdict = parse_header(self.headers['content-disposition'])
472 self.disposition = cdisp
473 self.disposition_options = pdict
474 self.name = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000475 if 'name' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000476 self.name = pdict['name']
477 self.filename = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000478 if 'filename' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000479 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000480
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000481 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000482 #
483 # Honor any existing content-type header. But if there is no
484 # content-type header, use some sensible defaults. Assume
485 # outerboundary is "" at the outer level, but something non-false
486 # inside a multi-part. The default for an inner part is text/plain,
487 # but for an outer part it should be urlencoded. This should catch
488 # bogus clients which erroneously forget to include a content-type
489 # header.
490 #
491 # See below for what we do if there does exist a content-type header,
492 # but it happens to be something we don't understand.
Raymond Hettinger54f02222002-06-01 14:18:47 +0000493 if 'content-type' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000494 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000495 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000496 ctype, pdict = "text/plain", {}
497 else:
498 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000499 self.type = ctype
500 self.type_options = pdict
501 self.innerboundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000502 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000503 self.innerboundary = pdict['boundary']
504 clen = -1
Raymond Hettinger54f02222002-06-01 14:18:47 +0000505 if 'content-length' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000506 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000507 clen = int(self.headers['content-length'])
Skip Montanarodb5d1442002-03-23 05:50:17 +0000508 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000509 pass
510 if maxlen and clen > maxlen:
511 raise ValueError, 'Maximum content length exceeded'
512 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000513
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000514 self.list = self.file = None
515 self.done = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000516 if ctype == 'application/x-www-form-urlencoded':
517 self.read_urlencoded()
518 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000519 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000520 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000521 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000522
523 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000524 """Return a printable representation."""
525 return "FieldStorage(%s, %s, %s)" % (
526 `self.name`, `self.filename`, `self.value`)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000527
Guido van Rossum4061cbe2002-09-11 18:20:34 +0000528 def __iter__(self):
529 return iter(self.keys())
530
Guido van Rossum7aee3841996-03-07 18:00:44 +0000531 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000532 if name != 'value':
533 raise AttributeError, name
534 if self.file:
535 self.file.seek(0)
536 value = self.file.read()
537 self.file.seek(0)
538 elif self.list is not None:
539 value = self.list
540 else:
541 value = None
542 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000543
544 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000545 """Dictionary style indexing."""
546 if self.list is None:
547 raise TypeError, "not indexable"
548 found = []
549 for item in self.list:
550 if item.name == key: found.append(item)
551 if not found:
552 raise KeyError, key
553 if len(found) == 1:
554 return found[0]
555 else:
556 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000557
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000558 def getvalue(self, key, default=None):
559 """Dictionary style get() method, including 'value' lookup."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000560 if key in self:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000561 value = self[key]
562 if type(value) is type([]):
563 return map(lambda v: v.value, value)
564 else:
565 return value.value
566 else:
567 return default
568
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000569 def getfirst(self, key, default=None):
570 """ Return the first value received."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000571 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000572 value = self[key]
573 if type(value) is type([]):
574 return value[0].value
575 else:
576 return value.value
577 else:
578 return default
579
580 def getlist(self, key):
581 """ Return list of received values."""
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 map(lambda v: v.value, value)
586 else:
587 return [value.value]
588 else:
589 return []
590
Guido van Rossum7aee3841996-03-07 18:00:44 +0000591 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000592 """Dictionary style keys() method."""
593 if self.list is None:
594 raise TypeError, "not indexable"
595 keys = []
596 for item in self.list:
597 if item.name not in keys: keys.append(item.name)
598 return keys
Guido van Rossum7aee3841996-03-07 18:00:44 +0000599
Guido van Rossum0147db01996-03-09 03:16:04 +0000600 def has_key(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000601 """Dictionary style has_key() method."""
602 if self.list is None:
603 raise TypeError, "not indexable"
604 for item in self.list:
Tim Petersbc0e9102002-04-04 22:55:58 +0000605 if item.name == key: return True
606 return False
Guido van Rossum0147db01996-03-09 03:16:04 +0000607
Raymond Hettinger54f02222002-06-01 14:18:47 +0000608 def __contains__(self, key):
609 """Dictionary style __contains__ method."""
610 if self.list is None:
611 raise TypeError, "not indexable"
612 for item in self.list:
613 if item.name == key: return True
614 return False
615
Guido van Rossum88b85d41997-01-11 19:21:33 +0000616 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000617 """Dictionary style len(x) support."""
618 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000619
Guido van Rossum7aee3841996-03-07 18:00:44 +0000620 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000621 """Internal: read data in query string format."""
622 qs = self.fp.read(self.length)
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000623 self.list = list = []
624 for key, value in parse_qsl(qs, self.keep_blank_values,
625 self.strict_parsing):
626 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000627 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000628
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000629 FieldStorageClass = None
630
Guido van Rossumf5745001998-10-20 14:43:02 +0000631 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000632 """Internal: read a part that is itself multipart."""
Guido van Rossum2e441f72001-07-25 21:00:19 +0000633 ib = self.innerboundary
634 if not valid_boundary(ib):
Tim Petersab9ba272001-08-09 21:40:30 +0000635 raise ValueError, ('Invalid boundary in multipart form: %s'
Guido van Rossum2e441f72001-07-25 21:00:19 +0000636 % `ib`)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000637 self.list = []
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000638 klass = self.FieldStorageClass or self.__class__
Guido van Rossum2e441f72001-07-25 21:00:19 +0000639 part = klass(self.fp, {}, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000640 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000641 # Throw first part away
642 while not part.done:
643 headers = rfc822.Message(self.fp)
Guido van Rossum2e441f72001-07-25 21:00:19 +0000644 part = klass(self.fp, headers, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000645 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000646 self.list.append(part)
647 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000648
649 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000650 """Internal: read an atomic part."""
651 if self.length >= 0:
652 self.read_binary()
653 self.skip_lines()
654 else:
655 self.read_lines()
656 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000657
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000658 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000659
660 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000661 """Internal: read binary data."""
662 self.file = self.make_file('b')
663 todo = self.length
664 if todo >= 0:
665 while todo > 0:
666 data = self.fp.read(min(todo, self.bufsize))
667 if not data:
668 self.done = -1
669 break
670 self.file.write(data)
671 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000672
673 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000674 """Internal: read lines until EOF or outerboundary."""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000675 self.file = self.__file = StringIO()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000676 if self.outerboundary:
677 self.read_lines_to_outerboundary()
678 else:
679 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000680
Guido van Rossum52b8c292001-06-29 13:06:06 +0000681 def __write(self, line):
682 if self.__file is not None:
683 if self.__file.tell() + len(line) > 1000:
684 self.file = self.make_file('')
685 self.file.write(self.__file.getvalue())
686 self.__file = None
687 self.file.write(line)
688
Guido van Rossum7aee3841996-03-07 18:00:44 +0000689 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000690 """Internal: read lines until EOF."""
691 while 1:
692 line = self.fp.readline()
693 if not line:
694 self.done = -1
695 break
Guido van Rossum52b8c292001-06-29 13:06:06 +0000696 self.__write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000697
698 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000699 """Internal: read lines until outerboundary."""
700 next = "--" + self.outerboundary
701 last = next + "--"
702 delim = ""
703 while 1:
704 line = self.fp.readline()
705 if not line:
706 self.done = -1
707 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000708 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000709 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000710 if strippedline == next:
711 break
712 if strippedline == last:
713 self.done = 1
714 break
715 odelim = delim
716 if line[-2:] == "\r\n":
717 delim = "\r\n"
718 line = line[:-2]
719 elif line[-1] == "\n":
720 delim = "\n"
721 line = line[:-1]
722 else:
723 delim = ""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000724 self.__write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000725
726 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000727 """Internal: skip lines until outer boundary if defined."""
728 if not self.outerboundary or self.done:
729 return
730 next = "--" + self.outerboundary
731 last = next + "--"
732 while 1:
733 line = self.fp.readline()
734 if not line:
735 self.done = -1
736 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000737 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000738 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000739 if strippedline == next:
740 break
741 if strippedline == last:
742 self.done = 1
743 break
Guido van Rossum7aee3841996-03-07 18:00:44 +0000744
Guido van Rossuma5e9fb61997-08-12 18:18:13 +0000745 def make_file(self, binary=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000746 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000747
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000748 The file will be used as follows:
749 - data is written to it
750 - seek(0)
751 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +0000752
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000753 The 'binary' argument is unused -- the file is always opened
754 in binary mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000755
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000756 This version opens a temporary file for reading and writing,
757 and immediately deletes (unlinks) it. The trick (on Unix!) is
758 that the file can still be used, but it can't be opened by
759 another process, and it will automatically be deleted when it
760 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000761
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000762 If you want a more permanent file, you derive a class which
763 overrides this method. If you want a visible temporary file
764 that is nevertheless automatically deleted when the script
765 terminates, try defining a __del__ method in a derived class
766 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000767
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000768 """
769 import tempfile
770 return tempfile.TemporaryFile("w+b")
Tim Peters88869f92001-01-14 23:36:06 +0000771
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000772
773
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000774# Backwards Compatibility Classes
775# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +0000776
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000777class FormContentDict(UserDict.UserDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000778 """Form content as dictionary with a list of values per field.
Guido van Rossum72755611996-03-06 07:20:06 +0000779
Guido van Rossum7aee3841996-03-07 18:00:44 +0000780 form = FormContentDict()
781
782 form[key] -> [value, value, ...]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000783 key in form -> Boolean
Guido van Rossum7aee3841996-03-07 18:00:44 +0000784 form.keys() -> [key, key, ...]
785 form.values() -> [[val, val, ...], [val, val, ...], ...]
786 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
787 form.dict == {key: [val, val, ...], ...}
788
789 """
Guido van Rossum773ab271996-07-23 03:46:24 +0000790 def __init__(self, environ=os.environ):
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000791 self.dict = self.data = parse(environ=environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000792 self.query_string = environ['QUERY_STRING']
Guido van Rossum9a22de11995-01-12 12:29:47 +0000793
794
Guido van Rossum9a22de11995-01-12 12:29:47 +0000795class SvFormContentDict(FormContentDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000796 """Form content as dictionary expecting a single value per field.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000797
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000798 If you only expect a single value for each field, then form[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000799 will return that single value. It will raise an IndexError if
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000800 that expectation is not true. If you expect a field to have
Guido van Rossum7aee3841996-03-07 18:00:44 +0000801 possible multiple values, than you can use form.getlist(key) to
802 get all of the values. values() and items() are a compromise:
803 they return single strings where there is a single value, and
804 lists of strings otherwise.
805
806 """
807 def __getitem__(self, key):
Tim Peters88869f92001-01-14 23:36:06 +0000808 if len(self.dict[key]) > 1:
809 raise IndexError, 'expecting a single value'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000810 return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000811 def getlist(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000812 return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000813 def values(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000814 result = []
815 for value in self.dict.values():
816 if len(value) == 1:
817 result.append(value[0])
818 else: result.append(value)
819 return result
Guido van Rossum7aee3841996-03-07 18:00:44 +0000820 def items(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000821 result = []
822 for key, value in self.dict.items():
823 if len(value) == 1:
824 result.append((key, value[0]))
825 else: result.append((key, value))
826 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000827
828
Guido van Rossum9a22de11995-01-12 12:29:47 +0000829class InterpFormContentDict(SvFormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000830 """This class is present for backwards compatibility only."""
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000831 def __getitem__(self, key):
832 v = SvFormContentDict.__getitem__(self, key)
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000833 if v[0] in '0123456789+-.':
834 try: return int(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000835 except ValueError:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000836 try: return float(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000837 except ValueError: pass
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000838 return v.strip()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000839 def values(self):
840 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000841 for key in self.keys():
842 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000843 result.append(self[key])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000844 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000845 result.append(self.dict[key])
846 return result
847 def items(self):
848 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000849 for key in self.keys():
850 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000851 result.append((key, self[key]))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000852 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000853 result.append((key, self.dict[key]))
854 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000855
856
Guido van Rossum9a22de11995-01-12 12:29:47 +0000857class FormContent(FormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000858 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +0000859 def values(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000860 if key in self.dict :return self.dict[key]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000861 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000862 def indexed_value(self, key, location):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000863 if key in self.dict:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000864 if len(self.dict[key]) > location:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000865 return self.dict[key][location]
866 else: return None
867 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000868 def value(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000869 if key in self.dict: return self.dict[key][0]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000870 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000871 def length(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000872 return len(self.dict[key])
Guido van Rossum0147db01996-03-09 03:16:04 +0000873 def stripped(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000874 if key in self.dict: return self.dict[key][0].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000875 else: return None
Guido van Rossum7aee3841996-03-07 18:00:44 +0000876 def pars(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000877 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000878
879
Guido van Rossum72755611996-03-06 07:20:06 +0000880# Test/debug code
881# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +0000882
Guido van Rossum773ab271996-07-23 03:46:24 +0000883def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000884 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000885
Guido van Rossum7aee3841996-03-07 18:00:44 +0000886 Write minimal HTTP headers and dump all information provided to
887 the script in HTML form.
888
889 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000890 print "Content-type: text/html"
891 print
892 sys.stderr = sys.stdout
893 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000894 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000895 print_directory()
896 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000897 print_form(form)
898 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000899 print_environ_usage()
900 def f():
901 exec "testing print_exception() -- <I>italics?</I>"
902 def g(f=f):
903 f()
904 print "<H3>What follows is a test, not an actual exception:</H3>"
905 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000906 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000907 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000908
Guido van Rossum57d51f22000-09-16 21:16:01 +0000909 print "<H1>Second try with a small maxlen...</H1>"
910
Guido van Rossumad164711997-05-13 19:03:23 +0000911 global maxlen
912 maxlen = 50
913 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000914 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000915 print_directory()
916 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000917 print_form(form)
918 print_environ(environ)
Guido van Rossumad164711997-05-13 19:03:23 +0000919 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000920 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +0000921
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000922def print_exception(type=None, value=None, tb=None, limit=None):
923 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000924 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000925 import traceback
926 print
Guido van Rossum7dd06962000-12-27 19:12:58 +0000927 print "<H3>Traceback (most recent call last):</H3>"
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000928 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000929 traceback.format_exception_only(type, value)
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000930 print "<PRE>%s<B>%s</B></PRE>" % (
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000931 escape("".join(list[:-1])),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000932 escape(list[-1]),
933 )
Guido van Rossumf15d1591997-09-29 23:22:12 +0000934 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +0000935
Guido van Rossum773ab271996-07-23 03:46:24 +0000936def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000937 """Dump the shell environment as HTML."""
938 keys = environ.keys()
939 keys.sort()
940 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000941 print "<H3>Shell Environment:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000942 print "<DL>"
943 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000944 print "<DT>", escape(key), "<DD>", escape(environ[key])
Tim Peters88869f92001-01-14 23:36:06 +0000945 print "</DL>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000946 print
Guido van Rossum72755611996-03-06 07:20:06 +0000947
948def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000949 """Dump the contents of a form as HTML."""
950 keys = form.keys()
951 keys.sort()
952 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000953 print "<H3>Form Contents:</H3>"
Guido van Rossum57d51f22000-09-16 21:16:01 +0000954 if not keys:
955 print "<P>No form fields."
Guido van Rossum7aee3841996-03-07 18:00:44 +0000956 print "<DL>"
957 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000958 print "<DT>" + escape(key) + ":",
959 value = form[key]
960 print "<i>" + escape(`type(value)`) + "</i>"
961 print "<DD>" + escape(`value`)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000962 print "</DL>"
963 print
964
965def print_directory():
966 """Dump the current directory as HTML."""
967 print
968 print "<H3>Current Working Directory:</H3>"
969 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000970 pwd = os.getcwd()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000971 except os.error, msg:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000972 print "os.error:", escape(str(msg))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000973 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000974 print escape(pwd)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000975 print
Guido van Rossum9a22de11995-01-12 12:29:47 +0000976
Guido van Rossuma8738a51996-03-14 21:30:28 +0000977def print_arguments():
978 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000979 print "<H3>Command Line Arguments:</H3>"
Guido van Rossuma8738a51996-03-14 21:30:28 +0000980 print
981 print sys.argv
982 print
983
Guido van Rossum9a22de11995-01-12 12:29:47 +0000984def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +0000985 """Dump a list of environment variables used by CGI as HTML."""
986 print """
Guido van Rossum72755611996-03-06 07:20:06 +0000987<H3>These environment variables could have been set:</H3>
988<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +0000989<LI>AUTH_TYPE
990<LI>CONTENT_LENGTH
991<LI>CONTENT_TYPE
992<LI>DATE_GMT
993<LI>DATE_LOCAL
994<LI>DOCUMENT_NAME
995<LI>DOCUMENT_ROOT
996<LI>DOCUMENT_URI
997<LI>GATEWAY_INTERFACE
998<LI>LAST_MODIFIED
999<LI>PATH
1000<LI>PATH_INFO
1001<LI>PATH_TRANSLATED
1002<LI>QUERY_STRING
1003<LI>REMOTE_ADDR
1004<LI>REMOTE_HOST
1005<LI>REMOTE_IDENT
1006<LI>REMOTE_USER
1007<LI>REQUEST_METHOD
1008<LI>SCRIPT_NAME
1009<LI>SERVER_NAME
1010<LI>SERVER_PORT
1011<LI>SERVER_PROTOCOL
1012<LI>SERVER_ROOT
1013<LI>SERVER_SOFTWARE
1014</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001015In addition, HTTP headers sent by the server may be passed in the
1016environment as well. Here are some common variable names:
1017<UL>
1018<LI>HTTP_ACCEPT
1019<LI>HTTP_CONNECTION
1020<LI>HTTP_HOST
1021<LI>HTTP_PRAGMA
1022<LI>HTTP_REFERER
1023<LI>HTTP_USER_AGENT
1024</UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001025"""
1026
Guido van Rossum9a22de11995-01-12 12:29:47 +00001027
Guido van Rossum72755611996-03-06 07:20:06 +00001028# Utilities
1029# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001030
Guido van Rossum64c66201997-07-19 20:11:53 +00001031def escape(s, quote=None):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001032 """Replace special characters '&', '<' and '>' by SGML entities."""
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001033 s = s.replace("&", "&amp;") # Must be done first!
1034 s = s.replace("<", "&lt;")
1035 s = s.replace(">", "&gt;")
Guido van Rossum64c66201997-07-19 20:11:53 +00001036 if quote:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001037 s = s.replace('"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +00001038 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001039
Guido van Rossum2e441f72001-07-25 21:00:19 +00001040def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
1041 import re
1042 return re.match(_vb_pattern, s)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001043
Guido van Rossum72755611996-03-06 07:20:06 +00001044# Invoke mainline
1045# ===============
1046
1047# Call test() when this file is run as a script (not imported as a module)
Tim Peters88869f92001-01-14 23:36:06 +00001048if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001049 test()