blob: 01a28fe4b646e6ee50d21558b1ddb9fd2974e059 [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
Raymond Hettinger2add3522008-02-04 22:43:27 +000043import collections
Guido van Rossum68937b42007-05-18 00:51:22 +000044from io import StringIO
Guido van Rossum72755611996-03-06 07:20:06 +000045
Guido van Rossuma8423a92001-03-19 13:40:44 +000046__all__ = ["MiniFieldStorage", "FieldStorage", "FormContentDict",
47 "SvFormContentDict", "InterpFormContentDict", "FormContent",
48 "parse", "parse_qs", "parse_qsl", "parse_multipart",
49 "parse_header", "print_exception", "print_environ",
50 "print_form", "print_directory", "print_arguments",
51 "print_environ_usage", "escape"]
Guido van Rossumc204c701996-09-05 19:07:11 +000052
53# Logging support
54# ===============
55
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000056logfile = "" # Filename to log to, if not empty
57logfp = None # File object to log to, if not None
Guido van Rossumc204c701996-09-05 19:07:11 +000058
59def initlog(*allargs):
60 """Write a log message, if there is a log file.
61
62 Even though this function is called initlog(), you should always
63 use log(); log is a variable that is set either to initlog
64 (initially), to dolog (once the log file has been opened), or to
65 nolog (when logging is disabled).
66
67 The first argument is a format string; the remaining arguments (if
68 any) are arguments to the % operator, so e.g.
69 log("%s: %s", "a", "b")
70 will write "a: b" to the log file, followed by a newline.
71
72 If the global logfp is not None, it should be a file object to
73 which log data is written.
74
75 If the global logfp is None, the global logfile may be a string
76 giving a filename to open, in append mode. This file should be
77 world writable!!! If the file can't be opened, logging is
78 silently disabled (since there is no safe place where we could
79 send an error message).
80
81 """
82 global logfp, log
83 if logfile and not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000084 try:
85 logfp = open(logfile, "a")
86 except IOError:
87 pass
Guido van Rossumc204c701996-09-05 19:07:11 +000088 if not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000089 log = nolog
Guido van Rossumc204c701996-09-05 19:07:11 +000090 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000091 log = dolog
Guido van Rossum68468eb2003-02-27 20:14:51 +000092 log(*allargs)
Guido van Rossumc204c701996-09-05 19:07:11 +000093
94def dolog(fmt, *args):
95 """Write a log message to the log file. See initlog() for docs."""
96 logfp.write(fmt%args + "\n")
97
98def nolog(*allargs):
99 """Dummy function, assigned to log when logging is disabled."""
100 pass
101
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000102log = initlog # The current logging function
Guido van Rossumc204c701996-09-05 19:07:11 +0000103
104
Guido van Rossum72755611996-03-06 07:20:06 +0000105# Parsing functions
106# =================
107
Guido van Rossumad164711997-05-13 19:03:23 +0000108# Maximum input we will accept when REQUEST_METHOD is POST
109# 0 ==> unlimited input
110maxlen = 0
111
Guido van Rossume08c04c1996-11-11 19:29:11 +0000112def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum773ab271996-07-23 03:46:24 +0000113 """Parse a query in the environment or from a file (default stdin)
114
115 Arguments, all optional:
116
117 fp : file pointer; default: sys.stdin
118
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000119 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000120
121 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000122 URL encoded forms should be treated as blank strings.
123 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000124 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000125 blank values are to be ignored and treated as if they were
126 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000127
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000128 strict_parsing: flag indicating what to do with parsing errors.
129 If false (the default), errors are silently ignored.
130 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000131 """
Raymond Hettingera1449002002-05-31 23:54:44 +0000132 if fp is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000133 fp = sys.stdin
Raymond Hettinger54f02222002-06-01 14:18:47 +0000134 if not 'REQUEST_METHOD' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000135 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
Guido van Rossum7aee3841996-03-07 18:00:44 +0000136 if environ['REQUEST_METHOD'] == 'POST':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000137 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
138 if ctype == 'multipart/form-data':
139 return parse_multipart(fp, pdict)
140 elif ctype == 'application/x-www-form-urlencoded':
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000141 clength = int(environ['CONTENT_LENGTH'])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000142 if maxlen and clength > maxlen:
Collin Winterce36ad82007-08-30 01:19:48 +0000143 raise ValueError('Maximum content length exceeded')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000144 qs = fp.read(clength)
145 else:
146 qs = '' # Unknown content-type
Raymond Hettinger54f02222002-06-01 14:18:47 +0000147 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000148 if qs: qs = qs + '&'
149 qs = qs + environ['QUERY_STRING']
Tim Peters88869f92001-01-14 23:36:06 +0000150 elif sys.argv[1:]:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000151 if qs: qs = qs + '&'
152 qs = qs + sys.argv[1]
153 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Raymond Hettinger54f02222002-06-01 14:18:47 +0000154 elif 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000155 qs = environ['QUERY_STRING']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000156 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000157 if sys.argv[1:]:
158 qs = sys.argv[1]
159 else:
160 qs = ""
161 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossume08c04c1996-11-11 19:29:11 +0000162 return parse_qs(qs, keep_blank_values, strict_parsing)
Guido van Rossume7808771995-08-07 20:12:09 +0000163
164
Guido van Rossume08c04c1996-11-11 19:29:11 +0000165def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
166 """Parse a query given as a string argument.
Guido van Rossum773ab271996-07-23 03:46:24 +0000167
168 Arguments:
169
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000170 qs: URL-encoded query string to be parsed
Guido van Rossum773ab271996-07-23 03:46:24 +0000171
172 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000173 URL encoded queries should be treated as blank strings.
174 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000175 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000176 blank values are to be ignored and treated as if they were
177 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000178
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000179 strict_parsing: flag indicating what to do with parsing errors.
180 If false (the default), errors are silently ignored.
181 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000182 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000183 dict = {}
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000184 for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000185 if name in dict:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000186 dict[name].append(value)
187 else:
188 dict[name] = [value]
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000189 return dict
190
191def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
192 """Parse a query given as a string argument.
193
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000194 Arguments:
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000195
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000196 qs: URL-encoded query string to be parsed
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000197
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000198 keep_blank_values: flag indicating whether blank values in
199 URL encoded queries should be treated as blank strings. A
200 true value indicates that blanks should be retained as blank
201 strings. The default false value indicates that blank values
202 are to be ignored and treated as if they were not included.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000203
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000204 strict_parsing: flag indicating what to do with parsing errors. If
205 false (the default), errors are silently ignored. If true,
Tim Peters88869f92001-01-14 23:36:06 +0000206 errors raise a ValueError exception.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000207
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000208 Returns a list, as G-d intended.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000209 """
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000210 pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
211 r = []
212 for name_value in pairs:
Neil Schemenauer66edb622004-07-19 15:38:11 +0000213 if not name_value and not strict_parsing:
214 continue
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000215 nv = name_value.split('=', 1)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000216 if len(nv) != 2:
217 if strict_parsing:
Collin Winterce36ad82007-08-30 01:19:48 +0000218 raise ValueError("bad query field: %r" % (name_value,))
Brett Cannon8d9b60f2004-03-21 22:16:15 +0000219 # Handle case of a control-name with no equal sign
220 if keep_blank_values:
221 nv.append('')
222 else:
223 continue
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000224 if len(nv[1]) or keep_blank_values:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000225 name = urllib.unquote(nv[0].replace('+', ' '))
226 value = urllib.unquote(nv[1].replace('+', ' '))
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000227 r.append((name, value))
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000228
229 return r
Guido van Rossum9a22de11995-01-12 12:29:47 +0000230
231
Guido van Rossum0147db01996-03-09 03:16:04 +0000232def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000233 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000234
Guido van Rossum7aee3841996-03-07 18:00:44 +0000235 Arguments:
236 fp : input file
Johannes Gijsbersc7fc10a2005-01-08 13:56:36 +0000237 pdict: dictionary containing other parameters of content-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000238
Tim Peters88869f92001-01-14 23:36:06 +0000239 Returns a dictionary just like parse_qs(): keys are the field names, each
240 value is a list of values for that field. This is easy to use but not
241 much good if you are expecting megabytes to be uploaded -- in that case,
242 use the FieldStorage class instead which is much more flexible. Note
243 that content-type is the raw, unparsed contents of the content-type
Guido van Rossum0147db01996-03-09 03:16:04 +0000244 header.
Tim Peters88869f92001-01-14 23:36:06 +0000245
246 XXX This does not parse nested multipart parts -- use FieldStorage for
Guido van Rossum0147db01996-03-09 03:16:04 +0000247 that.
Tim Peters88869f92001-01-14 23:36:06 +0000248
249 XXX This should really be subsumed by FieldStorage altogether -- no
Guido van Rossum0147db01996-03-09 03:16:04 +0000250 point in having two implementations of the same parsing algorithm.
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000251 Also, FieldStorage protects itself better against certain DoS attacks
252 by limiting the size of the data read in one chunk. The API here
253 does not support that kind of protection. This also affects parse()
254 since it can call parse_multipart().
Guido van Rossum72755611996-03-06 07:20:06 +0000255
Guido van Rossum7aee3841996-03-07 18:00:44 +0000256 """
Guido van Rossum2e441f72001-07-25 21:00:19 +0000257 boundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000258 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000259 boundary = pdict['boundary']
Guido van Rossum2e441f72001-07-25 21:00:19 +0000260 if not valid_boundary(boundary):
Collin Winterce36ad82007-08-30 01:19:48 +0000261 raise ValueError('Invalid boundary in multipart form: %r'
Walter Dörwald70a6b492004-02-12 17:35:32 +0000262 % (boundary,))
Tim Petersab9ba272001-08-09 21:40:30 +0000263
Guido van Rossum7aee3841996-03-07 18:00:44 +0000264 nextpart = "--" + boundary
265 lastpart = "--" + boundary + "--"
266 partdict = {}
267 terminator = ""
268
269 while terminator != lastpart:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000270 bytes = -1
271 data = None
272 if terminator:
273 # At start of next part. Read headers first.
Armin Rigo3a703b62005-09-19 09:11:04 +0000274 headers = mimetools.Message(fp)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000275 clength = headers.getheader('content-length')
276 if clength:
277 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000278 bytes = int(clength)
279 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000280 pass
281 if bytes > 0:
282 if maxlen and bytes > maxlen:
Collin Winterce36ad82007-08-30 01:19:48 +0000283 raise ValueError('Maximum content length exceeded')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000284 data = fp.read(bytes)
285 else:
286 data = ""
287 # Read lines until end of part.
288 lines = []
289 while 1:
290 line = fp.readline()
291 if not line:
292 terminator = lastpart # End outer loop
293 break
294 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000295 terminator = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000296 if terminator in (nextpart, lastpart):
297 break
298 lines.append(line)
299 # Done with part.
300 if data is None:
301 continue
302 if bytes < 0:
303 if lines:
304 # Strip final line terminator
305 line = lines[-1]
306 if line[-2:] == "\r\n":
307 line = line[:-2]
308 elif line[-1:] == "\n":
309 line = line[:-1]
310 lines[-1] = line
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000311 data = "".join(lines)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000312 line = headers['content-disposition']
313 if not line:
314 continue
315 key, params = parse_header(line)
316 if key != 'form-data':
317 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000318 if 'name' in params:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000319 name = params['name']
320 else:
321 continue
Raymond Hettinger54f02222002-06-01 14:18:47 +0000322 if name in partdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000323 partdict[name].append(data)
324 else:
325 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000326
Guido van Rossum7aee3841996-03-07 18:00:44 +0000327 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000328
329
Guido van Rossum72755611996-03-06 07:20:06 +0000330def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000331 """Parse a Content-type like header.
332
333 Return the main content-type and a dictionary of options.
334
335 """
Raymond Hettingerf871d832004-12-31 21:59:02 +0000336 plist = [x.strip() for x in line.split(';')]
Raymond Hettinger46ac8eb2002-06-30 03:39:14 +0000337 key = plist.pop(0).lower()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000338 pdict = {}
339 for p in plist:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000340 i = p.find('=')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000341 if i >= 0:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000342 name = p[:i].strip().lower()
343 value = p[i+1:].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000344 if len(value) >= 2 and value[0] == value[-1] == '"':
345 value = value[1:-1]
Johannes Gijsbers9e15dd62004-08-14 15:39:34 +0000346 value = value.replace('\\\\', '\\').replace('\\"', '"')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000347 pdict[name] = value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000348 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000349
350
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000351# Classes for field storage
352# =========================
353
354class MiniFieldStorage:
355
Guido van Rossum0147db01996-03-09 03:16:04 +0000356 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000357
Guido van Rossum7aee3841996-03-07 18:00:44 +0000358 # Dummy attributes
359 filename = None
360 list = None
361 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000362 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000363 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000364 disposition = None
365 disposition_options = {}
366 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000367
Guido van Rossum7aee3841996-03-07 18:00:44 +0000368 def __init__(self, name, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000369 """Constructor from field name and value."""
370 self.name = name
371 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000372 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000373
374 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000375 """Return printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000376 return "MiniFieldStorage(%r, %r)" % (self.name, self.value)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000377
378
379class FieldStorage:
380
Guido van Rossum7aee3841996-03-07 18:00:44 +0000381 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000382
Guido van Rossum7aee3841996-03-07 18:00:44 +0000383 This class provides naming, typing, files stored on disk, and
384 more. At the top level, it is accessible like a dictionary, whose
385 keys are the field names. (Note: None can occur as a field name.)
386 The items are either a Python list (if there's multiple values) or
387 another FieldStorage or MiniFieldStorage object. If it's a single
388 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000389
Guido van Rossum7aee3841996-03-07 18:00:44 +0000390 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000391
Guido van Rossum7aee3841996-03-07 18:00:44 +0000392 filename: the filename, if specified; otherwise None; this is the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000393 client side filename, *not* the file name on which it is
394 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000395
Guido van Rossum7aee3841996-03-07 18:00:44 +0000396 value: the value as a *string*; for file uploads, this
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000397 transparently reads the file every time you request the value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000398
399 file: the file(-like) object from which you can read the data;
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000400 None if the data is stored a simple string
Guido van Rossum7aee3841996-03-07 18:00:44 +0000401
402 type: the content-type, or None if not specified
403
404 type_options: dictionary of options specified on the content-type
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000405 line
Guido van Rossum7aee3841996-03-07 18:00:44 +0000406
407 disposition: content-disposition, or None if not specified
408
409 disposition_options: dictionary of corresponding options
410
Armin Rigo3a703b62005-09-19 09:11:04 +0000411 headers: a dictionary(-like) object (sometimes rfc822.Message or a
412 subclass thereof) containing *all* headers
Guido van Rossum7aee3841996-03-07 18:00:44 +0000413
414 The class is subclassable, mostly for the purpose of overriding
415 the make_file() method, which is called internally to come up with
416 a file open for reading and writing. This makes it possible to
417 override the default choice of storing all files in a temporary
418 directory and unlinking them as soon as they have been opened.
419
420 """
421
Guido van Rossum773ab271996-07-23 03:46:24 +0000422 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000423 environ=os.environ, keep_blank_values=0, strict_parsing=0):
424 """Constructor. Read multipart/* until last part.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000425
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000426 Arguments, all optional:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000427
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000428 fp : file pointer; default: sys.stdin
Guido van Rossumb1b4f941998-05-08 19:55:51 +0000429 (not used when the request method is GET)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000430
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000431 headers : header dictionary-like object; default:
432 taken from environ as per CGI spec
Guido van Rossum7aee3841996-03-07 18:00:44 +0000433
Guido van Rossum773ab271996-07-23 03:46:24 +0000434 outerboundary : terminating multipart boundary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000435 (for internal use only)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000436
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000437 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000438
439 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000440 URL encoded forms should be treated as blank strings.
441 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000442 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000443 blank values are to be ignored and treated as if they were
444 not included.
Guido van Rossum773ab271996-07-23 03:46:24 +0000445
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000446 strict_parsing: flag indicating what to do with parsing errors.
447 If false (the default), errors are silently ignored.
448 If true, errors raise a ValueError exception.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000449
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000450 """
451 method = 'GET'
452 self.keep_blank_values = keep_blank_values
453 self.strict_parsing = strict_parsing
Raymond Hettinger54f02222002-06-01 14:18:47 +0000454 if 'REQUEST_METHOD' in environ:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000455 method = environ['REQUEST_METHOD'].upper()
Guido van Rossum01852831998-06-25 02:40:17 +0000456 if method == 'GET' or method == 'HEAD':
Raymond Hettinger54f02222002-06-01 14:18:47 +0000457 if 'QUERY_STRING' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000458 qs = environ['QUERY_STRING']
459 elif sys.argv[1:]:
460 qs = sys.argv[1]
461 else:
462 qs = ""
463 fp = StringIO(qs)
464 if headers is None:
465 headers = {'content-type':
466 "application/x-www-form-urlencoded"}
467 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000468 headers = {}
469 if method == 'POST':
470 # Set default content-type for POST to what's traditional
471 headers['content-type'] = "application/x-www-form-urlencoded"
Raymond Hettinger54f02222002-06-01 14:18:47 +0000472 if 'CONTENT_TYPE' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000473 headers['content-type'] = environ['CONTENT_TYPE']
Raymond Hettinger54f02222002-06-01 14:18:47 +0000474 if 'CONTENT_LENGTH' in environ:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000475 headers['content-length'] = environ['CONTENT_LENGTH']
476 self.fp = fp or sys.stdin
477 self.headers = headers
478 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000479
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000480 # Process content-disposition header
481 cdisp, pdict = "", {}
Raymond Hettinger54f02222002-06-01 14:18:47 +0000482 if 'content-disposition' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000483 cdisp, pdict = parse_header(self.headers['content-disposition'])
484 self.disposition = cdisp
485 self.disposition_options = pdict
486 self.name = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000487 if 'name' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000488 self.name = pdict['name']
489 self.filename = None
Raymond Hettinger54f02222002-06-01 14:18:47 +0000490 if 'filename' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000491 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000492
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000493 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000494 #
495 # Honor any existing content-type header. But if there is no
496 # content-type header, use some sensible defaults. Assume
497 # outerboundary is "" at the outer level, but something non-false
498 # inside a multi-part. The default for an inner part is text/plain,
499 # but for an outer part it should be urlencoded. This should catch
500 # bogus clients which erroneously forget to include a content-type
501 # header.
502 #
503 # See below for what we do if there does exist a content-type header,
504 # but it happens to be something we don't understand.
Raymond Hettinger54f02222002-06-01 14:18:47 +0000505 if 'content-type' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000506 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000507 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000508 ctype, pdict = "text/plain", {}
509 else:
510 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000511 self.type = ctype
512 self.type_options = pdict
513 self.innerboundary = ""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000514 if 'boundary' in pdict:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000515 self.innerboundary = pdict['boundary']
516 clen = -1
Raymond Hettinger54f02222002-06-01 14:18:47 +0000517 if 'content-length' in self.headers:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000518 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000519 clen = int(self.headers['content-length'])
Skip Montanarodb5d1442002-03-23 05:50:17 +0000520 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000521 pass
522 if maxlen and clen > maxlen:
Collin Winterce36ad82007-08-30 01:19:48 +0000523 raise ValueError('Maximum content length exceeded')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000524 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000525
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000526 self.list = self.file = None
527 self.done = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000528 if ctype == 'application/x-www-form-urlencoded':
529 self.read_urlencoded()
530 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000531 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000532 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000533 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000534
535 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000536 """Return a printable representation."""
Walter Dörwald70a6b492004-02-12 17:35:32 +0000537 return "FieldStorage(%r, %r, %r)" % (
538 self.name, self.filename, self.value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000539
Guido van Rossum4061cbe2002-09-11 18:20:34 +0000540 def __iter__(self):
541 return iter(self.keys())
542
Guido van Rossum7aee3841996-03-07 18:00:44 +0000543 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000544 if name != 'value':
Collin Winterce36ad82007-08-30 01:19:48 +0000545 raise AttributeError(name)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000546 if self.file:
547 self.file.seek(0)
548 value = self.file.read()
549 self.file.seek(0)
550 elif self.list is not None:
551 value = self.list
552 else:
553 value = None
554 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000555
556 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000557 """Dictionary style indexing."""
558 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000559 raise TypeError("not indexable")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000560 found = []
561 for item in self.list:
562 if item.name == key: found.append(item)
563 if not found:
Collin Winterce36ad82007-08-30 01:19:48 +0000564 raise KeyError(key)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000565 if len(found) == 1:
566 return found[0]
567 else:
568 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000569
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000570 def getvalue(self, key, default=None):
571 """Dictionary style get() method, including 'value' lookup."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000572 if key in self:
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000573 value = self[key]
574 if type(value) is type([]):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000575 return [x.value for x in value]
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000576 else:
577 return value.value
578 else:
579 return default
580
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000581 def getfirst(self, key, default=None):
582 """ Return the first value received."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000583 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000584 value = self[key]
585 if type(value) is type([]):
586 return value[0].value
587 else:
588 return value.value
589 else:
590 return default
591
592 def getlist(self, key):
593 """ Return list of received values."""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000594 if key in self:
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000595 value = self[key]
596 if type(value) is type([]):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000597 return [x.value for x in value]
Guido van Rossum1bfb3882001-09-05 19:45:34 +0000598 else:
599 return [value.value]
600 else:
601 return []
602
Guido van Rossum7aee3841996-03-07 18:00:44 +0000603 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000604 """Dictionary style keys() method."""
605 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000606 raise TypeError("not indexable")
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000607 return list(set(item.name for item in self.list))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000608
Raymond Hettinger54f02222002-06-01 14:18:47 +0000609 def __contains__(self, key):
610 """Dictionary style __contains__ method."""
611 if self.list is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000612 raise TypeError("not indexable")
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000613 return any(item.name == key for item in self.list)
Raymond Hettinger54f02222002-06-01 14:18:47 +0000614
Guido van Rossum88b85d41997-01-11 19:21:33 +0000615 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000616 """Dictionary style len(x) support."""
617 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000618
Thomas Wouters8ce81f72007-09-20 18:22:40 +0000619 def __nonzero__(self):
620 return bool(self.list)
621
Guido van Rossum7aee3841996-03-07 18:00:44 +0000622 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000623 """Internal: read data in query string format."""
624 qs = self.fp.read(self.length)
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000625 self.list = list = []
626 for key, value in parse_qsl(qs, self.keep_blank_values,
627 self.strict_parsing):
628 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000629 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000630
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000631 FieldStorageClass = None
632
Guido van Rossumf5745001998-10-20 14:43:02 +0000633 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000634 """Internal: read a part that is itself multipart."""
Guido van Rossum2e441f72001-07-25 21:00:19 +0000635 ib = self.innerboundary
636 if not valid_boundary(ib):
Collin Winterce36ad82007-08-30 01:19:48 +0000637 raise ValueError('Invalid boundary in multipart form: %r' % (ib,))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000638 self.list = []
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000639 klass = self.FieldStorageClass or self.__class__
Guido van Rossum2e441f72001-07-25 21:00:19 +0000640 part = klass(self.fp, {}, ib,
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000641 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000642 # Throw first part away
643 while not part.done:
Armin Rigo3a703b62005-09-19 09:11:04 +0000644 headers = rfc822.Message(self.fp)
Guido van Rossum2e441f72001-07-25 21:00:19 +0000645 part = klass(self.fp, headers, 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 self.list.append(part)
648 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000649
650 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000651 """Internal: read an atomic part."""
652 if self.length >= 0:
653 self.read_binary()
654 self.skip_lines()
655 else:
656 self.read_lines()
657 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000658
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000659 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000660
661 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000662 """Internal: read binary data."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000663 self.file = self.make_file()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000664 todo = self.length
665 if todo >= 0:
666 while todo > 0:
667 data = self.fp.read(min(todo, self.bufsize))
668 if not data:
669 self.done = -1
670 break
671 self.file.write(data)
672 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000673
674 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000675 """Internal: read lines until EOF or outerboundary."""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000676 self.file = self.__file = StringIO()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000677 if self.outerboundary:
678 self.read_lines_to_outerboundary()
679 else:
680 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000681
Guido van Rossum52b8c292001-06-29 13:06:06 +0000682 def __write(self, line):
683 if self.__file is not None:
684 if self.__file.tell() + len(line) > 1000:
Guido van Rossuma1a68522007-08-28 03:11:34 +0000685 self.file = self.make_file()
686 data = self.__file.getvalue()
687 self.file.write(data)
Guido van Rossum52b8c292001-06-29 13:06:06 +0000688 self.__file = None
689 self.file.write(line)
690
Guido van Rossum7aee3841996-03-07 18:00:44 +0000691 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000692 """Internal: read lines until EOF."""
693 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000694 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000695 if not line:
696 self.done = -1
697 break
Guido van Rossum52b8c292001-06-29 13:06:06 +0000698 self.__write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000699
700 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000701 """Internal: read lines until outerboundary."""
702 next = "--" + self.outerboundary
703 last = next + "--"
704 delim = ""
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000705 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000706 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000707 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000708 if not line:
709 self.done = -1
710 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000711 if line[:2] == "--" and last_line_lfend:
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]
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000722 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000723 elif line[-1] == "\n":
724 delim = "\n"
725 line = line[:-1]
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000726 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000727 else:
728 delim = ""
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000729 last_line_lfend = False
Guido van Rossum52b8c292001-06-29 13:06:06 +0000730 self.__write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000731
732 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000733 """Internal: skip lines until outer boundary if defined."""
734 if not self.outerboundary or self.done:
735 return
736 next = "--" + self.outerboundary
737 last = next + "--"
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000738 last_line_lfend = True
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000739 while 1:
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000740 line = self.fp.readline(1<<16)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000741 if not line:
742 self.done = -1
743 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000744 if line[:2] == "--" and last_line_lfend:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000745 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000746 if strippedline == next:
747 break
748 if strippedline == last:
749 self.done = 1
750 break
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000751 last_line_lfend = line.endswith('\n')
Guido van Rossum7aee3841996-03-07 18:00:44 +0000752
Guido van Rossuma1a68522007-08-28 03:11:34 +0000753 def make_file(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000754 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000755
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000756 The file will be used as follows:
757 - data is written to it
758 - seek(0)
759 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +0000760
Guido van Rossuma1a68522007-08-28 03:11:34 +0000761 The file is always opened in text mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000762
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000763 This version opens a temporary file for reading and writing,
764 and immediately deletes (unlinks) it. The trick (on Unix!) is
765 that the file can still be used, but it can't be opened by
766 another process, and it will automatically be deleted when it
767 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000768
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000769 If you want a more permanent file, you derive a class which
770 overrides this method. If you want a visible temporary file
771 that is nevertheless automatically deleted when the script
772 terminates, try defining a __del__ method in a derived class
773 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000774
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000775 """
776 import tempfile
Guido van Rossum92bab812007-08-28 03:32:38 +0000777 return tempfile.TemporaryFile("w+", encoding="utf-8", newline="\n")
Tim Peters88869f92001-01-14 23:36:06 +0000778
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000779
780
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000781# Backwards Compatibility Classes
782# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +0000783
Raymond Hettinger2add3522008-02-04 22:43:27 +0000784class FormContentDict(collections.Mapping):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000785 """Form content as dictionary with a list of values per field.
Guido van Rossum72755611996-03-06 07:20:06 +0000786
Guido van Rossum7aee3841996-03-07 18:00:44 +0000787 form = FormContentDict()
788
789 form[key] -> [value, value, ...]
Raymond Hettinger54f02222002-06-01 14:18:47 +0000790 key in form -> Boolean
Guido van Rossum7aee3841996-03-07 18:00:44 +0000791 form.keys() -> [key, key, ...]
792 form.values() -> [[val, val, ...], [val, val, ...], ...]
793 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
794 form.dict == {key: [val, val, ...], ...}
795
796 """
Thomas Wouters89f507f2006-12-13 04:49:30 +0000797 def __init__(self, environ=os.environ, keep_blank_values=0, strict_parsing=0):
798 self.dict = self.data = parse(environ=environ,
799 keep_blank_values=keep_blank_values,
800 strict_parsing=strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000801 self.query_string = environ['QUERY_STRING']
Guido van Rossum9a22de11995-01-12 12:29:47 +0000802
Raymond Hettinger2add3522008-02-04 22:43:27 +0000803 def __len__(self):
804 return len(self.dict)
805
806 def __iter__(self):
807 return iter(self.dict)
808
809 def __getitem__(self, key):
810 return self.dict[key]
811
Guido van Rossum9a22de11995-01-12 12:29:47 +0000812
Guido van Rossum9a22de11995-01-12 12:29:47 +0000813class SvFormContentDict(FormContentDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000814 """Form content as dictionary expecting a single value per field.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000815
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000816 If you only expect a single value for each field, then form[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000817 will return that single value. It will raise an IndexError if
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000818 that expectation is not true. If you expect a field to have
Guido van Rossum7aee3841996-03-07 18:00:44 +0000819 possible multiple values, than you can use form.getlist(key) to
820 get all of the values. values() and items() are a compromise:
821 they return single strings where there is a single value, and
822 lists of strings otherwise.
823
824 """
825 def __getitem__(self, key):
Tim Peters88869f92001-01-14 23:36:06 +0000826 if len(self.dict[key]) > 1:
Collin Winterce36ad82007-08-30 01:19:48 +0000827 raise IndexError('expecting a single value')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000828 return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000829 def getlist(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000830 return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000831 def values(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000832 result = []
833 for value in self.dict.values():
834 if len(value) == 1:
835 result.append(value[0])
836 else: result.append(value)
837 return result
Guido van Rossum7aee3841996-03-07 18:00:44 +0000838 def items(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000839 result = []
840 for key, value in self.dict.items():
841 if len(value) == 1:
842 result.append((key, value[0]))
843 else: result.append((key, value))
844 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000845
846
Guido van Rossum9a22de11995-01-12 12:29:47 +0000847class InterpFormContentDict(SvFormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000848 """This class is present for backwards compatibility only."""
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000849 def __getitem__(self, key):
850 v = SvFormContentDict.__getitem__(self, key)
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000851 if v[0] in '0123456789+-.':
852 try: return int(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000853 except ValueError:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000854 try: return float(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000855 except ValueError: pass
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000856 return v.strip()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000857 def values(self):
858 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000859 for key in self.keys():
860 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000861 result.append(self[key])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000862 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000863 result.append(self.dict[key])
864 return result
865 def items(self):
866 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000867 for key in self.keys():
868 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000869 result.append((key, self[key]))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000870 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000871 result.append((key, self.dict[key]))
872 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000873
874
Guido van Rossum9a22de11995-01-12 12:29:47 +0000875class FormContent(FormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000876 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +0000877 def values(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000878 if key in self.dict :return self.dict[key]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000879 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000880 def indexed_value(self, key, location):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000881 if key in self.dict:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000882 if len(self.dict[key]) > location:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000883 return self.dict[key][location]
884 else: return None
885 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000886 def value(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000887 if key in self.dict: return self.dict[key][0]
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000888 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000889 def length(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000890 return len(self.dict[key])
Guido van Rossum0147db01996-03-09 03:16:04 +0000891 def stripped(self, key):
Raymond Hettinger54f02222002-06-01 14:18:47 +0000892 if key in self.dict: return self.dict[key][0].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000893 else: return None
Guido van Rossum7aee3841996-03-07 18:00:44 +0000894 def pars(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000895 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000896
897
Guido van Rossum72755611996-03-06 07:20:06 +0000898# Test/debug code
899# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +0000900
Guido van Rossum773ab271996-07-23 03:46:24 +0000901def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000902 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000903
Guido van Rossum7aee3841996-03-07 18:00:44 +0000904 Write minimal HTTP headers and dump all information provided to
905 the script in HTML form.
906
907 """
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000908 print("Content-type: text/html")
909 print()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000910 sys.stderr = sys.stdout
911 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000912 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000913 print_directory()
914 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000915 print_form(form)
916 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000917 print_environ_usage()
918 def f():
Georg Brandl7cae87c2006-09-06 06:51:57 +0000919 exec("testing print_exception() -- <I>italics?</I>")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000920 def g(f=f):
921 f()
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000922 print("<H3>What follows is a test, not an actual exception:</H3>")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000923 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000924 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000925 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000926
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000927 print("<H1>Second try with a small maxlen...</H1>")
Guido van Rossum57d51f22000-09-16 21:16:01 +0000928
Guido van Rossumad164711997-05-13 19:03:23 +0000929 global maxlen
930 maxlen = 50
931 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000932 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000933 print_directory()
934 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000935 print_form(form)
936 print_environ(environ)
Guido van Rossumad164711997-05-13 19:03:23 +0000937 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000938 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +0000939
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000940def print_exception(type=None, value=None, tb=None, limit=None):
941 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000942 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000943 import traceback
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000944 print()
945 print("<H3>Traceback (most recent call last):</H3>")
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000946 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000947 traceback.format_exception_only(type, value)
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000948 print("<PRE>%s<B>%s</B></PRE>" % (
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000949 escape("".join(list[:-1])),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000950 escape(list[-1]),
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000951 ))
Guido van Rossumf15d1591997-09-29 23:22:12 +0000952 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +0000953
Guido van Rossum773ab271996-07-23 03:46:24 +0000954def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000955 """Dump the shell environment as HTML."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000956 keys = sorted(environ.keys())
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000957 print()
958 print("<H3>Shell Environment:</H3>")
959 print("<DL>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000960 for key in keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000961 print("<DT>", escape(key), "<DD>", escape(environ[key]))
962 print("</DL>")
963 print()
Guido van Rossum72755611996-03-06 07:20:06 +0000964
965def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000966 """Dump the contents of a form as HTML."""
Guido van Rossuma1a68522007-08-28 03:11:34 +0000967 keys = sorted(form.keys())
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000968 print()
969 print("<H3>Form Contents:</H3>")
Guido van Rossum57d51f22000-09-16 21:16:01 +0000970 if not keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000971 print("<P>No form fields.")
972 print("<DL>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000973 for key in keys:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000974 print("<DT>" + escape(key) + ":", end=' ')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000975 value = form[key]
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000976 print("<i>" + escape(repr(type(value))) + "</i>")
977 print("<DD>" + escape(repr(value)))
978 print("</DL>")
979 print()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000980
981def print_directory():
982 """Dump the current directory as HTML."""
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000983 print()
984 print("<H3>Current Working Directory:</H3>")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000985 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000986 pwd = os.getcwd()
Guido van Rossumb940e112007-01-10 16:19:56 +0000987 except os.error as msg:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000988 print("os.error:", escape(str(msg)))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000989 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000990 print(escape(pwd))
991 print()
Guido van Rossum9a22de11995-01-12 12:29:47 +0000992
Guido van Rossuma8738a51996-03-14 21:30:28 +0000993def print_arguments():
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000994 print()
995 print("<H3>Command Line Arguments:</H3>")
996 print()
997 print(sys.argv)
998 print()
Guido van Rossuma8738a51996-03-14 21:30:28 +0000999
Guido van Rossum9a22de11995-01-12 12:29:47 +00001000def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +00001001 """Dump a list of environment variables used by CGI as HTML."""
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001002 print("""
Guido van Rossum72755611996-03-06 07:20:06 +00001003<H3>These environment variables could have been set:</H3>
1004<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001005<LI>AUTH_TYPE
1006<LI>CONTENT_LENGTH
1007<LI>CONTENT_TYPE
1008<LI>DATE_GMT
1009<LI>DATE_LOCAL
1010<LI>DOCUMENT_NAME
1011<LI>DOCUMENT_ROOT
1012<LI>DOCUMENT_URI
1013<LI>GATEWAY_INTERFACE
1014<LI>LAST_MODIFIED
1015<LI>PATH
1016<LI>PATH_INFO
1017<LI>PATH_TRANSLATED
1018<LI>QUERY_STRING
1019<LI>REMOTE_ADDR
1020<LI>REMOTE_HOST
1021<LI>REMOTE_IDENT
1022<LI>REMOTE_USER
1023<LI>REQUEST_METHOD
1024<LI>SCRIPT_NAME
1025<LI>SERVER_NAME
1026<LI>SERVER_PORT
1027<LI>SERVER_PROTOCOL
1028<LI>SERVER_ROOT
1029<LI>SERVER_SOFTWARE
1030</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001031In addition, HTTP headers sent by the server may be passed in the
1032environment as well. Here are some common variable names:
1033<UL>
1034<LI>HTTP_ACCEPT
1035<LI>HTTP_CONNECTION
1036<LI>HTTP_HOST
1037<LI>HTTP_PRAGMA
1038<LI>HTTP_REFERER
1039<LI>HTTP_USER_AGENT
1040</UL>
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001041""")
Guido van Rossum9a22de11995-01-12 12:29:47 +00001042
Guido van Rossum9a22de11995-01-12 12:29:47 +00001043
Guido van Rossum72755611996-03-06 07:20:06 +00001044# Utilities
1045# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001046
Guido van Rossum64c66201997-07-19 20:11:53 +00001047def escape(s, quote=None):
Skip Montanaro97b2fa22005-08-02 02:50:25 +00001048 '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
1049 If the optional flag quote is true, the quotation mark character (")
1050 is also translated.'''
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001051 s = s.replace("&", "&amp;") # Must be done first!
1052 s = s.replace("<", "&lt;")
1053 s = s.replace(">", "&gt;")
Guido van Rossum64c66201997-07-19 20:11:53 +00001054 if quote:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +00001055 s = s.replace('"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +00001056 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001057
Guido van Rossum2e441f72001-07-25 21:00:19 +00001058def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
1059 import re
1060 return re.match(_vb_pattern, s)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001061
Guido van Rossum72755611996-03-06 07:20:06 +00001062# Invoke mainline
1063# ===============
1064
1065# Call test() when this file is run as a script (not imported as a module)
Tim Peters88869f92001-01-14 23:36:06 +00001066if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001067 test()