blob: 3f1a1c4e1e8f156aa63f9ddc8f8eeb4c4c8268bf [file] [log] [blame]
Guido van Rossum9a22de11995-01-12 12:29:47 +00001#!/usr/local/bin/python
Guido van Rossum1c9daa81995-09-18 21:52:37 +00002
Guido van Rossum72755611996-03-06 07:20:06 +00003"""Support module for CGI (Common Gateway Interface) scripts.
Guido van Rossum1c9daa81995-09-18 21:52:37 +00004
Guido van Rossum7aee3841996-03-07 18:00:44 +00005This module defines a number of utilities for use by CGI scripts
6written in Python.
Guido van Rossum9a22de11995-01-12 12:29:47 +00007
8
Guido van Rossum72755611996-03-06 07:20:06 +00009Introduction
10------------
11
Guido van Rossum391b4e61996-03-06 19:11:33 +000012A CGI script is invoked by an HTTP server, usually to process user
13input submitted through an HTML <FORM> or <ISINPUT> element.
Guido van Rossum72755611996-03-06 07:20:06 +000014
Guido van Rossum391b4e61996-03-06 19:11:33 +000015Most often, CGI scripts live in the server's special cgi-bin
16directory. The HTTP server places all sorts of information about the
17request (such as the client's hostname, the requested URL, the query
18string, and lots of other goodies) in the script's shell environment,
19executes the script, and sends the script's output back to the client.
Guido van Rossum72755611996-03-06 07:20:06 +000020
Guido van Rossum391b4e61996-03-06 19:11:33 +000021The script's input is connected to the client too, and sometimes the
22form data is read this way; at other times the form data is passed via
23the "query string" part of the URL. This module (cgi.py) is intended
24to take care of the different cases and provide a simpler interface to
25the Python script. It also provides a number of utilities that help
26in debugging scripts, and the latest addition is support for file
27uploads from a form (if your browser supports it -- Grail 0.3 and
28Netscape 2.0 do).
Guido van Rossum72755611996-03-06 07:20:06 +000029
Guido van Rossum391b4e61996-03-06 19:11:33 +000030The output of a CGI script should consist of two sections, separated
31by a blank line. The first section contains a number of headers,
32telling the client what kind of data is following. Python code to
33generate a minimal header section looks like this:
Guido van Rossum72755611996-03-06 07:20:06 +000034
Guido van Rossum243ddcd1996-03-07 06:33:07 +000035 print "Content-type: text/html" # HTML is following
36 print # blank line, end of headers
Guido van Rossum72755611996-03-06 07:20:06 +000037
Guido van Rossum391b4e61996-03-06 19:11:33 +000038The second section is usually HTML, which allows the client software
39to display nicely formatted text with header, in-line images, etc.
40Here's Python code that prints a simple piece of HTML:
Guido van Rossum72755611996-03-06 07:20:06 +000041
42 print "<TITLE>CGI script output</TITLE>"
43 print "<H1>This is my first CGI script</H1>"
44 print "Hello, world!"
45
Guido van Rossum391b4e61996-03-06 19:11:33 +000046(It may not be fully legal HTML according to the letter of the
47standard, but any browser will understand it.)
Guido van Rossum72755611996-03-06 07:20:06 +000048
49
50Using the cgi module
51--------------------
52
Guido van Rossum391b4e61996-03-06 19:11:33 +000053Begin by writing "import cgi". Don't use "from cgi import *" -- the
Guido van Rossum0147db01996-03-09 03:16:04 +000054module defines all sorts of names for its own use or for backward
55compatibility that you don't want in your namespace.
Guido van Rossum72755611996-03-06 07:20:06 +000056
Guido van Rossum0147db01996-03-09 03:16:04 +000057It's best to use the FieldStorage class. The other classes define in this
58module are provided mostly for backward compatibility. Instantiate it
59exactly once, without arguments. This reads the form contents from
60standard input or the environment (depending on the value of various
61environment variables set according to the CGI standard). Since it may
62consume standard input, it should be instantiated only once.
Guido van Rossum72755611996-03-06 07:20:06 +000063
Guido van Rossum0147db01996-03-09 03:16:04 +000064The FieldStorage instance can be accessed as if it were a Python
65dictionary. For instance, the following code (which assumes that the
66Content-type header and blank line have already been printed) checks that
67the fields "name" and "addr" are both set to a non-empty string:
Guido van Rossum72755611996-03-06 07:20:06 +000068
Guido van Rossum503e50b1996-05-28 22:57:20 +000069 form = cgi.FieldStorage()
Guido van Rossum72755611996-03-06 07:20:06 +000070 form_ok = 0
71 if form.has_key("name") and form.has_key("addr"):
Guido van Rossum0147db01996-03-09 03:16:04 +000072 if form["name"].value != "" and form["addr"].value != "":
Guido van Rossum72755611996-03-06 07:20:06 +000073 form_ok = 1
74 if not form_ok:
75 print "<H1>Error</H1>"
76 print "Please fill in the name and addr fields."
77 return
Guido van Rossum0147db01996-03-09 03:16:04 +000078 ...further form processing here...
Guido van Rossum72755611996-03-06 07:20:06 +000079
Guido van Rossum4032c2c1996-03-09 04:04:35 +000080Here the fields, accessed through form[key], are themselves instances
81of FieldStorage (or MiniFieldStorage, depending on the form encoding).
Guido van Rossum72755611996-03-06 07:20:06 +000082
Guido van Rossum4032c2c1996-03-09 04:04:35 +000083If the submitted form data contains more than one field with the same
84name, the object retrieved by form[key] is not a (Mini)FieldStorage
85instance but a list of such instances. If you expect this possibility
86(i.e., when your HTML form comtains multiple fields with the same
87name), use the type() function to determine whether you have a single
88instance or a list of instances. For example, here's code that
89concatenates any number of username fields, separated by commas:
90
91 username = form["username"]
Guido van Rossum0147db01996-03-09 03:16:04 +000092 if type(username) is type([]):
93 # Multiple username fields specified
94 usernames = ""
95 for item in username:
96 if usernames:
97 # Next item -- insert comma
98 usernames = usernames + "," + item.value
99 else:
100 # First item -- don't insert comma
101 usernames = item.value
102 else:
103 # Single username field specified
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000104 usernames = username.value
Guido van Rossum0147db01996-03-09 03:16:04 +0000105
106If a field represents an uploaded file, the value attribute reads the
107entire file in memory as a string. This may not be what you want. You can
108test for an uploaded file by testing either the filename attribute or the
109file attribute. You can then read the data at leasure from the file
110attribute:
111
112 fileitem = form["userfile"]
113 if fileitem.file:
114 # It's an uploaded file; count lines
115 linecount = 0
116 while 1:
117 line = fileitem.file.readline()
118 if not line: break
119 linecount = linecount + 1
120
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000121The file upload draft standard entertains the possibility of uploading
122multiple files from one field (using a recursive multipart/*
123encoding). When this occurs, the item will be a dictionary-like
124FieldStorage item. This can be determined by testing its type
125attribute, which should have the value "multipart/form-data" (or
126perhaps another string beginning with "multipart/"). It this case, it
127can be iterated over recursively just like the top-level form object.
128
Guido van Rossum0147db01996-03-09 03:16:04 +0000129When a form is submitted in the "old" format (as the query string or as a
130single data part of type application/x-www-form-urlencoded), the items
131will actually be instances of the class MiniFieldStorage. In this case,
132the list, file and filename attributes are always None.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000133
Guido van Rossum72755611996-03-06 07:20:06 +0000134
Guido van Rossum0147db01996-03-09 03:16:04 +0000135Old classes
136-----------
Guido van Rossum72755611996-03-06 07:20:06 +0000137
Guido van Rossum0147db01996-03-09 03:16:04 +0000138These classes, present in earlier versions of the cgi module, are still
Guido van Rossum16d5b111996-10-24 14:44:32 +0000139supported for backward compatibility. New applications should use the
140FieldStorage class.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000141
Guido van Rossum0147db01996-03-09 03:16:04 +0000142SvFormContentDict: single value form content as dictionary; assumes each
143field name occurs in the form only once.
Guido van Rossum72755611996-03-06 07:20:06 +0000144
Guido van Rossum391b4e61996-03-06 19:11:33 +0000145FormContentDict: multiple value form content as dictionary (the form
146items are lists of values). Useful if your form contains multiple
147fields with the same name.
Guido van Rossum72755611996-03-06 07:20:06 +0000148
Guido van Rossum391b4e61996-03-06 19:11:33 +0000149Other classes (FormContent, InterpFormContentDict) are present for
Guido van Rossum0147db01996-03-09 03:16:04 +0000150backwards compatibility with really old applications only. If you still
151use these and would be inconvenienced when they disappeared from a next
152version of this module, drop me a note.
Guido van Rossum72755611996-03-06 07:20:06 +0000153
154
Guido van Rossum0147db01996-03-09 03:16:04 +0000155Functions
156---------
Guido van Rossum72755611996-03-06 07:20:06 +0000157
Guido van Rossum391b4e61996-03-06 19:11:33 +0000158These are useful if you want more control, or if you want to employ
159some of the algorithms implemented in this module in other
160circumstances.
Guido van Rossum72755611996-03-06 07:20:06 +0000161
Guido van Rossume08c04c1996-11-11 19:29:11 +0000162parse(fp, [environ, [keep_blank_values, [strict_parsing]]]): parse a
163form into a Python dictionary.
Guido van Rossum72755611996-03-06 07:20:06 +0000164
Guido van Rossume08c04c1996-11-11 19:29:11 +0000165parse_qs(qs, [keep_blank_values, [strict_parsing]]): parse a query
166string (data of type application/x-www-form-urlencoded).
Guido van Rossum72755611996-03-06 07:20:06 +0000167
Guido van Rossum0147db01996-03-09 03:16:04 +0000168parse_multipart(fp, pdict): parse input of type multipart/form-data (for
Guido van Rossum391b4e61996-03-06 19:11:33 +0000169file uploads).
Guido van Rossum72755611996-03-06 07:20:06 +0000170
Guido van Rossum391b4e61996-03-06 19:11:33 +0000171parse_header(string): parse a header like Content-type into a main
172value and a dictionary of parameters.
Guido van Rossum72755611996-03-06 07:20:06 +0000173
174test(): complete test program.
175
176print_environ(): format the shell environment in HTML.
177
178print_form(form): format a form in HTML.
179
Guido van Rossum391b4e61996-03-06 19:11:33 +0000180print_environ_usage(): print a list of useful environment variables in
181HTML.
Guido van Rossum72755611996-03-06 07:20:06 +0000182
Guido van Rossum391b4e61996-03-06 19:11:33 +0000183escape(): convert the characters "&", "<" and ">" to HTML-safe
184sequences. Use this if you need to display text that might contain
185such characters in HTML. To translate URLs for inclusion in the HREF
186attribute of an <A> tag, use urllib.quote().
Guido van Rossum72755611996-03-06 07:20:06 +0000187
Guido van Rossumc204c701996-09-05 19:07:11 +0000188log(fmt, ...): write a line to a log file; see docs for initlog().
189
Guido van Rossum72755611996-03-06 07:20:06 +0000190
191Caring about security
192---------------------
193
Guido van Rossum391b4e61996-03-06 19:11:33 +0000194There's one important rule: if you invoke an external program (e.g.
195via the os.system() or os.popen() functions), make very sure you don't
196pass arbitrary strings received from the client to the shell. This is
197a well-known security hole whereby clever hackers anywhere on the web
198can exploit a gullible CGI script to invoke arbitrary shell commands.
199Even parts of the URL or field names cannot be trusted, since the
200request doesn't have to come from your form!
Guido van Rossum72755611996-03-06 07:20:06 +0000201
Guido van Rossum391b4e61996-03-06 19:11:33 +0000202To be on the safe side, if you must pass a string gotten from a form
203to a shell command, you should make sure the string contains only
204alphanumeric characters, dashes, underscores, and periods.
Guido van Rossum72755611996-03-06 07:20:06 +0000205
206
207Installing your CGI script on a Unix system
208-------------------------------------------
209
Guido van Rossum391b4e61996-03-06 19:11:33 +0000210Read the documentation for your HTTP server and check with your local
211system administrator to find the directory where CGI scripts should be
Guido van Rossum72755611996-03-06 07:20:06 +0000212installed; usually this is in a directory cgi-bin in the server tree.
213
Guido van Rossum391b4e61996-03-06 19:11:33 +0000214Make sure that your script is readable and executable by "others"; the
215Unix file mode should be 755 (use "chmod 755 filename"). Make sure
216that the first line of the script contains "#!" starting in column 1
217followed by the pathname of the Python interpreter, for instance:
Guido van Rossum72755611996-03-06 07:20:06 +0000218
219 #!/usr/local/bin/python
220
Guido van Rossum391b4e61996-03-06 19:11:33 +0000221Make sure the Python interpreter exists and is executable by "others".
Guido van Rossum72755611996-03-06 07:20:06 +0000222
Guido van Rossum391b4e61996-03-06 19:11:33 +0000223Make sure that any files your script needs to read or write are
224readable or writable, respectively, by "others" -- their mode should
225be 644 for readable and 666 for writable. This is because, for
226security reasons, the HTTP server executes your script as user
227"nobody", without any special privileges. It can only read (write,
228execute) files that everybody can read (write, execute). The current
229directory at execution time is also different (it is usually the
230server's cgi-bin directory) and the set of environment variables is
231also different from what you get at login. in particular, don't count
232on the shell's search path for executables ($PATH) or the Python
233module search path ($PYTHONPATH) to be set to anything interesting.
Guido van Rossum72755611996-03-06 07:20:06 +0000234
Guido van Rossum391b4e61996-03-06 19:11:33 +0000235If you need to load modules from a directory which is not on Python's
236default module search path, you can change the path in your script,
237before importing other modules, e.g.:
Guido van Rossum72755611996-03-06 07:20:06 +0000238
239 import sys
240 sys.path.insert(0, "/usr/home/joe/lib/python")
241 sys.path.insert(0, "/usr/local/lib/python")
242
243(This way, the directory inserted last will be searched first!)
244
Guido van Rossum391b4e61996-03-06 19:11:33 +0000245Instructions for non-Unix systems will vary; check your HTTP server's
Guido van Rossum72755611996-03-06 07:20:06 +0000246documentation (it will usually have a section on CGI scripts).
247
248
249Testing your CGI script
250-----------------------
251
Guido van Rossum391b4e61996-03-06 19:11:33 +0000252Unfortunately, a CGI script will generally not run when you try it
253from the command line, and a script that works perfectly from the
254command line may fail mysteriously when run from the server. There's
255one reason why you should still test your script from the command
256line: if it contains a syntax error, the python interpreter won't
257execute it at all, and the HTTP server will most likely send a cryptic
258error to the client.
Guido van Rossum72755611996-03-06 07:20:06 +0000259
Guido van Rossum391b4e61996-03-06 19:11:33 +0000260Assuming your script has no syntax errors, yet it does not work, you
261have no choice but to read the next section:
Guido van Rossum72755611996-03-06 07:20:06 +0000262
263
264Debugging CGI scripts
265---------------------
266
Guido van Rossum391b4e61996-03-06 19:11:33 +0000267First of all, check for trivial installation errors -- reading the
268section above on installing your CGI script carefully can save you a
269lot of time. If you wonder whether you have understood the
270installation procedure correctly, try installing a copy of this module
271file (cgi.py) as a CGI script. When invoked as a script, the file
272will dump its environment and the contents of the form in HTML form.
273Give it the right mode etc, and send it a request. If it's installed
274in the standard cgi-bin directory, it should be possible to send it a
275request by entering a URL into your browser of the form:
Guido van Rossum72755611996-03-06 07:20:06 +0000276
277 http://yourhostname/cgi-bin/cgi.py?name=Joe+Blow&addr=At+Home
278
Guido van Rossum391b4e61996-03-06 19:11:33 +0000279If this gives an error of type 404, the server cannot find the script
280-- perhaps you need to install it in a different directory. If it
281gives another error (e.g. 500), there's an installation problem that
282you should fix before trying to go any further. If you get a nicely
283formatted listing of the environment and form content (in this
284example, the fields should be listed as "addr" with value "At Home"
285and "name" with value "Joe Blow"), the cgi.py script has been
286installed correctly. If you follow the same procedure for your own
287script, you should now be able to debug it.
Guido van Rossum72755611996-03-06 07:20:06 +0000288
Guido van Rossum391b4e61996-03-06 19:11:33 +0000289The next step could be to call the cgi module's test() function from
290your script: replace its main code with the single statement
Guido van Rossum72755611996-03-06 07:20:06 +0000291
292 cgi.test()
293
Guido van Rossum391b4e61996-03-06 19:11:33 +0000294This should produce the same results as those gotten from installing
295the cgi.py file itself.
Guido van Rossum72755611996-03-06 07:20:06 +0000296
Guido van Rossum391b4e61996-03-06 19:11:33 +0000297When an ordinary Python script raises an unhandled exception
298(e.g. because of a typo in a module name, a file that can't be opened,
299etc.), the Python interpreter prints a nice traceback and exits.
300While the Python interpreter will still do this when your CGI script
301raises an exception, most likely the traceback will end up in one of
302the HTTP server's log file, or be discarded altogether.
Guido van Rossum72755611996-03-06 07:20:06 +0000303
Guido van Rossum391b4e61996-03-06 19:11:33 +0000304Fortunately, once you have managed to get your script to execute
305*some* code, it is easy to catch exceptions and cause a traceback to
306be printed. The test() function below in this module is an example.
307Here are the rules:
Guido van Rossum72755611996-03-06 07:20:06 +0000308
Guido van Rossum391b4e61996-03-06 19:11:33 +0000309 1. Import the traceback module (before entering the
310 try-except!)
Guido van Rossum72755611996-03-06 07:20:06 +0000311
Guido van Rossum391b4e61996-03-06 19:11:33 +0000312 2. Make sure you finish printing the headers and the blank
313 line early
Guido van Rossum72755611996-03-06 07:20:06 +0000314
315 3. Assign sys.stderr to sys.stdout
316
317 3. Wrap all remaining code in a try-except statement
318
319 4. In the except clause, call traceback.print_exc()
320
321For example:
322
323 import sys
324 import traceback
325 print "Content-type: text/html"
326 print
327 sys.stderr = sys.stdout
328 try:
329 ...your code here...
330 except:
331 print "\n\n<PRE>"
332 traceback.print_exc()
333
Guido van Rossum391b4e61996-03-06 19:11:33 +0000334Notes: The assignment to sys.stderr is needed because the traceback
335prints to sys.stderr. The print "\n\n<PRE>" statement is necessary to
336disable the word wrapping in HTML.
Guido van Rossum72755611996-03-06 07:20:06 +0000337
Guido van Rossum391b4e61996-03-06 19:11:33 +0000338If you suspect that there may be a problem in importing the traceback
339module, you can use an even more robust approach (which only uses
340built-in modules):
Guido van Rossum72755611996-03-06 07:20:06 +0000341
342 import sys
343 sys.stderr = sys.stdout
344 print "Content-type: text/plain"
345 print
346 ...your code here...
347
Guido van Rossum391b4e61996-03-06 19:11:33 +0000348This relies on the Python interpreter to print the traceback. The
349content type of the output is set to plain text, which disables all
350HTML processing. If your script works, the raw HTML will be displayed
351by your client. If it raises an exception, most likely after the
352first two lines have been printed, a traceback will be displayed.
353Because no HTML interpretation is going on, the traceback will
354readable.
Guido van Rossum72755611996-03-06 07:20:06 +0000355
Guido van Rossumc204c701996-09-05 19:07:11 +0000356When all else fails, you may want to insert calls to log() to your
357program or even to a copy of the cgi.py file. Note that this requires
358you to set cgi.logfile to the name of a world-writable file before the
359first call to log() is made!
360
Guido van Rossum72755611996-03-06 07:20:06 +0000361Good luck!
362
363
364Common problems and solutions
365-----------------------------
366
Guido van Rossum391b4e61996-03-06 19:11:33 +0000367- Most HTTP servers buffer the output from CGI scripts until the
368script is completed. This means that it is not possible to display a
369progress report on the client's display while the script is running.
Guido van Rossum72755611996-03-06 07:20:06 +0000370
371- Check the installation instructions above.
372
Guido van Rossum391b4e61996-03-06 19:11:33 +0000373- Check the HTTP server's log files. ("tail -f logfile" in a separate
Guido van Rossum72755611996-03-06 07:20:06 +0000374window may be useful!)
375
Guido van Rossum391b4e61996-03-06 19:11:33 +0000376- Always check a script for syntax errors first, by doing something
377like "python script.py".
Guido van Rossum72755611996-03-06 07:20:06 +0000378
379- When using any of the debugging techniques, don't forget to add
380"import sys" to the top of the script.
381
Guido van Rossum391b4e61996-03-06 19:11:33 +0000382- When invoking external programs, make sure they can be found.
383Usually, this means using absolute path names -- $PATH is usually not
384set to a very useful value in a CGI script.
Guido van Rossum72755611996-03-06 07:20:06 +0000385
Guido van Rossum391b4e61996-03-06 19:11:33 +0000386- When reading or writing external files, make sure they can be read
387or written by every user on the system.
Guido van Rossum72755611996-03-06 07:20:06 +0000388
Guido van Rossum391b4e61996-03-06 19:11:33 +0000389- Don't try to give a CGI script a set-uid mode. This doesn't work on
390most systems, and is a security liability as well.
Guido van Rossum72755611996-03-06 07:20:06 +0000391
392
393History
394-------
395
Guido van Rossum391b4e61996-03-06 19:11:33 +0000396Michael McLay started this module. Steve Majewski changed the
397interface to SvFormContentDict and FormContentDict. The multipart
398parsing was inspired by code submitted by Andreas Paepcke. Guido van
399Rossum rewrote, reformatted and documented the module and is currently
400responsible for its maintenance.
Guido van Rossum72755611996-03-06 07:20:06 +0000401
Guido van Rossum0147db01996-03-09 03:16:04 +0000402
403XXX The module is getting pretty heavy with all those docstrings.
404Perhaps there should be a slimmed version that doesn't contain all those
405backwards compatible and debugging classes and functions?
406
Guido van Rossum72755611996-03-06 07:20:06 +0000407"""
408
Guido van Rossum9e3f4291996-08-26 15:46:13 +0000409# " <== Emacs font-lock de-bogo-kludgificocity
410
Guido van Rossume08c04c1996-11-11 19:29:11 +0000411__version__ = "2.1"
Guido van Rossum0147db01996-03-09 03:16:04 +0000412
Guido van Rossum72755611996-03-06 07:20:06 +0000413
414# Imports
415# =======
416
417import string
Guido van Rossum72755611996-03-06 07:20:06 +0000418import sys
419import os
Guido van Rossum72755611996-03-06 07:20:06 +0000420
Guido van Rossumc204c701996-09-05 19:07:11 +0000421
422# Logging support
423# ===============
424
425logfile = "" # Filename to log to, if not empty
426logfp = None # File object to log to, if not None
427
428def initlog(*allargs):
429 """Write a log message, if there is a log file.
430
431 Even though this function is called initlog(), you should always
432 use log(); log is a variable that is set either to initlog
433 (initially), to dolog (once the log file has been opened), or to
434 nolog (when logging is disabled).
435
436 The first argument is a format string; the remaining arguments (if
437 any) are arguments to the % operator, so e.g.
438 log("%s: %s", "a", "b")
439 will write "a: b" to the log file, followed by a newline.
440
441 If the global logfp is not None, it should be a file object to
442 which log data is written.
443
444 If the global logfp is None, the global logfile may be a string
445 giving a filename to open, in append mode. This file should be
446 world writable!!! If the file can't be opened, logging is
447 silently disabled (since there is no safe place where we could
448 send an error message).
449
450 """
451 global logfp, log
452 if logfile and not logfp:
453 try:
454 logfp = open(logfile, "a")
455 except IOError:
456 pass
457 if not logfp:
458 log = nolog
459 else:
460 log = dolog
461 apply(log, allargs)
462
463def dolog(fmt, *args):
464 """Write a log message to the log file. See initlog() for docs."""
465 logfp.write(fmt%args + "\n")
466
467def nolog(*allargs):
468 """Dummy function, assigned to log when logging is disabled."""
469 pass
470
471log = initlog # The current logging function
472
473
Guido van Rossum72755611996-03-06 07:20:06 +0000474# Parsing functions
475# =================
476
Guido van Rossume08c04c1996-11-11 19:29:11 +0000477def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum773ab271996-07-23 03:46:24 +0000478 """Parse a query in the environment or from a file (default stdin)
479
480 Arguments, all optional:
481
482 fp : file pointer; default: sys.stdin
483
484 environ : environment dictionary; default: os.environ
485
486 keep_blank_values: flag indicating whether blank values in
487 URL encoded forms should be treated as blank strings.
488 A true value inicates that blanks should be retained as
489 blank strings. The default false value indicates that
490 blank values are to be ignored and treated as if they were
491 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000492
493 strict_parsing: flag indicating what to do with parsing errors.
494 If false (the default), errors are silently ignored.
495 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000496 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000497 if not fp:
498 fp = sys.stdin
499 if not environ.has_key('REQUEST_METHOD'):
500 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
501 if environ['REQUEST_METHOD'] == 'POST':
502 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
503 if ctype == 'multipart/form-data':
Guido van Rossum0147db01996-03-09 03:16:04 +0000504 return parse_multipart(fp, pdict)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000505 elif ctype == 'application/x-www-form-urlencoded':
506 clength = string.atoi(environ['CONTENT_LENGTH'])
507 qs = fp.read(clength)
Guido van Rossum1c9daa81995-09-18 21:52:37 +0000508 else:
Guido van Rossum0147db01996-03-09 03:16:04 +0000509 qs = '' # Unknown content-type
Guido van Rossumafb5e931996-08-08 18:42:12 +0000510 if environ.has_key('QUERY_STRING'):
511 if qs: qs = qs + '&'
512 qs = qs + environ['QUERY_STRING']
513 elif sys.argv[1:]:
514 if qs: qs = qs + '&'
515 qs = qs + sys.argv[1]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000516 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
517 elif environ.has_key('QUERY_STRING'):
518 qs = environ['QUERY_STRING']
519 else:
520 if sys.argv[1:]:
521 qs = sys.argv[1]
522 else:
523 qs = ""
524 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossume08c04c1996-11-11 19:29:11 +0000525 return parse_qs(qs, keep_blank_values, strict_parsing)
Guido van Rossume7808771995-08-07 20:12:09 +0000526
527
Guido van Rossume08c04c1996-11-11 19:29:11 +0000528def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
529 """Parse a query given as a string argument.
Guido van Rossum773ab271996-07-23 03:46:24 +0000530
531 Arguments:
532
Guido van Rossume08c04c1996-11-11 19:29:11 +0000533 qs: URL-encoded query string to be parsed
Guido van Rossum773ab271996-07-23 03:46:24 +0000534
535 keep_blank_values: flag indicating whether blank values in
536 URL encoded queries should be treated as blank strings.
537 A true value inicates that blanks should be retained as
538 blank strings. The default false value indicates that
539 blank values are to be ignored and treated as if they were
540 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000541
542 strict_parsing: flag indicating what to do with parsing errors.
543 If false (the default), errors are silently ignored.
544 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000545 """
Guido van Rossum0147db01996-03-09 03:16:04 +0000546 import urllib, regsub
Guido van Rossum7aee3841996-03-07 18:00:44 +0000547 name_value_pairs = string.splitfields(qs, '&')
548 dict = {}
549 for name_value in name_value_pairs:
550 nv = string.splitfields(name_value, '=')
551 if len(nv) != 2:
Guido van Rossume08c04c1996-11-11 19:29:11 +0000552 if strict_parsing:
553 raise ValueError, "bad query field: %s" % `name_value`
Guido van Rossum7aee3841996-03-07 18:00:44 +0000554 continue
555 name = nv[0]
556 value = urllib.unquote(regsub.gsub('+', ' ', nv[1]))
Guido van Rossum773ab271996-07-23 03:46:24 +0000557 if len(value) or keep_blank_values:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000558 if dict.has_key (name):
559 dict[name].append(value)
560 else:
561 dict[name] = [value]
562 return dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000563
564
Guido van Rossum0147db01996-03-09 03:16:04 +0000565def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000566 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000567
Guido van Rossum7aee3841996-03-07 18:00:44 +0000568 Arguments:
569 fp : input file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000570 pdict: dictionary containing other parameters of conten-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000571
Guido van Rossum0147db01996-03-09 03:16:04 +0000572 Returns a dictionary just like parse_qs(): keys are the field names, each
573 value is a list of values for that field. This is easy to use but not
574 much good if you are expecting megabytes to be uploaded -- in that case,
575 use the FieldStorage class instead which is much more flexible. Note
576 that content-type is the raw, unparsed contents of the content-type
577 header.
578
579 XXX This does not parse nested multipart parts -- use FieldStorage for
580 that.
581
582 XXX This should really be subsumed by FieldStorage altogether -- no
583 point in having two implementations of the same parsing algorithm.
Guido van Rossum72755611996-03-06 07:20:06 +0000584
Guido van Rossum7aee3841996-03-07 18:00:44 +0000585 """
586 import mimetools
587 if pdict.has_key('boundary'):
588 boundary = pdict['boundary']
589 else:
590 boundary = ""
591 nextpart = "--" + boundary
592 lastpart = "--" + boundary + "--"
593 partdict = {}
594 terminator = ""
595
596 while terminator != lastpart:
597 bytes = -1
598 data = None
599 if terminator:
600 # At start of next part. Read headers first.
601 headers = mimetools.Message(fp)
602 clength = headers.getheader('content-length')
603 if clength:
604 try:
605 bytes = string.atoi(clength)
606 except string.atoi_error:
607 pass
608 if bytes > 0:
609 data = fp.read(bytes)
610 else:
611 data = ""
612 # Read lines until end of part.
613 lines = []
614 while 1:
615 line = fp.readline()
616 if not line:
617 terminator = lastpart # End outer loop
618 break
619 if line[:2] == "--":
620 terminator = string.strip(line)
621 if terminator in (nextpart, lastpart):
622 break
Guido van Rossum7aee3841996-03-07 18:00:44 +0000623 lines.append(line)
624 # Done with part.
625 if data is None:
626 continue
627 if bytes < 0:
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000628 if lines:
629 # Strip final line terminator
630 line = lines[-1]
631 if line[-2:] == "\r\n":
632 line = line[:-2]
633 elif line[-1:] == "\n":
634 line = line[:-1]
635 lines[-1] = line
636 data = string.joinfields(lines, "")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000637 line = headers['content-disposition']
638 if not line:
639 continue
640 key, params = parse_header(line)
641 if key != 'form-data':
642 continue
643 if params.has_key('name'):
644 name = params['name']
Guido van Rossum72755611996-03-06 07:20:06 +0000645 else:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000646 continue
Guido van Rossum7aee3841996-03-07 18:00:44 +0000647 if partdict.has_key(name):
648 partdict[name].append(data)
649 else:
650 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000651
Guido van Rossum7aee3841996-03-07 18:00:44 +0000652 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000653
654
Guido van Rossum72755611996-03-06 07:20:06 +0000655def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000656 """Parse a Content-type like header.
657
658 Return the main content-type and a dictionary of options.
659
660 """
661 plist = map(string.strip, string.splitfields(line, ';'))
662 key = string.lower(plist[0])
663 del plist[0]
664 pdict = {}
665 for p in plist:
666 i = string.find(p, '=')
667 if i >= 0:
668 name = string.lower(string.strip(p[:i]))
669 value = string.strip(p[i+1:])
670 if len(value) >= 2 and value[0] == value[-1] == '"':
671 value = value[1:-1]
672 pdict[name] = value
673 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000674
675
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000676# Classes for field storage
677# =========================
678
679class MiniFieldStorage:
680
Guido van Rossum0147db01996-03-09 03:16:04 +0000681 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000682
Guido van Rossum7aee3841996-03-07 18:00:44 +0000683 # Dummy attributes
684 filename = None
685 list = None
686 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000687 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000688 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000689 disposition = None
690 disposition_options = {}
691 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000692
Guido van Rossum7aee3841996-03-07 18:00:44 +0000693 def __init__(self, name, value):
694 """Constructor from field name and value."""
695 from StringIO import StringIO
696 self.name = name
697 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000698 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000699
700 def __repr__(self):
701 """Return printable representation."""
702 return "MiniFieldStorage(%s, %s)" % (`self.name`, `self.value`)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000703
704
705class FieldStorage:
706
Guido van Rossum7aee3841996-03-07 18:00:44 +0000707 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000708
Guido van Rossum7aee3841996-03-07 18:00:44 +0000709 This class provides naming, typing, files stored on disk, and
710 more. At the top level, it is accessible like a dictionary, whose
711 keys are the field names. (Note: None can occur as a field name.)
712 The items are either a Python list (if there's multiple values) or
713 another FieldStorage or MiniFieldStorage object. If it's a single
714 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000715
Guido van Rossum7aee3841996-03-07 18:00:44 +0000716 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000717
Guido van Rossum7aee3841996-03-07 18:00:44 +0000718 filename: the filename, if specified; otherwise None; this is the
719 client side filename, *not* the file name on which it is
Guido van Rossum0147db01996-03-09 03:16:04 +0000720 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000721
Guido van Rossum7aee3841996-03-07 18:00:44 +0000722 value: the value as a *string*; for file uploads, this
723 transparently reads the file every time you request the value
724
725 file: the file(-like) object from which you can read the data;
726 None if the data is stored a simple string
727
728 type: the content-type, or None if not specified
729
730 type_options: dictionary of options specified on the content-type
731 line
732
733 disposition: content-disposition, or None if not specified
734
735 disposition_options: dictionary of corresponding options
736
737 headers: a dictionary(-like) object (sometimes rfc822.Message or a
738 subclass thereof) containing *all* headers
739
740 The class is subclassable, mostly for the purpose of overriding
741 the make_file() method, which is called internally to come up with
742 a file open for reading and writing. This makes it possible to
743 override the default choice of storing all files in a temporary
744 directory and unlinking them as soon as they have been opened.
745
746 """
747
Guido van Rossum773ab271996-07-23 03:46:24 +0000748 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossume08c04c1996-11-11 19:29:11 +0000749 environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000750 """Constructor. Read multipart/* until last part.
751
752 Arguments, all optional:
753
754 fp : file pointer; default: sys.stdin
755
756 headers : header dictionary-like object; default:
757 taken from environ as per CGI spec
758
Guido van Rossum773ab271996-07-23 03:46:24 +0000759 outerboundary : terminating multipart boundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000760 (for internal use only)
761
Guido van Rossum773ab271996-07-23 03:46:24 +0000762 environ : environment dictionary; default: os.environ
763
764 keep_blank_values: flag indicating whether blank values in
765 URL encoded forms should be treated as blank strings.
766 A true value inicates that blanks should be retained as
767 blank strings. The default false value indicates that
768 blank values are to be ignored and treated as if they were
769 not included.
770
Guido van Rossume08c04c1996-11-11 19:29:11 +0000771 strict_parsing: flag indicating what to do with parsing errors.
772 If false (the default), errors are silently ignored.
773 If true, errors raise a ValueError exception.
774
Guido van Rossum7aee3841996-03-07 18:00:44 +0000775 """
776 method = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000777 self.keep_blank_values = keep_blank_values
Guido van Rossume08c04c1996-11-11 19:29:11 +0000778 self.strict_parsing = strict_parsing
Guido van Rossum7aee3841996-03-07 18:00:44 +0000779 if environ.has_key('REQUEST_METHOD'):
780 method = string.upper(environ['REQUEST_METHOD'])
781 if not fp and method == 'GET':
782 qs = None
783 if environ.has_key('QUERY_STRING'):
784 qs = environ['QUERY_STRING']
785 from StringIO import StringIO
786 fp = StringIO(qs or "")
787 if headers is None:
788 headers = {'content-type':
789 "application/x-www-form-urlencoded"}
790 if headers is None:
791 headers = {}
792 if environ.has_key('CONTENT_TYPE'):
793 headers['content-type'] = environ['CONTENT_TYPE']
794 if environ.has_key('CONTENT_LENGTH'):
795 headers['content-length'] = environ['CONTENT_LENGTH']
796 self.fp = fp or sys.stdin
797 self.headers = headers
798 self.outerboundary = outerboundary
799
800 # Process content-disposition header
801 cdisp, pdict = "", {}
802 if self.headers.has_key('content-disposition'):
803 cdisp, pdict = parse_header(self.headers['content-disposition'])
804 self.disposition = cdisp
805 self.disposition_options = pdict
806 self.name = None
807 if pdict.has_key('name'):
808 self.name = pdict['name']
809 self.filename = None
810 if pdict.has_key('filename'):
811 self.filename = pdict['filename']
812
813 # Process content-type header
814 ctype, pdict = "text/plain", {}
815 if self.headers.has_key('content-type'):
816 ctype, pdict = parse_header(self.headers['content-type'])
817 self.type = ctype
818 self.type_options = pdict
819 self.innerboundary = ""
820 if pdict.has_key('boundary'):
821 self.innerboundary = pdict['boundary']
822 clen = -1
823 if self.headers.has_key('content-length'):
824 try:
825 clen = string.atoi(self.headers['content-length'])
826 except:
827 pass
828 self.length = clen
829
830 self.list = self.file = None
831 self.done = 0
832 self.lines = []
833 if ctype == 'application/x-www-form-urlencoded':
834 self.read_urlencoded()
835 elif ctype[:10] == 'multipart/':
836 self.read_multi()
837 else:
838 self.read_single()
839
840 def __repr__(self):
841 """Return a printable representation."""
842 return "FieldStorage(%s, %s, %s)" % (
843 `self.name`, `self.filename`, `self.value`)
844
845 def __getattr__(self, name):
846 if name != 'value':
847 raise AttributeError, name
848 if self.file:
849 self.file.seek(0)
850 value = self.file.read()
851 self.file.seek(0)
852 elif self.list is not None:
853 value = self.list
854 else:
855 value = None
856 return value
857
858 def __getitem__(self, key):
859 """Dictionary style indexing."""
860 if self.list is None:
861 raise TypeError, "not indexable"
862 found = []
863 for item in self.list:
864 if item.name == key: found.append(item)
865 if not found:
866 raise KeyError, key
Guido van Rossum0147db01996-03-09 03:16:04 +0000867 if len(found) == 1:
868 return found[0]
869 else:
870 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000871
872 def keys(self):
873 """Dictionary style keys() method."""
874 if self.list is None:
875 raise TypeError, "not indexable"
876 keys = []
877 for item in self.list:
878 if item.name not in keys: keys.append(item.name)
879 return keys
880
Guido van Rossum0147db01996-03-09 03:16:04 +0000881 def has_key(self, key):
882 """Dictionary style has_key() method."""
883 if self.list is None:
884 raise TypeError, "not indexable"
885 for item in self.list:
886 if item.name == key: return 1
887 return 0
888
Guido van Rossum7aee3841996-03-07 18:00:44 +0000889 def read_urlencoded(self):
890 """Internal: read data in query string format."""
891 qs = self.fp.read(self.length)
Guido van Rossume08c04c1996-11-11 19:29:11 +0000892 dict = parse_qs(qs, self.keep_blank_values, self.strict_parsing)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000893 self.list = []
894 for key, valuelist in dict.items():
895 for value in valuelist:
896 self.list.append(MiniFieldStorage(key, value))
897 self.skip_lines()
898
899 def read_multi(self):
900 """Internal: read a part that is itself multipart."""
901 import rfc822
902 self.list = []
903 part = self.__class__(self.fp, {}, self.innerboundary)
904 # Throw first part away
905 while not part.done:
906 headers = rfc822.Message(self.fp)
907 part = self.__class__(self.fp, headers, self.innerboundary)
908 self.list.append(part)
909 self.skip_lines()
910
911 def read_single(self):
912 """Internal: read an atomic part."""
913 if self.length >= 0:
914 self.read_binary()
915 self.skip_lines()
916 else:
917 self.read_lines()
918 self.file.seek(0)
919
920 bufsize = 8*1024 # I/O buffering size for copy to file
921
922 def read_binary(self):
923 """Internal: read binary data."""
924 self.file = self.make_file('b')
925 todo = self.length
926 if todo >= 0:
927 while todo > 0:
928 data = self.fp.read(min(todo, self.bufsize))
929 if not data:
930 self.done = -1
931 break
932 self.file.write(data)
933 todo = todo - len(data)
934
935 def read_lines(self):
936 """Internal: read lines until EOF or outerboundary."""
937 self.file = self.make_file('')
938 if self.outerboundary:
939 self.read_lines_to_outerboundary()
940 else:
941 self.read_lines_to_eof()
942
943 def read_lines_to_eof(self):
944 """Internal: read lines until EOF."""
945 while 1:
946 line = self.fp.readline()
947 if not line:
948 self.done = -1
949 break
950 self.lines.append(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000951 self.file.write(line)
952
953 def read_lines_to_outerboundary(self):
954 """Internal: read lines until outerboundary."""
955 next = "--" + self.outerboundary
956 last = next + "--"
957 delim = ""
958 while 1:
959 line = self.fp.readline()
960 if not line:
961 self.done = -1
962 break
963 self.lines.append(line)
964 if line[:2] == "--":
965 strippedline = string.strip(line)
966 if strippedline == next:
967 break
968 if strippedline == last:
969 self.done = 1
970 break
Guido van Rossume5e46e01996-09-05 19:03:36 +0000971 odelim = delim
Guido van Rossum7aee3841996-03-07 18:00:44 +0000972 if line[-2:] == "\r\n":
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000973 delim = "\r\n"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000974 line = line[:-2]
975 elif line[-1] == "\n":
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000976 delim = "\n"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000977 line = line[:-1]
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000978 else:
979 delim = ""
Guido van Rossume5e46e01996-09-05 19:03:36 +0000980 self.file.write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000981
982 def skip_lines(self):
983 """Internal: skip lines until outer boundary if defined."""
984 if not self.outerboundary or self.done:
985 return
986 next = "--" + self.outerboundary
987 last = next + "--"
988 while 1:
989 line = self.fp.readline()
990 if not line:
991 self.done = -1
992 break
993 self.lines.append(line)
994 if line[:2] == "--":
995 strippedline = string.strip(line)
996 if strippedline == next:
997 break
998 if strippedline == last:
999 self.done = 1
1000 break
1001
1002 def make_file(self, binary):
1003 """Overridable: return a readable & writable file.
1004
1005 The file will be used as follows:
1006 - data is written to it
1007 - seek(0)
1008 - data is read from it
1009
1010 The 'binary' argument is 'b' if the file should be created in
1011 binary mode (on non-Unix systems), '' otherwise.
1012
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001013 This version opens a temporary file for reading and writing,
1014 and immediately deletes (unlinks) it. The trick (on Unix!) is
1015 that the file can still be used, but it can't be opened by
1016 another process, and it will automatically be deleted when it
1017 is closed or when the current process terminates.
1018
1019 If you want a more permanent file, you derive a class which
1020 overrides this method. If you want a visible temporary file
1021 that is nevertheless automatically deleted when the script
1022 terminates, try defining a __del__ method in a derived class
1023 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +00001024
1025 """
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001026 import tempfile
1027 tfn = tempfile.mktemp()
1028 f = open(tfn, "w%s+" % binary)
1029 os.unlink(tfn)
1030 return f
Guido van Rossum243ddcd1996-03-07 06:33:07 +00001031
1032
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001033# Backwards Compatibility Classes
1034# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +00001035
1036class FormContentDict:
Guido van Rossum7aee3841996-03-07 18:00:44 +00001037 """Basic (multiple values per field) form content as dictionary.
Guido van Rossum72755611996-03-06 07:20:06 +00001038
Guido van Rossum7aee3841996-03-07 18:00:44 +00001039 form = FormContentDict()
1040
1041 form[key] -> [value, value, ...]
1042 form.has_key(key) -> Boolean
1043 form.keys() -> [key, key, ...]
1044 form.values() -> [[val, val, ...], [val, val, ...], ...]
1045 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
1046 form.dict == {key: [val, val, ...], ...}
1047
1048 """
Guido van Rossum773ab271996-07-23 03:46:24 +00001049 def __init__(self, environ=os.environ):
Guido van Rossumafb5e931996-08-08 18:42:12 +00001050 self.dict = parse(environ=environ)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001051 self.query_string = environ['QUERY_STRING']
1052 def __getitem__(self,key):
1053 return self.dict[key]
1054 def keys(self):
1055 return self.dict.keys()
1056 def has_key(self, key):
1057 return self.dict.has_key(key)
1058 def values(self):
1059 return self.dict.values()
1060 def items(self):
1061 return self.dict.items()
1062 def __len__( self ):
1063 return len(self.dict)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001064
1065
Guido van Rossum9a22de11995-01-12 12:29:47 +00001066class SvFormContentDict(FormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001067 """Strict single-value expecting form content as dictionary.
1068
1069 IF you only expect a single value for each field, then form[key]
1070 will return that single value. It will raise an IndexError if
1071 that expectation is not true. IF you expect a field to have
1072 possible multiple values, than you can use form.getlist(key) to
1073 get all of the values. values() and items() are a compromise:
1074 they return single strings where there is a single value, and
1075 lists of strings otherwise.
1076
1077 """
1078 def __getitem__(self, key):
1079 if len(self.dict[key]) > 1:
1080 raise IndexError, 'expecting a single value'
1081 return self.dict[key][0]
1082 def getlist(self, key):
1083 return self.dict[key]
1084 def values(self):
1085 lis = []
1086 for each in self.dict.values():
1087 if len( each ) == 1 :
1088 lis.append(each[0])
1089 else: lis.append(each)
1090 return lis
1091 def items(self):
1092 lis = []
1093 for key,value in self.dict.items():
1094 if len(value) == 1 :
1095 lis.append((key, value[0]))
1096 else: lis.append((key, value))
1097 return lis
Guido van Rossum9a22de11995-01-12 12:29:47 +00001098
1099
Guido van Rossum9a22de11995-01-12 12:29:47 +00001100class InterpFormContentDict(SvFormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001101 """This class is present for backwards compatibility only."""
1102 def __getitem__( self, key ):
1103 v = SvFormContentDict.__getitem__( self, key )
1104 if v[0] in string.digits+'+-.' :
1105 try: return string.atoi( v )
1106 except ValueError:
1107 try: return string.atof( v )
1108 except ValueError: pass
1109 return string.strip(v)
1110 def values( self ):
1111 lis = []
1112 for key in self.keys():
1113 try:
1114 lis.append( self[key] )
1115 except IndexError:
1116 lis.append( self.dict[key] )
1117 return lis
1118 def items( self ):
1119 lis = []
1120 for key in self.keys():
1121 try:
1122 lis.append( (key, self[key]) )
1123 except IndexError:
1124 lis.append( (key, self.dict[key]) )
1125 return lis
Guido van Rossum9a22de11995-01-12 12:29:47 +00001126
1127
Guido van Rossum9a22de11995-01-12 12:29:47 +00001128class FormContent(FormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001129 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +00001130 def values(self, key):
1131 if self.dict.has_key(key) :return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +00001132 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001133 def indexed_value(self, key, location):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001134 if self.dict.has_key(key):
1135 if len (self.dict[key]) > location:
1136 return self.dict[key][location]
1137 else: return None
1138 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001139 def value(self, key):
1140 if self.dict.has_key(key): return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +00001141 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001142 def length(self, key):
1143 return len(self.dict[key])
1144 def stripped(self, key):
1145 if self.dict.has_key(key): return string.strip(self.dict[key][0])
Guido van Rossum7aee3841996-03-07 18:00:44 +00001146 else: return None
1147 def pars(self):
1148 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +00001149
1150
Guido van Rossum72755611996-03-06 07:20:06 +00001151# Test/debug code
1152# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +00001153
Guido van Rossum773ab271996-07-23 03:46:24 +00001154def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001155 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +00001156
Guido van Rossum7aee3841996-03-07 18:00:44 +00001157 Write minimal HTTP headers and dump all information provided to
1158 the script in HTML form.
1159
1160 """
1161 import traceback
1162 print "Content-type: text/html"
1163 print
1164 sys.stderr = sys.stdout
1165 try:
Guido van Rossum0147db01996-03-09 03:16:04 +00001166 form = FieldStorage() # Replace with other classes to test those
1167 print_form(form)
Guido van Rossum773ab271996-07-23 03:46:24 +00001168 print_environ(environ)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001169 print_directory()
Guido van Rossuma8738a51996-03-14 21:30:28 +00001170 print_arguments()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001171 print_environ_usage()
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001172 def f():
1173 exec "testing print_exception() -- <I>italics?</I>"
1174 def g(f=f):
1175 f()
1176 print "<H3>What follows is a test, not an actual exception:</H3>"
1177 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001178 except:
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001179 print_exception()
1180
1181def print_exception(type=None, value=None, tb=None, limit=None):
1182 if type is None:
1183 type, value, tb = sys.exc_type, sys.exc_value, sys.exc_traceback
1184 import traceback
1185 print
1186 print "<H3>Traceback (innermost last):</H3>"
1187 list = traceback.format_tb(tb, limit) + \
1188 traceback.format_exception_only(type, value)
1189 print "<PRE>%s<B>%s</B></PRE>" % (
1190 escape(string.join(list[:-1], "")),
1191 escape(list[-1]),
1192 )
Guido van Rossum9a22de11995-01-12 12:29:47 +00001193
Guido van Rossum773ab271996-07-23 03:46:24 +00001194def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001195 """Dump the shell environment as HTML."""
1196 keys = environ.keys()
1197 keys.sort()
1198 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001199 print "<H3>Shell Environment:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +00001200 print "<DL>"
1201 for key in keys:
1202 print "<DT>", escape(key), "<DD>", escape(environ[key])
1203 print "</DL>"
1204 print
Guido van Rossum72755611996-03-06 07:20:06 +00001205
1206def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001207 """Dump the contents of a form as HTML."""
1208 keys = form.keys()
1209 keys.sort()
1210 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001211 print "<H3>Form Contents:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +00001212 print "<DL>"
1213 for key in keys:
1214 print "<DT>" + escape(key) + ":",
1215 value = form[key]
1216 print "<i>" + escape(`type(value)`) + "</i>"
1217 print "<DD>" + escape(`value`)
1218 print "</DL>"
1219 print
1220
1221def print_directory():
1222 """Dump the current directory as HTML."""
1223 print
1224 print "<H3>Current Working Directory:</H3>"
1225 try:
1226 pwd = os.getcwd()
1227 except os.error, msg:
1228 print "os.error:", escape(str(msg))
1229 else:
1230 print escape(pwd)
1231 print
Guido van Rossum9a22de11995-01-12 12:29:47 +00001232
Guido van Rossuma8738a51996-03-14 21:30:28 +00001233def print_arguments():
1234 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001235 print "<H3>Command Line Arguments:</H3>"
Guido van Rossuma8738a51996-03-14 21:30:28 +00001236 print
1237 print sys.argv
1238 print
1239
Guido van Rossum9a22de11995-01-12 12:29:47 +00001240def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +00001241 """Dump a list of environment variables used by CGI as HTML."""
1242 print """
Guido van Rossum72755611996-03-06 07:20:06 +00001243<H3>These environment variables could have been set:</H3>
1244<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001245<LI>AUTH_TYPE
1246<LI>CONTENT_LENGTH
1247<LI>CONTENT_TYPE
1248<LI>DATE_GMT
1249<LI>DATE_LOCAL
1250<LI>DOCUMENT_NAME
1251<LI>DOCUMENT_ROOT
1252<LI>DOCUMENT_URI
1253<LI>GATEWAY_INTERFACE
1254<LI>LAST_MODIFIED
1255<LI>PATH
1256<LI>PATH_INFO
1257<LI>PATH_TRANSLATED
1258<LI>QUERY_STRING
1259<LI>REMOTE_ADDR
1260<LI>REMOTE_HOST
1261<LI>REMOTE_IDENT
1262<LI>REMOTE_USER
1263<LI>REQUEST_METHOD
1264<LI>SCRIPT_NAME
1265<LI>SERVER_NAME
1266<LI>SERVER_PORT
1267<LI>SERVER_PROTOCOL
1268<LI>SERVER_ROOT
1269<LI>SERVER_SOFTWARE
1270</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001271In addition, HTTP headers sent by the server may be passed in the
1272environment as well. Here are some common variable names:
1273<UL>
1274<LI>HTTP_ACCEPT
1275<LI>HTTP_CONNECTION
1276<LI>HTTP_HOST
1277<LI>HTTP_PRAGMA
1278<LI>HTTP_REFERER
1279<LI>HTTP_USER_AGENT
1280</UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001281"""
1282
Guido van Rossum9a22de11995-01-12 12:29:47 +00001283
Guido van Rossum72755611996-03-06 07:20:06 +00001284# Utilities
1285# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001286
Guido van Rossum72755611996-03-06 07:20:06 +00001287def escape(s):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001288 """Replace special characters '&', '<' and '>' by SGML entities."""
Guido van Rossum0147db01996-03-09 03:16:04 +00001289 import regsub
Guido van Rossum7aee3841996-03-07 18:00:44 +00001290 s = regsub.gsub("&", "&amp;", s) # Must be done first!
1291 s = regsub.gsub("<", "&lt;", s)
1292 s = regsub.gsub(">", "&gt;", s)
1293 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001294
Guido van Rossum9a22de11995-01-12 12:29:47 +00001295
Guido van Rossum72755611996-03-06 07:20:06 +00001296# Invoke mainline
1297# ===============
1298
1299# Call test() when this file is run as a script (not imported as a module)
1300if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001301 test()