blob: af5caba00ef2f812c1182cff1312e2b87d1258f1 [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 Rossum0147db01996-03-09 03:16:04 +0000162parse(fp): parse a form into a Python dictionary.
Guido van Rossum72755611996-03-06 07:20:06 +0000163
Guido van Rossum0147db01996-03-09 03:16:04 +0000164parse_qs(qs): parse a query string (data of type
165application/x-www-form-urlencoded).
Guido van Rossum72755611996-03-06 07:20:06 +0000166
Guido van Rossum0147db01996-03-09 03:16:04 +0000167parse_multipart(fp, pdict): parse input of type multipart/form-data (for
Guido van Rossum391b4e61996-03-06 19:11:33 +0000168file uploads).
Guido van Rossum72755611996-03-06 07:20:06 +0000169
Guido van Rossum391b4e61996-03-06 19:11:33 +0000170parse_header(string): parse a header like Content-type into a main
171value and a dictionary of parameters.
Guido van Rossum72755611996-03-06 07:20:06 +0000172
173test(): complete test program.
174
175print_environ(): format the shell environment in HTML.
176
177print_form(form): format a form in HTML.
178
Guido van Rossum391b4e61996-03-06 19:11:33 +0000179print_environ_usage(): print a list of useful environment variables in
180HTML.
Guido van Rossum72755611996-03-06 07:20:06 +0000181
Guido van Rossum391b4e61996-03-06 19:11:33 +0000182escape(): convert the characters "&", "<" and ">" to HTML-safe
183sequences. Use this if you need to display text that might contain
184such characters in HTML. To translate URLs for inclusion in the HREF
185attribute of an <A> tag, use urllib.quote().
Guido van Rossum72755611996-03-06 07:20:06 +0000186
Guido van Rossumc204c701996-09-05 19:07:11 +0000187log(fmt, ...): write a line to a log file; see docs for initlog().
188
Guido van Rossum72755611996-03-06 07:20:06 +0000189
190Caring about security
191---------------------
192
Guido van Rossum391b4e61996-03-06 19:11:33 +0000193There's one important rule: if you invoke an external program (e.g.
194via the os.system() or os.popen() functions), make very sure you don't
195pass arbitrary strings received from the client to the shell. This is
196a well-known security hole whereby clever hackers anywhere on the web
197can exploit a gullible CGI script to invoke arbitrary shell commands.
198Even parts of the URL or field names cannot be trusted, since the
199request doesn't have to come from your form!
Guido van Rossum72755611996-03-06 07:20:06 +0000200
Guido van Rossum391b4e61996-03-06 19:11:33 +0000201To be on the safe side, if you must pass a string gotten from a form
202to a shell command, you should make sure the string contains only
203alphanumeric characters, dashes, underscores, and periods.
Guido van Rossum72755611996-03-06 07:20:06 +0000204
205
206Installing your CGI script on a Unix system
207-------------------------------------------
208
Guido van Rossum391b4e61996-03-06 19:11:33 +0000209Read the documentation for your HTTP server and check with your local
210system administrator to find the directory where CGI scripts should be
Guido van Rossum72755611996-03-06 07:20:06 +0000211installed; usually this is in a directory cgi-bin in the server tree.
212
Guido van Rossum391b4e61996-03-06 19:11:33 +0000213Make sure that your script is readable and executable by "others"; the
214Unix file mode should be 755 (use "chmod 755 filename"). Make sure
215that the first line of the script contains "#!" starting in column 1
216followed by the pathname of the Python interpreter, for instance:
Guido van Rossum72755611996-03-06 07:20:06 +0000217
218 #!/usr/local/bin/python
219
Guido van Rossum391b4e61996-03-06 19:11:33 +0000220Make sure the Python interpreter exists and is executable by "others".
Guido van Rossum72755611996-03-06 07:20:06 +0000221
Guido van Rossum391b4e61996-03-06 19:11:33 +0000222Make sure that any files your script needs to read or write are
223readable or writable, respectively, by "others" -- their mode should
224be 644 for readable and 666 for writable. This is because, for
225security reasons, the HTTP server executes your script as user
226"nobody", without any special privileges. It can only read (write,
227execute) files that everybody can read (write, execute). The current
228directory at execution time is also different (it is usually the
229server's cgi-bin directory) and the set of environment variables is
230also different from what you get at login. in particular, don't count
231on the shell's search path for executables ($PATH) or the Python
232module search path ($PYTHONPATH) to be set to anything interesting.
Guido van Rossum72755611996-03-06 07:20:06 +0000233
Guido van Rossum391b4e61996-03-06 19:11:33 +0000234If you need to load modules from a directory which is not on Python's
235default module search path, you can change the path in your script,
236before importing other modules, e.g.:
Guido van Rossum72755611996-03-06 07:20:06 +0000237
238 import sys
239 sys.path.insert(0, "/usr/home/joe/lib/python")
240 sys.path.insert(0, "/usr/local/lib/python")
241
242(This way, the directory inserted last will be searched first!)
243
Guido van Rossum391b4e61996-03-06 19:11:33 +0000244Instructions for non-Unix systems will vary; check your HTTP server's
Guido van Rossum72755611996-03-06 07:20:06 +0000245documentation (it will usually have a section on CGI scripts).
246
247
248Testing your CGI script
249-----------------------
250
Guido van Rossum391b4e61996-03-06 19:11:33 +0000251Unfortunately, a CGI script will generally not run when you try it
252from the command line, and a script that works perfectly from the
253command line may fail mysteriously when run from the server. There's
254one reason why you should still test your script from the command
255line: if it contains a syntax error, the python interpreter won't
256execute it at all, and the HTTP server will most likely send a cryptic
257error to the client.
Guido van Rossum72755611996-03-06 07:20:06 +0000258
Guido van Rossum391b4e61996-03-06 19:11:33 +0000259Assuming your script has no syntax errors, yet it does not work, you
260have no choice but to read the next section:
Guido van Rossum72755611996-03-06 07:20:06 +0000261
262
263Debugging CGI scripts
264---------------------
265
Guido van Rossum391b4e61996-03-06 19:11:33 +0000266First of all, check for trivial installation errors -- reading the
267section above on installing your CGI script carefully can save you a
268lot of time. If you wonder whether you have understood the
269installation procedure correctly, try installing a copy of this module
270file (cgi.py) as a CGI script. When invoked as a script, the file
271will dump its environment and the contents of the form in HTML form.
272Give it the right mode etc, and send it a request. If it's installed
273in the standard cgi-bin directory, it should be possible to send it a
274request by entering a URL into your browser of the form:
Guido van Rossum72755611996-03-06 07:20:06 +0000275
276 http://yourhostname/cgi-bin/cgi.py?name=Joe+Blow&addr=At+Home
277
Guido van Rossum391b4e61996-03-06 19:11:33 +0000278If this gives an error of type 404, the server cannot find the script
279-- perhaps you need to install it in a different directory. If it
280gives another error (e.g. 500), there's an installation problem that
281you should fix before trying to go any further. If you get a nicely
282formatted listing of the environment and form content (in this
283example, the fields should be listed as "addr" with value "At Home"
284and "name" with value "Joe Blow"), the cgi.py script has been
285installed correctly. If you follow the same procedure for your own
286script, you should now be able to debug it.
Guido van Rossum72755611996-03-06 07:20:06 +0000287
Guido van Rossum391b4e61996-03-06 19:11:33 +0000288The next step could be to call the cgi module's test() function from
289your script: replace its main code with the single statement
Guido van Rossum72755611996-03-06 07:20:06 +0000290
291 cgi.test()
292
Guido van Rossum391b4e61996-03-06 19:11:33 +0000293This should produce the same results as those gotten from installing
294the cgi.py file itself.
Guido van Rossum72755611996-03-06 07:20:06 +0000295
Guido van Rossum391b4e61996-03-06 19:11:33 +0000296When an ordinary Python script raises an unhandled exception
297(e.g. because of a typo in a module name, a file that can't be opened,
298etc.), the Python interpreter prints a nice traceback and exits.
299While the Python interpreter will still do this when your CGI script
300raises an exception, most likely the traceback will end up in one of
301the HTTP server's log file, or be discarded altogether.
Guido van Rossum72755611996-03-06 07:20:06 +0000302
Guido van Rossum391b4e61996-03-06 19:11:33 +0000303Fortunately, once you have managed to get your script to execute
304*some* code, it is easy to catch exceptions and cause a traceback to
305be printed. The test() function below in this module is an example.
306Here are the rules:
Guido van Rossum72755611996-03-06 07:20:06 +0000307
Guido van Rossum391b4e61996-03-06 19:11:33 +0000308 1. Import the traceback module (before entering the
309 try-except!)
Guido van Rossum72755611996-03-06 07:20:06 +0000310
Guido van Rossum391b4e61996-03-06 19:11:33 +0000311 2. Make sure you finish printing the headers and the blank
312 line early
Guido van Rossum72755611996-03-06 07:20:06 +0000313
314 3. Assign sys.stderr to sys.stdout
315
316 3. Wrap all remaining code in a try-except statement
317
318 4. In the except clause, call traceback.print_exc()
319
320For example:
321
322 import sys
323 import traceback
324 print "Content-type: text/html"
325 print
326 sys.stderr = sys.stdout
327 try:
328 ...your code here...
329 except:
330 print "\n\n<PRE>"
331 traceback.print_exc()
332
Guido van Rossum391b4e61996-03-06 19:11:33 +0000333Notes: The assignment to sys.stderr is needed because the traceback
334prints to sys.stderr. The print "\n\n<PRE>" statement is necessary to
335disable the word wrapping in HTML.
Guido van Rossum72755611996-03-06 07:20:06 +0000336
Guido van Rossum391b4e61996-03-06 19:11:33 +0000337If you suspect that there may be a problem in importing the traceback
338module, you can use an even more robust approach (which only uses
339built-in modules):
Guido van Rossum72755611996-03-06 07:20:06 +0000340
341 import sys
342 sys.stderr = sys.stdout
343 print "Content-type: text/plain"
344 print
345 ...your code here...
346
Guido van Rossum391b4e61996-03-06 19:11:33 +0000347This relies on the Python interpreter to print the traceback. The
348content type of the output is set to plain text, which disables all
349HTML processing. If your script works, the raw HTML will be displayed
350by your client. If it raises an exception, most likely after the
351first two lines have been printed, a traceback will be displayed.
352Because no HTML interpretation is going on, the traceback will
353readable.
Guido van Rossum72755611996-03-06 07:20:06 +0000354
Guido van Rossumc204c701996-09-05 19:07:11 +0000355When all else fails, you may want to insert calls to log() to your
356program or even to a copy of the cgi.py file. Note that this requires
357you to set cgi.logfile to the name of a world-writable file before the
358first call to log() is made!
359
Guido van Rossum72755611996-03-06 07:20:06 +0000360Good luck!
361
362
363Common problems and solutions
364-----------------------------
365
Guido van Rossum391b4e61996-03-06 19:11:33 +0000366- Most HTTP servers buffer the output from CGI scripts until the
367script is completed. This means that it is not possible to display a
368progress report on the client's display while the script is running.
Guido van Rossum72755611996-03-06 07:20:06 +0000369
370- Check the installation instructions above.
371
Guido van Rossum391b4e61996-03-06 19:11:33 +0000372- Check the HTTP server's log files. ("tail -f logfile" in a separate
Guido van Rossum72755611996-03-06 07:20:06 +0000373window may be useful!)
374
Guido van Rossum391b4e61996-03-06 19:11:33 +0000375- Always check a script for syntax errors first, by doing something
376like "python script.py".
Guido van Rossum72755611996-03-06 07:20:06 +0000377
378- When using any of the debugging techniques, don't forget to add
379"import sys" to the top of the script.
380
Guido van Rossum391b4e61996-03-06 19:11:33 +0000381- When invoking external programs, make sure they can be found.
382Usually, this means using absolute path names -- $PATH is usually not
383set to a very useful value in a CGI script.
Guido van Rossum72755611996-03-06 07:20:06 +0000384
Guido van Rossum391b4e61996-03-06 19:11:33 +0000385- When reading or writing external files, make sure they can be read
386or written by every user on the system.
Guido van Rossum72755611996-03-06 07:20:06 +0000387
Guido van Rossum391b4e61996-03-06 19:11:33 +0000388- Don't try to give a CGI script a set-uid mode. This doesn't work on
389most systems, and is a security liability as well.
Guido van Rossum72755611996-03-06 07:20:06 +0000390
391
392History
393-------
394
Guido van Rossum391b4e61996-03-06 19:11:33 +0000395Michael McLay started this module. Steve Majewski changed the
396interface to SvFormContentDict and FormContentDict. The multipart
397parsing was inspired by code submitted by Andreas Paepcke. Guido van
398Rossum rewrote, reformatted and documented the module and is currently
399responsible for its maintenance.
Guido van Rossum72755611996-03-06 07:20:06 +0000400
Guido van Rossum0147db01996-03-09 03:16:04 +0000401
402XXX The module is getting pretty heavy with all those docstrings.
403Perhaps there should be a slimmed version that doesn't contain all those
404backwards compatible and debugging classes and functions?
405
Guido van Rossum72755611996-03-06 07:20:06 +0000406"""
407
Guido van Rossum9e3f4291996-08-26 15:46:13 +0000408# " <== Emacs font-lock de-bogo-kludgificocity
409
Guido van Rossum16d5b111996-10-24 14:44:32 +0000410__version__ = "2.0"
Guido van Rossum0147db01996-03-09 03:16:04 +0000411
Guido van Rossum72755611996-03-06 07:20:06 +0000412
413# Imports
414# =======
415
416import string
Guido van Rossum72755611996-03-06 07:20:06 +0000417import sys
418import os
Guido van Rossum72755611996-03-06 07:20:06 +0000419
Guido van Rossumc204c701996-09-05 19:07:11 +0000420
421# Logging support
422# ===============
423
424logfile = "" # Filename to log to, if not empty
425logfp = None # File object to log to, if not None
426
427def initlog(*allargs):
428 """Write a log message, if there is a log file.
429
430 Even though this function is called initlog(), you should always
431 use log(); log is a variable that is set either to initlog
432 (initially), to dolog (once the log file has been opened), or to
433 nolog (when logging is disabled).
434
435 The first argument is a format string; the remaining arguments (if
436 any) are arguments to the % operator, so e.g.
437 log("%s: %s", "a", "b")
438 will write "a: b" to the log file, followed by a newline.
439
440 If the global logfp is not None, it should be a file object to
441 which log data is written.
442
443 If the global logfp is None, the global logfile may be a string
444 giving a filename to open, in append mode. This file should be
445 world writable!!! If the file can't be opened, logging is
446 silently disabled (since there is no safe place where we could
447 send an error message).
448
449 """
450 global logfp, log
451 if logfile and not logfp:
452 try:
453 logfp = open(logfile, "a")
454 except IOError:
455 pass
456 if not logfp:
457 log = nolog
458 else:
459 log = dolog
460 apply(log, allargs)
461
462def dolog(fmt, *args):
463 """Write a log message to the log file. See initlog() for docs."""
464 logfp.write(fmt%args + "\n")
465
466def nolog(*allargs):
467 """Dummy function, assigned to log when logging is disabled."""
468 pass
469
470log = initlog # The current logging function
471
472
Guido van Rossum72755611996-03-06 07:20:06 +0000473# Parsing functions
474# =================
475
Guido van Rossum773ab271996-07-23 03:46:24 +0000476def parse(fp=None, environ=os.environ, keep_blank_values=None):
477 """Parse a query in the environment or from a file (default stdin)
478
479 Arguments, all optional:
480
481 fp : file pointer; default: sys.stdin
482
483 environ : environment dictionary; default: os.environ
484
485 keep_blank_values: flag indicating whether blank values in
486 URL encoded forms should be treated as blank strings.
487 A true value inicates that blanks should be retained as
488 blank strings. The default false value indicates that
489 blank values are to be ignored and treated as if they were
490 not included.
491 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000492 if not fp:
493 fp = sys.stdin
494 if not environ.has_key('REQUEST_METHOD'):
495 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
496 if environ['REQUEST_METHOD'] == 'POST':
497 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
498 if ctype == 'multipart/form-data':
Guido van Rossum0147db01996-03-09 03:16:04 +0000499 return parse_multipart(fp, pdict)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000500 elif ctype == 'application/x-www-form-urlencoded':
501 clength = string.atoi(environ['CONTENT_LENGTH'])
502 qs = fp.read(clength)
Guido van Rossum1c9daa81995-09-18 21:52:37 +0000503 else:
Guido van Rossum0147db01996-03-09 03:16:04 +0000504 qs = '' # Unknown content-type
Guido van Rossumafb5e931996-08-08 18:42:12 +0000505 if environ.has_key('QUERY_STRING'):
506 if qs: qs = qs + '&'
507 qs = qs + environ['QUERY_STRING']
508 elif sys.argv[1:]:
509 if qs: qs = qs + '&'
510 qs = qs + sys.argv[1]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000511 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
512 elif environ.has_key('QUERY_STRING'):
513 qs = environ['QUERY_STRING']
514 else:
515 if sys.argv[1:]:
516 qs = sys.argv[1]
517 else:
518 qs = ""
519 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossum773ab271996-07-23 03:46:24 +0000520 return parse_qs(qs, keep_blank_values)
Guido van Rossume7808771995-08-07 20:12:09 +0000521
522
Guido van Rossum773ab271996-07-23 03:46:24 +0000523def parse_qs(qs, keep_blank_values=None):
524 """Parse a query given as a string argumen
525
526 Arguments:
527
528 qs : URL-encoded query string to be parsed
529
530 keep_blank_values: flag indicating whether blank values in
531 URL encoded queries should be treated as blank strings.
532 A true value inicates that blanks should be retained as
533 blank strings. The default false value indicates that
534 blank values are to be ignored and treated as if they were
535 not included.
536 """
Guido van Rossum0147db01996-03-09 03:16:04 +0000537 import urllib, regsub
Guido van Rossum7aee3841996-03-07 18:00:44 +0000538 name_value_pairs = string.splitfields(qs, '&')
539 dict = {}
540 for name_value in name_value_pairs:
541 nv = string.splitfields(name_value, '=')
542 if len(nv) != 2:
543 continue
544 name = nv[0]
545 value = urllib.unquote(regsub.gsub('+', ' ', nv[1]))
Guido van Rossum773ab271996-07-23 03:46:24 +0000546 if len(value) or keep_blank_values:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000547 if dict.has_key (name):
548 dict[name].append(value)
549 else:
550 dict[name] = [value]
551 return dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000552
553
Guido van Rossum0147db01996-03-09 03:16:04 +0000554def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000555 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000556
Guido van Rossum7aee3841996-03-07 18:00:44 +0000557 Arguments:
558 fp : input file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000559 pdict: dictionary containing other parameters of conten-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000560
Guido van Rossum0147db01996-03-09 03:16:04 +0000561 Returns a dictionary just like parse_qs(): keys are the field names, each
562 value is a list of values for that field. This is easy to use but not
563 much good if you are expecting megabytes to be uploaded -- in that case,
564 use the FieldStorage class instead which is much more flexible. Note
565 that content-type is the raw, unparsed contents of the content-type
566 header.
567
568 XXX This does not parse nested multipart parts -- use FieldStorage for
569 that.
570
571 XXX This should really be subsumed by FieldStorage altogether -- no
572 point in having two implementations of the same parsing algorithm.
Guido van Rossum72755611996-03-06 07:20:06 +0000573
Guido van Rossum7aee3841996-03-07 18:00:44 +0000574 """
575 import mimetools
576 if pdict.has_key('boundary'):
577 boundary = pdict['boundary']
578 else:
579 boundary = ""
580 nextpart = "--" + boundary
581 lastpart = "--" + boundary + "--"
582 partdict = {}
583 terminator = ""
584
585 while terminator != lastpart:
586 bytes = -1
587 data = None
588 if terminator:
589 # At start of next part. Read headers first.
590 headers = mimetools.Message(fp)
591 clength = headers.getheader('content-length')
592 if clength:
593 try:
594 bytes = string.atoi(clength)
595 except string.atoi_error:
596 pass
597 if bytes > 0:
598 data = fp.read(bytes)
599 else:
600 data = ""
601 # Read lines until end of part.
602 lines = []
603 while 1:
604 line = fp.readline()
605 if not line:
606 terminator = lastpart # End outer loop
607 break
608 if line[:2] == "--":
609 terminator = string.strip(line)
610 if terminator in (nextpart, lastpart):
611 break
Guido van Rossum7aee3841996-03-07 18:00:44 +0000612 lines.append(line)
613 # Done with part.
614 if data is None:
615 continue
616 if bytes < 0:
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000617 if lines:
618 # Strip final line terminator
619 line = lines[-1]
620 if line[-2:] == "\r\n":
621 line = line[:-2]
622 elif line[-1:] == "\n":
623 line = line[:-1]
624 lines[-1] = line
625 data = string.joinfields(lines, "")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000626 line = headers['content-disposition']
627 if not line:
628 continue
629 key, params = parse_header(line)
630 if key != 'form-data':
631 continue
632 if params.has_key('name'):
633 name = params['name']
Guido van Rossum72755611996-03-06 07:20:06 +0000634 else:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000635 continue
Guido van Rossum7aee3841996-03-07 18:00:44 +0000636 if partdict.has_key(name):
637 partdict[name].append(data)
638 else:
639 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000640
Guido van Rossum7aee3841996-03-07 18:00:44 +0000641 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000642
643
Guido van Rossum72755611996-03-06 07:20:06 +0000644def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000645 """Parse a Content-type like header.
646
647 Return the main content-type and a dictionary of options.
648
649 """
650 plist = map(string.strip, string.splitfields(line, ';'))
651 key = string.lower(plist[0])
652 del plist[0]
653 pdict = {}
654 for p in plist:
655 i = string.find(p, '=')
656 if i >= 0:
657 name = string.lower(string.strip(p[:i]))
658 value = string.strip(p[i+1:])
659 if len(value) >= 2 and value[0] == value[-1] == '"':
660 value = value[1:-1]
661 pdict[name] = value
662 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000663
664
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000665# Classes for field storage
666# =========================
667
668class MiniFieldStorage:
669
Guido van Rossum0147db01996-03-09 03:16:04 +0000670 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000671
Guido van Rossum7aee3841996-03-07 18:00:44 +0000672 # Dummy attributes
673 filename = None
674 list = None
675 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000676 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000677 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000678 disposition = None
679 disposition_options = {}
680 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000681
Guido van Rossum7aee3841996-03-07 18:00:44 +0000682 def __init__(self, name, value):
683 """Constructor from field name and value."""
684 from StringIO import StringIO
685 self.name = name
686 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000687 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000688
689 def __repr__(self):
690 """Return printable representation."""
691 return "MiniFieldStorage(%s, %s)" % (`self.name`, `self.value`)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000692
693
694class FieldStorage:
695
Guido van Rossum7aee3841996-03-07 18:00:44 +0000696 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000697
Guido van Rossum7aee3841996-03-07 18:00:44 +0000698 This class provides naming, typing, files stored on disk, and
699 more. At the top level, it is accessible like a dictionary, whose
700 keys are the field names. (Note: None can occur as a field name.)
701 The items are either a Python list (if there's multiple values) or
702 another FieldStorage or MiniFieldStorage object. If it's a single
703 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000704
Guido van Rossum7aee3841996-03-07 18:00:44 +0000705 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000706
Guido van Rossum7aee3841996-03-07 18:00:44 +0000707 filename: the filename, if specified; otherwise None; this is the
708 client side filename, *not* the file name on which it is
Guido van Rossum0147db01996-03-09 03:16:04 +0000709 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000710
Guido van Rossum7aee3841996-03-07 18:00:44 +0000711 value: the value as a *string*; for file uploads, this
712 transparently reads the file every time you request the value
713
714 file: the file(-like) object from which you can read the data;
715 None if the data is stored a simple string
716
717 type: the content-type, or None if not specified
718
719 type_options: dictionary of options specified on the content-type
720 line
721
722 disposition: content-disposition, or None if not specified
723
724 disposition_options: dictionary of corresponding options
725
726 headers: a dictionary(-like) object (sometimes rfc822.Message or a
727 subclass thereof) containing *all* headers
728
729 The class is subclassable, mostly for the purpose of overriding
730 the make_file() method, which is called internally to come up with
731 a file open for reading and writing. This makes it possible to
732 override the default choice of storing all files in a temporary
733 directory and unlinking them as soon as they have been opened.
734
735 """
736
Guido van Rossum773ab271996-07-23 03:46:24 +0000737 def __init__(self, fp=None, headers=None, outerboundary="",
738 environ=os.environ, keep_blank_values=None):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000739 """Constructor. Read multipart/* until last part.
740
741 Arguments, all optional:
742
743 fp : file pointer; default: sys.stdin
744
745 headers : header dictionary-like object; default:
746 taken from environ as per CGI spec
747
Guido van Rossum773ab271996-07-23 03:46:24 +0000748 outerboundary : terminating multipart boundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000749 (for internal use only)
750
Guido van Rossum773ab271996-07-23 03:46:24 +0000751 environ : environment dictionary; default: os.environ
752
753 keep_blank_values: flag indicating whether blank values in
754 URL encoded forms should be treated as blank strings.
755 A true value inicates that blanks should be retained as
756 blank strings. The default false value indicates that
757 blank values are to be ignored and treated as if they were
758 not included.
759
Guido van Rossum7aee3841996-03-07 18:00:44 +0000760 """
761 method = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000762 self.keep_blank_values = keep_blank_values
Guido van Rossum7aee3841996-03-07 18:00:44 +0000763 if environ.has_key('REQUEST_METHOD'):
764 method = string.upper(environ['REQUEST_METHOD'])
765 if not fp and method == 'GET':
766 qs = None
767 if environ.has_key('QUERY_STRING'):
768 qs = environ['QUERY_STRING']
769 from StringIO import StringIO
770 fp = StringIO(qs or "")
771 if headers is None:
772 headers = {'content-type':
773 "application/x-www-form-urlencoded"}
774 if headers is None:
775 headers = {}
776 if environ.has_key('CONTENT_TYPE'):
777 headers['content-type'] = environ['CONTENT_TYPE']
778 if environ.has_key('CONTENT_LENGTH'):
779 headers['content-length'] = environ['CONTENT_LENGTH']
780 self.fp = fp or sys.stdin
781 self.headers = headers
782 self.outerboundary = outerboundary
783
784 # Process content-disposition header
785 cdisp, pdict = "", {}
786 if self.headers.has_key('content-disposition'):
787 cdisp, pdict = parse_header(self.headers['content-disposition'])
788 self.disposition = cdisp
789 self.disposition_options = pdict
790 self.name = None
791 if pdict.has_key('name'):
792 self.name = pdict['name']
793 self.filename = None
794 if pdict.has_key('filename'):
795 self.filename = pdict['filename']
796
797 # Process content-type header
798 ctype, pdict = "text/plain", {}
799 if self.headers.has_key('content-type'):
800 ctype, pdict = parse_header(self.headers['content-type'])
801 self.type = ctype
802 self.type_options = pdict
803 self.innerboundary = ""
804 if pdict.has_key('boundary'):
805 self.innerboundary = pdict['boundary']
806 clen = -1
807 if self.headers.has_key('content-length'):
808 try:
809 clen = string.atoi(self.headers['content-length'])
810 except:
811 pass
812 self.length = clen
813
814 self.list = self.file = None
815 self.done = 0
816 self.lines = []
817 if ctype == 'application/x-www-form-urlencoded':
818 self.read_urlencoded()
819 elif ctype[:10] == 'multipart/':
820 self.read_multi()
821 else:
822 self.read_single()
823
824 def __repr__(self):
825 """Return a printable representation."""
826 return "FieldStorage(%s, %s, %s)" % (
827 `self.name`, `self.filename`, `self.value`)
828
829 def __getattr__(self, name):
830 if name != 'value':
831 raise AttributeError, name
832 if self.file:
833 self.file.seek(0)
834 value = self.file.read()
835 self.file.seek(0)
836 elif self.list is not None:
837 value = self.list
838 else:
839 value = None
840 return value
841
842 def __getitem__(self, key):
843 """Dictionary style indexing."""
844 if self.list is None:
845 raise TypeError, "not indexable"
846 found = []
847 for item in self.list:
848 if item.name == key: found.append(item)
849 if not found:
850 raise KeyError, key
Guido van Rossum0147db01996-03-09 03:16:04 +0000851 if len(found) == 1:
852 return found[0]
853 else:
854 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000855
856 def keys(self):
857 """Dictionary style keys() method."""
858 if self.list is None:
859 raise TypeError, "not indexable"
860 keys = []
861 for item in self.list:
862 if item.name not in keys: keys.append(item.name)
863 return keys
864
Guido van Rossum0147db01996-03-09 03:16:04 +0000865 def has_key(self, key):
866 """Dictionary style has_key() method."""
867 if self.list is None:
868 raise TypeError, "not indexable"
869 for item in self.list:
870 if item.name == key: return 1
871 return 0
872
Guido van Rossum7aee3841996-03-07 18:00:44 +0000873 def read_urlencoded(self):
874 """Internal: read data in query string format."""
875 qs = self.fp.read(self.length)
Guido van Rossum773ab271996-07-23 03:46:24 +0000876 dict = parse_qs(qs, self.keep_blank_values)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000877 self.list = []
878 for key, valuelist in dict.items():
879 for value in valuelist:
880 self.list.append(MiniFieldStorage(key, value))
881 self.skip_lines()
882
883 def read_multi(self):
884 """Internal: read a part that is itself multipart."""
885 import rfc822
886 self.list = []
887 part = self.__class__(self.fp, {}, self.innerboundary)
888 # Throw first part away
889 while not part.done:
890 headers = rfc822.Message(self.fp)
891 part = self.__class__(self.fp, headers, self.innerboundary)
892 self.list.append(part)
893 self.skip_lines()
894
895 def read_single(self):
896 """Internal: read an atomic part."""
897 if self.length >= 0:
898 self.read_binary()
899 self.skip_lines()
900 else:
901 self.read_lines()
902 self.file.seek(0)
903
904 bufsize = 8*1024 # I/O buffering size for copy to file
905
906 def read_binary(self):
907 """Internal: read binary data."""
908 self.file = self.make_file('b')
909 todo = self.length
910 if todo >= 0:
911 while todo > 0:
912 data = self.fp.read(min(todo, self.bufsize))
913 if not data:
914 self.done = -1
915 break
916 self.file.write(data)
917 todo = todo - len(data)
918
919 def read_lines(self):
920 """Internal: read lines until EOF or outerboundary."""
921 self.file = self.make_file('')
922 if self.outerboundary:
923 self.read_lines_to_outerboundary()
924 else:
925 self.read_lines_to_eof()
926
927 def read_lines_to_eof(self):
928 """Internal: read lines until EOF."""
929 while 1:
930 line = self.fp.readline()
931 if not line:
932 self.done = -1
933 break
934 self.lines.append(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000935 self.file.write(line)
936
937 def read_lines_to_outerboundary(self):
938 """Internal: read lines until outerboundary."""
939 next = "--" + self.outerboundary
940 last = next + "--"
941 delim = ""
942 while 1:
943 line = self.fp.readline()
944 if not line:
945 self.done = -1
946 break
947 self.lines.append(line)
948 if line[:2] == "--":
949 strippedline = string.strip(line)
950 if strippedline == next:
951 break
952 if strippedline == last:
953 self.done = 1
954 break
Guido van Rossume5e46e01996-09-05 19:03:36 +0000955 odelim = delim
Guido van Rossum7aee3841996-03-07 18:00:44 +0000956 if line[-2:] == "\r\n":
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000957 delim = "\r\n"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000958 line = line[:-2]
959 elif line[-1] == "\n":
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000960 delim = "\n"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000961 line = line[:-1]
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000962 else:
963 delim = ""
Guido van Rossume5e46e01996-09-05 19:03:36 +0000964 self.file.write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000965
966 def skip_lines(self):
967 """Internal: skip lines until outer boundary if defined."""
968 if not self.outerboundary or self.done:
969 return
970 next = "--" + self.outerboundary
971 last = next + "--"
972 while 1:
973 line = self.fp.readline()
974 if not line:
975 self.done = -1
976 break
977 self.lines.append(line)
978 if line[:2] == "--":
979 strippedline = string.strip(line)
980 if strippedline == next:
981 break
982 if strippedline == last:
983 self.done = 1
984 break
985
986 def make_file(self, binary):
987 """Overridable: return a readable & writable file.
988
989 The file will be used as follows:
990 - data is written to it
991 - seek(0)
992 - data is read from it
993
994 The 'binary' argument is 'b' if the file should be created in
995 binary mode (on non-Unix systems), '' otherwise.
996
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000997 This version opens a temporary file for reading and writing,
998 and immediately deletes (unlinks) it. The trick (on Unix!) is
999 that the file can still be used, but it can't be opened by
1000 another process, and it will automatically be deleted when it
1001 is closed or when the current process terminates.
1002
1003 If you want a more permanent file, you derive a class which
1004 overrides this method. If you want a visible temporary file
1005 that is nevertheless automatically deleted when the script
1006 terminates, try defining a __del__ method in a derived class
1007 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +00001008
1009 """
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001010 import tempfile
1011 tfn = tempfile.mktemp()
1012 f = open(tfn, "w%s+" % binary)
1013 os.unlink(tfn)
1014 return f
Guido van Rossum243ddcd1996-03-07 06:33:07 +00001015
1016
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001017# Backwards Compatibility Classes
1018# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +00001019
1020class FormContentDict:
Guido van Rossum7aee3841996-03-07 18:00:44 +00001021 """Basic (multiple values per field) form content as dictionary.
Guido van Rossum72755611996-03-06 07:20:06 +00001022
Guido van Rossum7aee3841996-03-07 18:00:44 +00001023 form = FormContentDict()
1024
1025 form[key] -> [value, value, ...]
1026 form.has_key(key) -> Boolean
1027 form.keys() -> [key, key, ...]
1028 form.values() -> [[val, val, ...], [val, val, ...], ...]
1029 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
1030 form.dict == {key: [val, val, ...], ...}
1031
1032 """
Guido van Rossum773ab271996-07-23 03:46:24 +00001033 def __init__(self, environ=os.environ):
Guido van Rossumafb5e931996-08-08 18:42:12 +00001034 self.dict = parse(environ=environ)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001035 self.query_string = environ['QUERY_STRING']
1036 def __getitem__(self,key):
1037 return self.dict[key]
1038 def keys(self):
1039 return self.dict.keys()
1040 def has_key(self, key):
1041 return self.dict.has_key(key)
1042 def values(self):
1043 return self.dict.values()
1044 def items(self):
1045 return self.dict.items()
1046 def __len__( self ):
1047 return len(self.dict)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001048
1049
Guido van Rossum9a22de11995-01-12 12:29:47 +00001050class SvFormContentDict(FormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001051 """Strict single-value expecting form content as dictionary.
1052
1053 IF you only expect a single value for each field, then form[key]
1054 will return that single value. It will raise an IndexError if
1055 that expectation is not true. IF you expect a field to have
1056 possible multiple values, than you can use form.getlist(key) to
1057 get all of the values. values() and items() are a compromise:
1058 they return single strings where there is a single value, and
1059 lists of strings otherwise.
1060
1061 """
1062 def __getitem__(self, key):
1063 if len(self.dict[key]) > 1:
1064 raise IndexError, 'expecting a single value'
1065 return self.dict[key][0]
1066 def getlist(self, key):
1067 return self.dict[key]
1068 def values(self):
1069 lis = []
1070 for each in self.dict.values():
1071 if len( each ) == 1 :
1072 lis.append(each[0])
1073 else: lis.append(each)
1074 return lis
1075 def items(self):
1076 lis = []
1077 for key,value in self.dict.items():
1078 if len(value) == 1 :
1079 lis.append((key, value[0]))
1080 else: lis.append((key, value))
1081 return lis
Guido van Rossum9a22de11995-01-12 12:29:47 +00001082
1083
Guido van Rossum9a22de11995-01-12 12:29:47 +00001084class InterpFormContentDict(SvFormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001085 """This class is present for backwards compatibility only."""
1086 def __getitem__( self, key ):
1087 v = SvFormContentDict.__getitem__( self, key )
1088 if v[0] in string.digits+'+-.' :
1089 try: return string.atoi( v )
1090 except ValueError:
1091 try: return string.atof( v )
1092 except ValueError: pass
1093 return string.strip(v)
1094 def values( self ):
1095 lis = []
1096 for key in self.keys():
1097 try:
1098 lis.append( self[key] )
1099 except IndexError:
1100 lis.append( self.dict[key] )
1101 return lis
1102 def items( self ):
1103 lis = []
1104 for key in self.keys():
1105 try:
1106 lis.append( (key, self[key]) )
1107 except IndexError:
1108 lis.append( (key, self.dict[key]) )
1109 return lis
Guido van Rossum9a22de11995-01-12 12:29:47 +00001110
1111
Guido van Rossum9a22de11995-01-12 12:29:47 +00001112class FormContent(FormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001113 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +00001114 def values(self, key):
1115 if self.dict.has_key(key) :return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +00001116 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001117 def indexed_value(self, key, location):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001118 if self.dict.has_key(key):
1119 if len (self.dict[key]) > location:
1120 return self.dict[key][location]
1121 else: return None
1122 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001123 def value(self, key):
1124 if self.dict.has_key(key): return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +00001125 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001126 def length(self, key):
1127 return len(self.dict[key])
1128 def stripped(self, key):
1129 if self.dict.has_key(key): return string.strip(self.dict[key][0])
Guido van Rossum7aee3841996-03-07 18:00:44 +00001130 else: return None
1131 def pars(self):
1132 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +00001133
1134
Guido van Rossum72755611996-03-06 07:20:06 +00001135# Test/debug code
1136# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +00001137
Guido van Rossum773ab271996-07-23 03:46:24 +00001138def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001139 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +00001140
Guido van Rossum7aee3841996-03-07 18:00:44 +00001141 Write minimal HTTP headers and dump all information provided to
1142 the script in HTML form.
1143
1144 """
1145 import traceback
1146 print "Content-type: text/html"
1147 print
1148 sys.stderr = sys.stdout
1149 try:
Guido van Rossum0147db01996-03-09 03:16:04 +00001150 form = FieldStorage() # Replace with other classes to test those
1151 print_form(form)
Guido van Rossum773ab271996-07-23 03:46:24 +00001152 print_environ(environ)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001153 print_directory()
Guido van Rossuma8738a51996-03-14 21:30:28 +00001154 print_arguments()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001155 print_environ_usage()
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001156 def f():
1157 exec "testing print_exception() -- <I>italics?</I>"
1158 def g(f=f):
1159 f()
1160 print "<H3>What follows is a test, not an actual exception:</H3>"
1161 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001162 except:
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001163 print_exception()
1164
1165def print_exception(type=None, value=None, tb=None, limit=None):
1166 if type is None:
1167 type, value, tb = sys.exc_type, sys.exc_value, sys.exc_traceback
1168 import traceback
1169 print
1170 print "<H3>Traceback (innermost last):</H3>"
1171 list = traceback.format_tb(tb, limit) + \
1172 traceback.format_exception_only(type, value)
1173 print "<PRE>%s<B>%s</B></PRE>" % (
1174 escape(string.join(list[:-1], "")),
1175 escape(list[-1]),
1176 )
Guido van Rossum9a22de11995-01-12 12:29:47 +00001177
Guido van Rossum773ab271996-07-23 03:46:24 +00001178def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001179 """Dump the shell environment as HTML."""
1180 keys = environ.keys()
1181 keys.sort()
1182 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001183 print "<H3>Shell Environment:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +00001184 print "<DL>"
1185 for key in keys:
1186 print "<DT>", escape(key), "<DD>", escape(environ[key])
1187 print "</DL>"
1188 print
Guido van Rossum72755611996-03-06 07:20:06 +00001189
1190def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001191 """Dump the contents of a form as HTML."""
1192 keys = form.keys()
1193 keys.sort()
1194 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001195 print "<H3>Form Contents:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +00001196 print "<DL>"
1197 for key in keys:
1198 print "<DT>" + escape(key) + ":",
1199 value = form[key]
1200 print "<i>" + escape(`type(value)`) + "</i>"
1201 print "<DD>" + escape(`value`)
1202 print "</DL>"
1203 print
1204
1205def print_directory():
1206 """Dump the current directory as HTML."""
1207 print
1208 print "<H3>Current Working Directory:</H3>"
1209 try:
1210 pwd = os.getcwd()
1211 except os.error, msg:
1212 print "os.error:", escape(str(msg))
1213 else:
1214 print escape(pwd)
1215 print
Guido van Rossum9a22de11995-01-12 12:29:47 +00001216
Guido van Rossuma8738a51996-03-14 21:30:28 +00001217def print_arguments():
1218 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001219 print "<H3>Command Line Arguments:</H3>"
Guido van Rossuma8738a51996-03-14 21:30:28 +00001220 print
1221 print sys.argv
1222 print
1223
Guido van Rossum9a22de11995-01-12 12:29:47 +00001224def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +00001225 """Dump a list of environment variables used by CGI as HTML."""
1226 print """
Guido van Rossum72755611996-03-06 07:20:06 +00001227<H3>These environment variables could have been set:</H3>
1228<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001229<LI>AUTH_TYPE
1230<LI>CONTENT_LENGTH
1231<LI>CONTENT_TYPE
1232<LI>DATE_GMT
1233<LI>DATE_LOCAL
1234<LI>DOCUMENT_NAME
1235<LI>DOCUMENT_ROOT
1236<LI>DOCUMENT_URI
1237<LI>GATEWAY_INTERFACE
1238<LI>LAST_MODIFIED
1239<LI>PATH
1240<LI>PATH_INFO
1241<LI>PATH_TRANSLATED
1242<LI>QUERY_STRING
1243<LI>REMOTE_ADDR
1244<LI>REMOTE_HOST
1245<LI>REMOTE_IDENT
1246<LI>REMOTE_USER
1247<LI>REQUEST_METHOD
1248<LI>SCRIPT_NAME
1249<LI>SERVER_NAME
1250<LI>SERVER_PORT
1251<LI>SERVER_PROTOCOL
1252<LI>SERVER_ROOT
1253<LI>SERVER_SOFTWARE
1254</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001255In addition, HTTP headers sent by the server may be passed in the
1256environment as well. Here are some common variable names:
1257<UL>
1258<LI>HTTP_ACCEPT
1259<LI>HTTP_CONNECTION
1260<LI>HTTP_HOST
1261<LI>HTTP_PRAGMA
1262<LI>HTTP_REFERER
1263<LI>HTTP_USER_AGENT
1264</UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001265"""
1266
Guido van Rossum9a22de11995-01-12 12:29:47 +00001267
Guido van Rossum72755611996-03-06 07:20:06 +00001268# Utilities
1269# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001270
Guido van Rossum72755611996-03-06 07:20:06 +00001271def escape(s):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001272 """Replace special characters '&', '<' and '>' by SGML entities."""
Guido van Rossum0147db01996-03-09 03:16:04 +00001273 import regsub
Guido van Rossum7aee3841996-03-07 18:00:44 +00001274 s = regsub.gsub("&", "&amp;", s) # Must be done first!
1275 s = regsub.gsub("<", "&lt;", s)
1276 s = regsub.gsub(">", "&gt;", s)
1277 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001278
Guido van Rossum9a22de11995-01-12 12:29:47 +00001279
Guido van Rossum72755611996-03-06 07:20:06 +00001280# Invoke mainline
1281# ===============
1282
1283# Call test() when this file is run as a script (not imported as a module)
1284if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001285 test()