blob: 487b01e3f2ebb92e9ab90c82a5261a84763a1d0e [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:
212 nv = name_value.split('=', 1)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000213 if len(nv) != 2:
214 if strict_parsing:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000215 raise ValueError, "bad query field: %r" % (name_value,)
Brett Cannon8d9b60f2004-03-21 22:16:15 +0000216 # Handle case of a control-name with no equal sign
217 if keep_blank_values:
218 nv.append('')
219 else:
220 continue
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000221 if len(nv[1]) or keep_blank_values:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000222 name = urllib.unquote(nv[0].replace('+', ' '))
223 value = urllib.unquote(nv[1].replace('+', ' '))
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000224 r.append((name, value))
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000225
226 return r
Guido van Rossum9a22de11995-01-12 12:29:47 +0000227
228
Guido van Rossum0147db01996-03-09 03:16:04 +0000229def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000230 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000231
Guido van Rossum7aee3841996-03-07 18:00:44 +0000232 Arguments:
233 fp : input file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000234 pdict: dictionary containing other parameters of conten-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000235
Tim Peters88869f92001-01-14 23:36:06 +0000236 Returns a dictionary just like parse_qs(): keys are the field names, each
237 value is a list of values for that field. This is easy to use but not
238 much good if you are expecting megabytes to be uploaded -- in that case,
239 use the FieldStorage class instead which is much more flexible. Note
240 that content-type is the raw, unparsed contents of the content-type
Guido van Rossum0147db01996-03-09 03:16:04 +0000241 header.
Tim Peters88869f92001-01-14 23:36:06 +0000242
243 XXX This does not parse nested multipart parts -- use FieldStorage for
Guido van Rossum0147db01996-03-09 03:16:04 +0000244 that.
Tim Peters88869f92001-01-14 23:36:06 +0000245
246 XXX This should really be subsumed by FieldStorage altogether -- no
Guido van Rossum0147db01996-03-09 03:16:04 +0000247 point in having two implementations of the same parsing algorithm.
Guido van Rossum72755611996-03-06 07:20:06 +0000248
Guido van Rossum7aee3841996-03-07 18:00:44 +0000249 """
Guido van Rossum2e441f72001-07-25 21:00:19 +0000250 boundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000251 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000252 boundary = pdict['boundary']
Guido van Rossum2e441f72001-07-25 21:00:19 +0000253 if not valid_boundary(boundary):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000254 raise ValueError, ('Invalid boundary in multipart form: %r'
255 % (boundary,))
Tim Petersab9ba272001-08-09 21:40:30 +0000256
Guido van Rossum7aee3841996-03-07 18:00:44 +0000257 nextpart = "--" + boundary
258 lastpart = "--" + boundary + "--"
259 partdict = {}
260 terminator = ""
261
262 while terminator != lastpart:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000263 bytes = -1
264 data = None
265 if terminator:
266 # At start of next part. Read headers first.
267 headers = mimetools.Message(fp)
268 clength = headers.getheader('content-length')
269 if clength:
270 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000271 bytes = int(clength)
272 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000273 pass
274 if bytes > 0:
275 if maxlen and bytes > maxlen:
276 raise ValueError, 'Maximum content length exceeded'
277 data = fp.read(bytes)
278 else:
279 data = ""
280 # Read lines until end of part.
281 lines = []
282 while 1:
283 line = fp.readline()
284 if not line:
285 terminator = lastpart # End outer loop
286 break
287 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000288 terminator = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000289 if terminator in (nextpart, lastpart):
290 break
291 lines.append(line)
292 # Done with part.
293 if data is None:
294 continue
295 if bytes < 0:
296 if lines:
297 # Strip final line terminator
298 line = lines[-1]
299 if line[-2:] == "\r\n":
300 line = line[:-2]
301 elif line[-1:] == "\n":
302 line = line[:-1]
303 lines[-1] = line
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000304 data = "".join(lines)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000305 line = headers['content-disposition']
306 if not line:
307 continue
308 key, params = parse_header(line)
309 if key != 'form-data':
310 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000311 if 'name' in params:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000312 name = params['name']
313 else:
314 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000315 if name in partdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000316 partdict[name].append(data)
317 else:
318 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000319
Guido van Rossum7aee3841996-03-07 18:00:44 +0000320 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000321
322
Guido van Rossum72755611996-03-06 07:20:06 +0000323def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000324 """Parse a Content-type like header.
325
326 Return the main content-type and a dictionary of options.
327
328 """
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000329 plist = map(lambda x: x.strip(), line.split(';'))
Raymond Hettinger46ac8eb2002-06-30 03:39:14 +0000330 key = plist.pop(0).lower()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000331 pdict = {}
332 for p in plist:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000333 i = p.find('=')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000334 if i >= 0:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000335 name = p[:i].strip().lower()
336 value = p[i+1:].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000337 if len(value) >= 2 and value[0] == value[-1] == '"':
338 value = value[1:-1]
339 pdict[name] = value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000340 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000341
342
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000343# Classes for field storage
344# =========================
345
346class MiniFieldStorage:
347
Guido van Rossum0147db01996-03-09 03:16:04 +0000348 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000349
Guido van Rossum7aee3841996-03-07 18:00:44 +0000350 # Dummy attributes
351 filename = None
352 list = None
353 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000354 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000355 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000356 disposition = None
357 disposition_options = {}
358 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000359
Guido van Rossum7aee3841996-03-07 18:00:44 +0000360 def __init__(self, name, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000361 """Constructor from field name and value."""
362 self.name = name
363 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000364 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000365
366 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000367 """Return printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000368 return "MiniFieldStorage(%r, %r)" % (self.name, self.value)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000369
370
371class FieldStorage:
372
Guido van Rossum7aee3841996-03-07 18:00:44 +0000373 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000374
Guido van Rossum7aee3841996-03-07 18:00:44 +0000375 This class provides naming, typing, files stored on disk, and
376 more. At the top level, it is accessible like a dictionary, whose
377 keys are the field names. (Note: None can occur as a field name.)
378 The items are either a Python list (if there's multiple values) or
379 another FieldStorage or MiniFieldStorage object. If it's a single
380 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000381
Guido van Rossum7aee3841996-03-07 18:00:44 +0000382 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000383
Guido van Rossum7aee3841996-03-07 18:00:44 +0000384 filename: the filename, if specified; otherwise None; this is the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000385 client side filename, *not* the file name on which it is
386 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000387
Guido van Rossum7aee3841996-03-07 18:00:44 +0000388 value: the value as a *string*; for file uploads, this
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000389 transparently reads the file every time you request the value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000390
391 file: the file(-like) object from which you can read the data;
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000392 None if the data is stored a simple string
Guido van Rossum7aee3841996-03-07 18:00:44 +0000393
394 type: the content-type, or None if not specified
395
396 type_options: dictionary of options specified on the content-type
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000397 line
Guido van Rossum7aee3841996-03-07 18:00:44 +0000398
399 disposition: content-disposition, or None if not specified
400
401 disposition_options: dictionary of corresponding options
402
403 headers: a dictionary(-like) object (sometimes rfc822.Message or a
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000404 subclass thereof) containing *all* headers
Guido van Rossum7aee3841996-03-07 18:00:44 +0000405
406 The class is subclassable, mostly for the purpose of overriding
407 the make_file() method, which is called internally to come up with
408 a file open for reading and writing. This makes it possible to
409 override the default choice of storing all files in a temporary
410 directory and unlinking them as soon as they have been opened.
411
412 """
413
Guido van Rossum773ab271996-07-23 03:46:24 +0000414 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000415 environ=os.environ, keep_blank_values=0, strict_parsing=0):
416 """Constructor. Read multipart/* until last part.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000417
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000418 Arguments, all optional:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000419
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000420 fp : file pointer; default: sys.stdin
Guido van Rossumb1b4f941998-05-08 19:55:51 +0000421 (not used when the request method is GET)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000422
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000423 headers : header dictionary-like object; default:
424 taken from environ as per CGI spec
Guido van Rossum7aee3841996-03-07 18:00:44 +0000425
Guido van Rossum773ab271996-07-23 03:46:24 +0000426 outerboundary : terminating multipart boundary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000427 (for internal use only)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000428
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000429 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000430
431 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000432 URL encoded forms should be treated as blank strings.
433 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000434 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000435 blank values are to be ignored and treated as if they were
436 not included.
Guido van Rossum773ab271996-07-23 03:46:24 +0000437
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000438 strict_parsing: flag indicating what to do with parsing errors.
439 If false (the default), errors are silently ignored.
440 If true, errors raise a ValueError exception.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000441
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000442 """
443 method = 'GET'
444 self.keep_blank_values = keep_blank_values
445 self.strict_parsing = strict_parsing
Raymond Hettinger54f02222002-06-01 14:18:47 +0000446 if 'REQUEST_METHOD' in environ:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000447 method = environ['REQUEST_METHOD'].upper()
Guido van Rossum01852831998-06-25 02:40:17 +0000448 if method == 'GET' or method == 'HEAD':
Raymond Hettinger54f02222002-06-01 14:18:47 +0000449 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000450 qs = environ['QUERY_STRING']
451 elif sys.argv[1:]:
452 qs = sys.argv[1]
453 else:
454 qs = ""
455 fp = StringIO(qs)
456 if headers is None:
457 headers = {'content-type':
458 "application/x-www-form-urlencoded"}
459 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000460 headers = {}
461 if method == 'POST':
462 # Set default content-type for POST to what's traditional
463 headers['content-type'] = "application/x-www-form-urlencoded"
Raymond Hettinger54f02222002-06-01 14:18:47 +0000464 if 'CONTENT_TYPE' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000465 headers['content-type'] = environ['CONTENT_TYPE']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000466 if 'CONTENT_LENGTH' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000467 headers['content-length'] = environ['CONTENT_LENGTH']
468 self.fp = fp or sys.stdin
469 self.headers = headers
470 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000471
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000472 # Process content-disposition header
473 cdisp, pdict = "", {}
Raymond Hettinger54f02222002-06-01 14:18:47 +0000474 if 'content-disposition' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000475 cdisp, pdict = parse_header(self.headers['content-disposition'])
476 self.disposition = cdisp
477 self.disposition_options = pdict
478 self.name = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000479 if 'name' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000480 self.name = pdict['name']
481 self.filename = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000482 if 'filename' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000483 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000484
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000485 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000486 #
487 # Honor any existing content-type header. But if there is no
488 # content-type header, use some sensible defaults. Assume
489 # outerboundary is "" at the outer level, but something non-false
490 # inside a multi-part. The default for an inner part is text/plain,
491 # but for an outer part it should be urlencoded. This should catch
492 # bogus clients which erroneously forget to include a content-type
493 # header.
494 #
495 # See below for what we do if there does exist a content-type header,
496 # but it happens to be something we don't understand.
Raymond Hettinger54f02222002-06-01 14:18:47 +0000497 if 'content-type' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000498 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000499 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000500 ctype, pdict = "text/plain", {}
501 else:
502 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000503 self.type = ctype
504 self.type_options = pdict
505 self.innerboundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000506 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000507 self.innerboundary = pdict['boundary']
508 clen = -1
Raymond Hettinger54f02222002-06-01 14:18:47 +0000509 if 'content-length' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000510 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000511 clen = int(self.headers['content-length'])
Skip Montanarodb5d1442002-03-23 05:50:17 +0000512 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000513 pass
514 if maxlen and clen > maxlen:
515 raise ValueError, 'Maximum content length exceeded'
516 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000517
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000518 self.list = self.file = None
519 self.done = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000520 if ctype == 'application/x-www-form-urlencoded':
521 self.read_urlencoded()
522 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000523 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000524 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000525 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000526
527 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000528 """Return a printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000529 return "FieldStorage(%r, %r, %r)" % (
530 self.name, self.filename, self.value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000531
Guido van Rossum4061cbe2002-09-11 18:20:34 +0000532 def __iter__(self):
533 return iter(self.keys())
534
Guido van Rossum7aee3841996-03-07 18:00:44 +0000535 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000536 if name != 'value':
537 raise AttributeError, name
538 if self.file:
539 self.file.seek(0)
540 value = self.file.read()
541 self.file.seek(0)
542 elif self.list is not None:
543 value = self.list
544 else:
545 value = None
546 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000547
548 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000549 """Dictionary style indexing."""
550 if self.list is None:
551 raise TypeError, "not indexable"
552 found = []
553 for item in self.list:
554 if item.name == key: found.append(item)
555 if not found:
556 raise KeyError, key
557 if len(found) == 1:
558 return found[0]
559 else:
560 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000561
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000562 def getvalue(self, key, default=None):
563 """Dictionary style get() method, including 'value' lookup."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000564 if key in self:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000565 value = self[key]
566 if type(value) is type([]):
567 return map(lambda v: v.value, value)
568 else:
569 return value.value
570 else:
571 return default
572
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000573 def getfirst(self, key, default=None):
574 """ Return the first value received."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000575 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000576 value = self[key]
577 if type(value) is type([]):
578 return value[0].value
579 else:
580 return value.value
581 else:
582 return default
583
584 def getlist(self, key):
585 """ Return list of received values."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000586 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000587 value = self[key]
588 if type(value) is type([]):
589 return map(lambda v: v.value, value)
590 else:
591 return [value.value]
592 else:
593 return []
594
Guido van Rossum7aee3841996-03-07 18:00:44 +0000595 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000596 """Dictionary style keys() method."""
597 if self.list is None:
598 raise TypeError, "not indexable"
599 keys = []
600 for item in self.list:
601 if item.name not in keys: keys.append(item.name)
602 return keys
Guido van Rossum7aee3841996-03-07 18:00:44 +0000603
Guido van Rossum0147db01996-03-09 03:16:04 +0000604 def has_key(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000605 """Dictionary style has_key() method."""
606 if self.list is None:
607 raise TypeError, "not indexable"
608 for item in self.list:
Tim Petersbc0e9102002-04-04 22:55:58 +0000609 if item.name == key: return True
610 return False
Guido van Rossum0147db01996-03-09 03:16:04 +0000611
Raymond Hettinger54f02222002-06-01 14:18:47 +0000612 def __contains__(self, key):
613 """Dictionary style __contains__ method."""
614 if self.list is None:
615 raise TypeError, "not indexable"
616 for item in self.list:
617 if item.name == key: return True
618 return False
619
Guido van Rossum88b85d41997-01-11 19:21:33 +0000620 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000621 """Dictionary style len(x) support."""
622 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000623
Guido van Rossum7aee3841996-03-07 18:00:44 +0000624 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000625 """Internal: read data in query string format."""
626 qs = self.fp.read(self.length)
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000627 self.list = list = []
628 for key, value in parse_qsl(qs, self.keep_blank_values,
629 self.strict_parsing):
630 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000631 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000632
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000633 FieldStorageClass = None
634
Guido van Rossumf5745001998-10-20 14:43:02 +0000635 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000636 """Internal: read a part that is itself multipart."""
Guido van Rossum2e441f72001-07-25 21:00:19 +0000637 ib = self.innerboundary
638 if not valid_boundary(ib):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000639 raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000640 self.list = []
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000641 klass = self.FieldStorageClass or self.__class__
Guido van Rossum2e441f72001-07-25 21:00:19 +0000642 part = klass(self.fp, {}, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000643 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000644 # Throw first part away
645 while not part.done:
646 headers = rfc822.Message(self.fp)
Guido van Rossum2e441f72001-07-25 21:00:19 +0000647 part = klass(self.fp, headers, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000648 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000649 self.list.append(part)
650 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000651
652 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000653 """Internal: read an atomic part."""
654 if self.length >= 0:
655 self.read_binary()
656 self.skip_lines()
657 else:
658 self.read_lines()
659 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000660
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000661 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000662
663 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000664 """Internal: read binary data."""
665 self.file = self.make_file('b')
666 todo = self.length
667 if todo >= 0:
668 while todo > 0:
669 data = self.fp.read(min(todo, self.bufsize))
670 if not data:
671 self.done = -1
672 break
673 self.file.write(data)
674 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000675
676 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000677 """Internal: read lines until EOF or outerboundary."""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000678 self.file = self.__file = StringIO()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000679 if self.outerboundary:
680 self.read_lines_to_outerboundary()
681 else:
682 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000683
Guido van Rossum52b8c292001-06-29 13:06:06 +0000684 def __write(self, line):
685 if self.__file is not None:
686 if self.__file.tell() + len(line) > 1000:
687 self.file = self.make_file('')
688 self.file.write(self.__file.getvalue())
689 self.__file = None
690 self.file.write(line)
691
Guido van Rossum7aee3841996-03-07 18:00:44 +0000692 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000693 """Internal: read lines until EOF."""
694 while 1:
695 line = self.fp.readline()
696 if not line:
697 self.done = -1
698 break
Guido van Rossum52b8c292001-06-29 13:06:06 +0000699 self.__write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000700
701 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000702 """Internal: read lines until outerboundary."""
703 next = "--" + self.outerboundary
704 last = next + "--"
705 delim = ""
706 while 1:
707 line = self.fp.readline()
708 if not line:
709 self.done = -1
710 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000711 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000712 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000713 if strippedline == next:
714 break
715 if strippedline == last:
716 self.done = 1
717 break
718 odelim = delim
719 if line[-2:] == "\r\n":
720 delim = "\r\n"
721 line = line[:-2]
722 elif line[-1] == "\n":
723 delim = "\n"
724 line = line[:-1]
725 else:
726 delim = ""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000727 self.__write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000728
729 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000730 """Internal: skip lines until outer boundary if defined."""
731 if not self.outerboundary or self.done:
732 return
733 next = "--" + self.outerboundary
734 last = next + "--"
735 while 1:
736 line = self.fp.readline()
737 if not line:
738 self.done = -1
739 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000740 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000741 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000742 if strippedline == next:
743 break
744 if strippedline == last:
745 self.done = 1
746 break
Guido van Rossum7aee3841996-03-07 18:00:44 +0000747
Guido van Rossuma5e9fb61997-08-12 18:18:13 +0000748 def make_file(self, binary=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000749 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000750
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000751 The file will be used as follows:
752 - data is written to it
753 - seek(0)
754 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +0000755
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000756 The 'binary' argument is unused -- the file is always opened
757 in binary mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000758
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000759 This version opens a temporary file for reading and writing,
760 and immediately deletes (unlinks) it. The trick (on Unix!) is
761 that the file can still be used, but it can't be opened by
762 another process, and it will automatically be deleted when it
763 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000764
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000765 If you want a more permanent file, you derive a class which
766 overrides this method. If you want a visible temporary file
767 that is nevertheless automatically deleted when the script
768 terminates, try defining a __del__ method in a derived class
769 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000770
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000771 """
772 import tempfile
773 return tempfile.TemporaryFile("w+b")
Tim Peters88869f92001-01-14 23:36:06 +0000774
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000775
776
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000777# Backwards Compatibility Classes
778# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +0000779
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000780class FormContentDict(UserDict.UserDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000781 """Form content as dictionary with a list of values per field.
Guido van Rossum72755611996-03-06 07:20:06 +0000782
Guido van Rossum7aee3841996-03-07 18:00:44 +0000783 form = FormContentDict()
784
785 form[key] -> [value, value, ...]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000786 key in form -> Boolean
Guido van Rossum7aee3841996-03-07 18:00:44 +0000787 form.keys() -> [key, key, ...]
788 form.values() -> [[val, val, ...], [val, val, ...], ...]
789 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
790 form.dict == {key: [val, val, ...], ...}
791
792 """
Guido van Rossum773ab271996-07-23 03:46:24 +0000793 def __init__(self, environ=os.environ):
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000794 self.dict = self.data = parse(environ=environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000795 self.query_string = environ['QUERY_STRING']
Guido van Rossum9a22de11995-01-12 12:29:47 +0000796
797
Guido van Rossum9a22de11995-01-12 12:29:47 +0000798class SvFormContentDict(FormContentDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000799 """Form content as dictionary expecting a single value per field.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000800
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000801 If you only expect a single value for each field, then form[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000802 will return that single value. It will raise an IndexError if
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000803 that expectation is not true. If you expect a field to have
Guido van Rossum7aee3841996-03-07 18:00:44 +0000804 possible multiple values, than you can use form.getlist(key) to
805 get all of the values. values() and items() are a compromise:
806 they return single strings where there is a single value, and
807 lists of strings otherwise.
808
809 """
810 def __getitem__(self, key):
Tim Peters88869f92001-01-14 23:36:06 +0000811 if len(self.dict[key]) > 1:
812 raise IndexError, 'expecting a single value'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000813 return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000814 def getlist(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000815 return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000816 def values(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000817 result = []
818 for value in self.dict.values():
819 if len(value) == 1:
820 result.append(value[0])
821 else: result.append(value)
822 return result
Guido van Rossum7aee3841996-03-07 18:00:44 +0000823 def items(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000824 result = []
825 for key, value in self.dict.items():
826 if len(value) == 1:
827 result.append((key, value[0]))
828 else: result.append((key, value))
829 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000830
831
Guido van Rossum9a22de11995-01-12 12:29:47 +0000832class InterpFormContentDict(SvFormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000833 """This class is present for backwards compatibility only."""
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000834 def __getitem__(self, key):
835 v = SvFormContentDict.__getitem__(self, key)
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000836 if v[0] in '0123456789+-.':
837 try: return int(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000838 except ValueError:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000839 try: return float(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000840 except ValueError: pass
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000841 return v.strip()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000842 def values(self):
843 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000844 for key in self.keys():
845 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000846 result.append(self[key])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000847 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000848 result.append(self.dict[key])
849 return result
850 def items(self):
851 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000852 for key in self.keys():
853 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000854 result.append((key, self[key]))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000855 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000856 result.append((key, self.dict[key]))
857 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000858
859
Guido van Rossum9a22de11995-01-12 12:29:47 +0000860class FormContent(FormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000861 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +0000862 def values(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000863 if key in self.dict :return self.dict[key]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000864 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000865 def indexed_value(self, key, location):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000866 if key in self.dict:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000867 if len(self.dict[key]) > location:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000868 return self.dict[key][location]
869 else: return None
870 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000871 def value(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000872 if key in self.dict: return self.dict[key][0]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000873 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000874 def length(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000875 return len(self.dict[key])
Guido van Rossum0147db01996-03-09 03:16:04 +0000876 def stripped(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000877 if key in self.dict: return self.dict[key][0].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000878 else: return None
Guido van Rossum7aee3841996-03-07 18:00:44 +0000879 def pars(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000880 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000881
882
Guido van Rossum72755611996-03-06 07:20:06 +0000883# Test/debug code
884# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +0000885
Guido van Rossum773ab271996-07-23 03:46:24 +0000886def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000887 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000888
Guido van Rossum7aee3841996-03-07 18:00:44 +0000889 Write minimal HTTP headers and dump all information provided to
890 the script in HTML form.
891
892 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000893 print "Content-type: text/html"
894 print
895 sys.stderr = sys.stdout
896 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000897 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000898 print_directory()
899 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000900 print_form(form)
901 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000902 print_environ_usage()
903 def f():
904 exec "testing print_exception() -- <I>italics?</I>"
905 def g(f=f):
906 f()
907 print "<H3>What follows is a test, not an actual exception:</H3>"
908 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000909 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000910 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000911
Guido van Rossum57d51f22000-09-16 21:16:01 +0000912 print "<H1>Second try with a small maxlen...</H1>"
913
Guido van Rossumad164711997-05-13 19:03:23 +0000914 global maxlen
915 maxlen = 50
916 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000917 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000918 print_directory()
919 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000920 print_form(form)
921 print_environ(environ)
Guido van Rossumad164711997-05-13 19:03:23 +0000922 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000923 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +0000924
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000925def print_exception(type=None, value=None, tb=None, limit=None):
926 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000927 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000928 import traceback
929 print
Guido van Rossum7dd06962000-12-27 19:12:58 +0000930 print "<H3>Traceback (most recent call last):</H3>"
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000931 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000932 traceback.format_exception_only(type, value)
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000933 print "<PRE>%s<B>%s</B></PRE>" % (
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000934 escape("".join(list[:-1])),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000935 escape(list[-1]),
936 )
Guido van Rossumf15d1591997-09-29 23:22:12 +0000937 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +0000938
Guido van Rossum773ab271996-07-23 03:46:24 +0000939def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000940 """Dump the shell environment as HTML."""
941 keys = environ.keys()
942 keys.sort()
943 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000944 print "<H3>Shell Environment:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000945 print "<DL>"
946 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000947 print "<DT>", escape(key), "<DD>", escape(environ[key])
Tim Peters88869f92001-01-14 23:36:06 +0000948 print "</DL>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000949 print
Guido van Rossum72755611996-03-06 07:20:06 +0000950
951def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000952 """Dump the contents of a form as HTML."""
953 keys = form.keys()
954 keys.sort()
955 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000956 print "<H3>Form Contents:</H3>"
Guido van Rossum57d51f22000-09-16 21:16:01 +0000957 if not keys:
958 print "<P>No form fields."
Guido van Rossum7aee3841996-03-07 18:00:44 +0000959 print "<DL>"
960 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000961 print "<DT>" + escape(key) + ":",
962 value = form[key]
Walter Dörwald70a6b492004-02-12 17:35:32 +0000963 print "<i>" + escape(repr(type(value))) + "</i>"
964 print "<DD>" + escape(repr(value))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000965 print "</DL>"
966 print
967
968def print_directory():
969 """Dump the current directory as HTML."""
970 print
971 print "<H3>Current Working Directory:</H3>"
972 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000973 pwd = os.getcwd()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000974 except os.error, msg:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000975 print "os.error:", escape(str(msg))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000976 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000977 print escape(pwd)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000978 print
Guido van Rossum9a22de11995-01-12 12:29:47 +0000979
Guido van Rossuma8738a51996-03-14 21:30:28 +0000980def print_arguments():
981 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000982 print "<H3>Command Line Arguments:</H3>"
Guido van Rossuma8738a51996-03-14 21:30:28 +0000983 print
984 print sys.argv
985 print
986
Guido van Rossum9a22de11995-01-12 12:29:47 +0000987def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +0000988 """Dump a list of environment variables used by CGI as HTML."""
989 print """
Guido van Rossum72755611996-03-06 07:20:06 +0000990<H3>These environment variables could have been set:</H3>
991<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +0000992<LI>AUTH_TYPE
993<LI>CONTENT_LENGTH
994<LI>CONTENT_TYPE
995<LI>DATE_GMT
996<LI>DATE_LOCAL
997<LI>DOCUMENT_NAME
998<LI>DOCUMENT_ROOT
999<LI>DOCUMENT_URI
1000<LI>GATEWAY_INTERFACE
1001<LI>LAST_MODIFIED
1002<LI>PATH
1003<LI>PATH_INFO
1004<LI>PATH_TRANSLATED
1005<LI>QUERY_STRING
1006<LI>REMOTE_ADDR
1007<LI>REMOTE_HOST
1008<LI>REMOTE_IDENT
1009<LI>REMOTE_USER
1010<LI>REQUEST_METHOD
1011<LI>SCRIPT_NAME
1012<LI>SERVER_NAME
1013<LI>SERVER_PORT
1014<LI>SERVER_PROTOCOL
1015<LI>SERVER_ROOT
1016<LI>SERVER_SOFTWARE
1017</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001018In addition, HTTP headers sent by the server may be passed in the
1019environment as well. Here are some common variable names:
1020<UL>
1021<LI>HTTP_ACCEPT
1022<LI>HTTP_CONNECTION
1023<LI>HTTP_HOST
1024<LI>HTTP_PRAGMA
1025<LI>HTTP_REFERER
1026<LI>HTTP_USER_AGENT
1027</UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001028"""
1029
Guido van Rossum9a22de11995-01-12 12:29:47 +00001030
Guido van Rossum72755611996-03-06 07:20:06 +00001031# Utilities
1032# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001033
Guido van Rossum64c66201997-07-19 20:11:53 +00001034def escape(s, quote=None):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001035 """Replace special characters '&', '<' and '>' by SGML entities."""
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001036 s = s.replace("&", "&amp;") # Must be done first!
1037 s = s.replace("<", "&lt;")
1038 s = s.replace(">", "&gt;")
Guido van Rossum64c66201997-07-19 20:11:53 +00001039 if quote:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001040 s = s.replace('"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +00001041 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001042
Guido van Rossum2e441f72001-07-25 21:00:19 +00001043def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
1044 import re
1045 return re.match(_vb_pattern, s)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001046
Guido van Rossum72755611996-03-06 07:20:06 +00001047# Invoke mainline
1048# ===============
1049
1050# Call test() when this file is run as a script (not imported as a module)
Tim Peters88869f92001-01-14 23:36:06 +00001051if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001052 test()