blob: 35343607a7fbbc1d92a5d07978e2653ed689bced [file] [log] [blame]
Guido van Rossum51914632000-10-03 13:51:09 +00001#! /usr/local/bin/python
Guido van Rossum1c9daa81995-09-18 21:52:37 +00002
Guido van Rossum467d7232001-02-13 13:13:33 +00003# NOTE: the above "/usr/local/bin/python" is NOT a mistake. It is
4# intentionally NOT "/usr/bin/env python". On many systems
5# (e.g. Solaris), /usr/local/bin is not in $PATH as passed to CGI
6# scripts, and /usr/local/bin is the default directory where Python is
7# installed, so /usr/bin/env would be unable to find python. Granted,
8# binary installations by Linux vendors often install Python in
9# /usr/bin. So let those vendors patch cgi.py to match their choice
10# of installation.
11
Guido van Rossum72755611996-03-06 07:20:06 +000012"""Support module for CGI (Common Gateway Interface) scripts.
Guido van Rossum1c9daa81995-09-18 21:52:37 +000013
Guido van Rossum7aee3841996-03-07 18:00:44 +000014This module defines a number of utilities for use by CGI scripts
15written in Python.
Guido van Rossum72755611996-03-06 07:20:06 +000016"""
17
Jeremy Hyltonc253d9a2000-08-03 20:57:44 +000018# XXX Perhaps there should be a slimmed version that doesn't contain
19# all those backwards compatible and debugging classes and functions?
Guido van Rossum98d9fd32000-02-28 15:12:25 +000020
21# History
22# -------
Tim Peters88869f92001-01-14 23:36:06 +000023#
Guido van Rossum98d9fd32000-02-28 15:12:25 +000024# Michael McLay started this module. Steve Majewski changed the
25# interface to SvFormContentDict and FormContentDict. The multipart
26# parsing was inspired by code submitted by Andreas Paepcke. Guido van
27# Rossum rewrote, reformatted and documented the module and is currently
28# responsible for its maintenance.
Tim Peters88869f92001-01-14 23:36:06 +000029#
Guido van Rossum98d9fd32000-02-28 15:12:25 +000030
Guido van Rossum52b8c292001-06-29 13:06:06 +000031__version__ = "2.6"
Guido van Rossum0147db01996-03-09 03:16:04 +000032
Guido van Rossum72755611996-03-06 07:20:06 +000033
34# Imports
35# =======
36
Guido van Rossum72755611996-03-06 07:20:06 +000037import sys
38import os
Guido van Rossuma5e9fb61997-08-12 18:18:13 +000039import urllib
Guido van Rossuma5e9fb61997-08-12 18:18:13 +000040import mimetools
41import rfc822
Moshe Zadkaa1a4b592000-08-25 21:47:56 +000042import UserDict
Guido van Rossuma5e9fb61997-08-12 18:18:13 +000043from StringIO import StringIO
Guido van Rossum72755611996-03-06 07:20:06 +000044
Guido van Rossuma8423a92001-03-19 13:40:44 +000045__all__ = ["MiniFieldStorage", "FieldStorage", "FormContentDict",
46 "SvFormContentDict", "InterpFormContentDict", "FormContent",
47 "parse", "parse_qs", "parse_qsl", "parse_multipart",
48 "parse_header", "print_exception", "print_environ",
49 "print_form", "print_directory", "print_arguments",
50 "print_environ_usage", "escape"]
Guido van Rossumc204c701996-09-05 19:07:11 +000051
52# Logging support
53# ===============
54
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000055logfile = "" # Filename to log to, if not empty
56logfp = None # File object to log to, if not None
Guido van Rossumc204c701996-09-05 19:07:11 +000057
58def initlog(*allargs):
59 """Write a log message, if there is a log file.
60
61 Even though this function is called initlog(), you should always
62 use log(); log is a variable that is set either to initlog
63 (initially), to dolog (once the log file has been opened), or to
64 nolog (when logging is disabled).
65
66 The first argument is a format string; the remaining arguments (if
67 any) are arguments to the % operator, so e.g.
68 log("%s: %s", "a", "b")
69 will write "a: b" to the log file, followed by a newline.
70
71 If the global logfp is not None, it should be a file object to
72 which log data is written.
73
74 If the global logfp is None, the global logfile may be a string
75 giving a filename to open, in append mode. This file should be
76 world writable!!! If the file can't be opened, logging is
77 silently disabled (since there is no safe place where we could
78 send an error message).
79
80 """
81 global logfp, log
82 if logfile and not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000083 try:
84 logfp = open(logfile, "a")
85 except IOError:
86 pass
Guido van Rossumc204c701996-09-05 19:07:11 +000087 if not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000088 log = nolog
Guido van Rossumc204c701996-09-05 19:07:11 +000089 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000090 log = dolog
Guido van Rossumc204c701996-09-05 19:07:11 +000091 apply(log, allargs)
92
93def dolog(fmt, *args):
94 """Write a log message to the log file. See initlog() for docs."""
95 logfp.write(fmt%args + "\n")
96
97def nolog(*allargs):
98 """Dummy function, assigned to log when logging is disabled."""
99 pass
100
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000101log = initlog # The current logging function
Guido van Rossumc204c701996-09-05 19:07:11 +0000102
103
Guido van Rossum72755611996-03-06 07:20:06 +0000104# Parsing functions
105# =================
106
Guido van Rossumad164711997-05-13 19:03:23 +0000107# Maximum input we will accept when REQUEST_METHOD is POST
108# 0 ==> unlimited input
109maxlen = 0
110
Guido van Rossume08c04c1996-11-11 19:29:11 +0000111def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum773ab271996-07-23 03:46:24 +0000112 """Parse a query in the environment or from a file (default stdin)
113
114 Arguments, all optional:
115
116 fp : file pointer; default: sys.stdin
117
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000118 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000119
120 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000121 URL encoded forms should be treated as blank strings.
122 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000123 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000124 blank values are to be ignored and treated as if they were
125 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000126
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000127 strict_parsing: flag indicating what to do with parsing errors.
128 If false (the default), errors are silently ignored.
129 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000130 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000131 if not fp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000132 fp = sys.stdin
Guido van Rossum7aee3841996-03-07 18:00:44 +0000133 if not environ.has_key('REQUEST_METHOD'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000134 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
Guido van Rossum7aee3841996-03-07 18:00:44 +0000135 if environ['REQUEST_METHOD'] == 'POST':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000136 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
137 if ctype == 'multipart/form-data':
138 return parse_multipart(fp, pdict)
139 elif ctype == 'application/x-www-form-urlencoded':
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000140 clength = int(environ['CONTENT_LENGTH'])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000141 if maxlen and clength > maxlen:
142 raise ValueError, 'Maximum content length exceeded'
143 qs = fp.read(clength)
144 else:
145 qs = '' # Unknown content-type
Tim Peters88869f92001-01-14 23:36:06 +0000146 if environ.has_key('QUERY_STRING'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000147 if qs: qs = qs + '&'
148 qs = qs + environ['QUERY_STRING']
Tim Peters88869f92001-01-14 23:36:06 +0000149 elif sys.argv[1:]:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000150 if qs: qs = qs + '&'
151 qs = qs + sys.argv[1]
152 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossum7aee3841996-03-07 18:00:44 +0000153 elif environ.has_key('QUERY_STRING'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000154 qs = environ['QUERY_STRING']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000155 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000156 if sys.argv[1:]:
157 qs = sys.argv[1]
158 else:
159 qs = ""
160 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossume08c04c1996-11-11 19:29:11 +0000161 return parse_qs(qs, keep_blank_values, strict_parsing)
Guido van Rossume7808771995-08-07 20:12:09 +0000162
163
Guido van Rossume08c04c1996-11-11 19:29:11 +0000164def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
165 """Parse a query given as a string argument.
Guido van Rossum773ab271996-07-23 03:46:24 +0000166
167 Arguments:
168
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000169 qs: URL-encoded query string to be parsed
Guido van Rossum773ab271996-07-23 03:46:24 +0000170
171 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000172 URL encoded queries should be treated as blank strings.
173 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000174 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000175 blank values are to be ignored and treated as if they were
176 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000177
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000178 strict_parsing: flag indicating what to do with parsing errors.
179 If false (the default), errors are silently ignored.
180 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000181 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000182 dict = {}
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000183 for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000184 if dict.has_key(name):
185 dict[name].append(value)
186 else:
187 dict[name] = [value]
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000188 return dict
189
190def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
191 """Parse a query given as a string argument.
192
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000193 Arguments:
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000194
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000195 qs: URL-encoded query string to be parsed
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000196
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000197 keep_blank_values: flag indicating whether blank values in
198 URL encoded queries should be treated as blank strings. A
199 true value indicates that blanks should be retained as blank
200 strings. The default false value indicates that blank values
201 are to be ignored and treated as if they were not included.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000202
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000203 strict_parsing: flag indicating what to do with parsing errors. If
204 false (the default), errors are silently ignored. If true,
Tim Peters88869f92001-01-14 23:36:06 +0000205 errors raise a ValueError exception.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000206
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000207 Returns a list, as G-d intended.
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000208 """
Jeremy Hyltonafde7e22000-09-15 20:06:57 +0000209 pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
210 r = []
211 for name_value in pairs:
212 nv = name_value.split('=', 1)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000213 if len(nv) != 2:
214 if strict_parsing:
215 raise ValueError, "bad query field: %s" % `name_value`
216 continue
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000217 if len(nv[1]) or keep_blank_values:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000218 name = urllib.unquote(nv[0].replace('+', ' '))
219 value = urllib.unquote(nv[1].replace('+', ' '))
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000220 r.append((name, value))
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000221
222 return r
Guido van Rossum9a22de11995-01-12 12:29:47 +0000223
224
Guido van Rossum0147db01996-03-09 03:16:04 +0000225def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000226 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000227
Guido van Rossum7aee3841996-03-07 18:00:44 +0000228 Arguments:
229 fp : input file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000230 pdict: dictionary containing other parameters of conten-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000231
Tim Peters88869f92001-01-14 23:36:06 +0000232 Returns a dictionary just like parse_qs(): keys are the field names, each
233 value is a list of values for that field. This is easy to use but not
234 much good if you are expecting megabytes to be uploaded -- in that case,
235 use the FieldStorage class instead which is much more flexible. Note
236 that content-type is the raw, unparsed contents of the content-type
Guido van Rossum0147db01996-03-09 03:16:04 +0000237 header.
Tim Peters88869f92001-01-14 23:36:06 +0000238
239 XXX This does not parse nested multipart parts -- use FieldStorage for
Guido van Rossum0147db01996-03-09 03:16:04 +0000240 that.
Tim Peters88869f92001-01-14 23:36:06 +0000241
242 XXX This should really be subsumed by FieldStorage altogether -- no
Guido van Rossum0147db01996-03-09 03:16:04 +0000243 point in having two implementations of the same parsing algorithm.
Guido van Rossum72755611996-03-06 07:20:06 +0000244
Guido van Rossum7aee3841996-03-07 18:00:44 +0000245 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000246 if pdict.has_key('boundary'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000247 boundary = pdict['boundary']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000248 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000249 boundary = ""
Guido van Rossum7aee3841996-03-07 18:00:44 +0000250 nextpart = "--" + boundary
251 lastpart = "--" + boundary + "--"
252 partdict = {}
253 terminator = ""
254
255 while terminator != lastpart:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000256 bytes = -1
257 data = None
258 if terminator:
259 # At start of next part. Read headers first.
260 headers = mimetools.Message(fp)
261 clength = headers.getheader('content-length')
262 if clength:
263 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000264 bytes = int(clength)
265 except ValueError:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000266 pass
267 if bytes > 0:
268 if maxlen and bytes > maxlen:
269 raise ValueError, 'Maximum content length exceeded'
270 data = fp.read(bytes)
271 else:
272 data = ""
273 # Read lines until end of part.
274 lines = []
275 while 1:
276 line = fp.readline()
277 if not line:
278 terminator = lastpart # End outer loop
279 break
280 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000281 terminator = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000282 if terminator in (nextpart, lastpart):
283 break
284 lines.append(line)
285 # Done with part.
286 if data is None:
287 continue
288 if bytes < 0:
289 if lines:
290 # Strip final line terminator
291 line = lines[-1]
292 if line[-2:] == "\r\n":
293 line = line[:-2]
294 elif line[-1:] == "\n":
295 line = line[:-1]
296 lines[-1] = line
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000297 data = "".join(lines)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000298 line = headers['content-disposition']
299 if not line:
300 continue
301 key, params = parse_header(line)
302 if key != 'form-data':
303 continue
304 if params.has_key('name'):
305 name = params['name']
306 else:
307 continue
308 if partdict.has_key(name):
309 partdict[name].append(data)
310 else:
311 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000312
Guido van Rossum7aee3841996-03-07 18:00:44 +0000313 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000314
315
Guido van Rossum72755611996-03-06 07:20:06 +0000316def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000317 """Parse a Content-type like header.
318
319 Return the main content-type and a dictionary of options.
320
321 """
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000322 plist = map(lambda x: x.strip(), line.split(';'))
323 key = plist[0].lower()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000324 del plist[0]
325 pdict = {}
326 for p in plist:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000327 i = p.find('=')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000328 if i >= 0:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000329 name = p[:i].strip().lower()
330 value = p[i+1:].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000331 if len(value) >= 2 and value[0] == value[-1] == '"':
332 value = value[1:-1]
333 pdict[name] = value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000334 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000335
336
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000337# Classes for field storage
338# =========================
339
340class MiniFieldStorage:
341
Guido van Rossum0147db01996-03-09 03:16:04 +0000342 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000343
Guido van Rossum7aee3841996-03-07 18:00:44 +0000344 # Dummy attributes
345 filename = None
346 list = None
347 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000348 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000349 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000350 disposition = None
351 disposition_options = {}
352 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000353
Guido van Rossum7aee3841996-03-07 18:00:44 +0000354 def __init__(self, name, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000355 """Constructor from field name and value."""
356 self.name = name
357 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000358 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000359
360 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000361 """Return printable representation."""
362 return "MiniFieldStorage(%s, %s)" % (`self.name`, `self.value`)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000363
364
365class FieldStorage:
366
Guido van Rossum7aee3841996-03-07 18:00:44 +0000367 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000368
Guido van Rossum7aee3841996-03-07 18:00:44 +0000369 This class provides naming, typing, files stored on disk, and
370 more. At the top level, it is accessible like a dictionary, whose
371 keys are the field names. (Note: None can occur as a field name.)
372 The items are either a Python list (if there's multiple values) or
373 another FieldStorage or MiniFieldStorage object. If it's a single
374 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000375
Guido van Rossum7aee3841996-03-07 18:00:44 +0000376 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000377
Guido van Rossum7aee3841996-03-07 18:00:44 +0000378 filename: the filename, if specified; otherwise None; this is the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000379 client side filename, *not* the file name on which it is
380 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000381
Guido van Rossum7aee3841996-03-07 18:00:44 +0000382 value: the value as a *string*; for file uploads, this
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000383 transparently reads the file every time you request the value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000384
385 file: the file(-like) object from which you can read the data;
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000386 None if the data is stored a simple string
Guido van Rossum7aee3841996-03-07 18:00:44 +0000387
388 type: the content-type, or None if not specified
389
390 type_options: dictionary of options specified on the content-type
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000391 line
Guido van Rossum7aee3841996-03-07 18:00:44 +0000392
393 disposition: content-disposition, or None if not specified
394
395 disposition_options: dictionary of corresponding options
396
397 headers: a dictionary(-like) object (sometimes rfc822.Message or a
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000398 subclass thereof) containing *all* headers
Guido van Rossum7aee3841996-03-07 18:00:44 +0000399
400 The class is subclassable, mostly for the purpose of overriding
401 the make_file() method, which is called internally to come up with
402 a file open for reading and writing. This makes it possible to
403 override the default choice of storing all files in a temporary
404 directory and unlinking them as soon as they have been opened.
405
406 """
407
Guido van Rossum773ab271996-07-23 03:46:24 +0000408 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000409 environ=os.environ, keep_blank_values=0, strict_parsing=0):
410 """Constructor. Read multipart/* until last part.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000411
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000412 Arguments, all optional:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000413
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000414 fp : file pointer; default: sys.stdin
Guido van Rossumb1b4f941998-05-08 19:55:51 +0000415 (not used when the request method is GET)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000416
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000417 headers : header dictionary-like object; default:
418 taken from environ as per CGI spec
Guido van Rossum7aee3841996-03-07 18:00:44 +0000419
Guido van Rossum773ab271996-07-23 03:46:24 +0000420 outerboundary : terminating multipart boundary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000421 (for internal use only)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000422
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000423 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000424
425 keep_blank_values: flag indicating whether blank values in
Tim Peters88869f92001-01-14 23:36:06 +0000426 URL encoded forms should be treated as blank strings.
427 A true value indicates that blanks should be retained as
Guido van Rossum773ab271996-07-23 03:46:24 +0000428 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000429 blank values are to be ignored and treated as if they were
430 not included.
Guido van Rossum773ab271996-07-23 03:46:24 +0000431
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000432 strict_parsing: flag indicating what to do with parsing errors.
433 If false (the default), errors are silently ignored.
434 If true, errors raise a ValueError exception.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000435
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000436 """
437 method = 'GET'
438 self.keep_blank_values = keep_blank_values
439 self.strict_parsing = strict_parsing
440 if environ.has_key('REQUEST_METHOD'):
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000441 method = environ['REQUEST_METHOD'].upper()
Guido van Rossum01852831998-06-25 02:40:17 +0000442 if method == 'GET' or method == 'HEAD':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000443 if environ.has_key('QUERY_STRING'):
444 qs = environ['QUERY_STRING']
445 elif sys.argv[1:]:
446 qs = sys.argv[1]
447 else:
448 qs = ""
449 fp = StringIO(qs)
450 if headers is None:
451 headers = {'content-type':
452 "application/x-www-form-urlencoded"}
453 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000454 headers = {}
455 if method == 'POST':
456 # Set default content-type for POST to what's traditional
457 headers['content-type'] = "application/x-www-form-urlencoded"
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000458 if environ.has_key('CONTENT_TYPE'):
459 headers['content-type'] = environ['CONTENT_TYPE']
460 if environ.has_key('CONTENT_LENGTH'):
461 headers['content-length'] = environ['CONTENT_LENGTH']
462 self.fp = fp or sys.stdin
463 self.headers = headers
464 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000465
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000466 # Process content-disposition header
467 cdisp, pdict = "", {}
468 if self.headers.has_key('content-disposition'):
469 cdisp, pdict = parse_header(self.headers['content-disposition'])
470 self.disposition = cdisp
471 self.disposition_options = pdict
472 self.name = None
473 if pdict.has_key('name'):
474 self.name = pdict['name']
475 self.filename = None
476 if pdict.has_key('filename'):
477 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000478
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000479 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000480 #
481 # Honor any existing content-type header. But if there is no
482 # content-type header, use some sensible defaults. Assume
483 # outerboundary is "" at the outer level, but something non-false
484 # inside a multi-part. The default for an inner part is text/plain,
485 # but for an outer part it should be urlencoded. This should catch
486 # bogus clients which erroneously forget to include a content-type
487 # header.
488 #
489 # See below for what we do if there does exist a content-type header,
490 # but it happens to be something we don't understand.
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000491 if self.headers.has_key('content-type'):
492 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000493 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000494 ctype, pdict = "text/plain", {}
495 else:
496 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000497 self.type = ctype
498 self.type_options = pdict
499 self.innerboundary = ""
500 if pdict.has_key('boundary'):
501 self.innerboundary = pdict['boundary']
502 clen = -1
503 if self.headers.has_key('content-length'):
504 try:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000505 clen = int(self.headers['content-length'])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000506 except:
507 pass
508 if maxlen and clen > maxlen:
509 raise ValueError, 'Maximum content length exceeded'
510 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000511
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000512 self.list = self.file = None
513 self.done = 0
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000514 if ctype == 'application/x-www-form-urlencoded':
515 self.read_urlencoded()
516 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000517 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000518 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000519 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000520
521 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000522 """Return a printable representation."""
523 return "FieldStorage(%s, %s, %s)" % (
524 `self.name`, `self.filename`, `self.value`)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000525
526 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000527 if name != 'value':
528 raise AttributeError, name
529 if self.file:
530 self.file.seek(0)
531 value = self.file.read()
532 self.file.seek(0)
533 elif self.list is not None:
534 value = self.list
535 else:
536 value = None
537 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000538
539 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000540 """Dictionary style indexing."""
541 if self.list is None:
542 raise TypeError, "not indexable"
543 found = []
544 for item in self.list:
545 if item.name == key: found.append(item)
546 if not found:
547 raise KeyError, key
548 if len(found) == 1:
549 return found[0]
550 else:
551 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000552
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000553 def getvalue(self, key, default=None):
554 """Dictionary style get() method, including 'value' lookup."""
555 if self.has_key(key):
556 value = self[key]
557 if type(value) is type([]):
558 return map(lambda v: v.value, value)
559 else:
560 return value.value
561 else:
562 return default
563
Guido van Rossum7aee3841996-03-07 18:00:44 +0000564 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000565 """Dictionary style keys() method."""
566 if self.list is None:
567 raise TypeError, "not indexable"
568 keys = []
569 for item in self.list:
570 if item.name not in keys: keys.append(item.name)
571 return keys
Guido van Rossum7aee3841996-03-07 18:00:44 +0000572
Guido van Rossum0147db01996-03-09 03:16:04 +0000573 def has_key(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000574 """Dictionary style has_key() method."""
575 if self.list is None:
576 raise TypeError, "not indexable"
577 for item in self.list:
578 if item.name == key: return 1
579 return 0
Guido van Rossum0147db01996-03-09 03:16:04 +0000580
Guido van Rossum88b85d41997-01-11 19:21:33 +0000581 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000582 """Dictionary style len(x) support."""
583 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000584
Guido van Rossum7aee3841996-03-07 18:00:44 +0000585 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000586 """Internal: read data in query string format."""
587 qs = self.fp.read(self.length)
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000588 self.list = list = []
589 for key, value in parse_qsl(qs, self.keep_blank_values,
590 self.strict_parsing):
591 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000592 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000593
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000594 FieldStorageClass = None
595
Guido van Rossumf5745001998-10-20 14:43:02 +0000596 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000597 """Internal: read a part that is itself multipart."""
598 self.list = []
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000599 klass = self.FieldStorageClass or self.__class__
600 part = klass(self.fp, {}, self.innerboundary,
601 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000602 # Throw first part away
603 while not part.done:
604 headers = rfc822.Message(self.fp)
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000605 part = klass(self.fp, headers, self.innerboundary,
606 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000607 self.list.append(part)
608 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000609
610 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000611 """Internal: read an atomic part."""
612 if self.length >= 0:
613 self.read_binary()
614 self.skip_lines()
615 else:
616 self.read_lines()
617 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000618
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000619 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000620
621 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000622 """Internal: read binary data."""
623 self.file = self.make_file('b')
624 todo = self.length
625 if todo >= 0:
626 while todo > 0:
627 data = self.fp.read(min(todo, self.bufsize))
628 if not data:
629 self.done = -1
630 break
631 self.file.write(data)
632 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000633
634 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000635 """Internal: read lines until EOF or outerboundary."""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000636 self.file = self.__file = StringIO()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000637 if self.outerboundary:
638 self.read_lines_to_outerboundary()
639 else:
640 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000641
Guido van Rossum52b8c292001-06-29 13:06:06 +0000642 def __write(self, line):
643 if self.__file is not None:
644 if self.__file.tell() + len(line) > 1000:
645 self.file = self.make_file('')
646 self.file.write(self.__file.getvalue())
647 self.__file = None
648 self.file.write(line)
649
Guido van Rossum7aee3841996-03-07 18:00:44 +0000650 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000651 """Internal: read lines until EOF."""
652 while 1:
653 line = self.fp.readline()
654 if not line:
655 self.done = -1
656 break
Guido van Rossum52b8c292001-06-29 13:06:06 +0000657 self.__write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000658
659 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000660 """Internal: read lines until outerboundary."""
661 next = "--" + self.outerboundary
662 last = next + "--"
663 delim = ""
664 while 1:
665 line = self.fp.readline()
666 if not line:
667 self.done = -1
668 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000669 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000670 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000671 if strippedline == next:
672 break
673 if strippedline == last:
674 self.done = 1
675 break
676 odelim = delim
677 if line[-2:] == "\r\n":
678 delim = "\r\n"
679 line = line[:-2]
680 elif line[-1] == "\n":
681 delim = "\n"
682 line = line[:-1]
683 else:
684 delim = ""
Guido van Rossum52b8c292001-06-29 13:06:06 +0000685 self.__write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000686
687 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000688 """Internal: skip lines until outer boundary if defined."""
689 if not self.outerboundary or self.done:
690 return
691 next = "--" + self.outerboundary
692 last = next + "--"
693 while 1:
694 line = self.fp.readline()
695 if not line:
696 self.done = -1
697 break
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000698 if line[:2] == "--":
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000699 strippedline = line.strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000700 if strippedline == next:
701 break
702 if strippedline == last:
703 self.done = 1
704 break
Guido van Rossum7aee3841996-03-07 18:00:44 +0000705
Guido van Rossuma5e9fb61997-08-12 18:18:13 +0000706 def make_file(self, binary=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000707 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000708
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000709 The file will be used as follows:
710 - data is written to it
711 - seek(0)
712 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +0000713
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000714 The 'binary' argument is unused -- the file is always opened
715 in binary mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000716
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000717 This version opens a temporary file for reading and writing,
718 and immediately deletes (unlinks) it. The trick (on Unix!) is
719 that the file can still be used, but it can't be opened by
720 another process, and it will automatically be deleted when it
721 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000722
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000723 If you want a more permanent file, you derive a class which
724 overrides this method. If you want a visible temporary file
725 that is nevertheless automatically deleted when the script
726 terminates, try defining a __del__ method in a derived class
727 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000728
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000729 """
730 import tempfile
731 return tempfile.TemporaryFile("w+b")
Tim Peters88869f92001-01-14 23:36:06 +0000732
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000733
734
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000735# Backwards Compatibility Classes
736# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +0000737
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000738class FormContentDict(UserDict.UserDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000739 """Form content as dictionary with a list of values per field.
Guido van Rossum72755611996-03-06 07:20:06 +0000740
Guido van Rossum7aee3841996-03-07 18:00:44 +0000741 form = FormContentDict()
742
743 form[key] -> [value, value, ...]
744 form.has_key(key) -> Boolean
745 form.keys() -> [key, key, ...]
746 form.values() -> [[val, val, ...], [val, val, ...], ...]
747 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
748 form.dict == {key: [val, val, ...], ...}
749
750 """
Guido van Rossum773ab271996-07-23 03:46:24 +0000751 def __init__(self, environ=os.environ):
Moshe Zadkaa1a4b592000-08-25 21:47:56 +0000752 self.dict = self.data = parse(environ=environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000753 self.query_string = environ['QUERY_STRING']
Guido van Rossum9a22de11995-01-12 12:29:47 +0000754
755
Guido van Rossum9a22de11995-01-12 12:29:47 +0000756class SvFormContentDict(FormContentDict):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000757 """Form content as dictionary expecting a single value per field.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000758
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000759 If you only expect a single value for each field, then form[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000760 will return that single value. It will raise an IndexError if
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000761 that expectation is not true. If you expect a field to have
Guido van Rossum7aee3841996-03-07 18:00:44 +0000762 possible multiple values, than you can use form.getlist(key) to
763 get all of the values. values() and items() are a compromise:
764 they return single strings where there is a single value, and
765 lists of strings otherwise.
766
767 """
768 def __getitem__(self, key):
Tim Peters88869f92001-01-14 23:36:06 +0000769 if len(self.dict[key]) > 1:
770 raise IndexError, 'expecting a single value'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000771 return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000772 def getlist(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000773 return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000774 def values(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000775 result = []
776 for value in self.dict.values():
777 if len(value) == 1:
778 result.append(value[0])
779 else: result.append(value)
780 return result
Guido van Rossum7aee3841996-03-07 18:00:44 +0000781 def items(self):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000782 result = []
783 for key, value in self.dict.items():
784 if len(value) == 1:
785 result.append((key, value[0]))
786 else: result.append((key, value))
787 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000788
789
Guido van Rossum9a22de11995-01-12 12:29:47 +0000790class InterpFormContentDict(SvFormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000791 """This class is present for backwards compatibility only."""
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000792 def __getitem__(self, key):
793 v = SvFormContentDict.__getitem__(self, key)
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000794 if v[0] in '0123456789+-.':
795 try: return int(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000796 except ValueError:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000797 try: return float(v)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000798 except ValueError: pass
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000799 return v.strip()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000800 def values(self):
801 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000802 for key in self.keys():
803 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000804 result.append(self[key])
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000805 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000806 result.append(self.dict[key])
807 return result
808 def items(self):
809 result = []
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000810 for key in self.keys():
811 try:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000812 result.append((key, self[key]))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000813 except IndexError:
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000814 result.append((key, self.dict[key]))
815 return result
Guido van Rossum9a22de11995-01-12 12:29:47 +0000816
817
Guido van Rossum9a22de11995-01-12 12:29:47 +0000818class FormContent(FormContentDict):
Tim Peters88869f92001-01-14 23:36:06 +0000819 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +0000820 def values(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000821 if self.dict.has_key(key) :return self.dict[key]
822 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000823 def indexed_value(self, key, location):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000824 if self.dict.has_key(key):
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000825 if len(self.dict[key]) > location:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000826 return self.dict[key][location]
827 else: return None
828 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000829 def value(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000830 if self.dict.has_key(key): return self.dict[key][0]
831 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +0000832 def length(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000833 return len(self.dict[key])
Guido van Rossum0147db01996-03-09 03:16:04 +0000834 def stripped(self, key):
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000835 if self.dict.has_key(key): return self.dict[key][0].strip()
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000836 else: return None
Guido van Rossum7aee3841996-03-07 18:00:44 +0000837 def pars(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000838 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000839
840
Guido van Rossum72755611996-03-06 07:20:06 +0000841# Test/debug code
842# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +0000843
Guido van Rossum773ab271996-07-23 03:46:24 +0000844def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000845 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000846
Guido van Rossum7aee3841996-03-07 18:00:44 +0000847 Write minimal HTTP headers and dump all information provided to
848 the script in HTML form.
849
850 """
851 import traceback
852 print "Content-type: text/html"
853 print
854 sys.stderr = sys.stdout
855 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000856 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000857 print_directory()
858 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000859 print_form(form)
860 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000861 print_environ_usage()
862 def f():
863 exec "testing print_exception() -- <I>italics?</I>"
864 def g(f=f):
865 f()
866 print "<H3>What follows is a test, not an actual exception:</H3>"
867 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000868 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000869 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000870
Guido van Rossum57d51f22000-09-16 21:16:01 +0000871 print "<H1>Second try with a small maxlen...</H1>"
872
Guido van Rossumad164711997-05-13 19:03:23 +0000873 global maxlen
874 maxlen = 50
875 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000876 form = FieldStorage() # Replace with other classes to test those
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000877 print_directory()
878 print_arguments()
Guido van Rossuma3c6a8a2000-09-19 04:11:46 +0000879 print_form(form)
880 print_environ(environ)
Guido van Rossumad164711997-05-13 19:03:23 +0000881 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000882 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +0000883
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000884def print_exception(type=None, value=None, tb=None, limit=None):
885 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000886 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000887 import traceback
888 print
Guido van Rossum7dd06962000-12-27 19:12:58 +0000889 print "<H3>Traceback (most recent call last):</H3>"
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000890 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000891 traceback.format_exception_only(type, value)
Guido van Rossumf85de8a1996-08-20 20:22:39 +0000892 print "<PRE>%s<B>%s</B></PRE>" % (
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000893 escape("".join(list[:-1])),
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000894 escape(list[-1]),
895 )
Guido van Rossumf15d1591997-09-29 23:22:12 +0000896 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +0000897
Guido van Rossum773ab271996-07-23 03:46:24 +0000898def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000899 """Dump the shell environment as HTML."""
900 keys = environ.keys()
901 keys.sort()
902 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000903 print "<H3>Shell Environment:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000904 print "<DL>"
905 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000906 print "<DT>", escape(key), "<DD>", escape(environ[key])
Tim Peters88869f92001-01-14 23:36:06 +0000907 print "</DL>"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000908 print
Guido van Rossum72755611996-03-06 07:20:06 +0000909
910def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000911 """Dump the contents of a form as HTML."""
912 keys = form.keys()
913 keys.sort()
914 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000915 print "<H3>Form Contents:</H3>"
Guido van Rossum57d51f22000-09-16 21:16:01 +0000916 if not keys:
917 print "<P>No form fields."
Guido van Rossum7aee3841996-03-07 18:00:44 +0000918 print "<DL>"
919 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000920 print "<DT>" + escape(key) + ":",
921 value = form[key]
922 print "<i>" + escape(`type(value)`) + "</i>"
923 print "<DD>" + escape(`value`)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000924 print "</DL>"
925 print
926
927def print_directory():
928 """Dump the current directory as HTML."""
929 print
930 print "<H3>Current Working Directory:</H3>"
931 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000932 pwd = os.getcwd()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000933 except os.error, msg:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000934 print "os.error:", escape(str(msg))
Guido van Rossum7aee3841996-03-07 18:00:44 +0000935 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000936 print escape(pwd)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000937 print
Guido van Rossum9a22de11995-01-12 12:29:47 +0000938
Guido van Rossuma8738a51996-03-14 21:30:28 +0000939def print_arguments():
940 print
Guido van Rossum503e50b1996-05-28 22:57:20 +0000941 print "<H3>Command Line Arguments:</H3>"
Guido van Rossuma8738a51996-03-14 21:30:28 +0000942 print
943 print sys.argv
944 print
945
Guido van Rossum9a22de11995-01-12 12:29:47 +0000946def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +0000947 """Dump a list of environment variables used by CGI as HTML."""
948 print """
Guido van Rossum72755611996-03-06 07:20:06 +0000949<H3>These environment variables could have been set:</H3>
950<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +0000951<LI>AUTH_TYPE
952<LI>CONTENT_LENGTH
953<LI>CONTENT_TYPE
954<LI>DATE_GMT
955<LI>DATE_LOCAL
956<LI>DOCUMENT_NAME
957<LI>DOCUMENT_ROOT
958<LI>DOCUMENT_URI
959<LI>GATEWAY_INTERFACE
960<LI>LAST_MODIFIED
961<LI>PATH
962<LI>PATH_INFO
963<LI>PATH_TRANSLATED
964<LI>QUERY_STRING
965<LI>REMOTE_ADDR
966<LI>REMOTE_HOST
967<LI>REMOTE_IDENT
968<LI>REMOTE_USER
969<LI>REQUEST_METHOD
970<LI>SCRIPT_NAME
971<LI>SERVER_NAME
972<LI>SERVER_PORT
973<LI>SERVER_PROTOCOL
974<LI>SERVER_ROOT
975<LI>SERVER_SOFTWARE
976</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +0000977In addition, HTTP headers sent by the server may be passed in the
978environment as well. Here are some common variable names:
979<UL>
980<LI>HTTP_ACCEPT
981<LI>HTTP_CONNECTION
982<LI>HTTP_HOST
983<LI>HTTP_PRAGMA
984<LI>HTTP_REFERER
985<LI>HTTP_USER_AGENT
986</UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +0000987"""
988
Guido van Rossum9a22de11995-01-12 12:29:47 +0000989
Guido van Rossum72755611996-03-06 07:20:06 +0000990# Utilities
991# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +0000992
Guido van Rossum64c66201997-07-19 20:11:53 +0000993def escape(s, quote=None):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000994 """Replace special characters '&', '<' and '>' by SGML entities."""
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000995 s = s.replace("&", "&amp;") # Must be done first!
996 s = s.replace("<", "&lt;")
997 s = s.replace(">", "&gt;")
Guido van Rossum64c66201997-07-19 20:11:53 +0000998 if quote:
Eric S. Raymond7e9b4f52001-02-09 09:59:10 +0000999 s = s.replace('"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +00001000 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001001
Guido van Rossum9a22de11995-01-12 12:29:47 +00001002
Guido van Rossum72755611996-03-06 07:20:06 +00001003# Invoke mainline
1004# ===============
1005
1006# Call test() when this file is run as a script (not imported as a module)
Tim Peters88869f92001-01-14 23:36:06 +00001007if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001008 test()