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
12 """Support module for CGI (Common Gateway Interface) scripts.
14 This module defines a number of utilities for use by CGI scripts
18 # XXX Perhaps there should be a slimmed version that doesn't contain
19 # all those backwards compatible and debugging classes and functions?
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.
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"]
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).
82 if logfile
and not logfp
:
84 logfp
= open(logfile
, "a")
93 def dolog(fmt
, *args
):
94 """Write a log message to the log file. See initlog() for docs."""
95 logfp
.write(fmt
%args
+ "\n")
98 """Dummy function, assigned to log when logging is disabled."""
101 log
= initlog
# The current logging function
107 # Maximum input we will accept when REQUEST_METHOD is POST
108 # 0 ==> unlimited input
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
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.
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
)
145 qs
= '' # Unknown content-type
146 if 'QUERY_STRING' in environ
:
148 qs
= qs
+ environ
['QUERY_STRING']
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']
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.
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
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.
183 for name
, value
in parse_qsl(qs
, keep_blank_values
, strict_parsing
):
185 dict[name
].append(value
)
190 def parse_qsl(qs
, keep_blank_values
=0, strict_parsing
=0):
191 """Parse a query given as a string argument.
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(';')]
211 for name_value
in pairs
:
212 nv
= name_value
.split('=', 1)
215 raise ValueError, "bad query field: %s" % `name_value`
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
))
225 def parse_multipart(fp
, pdict
):
226 """Parse multipart input.
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
239 XXX This does not parse nested multipart parts -- use FieldStorage for
242 XXX This should really be subsumed by FieldStorage altogether -- no
243 point in having two implementations of the same parsing algorithm.
247 if 'boundary' in pdict
:
248 boundary
= pdict
['boundary']
249 if not valid_boundary(boundary
):
250 raise ValueError, ('Invalid boundary in multipart form: %s'
253 nextpart
= "--" + boundary
254 lastpart
= "--" + boundary
+ "--"
258 while terminator
!= lastpart
:
262 # At start of next part. Read headers first.
263 headers
= mimetools
.Message(fp
)
264 clength
= headers
.getheader('content-length')
271 if maxlen
and bytes
> maxlen
:
272 raise ValueError, 'Maximum content length exceeded'
273 data
= fp
.read(bytes
)
276 # Read lines until end of part.
281 terminator
= lastpart
# End outer loop
284 terminator
= line
.strip()
285 if terminator
in (nextpart
, lastpart
):
293 # Strip final line terminator
295 if line
[-2:] == "\r\n":
297 elif line
[-1:] == "\n":
300 data
= "".join(lines
)
301 line
= headers
['content-disposition']
304 key
, params
= parse_header(line
)
305 if key
!= 'form-data':
308 name
= params
['name']
312 partdict
[name
].append(data
)
314 partdict
[name
] = [data
]
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()
331 name
= p
[:i
].strip().lower()
332 value
= p
[i
+1:].strip()
333 if len(value
) >= 2 and value
[0] == value
[-1] == '"':
339 # Classes for field storage
340 # =========================
342 class MiniFieldStorage
:
344 """Like FieldStorage, for use when no file uploads are possible."""
353 disposition_options
= {}
356 def __init__(self
, name
, value
):
357 """Constructor from field name and value."""
360 # self.file = StringIO(value)
363 """Return printable representation."""
364 return "MiniFieldStorage(%s, %s)" % (`self
.name`
, `self
.value`
)
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
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
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.
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']
453 headers
= {'content-type':
454 "application/x-www-form-urlencoded"}
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
476 self
.name
= pdict
['name']
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
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", {}
498 ctype
, pdict
= 'application/x-www-form-urlencoded', {}
500 self
.type_options
= pdict
501 self
.innerboundary
= ""
502 if 'boundary' in pdict
:
503 self
.innerboundary
= pdict
['boundary']
505 if 'content-length' in self
.headers
:
507 clen
= int(self
.headers
['content-length'])
510 if maxlen
and clen
> maxlen
:
511 raise ValueError, 'Maximum content length exceeded'
514 self
.list = self
.file = None
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
)
524 """Return a printable representation."""
525 return "FieldStorage(%s, %s, %s)" % (
526 `self
.name`
, `self
.filename`
, `self
.value`
)
528 def __getattr__(self
, name
):
530 raise AttributeError, name
533 value
= self
.file.read()
535 elif self
.list is not None:
541 def __getitem__(self
, key
):
542 """Dictionary style indexing."""
543 if self
.list is None:
544 raise TypeError, "not indexable"
546 for item
in self
.list:
547 if item
.name
== key
: found
.append(item
)
555 def getvalue(self
, key
, default
=None):
556 """Dictionary style get() method, including 'value' lookup."""
559 if type(value
) is type([]):
560 return map(lambda v
: v
.value
, value
)
566 def getfirst(self
, key
, default
=None):
567 """ Return the first value received."""
570 if type(value
) is type([]):
571 return value
[0].value
577 def getlist(self
, key
):
578 """ Return list of received values."""
581 if type(value
) is type([]):
582 return map(lambda v
: v
.value
, value
)
589 """Dictionary style keys() method."""
590 if self
.list is None:
591 raise TypeError, "not indexable"
593 for item
in self
.list:
594 if item
.name
not in keys
: keys
.append(item
.name
)
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
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
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
))
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'
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
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
)
646 def read_single(self
):
647 """Internal: read an atomic part."""
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')
663 data
= self
.fp
.read(min(todo
, self
.bufsize
))
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()
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())
684 self
.file.write(line
)
686 def read_lines_to_eof(self
):
687 """Internal: read lines until EOF."""
689 line
= self
.fp
.readline()
695 def read_lines_to_outerboundary(self
):
696 """Internal: read lines until outerboundary."""
697 next
= "--" + self
.outerboundary
701 line
= self
.fp
.readline()
706 strippedline
= line
.strip()
707 if strippedline
== next
:
709 if strippedline
== last
:
713 if line
[-2:] == "\r\n":
716 elif line
[-1] == "\n":
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
:
727 next
= "--" + self
.outerboundary
730 line
= self
.fp
.readline()
735 strippedline
= line
.strip()
736 if strippedline
== next
:
738 if strippedline
== last
:
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
748 - data is read from it
750 The 'binary' argument is unused -- the file is always opened
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.
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
]
812 for value
in self
.dict.values():
814 result
.append(value
[0])
815 else: result
.append(value
)
819 for key
, value
in self
.dict.items():
821 result
.append((key
, value
[0]))
822 else: result
.append((key
, value
))
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+-.':
834 except ValueError: pass
838 for key
in self
.keys():
840 result
.append(self
[key
])
842 result
.append(self
.dict[key
])
846 for key
in self
.keys():
848 result
.append((key
, self
[key
]))
850 result
.append((key
, self
.dict[key
]))
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
]
859 def indexed_value(self
, key
, location
):
861 if len(self
.dict[key
]) > location
:
862 return self
.dict[key
][location
]
865 def value(self
, key
):
866 if key
in self
.dict: return self
.dict[key
][0]
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()
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"
889 sys
.stderr
= sys
.stdout
891 form
= FieldStorage() # Replace with other classes to test those
895 print_environ(environ
)
896 print_environ_usage()
898 exec "testing print_exception() -- <I>italics?</I>"
901 print "<H3>What follows is a test, not an actual exception:</H3>"
906 print "<H1>Second try with a small maxlen...</H1>"
911 form
= FieldStorage() # Replace with other classes to test those
915 print_environ(environ
)
919 def print_exception(type=None, value
=None, tb
=None, limit
=None):
921 type, value
, tb
= sys
.exc_info()
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])),
933 def print_environ(environ
=os
.environ
):
934 """Dump the shell environment as HTML."""
935 keys
= environ
.keys()
938 print "<H3>Shell Environment:</H3>"
941 print "<DT>", escape(key
), "<DD>", escape(environ
[key
])
945 def print_form(form
):
946 """Dump the contents of a form as HTML."""
950 print "<H3>Form Contents:</H3>"
952 print "<P>No form fields."
955 print "<DT>" + escape(key
) + ":",
957 print "<i>" + escape(`
type(value
)`
) + "</i>"
958 print "<DD>" + escape(`value`
)
962 def print_directory():
963 """Dump the current directory as HTML."""
965 print "<H3>Current Working Directory:</H3>"
968 except os
.error
, msg
:
969 print "os.error:", escape(str(msg
))
974 def print_arguments():
976 print "<H3>Command Line Arguments:</H3>"
981 def print_environ_usage():
982 """Dump a list of environment variables used by CGI as HTML."""
984 <H3>These environment variables could have been set:</H3>
994 <LI>GATEWAY_INTERFACE
1012 In addition, HTTP headers sent by the server may be passed in the
1013 environment as well. Here are some common variable names:
1028 def escape(s
, quote
=None):
1029 """Replace special characters '&', '<' and '>' by SGML entities."""
1030 s
= s
.replace("&", "&") # Must be done first!
1031 s
= s
.replace("<", "<")
1032 s
= s
.replace(">", ">")
1034 s
= s
.replace('"', """)
1037 def valid_boundary(s
, _vb_pattern
="^[ -~]{0,200}[!-~]$"):
1039 return re
.match(_vb_pattern
, s
)
1044 # Call test() when this file is run as a script (not imported as a module)
1045 if __name__
== '__main__':