blob: fb40ed36a3c11d5aee7229a8801fda3d1b034c41 [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 Rossum68468eb2003-02-27 20:14:51 +000091 log(*allargs)
Guido van Rossumc204c701996-09-05 19:07:11 +000092
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:
Neil Schemenauer66edb622004-07-19 15:38:11 +0000212 if not name_value and not strict_parsing:
213 continue
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000214 nv = name_value.split('=', 1)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000215 if len(nv) != 2:
216 if strict_parsing:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000217 raise ValueError, "bad query field: %r" % (name_value,)
Brett Cannon8d9b60f2004-03-21 22:16:15 +0000218 # Handle case of a control-name with no equal sign
219 if keep_blank_values:
220 nv.append('')
221 else:
222 continue
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000223 if len(nv[1]) or keep_blank_values:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000224 name = urllib.unquote(nv[0].replace('+', ' '))
225 value = urllib.unquote(nv[1].replace('+', ' '))
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000226 r.append((name, value))
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000227
228 return r
Guido van Rossum9a22de11995-01-12 12:29:47 +0000229
230
Guido van Rossum0147db01996-03-09 03:16:04 +0000231def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000232 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000233
Guido van Rossum7aee3841996-03-07 18:00:44 +0000234 Arguments:
235 fp : input file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000236 pdict: dictionary containing other parameters of conten-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000237
Tim Peters88869f92001-01-14 23:36:06 +0000238 Returns a dictionary just like parse_qs(): keys are the field names, each
239 value is a list of values for that field. This is easy to use but not
240 much good if you are expecting megabytes to be uploaded -- in that case,
241 use the FieldStorage class instead which is much more flexible. Note
242 that content-type is the raw, unparsed contents of the content-type
Guido van Rossum0147db01996-03-09 03:16:04 +0000243 header.
Tim Peters88869f92001-01-14 23:36:06 +0000244
245 XXX This does not parse nested multipart parts -- use FieldStorage for
Guido van Rossum0147db01996-03-09 03:16:04 +0000246 that.
Tim Peters88869f92001-01-14 23:36:06 +0000247
248 XXX This should really be subsumed by FieldStorage altogether -- no
Guido van Rossum0147db01996-03-09 03:16:04 +0000249 point in having two implementations of the same parsing algorithm.
Guido van Rossum72755611996-03-06 07:20:06 +0000250
Guido van Rossum7aee3841996-03-07 18:00:44 +0000251 """
Guido van Rossum2e441f72001-07-25 21:00:19 +0000252 boundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000253 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000254 boundary = pdict['boundary']
Guido van Rossum2e441f72001-07-25 21:00:19 +0000255 if not valid_boundary(boundary):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000256 raise ValueError, ('Invalid boundary in multipart form: %r'
257 % (boundary,))
Tim Petersab9ba272001-08-09 21:40:30 +0000258
Guido van Rossum7aee3841996-03-07 18:00:44 +0000259 nextpart = "--" + boundary
260 lastpart = "--" + boundary + "--"
261 partdict = {}
262 terminator = ""
263
264 while terminator != lastpart:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000265 bytes = -1
266 data = None
267 if terminator:
268 # At start of next part. Read headers first.
269 headers = mimetools.Message(fp)
270 clength = headers.getheader('content-length')
271 if clength:
272 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000273 bytes = int(clength)
274 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000275 pass
276 if bytes > 0:
277 if maxlen and bytes > maxlen:
278 raise ValueError, 'Maximum content length exceeded'
279 data = fp.read(bytes)
280 else:
281 data = ""
282 # Read lines until end of part.
283 lines = []
284 while 1:
285 line = fp.readline()
286 if not line:
287 terminator = lastpart # End outer loop
288 break
289 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000290 terminator = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000291 if terminator in (nextpart, lastpart):
292 break
293 lines.append(line)
294 # Done with part.
295 if data is None:
296 continue
297 if bytes < 0:
298 if lines:
299 # Strip final line terminator
300 line = lines[-1]
301 if line[-2:] == "\r\n":
302 line = line[:-2]
303 elif line[-1:] == "\n":
304 line = line[:-1]
305 lines[-1] = line
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000306 data = "".join(lines)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000307 line = headers['content-disposition']
308 if not line:
309 continue
310 key, params = parse_header(line)
311 if key != 'form-data':
312 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000313 if 'name' in params:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000314 name = params['name']
315 else:
316 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000317 if name in partdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000318 partdict[name].append(data)
319 else:
320 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000321
Guido van Rossum7aee3841996-03-07 18:00:44 +0000322 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000323
324
Guido van Rossum72755611996-03-06 07:20:06 +0000325def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000326 """Parse a Content-type like header.
327
328 Return the main content-type and a dictionary of options.
329
330 """
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000331 plist = map(lambda x: x.strip(), line.split(';'))
Raymond Hettinger46ac8eb2002-06-30 03:39:14 +0000332 key = plist.pop(0).lower()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000333 pdict = {}
334 for p in plist:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000335 i = p.find('=')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000336 if i >= 0:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000337 name = p[:i].strip().lower()
338 value = p[i+1:].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000339 if len(value) >= 2 and value[0] == value[-1] == '"':
340 value = value[1:-1]
Johannes Gijsbers9e15dd62004-08-14 15:39:34 +0000341 value = value.replace('\\\\', '\\').replace('\\"', '"')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000342 pdict[name] = value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000343 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000344
345
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000346# Classes for field storage
347# =========================
348
349class MiniFieldStorage:
350
Guido van Rossum0147db01996-03-09 03:16:04 +0000351 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000352
Guido van Rossum7aee3841996-03-07 18:00:44 +0000353 # Dummy attributes
354 filename = None
355 list = None
356 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000357 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000358 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000359 disposition = None
360 disposition_options = {}
361 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000362
Guido van Rossum7aee3841996-03-07 18:00:44 +0000363 def __init__(self, name, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000364 """Constructor from field name and value."""
365 self.name = name
366 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000367 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000368
369 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000370 """Return printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000371 return "MiniFieldStorage(%r, %r)" % (self.name, self.value)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000372
373
374class FieldStorage:
375
Guido van Rossum7aee3841996-03-07 18:00:44 +0000376 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000377
Guido van Rossum7aee3841996-03-07 18:00:44 +0000378 This class provides naming, typing, files stored on disk, and
379 more. At the top level, it is accessible like a dictionary, whose
380 keys are the field names. (Note: None can occur as a field name.)
381 The items are either a Python list (if there's multiple values) or
382 another FieldStorage or MiniFieldStorage object. If it's a single
383 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000384
Guido van Rossum7aee3841996-03-07 18:00:44 +0000385 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000386
Guido van Rossum7aee3841996-03-07 18:00:44 +0000387 filename: the filename, if specified; otherwise None; this is the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000388 client side filename, *not* the file name on which it is
389 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000390
Guido van Rossum7aee3841996-03-07 18:00:44 +0000391 value: the value as a *string*; for file uploads, this
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000392 transparently reads the file every time you request the value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000393
394 file: the file(-like) object from which you can read the data;
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000395 None if the data is stored a simple string
Guido van Rossum7aee3841996-03-07 18:00:44 +0000396
397 type: the content-type, or None if not specified
398
399 type_options: dictionary of options specified on the content-type
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000400 line
Guido van Rossum7aee3841996-03-07 18:00:44 +0000401
402 disposition: content-disposition, or None if not specified
403
404 disposition_options: dictionary of corresponding options
405
406 headers: a dictionary(-like) object (sometimes rfc822.Message or a
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000407 subclass thereof) containing *all* headers
Guido van Rossum7aee3841996-03-07 18:00:44 +0000408
409 The class is subclassable, mostly for the purpose of overriding
410 the make_file() method, which is called internally to come up with
411 a file open for reading and writing. This makes it possible to
412 override the default choice of storing all files in a temporary
413 directory and unlinking them as soon as they have been opened.
414
415 """
416
Guido van Rossum773ab271996-07-23 03:46:24 +0000417 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000418 environ=os.environ, keep_blank_values=0, strict_parsing=0):
419 """Constructor. Read multipart/* until last part.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000420
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000421 Arguments, all optional:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000422
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000423 fp : file pointer; default: sys.stdin
Guido van Rossumb1b4f941998-05-08 19:55:51 +0000424 (not used when the request method is GET)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000425
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000426 headers : header dictionary-like object; default:
427 taken from environ as per CGI spec
Guido van Rossum7aee3841996-03-07 18:00:44 +0000428
Guido van Rossum773ab271996-07-23 03:46:24 +0000429 outerboundary : terminating multipart boundary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000430 (for internal use only)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000431
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000432 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000433
434 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000435 URL encoded forms should be treated as blank strings.
436 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000437 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000438 blank values are to be ignored and treated as if they were
439 not included.
Guido van Rossum773ab271996-07-23 03:46:24 +0000440
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000441 strict_parsing: flag indicating what to do with parsing errors.
442 If false (the default), errors are silently ignored.
443 If true, errors raise a ValueError exception.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000444
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000445 """
446 method = 'GET'
447 self.keep_blank_values = keep_blank_values
448 self.strict_parsing = strict_parsing
Raymond Hettinger54f02222002-06-01 14:18:47 +0000449 if 'REQUEST_METHOD' in environ:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000450 method = environ['REQUEST_METHOD'].upper()
Guido van Rossum01852831998-06-25 02:40:17 +0000451 if method == 'GET' or method == 'HEAD':
Raymond Hettinger54f02222002-06-01 14:18:47 +0000452 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000453 qs = environ['QUERY_STRING']
454 elif sys.argv[1:]:
455 qs = sys.argv[1]
456 else:
457 qs = ""
458 fp = StringIO(qs)
459 if headers is None:
460 headers = {'content-type':
461 "application/x-www-form-urlencoded"}
462 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000463 headers = {}
464 if method == 'POST':
465 # Set default content-type for POST to what's traditional
466 headers['content-type'] = "application/x-www-form-urlencoded"
Raymond Hettinger54f02222002-06-01 14:18:47 +0000467 if 'CONTENT_TYPE' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000468 headers['content-type'] = environ['CONTENT_TYPE']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000469 if 'CONTENT_LENGTH' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000470 headers['content-length'] = environ['CONTENT_LENGTH']
471 self.fp = fp or sys.stdin
472 self.headers = headers
473 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000474
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000475 # Process content-disposition header
476 cdisp, pdict = "", {}
Raymond Hettinger54f02222002-06-01 14:18:47 +0000477 if 'content-disposition' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000478 cdisp, pdict = parse_header(self.headers['content-disposition'])
479 self.disposition = cdisp
480 self.disposition_options = pdict
481 self.name = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000482 if 'name' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000483 self.name = pdict['name']
484 self.filename = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000485 if 'filename' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000486 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000487
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000488 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000489 #
490 # Honor any existing content-type header. But if there is no
491 # content-type header, use some sensible defaults. Assume
492 # outerboundary is "" at the outer level, but something non-false
493 # inside a multi-part. The default for an inner part is text/plain,
494 # but for an outer part it should be urlencoded. This should catch
495 # bogus clients which erroneously forget to include a content-type
496 # header.
497 #
498 # See below for what we do if there does exist a content-type header,
499 # but it happens to be something we don't understand.
Raymond Hettinger54f02222002-06-01 14:18:47 +0000500 if 'content-type' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000501 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000502 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000503 ctype, pdict = "text/plain", {}
504 else:
505 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000506 self.type = ctype
507 self.type_options = pdict
508 self.innerboundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000509 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000510 self.innerboundary = pdict['boundary']
511 clen = -1
Raymond Hettinger54f02222002-06-01 14:18:47 +0000512 if 'content-length' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000513 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000514 clen = int(self.headers['content-length'])
Skip Montanarodb5d1442002-03-23 05:50:17 +0000515 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000516 pass
517 if maxlen and clen > maxlen:
518 raise ValueError, 'Maximum content length exceeded'
519 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000520
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000521 self.list = self.file = None
522 self.done = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000523 if ctype == 'application/x-www-form-urlencoded':
524 self.read_urlencoded()
525 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000526 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000527 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000528 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000529
530 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000531 """Return a printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000532 return "FieldStorage(%r, %r, %r)" % (
533 self.name, self.filename, self.value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000534
Guido van Rossum4061cbe2002-09-11 18:20:34 +0000535 def __iter__(self):
536 return iter(self.keys())
537
Guido van Rossum7aee3841996-03-07 18:00:44 +0000538 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000539 if name != 'value':
540 raise AttributeError, name
541 if self.file:
542 self.file.seek(0)
543 value = self.file.read()
544 self.file.seek(0)
545 elif self.list is not None:
546 value = self.list
547 else:
548 value = None
549 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000550
551 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000552 """Dictionary style indexing."""
553 if self.list is None:
554 raise TypeError, "not indexable"
555 found = []
556 for item in self.list:
557 if item.name == key: found.append(item)
558 if not found:
559 raise KeyError, key
560 if len(found) == 1:
561 return found[0]
562 else:
563 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000564
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000565 def getvalue(self, key, default=None):
566 """Dictionary style get() method, including 'value' lookup."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000567 if key in self:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000568 value = self[key]
569 if type(value) is type([]):
570 return map(lambda v: v.value, value)
571 else:
572 return value.value
573 else:
574 return default
575
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000576 def getfirst(self, key, default=None):
577 """ Return the first value received."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000578 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000579 value = self[key]
580 if type(value) is type([]):
581 return value[0].value
582 else:
583 return value.value
584 else:
585 return default
586
587 def getlist(self, key):
588 """ Return list of received values."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000589 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000590 value = self[key]
591 if type(value) is type([]):
592 return map(lambda v: v.value, value)
593 else:
594 return [value.value]
595 else:
596 return []
597
Guido van Rossum7aee3841996-03-07 18:00:44 +0000598 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000599 """Dictionary style keys() method."""
600 if self.list is None:
601 raise TypeError, "not indexable"
602 keys = []
603 for item in self.list:
604 if item.name not in keys: keys.append(item.name)
605 return keys
Guido van Rossum7aee3841996-03-07 18:00:44 +0000606
Guido van Rossum0147db01996-03-09 03:16:04 +0000607 def has_key(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000608 """Dictionary style has_key() method."""
609 if self.list is None:
610 raise TypeError, "not indexable"
611 for item in self.list:
Tim Petersbc0e9102002-04-04 22:55:58 +0000612 if item.name == key: return True
613 return False
Guido van Rossum0147db01996-03-09 03:16:04 +0000614
Raymond Hettinger54f02222002-06-01 14:18:47 +0000615 def __contains__(self, key):
616 """Dictionary style __contains__ method."""
617 if self.list is None:
618 raise TypeError, "not indexable"
619 for item in self.list:
620 if item.name == key: return True
621 return False
622
Guido van Rossum88b85d41997-01-11 19:21:33 +0000623 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000624 """Dictionary style len(x) support."""
625 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000626
Guido van Rossum7aee3841996-03-07 18:00:44 +0000627 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000628 """Internal: read data in query string format."""
629 qs = self.fp.read(self.length)
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000630 self.list = list = []
631 for key, value in parse_qsl(qs, self.keep_blank_values,
632 self.strict_parsing):
633 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000634 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000635
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000636 FieldStorageClass = None
637
Guido van Rossumf5745001998-10-20 14:43:02 +0000638 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000639 """Internal: read a part that is itself multipart."""
Guido van Rossum2e441f72001-07-25 21:00:19 +0000640 ib = self.innerboundary
641 if not valid_boundary(ib):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000642 raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000643 self.list = []
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000644 klass = self.FieldStorageClass or self.__class__
Guido van Rossum2e441f72001-07-25 21:00:19 +0000645 part = klass(self.fp, {}, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000646 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000647 # Throw first part away
648 while not part.done:
649 headers = rfc822.Message(self.fp)
Guido van Rossum2e441f72001-07-25 21:00:19 +0000650 part = klass(self.fp, headers, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000651 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000652 self.list.append(part)
653 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000654
655 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000656 """Internal: read an atomic part."""
657 if self.length >= 0:
658 self.read_binary()
659 self.skip_lines()
660 else:
661 self.read_lines()
662 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000663
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000664 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000665
666 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000667 """Internal: read binary data."""
668 self.file = self.make_file('b')
669 todo = self.length
670 if todo >= 0:
671 while todo > 0:
672 data = self.fp.read(min(todo, self.bufsize))
673 if not data:
674 self.done = -1
675 break
676 self.file.write(data)
677 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000678
679 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000680 """Internal: read lines until EOF or outerboundary."""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000681 self.file = self.__file = StringIO()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000682 if self.outerboundary:
683 self.read_lines_to_outerboundary()
684 else:
685 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000686
Guido van Rossum52b8c292001-06-29 13:06:06 +0000687 def __write(self, line):
688 if self.__file is not None:
689 if self.__file.tell() + len(line) > 1000:
690 self.file = self.make_file('')
691 self.file.write(self.__file.getvalue())
692 self.__file = None
693 self.file.write(line)
694
Guido van Rossum7aee3841996-03-07 18:00:44 +0000695 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000696 """Internal: read lines until EOF."""
697 while 1:
698 line = self.fp.readline()
699 if not line:
700 self.done = -1
701 break
Guido van Rossum52b8c292001-06-29 13:06:06 +0000702 self.__write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000703
704 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000705 """Internal: read lines until outerboundary."""
706 next = "--" + self.outerboundary
707 last = next + "--"
708 delim = ""
709 while 1:
710 line = self.fp.readline()
711 if not line:
712 self.done = -1
713 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000714 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000715 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000716 if strippedline == next:
717 break
718 if strippedline == last:
719 self.done = 1
720 break
721 odelim = delim
722 if line[-2:] == "\r\n":
723 delim = "\r\n"
724 line = line[:-2]
725 elif line[-1] == "\n":
726 delim = "\n"
727 line = line[:-1]
728 else:
729 delim = ""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000730 self.__write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000731
732 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000733 """Internal: skip lines until outer boundary if defined."""
734 if not self.outerboundary or self.done:
735 return
736 next = "--" + self.outerboundary
737 last = next + "--"
738 while 1:
739 line = self.fp.readline()
740 if not line:
741 self.done = -1
742 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000743 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000744 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000745 if strippedline == next:
746 break
747 if strippedline == last:
748 self.done = 1
749 break
Guido van Rossum7aee3841996-03-07 18:00:44 +0000750
Guido van Rossuma5e9fb61997-08-12 18:18:13 +0000751 def make_file(self, binary=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000752 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000753
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000754 The file will be used as follows:
755 - data is written to it
756 - seek(0)
757 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +0000758
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000759 The 'binary' argument is unused -- the file is always opened
760 in binary mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000761
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000762 This version opens a temporary file for reading and writing,
763 and immediately deletes (unlinks) it. The trick (on Unix!) is
764 that the file can still be used, but it can't be opened by
765 another process, and it will automatically be deleted when it
766 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000767
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000768 If you want a more permanent file, you derive a class which
769 overrides this method. If you want a visible temporary file
770 that is nevertheless automatically deleted when the script
771 terminates, try defining a __del__ method in a derived class
772 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000773
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000774 """
775 import tempfile
776 return tempfile.TemporaryFile("w+b")
Tim Peters88869f92001-01-14 23:36:06 +0000777
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000778
779
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000780# Backwards Compatibility Classes
781# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +0000782
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000783class FormContentDict(UserDict.UserDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000784 """Form content as dictionary with a list of values per field.
Guido van Rossum72755611996-03-06 07:20:06 +0000785
Guido van Rossum7aee3841996-03-07 18:00:44 +0000786 form = FormContentDict()
787
788 form[key] -> [value, value, ...]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000789 key in form -> Boolean
Guido van Rossum7aee3841996-03-07 18:00:44 +0000790 form.keys() -> [key, key, ...]
791 form.values() -> [[val, val, ...], [val, val, ...], ...]
792 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
793 form.dict == {key: [val, val, ...], ...}
794
795 """
Guido van Rossum773ab271996-07-23 03:46:24 +0000796 def __init__(self, environ=os.environ):
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000797 self.dict = self.data = parse(environ=environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000798 self.query_string = environ['QUERY_STRING']
Guido van Rossum9a22de11995-01-12 12:29:47 +0000799
800
Guido van Rossum9a22de11995-01-12 12:29:47 +0000801class SvFormContentDict(FormContentDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000802 """Form content as dictionary expecting a single value per field.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000803
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000804 If you only expect a single value for each field, then form[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000805 will return that single value. It will raise an IndexError if
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000806 that expectation is not true. If you expect a field to have
Guido van Rossum7aee3841996-03-07 18:00:44 +0000807 possible multiple values, than you can use form.getlist(key) to
808 get all of the values. values() and items() are a compromise:
809 they return single strings where there is a single value, and
810 lists of strings otherwise.
811
812 """
813 def __getitem__(self, key):
Tim Peters88869f92001-01-14 23:36:06 +0000814 if len(self.dict[key]) > 1:
815 raise IndexError, 'expecting a single value'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000816 return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000817 def getlist(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000818 return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000819 def values(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000820 result = []
821 for value in self.dict.values():
822 if len(value) == 1:
823 result.append(value[0])
824 else: result.append(value)
825 return result
Guido van Rossum7aee3841996-03-07 18:00:44 +0000826 def items(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000827 result = []
828 for key, value in self.dict.items():
829 if len(value) == 1:
830 result.append((key, value[0]))
831 else: result.append((key, value))
832 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000833
834
Guido van Rossum9a22de11995-01-12 12:29:47 +0000835class InterpFormContentDict(SvFormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000836 """This class is present for backwards compatibility only."""
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000837 def __getitem__(self, key):
838 v = SvFormContentDict.__getitem__(self, key)
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000839 if v[0] in '0123456789+-.':
840 try: return int(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000841 except ValueError:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000842 try: return float(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000843 except ValueError: pass
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000844 return v.strip()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000845 def values(self):
846 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000847 for key in self.keys():
848 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000849 result.append(self[key])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000850 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000851 result.append(self.dict[key])
852 return result
853 def items(self):
854 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000855 for key in self.keys():
856 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000857 result.append((key, self[key]))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000858 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000859 result.append((key, self.dict[key]))
860 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000861
862
Guido van Rossum9a22de11995-01-12 12:29:47 +0000863class FormContent(FormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000864 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +0000865 def values(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000866 if key in self.dict :return self.dict[key]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000867 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000868 def indexed_value(self, key, location):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000869 if key in self.dict:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000870 if len(self.dict[key]) > location:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000871 return self.dict[key][location]
872 else: return None
873 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000874 def value(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000875 if key in self.dict: return self.dict[key][0]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000876 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000877 def length(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000878 return len(self.dict[key])
Guido van Rossum0147db01996-03-09 03:16:04 +0000879 def stripped(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000880 if key in self.dict: return self.dict[key][0].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000881 else: return None
Guido van Rossum7aee3841996-03-07 18:00:44 +0000882 def pars(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000883 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000884
885
Guido van Rossum72755611996-03-06 07:20:06 +0000886# Test/debug code
887# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +0000888
Guido van Rossum773ab271996-07-23 03:46:24 +0000889def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000890 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000891
Guido van Rossum7aee3841996-03-07 18:00:44 +0000892 Write minimal HTTP headers and dump all information provided to
893 the script in HTML form.
894
895 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000896 print "Content-type: text/html"
897 print
898 sys.stderr = sys.stdout
899 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000900 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000901 print_directory()
902 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000903 print_form(form)
904 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000905 print_environ_usage()
906 def f():
907 exec "testing print_exception() -- <I>italics?</I>"
908 def g(f=f):
909 f()
910 print "<H3>What follows is a test, not an actual exception:</H3>"
911 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000912 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000913 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000914
Guido van Rossum57d51f22000-09-16 21:16:01 +0000915 print "<H1>Second try with a small maxlen...</H1>"
916
Guido van Rossumad164711997-05-13 19:03:23 +0000917 global maxlen
918 maxlen = 50
919 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000920 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000921 print_directory()
922 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000923 print_form(form)
924 print_environ(environ)
Guido van Rossumad164711997-05-13 19:03:23 +0000925 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000926 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +0000927
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000928def print_exception(type=None, value=None, tb=None, limit=None):
929 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000930 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000931 import traceback
932 print
Guido van Rossum7dd06962000-12-27 19:12:58 +0000933 print "<H3>Traceback (most recent call last):</H3>"
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000934 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000935 traceback.format_exception_only(type, value)
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000936 print "<PRE>%s<B>%s</B></PRE>" % (
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000937 escape("".join(list[:-1])),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000938 escape(list[-1]),
939 )
Guido van Rossumf15d1591997-09-29 23:22:12 +0000940 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +0000941
Guido van Rossum773ab271996-07-23 03:46:24 +0000942def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000943 """Dump the shell environment as HTML."""
944 keys = environ.keys()
945 keys.sort()
946 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000947 print "<H3>Shell Environment:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000948 print "<DL>"
949 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000950 print "<DT>", escape(key), "<DD>", escape(environ[key])
Tim Peters88869f92001-01-14 23:36:06 +0000951 print "</DL>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000952 print
Guido van Rossum72755611996-03-06 07:20:06 +0000953
954def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000955 """Dump the contents of a form as HTML."""
956 keys = form.keys()
957 keys.sort()
958 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000959 print "<H3>Form Contents:</H3>"
Guido van Rossum57d51f22000-09-16 21:16:01 +0000960 if not keys:
961 print "<P>No form fields."
Guido van Rossum7aee3841996-03-07 18:00:44 +0000962 print "<DL>"
963 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000964 print "<DT>" + escape(key) + ":",
965 value = form[key]
Walter Dörwald70a6b492004-02-12 17:35:32 +0000966 print "<i>" + escape(repr(type(value))) + "</i>"
967 print "<DD>" + escape(repr(value))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000968 print "</DL>"
969 print
970
971def print_directory():
972 """Dump the current directory as HTML."""
973 print
974 print "<H3>Current Working Directory:</H3>"
975 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000976 pwd = os.getcwd()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000977 except os.error, msg:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000978 print "os.error:", escape(str(msg))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000979 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000980 print escape(pwd)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000981 print
Guido van Rossum9a22de11995-01-12 12:29:47 +0000982
Guido van Rossuma8738a51996-03-14 21:30:28 +0000983def print_arguments():
984 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000985 print "<H3>Command Line Arguments:</H3>"
Guido van Rossuma8738a51996-03-14 21:30:28 +0000986 print
987 print sys.argv
988 print
989
Guido van Rossum9a22de11995-01-12 12:29:47 +0000990def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +0000991 """Dump a list of environment variables used by CGI as HTML."""
992 print """
Guido van Rossum72755611996-03-06 07:20:06 +0000993<H3>These environment variables could have been set:</H3>
994<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +0000995<LI>AUTH_TYPE
996<LI>CONTENT_LENGTH
997<LI>CONTENT_TYPE
998<LI>DATE_GMT
999<LI>DATE_LOCAL
1000<LI>DOCUMENT_NAME
1001<LI>DOCUMENT_ROOT
1002<LI>DOCUMENT_URI
1003<LI>GATEWAY_INTERFACE
1004<LI>LAST_MODIFIED
1005<LI>PATH
1006<LI>PATH_INFO
1007<LI>PATH_TRANSLATED
1008<LI>QUERY_STRING
1009<LI>REMOTE_ADDR
1010<LI>REMOTE_HOST
1011<LI>REMOTE_IDENT
1012<LI>REMOTE_USER
1013<LI>REQUEST_METHOD
1014<LI>SCRIPT_NAME
1015<LI>SERVER_NAME
1016<LI>SERVER_PORT
1017<LI>SERVER_PROTOCOL
1018<LI>SERVER_ROOT
1019<LI>SERVER_SOFTWARE
1020</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001021In addition, HTTP headers sent by the server may be passed in the
1022environment as well. Here are some common variable names:
1023<UL>
1024<LI>HTTP_ACCEPT
1025<LI>HTTP_CONNECTION
1026<LI>HTTP_HOST
1027<LI>HTTP_PRAGMA
1028<LI>HTTP_REFERER
1029<LI>HTTP_USER_AGENT
1030</UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001031"""
1032
Guido van Rossum9a22de11995-01-12 12:29:47 +00001033
Guido van Rossum72755611996-03-06 07:20:06 +00001034# Utilities
1035# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001036
Guido van Rossum64c66201997-07-19 20:11:53 +00001037def escape(s, quote=None):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001038 """Replace special characters '&', '<' and '>' by SGML entities."""
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001039 s = s.replace("&", "&amp;") # Must be done first!
1040 s = s.replace("<", "&lt;")
1041 s = s.replace(">", "&gt;")
Guido van Rossum64c66201997-07-19 20:11:53 +00001042 if quote:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001043 s = s.replace('"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +00001044 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001045
Guido van Rossum2e441f72001-07-25 21:00:19 +00001046def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
1047 import re
1048 return re.match(_vb_pattern, s)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001049
Guido van Rossum72755611996-03-06 07:20:06 +00001050# Invoke mainline
1051# ===============
1052
1053# Call test() when this file is run as a script (not imported as a module)
Tim Peters88869f92001-01-14 23:36:06 +00001054if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001055 test()