blob: 7c3d6579434ff2cd78db0593d3630395a9456003 [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]
341 pdict[name] = value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000342 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000343
344
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000345# Classes for field storage
346# =========================
347
348class MiniFieldStorage:
349
Guido van Rossum0147db01996-03-09 03:16:04 +0000350 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000351
Guido van Rossum7aee3841996-03-07 18:00:44 +0000352 # Dummy attributes
353 filename = None
354 list = None
355 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000356 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000357 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000358 disposition = None
359 disposition_options = {}
360 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000361
Guido van Rossum7aee3841996-03-07 18:00:44 +0000362 def __init__(self, name, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000363 """Constructor from field name and value."""
364 self.name = name
365 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000366 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000367
368 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000369 """Return printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000370 return "MiniFieldStorage(%r, %r)" % (self.name, self.value)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000371
372
373class FieldStorage:
374
Guido van Rossum7aee3841996-03-07 18:00:44 +0000375 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000376
Guido van Rossum7aee3841996-03-07 18:00:44 +0000377 This class provides naming, typing, files stored on disk, and
378 more. At the top level, it is accessible like a dictionary, whose
379 keys are the field names. (Note: None can occur as a field name.)
380 The items are either a Python list (if there's multiple values) or
381 another FieldStorage or MiniFieldStorage object. If it's a single
382 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000383
Guido van Rossum7aee3841996-03-07 18:00:44 +0000384 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000385
Guido van Rossum7aee3841996-03-07 18:00:44 +0000386 filename: the filename, if specified; otherwise None; this is the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000387 client side filename, *not* the file name on which it is
388 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000389
Guido van Rossum7aee3841996-03-07 18:00:44 +0000390 value: the value as a *string*; for file uploads, this
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000391 transparently reads the file every time you request the value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000392
393 file: the file(-like) object from which you can read the data;
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000394 None if the data is stored a simple string
Guido van Rossum7aee3841996-03-07 18:00:44 +0000395
396 type: the content-type, or None if not specified
397
398 type_options: dictionary of options specified on the content-type
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000399 line
Guido van Rossum7aee3841996-03-07 18:00:44 +0000400
401 disposition: content-disposition, or None if not specified
402
403 disposition_options: dictionary of corresponding options
404
405 headers: a dictionary(-like) object (sometimes rfc822.Message or a
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000406 subclass thereof) containing *all* headers
Guido van Rossum7aee3841996-03-07 18:00:44 +0000407
408 The class is subclassable, mostly for the purpose of overriding
409 the make_file() method, which is called internally to come up with
410 a file open for reading and writing. This makes it possible to
411 override the default choice of storing all files in a temporary
412 directory and unlinking them as soon as they have been opened.
413
414 """
415
Guido van Rossum773ab271996-07-23 03:46:24 +0000416 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000417 environ=os.environ, keep_blank_values=0, strict_parsing=0):
418 """Constructor. Read multipart/* until last part.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000419
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000420 Arguments, all optional:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000421
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000422 fp : file pointer; default: sys.stdin
Guido van Rossumb1b4f941998-05-08 19:55:51 +0000423 (not used when the request method is GET)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000424
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000425 headers : header dictionary-like object; default:
426 taken from environ as per CGI spec
Guido van Rossum7aee3841996-03-07 18:00:44 +0000427
Guido van Rossum773ab271996-07-23 03:46:24 +0000428 outerboundary : terminating multipart boundary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000429 (for internal use only)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000430
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000431 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000432
433 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000434 URL encoded forms should be treated as blank strings.
435 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000436 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000437 blank values are to be ignored and treated as if they were
438 not included.
Guido van Rossum773ab271996-07-23 03:46:24 +0000439
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000440 strict_parsing: flag indicating what to do with parsing errors.
441 If false (the default), errors are silently ignored.
442 If true, errors raise a ValueError exception.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000443
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000444 """
445 method = 'GET'
446 self.keep_blank_values = keep_blank_values
447 self.strict_parsing = strict_parsing
Raymond Hettinger54f02222002-06-01 14:18:47 +0000448 if 'REQUEST_METHOD' in environ:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000449 method = environ['REQUEST_METHOD'].upper()
Guido van Rossum01852831998-06-25 02:40:17 +0000450 if method == 'GET' or method == 'HEAD':
Raymond Hettinger54f02222002-06-01 14:18:47 +0000451 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000452 qs = environ['QUERY_STRING']
453 elif sys.argv[1:]:
454 qs = sys.argv[1]
455 else:
456 qs = ""
457 fp = StringIO(qs)
458 if headers is None:
459 headers = {'content-type':
460 "application/x-www-form-urlencoded"}
461 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000462 headers = {}
463 if method == 'POST':
464 # Set default content-type for POST to what's traditional
465 headers['content-type'] = "application/x-www-form-urlencoded"
Raymond Hettinger54f02222002-06-01 14:18:47 +0000466 if 'CONTENT_TYPE' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000467 headers['content-type'] = environ['CONTENT_TYPE']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000468 if 'CONTENT_LENGTH' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000469 headers['content-length'] = environ['CONTENT_LENGTH']
470 self.fp = fp or sys.stdin
471 self.headers = headers
472 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000473
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000474 # Process content-disposition header
475 cdisp, pdict = "", {}
Raymond Hettinger54f02222002-06-01 14:18:47 +0000476 if 'content-disposition' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000477 cdisp, pdict = parse_header(self.headers['content-disposition'])
478 self.disposition = cdisp
479 self.disposition_options = pdict
480 self.name = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000481 if 'name' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000482 self.name = pdict['name']
483 self.filename = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000484 if 'filename' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000485 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000486
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000487 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000488 #
489 # Honor any existing content-type header. But if there is no
490 # content-type header, use some sensible defaults. Assume
491 # outerboundary is "" at the outer level, but something non-false
492 # inside a multi-part. The default for an inner part is text/plain,
493 # but for an outer part it should be urlencoded. This should catch
494 # bogus clients which erroneously forget to include a content-type
495 # header.
496 #
497 # See below for what we do if there does exist a content-type header,
498 # but it happens to be something we don't understand.
Raymond Hettinger54f02222002-06-01 14:18:47 +0000499 if 'content-type' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000500 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000501 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000502 ctype, pdict = "text/plain", {}
503 else:
504 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000505 self.type = ctype
506 self.type_options = pdict
507 self.innerboundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000508 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000509 self.innerboundary = pdict['boundary']
510 clen = -1
Raymond Hettinger54f02222002-06-01 14:18:47 +0000511 if 'content-length' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000512 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000513 clen = int(self.headers['content-length'])
Skip Montanarodb5d1442002-03-23 05:50:17 +0000514 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000515 pass
516 if maxlen and clen > maxlen:
517 raise ValueError, 'Maximum content length exceeded'
518 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000519
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000520 self.list = self.file = None
521 self.done = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000522 if ctype == 'application/x-www-form-urlencoded':
523 self.read_urlencoded()
524 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000525 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000526 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000527 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000528
529 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000530 """Return a printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000531 return "FieldStorage(%r, %r, %r)" % (
532 self.name, self.filename, self.value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000533
Guido van Rossum4061cbe2002-09-11 18:20:34 +0000534 def __iter__(self):
535 return iter(self.keys())
536
Guido van Rossum7aee3841996-03-07 18:00:44 +0000537 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000538 if name != 'value':
539 raise AttributeError, name
540 if self.file:
541 self.file.seek(0)
542 value = self.file.read()
543 self.file.seek(0)
544 elif self.list is not None:
545 value = self.list
546 else:
547 value = None
548 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000549
550 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000551 """Dictionary style indexing."""
552 if self.list is None:
553 raise TypeError, "not indexable"
554 found = []
555 for item in self.list:
556 if item.name == key: found.append(item)
557 if not found:
558 raise KeyError, key
559 if len(found) == 1:
560 return found[0]
561 else:
562 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000563
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000564 def getvalue(self, key, default=None):
565 """Dictionary style get() method, including 'value' lookup."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000566 if key in self:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000567 value = self[key]
568 if type(value) is type([]):
569 return map(lambda v: v.value, value)
570 else:
571 return value.value
572 else:
573 return default
574
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000575 def getfirst(self, key, default=None):
576 """ Return the first value received."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000577 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000578 value = self[key]
579 if type(value) is type([]):
580 return value[0].value
581 else:
582 return value.value
583 else:
584 return default
585
586 def getlist(self, key):
587 """ Return list of received values."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000588 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000589 value = self[key]
590 if type(value) is type([]):
591 return map(lambda v: v.value, value)
592 else:
593 return [value.value]
594 else:
595 return []
596
Guido van Rossum7aee3841996-03-07 18:00:44 +0000597 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000598 """Dictionary style keys() method."""
599 if self.list is None:
600 raise TypeError, "not indexable"
601 keys = []
602 for item in self.list:
603 if item.name not in keys: keys.append(item.name)
604 return keys
Guido van Rossum7aee3841996-03-07 18:00:44 +0000605
Guido van Rossum0147db01996-03-09 03:16:04 +0000606 def has_key(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000607 """Dictionary style has_key() method."""
608 if self.list is None:
609 raise TypeError, "not indexable"
610 for item in self.list:
Tim Petersbc0e9102002-04-04 22:55:58 +0000611 if item.name == key: return True
612 return False
Guido van Rossum0147db01996-03-09 03:16:04 +0000613
Raymond Hettinger54f02222002-06-01 14:18:47 +0000614 def __contains__(self, key):
615 """Dictionary style __contains__ method."""
616 if self.list is None:
617 raise TypeError, "not indexable"
618 for item in self.list:
619 if item.name == key: return True
620 return False
621
Guido van Rossum88b85d41997-01-11 19:21:33 +0000622 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000623 """Dictionary style len(x) support."""
624 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000625
Guido van Rossum7aee3841996-03-07 18:00:44 +0000626 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000627 """Internal: read data in query string format."""
628 qs = self.fp.read(self.length)
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000629 self.list = list = []
630 for key, value in parse_qsl(qs, self.keep_blank_values,
631 self.strict_parsing):
632 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000633 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000634
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000635 FieldStorageClass = None
636
Guido van Rossumf5745001998-10-20 14:43:02 +0000637 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000638 """Internal: read a part that is itself multipart."""
Guido van Rossum2e441f72001-07-25 21:00:19 +0000639 ib = self.innerboundary
640 if not valid_boundary(ib):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000641 raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000642 self.list = []
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000643 klass = self.FieldStorageClass or self.__class__
Guido van Rossum2e441f72001-07-25 21:00:19 +0000644 part = klass(self.fp, {}, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000645 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000646 # Throw first part away
647 while not part.done:
648 headers = rfc822.Message(self.fp)
Guido van Rossum2e441f72001-07-25 21:00:19 +0000649 part = klass(self.fp, headers, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000650 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000651 self.list.append(part)
652 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000653
654 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000655 """Internal: read an atomic part."""
656 if self.length >= 0:
657 self.read_binary()
658 self.skip_lines()
659 else:
660 self.read_lines()
661 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000662
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000663 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000664
665 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000666 """Internal: read binary data."""
667 self.file = self.make_file('b')
668 todo = self.length
669 if todo >= 0:
670 while todo > 0:
671 data = self.fp.read(min(todo, self.bufsize))
672 if not data:
673 self.done = -1
674 break
675 self.file.write(data)
676 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000677
678 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000679 """Internal: read lines until EOF or outerboundary."""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000680 self.file = self.__file = StringIO()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000681 if self.outerboundary:
682 self.read_lines_to_outerboundary()
683 else:
684 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000685
Guido van Rossum52b8c292001-06-29 13:06:06 +0000686 def __write(self, line):
687 if self.__file is not None:
688 if self.__file.tell() + len(line) > 1000:
689 self.file = self.make_file('')
690 self.file.write(self.__file.getvalue())
691 self.__file = None
692 self.file.write(line)
693
Guido van Rossum7aee3841996-03-07 18:00:44 +0000694 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000695 """Internal: read lines until EOF."""
696 while 1:
697 line = self.fp.readline()
698 if not line:
699 self.done = -1
700 break
Guido van Rossum52b8c292001-06-29 13:06:06 +0000701 self.__write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000702
703 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000704 """Internal: read lines until outerboundary."""
705 next = "--" + self.outerboundary
706 last = next + "--"
707 delim = ""
708 while 1:
709 line = self.fp.readline()
710 if not line:
711 self.done = -1
712 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000713 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000714 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000715 if strippedline == next:
716 break
717 if strippedline == last:
718 self.done = 1
719 break
720 odelim = delim
721 if line[-2:] == "\r\n":
722 delim = "\r\n"
723 line = line[:-2]
724 elif line[-1] == "\n":
725 delim = "\n"
726 line = line[:-1]
727 else:
728 delim = ""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000729 self.__write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000730
731 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000732 """Internal: skip lines until outer boundary if defined."""
733 if not self.outerboundary or self.done:
734 return
735 next = "--" + self.outerboundary
736 last = next + "--"
737 while 1:
738 line = self.fp.readline()
739 if not line:
740 self.done = -1
741 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000742 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000743 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000744 if strippedline == next:
745 break
746 if strippedline == last:
747 self.done = 1
748 break
Guido van Rossum7aee3841996-03-07 18:00:44 +0000749
Guido van Rossuma5e9fb61997-08-12 18:18:13 +0000750 def make_file(self, binary=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000751 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000752
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000753 The file will be used as follows:
754 - data is written to it
755 - seek(0)
756 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +0000757
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000758 The 'binary' argument is unused -- the file is always opened
759 in binary mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000760
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000761 This version opens a temporary file for reading and writing,
762 and immediately deletes (unlinks) it. The trick (on Unix!) is
763 that the file can still be used, but it can't be opened by
764 another process, and it will automatically be deleted when it
765 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000766
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000767 If you want a more permanent file, you derive a class which
768 overrides this method. If you want a visible temporary file
769 that is nevertheless automatically deleted when the script
770 terminates, try defining a __del__ method in a derived class
771 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000772
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000773 """
774 import tempfile
775 return tempfile.TemporaryFile("w+b")
Tim Peters88869f92001-01-14 23:36:06 +0000776
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000777
778
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000779# Backwards Compatibility Classes
780# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +0000781
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000782class FormContentDict(UserDict.UserDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000783 """Form content as dictionary with a list of values per field.
Guido van Rossum72755611996-03-06 07:20:06 +0000784
Guido van Rossum7aee3841996-03-07 18:00:44 +0000785 form = FormContentDict()
786
787 form[key] -> [value, value, ...]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000788 key in form -> Boolean
Guido van Rossum7aee3841996-03-07 18:00:44 +0000789 form.keys() -> [key, key, ...]
790 form.values() -> [[val, val, ...], [val, val, ...], ...]
791 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
792 form.dict == {key: [val, val, ...], ...}
793
794 """
Guido van Rossum773ab271996-07-23 03:46:24 +0000795 def __init__(self, environ=os.environ):
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000796 self.dict = self.data = parse(environ=environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000797 self.query_string = environ['QUERY_STRING']
Guido van Rossum9a22de11995-01-12 12:29:47 +0000798
799
Guido van Rossum9a22de11995-01-12 12:29:47 +0000800class SvFormContentDict(FormContentDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000801 """Form content as dictionary expecting a single value per field.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000802
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000803 If you only expect a single value for each field, then form[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000804 will return that single value. It will raise an IndexError if
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000805 that expectation is not true. If you expect a field to have
Guido van Rossum7aee3841996-03-07 18:00:44 +0000806 possible multiple values, than you can use form.getlist(key) to
807 get all of the values. values() and items() are a compromise:
808 they return single strings where there is a single value, and
809 lists of strings otherwise.
810
811 """
812 def __getitem__(self, key):
Tim Peters88869f92001-01-14 23:36:06 +0000813 if len(self.dict[key]) > 1:
814 raise IndexError, 'expecting a single value'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000815 return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000816 def getlist(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000817 return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000818 def values(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000819 result = []
820 for value in self.dict.values():
821 if len(value) == 1:
822 result.append(value[0])
823 else: result.append(value)
824 return result
Guido van Rossum7aee3841996-03-07 18:00:44 +0000825 def items(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000826 result = []
827 for key, value in self.dict.items():
828 if len(value) == 1:
829 result.append((key, value[0]))
830 else: result.append((key, value))
831 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000832
833
Guido van Rossum9a22de11995-01-12 12:29:47 +0000834class InterpFormContentDict(SvFormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000835 """This class is present for backwards compatibility only."""
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000836 def __getitem__(self, key):
837 v = SvFormContentDict.__getitem__(self, key)
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000838 if v[0] in '0123456789+-.':
839 try: return int(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000840 except ValueError:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000841 try: return float(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000842 except ValueError: pass
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000843 return v.strip()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000844 def values(self):
845 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000846 for key in self.keys():
847 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000848 result.append(self[key])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000849 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000850 result.append(self.dict[key])
851 return result
852 def items(self):
853 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000854 for key in self.keys():
855 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000856 result.append((key, self[key]))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000857 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000858 result.append((key, self.dict[key]))
859 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000860
861
Guido van Rossum9a22de11995-01-12 12:29:47 +0000862class FormContent(FormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000863 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +0000864 def values(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000865 if key in self.dict :return self.dict[key]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000866 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000867 def indexed_value(self, key, location):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000868 if key in self.dict:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000869 if len(self.dict[key]) > location:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000870 return self.dict[key][location]
871 else: return None
872 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000873 def value(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000874 if key in self.dict: return self.dict[key][0]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000875 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000876 def length(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000877 return len(self.dict[key])
Guido van Rossum0147db01996-03-09 03:16:04 +0000878 def stripped(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000879 if key in self.dict: return self.dict[key][0].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000880 else: return None
Guido van Rossum7aee3841996-03-07 18:00:44 +0000881 def pars(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000882 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000883
884
Guido van Rossum72755611996-03-06 07:20:06 +0000885# Test/debug code
886# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +0000887
Guido van Rossum773ab271996-07-23 03:46:24 +0000888def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000889 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000890
Guido van Rossum7aee3841996-03-07 18:00:44 +0000891 Write minimal HTTP headers and dump all information provided to
892 the script in HTML form.
893
894 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000895 print "Content-type: text/html"
896 print
897 sys.stderr = sys.stdout
898 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000899 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000900 print_directory()
901 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000902 print_form(form)
903 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000904 print_environ_usage()
905 def f():
906 exec "testing print_exception() -- <I>italics?</I>"
907 def g(f=f):
908 f()
909 print "<H3>What follows is a test, not an actual exception:</H3>"
910 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000911 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000912 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000913
Guido van Rossum57d51f22000-09-16 21:16:01 +0000914 print "<H1>Second try with a small maxlen...</H1>"
915
Guido van Rossumad164711997-05-13 19:03:23 +0000916 global maxlen
917 maxlen = 50
918 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000919 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000920 print_directory()
921 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000922 print_form(form)
923 print_environ(environ)
Guido van Rossumad164711997-05-13 19:03:23 +0000924 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000925 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +0000926
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000927def print_exception(type=None, value=None, tb=None, limit=None):
928 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000929 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000930 import traceback
931 print
Guido van Rossum7dd06962000-12-27 19:12:58 +0000932 print "<H3>Traceback (most recent call last):</H3>"
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000933 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000934 traceback.format_exception_only(type, value)
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000935 print "<PRE>%s<B>%s</B></PRE>" % (
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000936 escape("".join(list[:-1])),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000937 escape(list[-1]),
938 )
Guido van Rossumf15d1591997-09-29 23:22:12 +0000939 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +0000940
Guido van Rossum773ab271996-07-23 03:46:24 +0000941def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000942 """Dump the shell environment as HTML."""
943 keys = environ.keys()
944 keys.sort()
945 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000946 print "<H3>Shell Environment:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000947 print "<DL>"
948 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000949 print "<DT>", escape(key), "<DD>", escape(environ[key])
Tim Peters88869f92001-01-14 23:36:06 +0000950 print "</DL>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000951 print
Guido van Rossum72755611996-03-06 07:20:06 +0000952
953def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000954 """Dump the contents of a form as HTML."""
955 keys = form.keys()
956 keys.sort()
957 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000958 print "<H3>Form Contents:</H3>"
Guido van Rossum57d51f22000-09-16 21:16:01 +0000959 if not keys:
960 print "<P>No form fields."
Guido van Rossum7aee3841996-03-07 18:00:44 +0000961 print "<DL>"
962 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000963 print "<DT>" + escape(key) + ":",
964 value = form[key]
Walter Dörwald70a6b492004-02-12 17:35:32 +0000965 print "<i>" + escape(repr(type(value))) + "</i>"
966 print "<DD>" + escape(repr(value))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000967 print "</DL>"
968 print
969
970def print_directory():
971 """Dump the current directory as HTML."""
972 print
973 print "<H3>Current Working Directory:</H3>"
974 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000975 pwd = os.getcwd()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000976 except os.error, msg:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000977 print "os.error:", escape(str(msg))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000978 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000979 print escape(pwd)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000980 print
Guido van Rossum9a22de11995-01-12 12:29:47 +0000981
Guido van Rossuma8738a51996-03-14 21:30:28 +0000982def print_arguments():
983 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000984 print "<H3>Command Line Arguments:</H3>"
Guido van Rossuma8738a51996-03-14 21:30:28 +0000985 print
986 print sys.argv
987 print
988
Guido van Rossum9a22de11995-01-12 12:29:47 +0000989def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +0000990 """Dump a list of environment variables used by CGI as HTML."""
991 print """
Guido van Rossum72755611996-03-06 07:20:06 +0000992<H3>These environment variables could have been set:</H3>
993<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +0000994<LI>AUTH_TYPE
995<LI>CONTENT_LENGTH
996<LI>CONTENT_TYPE
997<LI>DATE_GMT
998<LI>DATE_LOCAL
999<LI>DOCUMENT_NAME
1000<LI>DOCUMENT_ROOT
1001<LI>DOCUMENT_URI
1002<LI>GATEWAY_INTERFACE
1003<LI>LAST_MODIFIED
1004<LI>PATH
1005<LI>PATH_INFO
1006<LI>PATH_TRANSLATED
1007<LI>QUERY_STRING
1008<LI>REMOTE_ADDR
1009<LI>REMOTE_HOST
1010<LI>REMOTE_IDENT
1011<LI>REMOTE_USER
1012<LI>REQUEST_METHOD
1013<LI>SCRIPT_NAME
1014<LI>SERVER_NAME
1015<LI>SERVER_PORT
1016<LI>SERVER_PROTOCOL
1017<LI>SERVER_ROOT
1018<LI>SERVER_SOFTWARE
1019</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001020In addition, HTTP headers sent by the server may be passed in the
1021environment as well. Here are some common variable names:
1022<UL>
1023<LI>HTTP_ACCEPT
1024<LI>HTTP_CONNECTION
1025<LI>HTTP_HOST
1026<LI>HTTP_PRAGMA
1027<LI>HTTP_REFERER
1028<LI>HTTP_USER_AGENT
1029</UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001030"""
1031
Guido van Rossum9a22de11995-01-12 12:29:47 +00001032
Guido van Rossum72755611996-03-06 07:20:06 +00001033# Utilities
1034# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001035
Guido van Rossum64c66201997-07-19 20:11:53 +00001036def escape(s, quote=None):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001037 """Replace special characters '&', '<' and '>' by SGML entities."""
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001038 s = s.replace("&", "&amp;") # Must be done first!
1039 s = s.replace("<", "&lt;")
1040 s = s.replace(">", "&gt;")
Guido van Rossum64c66201997-07-19 20:11:53 +00001041 if quote:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001042 s = s.replace('"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +00001043 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001044
Guido van Rossum2e441f72001-07-25 21:00:19 +00001045def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
1046 import re
1047 return re.match(_vb_pattern, s)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001048
Guido van Rossum72755611996-03-06 07:20:06 +00001049# Invoke mainline
1050# ===============
1051
1052# Call test() when this file is run as a script (not imported as a module)
Tim Peters88869f92001-01-14 23:36:06 +00001053if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001054 test()