Use full package paths in imports.
[python/dscho.git] / Lib / cgi.py
blob5f4bad3c8b6e126162c50bd72fad58774825ecba
1 #! /usr/local/bin/python
3 # 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.
12 """Support module for CGI (Common Gateway Interface) scripts.
14 This module defines a number of utilities for use by CGI scripts
15 written in Python.
16 """
18 # XXX Perhaps there should be a slimmed version that doesn't contain
19 # all those backwards compatible and debugging classes and functions?
21 # History
22 # -------
24 # 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.
31 __version__ = "2.6"
34 # Imports
35 # =======
37 import sys
38 import os
39 import urllib
40 import mimetools
41 import rfc822
42 import UserDict
43 from StringIO import StringIO
45 __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"]
52 # Logging support
53 # ===============
55 logfile = "" # Filename to log to, if not empty
56 logfp = None # File object to log to, if not None
58 def initlog(*allargs):
59 """Write a log message, if there is a log file.
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).
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.
71 If the global logfp is not None, it should be a file object to
72 which log data is written.
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).
80 """
81 global logfp, log
82 if logfile and not logfp:
83 try:
84 logfp = open(logfile, "a")
85 except IOError:
86 pass
87 if not logfp:
88 log = nolog
89 else:
90 log = dolog
91 apply(log, allargs)
93 def dolog(fmt, *args):
94 """Write a log message to the log file. See initlog() for docs."""
95 logfp.write(fmt%args + "\n")
97 def nolog(*allargs):
98 """Dummy function, assigned to log when logging is disabled."""
99 pass
101 log = initlog # The current logging function
104 # Parsing functions
105 # =================
107 # Maximum input we will accept when REQUEST_METHOD is POST
108 # 0 ==> unlimited input
109 maxlen = 0
111 def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
112 """Parse a query in the environment or from a file (default stdin)
114 Arguments, all optional:
116 fp : file pointer; default: sys.stdin
118 environ : environment dictionary; default: os.environ
120 keep_blank_values: flag indicating whether blank values in
121 URL encoded forms should be treated as blank strings.
122 A true value indicates that blanks should be retained as
123 blank strings. The default false value indicates that
124 blank values are to be ignored and treated as if they were
125 not included.
127 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.
131 if fp is None:
132 fp = sys.stdin
133 if not 'REQUEST_METHOD' in environ:
134 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
135 if environ['REQUEST_METHOD'] == 'POST':
136 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':
140 clength = int(environ['CONTENT_LENGTH'])
141 if maxlen and clength > maxlen:
142 raise ValueError, 'Maximum content length exceeded'
143 qs = fp.read(clength)
144 else:
145 qs = '' # Unknown content-type
146 if 'QUERY_STRING' in environ:
147 if qs: qs = qs + '&'
148 qs = qs + environ['QUERY_STRING']
149 elif sys.argv[1:]:
150 if qs: qs = qs + '&'
151 qs = qs + sys.argv[1]
152 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
153 elif 'QUERY_STRING' in environ:
154 qs = environ['QUERY_STRING']
155 else:
156 if sys.argv[1:]:
157 qs = sys.argv[1]
158 else:
159 qs = ""
160 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
161 return parse_qs(qs, keep_blank_values, strict_parsing)
164 def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
165 """Parse a query given as a string argument.
167 Arguments:
169 qs: URL-encoded query string to be parsed
171 keep_blank_values: flag indicating whether blank values in
172 URL encoded queries should be treated as blank strings.
173 A true value indicates that blanks should be retained as
174 blank strings. The default false value indicates that
175 blank values are to be ignored and treated as if they were
176 not included.
178 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.
182 dict = {}
183 for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
184 if name in dict:
185 dict[name].append(value)
186 else:
187 dict[name] = [value]
188 return dict
190 def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
191 """Parse a query given as a string argument.
193 Arguments:
195 qs: URL-encoded query string to be parsed
197 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.
203 strict_parsing: flag indicating what to do with parsing errors. If
204 false (the default), errors are silently ignored. If true,
205 errors raise a ValueError exception.
207 Returns a list, as G-d intended.
209 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)
213 if len(nv) != 2:
214 if strict_parsing:
215 raise ValueError, "bad query field: %s" % `name_value`
216 continue
217 if len(nv[1]) or keep_blank_values:
218 name = urllib.unquote(nv[0].replace('+', ' '))
219 value = urllib.unquote(nv[1].replace('+', ' '))
220 r.append((name, value))
222 return r
225 def parse_multipart(fp, pdict):
226 """Parse multipart input.
228 Arguments:
229 fp : input file
230 pdict: dictionary containing other parameters of conten-type header
232 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
237 header.
239 XXX This does not parse nested multipart parts -- use FieldStorage for
240 that.
242 XXX This should really be subsumed by FieldStorage altogether -- no
243 point in having two implementations of the same parsing algorithm.
246 boundary = ""
247 if 'boundary' in pdict:
248 boundary = pdict['boundary']
249 if not valid_boundary(boundary):
250 raise ValueError, ('Invalid boundary in multipart form: %s'
251 % `boundary`)
253 nextpart = "--" + boundary
254 lastpart = "--" + boundary + "--"
255 partdict = {}
256 terminator = ""
258 while terminator != lastpart:
259 bytes = -1
260 data = None
261 if terminator:
262 # At start of next part. Read headers first.
263 headers = mimetools.Message(fp)
264 clength = headers.getheader('content-length')
265 if clength:
266 try:
267 bytes = int(clength)
268 except ValueError:
269 pass
270 if bytes > 0:
271 if maxlen and bytes > maxlen:
272 raise ValueError, 'Maximum content length exceeded'
273 data = fp.read(bytes)
274 else:
275 data = ""
276 # Read lines until end of part.
277 lines = []
278 while 1:
279 line = fp.readline()
280 if not line:
281 terminator = lastpart # End outer loop
282 break
283 if line[:2] == "--":
284 terminator = line.strip()
285 if terminator in (nextpart, lastpart):
286 break
287 lines.append(line)
288 # Done with part.
289 if data is None:
290 continue
291 if bytes < 0:
292 if lines:
293 # Strip final line terminator
294 line = lines[-1]
295 if line[-2:] == "\r\n":
296 line = line[:-2]
297 elif line[-1:] == "\n":
298 line = line[:-1]
299 lines[-1] = line
300 data = "".join(lines)
301 line = headers['content-disposition']
302 if not line:
303 continue
304 key, params = parse_header(line)
305 if key != 'form-data':
306 continue
307 if 'name' in params:
308 name = params['name']
309 else:
310 continue
311 if name in partdict:
312 partdict[name].append(data)
313 else:
314 partdict[name] = [data]
316 return partdict
319 def parse_header(line):
320 """Parse a Content-type like header.
322 Return the main content-type and a dictionary of options.
325 plist = map(lambda x: x.strip(), line.split(';'))
326 key = plist.pop(0).lower()
327 pdict = {}
328 for p in plist:
329 i = p.find('=')
330 if i >= 0:
331 name = p[:i].strip().lower()
332 value = p[i+1:].strip()
333 if len(value) >= 2 and value[0] == value[-1] == '"':
334 value = value[1:-1]
335 pdict[name] = value
336 return key, pdict
339 # Classes for field storage
340 # =========================
342 class MiniFieldStorage:
344 """Like FieldStorage, for use when no file uploads are possible."""
346 # Dummy attributes
347 filename = None
348 list = None
349 type = None
350 file = None
351 type_options = {}
352 disposition = None
353 disposition_options = {}
354 headers = {}
356 def __init__(self, name, value):
357 """Constructor from field name and value."""
358 self.name = name
359 self.value = value
360 # self.file = StringIO(value)
362 def __repr__(self):
363 """Return printable representation."""
364 return "MiniFieldStorage(%s, %s)" % (`self.name`, `self.value`)
367 class FieldStorage:
369 """Store a sequence of fields, reading multipart/form-data.
371 This class provides naming, typing, files stored on disk, and
372 more. At the top level, it is accessible like a dictionary, whose
373 keys are the field names. (Note: None can occur as a field name.)
374 The items are either a Python list (if there's multiple values) or
375 another FieldStorage or MiniFieldStorage object. If it's a single
376 object, it has the following attributes:
378 name: the field name, if specified; otherwise None
380 filename: the filename, if specified; otherwise None; this is the
381 client side filename, *not* the file name on which it is
382 stored (that's a temporary file you don't deal with)
384 value: the value as a *string*; for file uploads, this
385 transparently reads the file every time you request the value
387 file: the file(-like) object from which you can read the data;
388 None if the data is stored a simple string
390 type: the content-type, or None if not specified
392 type_options: dictionary of options specified on the content-type
393 line
395 disposition: content-disposition, or None if not specified
397 disposition_options: dictionary of corresponding options
399 headers: a dictionary(-like) object (sometimes rfc822.Message or a
400 subclass thereof) containing *all* headers
402 The class is subclassable, mostly for the purpose of overriding
403 the make_file() method, which is called internally to come up with
404 a file open for reading and writing. This makes it possible to
405 override the default choice of storing all files in a temporary
406 directory and unlinking them as soon as they have been opened.
410 def __init__(self, fp=None, headers=None, outerboundary="",
411 environ=os.environ, keep_blank_values=0, strict_parsing=0):
412 """Constructor. Read multipart/* until last part.
414 Arguments, all optional:
416 fp : file pointer; default: sys.stdin
417 (not used when the request method is GET)
419 headers : header dictionary-like object; default:
420 taken from environ as per CGI spec
422 outerboundary : terminating multipart boundary
423 (for internal use only)
425 environ : environment dictionary; default: os.environ
427 keep_blank_values: flag indicating whether blank values in
428 URL encoded forms should be treated as blank strings.
429 A true value indicates that blanks should be retained as
430 blank strings. The default false value indicates that
431 blank values are to be ignored and treated as if they were
432 not included.
434 strict_parsing: flag indicating what to do with parsing errors.
435 If false (the default), errors are silently ignored.
436 If true, errors raise a ValueError exception.
439 method = 'GET'
440 self.keep_blank_values = keep_blank_values
441 self.strict_parsing = strict_parsing
442 if 'REQUEST_METHOD' in environ:
443 method = environ['REQUEST_METHOD'].upper()
444 if method == 'GET' or method == 'HEAD':
445 if 'QUERY_STRING' in environ:
446 qs = environ['QUERY_STRING']
447 elif sys.argv[1:]:
448 qs = sys.argv[1]
449 else:
450 qs = ""
451 fp = StringIO(qs)
452 if headers is None:
453 headers = {'content-type':
454 "application/x-www-form-urlencoded"}
455 if headers is None:
456 headers = {}
457 if method == 'POST':
458 # Set default content-type for POST to what's traditional
459 headers['content-type'] = "application/x-www-form-urlencoded"
460 if 'CONTENT_TYPE' in environ:
461 headers['content-type'] = environ['CONTENT_TYPE']
462 if 'CONTENT_LENGTH' in environ:
463 headers['content-length'] = environ['CONTENT_LENGTH']
464 self.fp = fp or sys.stdin
465 self.headers = headers
466 self.outerboundary = outerboundary
468 # Process content-disposition header
469 cdisp, pdict = "", {}
470 if 'content-disposition' in self.headers:
471 cdisp, pdict = parse_header(self.headers['content-disposition'])
472 self.disposition = cdisp
473 self.disposition_options = pdict
474 self.name = None
475 if 'name' in pdict:
476 self.name = pdict['name']
477 self.filename = None
478 if 'filename' in pdict:
479 self.filename = pdict['filename']
481 # Process content-type header
483 # Honor any existing content-type header. But if there is no
484 # content-type header, use some sensible defaults. Assume
485 # outerboundary is "" at the outer level, but something non-false
486 # inside a multi-part. The default for an inner part is text/plain,
487 # but for an outer part it should be urlencoded. This should catch
488 # bogus clients which erroneously forget to include a content-type
489 # header.
491 # See below for what we do if there does exist a content-type header,
492 # but it happens to be something we don't understand.
493 if 'content-type' in self.headers:
494 ctype, pdict = parse_header(self.headers['content-type'])
495 elif self.outerboundary or method != 'POST':
496 ctype, pdict = "text/plain", {}
497 else:
498 ctype, pdict = 'application/x-www-form-urlencoded', {}
499 self.type = ctype
500 self.type_options = pdict
501 self.innerboundary = ""
502 if 'boundary' in pdict:
503 self.innerboundary = pdict['boundary']
504 clen = -1
505 if 'content-length' in self.headers:
506 try:
507 clen = int(self.headers['content-length'])
508 except ValueError:
509 pass
510 if maxlen and clen > maxlen:
511 raise ValueError, 'Maximum content length exceeded'
512 self.length = clen
514 self.list = self.file = None
515 self.done = 0
516 if ctype == 'application/x-www-form-urlencoded':
517 self.read_urlencoded()
518 elif ctype[:10] == 'multipart/':
519 self.read_multi(environ, keep_blank_values, strict_parsing)
520 else:
521 self.read_single()
523 def __repr__(self):
524 """Return a printable representation."""
525 return "FieldStorage(%s, %s, %s)" % (
526 `self.name`, `self.filename`, `self.value`)
528 def __getattr__(self, name):
529 if name != 'value':
530 raise AttributeError, name
531 if self.file:
532 self.file.seek(0)
533 value = self.file.read()
534 self.file.seek(0)
535 elif self.list is not None:
536 value = self.list
537 else:
538 value = None
539 return value
541 def __getitem__(self, key):
542 """Dictionary style indexing."""
543 if self.list is None:
544 raise TypeError, "not indexable"
545 found = []
546 for item in self.list:
547 if item.name == key: found.append(item)
548 if not found:
549 raise KeyError, key
550 if len(found) == 1:
551 return found[0]
552 else:
553 return found
555 def getvalue(self, key, default=None):
556 """Dictionary style get() method, including 'value' lookup."""
557 if key in self:
558 value = self[key]
559 if type(value) is type([]):
560 return map(lambda v: v.value, value)
561 else:
562 return value.value
563 else:
564 return default
566 def getfirst(self, key, default=None):
567 """ Return the first value received."""
568 if key in self:
569 value = self[key]
570 if type(value) is type([]):
571 return value[0].value
572 else:
573 return value.value
574 else:
575 return default
577 def getlist(self, key):
578 """ Return list of received values."""
579 if key in self:
580 value = self[key]
581 if type(value) is type([]):
582 return map(lambda v: v.value, value)
583 else:
584 return [value.value]
585 else:
586 return []
588 def keys(self):
589 """Dictionary style keys() method."""
590 if self.list is None:
591 raise TypeError, "not indexable"
592 keys = []
593 for item in self.list:
594 if item.name not in keys: keys.append(item.name)
595 return keys
597 def has_key(self, key):
598 """Dictionary style has_key() method."""
599 if self.list is None:
600 raise TypeError, "not indexable"
601 for item in self.list:
602 if item.name == key: return True
603 return False
605 def __contains__(self, key):
606 """Dictionary style __contains__ method."""
607 if self.list is None:
608 raise TypeError, "not indexable"
609 for item in self.list:
610 if item.name == key: return True
611 return False
613 def __len__(self):
614 """Dictionary style len(x) support."""
615 return len(self.keys())
617 def read_urlencoded(self):
618 """Internal: read data in query string format."""
619 qs = self.fp.read(self.length)
620 self.list = list = []
621 for key, value in parse_qsl(qs, self.keep_blank_values,
622 self.strict_parsing):
623 list.append(MiniFieldStorage(key, value))
624 self.skip_lines()
626 FieldStorageClass = None
628 def read_multi(self, environ, keep_blank_values, strict_parsing):
629 """Internal: read a part that is itself multipart."""
630 ib = self.innerboundary
631 if not valid_boundary(ib):
632 raise ValueError, ('Invalid boundary in multipart form: %s'
633 % `ib`)
634 self.list = []
635 klass = self.FieldStorageClass or self.__class__
636 part = klass(self.fp, {}, ib,
637 environ, keep_blank_values, strict_parsing)
638 # Throw first part away
639 while not part.done:
640 headers = rfc822.Message(self.fp)
641 part = klass(self.fp, headers, ib,
642 environ, keep_blank_values, strict_parsing)
643 self.list.append(part)
644 self.skip_lines()
646 def read_single(self):
647 """Internal: read an atomic part."""
648 if self.length >= 0:
649 self.read_binary()
650 self.skip_lines()
651 else:
652 self.read_lines()
653 self.file.seek(0)
655 bufsize = 8*1024 # I/O buffering size for copy to file
657 def read_binary(self):
658 """Internal: read binary data."""
659 self.file = self.make_file('b')
660 todo = self.length
661 if todo >= 0:
662 while todo > 0:
663 data = self.fp.read(min(todo, self.bufsize))
664 if not data:
665 self.done = -1
666 break
667 self.file.write(data)
668 todo = todo - len(data)
670 def read_lines(self):
671 """Internal: read lines until EOF or outerboundary."""
672 self.file = self.__file = StringIO()
673 if self.outerboundary:
674 self.read_lines_to_outerboundary()
675 else:
676 self.read_lines_to_eof()
678 def __write(self, line):
679 if self.__file is not None:
680 if self.__file.tell() + len(line) > 1000:
681 self.file = self.make_file('')
682 self.file.write(self.__file.getvalue())
683 self.__file = None
684 self.file.write(line)
686 def read_lines_to_eof(self):
687 """Internal: read lines until EOF."""
688 while 1:
689 line = self.fp.readline()
690 if not line:
691 self.done = -1
692 break
693 self.__write(line)
695 def read_lines_to_outerboundary(self):
696 """Internal: read lines until outerboundary."""
697 next = "--" + self.outerboundary
698 last = next + "--"
699 delim = ""
700 while 1:
701 line = self.fp.readline()
702 if not line:
703 self.done = -1
704 break
705 if line[:2] == "--":
706 strippedline = line.strip()
707 if strippedline == next:
708 break
709 if strippedline == last:
710 self.done = 1
711 break
712 odelim = delim
713 if line[-2:] == "\r\n":
714 delim = "\r\n"
715 line = line[:-2]
716 elif line[-1] == "\n":
717 delim = "\n"
718 line = line[:-1]
719 else:
720 delim = ""
721 self.__write(odelim + line)
723 def skip_lines(self):
724 """Internal: skip lines until outer boundary if defined."""
725 if not self.outerboundary or self.done:
726 return
727 next = "--" + self.outerboundary
728 last = next + "--"
729 while 1:
730 line = self.fp.readline()
731 if not line:
732 self.done = -1
733 break
734 if line[:2] == "--":
735 strippedline = line.strip()
736 if strippedline == next:
737 break
738 if strippedline == last:
739 self.done = 1
740 break
742 def make_file(self, binary=None):
743 """Overridable: return a readable & writable file.
745 The file will be used as follows:
746 - data is written to it
747 - seek(0)
748 - data is read from it
750 The 'binary' argument is unused -- the file is always opened
751 in binary mode.
753 This version opens a temporary file for reading and writing,
754 and immediately deletes (unlinks) it. The trick (on Unix!) is
755 that the file can still be used, but it can't be opened by
756 another process, and it will automatically be deleted when it
757 is closed or when the current process terminates.
759 If you want a more permanent file, you derive a class which
760 overrides this method. If you want a visible temporary file
761 that is nevertheless automatically deleted when the script
762 terminates, try defining a __del__ method in a derived class
763 which unlinks the temporary files you have created.
766 import tempfile
767 return tempfile.TemporaryFile("w+b")
771 # Backwards Compatibility Classes
772 # ===============================
774 class FormContentDict(UserDict.UserDict):
775 """Form content as dictionary with a list of values per field.
777 form = FormContentDict()
779 form[key] -> [value, value, ...]
780 key in form -> Boolean
781 form.keys() -> [key, key, ...]
782 form.values() -> [[val, val, ...], [val, val, ...], ...]
783 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
784 form.dict == {key: [val, val, ...], ...}
787 def __init__(self, environ=os.environ):
788 self.dict = self.data = parse(environ=environ)
789 self.query_string = environ['QUERY_STRING']
792 class SvFormContentDict(FormContentDict):
793 """Form content as dictionary expecting a single value per field.
795 If you only expect a single value for each field, then form[key]
796 will return that single value. It will raise an IndexError if
797 that expectation is not true. If you expect a field to have
798 possible multiple values, than you can use form.getlist(key) to
799 get all of the values. values() and items() are a compromise:
800 they return single strings where there is a single value, and
801 lists of strings otherwise.
804 def __getitem__(self, key):
805 if len(self.dict[key]) > 1:
806 raise IndexError, 'expecting a single value'
807 return self.dict[key][0]
808 def getlist(self, key):
809 return self.dict[key]
810 def values(self):
811 result = []
812 for value in self.dict.values():
813 if len(value) == 1:
814 result.append(value[0])
815 else: result.append(value)
816 return result
817 def items(self):
818 result = []
819 for key, value in self.dict.items():
820 if len(value) == 1:
821 result.append((key, value[0]))
822 else: result.append((key, value))
823 return result
826 class InterpFormContentDict(SvFormContentDict):
827 """This class is present for backwards compatibility only."""
828 def __getitem__(self, key):
829 v = SvFormContentDict.__getitem__(self, key)
830 if v[0] in '0123456789+-.':
831 try: return int(v)
832 except ValueError:
833 try: return float(v)
834 except ValueError: pass
835 return v.strip()
836 def values(self):
837 result = []
838 for key in self.keys():
839 try:
840 result.append(self[key])
841 except IndexError:
842 result.append(self.dict[key])
843 return result
844 def items(self):
845 result = []
846 for key in self.keys():
847 try:
848 result.append((key, self[key]))
849 except IndexError:
850 result.append((key, self.dict[key]))
851 return result
854 class FormContent(FormContentDict):
855 """This class is present for backwards compatibility only."""
856 def values(self, key):
857 if key in self.dict :return self.dict[key]
858 else: return None
859 def indexed_value(self, key, location):
860 if key in self.dict:
861 if len(self.dict[key]) > location:
862 return self.dict[key][location]
863 else: return None
864 else: return None
865 def value(self, key):
866 if key in self.dict: return self.dict[key][0]
867 else: return None
868 def length(self, key):
869 return len(self.dict[key])
870 def stripped(self, key):
871 if key in self.dict: return self.dict[key][0].strip()
872 else: return None
873 def pars(self):
874 return self.dict
877 # Test/debug code
878 # ===============
880 def test(environ=os.environ):
881 """Robust test CGI script, usable as main program.
883 Write minimal HTTP headers and dump all information provided to
884 the script in HTML form.
887 print "Content-type: text/html"
888 print
889 sys.stderr = sys.stdout
890 try:
891 form = FieldStorage() # Replace with other classes to test those
892 print_directory()
893 print_arguments()
894 print_form(form)
895 print_environ(environ)
896 print_environ_usage()
897 def f():
898 exec "testing print_exception() -- <I>italics?</I>"
899 def g(f=f):
901 print "<H3>What follows is a test, not an actual exception:</H3>"
903 except:
904 print_exception()
906 print "<H1>Second try with a small maxlen...</H1>"
908 global maxlen
909 maxlen = 50
910 try:
911 form = FieldStorage() # Replace with other classes to test those
912 print_directory()
913 print_arguments()
914 print_form(form)
915 print_environ(environ)
916 except:
917 print_exception()
919 def print_exception(type=None, value=None, tb=None, limit=None):
920 if type is None:
921 type, value, tb = sys.exc_info()
922 import traceback
923 print
924 print "<H3>Traceback (most recent call last):</H3>"
925 list = traceback.format_tb(tb, limit) + \
926 traceback.format_exception_only(type, value)
927 print "<PRE>%s<B>%s</B></PRE>" % (
928 escape("".join(list[:-1])),
929 escape(list[-1]),
931 del tb
933 def print_environ(environ=os.environ):
934 """Dump the shell environment as HTML."""
935 keys = environ.keys()
936 keys.sort()
937 print
938 print "<H3>Shell Environment:</H3>"
939 print "<DL>"
940 for key in keys:
941 print "<DT>", escape(key), "<DD>", escape(environ[key])
942 print "</DL>"
943 print
945 def print_form(form):
946 """Dump the contents of a form as HTML."""
947 keys = form.keys()
948 keys.sort()
949 print
950 print "<H3>Form Contents:</H3>"
951 if not keys:
952 print "<P>No form fields."
953 print "<DL>"
954 for key in keys:
955 print "<DT>" + escape(key) + ":",
956 value = form[key]
957 print "<i>" + escape(`type(value)`) + "</i>"
958 print "<DD>" + escape(`value`)
959 print "</DL>"
960 print
962 def print_directory():
963 """Dump the current directory as HTML."""
964 print
965 print "<H3>Current Working Directory:</H3>"
966 try:
967 pwd = os.getcwd()
968 except os.error, msg:
969 print "os.error:", escape(str(msg))
970 else:
971 print escape(pwd)
972 print
974 def print_arguments():
975 print
976 print "<H3>Command Line Arguments:</H3>"
977 print
978 print sys.argv
979 print
981 def print_environ_usage():
982 """Dump a list of environment variables used by CGI as HTML."""
983 print """
984 <H3>These environment variables could have been set:</H3>
985 <UL>
986 <LI>AUTH_TYPE
987 <LI>CONTENT_LENGTH
988 <LI>CONTENT_TYPE
989 <LI>DATE_GMT
990 <LI>DATE_LOCAL
991 <LI>DOCUMENT_NAME
992 <LI>DOCUMENT_ROOT
993 <LI>DOCUMENT_URI
994 <LI>GATEWAY_INTERFACE
995 <LI>LAST_MODIFIED
996 <LI>PATH
997 <LI>PATH_INFO
998 <LI>PATH_TRANSLATED
999 <LI>QUERY_STRING
1000 <LI>REMOTE_ADDR
1001 <LI>REMOTE_HOST
1002 <LI>REMOTE_IDENT
1003 <LI>REMOTE_USER
1004 <LI>REQUEST_METHOD
1005 <LI>SCRIPT_NAME
1006 <LI>SERVER_NAME
1007 <LI>SERVER_PORT
1008 <LI>SERVER_PROTOCOL
1009 <LI>SERVER_ROOT
1010 <LI>SERVER_SOFTWARE
1011 </UL>
1012 In addition, HTTP headers sent by the server may be passed in the
1013 environment as well. Here are some common variable names:
1014 <UL>
1015 <LI>HTTP_ACCEPT
1016 <LI>HTTP_CONNECTION
1017 <LI>HTTP_HOST
1018 <LI>HTTP_PRAGMA
1019 <LI>HTTP_REFERER
1020 <LI>HTTP_USER_AGENT
1021 </UL>
1025 # Utilities
1026 # =========
1028 def escape(s, quote=None):
1029 """Replace special characters '&', '<' and '>' by SGML entities."""
1030 s = s.replace("&", "&amp;") # Must be done first!
1031 s = s.replace("<", "&lt;")
1032 s = s.replace(">", "&gt;")
1033 if quote:
1034 s = s.replace('"', "&quot;")
1035 return s
1037 def valid_boundary(s, _vb_pattern="^[ -~]{0,200}[!-~]$"):
1038 import re
1039 return re.match(_vb_pattern, s)
1041 # Invoke mainline
1042 # ===============
1044 # Call test() when this file is run as a script (not imported as a module)
1045 if __name__ == '__main__':
1046 test()