blob: 5ddf16e8f8819dea68edb26d621ae56753fdac29 [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
Raymond Hettingerf871d832004-12-31 21:59:02 +000037from operator import attrgetter
Guido van Rossum72755611996-03-06 07:20:06 +000038import sys
39import os
Guido van Rossuma5e9fb61997-08-12 18:18:13 +000040import urllib
Armin Rigo3a703b62005-09-19 09:11:04 +000041import mimetools
42import rfc822
Moshe Zadkaa1a4b592000-08-25 21:47:56 +000043import UserDict
Raymond Hettingera6172712004-12-31 19:15:26 +000044try:
45 from cStringIO import StringIO
46except ImportError:
47 from StringIO import StringIO
Guido van Rossum72755611996-03-06 07:20:06 +000048
Guido van Rossuma8423a92001-03-19 13:40:44 +000049__all__ = ["MiniFieldStorage", "FieldStorage", "FormContentDict",
50 "SvFormContentDict", "InterpFormContentDict", "FormContent",
51 "parse", "parse_qs", "parse_qsl", "parse_multipart",
52 "parse_header", "print_exception", "print_environ",
53 "print_form", "print_directory", "print_arguments",
54 "print_environ_usage", "escape"]
Guido van Rossumc204c701996-09-05 19:07:11 +000055
56# Logging support
57# ===============
58
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000059logfile = "" # Filename to log to, if not empty
60logfp = None # File object to log to, if not None
Guido van Rossumc204c701996-09-05 19:07:11 +000061
62def initlog(*allargs):
63 """Write a log message, if there is a log file.
64
65 Even though this function is called initlog(), you should always
66 use log(); log is a variable that is set either to initlog
67 (initially), to dolog (once the log file has been opened), or to
68 nolog (when logging is disabled).
69
70 The first argument is a format string; the remaining arguments (if
71 any) are arguments to the % operator, so e.g.
72 log("%s: %s", "a", "b")
73 will write "a: b" to the log file, followed by a newline.
74
75 If the global logfp is not None, it should be a file object to
76 which log data is written.
77
78 If the global logfp is None, the global logfile may be a string
79 giving a filename to open, in append mode. This file should be
80 world writable!!! If the file can't be opened, logging is
81 silently disabled (since there is no safe place where we could
82 send an error message).
83
84 """
85 global logfp, log
86 if logfile and not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000087 try:
88 logfp = open(logfile, "a")
89 except IOError:
90 pass
Guido van Rossumc204c701996-09-05 19:07:11 +000091 if not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000092 log = nolog
Guido van Rossumc204c701996-09-05 19:07:11 +000093 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000094 log = dolog
Guido van Rossum68468eb2003-02-27 20:14:51 +000095 log(*allargs)
Guido van Rossumc204c701996-09-05 19:07:11 +000096
97def dolog(fmt, *args):
98 """Write a log message to the log file. See initlog() for docs."""
99 logfp.write(fmt%args + "\n")
100
101def nolog(*allargs):
102 """Dummy function, assigned to log when logging is disabled."""
103 pass
104
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000105log = initlog # The current logging function
Guido van Rossumc204c701996-09-05 19:07:11 +0000106
107
Guido van Rossum72755611996-03-06 07:20:06 +0000108# Parsing functions
109# =================
110
Guido van Rossumad164711997-05-13 19:03:23 +0000111# Maximum input we will accept when REQUEST_METHOD is POST
112# 0 ==> unlimited input
113maxlen = 0
114
Guido van Rossume08c04c1996-11-11 19:29:11 +0000115def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum773ab271996-07-23 03:46:24 +0000116 """Parse a query in the environment or from a file (default stdin)
117
118 Arguments, all optional:
119
120 fp : file pointer; default: sys.stdin
121
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000122 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000123
124 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000125 URL encoded forms should be treated as blank strings.
126 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000127 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000128 blank values are to be ignored and treated as if they were
129 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000130
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000131 strict_parsing: flag indicating what to do with parsing errors.
132 If false (the default), errors are silently ignored.
133 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000134 """
Raymond Hettingera1449002002-05-31 23:54:44 +0000135 if fp is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000136 fp = sys.stdin
Raymond Hettinger54f02222002-06-01 14:18:47 +0000137 if not 'REQUEST_METHOD' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000138 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
Guido van Rossum7aee3841996-03-07 18:00:44 +0000139 if environ['REQUEST_METHOD'] == 'POST':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000140 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
141 if ctype == 'multipart/form-data':
142 return parse_multipart(fp, pdict)
143 elif ctype == 'application/x-www-form-urlencoded':
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000144 clength = int(environ['CONTENT_LENGTH'])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000145 if maxlen and clength > maxlen:
146 raise ValueError, 'Maximum content length exceeded'
147 qs = fp.read(clength)
148 else:
149 qs = '' # Unknown content-type
Raymond Hettinger54f02222002-06-01 14:18:47 +0000150 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000151 if qs: qs = qs + '&'
152 qs = qs + environ['QUERY_STRING']
Tim Peters88869f92001-01-14 23:36:06 +0000153 elif sys.argv[1:]:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000154 if qs: qs = qs + '&'
155 qs = qs + sys.argv[1]
156 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Raymond Hettinger54f02222002-06-01 14:18:47 +0000157 elif 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000158 qs = environ['QUERY_STRING']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000159 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000160 if sys.argv[1:]:
161 qs = sys.argv[1]
162 else:
163 qs = ""
164 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossume08c04c1996-11-11 19:29:11 +0000165 return parse_qs(qs, keep_blank_values, strict_parsing)
Guido van Rossume7808771995-08-07 20:12:09 +0000166
167
Guido van Rossume08c04c1996-11-11 19:29:11 +0000168def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
169 """Parse a query given as a string argument.
Guido van Rossum773ab271996-07-23 03:46:24 +0000170
171 Arguments:
172
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000173 qs: URL-encoded query string to be parsed
Guido van Rossum773ab271996-07-23 03:46:24 +0000174
175 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000176 URL encoded queries should be treated as blank strings.
177 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000178 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000179 blank values are to be ignored and treated as if they were
180 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000181
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000182 strict_parsing: flag indicating what to do with parsing errors.
183 If false (the default), errors are silently ignored.
184 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000185 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000186 dict = {}
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000187 for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000188 if name in dict:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000189 dict[name].append(value)
190 else:
191 dict[name] = [value]
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000192 return dict
193
194def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
195 """Parse a query given as a string argument.
196
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000197 Arguments:
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000198
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000199 qs: URL-encoded query string to be parsed
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000200
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000201 keep_blank_values: flag indicating whether blank values in
202 URL encoded queries should be treated as blank strings. A
203 true value indicates that blanks should be retained as blank
204 strings. The default false value indicates that blank values
205 are to be ignored and treated as if they were not included.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000206
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000207 strict_parsing: flag indicating what to do with parsing errors. If
208 false (the default), errors are silently ignored. If true,
Tim Peters88869f92001-01-14 23:36:06 +0000209 errors raise a ValueError exception.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000210
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000211 Returns a list, as G-d intended.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000212 """
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000213 pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
214 r = []
215 for name_value in pairs:
Neil Schemenauer66edb622004-07-19 15:38:11 +0000216 if not name_value and not strict_parsing:
217 continue
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000218 nv = name_value.split('=', 1)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000219 if len(nv) != 2:
220 if strict_parsing:
Walter Dörwald70a6b492004-02-12 17:35:32 +0000221 raise ValueError, "bad query field: %r" % (name_value,)
Brett Cannon8d9b60f2004-03-21 22:16:15 +0000222 # Handle case of a control-name with no equal sign
223 if keep_blank_values:
224 nv.append('')
225 else:
226 continue
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000227 if len(nv[1]) or keep_blank_values:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000228 name = urllib.unquote(nv[0].replace('+', ' '))
229 value = urllib.unquote(nv[1].replace('+', ' '))
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000230 r.append((name, value))
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000231
232 return r
Guido van Rossum9a22de11995-01-12 12:29:47 +0000233
234
Guido van Rossum0147db01996-03-09 03:16:04 +0000235def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000236 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000237
Guido van Rossum7aee3841996-03-07 18:00:44 +0000238 Arguments:
239 fp : input file
Johannes Gijsbersc7fc10a2005-01-08 13:56:36 +0000240 pdict: dictionary containing other parameters of content-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000241
Tim Peters88869f92001-01-14 23:36:06 +0000242 Returns a dictionary just like parse_qs(): keys are the field names, each
243 value is a list of values for that field. This is easy to use but not
244 much good if you are expecting megabytes to be uploaded -- in that case,
245 use the FieldStorage class instead which is much more flexible. Note
246 that content-type is the raw, unparsed contents of the content-type
Guido van Rossum0147db01996-03-09 03:16:04 +0000247 header.
Tim Peters88869f92001-01-14 23:36:06 +0000248
249 XXX This does not parse nested multipart parts -- use FieldStorage for
Guido van Rossum0147db01996-03-09 03:16:04 +0000250 that.
Tim Peters88869f92001-01-14 23:36:06 +0000251
252 XXX This should really be subsumed by FieldStorage altogether -- no
Guido van Rossum0147db01996-03-09 03:16:04 +0000253 point in having two implementations of the same parsing algorithm.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000254 Also, FieldStorage protects itself better against certain DoS attacks
255 by limiting the size of the data read in one chunk. The API here
256 does not support that kind of protection. This also affects parse()
257 since it can call parse_multipart().
Guido van Rossum72755611996-03-06 07:20:06 +0000258
Guido van Rossum7aee3841996-03-07 18:00:44 +0000259 """
Guido van Rossum2e441f72001-07-25 21:00:19 +0000260 boundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000261 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000262 boundary = pdict['boundary']
Guido van Rossum2e441f72001-07-25 21:00:19 +0000263 if not valid_boundary(boundary):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000264 raise ValueError, ('Invalid boundary in multipart form: %r'
265 % (boundary,))
Tim Petersab9ba272001-08-09 21:40:30 +0000266
Guido van Rossum7aee3841996-03-07 18:00:44 +0000267 nextpart = "--" + boundary
268 lastpart = "--" + boundary + "--"
269 partdict = {}
270 terminator = ""
271
272 while terminator != lastpart:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000273 bytes = -1
274 data = None
275 if terminator:
276 # At start of next part. Read headers first.
Armin Rigo3a703b62005-09-19 09:11:04 +0000277 headers = mimetools.Message(fp)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000278 clength = headers.getheader('content-length')
279 if clength:
280 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000281 bytes = int(clength)
282 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000283 pass
284 if bytes > 0:
285 if maxlen and bytes > maxlen:
286 raise ValueError, 'Maximum content length exceeded'
287 data = fp.read(bytes)
288 else:
289 data = ""
290 # Read lines until end of part.
291 lines = []
292 while 1:
293 line = fp.readline()
294 if not line:
295 terminator = lastpart # End outer loop
296 break
297 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000298 terminator = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000299 if terminator in (nextpart, lastpart):
300 break
301 lines.append(line)
302 # Done with part.
303 if data is None:
304 continue
305 if bytes < 0:
306 if lines:
307 # Strip final line terminator
308 line = lines[-1]
309 if line[-2:] == "\r\n":
310 line = line[:-2]
311 elif line[-1:] == "\n":
312 line = line[:-1]
313 lines[-1] = line
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000314 data = "".join(lines)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000315 line = headers['content-disposition']
316 if not line:
317 continue
318 key, params = parse_header(line)
319 if key != 'form-data':
320 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000321 if 'name' in params:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000322 name = params['name']
323 else:
324 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000325 if name in partdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000326 partdict[name].append(data)
327 else:
328 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000329
Guido van Rossum7aee3841996-03-07 18:00:44 +0000330 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000331
332
Guido van Rossum72755611996-03-06 07:20:06 +0000333def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000334 """Parse a Content-type like header.
335
336 Return the main content-type and a dictionary of options.
337
338 """
Raymond Hettingerf871d832004-12-31 21:59:02 +0000339 plist = [x.strip() for x in line.split(';')]
Raymond Hettinger46ac8eb2002-06-30 03:39:14 +0000340 key = plist.pop(0).lower()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000341 pdict = {}
342 for p in plist:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000343 i = p.find('=')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000344 if i >= 0:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000345 name = p[:i].strip().lower()
346 value = p[i+1:].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000347 if len(value) >= 2 and value[0] == value[-1] == '"':
348 value = value[1:-1]
Johannes Gijsbers9e15dd62004-08-14 15:39:34 +0000349 value = value.replace('\\\\', '\\').replace('\\"', '"')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000350 pdict[name] = value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000351 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000352
353
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000354# Classes for field storage
355# =========================
356
357class MiniFieldStorage:
358
Guido van Rossum0147db01996-03-09 03:16:04 +0000359 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000360
Guido van Rossum7aee3841996-03-07 18:00:44 +0000361 # Dummy attributes
362 filename = None
363 list = None
364 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000365 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000366 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000367 disposition = None
368 disposition_options = {}
369 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000370
Guido van Rossum7aee3841996-03-07 18:00:44 +0000371 def __init__(self, name, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000372 """Constructor from field name and value."""
373 self.name = name
374 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000375 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000376
377 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000378 """Return printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000379 return "MiniFieldStorage(%r, %r)" % (self.name, self.value)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000380
381
382class FieldStorage:
383
Guido van Rossum7aee3841996-03-07 18:00:44 +0000384 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000385
Guido van Rossum7aee3841996-03-07 18:00:44 +0000386 This class provides naming, typing, files stored on disk, and
387 more. At the top level, it is accessible like a dictionary, whose
388 keys are the field names. (Note: None can occur as a field name.)
389 The items are either a Python list (if there's multiple values) or
390 another FieldStorage or MiniFieldStorage object. If it's a single
391 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000392
Guido van Rossum7aee3841996-03-07 18:00:44 +0000393 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000394
Guido van Rossum7aee3841996-03-07 18:00:44 +0000395 filename: the filename, if specified; otherwise None; this is the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000396 client side filename, *not* the file name on which it is
397 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000398
Guido van Rossum7aee3841996-03-07 18:00:44 +0000399 value: the value as a *string*; for file uploads, this
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000400 transparently reads the file every time you request the value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000401
402 file: the file(-like) object from which you can read the data;
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000403 None if the data is stored a simple string
Guido van Rossum7aee3841996-03-07 18:00:44 +0000404
405 type: the content-type, or None if not specified
406
407 type_options: dictionary of options specified on the content-type
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000408 line
Guido van Rossum7aee3841996-03-07 18:00:44 +0000409
410 disposition: content-disposition, or None if not specified
411
412 disposition_options: dictionary of corresponding options
413
Armin Rigo3a703b62005-09-19 09:11:04 +0000414 headers: a dictionary(-like) object (sometimes rfc822.Message or a
415 subclass thereof) containing *all* headers
Guido van Rossum7aee3841996-03-07 18:00:44 +0000416
417 The class is subclassable, mostly for the purpose of overriding
418 the make_file() method, which is called internally to come up with
419 a file open for reading and writing. This makes it possible to
420 override the default choice of storing all files in a temporary
421 directory and unlinking them as soon as they have been opened.
422
423 """
424
Guido van Rossum773ab271996-07-23 03:46:24 +0000425 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000426 environ=os.environ, keep_blank_values=0, strict_parsing=0):
427 """Constructor. Read multipart/* until last part.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000428
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000429 Arguments, all optional:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000430
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000431 fp : file pointer; default: sys.stdin
Guido van Rossumb1b4f941998-05-08 19:55:51 +0000432 (not used when the request method is GET)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000433
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000434 headers : header dictionary-like object; default:
435 taken from environ as per CGI spec
Guido van Rossum7aee3841996-03-07 18:00:44 +0000436
Guido van Rossum773ab271996-07-23 03:46:24 +0000437 outerboundary : terminating multipart boundary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000438 (for internal use only)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000439
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000440 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000441
442 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000443 URL encoded forms should be treated as blank strings.
444 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000445 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000446 blank values are to be ignored and treated as if they were
447 not included.
Guido van Rossum773ab271996-07-23 03:46:24 +0000448
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000449 strict_parsing: flag indicating what to do with parsing errors.
450 If false (the default), errors are silently ignored.
451 If true, errors raise a ValueError exception.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000452
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000453 """
454 method = 'GET'
455 self.keep_blank_values = keep_blank_values
456 self.strict_parsing = strict_parsing
Raymond Hettinger54f02222002-06-01 14:18:47 +0000457 if 'REQUEST_METHOD' in environ:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000458 method = environ['REQUEST_METHOD'].upper()
Guido van Rossum01852831998-06-25 02:40:17 +0000459 if method == 'GET' or method == 'HEAD':
Raymond Hettinger54f02222002-06-01 14:18:47 +0000460 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000461 qs = environ['QUERY_STRING']
462 elif sys.argv[1:]:
463 qs = sys.argv[1]
464 else:
465 qs = ""
466 fp = StringIO(qs)
467 if headers is None:
468 headers = {'content-type':
469 "application/x-www-form-urlencoded"}
470 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000471 headers = {}
472 if method == 'POST':
473 # Set default content-type for POST to what's traditional
474 headers['content-type'] = "application/x-www-form-urlencoded"
Raymond Hettinger54f02222002-06-01 14:18:47 +0000475 if 'CONTENT_TYPE' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000476 headers['content-type'] = environ['CONTENT_TYPE']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000477 if 'CONTENT_LENGTH' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000478 headers['content-length'] = environ['CONTENT_LENGTH']
479 self.fp = fp or sys.stdin
480 self.headers = headers
481 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000482
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000483 # Process content-disposition header
484 cdisp, pdict = "", {}
Raymond Hettinger54f02222002-06-01 14:18:47 +0000485 if 'content-disposition' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000486 cdisp, pdict = parse_header(self.headers['content-disposition'])
487 self.disposition = cdisp
488 self.disposition_options = pdict
489 self.name = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000490 if 'name' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000491 self.name = pdict['name']
492 self.filename = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000493 if 'filename' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000494 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000495
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000496 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000497 #
498 # Honor any existing content-type header. But if there is no
499 # content-type header, use some sensible defaults. Assume
500 # outerboundary is "" at the outer level, but something non-false
501 # inside a multi-part. The default for an inner part is text/plain,
502 # but for an outer part it should be urlencoded. This should catch
503 # bogus clients which erroneously forget to include a content-type
504 # header.
505 #
506 # See below for what we do if there does exist a content-type header,
507 # but it happens to be something we don't understand.
Raymond Hettinger54f02222002-06-01 14:18:47 +0000508 if 'content-type' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000509 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000510 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000511 ctype, pdict = "text/plain", {}
512 else:
513 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000514 self.type = ctype
515 self.type_options = pdict
516 self.innerboundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000517 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000518 self.innerboundary = pdict['boundary']
519 clen = -1
Raymond Hettinger54f02222002-06-01 14:18:47 +0000520 if 'content-length' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000521 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000522 clen = int(self.headers['content-length'])
Skip Montanarodb5d1442002-03-23 05:50:17 +0000523 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000524 pass
525 if maxlen and clen > maxlen:
526 raise ValueError, 'Maximum content length exceeded'
527 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000528
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000529 self.list = self.file = None
530 self.done = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000531 if ctype == 'application/x-www-form-urlencoded':
532 self.read_urlencoded()
533 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000534 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000535 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000536 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000537
538 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000539 """Return a printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000540 return "FieldStorage(%r, %r, %r)" % (
541 self.name, self.filename, self.value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000542
Guido van Rossum4061cbe2002-09-11 18:20:34 +0000543 def __iter__(self):
544 return iter(self.keys())
545
Guido van Rossum7aee3841996-03-07 18:00:44 +0000546 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000547 if name != 'value':
548 raise AttributeError, name
549 if self.file:
550 self.file.seek(0)
551 value = self.file.read()
552 self.file.seek(0)
553 elif self.list is not None:
554 value = self.list
555 else:
556 value = None
557 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000558
559 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000560 """Dictionary style indexing."""
561 if self.list is None:
562 raise TypeError, "not indexable"
563 found = []
564 for item in self.list:
565 if item.name == key: found.append(item)
566 if not found:
567 raise KeyError, key
568 if len(found) == 1:
569 return found[0]
570 else:
571 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000572
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000573 def getvalue(self, key, default=None):
574 """Dictionary style get() method, including 'value' lookup."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000575 if key in self:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000576 value = self[key]
577 if type(value) is type([]):
Raymond Hettingerf871d832004-12-31 21:59:02 +0000578 return map(attrgetter('value'), value)
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000579 else:
580 return value.value
581 else:
582 return default
583
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000584 def getfirst(self, key, default=None):
585 """ Return the first value received."""
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 value[0].value
590 else:
591 return value.value
592 else:
593 return default
594
595 def getlist(self, key):
596 """ Return list of received values."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000597 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000598 value = self[key]
599 if type(value) is type([]):
Raymond Hettingerf871d832004-12-31 21:59:02 +0000600 return map(attrgetter('value'), value)
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000601 else:
602 return [value.value]
603 else:
604 return []
605
Guido van Rossum7aee3841996-03-07 18:00:44 +0000606 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000607 """Dictionary style keys() method."""
608 if self.list is None:
609 raise TypeError, "not indexable"
610 keys = []
611 for item in self.list:
612 if item.name not in keys: keys.append(item.name)
613 return keys
Guido van Rossum7aee3841996-03-07 18:00:44 +0000614
Raymond Hettinger54f02222002-06-01 14:18:47 +0000615 def __contains__(self, key):
616 """Dictionary style __contains__ method."""
617 if self.list is None:
618 raise TypeError, "not indexable"
619 for item in self.list:
620 if item.name == key: return True
621 return False
622
Guido van Rossum88b85d41997-01-11 19:21:33 +0000623 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000624 """Dictionary style len(x) support."""
625 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000626
Guido van Rossum7aee3841996-03-07 18:00:44 +0000627 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000628 """Internal: read data in query string format."""
629 qs = self.fp.read(self.length)
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000630 self.list = list = []
631 for key, value in parse_qsl(qs, self.keep_blank_values,
632 self.strict_parsing):
633 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000634 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000635
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000636 FieldStorageClass = None
637
Guido van Rossumf5745001998-10-20 14:43:02 +0000638 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000639 """Internal: read a part that is itself multipart."""
Guido van Rossum2e441f72001-07-25 21:00:19 +0000640 ib = self.innerboundary
641 if not valid_boundary(ib):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000642 raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000643 self.list = []
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000644 klass = self.FieldStorageClass or self.__class__
Guido van Rossum2e441f72001-07-25 21:00:19 +0000645 part = klass(self.fp, {}, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000646 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000647 # Throw first part away
648 while not part.done:
Armin Rigo3a703b62005-09-19 09:11:04 +0000649 headers = rfc822.Message(self.fp)
Guido van Rossum2e441f72001-07-25 21:00:19 +0000650 part = klass(self.fp, headers, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000651 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000652 self.list.append(part)
653 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000654
655 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000656 """Internal: read an atomic part."""
657 if self.length >= 0:
658 self.read_binary()
659 self.skip_lines()
660 else:
661 self.read_lines()
662 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000663
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000664 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000665
666 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000667 """Internal: read binary data."""
668 self.file = self.make_file('b')
669 todo = self.length
670 if todo >= 0:
671 while todo > 0:
672 data = self.fp.read(min(todo, self.bufsize))
673 if not data:
674 self.done = -1
675 break
676 self.file.write(data)
677 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000678
679 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000680 """Internal: read lines until EOF or outerboundary."""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000681 self.file = self.__file = StringIO()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000682 if self.outerboundary:
683 self.read_lines_to_outerboundary()
684 else:
685 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000686
Guido van Rossum52b8c292001-06-29 13:06:06 +0000687 def __write(self, line):
688 if self.__file is not None:
689 if self.__file.tell() + len(line) > 1000:
690 self.file = self.make_file('')
691 self.file.write(self.__file.getvalue())
692 self.__file = None
693 self.file.write(line)
694
Guido van Rossum7aee3841996-03-07 18:00:44 +0000695 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000696 """Internal: read lines until EOF."""
697 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000698 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000699 if not line:
700 self.done = -1
701 break
Guido van Rossum52b8c292001-06-29 13:06:06 +0000702 self.__write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000703
704 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000705 """Internal: read lines until outerboundary."""
706 next = "--" + self.outerboundary
707 last = next + "--"
708 delim = ""
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000709 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000710 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000711 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000712 if not line:
713 self.done = -1
714 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000715 if line[:2] == "--" and last_line_lfend:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000716 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000717 if strippedline == next:
718 break
719 if strippedline == last:
720 self.done = 1
721 break
722 odelim = delim
723 if line[-2:] == "\r\n":
724 delim = "\r\n"
725 line = line[:-2]
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000726 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000727 elif line[-1] == "\n":
728 delim = "\n"
729 line = line[:-1]
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000730 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000731 else:
732 delim = ""
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000733 last_line_lfend = False
Guido van Rossum52b8c292001-06-29 13:06:06 +0000734 self.__write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000735
736 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000737 """Internal: skip lines until outer boundary if defined."""
738 if not self.outerboundary or self.done:
739 return
740 next = "--" + self.outerboundary
741 last = next + "--"
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000742 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000743 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000744 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000745 if not line:
746 self.done = -1
747 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000748 if line[:2] == "--" and last_line_lfend:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000749 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000750 if strippedline == next:
751 break
752 if strippedline == last:
753 self.done = 1
754 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000755 last_line_lfend = line.endswith('\n')
Guido van Rossum7aee3841996-03-07 18:00:44 +0000756
Guido van Rossuma5e9fb61997-08-12 18:18:13 +0000757 def make_file(self, binary=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000758 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000759
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000760 The file will be used as follows:
761 - data is written to it
762 - seek(0)
763 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +0000764
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000765 The 'binary' argument is unused -- the file is always opened
766 in binary mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000767
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000768 This version opens a temporary file for reading and writing,
769 and immediately deletes (unlinks) it. The trick (on Unix!) is
770 that the file can still be used, but it can't be opened by
771 another process, and it will automatically be deleted when it
772 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000773
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000774 If you want a more permanent file, you derive a class which
775 overrides this method. If you want a visible temporary file
776 that is nevertheless automatically deleted when the script
777 terminates, try defining a __del__ method in a derived class
778 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000779
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000780 """
781 import tempfile
782 return tempfile.TemporaryFile("w+b")
Tim Peters88869f92001-01-14 23:36:06 +0000783
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000784
785
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000786# Backwards Compatibility Classes
787# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +0000788
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000789class FormContentDict(UserDict.UserDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000790 """Form content as dictionary with a list of values per field.
Guido van Rossum72755611996-03-06 07:20:06 +0000791
Guido van Rossum7aee3841996-03-07 18:00:44 +0000792 form = FormContentDict()
793
794 form[key] -> [value, value, ...]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000795 key in form -> Boolean
Guido van Rossum7aee3841996-03-07 18:00:44 +0000796 form.keys() -> [key, key, ...]
797 form.values() -> [[val, val, ...], [val, val, ...], ...]
798 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
799 form.dict == {key: [val, val, ...], ...}
800
801 """
Thomas Wouters89f507f2006-12-13 04:49:30 +0000802 def __init__(self, environ=os.environ, keep_blank_values=0, strict_parsing=0):
803 self.dict = self.data = parse(environ=environ,
804 keep_blank_values=keep_blank_values,
805 strict_parsing=strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000806 self.query_string = environ['QUERY_STRING']
Guido van Rossum9a22de11995-01-12 12:29:47 +0000807
808
Guido van Rossum9a22de11995-01-12 12:29:47 +0000809class SvFormContentDict(FormContentDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000810 """Form content as dictionary expecting a single value per field.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000811
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000812 If you only expect a single value for each field, then form[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000813 will return that single value. It will raise an IndexError if
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000814 that expectation is not true. If you expect a field to have
Guido van Rossum7aee3841996-03-07 18:00:44 +0000815 possible multiple values, than you can use form.getlist(key) to
816 get all of the values. values() and items() are a compromise:
817 they return single strings where there is a single value, and
818 lists of strings otherwise.
819
820 """
821 def __getitem__(self, key):
Tim Peters88869f92001-01-14 23:36:06 +0000822 if len(self.dict[key]) > 1:
823 raise IndexError, 'expecting a single value'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000824 return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000825 def getlist(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000826 return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000827 def values(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000828 result = []
829 for value in self.dict.values():
830 if len(value) == 1:
831 result.append(value[0])
832 else: result.append(value)
833 return result
Guido van Rossum7aee3841996-03-07 18:00:44 +0000834 def items(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000835 result = []
836 for key, value in self.dict.items():
837 if len(value) == 1:
838 result.append((key, value[0]))
839 else: result.append((key, value))
840 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000841
842
Guido van Rossum9a22de11995-01-12 12:29:47 +0000843class InterpFormContentDict(SvFormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000844 """This class is present for backwards compatibility only."""
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000845 def __getitem__(self, key):
846 v = SvFormContentDict.__getitem__(self, key)
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000847 if v[0] in '0123456789+-.':
848 try: return int(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000849 except ValueError:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000850 try: return float(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000851 except ValueError: pass
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000852 return v.strip()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000853 def values(self):
854 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000855 for key in self.keys():
856 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000857 result.append(self[key])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000858 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000859 result.append(self.dict[key])
860 return result
861 def items(self):
862 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000863 for key in self.keys():
864 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000865 result.append((key, self[key]))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000866 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000867 result.append((key, self.dict[key]))
868 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000869
870
Guido van Rossum9a22de11995-01-12 12:29:47 +0000871class FormContent(FormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000872 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +0000873 def values(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000874 if key in self.dict :return self.dict[key]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000875 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000876 def indexed_value(self, key, location):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000877 if key in self.dict:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000878 if len(self.dict[key]) > location:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000879 return self.dict[key][location]
880 else: return None
881 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000882 def value(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000883 if key in self.dict: return self.dict[key][0]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000884 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000885 def length(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000886 return len(self.dict[key])
Guido van Rossum0147db01996-03-09 03:16:04 +0000887 def stripped(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000888 if key in self.dict: return self.dict[key][0].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000889 else: return None
Guido van Rossum7aee3841996-03-07 18:00:44 +0000890 def pars(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000891 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000892
893
Guido van Rossum72755611996-03-06 07:20:06 +0000894# Test/debug code
895# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +0000896
Guido van Rossum773ab271996-07-23 03:46:24 +0000897def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000898 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000899
Guido van Rossum7aee3841996-03-07 18:00:44 +0000900 Write minimal HTTP headers and dump all information provided to
901 the script in HTML form.
902
903 """
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000904 print("Content-type: text/html")
905 print()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000906 sys.stderr = sys.stdout
907 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000908 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000909 print_directory()
910 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000911 print_form(form)
912 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000913 print_environ_usage()
914 def f():
Georg Brandl7cae87c2006-09-06 06:51:57 +0000915 exec("testing print_exception() -- <I>italics?</I>")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000916 def g(f=f):
917 f()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000918 print("<H3>What follows is a test, not an actual exception:</H3>")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000919 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000920 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000921 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000922
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000923 print("<H1>Second try with a small maxlen...</H1>")
Guido van Rossum57d51f22000-09-16 21:16:01 +0000924
Guido van Rossumad164711997-05-13 19:03:23 +0000925 global maxlen
926 maxlen = 50
927 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000928 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000929 print_directory()
930 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000931 print_form(form)
932 print_environ(environ)
Guido van Rossumad164711997-05-13 19:03:23 +0000933 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000934 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +0000935
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000936def print_exception(type=None, value=None, tb=None, limit=None):
937 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000938 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000939 import traceback
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000940 print()
941 print("<H3>Traceback (most recent call last):</H3>")
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000942 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000943 traceback.format_exception_only(type, value)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000944 print("<PRE>%s<B>%s</B></PRE>" % (
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000945 escape("".join(list[:-1])),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000946 escape(list[-1]),
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000947 ))
Guido van Rossumf15d1591997-09-29 23:22:12 +0000948 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +0000949
Guido van Rossum773ab271996-07-23 03:46:24 +0000950def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000951 """Dump the shell environment as HTML."""
952 keys = environ.keys()
953 keys.sort()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000954 print()
955 print("<H3>Shell Environment:</H3>")
956 print("<DL>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000957 for key in keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000958 print("<DT>", escape(key), "<DD>", escape(environ[key]))
959 print("</DL>")
960 print()
Guido van Rossum72755611996-03-06 07:20:06 +0000961
962def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000963 """Dump the contents of a form as HTML."""
964 keys = form.keys()
965 keys.sort()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000966 print()
967 print("<H3>Form Contents:</H3>")
Guido van Rossum57d51f22000-09-16 21:16:01 +0000968 if not keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000969 print("<P>No form fields.")
970 print("<DL>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000971 for key in keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000972 print("<DT>" + escape(key) + ":", end=' ')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000973 value = form[key]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000974 print("<i>" + escape(repr(type(value))) + "</i>")
975 print("<DD>" + escape(repr(value)))
976 print("</DL>")
977 print()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000978
979def print_directory():
980 """Dump the current directory as HTML."""
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000981 print()
982 print("<H3>Current Working Directory:</H3>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000983 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000984 pwd = os.getcwd()
Guido van Rossumb940e112007-01-10 16:19:56 +0000985 except os.error as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000986 print("os.error:", escape(str(msg)))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000987 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000988 print(escape(pwd))
989 print()
Guido van Rossum9a22de11995-01-12 12:29:47 +0000990
Guido van Rossuma8738a51996-03-14 21:30:28 +0000991def print_arguments():
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000992 print()
993 print("<H3>Command Line Arguments:</H3>")
994 print()
995 print(sys.argv)
996 print()
Guido van Rossuma8738a51996-03-14 21:30:28 +0000997
Guido van Rossum9a22de11995-01-12 12:29:47 +0000998def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +0000999 """Dump a list of environment variables used by CGI as HTML."""
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001000 print("""
Guido van Rossum72755611996-03-06 07:20:06 +00001001<H3>These environment variables could have been set:</H3>
1002<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001003<LI>AUTH_TYPE
1004<LI>CONTENT_LENGTH
1005<LI>CONTENT_TYPE
1006<LI>DATE_GMT
1007<LI>DATE_LOCAL
1008<LI>DOCUMENT_NAME
1009<LI>DOCUMENT_ROOT
1010<LI>DOCUMENT_URI
1011<LI>GATEWAY_INTERFACE
1012<LI>LAST_MODIFIED
1013<LI>PATH
1014<LI>PATH_INFO
1015<LI>PATH_TRANSLATED
1016<LI>QUERY_STRING
1017<LI>REMOTE_ADDR
1018<LI>REMOTE_HOST
1019<LI>REMOTE_IDENT
1020<LI>REMOTE_USER
1021<LI>REQUEST_METHOD
1022<LI>SCRIPT_NAME
1023<LI>SERVER_NAME
1024<LI>SERVER_PORT
1025<LI>SERVER_PROTOCOL
1026<LI>SERVER_ROOT
1027<LI>SERVER_SOFTWARE
1028</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001029In addition, HTTP headers sent by the server may be passed in the
1030environment as well. Here are some common variable names:
1031<UL>
1032<LI>HTTP_ACCEPT
1033<LI>HTTP_CONNECTION
1034<LI>HTTP_HOST
1035<LI>HTTP_PRAGMA
1036<LI>HTTP_REFERER
1037<LI>HTTP_USER_AGENT
1038</UL>
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001039""")
Guido van Rossum9a22de11995-01-12 12:29:47 +00001040
Guido van Rossum9a22de11995-01-12 12:29:47 +00001041
Guido van Rossum72755611996-03-06 07:20:06 +00001042# Utilities
1043# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001044
Guido van Rossum64c66201997-07-19 20:11:53 +00001045def escape(s, quote=None):
Skip Montanaro97b2fa22005-08-02 02:50:25 +00001046 '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
1047 If the optional flag quote is true, the quotation mark character (")
1048 is also translated.'''
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001049 s = s.replace("&", "&amp;") # Must be done first!
1050 s = s.replace("<", "&lt;")
1051 s = s.replace(">", "&gt;")
Guido van Rossum64c66201997-07-19 20:11:53 +00001052 if quote:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001053 s = s.replace('"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +00001054 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001055
Guido van Rossum2e441f72001-07-25 21:00:19 +00001056def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
1057 import re
1058 return re.match(_vb_pattern, s)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001059
Guido van Rossum72755611996-03-06 07:20:06 +00001060# Invoke mainline
1061# ===============
1062
1063# Call test() when this file is run as a script (not imported as a module)
Tim Peters88869f92001-01-14 23:36:06 +00001064if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001065 test()