blob: db91ec6d2e445ff8d392f306acfebbba0ca128d9 [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 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000131 if not fp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000132 fp = sys.stdin
Guido van Rossum7aee3841996-03-07 18:00:44 +0000133 if not environ.has_key('REQUEST_METHOD'):
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
Tim Peters88869f92001-01-14 23:36:06 +0000146 if environ.has_key('QUERY_STRING'):
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
Guido van Rossum7aee3841996-03-07 18:00:44 +0000153 elif environ.has_key('QUERY_STRING'):
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):
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000184 if dict.has_key(name):
185 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 = ""
Guido van Rossum7aee3841996-03-07 18:00:44 +0000247 if pdict.has_key('boundary'):
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
307 if params.has_key('name'):
308 name = params['name']
309 else:
310 continue
311 if partdict.has_key(name):
312 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(';'))
326 key = plist[0].lower()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000327 del plist[0]
328 pdict = {}
329 for p in plist:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000330 i = p.find('=')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000331 if i >= 0:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000332 name = p[:i].strip().lower()
333 value = p[i+1:].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000334 if len(value) >= 2 and value[0] == value[-1] == '"':
335 value = value[1:-1]
336 pdict[name] = value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000337 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000338
339
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000340# Classes for field storage
341# =========================
342
343class MiniFieldStorage:
344
Guido van Rossum0147db01996-03-09 03:16:04 +0000345 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000346
Guido van Rossum7aee3841996-03-07 18:00:44 +0000347 # Dummy attributes
348 filename = None
349 list = None
350 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000351 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000352 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000353 disposition = None
354 disposition_options = {}
355 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000356
Guido van Rossum7aee3841996-03-07 18:00:44 +0000357 def __init__(self, name, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000358 """Constructor from field name and value."""
359 self.name = name
360 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000361 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000362
363 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000364 """Return printable representation."""
365 return "MiniFieldStorage(%s, %s)" % (`self.name`, `self.value`)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000366
367
368class FieldStorage:
369
Guido van Rossum7aee3841996-03-07 18:00:44 +0000370 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000371
Guido van Rossum7aee3841996-03-07 18:00:44 +0000372 This class provides naming, typing, files stored on disk, and
373 more. At the top level, it is accessible like a dictionary, whose
374 keys are the field names. (Note: None can occur as a field name.)
375 The items are either a Python list (if there's multiple values) or
376 another FieldStorage or MiniFieldStorage object. If it's a single
377 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000378
Guido van Rossum7aee3841996-03-07 18:00:44 +0000379 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000380
Guido van Rossum7aee3841996-03-07 18:00:44 +0000381 filename: the filename, if specified; otherwise None; this is the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000382 client side filename, *not* the file name on which it is
383 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000384
Guido van Rossum7aee3841996-03-07 18:00:44 +0000385 value: the value as a *string*; for file uploads, this
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000386 transparently reads the file every time you request the value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000387
388 file: the file(-like) object from which you can read the data;
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000389 None if the data is stored a simple string
Guido van Rossum7aee3841996-03-07 18:00:44 +0000390
391 type: the content-type, or None if not specified
392
393 type_options: dictionary of options specified on the content-type
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000394 line
Guido van Rossum7aee3841996-03-07 18:00:44 +0000395
396 disposition: content-disposition, or None if not specified
397
398 disposition_options: dictionary of corresponding options
399
400 headers: a dictionary(-like) object (sometimes rfc822.Message or a
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000401 subclass thereof) containing *all* headers
Guido van Rossum7aee3841996-03-07 18:00:44 +0000402
403 The class is subclassable, mostly for the purpose of overriding
404 the make_file() method, which is called internally to come up with
405 a file open for reading and writing. This makes it possible to
406 override the default choice of storing all files in a temporary
407 directory and unlinking them as soon as they have been opened.
408
409 """
410
Guido van Rossum773ab271996-07-23 03:46:24 +0000411 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000412 environ=os.environ, keep_blank_values=0, strict_parsing=0):
413 """Constructor. Read multipart/* until last part.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000414
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000415 Arguments, all optional:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000416
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000417 fp : file pointer; default: sys.stdin
Guido van Rossumb1b4f941998-05-08 19:55:51 +0000418 (not used when the request method is GET)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000419
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000420 headers : header dictionary-like object; default:
421 taken from environ as per CGI spec
Guido van Rossum7aee3841996-03-07 18:00:44 +0000422
Guido van Rossum773ab271996-07-23 03:46:24 +0000423 outerboundary : terminating multipart boundary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000424 (for internal use only)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000425
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000426 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000427
428 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000429 URL encoded forms should be treated as blank strings.
430 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000431 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000432 blank values are to be ignored and treated as if they were
433 not included.
Guido van Rossum773ab271996-07-23 03:46:24 +0000434
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000435 strict_parsing: flag indicating what to do with parsing errors.
436 If false (the default), errors are silently ignored.
437 If true, errors raise a ValueError exception.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000438
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000439 """
440 method = 'GET'
441 self.keep_blank_values = keep_blank_values
442 self.strict_parsing = strict_parsing
443 if environ.has_key('REQUEST_METHOD'):
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000444 method = environ['REQUEST_METHOD'].upper()
Guido van Rossum01852831998-06-25 02:40:17 +0000445 if method == 'GET' or method == 'HEAD':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000446 if environ.has_key('QUERY_STRING'):
447 qs = environ['QUERY_STRING']
448 elif sys.argv[1:]:
449 qs = sys.argv[1]
450 else:
451 qs = ""
452 fp = StringIO(qs)
453 if headers is None:
454 headers = {'content-type':
455 "application/x-www-form-urlencoded"}
456 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000457 headers = {}
458 if method == 'POST':
459 # Set default content-type for POST to what's traditional
460 headers['content-type'] = "application/x-www-form-urlencoded"
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000461 if environ.has_key('CONTENT_TYPE'):
462 headers['content-type'] = environ['CONTENT_TYPE']
463 if environ.has_key('CONTENT_LENGTH'):
464 headers['content-length'] = environ['CONTENT_LENGTH']
465 self.fp = fp or sys.stdin
466 self.headers = headers
467 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000468
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000469 # Process content-disposition header
470 cdisp, pdict = "", {}
471 if self.headers.has_key('content-disposition'):
472 cdisp, pdict = parse_header(self.headers['content-disposition'])
473 self.disposition = cdisp
474 self.disposition_options = pdict
475 self.name = None
476 if pdict.has_key('name'):
477 self.name = pdict['name']
478 self.filename = None
479 if pdict.has_key('filename'):
480 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000481
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000482 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000483 #
484 # Honor any existing content-type header. But if there is no
485 # content-type header, use some sensible defaults. Assume
486 # outerboundary is "" at the outer level, but something non-false
487 # inside a multi-part. The default for an inner part is text/plain,
488 # but for an outer part it should be urlencoded. This should catch
489 # bogus clients which erroneously forget to include a content-type
490 # header.
491 #
492 # See below for what we do if there does exist a content-type header,
493 # but it happens to be something we don't understand.
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000494 if self.headers.has_key('content-type'):
495 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000496 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000497 ctype, pdict = "text/plain", {}
498 else:
499 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000500 self.type = ctype
501 self.type_options = pdict
502 self.innerboundary = ""
503 if pdict.has_key('boundary'):
504 self.innerboundary = pdict['boundary']
505 clen = -1
506 if self.headers.has_key('content-length'):
507 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000508 clen = int(self.headers['content-length'])
Skip Montanarodb5d1442002-03-23 05:50:17 +0000509 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000510 pass
511 if maxlen and clen > maxlen:
512 raise ValueError, 'Maximum content length exceeded'
513 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000514
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000515 self.list = self.file = None
516 self.done = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000517 if ctype == 'application/x-www-form-urlencoded':
518 self.read_urlencoded()
519 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000520 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000521 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000522 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000523
524 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000525 """Return a printable representation."""
526 return "FieldStorage(%s, %s, %s)" % (
527 `self.name`, `self.filename`, `self.value`)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000528
529 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000530 if name != 'value':
531 raise AttributeError, name
532 if self.file:
533 self.file.seek(0)
534 value = self.file.read()
535 self.file.seek(0)
536 elif self.list is not None:
537 value = self.list
538 else:
539 value = None
540 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000541
542 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000543 """Dictionary style indexing."""
544 if self.list is None:
545 raise TypeError, "not indexable"
546 found = []
547 for item in self.list:
548 if item.name == key: found.append(item)
549 if not found:
550 raise KeyError, key
551 if len(found) == 1:
552 return found[0]
553 else:
554 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000555
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000556 def getvalue(self, key, default=None):
557 """Dictionary style get() method, including 'value' lookup."""
558 if self.has_key(key):
559 value = self[key]
560 if type(value) is type([]):
561 return map(lambda v: v.value, value)
562 else:
563 return value.value
564 else:
565 return default
566
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000567 def getfirst(self, key, default=None):
568 """ Return the first value received."""
569 if self.has_key(key):
570 value = self[key]
571 if type(value) is type([]):
572 return value[0].value
573 else:
574 return value.value
575 else:
576 return default
577
578 def getlist(self, key):
579 """ Return list of received values."""
580 if self.has_key(key):
581 value = self[key]
582 if type(value) is type([]):
583 return map(lambda v: v.value, value)
584 else:
585 return [value.value]
586 else:
587 return []
588
Guido van Rossum7aee3841996-03-07 18:00:44 +0000589 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000590 """Dictionary style keys() method."""
591 if self.list is None:
592 raise TypeError, "not indexable"
593 keys = []
594 for item in self.list:
595 if item.name not in keys: keys.append(item.name)
596 return keys
Guido van Rossum7aee3841996-03-07 18:00:44 +0000597
Guido van Rossum0147db01996-03-09 03:16:04 +0000598 def has_key(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000599 """Dictionary style has_key() method."""
600 if self.list is None:
601 raise TypeError, "not indexable"
602 for item in self.list:
603 if item.name == key: return 1
604 return 0
Guido van Rossum0147db01996-03-09 03:16:04 +0000605
Guido van Rossum88b85d41997-01-11 19:21:33 +0000606 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000607 """Dictionary style len(x) support."""
608 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000609
Guido van Rossum7aee3841996-03-07 18:00:44 +0000610 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000611 """Internal: read data in query string format."""
612 qs = self.fp.read(self.length)
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000613 self.list = list = []
614 for key, value in parse_qsl(qs, self.keep_blank_values,
615 self.strict_parsing):
616 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000617 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000618
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000619 FieldStorageClass = None
620
Guido van Rossumf5745001998-10-20 14:43:02 +0000621 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000622 """Internal: read a part that is itself multipart."""
Guido van Rossum2e441f72001-07-25 21:00:19 +0000623 ib = self.innerboundary
624 if not valid_boundary(ib):
Tim Petersab9ba272001-08-09 21:40:30 +0000625 raise ValueError, ('Invalid boundary in multipart form: %s'
Guido van Rossum2e441f72001-07-25 21:00:19 +0000626 % `ib`)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000627 self.list = []
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000628 klass = self.FieldStorageClass or self.__class__
Guido van Rossum2e441f72001-07-25 21:00:19 +0000629 part = klass(self.fp, {}, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000630 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000631 # Throw first part away
632 while not part.done:
633 headers = rfc822.Message(self.fp)
Guido van Rossum2e441f72001-07-25 21:00:19 +0000634 part = klass(self.fp, headers, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000635 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000636 self.list.append(part)
637 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000638
639 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000640 """Internal: read an atomic part."""
641 if self.length >= 0:
642 self.read_binary()
643 self.skip_lines()
644 else:
645 self.read_lines()
646 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000647
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000648 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000649
650 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000651 """Internal: read binary data."""
652 self.file = self.make_file('b')
653 todo = self.length
654 if todo >= 0:
655 while todo > 0:
656 data = self.fp.read(min(todo, self.bufsize))
657 if not data:
658 self.done = -1
659 break
660 self.file.write(data)
661 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000662
663 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000664 """Internal: read lines until EOF or outerboundary."""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000665 self.file = self.__file = StringIO()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000666 if self.outerboundary:
667 self.read_lines_to_outerboundary()
668 else:
669 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000670
Guido van Rossum52b8c292001-06-29 13:06:06 +0000671 def __write(self, line):
672 if self.__file is not None:
673 if self.__file.tell() + len(line) > 1000:
674 self.file = self.make_file('')
675 self.file.write(self.__file.getvalue())
676 self.__file = None
677 self.file.write(line)
678
Guido van Rossum7aee3841996-03-07 18:00:44 +0000679 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000680 """Internal: read lines until EOF."""
681 while 1:
682 line = self.fp.readline()
683 if not line:
684 self.done = -1
685 break
Guido van Rossum52b8c292001-06-29 13:06:06 +0000686 self.__write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000687
688 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000689 """Internal: read lines until outerboundary."""
690 next = "--" + self.outerboundary
691 last = next + "--"
692 delim = ""
693 while 1:
694 line = self.fp.readline()
695 if not line:
696 self.done = -1
697 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000698 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000699 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000700 if strippedline == next:
701 break
702 if strippedline == last:
703 self.done = 1
704 break
705 odelim = delim
706 if line[-2:] == "\r\n":
707 delim = "\r\n"
708 line = line[:-2]
709 elif line[-1] == "\n":
710 delim = "\n"
711 line = line[:-1]
712 else:
713 delim = ""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000714 self.__write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000715
716 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000717 """Internal: skip lines until outer boundary if defined."""
718 if not self.outerboundary or self.done:
719 return
720 next = "--" + self.outerboundary
721 last = next + "--"
722 while 1:
723 line = self.fp.readline()
724 if not line:
725 self.done = -1
726 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000727 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000728 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000729 if strippedline == next:
730 break
731 if strippedline == last:
732 self.done = 1
733 break
Guido van Rossum7aee3841996-03-07 18:00:44 +0000734
Guido van Rossuma5e9fb61997-08-12 18:18:13 +0000735 def make_file(self, binary=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000736 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000737
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000738 The file will be used as follows:
739 - data is written to it
740 - seek(0)
741 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +0000742
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000743 The 'binary' argument is unused -- the file is always opened
744 in binary mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000745
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000746 This version opens a temporary file for reading and writing,
747 and immediately deletes (unlinks) it. The trick (on Unix!) is
748 that the file can still be used, but it can't be opened by
749 another process, and it will automatically be deleted when it
750 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000751
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000752 If you want a more permanent file, you derive a class which
753 overrides this method. If you want a visible temporary file
754 that is nevertheless automatically deleted when the script
755 terminates, try defining a __del__ method in a derived class
756 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000757
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000758 """
759 import tempfile
760 return tempfile.TemporaryFile("w+b")
Tim Peters88869f92001-01-14 23:36:06 +0000761
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000762
763
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000764# Backwards Compatibility Classes
765# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +0000766
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000767class FormContentDict(UserDict.UserDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000768 """Form content as dictionary with a list of values per field.
Guido van Rossum72755611996-03-06 07:20:06 +0000769
Guido van Rossum7aee3841996-03-07 18:00:44 +0000770 form = FormContentDict()
771
772 form[key] -> [value, value, ...]
773 form.has_key(key) -> Boolean
774 form.keys() -> [key, key, ...]
775 form.values() -> [[val, val, ...], [val, val, ...], ...]
776 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
777 form.dict == {key: [val, val, ...], ...}
778
779 """
Guido van Rossum773ab271996-07-23 03:46:24 +0000780 def __init__(self, environ=os.environ):
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000781 self.dict = self.data = parse(environ=environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000782 self.query_string = environ['QUERY_STRING']
Guido van Rossum9a22de11995-01-12 12:29:47 +0000783
784
Guido van Rossum9a22de11995-01-12 12:29:47 +0000785class SvFormContentDict(FormContentDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000786 """Form content as dictionary expecting a single value per field.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000787
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000788 If you only expect a single value for each field, then form[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000789 will return that single value. It will raise an IndexError if
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000790 that expectation is not true. If you expect a field to have
Guido van Rossum7aee3841996-03-07 18:00:44 +0000791 possible multiple values, than you can use form.getlist(key) to
792 get all of the values. values() and items() are a compromise:
793 they return single strings where there is a single value, and
794 lists of strings otherwise.
795
796 """
797 def __getitem__(self, key):
Tim Peters88869f92001-01-14 23:36:06 +0000798 if len(self.dict[key]) > 1:
799 raise IndexError, 'expecting a single value'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000800 return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000801 def getlist(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000802 return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000803 def values(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000804 result = []
805 for value in self.dict.values():
806 if len(value) == 1:
807 result.append(value[0])
808 else: result.append(value)
809 return result
Guido van Rossum7aee3841996-03-07 18:00:44 +0000810 def items(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000811 result = []
812 for key, value in self.dict.items():
813 if len(value) == 1:
814 result.append((key, value[0]))
815 else: result.append((key, value))
816 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000817
818
Guido van Rossum9a22de11995-01-12 12:29:47 +0000819class InterpFormContentDict(SvFormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000820 """This class is present for backwards compatibility only."""
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000821 def __getitem__(self, key):
822 v = SvFormContentDict.__getitem__(self, key)
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000823 if v[0] in '0123456789+-.':
824 try: return int(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000825 except ValueError:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000826 try: return float(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000827 except ValueError: pass
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000828 return v.strip()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000829 def values(self):
830 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000831 for key in self.keys():
832 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000833 result.append(self[key])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000834 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000835 result.append(self.dict[key])
836 return result
837 def items(self):
838 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000839 for key in self.keys():
840 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000841 result.append((key, self[key]))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000842 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000843 result.append((key, self.dict[key]))
844 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000845
846
Guido van Rossum9a22de11995-01-12 12:29:47 +0000847class FormContent(FormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000848 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +0000849 def values(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000850 if self.dict.has_key(key) :return self.dict[key]
851 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000852 def indexed_value(self, key, location):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000853 if self.dict.has_key(key):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000854 if len(self.dict[key]) > location:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000855 return self.dict[key][location]
856 else: return None
857 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000858 def value(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000859 if self.dict.has_key(key): return self.dict[key][0]
860 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000861 def length(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000862 return len(self.dict[key])
Guido van Rossum0147db01996-03-09 03:16:04 +0000863 def stripped(self, key):
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000864 if self.dict.has_key(key): return self.dict[key][0].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000865 else: return None
Guido van Rossum7aee3841996-03-07 18:00:44 +0000866 def pars(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000867 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000868
869
Guido van Rossum72755611996-03-06 07:20:06 +0000870# Test/debug code
871# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +0000872
Guido van Rossum773ab271996-07-23 03:46:24 +0000873def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000874 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000875
Guido van Rossum7aee3841996-03-07 18:00:44 +0000876 Write minimal HTTP headers and dump all information provided to
877 the script in HTML form.
878
879 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000880 print "Content-type: text/html"
881 print
882 sys.stderr = sys.stdout
883 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000884 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000885 print_directory()
886 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000887 print_form(form)
888 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000889 print_environ_usage()
890 def f():
891 exec "testing print_exception() -- <I>italics?</I>"
892 def g(f=f):
893 f()
894 print "<H3>What follows is a test, not an actual exception:</H3>"
895 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000896 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000897 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000898
Guido van Rossum57d51f22000-09-16 21:16:01 +0000899 print "<H1>Second try with a small maxlen...</H1>"
900
Guido van Rossumad164711997-05-13 19:03:23 +0000901 global maxlen
902 maxlen = 50
903 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000904 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000905 print_directory()
906 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000907 print_form(form)
908 print_environ(environ)
Guido van Rossumad164711997-05-13 19:03:23 +0000909 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000910 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +0000911
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000912def print_exception(type=None, value=None, tb=None, limit=None):
913 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000914 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000915 import traceback
916 print
Guido van Rossum7dd06962000-12-27 19:12:58 +0000917 print "<H3>Traceback (most recent call last):</H3>"
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000918 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000919 traceback.format_exception_only(type, value)
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000920 print "<PRE>%s<B>%s</B></PRE>" % (
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000921 escape("".join(list[:-1])),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000922 escape(list[-1]),
923 )
Guido van Rossumf15d1591997-09-29 23:22:12 +0000924 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +0000925
Guido van Rossum773ab271996-07-23 03:46:24 +0000926def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000927 """Dump the shell environment as HTML."""
928 keys = environ.keys()
929 keys.sort()
930 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000931 print "<H3>Shell Environment:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000932 print "<DL>"
933 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000934 print "<DT>", escape(key), "<DD>", escape(environ[key])
Tim Peters88869f92001-01-14 23:36:06 +0000935 print "</DL>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000936 print
Guido van Rossum72755611996-03-06 07:20:06 +0000937
938def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000939 """Dump the contents of a form as HTML."""
940 keys = form.keys()
941 keys.sort()
942 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000943 print "<H3>Form Contents:</H3>"
Guido van Rossum57d51f22000-09-16 21:16:01 +0000944 if not keys:
945 print "<P>No form fields."
Guido van Rossum7aee3841996-03-07 18:00:44 +0000946 print "<DL>"
947 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000948 print "<DT>" + escape(key) + ":",
949 value = form[key]
950 print "<i>" + escape(`type(value)`) + "</i>"
951 print "<DD>" + escape(`value`)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000952 print "</DL>"
953 print
954
955def print_directory():
956 """Dump the current directory as HTML."""
957 print
958 print "<H3>Current Working Directory:</H3>"
959 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000960 pwd = os.getcwd()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000961 except os.error, msg:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000962 print "os.error:", escape(str(msg))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000963 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000964 print escape(pwd)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000965 print
Guido van Rossum9a22de11995-01-12 12:29:47 +0000966
Guido van Rossuma8738a51996-03-14 21:30:28 +0000967def print_arguments():
968 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000969 print "<H3>Command Line Arguments:</H3>"
Guido van Rossuma8738a51996-03-14 21:30:28 +0000970 print
971 print sys.argv
972 print
973
Guido van Rossum9a22de11995-01-12 12:29:47 +0000974def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +0000975 """Dump a list of environment variables used by CGI as HTML."""
976 print """
Guido van Rossum72755611996-03-06 07:20:06 +0000977<H3>These environment variables could have been set:</H3>
978<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +0000979<LI>AUTH_TYPE
980<LI>CONTENT_LENGTH
981<LI>CONTENT_TYPE
982<LI>DATE_GMT
983<LI>DATE_LOCAL
984<LI>DOCUMENT_NAME
985<LI>DOCUMENT_ROOT
986<LI>DOCUMENT_URI
987<LI>GATEWAY_INTERFACE
988<LI>LAST_MODIFIED
989<LI>PATH
990<LI>PATH_INFO
991<LI>PATH_TRANSLATED
992<LI>QUERY_STRING
993<LI>REMOTE_ADDR
994<LI>REMOTE_HOST
995<LI>REMOTE_IDENT
996<LI>REMOTE_USER
997<LI>REQUEST_METHOD
998<LI>SCRIPT_NAME
999<LI>SERVER_NAME
1000<LI>SERVER_PORT
1001<LI>SERVER_PROTOCOL
1002<LI>SERVER_ROOT
1003<LI>SERVER_SOFTWARE
1004</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001005In addition, HTTP headers sent by the server may be passed in the
1006environment as well. Here are some common variable names:
1007<UL>
1008<LI>HTTP_ACCEPT
1009<LI>HTTP_CONNECTION
1010<LI>HTTP_HOST
1011<LI>HTTP_PRAGMA
1012<LI>HTTP_REFERER
1013<LI>HTTP_USER_AGENT
1014</UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001015"""
1016
Guido van Rossum9a22de11995-01-12 12:29:47 +00001017
Guido van Rossum72755611996-03-06 07:20:06 +00001018# Utilities
1019# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001020
Guido van Rossum64c66201997-07-19 20:11:53 +00001021def escape(s, quote=None):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001022 """Replace special characters '&', '<' and '>' by SGML entities."""
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001023 s = s.replace("&", "&amp;") # Must be done first!
1024 s = s.replace("<", "&lt;")
1025 s = s.replace(">", "&gt;")
Guido van Rossum64c66201997-07-19 20:11:53 +00001026 if quote:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001027 s = s.replace('"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +00001028 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001029
Guido van Rossum2e441f72001-07-25 21:00:19 +00001030def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
1031 import re
1032 return re.match(_vb_pattern, s)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001033
Guido van Rossum72755611996-03-06 07:20:06 +00001034# Invoke mainline
1035# ===============
1036
1037# Call test() when this file is run as a script (not imported as a module)
Tim Peters88869f92001-01-14 23:36:06 +00001038if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001039 test()