blob: 8bc4177bc229e3ec3cdefe0c6f564f75c1bc57f5 [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
139supported for backward compatibility. New applications should use the
Guido van Rossum7aee3841996-03-07 18:00:44 +0000140
Guido van Rossum0147db01996-03-09 03:16:04 +0000141SvFormContentDict: single value form content as dictionary; assumes each
142field name occurs in the form only once.
Guido van Rossum72755611996-03-06 07:20:06 +0000143
Guido van Rossum391b4e61996-03-06 19:11:33 +0000144FormContentDict: multiple value form content as dictionary (the form
145items are lists of values). Useful if your form contains multiple
146fields with the same name.
Guido van Rossum72755611996-03-06 07:20:06 +0000147
Guido van Rossum391b4e61996-03-06 19:11:33 +0000148Other classes (FormContent, InterpFormContentDict) are present for
Guido van Rossum0147db01996-03-09 03:16:04 +0000149backwards compatibility with really old applications only. If you still
150use these and would be inconvenienced when they disappeared from a next
151version of this module, drop me a note.
Guido van Rossum72755611996-03-06 07:20:06 +0000152
153
Guido van Rossum0147db01996-03-09 03:16:04 +0000154Functions
155---------
Guido van Rossum72755611996-03-06 07:20:06 +0000156
Guido van Rossum391b4e61996-03-06 19:11:33 +0000157These are useful if you want more control, or if you want to employ
158some of the algorithms implemented in this module in other
159circumstances.
Guido van Rossum72755611996-03-06 07:20:06 +0000160
Guido van Rossum0147db01996-03-09 03:16:04 +0000161parse(fp): parse a form into a Python dictionary.
Guido van Rossum72755611996-03-06 07:20:06 +0000162
Guido van Rossum0147db01996-03-09 03:16:04 +0000163parse_qs(qs): parse a query string (data of type
164application/x-www-form-urlencoded).
Guido van Rossum72755611996-03-06 07:20:06 +0000165
Guido van Rossum0147db01996-03-09 03:16:04 +0000166parse_multipart(fp, pdict): parse input of type multipart/form-data (for
Guido van Rossum391b4e61996-03-06 19:11:33 +0000167file uploads).
Guido van Rossum72755611996-03-06 07:20:06 +0000168
Guido van Rossum391b4e61996-03-06 19:11:33 +0000169parse_header(string): parse a header like Content-type into a main
170value and a dictionary of parameters.
Guido van Rossum72755611996-03-06 07:20:06 +0000171
172test(): complete test program.
173
174print_environ(): format the shell environment in HTML.
175
176print_form(form): format a form in HTML.
177
Guido van Rossum391b4e61996-03-06 19:11:33 +0000178print_environ_usage(): print a list of useful environment variables in
179HTML.
Guido van Rossum72755611996-03-06 07:20:06 +0000180
Guido van Rossum391b4e61996-03-06 19:11:33 +0000181escape(): convert the characters "&", "<" and ">" to HTML-safe
182sequences. Use this if you need to display text that might contain
183such characters in HTML. To translate URLs for inclusion in the HREF
184attribute of an <A> tag, use urllib.quote().
Guido van Rossum72755611996-03-06 07:20:06 +0000185
Guido van Rossumc204c701996-09-05 19:07:11 +0000186log(fmt, ...): write a line to a log file; see docs for initlog().
187
Guido van Rossum72755611996-03-06 07:20:06 +0000188
189Caring about security
190---------------------
191
Guido van Rossum391b4e61996-03-06 19:11:33 +0000192There's one important rule: if you invoke an external program (e.g.
193via the os.system() or os.popen() functions), make very sure you don't
194pass arbitrary strings received from the client to the shell. This is
195a well-known security hole whereby clever hackers anywhere on the web
196can exploit a gullible CGI script to invoke arbitrary shell commands.
197Even parts of the URL or field names cannot be trusted, since the
198request doesn't have to come from your form!
Guido van Rossum72755611996-03-06 07:20:06 +0000199
Guido van Rossum391b4e61996-03-06 19:11:33 +0000200To be on the safe side, if you must pass a string gotten from a form
201to a shell command, you should make sure the string contains only
202alphanumeric characters, dashes, underscores, and periods.
Guido van Rossum72755611996-03-06 07:20:06 +0000203
204
205Installing your CGI script on a Unix system
206-------------------------------------------
207
Guido van Rossum391b4e61996-03-06 19:11:33 +0000208Read the documentation for your HTTP server and check with your local
209system administrator to find the directory where CGI scripts should be
Guido van Rossum72755611996-03-06 07:20:06 +0000210installed; usually this is in a directory cgi-bin in the server tree.
211
Guido van Rossum391b4e61996-03-06 19:11:33 +0000212Make sure that your script is readable and executable by "others"; the
213Unix file mode should be 755 (use "chmod 755 filename"). Make sure
214that the first line of the script contains "#!" starting in column 1
215followed by the pathname of the Python interpreter, for instance:
Guido van Rossum72755611996-03-06 07:20:06 +0000216
217 #!/usr/local/bin/python
218
Guido van Rossum391b4e61996-03-06 19:11:33 +0000219Make sure the Python interpreter exists and is executable by "others".
Guido van Rossum72755611996-03-06 07:20:06 +0000220
Guido van Rossum391b4e61996-03-06 19:11:33 +0000221Make sure that any files your script needs to read or write are
222readable or writable, respectively, by "others" -- their mode should
223be 644 for readable and 666 for writable. This is because, for
224security reasons, the HTTP server executes your script as user
225"nobody", without any special privileges. It can only read (write,
226execute) files that everybody can read (write, execute). The current
227directory at execution time is also different (it is usually the
228server's cgi-bin directory) and the set of environment variables is
229also different from what you get at login. in particular, don't count
230on the shell's search path for executables ($PATH) or the Python
231module search path ($PYTHONPATH) to be set to anything interesting.
Guido van Rossum72755611996-03-06 07:20:06 +0000232
Guido van Rossum391b4e61996-03-06 19:11:33 +0000233If you need to load modules from a directory which is not on Python's
234default module search path, you can change the path in your script,
235before importing other modules, e.g.:
Guido van Rossum72755611996-03-06 07:20:06 +0000236
237 import sys
238 sys.path.insert(0, "/usr/home/joe/lib/python")
239 sys.path.insert(0, "/usr/local/lib/python")
240
241(This way, the directory inserted last will be searched first!)
242
Guido van Rossum391b4e61996-03-06 19:11:33 +0000243Instructions for non-Unix systems will vary; check your HTTP server's
Guido van Rossum72755611996-03-06 07:20:06 +0000244documentation (it will usually have a section on CGI scripts).
245
246
247Testing your CGI script
248-----------------------
249
Guido van Rossum391b4e61996-03-06 19:11:33 +0000250Unfortunately, a CGI script will generally not run when you try it
251from the command line, and a script that works perfectly from the
252command line may fail mysteriously when run from the server. There's
253one reason why you should still test your script from the command
254line: if it contains a syntax error, the python interpreter won't
255execute it at all, and the HTTP server will most likely send a cryptic
256error to the client.
Guido van Rossum72755611996-03-06 07:20:06 +0000257
Guido van Rossum391b4e61996-03-06 19:11:33 +0000258Assuming your script has no syntax errors, yet it does not work, you
259have no choice but to read the next section:
Guido van Rossum72755611996-03-06 07:20:06 +0000260
261
262Debugging CGI scripts
263---------------------
264
Guido van Rossum391b4e61996-03-06 19:11:33 +0000265First of all, check for trivial installation errors -- reading the
266section above on installing your CGI script carefully can save you a
267lot of time. If you wonder whether you have understood the
268installation procedure correctly, try installing a copy of this module
269file (cgi.py) as a CGI script. When invoked as a script, the file
270will dump its environment and the contents of the form in HTML form.
271Give it the right mode etc, and send it a request. If it's installed
272in the standard cgi-bin directory, it should be possible to send it a
273request by entering a URL into your browser of the form:
Guido van Rossum72755611996-03-06 07:20:06 +0000274
275 http://yourhostname/cgi-bin/cgi.py?name=Joe+Blow&addr=At+Home
276
Guido van Rossum391b4e61996-03-06 19:11:33 +0000277If this gives an error of type 404, the server cannot find the script
278-- perhaps you need to install it in a different directory. If it
279gives another error (e.g. 500), there's an installation problem that
280you should fix before trying to go any further. If you get a nicely
281formatted listing of the environment and form content (in this
282example, the fields should be listed as "addr" with value "At Home"
283and "name" with value "Joe Blow"), the cgi.py script has been
284installed correctly. If you follow the same procedure for your own
285script, you should now be able to debug it.
Guido van Rossum72755611996-03-06 07:20:06 +0000286
Guido van Rossum391b4e61996-03-06 19:11:33 +0000287The next step could be to call the cgi module's test() function from
288your script: replace its main code with the single statement
Guido van Rossum72755611996-03-06 07:20:06 +0000289
290 cgi.test()
291
Guido van Rossum391b4e61996-03-06 19:11:33 +0000292This should produce the same results as those gotten from installing
293the cgi.py file itself.
Guido van Rossum72755611996-03-06 07:20:06 +0000294
Guido van Rossum391b4e61996-03-06 19:11:33 +0000295When an ordinary Python script raises an unhandled exception
296(e.g. because of a typo in a module name, a file that can't be opened,
297etc.), the Python interpreter prints a nice traceback and exits.
298While the Python interpreter will still do this when your CGI script
299raises an exception, most likely the traceback will end up in one of
300the HTTP server's log file, or be discarded altogether.
Guido van Rossum72755611996-03-06 07:20:06 +0000301
Guido van Rossum391b4e61996-03-06 19:11:33 +0000302Fortunately, once you have managed to get your script to execute
303*some* code, it is easy to catch exceptions and cause a traceback to
304be printed. The test() function below in this module is an example.
305Here are the rules:
Guido van Rossum72755611996-03-06 07:20:06 +0000306
Guido van Rossum391b4e61996-03-06 19:11:33 +0000307 1. Import the traceback module (before entering the
308 try-except!)
Guido van Rossum72755611996-03-06 07:20:06 +0000309
Guido van Rossum391b4e61996-03-06 19:11:33 +0000310 2. Make sure you finish printing the headers and the blank
311 line early
Guido van Rossum72755611996-03-06 07:20:06 +0000312
313 3. Assign sys.stderr to sys.stdout
314
315 3. Wrap all remaining code in a try-except statement
316
317 4. In the except clause, call traceback.print_exc()
318
319For example:
320
321 import sys
322 import traceback
323 print "Content-type: text/html"
324 print
325 sys.stderr = sys.stdout
326 try:
327 ...your code here...
328 except:
329 print "\n\n<PRE>"
330 traceback.print_exc()
331
Guido van Rossum391b4e61996-03-06 19:11:33 +0000332Notes: The assignment to sys.stderr is needed because the traceback
333prints to sys.stderr. The print "\n\n<PRE>" statement is necessary to
334disable the word wrapping in HTML.
Guido van Rossum72755611996-03-06 07:20:06 +0000335
Guido van Rossum391b4e61996-03-06 19:11:33 +0000336If you suspect that there may be a problem in importing the traceback
337module, you can use an even more robust approach (which only uses
338built-in modules):
Guido van Rossum72755611996-03-06 07:20:06 +0000339
340 import sys
341 sys.stderr = sys.stdout
342 print "Content-type: text/plain"
343 print
344 ...your code here...
345
Guido van Rossum391b4e61996-03-06 19:11:33 +0000346This relies on the Python interpreter to print the traceback. The
347content type of the output is set to plain text, which disables all
348HTML processing. If your script works, the raw HTML will be displayed
349by your client. If it raises an exception, most likely after the
350first two lines have been printed, a traceback will be displayed.
351Because no HTML interpretation is going on, the traceback will
352readable.
Guido van Rossum72755611996-03-06 07:20:06 +0000353
Guido van Rossumc204c701996-09-05 19:07:11 +0000354When all else fails, you may want to insert calls to log() to your
355program or even to a copy of the cgi.py file. Note that this requires
356you to set cgi.logfile to the name of a world-writable file before the
357first call to log() is made!
358
Guido van Rossum72755611996-03-06 07:20:06 +0000359Good luck!
360
361
362Common problems and solutions
363-----------------------------
364
Guido van Rossum391b4e61996-03-06 19:11:33 +0000365- Most HTTP servers buffer the output from CGI scripts until the
366script is completed. This means that it is not possible to display a
367progress report on the client's display while the script is running.
Guido van Rossum72755611996-03-06 07:20:06 +0000368
369- Check the installation instructions above.
370
Guido van Rossum391b4e61996-03-06 19:11:33 +0000371- Check the HTTP server's log files. ("tail -f logfile" in a separate
Guido van Rossum72755611996-03-06 07:20:06 +0000372window may be useful!)
373
Guido van Rossum391b4e61996-03-06 19:11:33 +0000374- Always check a script for syntax errors first, by doing something
375like "python script.py".
Guido van Rossum72755611996-03-06 07:20:06 +0000376
377- When using any of the debugging techniques, don't forget to add
378"import sys" to the top of the script.
379
Guido van Rossum391b4e61996-03-06 19:11:33 +0000380- When invoking external programs, make sure they can be found.
381Usually, this means using absolute path names -- $PATH is usually not
382set to a very useful value in a CGI script.
Guido van Rossum72755611996-03-06 07:20:06 +0000383
Guido van Rossum391b4e61996-03-06 19:11:33 +0000384- When reading or writing external files, make sure they can be read
385or written by every user on the system.
Guido van Rossum72755611996-03-06 07:20:06 +0000386
Guido van Rossum391b4e61996-03-06 19:11:33 +0000387- Don't try to give a CGI script a set-uid mode. This doesn't work on
388most systems, and is a security liability as well.
Guido van Rossum72755611996-03-06 07:20:06 +0000389
390
391History
392-------
393
Guido van Rossum391b4e61996-03-06 19:11:33 +0000394Michael McLay started this module. Steve Majewski changed the
395interface to SvFormContentDict and FormContentDict. The multipart
396parsing was inspired by code submitted by Andreas Paepcke. Guido van
397Rossum rewrote, reformatted and documented the module and is currently
398responsible for its maintenance.
Guido van Rossum72755611996-03-06 07:20:06 +0000399
Guido van Rossum0147db01996-03-09 03:16:04 +0000400
401XXX The module is getting pretty heavy with all those docstrings.
402Perhaps there should be a slimmed version that doesn't contain all those
403backwards compatible and debugging classes and functions?
404
Guido van Rossum72755611996-03-06 07:20:06 +0000405"""
406
Guido van Rossum9e3f4291996-08-26 15:46:13 +0000407# " <== Emacs font-lock de-bogo-kludgificocity
408
Guido van Rossume5e46e01996-09-05 19:03:36 +0000409__version__ = "2.0b4"
Guido van Rossum0147db01996-03-09 03:16:04 +0000410
Guido van Rossum72755611996-03-06 07:20:06 +0000411
412# Imports
413# =======
414
415import string
Guido van Rossum72755611996-03-06 07:20:06 +0000416import sys
417import os
Guido van Rossum72755611996-03-06 07:20:06 +0000418
Guido van Rossumc204c701996-09-05 19:07:11 +0000419
420# Logging support
421# ===============
422
423logfile = "" # Filename to log to, if not empty
424logfp = None # File object to log to, if not None
425
426def initlog(*allargs):
427 """Write a log message, if there is a log file.
428
429 Even though this function is called initlog(), you should always
430 use log(); log is a variable that is set either to initlog
431 (initially), to dolog (once the log file has been opened), or to
432 nolog (when logging is disabled).
433
434 The first argument is a format string; the remaining arguments (if
435 any) are arguments to the % operator, so e.g.
436 log("%s: %s", "a", "b")
437 will write "a: b" to the log file, followed by a newline.
438
439 If the global logfp is not None, it should be a file object to
440 which log data is written.
441
442 If the global logfp is None, the global logfile may be a string
443 giving a filename to open, in append mode. This file should be
444 world writable!!! If the file can't be opened, logging is
445 silently disabled (since there is no safe place where we could
446 send an error message).
447
448 """
449 global logfp, log
450 if logfile and not logfp:
451 try:
452 logfp = open(logfile, "a")
453 except IOError:
454 pass
455 if not logfp:
456 log = nolog
457 else:
458 log = dolog
459 apply(log, allargs)
460
461def dolog(fmt, *args):
462 """Write a log message to the log file. See initlog() for docs."""
463 logfp.write(fmt%args + "\n")
464
465def nolog(*allargs):
466 """Dummy function, assigned to log when logging is disabled."""
467 pass
468
469log = initlog # The current logging function
470
471
Guido van Rossum72755611996-03-06 07:20:06 +0000472# Parsing functions
473# =================
474
Guido van Rossum773ab271996-07-23 03:46:24 +0000475def parse(fp=None, environ=os.environ, keep_blank_values=None):
476 """Parse a query in the environment or from a file (default stdin)
477
478 Arguments, all optional:
479
480 fp : file pointer; default: sys.stdin
481
482 environ : environment dictionary; default: os.environ
483
484 keep_blank_values: flag indicating whether blank values in
485 URL encoded forms should be treated as blank strings.
486 A true value inicates that blanks should be retained as
487 blank strings. The default false value indicates that
488 blank values are to be ignored and treated as if they were
489 not included.
490 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000491 if not fp:
492 fp = sys.stdin
493 if not environ.has_key('REQUEST_METHOD'):
494 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
495 if environ['REQUEST_METHOD'] == 'POST':
496 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
497 if ctype == 'multipart/form-data':
Guido van Rossum0147db01996-03-09 03:16:04 +0000498 return parse_multipart(fp, pdict)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000499 elif ctype == 'application/x-www-form-urlencoded':
500 clength = string.atoi(environ['CONTENT_LENGTH'])
501 qs = fp.read(clength)
Guido van Rossum1c9daa81995-09-18 21:52:37 +0000502 else:
Guido van Rossum0147db01996-03-09 03:16:04 +0000503 qs = '' # Unknown content-type
Guido van Rossumafb5e931996-08-08 18:42:12 +0000504 if environ.has_key('QUERY_STRING'):
505 if qs: qs = qs + '&'
506 qs = qs + environ['QUERY_STRING']
507 elif sys.argv[1:]:
508 if qs: qs = qs + '&'
509 qs = qs + sys.argv[1]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000510 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
511 elif environ.has_key('QUERY_STRING'):
512 qs = environ['QUERY_STRING']
513 else:
514 if sys.argv[1:]:
515 qs = sys.argv[1]
516 else:
517 qs = ""
518 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossum773ab271996-07-23 03:46:24 +0000519 return parse_qs(qs, keep_blank_values)
Guido van Rossume7808771995-08-07 20:12:09 +0000520
521
Guido van Rossum773ab271996-07-23 03:46:24 +0000522def parse_qs(qs, keep_blank_values=None):
523 """Parse a query given as a string argumen
524
525 Arguments:
526
527 qs : URL-encoded query string to be parsed
528
529 keep_blank_values: flag indicating whether blank values in
530 URL encoded queries should be treated as blank strings.
531 A true value inicates that blanks should be retained as
532 blank strings. The default false value indicates that
533 blank values are to be ignored and treated as if they were
534 not included.
535 """
Guido van Rossum0147db01996-03-09 03:16:04 +0000536 import urllib, regsub
Guido van Rossum7aee3841996-03-07 18:00:44 +0000537 name_value_pairs = string.splitfields(qs, '&')
538 dict = {}
539 for name_value in name_value_pairs:
540 nv = string.splitfields(name_value, '=')
541 if len(nv) != 2:
542 continue
543 name = nv[0]
544 value = urllib.unquote(regsub.gsub('+', ' ', nv[1]))
Guido van Rossum773ab271996-07-23 03:46:24 +0000545 if len(value) or keep_blank_values:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000546 if dict.has_key (name):
547 dict[name].append(value)
548 else:
549 dict[name] = [value]
550 return dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000551
552
Guido van Rossum0147db01996-03-09 03:16:04 +0000553def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000554 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000555
Guido van Rossum7aee3841996-03-07 18:00:44 +0000556 Arguments:
557 fp : input file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000558 pdict: dictionary containing other parameters of conten-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000559
Guido van Rossum0147db01996-03-09 03:16:04 +0000560 Returns a dictionary just like parse_qs(): keys are the field names, each
561 value is a list of values for that field. This is easy to use but not
562 much good if you are expecting megabytes to be uploaded -- in that case,
563 use the FieldStorage class instead which is much more flexible. Note
564 that content-type is the raw, unparsed contents of the content-type
565 header.
566
567 XXX This does not parse nested multipart parts -- use FieldStorage for
568 that.
569
570 XXX This should really be subsumed by FieldStorage altogether -- no
571 point in having two implementations of the same parsing algorithm.
Guido van Rossum72755611996-03-06 07:20:06 +0000572
Guido van Rossum7aee3841996-03-07 18:00:44 +0000573 """
574 import mimetools
575 if pdict.has_key('boundary'):
576 boundary = pdict['boundary']
577 else:
578 boundary = ""
579 nextpart = "--" + boundary
580 lastpart = "--" + boundary + "--"
581 partdict = {}
582 terminator = ""
583
584 while terminator != lastpart:
585 bytes = -1
586 data = None
587 if terminator:
588 # At start of next part. Read headers first.
589 headers = mimetools.Message(fp)
590 clength = headers.getheader('content-length')
591 if clength:
592 try:
593 bytes = string.atoi(clength)
594 except string.atoi_error:
595 pass
596 if bytes > 0:
597 data = fp.read(bytes)
598 else:
599 data = ""
600 # Read lines until end of part.
601 lines = []
602 while 1:
603 line = fp.readline()
604 if not line:
605 terminator = lastpart # End outer loop
606 break
607 if line[:2] == "--":
608 terminator = string.strip(line)
609 if terminator in (nextpart, lastpart):
610 break
Guido van Rossum7aee3841996-03-07 18:00:44 +0000611 lines.append(line)
612 # Done with part.
613 if data is None:
614 continue
615 if bytes < 0:
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000616 if lines:
617 # Strip final line terminator
618 line = lines[-1]
619 if line[-2:] == "\r\n":
620 line = line[:-2]
621 elif line[-1:] == "\n":
622 line = line[:-1]
623 lines[-1] = line
624 data = string.joinfields(lines, "")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000625 line = headers['content-disposition']
626 if not line:
627 continue
628 key, params = parse_header(line)
629 if key != 'form-data':
630 continue
631 if params.has_key('name'):
632 name = params['name']
Guido van Rossum72755611996-03-06 07:20:06 +0000633 else:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000634 continue
Guido van Rossum7aee3841996-03-07 18:00:44 +0000635 if partdict.has_key(name):
636 partdict[name].append(data)
637 else:
638 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000639
Guido van Rossum7aee3841996-03-07 18:00:44 +0000640 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000641
642
Guido van Rossum72755611996-03-06 07:20:06 +0000643def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000644 """Parse a Content-type like header.
645
646 Return the main content-type and a dictionary of options.
647
648 """
649 plist = map(string.strip, string.splitfields(line, ';'))
650 key = string.lower(plist[0])
651 del plist[0]
652 pdict = {}
653 for p in plist:
654 i = string.find(p, '=')
655 if i >= 0:
656 name = string.lower(string.strip(p[:i]))
657 value = string.strip(p[i+1:])
658 if len(value) >= 2 and value[0] == value[-1] == '"':
659 value = value[1:-1]
660 pdict[name] = value
661 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000662
663
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000664# Classes for field storage
665# =========================
666
667class MiniFieldStorage:
668
Guido van Rossum0147db01996-03-09 03:16:04 +0000669 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000670
Guido van Rossum7aee3841996-03-07 18:00:44 +0000671 # Dummy attributes
672 filename = None
673 list = None
674 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000675 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000676 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000677 disposition = None
678 disposition_options = {}
679 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000680
Guido van Rossum7aee3841996-03-07 18:00:44 +0000681 def __init__(self, name, value):
682 """Constructor from field name and value."""
683 from StringIO import StringIO
684 self.name = name
685 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000686 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000687
688 def __repr__(self):
689 """Return printable representation."""
690 return "MiniFieldStorage(%s, %s)" % (`self.name`, `self.value`)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000691
692
693class FieldStorage:
694
Guido van Rossum7aee3841996-03-07 18:00:44 +0000695 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000696
Guido van Rossum7aee3841996-03-07 18:00:44 +0000697 This class provides naming, typing, files stored on disk, and
698 more. At the top level, it is accessible like a dictionary, whose
699 keys are the field names. (Note: None can occur as a field name.)
700 The items are either a Python list (if there's multiple values) or
701 another FieldStorage or MiniFieldStorage object. If it's a single
702 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000703
Guido van Rossum7aee3841996-03-07 18:00:44 +0000704 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000705
Guido van Rossum7aee3841996-03-07 18:00:44 +0000706 filename: the filename, if specified; otherwise None; this is the
707 client side filename, *not* the file name on which it is
Guido van Rossum0147db01996-03-09 03:16:04 +0000708 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000709
Guido van Rossum7aee3841996-03-07 18:00:44 +0000710 value: the value as a *string*; for file uploads, this
711 transparently reads the file every time you request the value
712
713 file: the file(-like) object from which you can read the data;
714 None if the data is stored a simple string
715
716 type: the content-type, or None if not specified
717
718 type_options: dictionary of options specified on the content-type
719 line
720
721 disposition: content-disposition, or None if not specified
722
723 disposition_options: dictionary of corresponding options
724
725 headers: a dictionary(-like) object (sometimes rfc822.Message or a
726 subclass thereof) containing *all* headers
727
728 The class is subclassable, mostly for the purpose of overriding
729 the make_file() method, which is called internally to come up with
730 a file open for reading and writing. This makes it possible to
731 override the default choice of storing all files in a temporary
732 directory and unlinking them as soon as they have been opened.
733
734 """
735
Guido van Rossum773ab271996-07-23 03:46:24 +0000736 def __init__(self, fp=None, headers=None, outerboundary="",
737 environ=os.environ, keep_blank_values=None):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000738 """Constructor. Read multipart/* until last part.
739
740 Arguments, all optional:
741
742 fp : file pointer; default: sys.stdin
743
744 headers : header dictionary-like object; default:
745 taken from environ as per CGI spec
746
Guido van Rossum773ab271996-07-23 03:46:24 +0000747 outerboundary : terminating multipart boundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000748 (for internal use only)
749
Guido van Rossum773ab271996-07-23 03:46:24 +0000750 environ : environment dictionary; default: os.environ
751
752 keep_blank_values: flag indicating whether blank values in
753 URL encoded forms should be treated as blank strings.
754 A true value inicates that blanks should be retained as
755 blank strings. The default false value indicates that
756 blank values are to be ignored and treated as if they were
757 not included.
758
Guido van Rossum7aee3841996-03-07 18:00:44 +0000759 """
760 method = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000761 self.keep_blank_values = keep_blank_values
Guido van Rossum7aee3841996-03-07 18:00:44 +0000762 if environ.has_key('REQUEST_METHOD'):
763 method = string.upper(environ['REQUEST_METHOD'])
764 if not fp and method == 'GET':
765 qs = None
766 if environ.has_key('QUERY_STRING'):
767 qs = environ['QUERY_STRING']
768 from StringIO import StringIO
769 fp = StringIO(qs or "")
770 if headers is None:
771 headers = {'content-type':
772 "application/x-www-form-urlencoded"}
773 if headers is None:
774 headers = {}
775 if environ.has_key('CONTENT_TYPE'):
776 headers['content-type'] = environ['CONTENT_TYPE']
777 if environ.has_key('CONTENT_LENGTH'):
778 headers['content-length'] = environ['CONTENT_LENGTH']
779 self.fp = fp or sys.stdin
780 self.headers = headers
781 self.outerboundary = outerboundary
782
783 # Process content-disposition header
784 cdisp, pdict = "", {}
785 if self.headers.has_key('content-disposition'):
786 cdisp, pdict = parse_header(self.headers['content-disposition'])
787 self.disposition = cdisp
788 self.disposition_options = pdict
789 self.name = None
790 if pdict.has_key('name'):
791 self.name = pdict['name']
792 self.filename = None
793 if pdict.has_key('filename'):
794 self.filename = pdict['filename']
795
796 # Process content-type header
797 ctype, pdict = "text/plain", {}
798 if self.headers.has_key('content-type'):
799 ctype, pdict = parse_header(self.headers['content-type'])
800 self.type = ctype
801 self.type_options = pdict
802 self.innerboundary = ""
803 if pdict.has_key('boundary'):
804 self.innerboundary = pdict['boundary']
805 clen = -1
806 if self.headers.has_key('content-length'):
807 try:
808 clen = string.atoi(self.headers['content-length'])
809 except:
810 pass
811 self.length = clen
812
813 self.list = self.file = None
814 self.done = 0
815 self.lines = []
816 if ctype == 'application/x-www-form-urlencoded':
817 self.read_urlencoded()
818 elif ctype[:10] == 'multipart/':
819 self.read_multi()
820 else:
821 self.read_single()
822
823 def __repr__(self):
824 """Return a printable representation."""
825 return "FieldStorage(%s, %s, %s)" % (
826 `self.name`, `self.filename`, `self.value`)
827
828 def __getattr__(self, name):
829 if name != 'value':
830 raise AttributeError, name
831 if self.file:
832 self.file.seek(0)
833 value = self.file.read()
834 self.file.seek(0)
835 elif self.list is not None:
836 value = self.list
837 else:
838 value = None
839 return value
840
841 def __getitem__(self, key):
842 """Dictionary style indexing."""
843 if self.list is None:
844 raise TypeError, "not indexable"
845 found = []
846 for item in self.list:
847 if item.name == key: found.append(item)
848 if not found:
849 raise KeyError, key
Guido van Rossum0147db01996-03-09 03:16:04 +0000850 if len(found) == 1:
851 return found[0]
852 else:
853 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000854
855 def keys(self):
856 """Dictionary style keys() method."""
857 if self.list is None:
858 raise TypeError, "not indexable"
859 keys = []
860 for item in self.list:
861 if item.name not in keys: keys.append(item.name)
862 return keys
863
Guido van Rossum0147db01996-03-09 03:16:04 +0000864 def has_key(self, key):
865 """Dictionary style has_key() method."""
866 if self.list is None:
867 raise TypeError, "not indexable"
868 for item in self.list:
869 if item.name == key: return 1
870 return 0
871
Guido van Rossum7aee3841996-03-07 18:00:44 +0000872 def read_urlencoded(self):
873 """Internal: read data in query string format."""
874 qs = self.fp.read(self.length)
Guido van Rossum773ab271996-07-23 03:46:24 +0000875 dict = parse_qs(qs, self.keep_blank_values)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000876 self.list = []
877 for key, valuelist in dict.items():
878 for value in valuelist:
879 self.list.append(MiniFieldStorage(key, value))
880 self.skip_lines()
881
882 def read_multi(self):
883 """Internal: read a part that is itself multipart."""
884 import rfc822
885 self.list = []
886 part = self.__class__(self.fp, {}, self.innerboundary)
887 # Throw first part away
888 while not part.done:
889 headers = rfc822.Message(self.fp)
890 part = self.__class__(self.fp, headers, self.innerboundary)
891 self.list.append(part)
892 self.skip_lines()
893
894 def read_single(self):
895 """Internal: read an atomic part."""
896 if self.length >= 0:
897 self.read_binary()
898 self.skip_lines()
899 else:
900 self.read_lines()
901 self.file.seek(0)
902
903 bufsize = 8*1024 # I/O buffering size for copy to file
904
905 def read_binary(self):
906 """Internal: read binary data."""
907 self.file = self.make_file('b')
908 todo = self.length
909 if todo >= 0:
910 while todo > 0:
911 data = self.fp.read(min(todo, self.bufsize))
912 if not data:
913 self.done = -1
914 break
915 self.file.write(data)
916 todo = todo - len(data)
917
918 def read_lines(self):
919 """Internal: read lines until EOF or outerboundary."""
920 self.file = self.make_file('')
921 if self.outerboundary:
922 self.read_lines_to_outerboundary()
923 else:
924 self.read_lines_to_eof()
925
926 def read_lines_to_eof(self):
927 """Internal: read lines until EOF."""
928 while 1:
929 line = self.fp.readline()
930 if not line:
931 self.done = -1
932 break
933 self.lines.append(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000934 self.file.write(line)
935
936 def read_lines_to_outerboundary(self):
937 """Internal: read lines until outerboundary."""
938 next = "--" + self.outerboundary
939 last = next + "--"
940 delim = ""
941 while 1:
942 line = self.fp.readline()
943 if not line:
944 self.done = -1
945 break
946 self.lines.append(line)
947 if line[:2] == "--":
948 strippedline = string.strip(line)
949 if strippedline == next:
950 break
951 if strippedline == last:
952 self.done = 1
953 break
Guido van Rossume5e46e01996-09-05 19:03:36 +0000954 odelim = delim
Guido van Rossum7aee3841996-03-07 18:00:44 +0000955 if line[-2:] == "\r\n":
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000956 delim = "\r\n"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000957 line = line[:-2]
958 elif line[-1] == "\n":
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000959 delim = "\n"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000960 line = line[:-1]
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000961 else:
962 delim = ""
Guido van Rossume5e46e01996-09-05 19:03:36 +0000963 self.file.write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000964
965 def skip_lines(self):
966 """Internal: skip lines until outer boundary if defined."""
967 if not self.outerboundary or self.done:
968 return
969 next = "--" + self.outerboundary
970 last = next + "--"
971 while 1:
972 line = self.fp.readline()
973 if not line:
974 self.done = -1
975 break
976 self.lines.append(line)
977 if line[:2] == "--":
978 strippedline = string.strip(line)
979 if strippedline == next:
980 break
981 if strippedline == last:
982 self.done = 1
983 break
984
985 def make_file(self, binary):
986 """Overridable: return a readable & writable file.
987
988 The file will be used as follows:
989 - data is written to it
990 - seek(0)
991 - data is read from it
992
993 The 'binary' argument is 'b' if the file should be created in
994 binary mode (on non-Unix systems), '' otherwise.
995
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000996 This version opens a temporary file for reading and writing,
997 and immediately deletes (unlinks) it. The trick (on Unix!) is
998 that the file can still be used, but it can't be opened by
999 another process, and it will automatically be deleted when it
1000 is closed or when the current process terminates.
1001
1002 If you want a more permanent file, you derive a class which
1003 overrides this method. If you want a visible temporary file
1004 that is nevertheless automatically deleted when the script
1005 terminates, try defining a __del__ method in a derived class
1006 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +00001007
1008 """
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001009 import tempfile
1010 tfn = tempfile.mktemp()
1011 f = open(tfn, "w%s+" % binary)
1012 os.unlink(tfn)
1013 return f
Guido van Rossum243ddcd1996-03-07 06:33:07 +00001014
1015
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001016# Backwards Compatibility Classes
1017# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +00001018
1019class FormContentDict:
Guido van Rossum7aee3841996-03-07 18:00:44 +00001020 """Basic (multiple values per field) form content as dictionary.
Guido van Rossum72755611996-03-06 07:20:06 +00001021
Guido van Rossum7aee3841996-03-07 18:00:44 +00001022 form = FormContentDict()
1023
1024 form[key] -> [value, value, ...]
1025 form.has_key(key) -> Boolean
1026 form.keys() -> [key, key, ...]
1027 form.values() -> [[val, val, ...], [val, val, ...], ...]
1028 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
1029 form.dict == {key: [val, val, ...], ...}
1030
1031 """
Guido van Rossum773ab271996-07-23 03:46:24 +00001032 def __init__(self, environ=os.environ):
Guido van Rossumafb5e931996-08-08 18:42:12 +00001033 self.dict = parse(environ=environ)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001034 self.query_string = environ['QUERY_STRING']
1035 def __getitem__(self,key):
1036 return self.dict[key]
1037 def keys(self):
1038 return self.dict.keys()
1039 def has_key(self, key):
1040 return self.dict.has_key(key)
1041 def values(self):
1042 return self.dict.values()
1043 def items(self):
1044 return self.dict.items()
1045 def __len__( self ):
1046 return len(self.dict)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001047
1048
Guido van Rossum9a22de11995-01-12 12:29:47 +00001049class SvFormContentDict(FormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001050 """Strict single-value expecting form content as dictionary.
1051
1052 IF you only expect a single value for each field, then form[key]
1053 will return that single value. It will raise an IndexError if
1054 that expectation is not true. IF you expect a field to have
1055 possible multiple values, than you can use form.getlist(key) to
1056 get all of the values. values() and items() are a compromise:
1057 they return single strings where there is a single value, and
1058 lists of strings otherwise.
1059
1060 """
1061 def __getitem__(self, key):
1062 if len(self.dict[key]) > 1:
1063 raise IndexError, 'expecting a single value'
1064 return self.dict[key][0]
1065 def getlist(self, key):
1066 return self.dict[key]
1067 def values(self):
1068 lis = []
1069 for each in self.dict.values():
1070 if len( each ) == 1 :
1071 lis.append(each[0])
1072 else: lis.append(each)
1073 return lis
1074 def items(self):
1075 lis = []
1076 for key,value in self.dict.items():
1077 if len(value) == 1 :
1078 lis.append((key, value[0]))
1079 else: lis.append((key, value))
1080 return lis
Guido van Rossum9a22de11995-01-12 12:29:47 +00001081
1082
Guido van Rossum9a22de11995-01-12 12:29:47 +00001083class InterpFormContentDict(SvFormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001084 """This class is present for backwards compatibility only."""
1085 def __getitem__( self, key ):
1086 v = SvFormContentDict.__getitem__( self, key )
1087 if v[0] in string.digits+'+-.' :
1088 try: return string.atoi( v )
1089 except ValueError:
1090 try: return string.atof( v )
1091 except ValueError: pass
1092 return string.strip(v)
1093 def values( self ):
1094 lis = []
1095 for key in self.keys():
1096 try:
1097 lis.append( self[key] )
1098 except IndexError:
1099 lis.append( self.dict[key] )
1100 return lis
1101 def items( self ):
1102 lis = []
1103 for key in self.keys():
1104 try:
1105 lis.append( (key, self[key]) )
1106 except IndexError:
1107 lis.append( (key, self.dict[key]) )
1108 return lis
Guido van Rossum9a22de11995-01-12 12:29:47 +00001109
1110
Guido van Rossum9a22de11995-01-12 12:29:47 +00001111class FormContent(FormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001112 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +00001113 def values(self, key):
1114 if self.dict.has_key(key) :return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +00001115 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001116 def indexed_value(self, key, location):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001117 if self.dict.has_key(key):
1118 if len (self.dict[key]) > location:
1119 return self.dict[key][location]
1120 else: return None
1121 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001122 def value(self, key):
1123 if self.dict.has_key(key): return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +00001124 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001125 def length(self, key):
1126 return len(self.dict[key])
1127 def stripped(self, key):
1128 if self.dict.has_key(key): return string.strip(self.dict[key][0])
Guido van Rossum7aee3841996-03-07 18:00:44 +00001129 else: return None
1130 def pars(self):
1131 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +00001132
1133
Guido van Rossum72755611996-03-06 07:20:06 +00001134# Test/debug code
1135# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +00001136
Guido van Rossum773ab271996-07-23 03:46:24 +00001137def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001138 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +00001139
Guido van Rossum7aee3841996-03-07 18:00:44 +00001140 Write minimal HTTP headers and dump all information provided to
1141 the script in HTML form.
1142
1143 """
1144 import traceback
1145 print "Content-type: text/html"
1146 print
1147 sys.stderr = sys.stdout
1148 try:
Guido van Rossum0147db01996-03-09 03:16:04 +00001149 form = FieldStorage() # Replace with other classes to test those
1150 print_form(form)
Guido van Rossum773ab271996-07-23 03:46:24 +00001151 print_environ(environ)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001152 print_directory()
Guido van Rossuma8738a51996-03-14 21:30:28 +00001153 print_arguments()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001154 print_environ_usage()
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001155 def f():
1156 exec "testing print_exception() -- <I>italics?</I>"
1157 def g(f=f):
1158 f()
1159 print "<H3>What follows is a test, not an actual exception:</H3>"
1160 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001161 except:
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001162 print_exception()
1163
1164def print_exception(type=None, value=None, tb=None, limit=None):
1165 if type is None:
1166 type, value, tb = sys.exc_type, sys.exc_value, sys.exc_traceback
1167 import traceback
1168 print
1169 print "<H3>Traceback (innermost last):</H3>"
1170 list = traceback.format_tb(tb, limit) + \
1171 traceback.format_exception_only(type, value)
1172 print "<PRE>%s<B>%s</B></PRE>" % (
1173 escape(string.join(list[:-1], "")),
1174 escape(list[-1]),
1175 )
Guido van Rossum9a22de11995-01-12 12:29:47 +00001176
Guido van Rossum773ab271996-07-23 03:46:24 +00001177def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001178 """Dump the shell environment as HTML."""
1179 keys = environ.keys()
1180 keys.sort()
1181 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001182 print "<H3>Shell Environment:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +00001183 print "<DL>"
1184 for key in keys:
1185 print "<DT>", escape(key), "<DD>", escape(environ[key])
1186 print "</DL>"
1187 print
Guido van Rossum72755611996-03-06 07:20:06 +00001188
1189def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001190 """Dump the contents of a form as HTML."""
1191 keys = form.keys()
1192 keys.sort()
1193 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001194 print "<H3>Form Contents:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +00001195 print "<DL>"
1196 for key in keys:
1197 print "<DT>" + escape(key) + ":",
1198 value = form[key]
1199 print "<i>" + escape(`type(value)`) + "</i>"
1200 print "<DD>" + escape(`value`)
1201 print "</DL>"
1202 print
1203
1204def print_directory():
1205 """Dump the current directory as HTML."""
1206 print
1207 print "<H3>Current Working Directory:</H3>"
1208 try:
1209 pwd = os.getcwd()
1210 except os.error, msg:
1211 print "os.error:", escape(str(msg))
1212 else:
1213 print escape(pwd)
1214 print
Guido van Rossum9a22de11995-01-12 12:29:47 +00001215
Guido van Rossuma8738a51996-03-14 21:30:28 +00001216def print_arguments():
1217 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001218 print "<H3>Command Line Arguments:</H3>"
Guido van Rossuma8738a51996-03-14 21:30:28 +00001219 print
1220 print sys.argv
1221 print
1222
Guido van Rossum9a22de11995-01-12 12:29:47 +00001223def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +00001224 """Dump a list of environment variables used by CGI as HTML."""
1225 print """
Guido van Rossum72755611996-03-06 07:20:06 +00001226<H3>These environment variables could have been set:</H3>
1227<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001228<LI>AUTH_TYPE
1229<LI>CONTENT_LENGTH
1230<LI>CONTENT_TYPE
1231<LI>DATE_GMT
1232<LI>DATE_LOCAL
1233<LI>DOCUMENT_NAME
1234<LI>DOCUMENT_ROOT
1235<LI>DOCUMENT_URI
1236<LI>GATEWAY_INTERFACE
1237<LI>LAST_MODIFIED
1238<LI>PATH
1239<LI>PATH_INFO
1240<LI>PATH_TRANSLATED
1241<LI>QUERY_STRING
1242<LI>REMOTE_ADDR
1243<LI>REMOTE_HOST
1244<LI>REMOTE_IDENT
1245<LI>REMOTE_USER
1246<LI>REQUEST_METHOD
1247<LI>SCRIPT_NAME
1248<LI>SERVER_NAME
1249<LI>SERVER_PORT
1250<LI>SERVER_PROTOCOL
1251<LI>SERVER_ROOT
1252<LI>SERVER_SOFTWARE
1253</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001254In addition, HTTP headers sent by the server may be passed in the
1255environment as well. Here are some common variable names:
1256<UL>
1257<LI>HTTP_ACCEPT
1258<LI>HTTP_CONNECTION
1259<LI>HTTP_HOST
1260<LI>HTTP_PRAGMA
1261<LI>HTTP_REFERER
1262<LI>HTTP_USER_AGENT
1263</UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001264"""
1265
Guido van Rossum9a22de11995-01-12 12:29:47 +00001266
Guido van Rossum72755611996-03-06 07:20:06 +00001267# Utilities
1268# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001269
Guido van Rossum72755611996-03-06 07:20:06 +00001270def escape(s):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001271 """Replace special characters '&', '<' and '>' by SGML entities."""
Guido van Rossum0147db01996-03-09 03:16:04 +00001272 import regsub
Guido van Rossum7aee3841996-03-07 18:00:44 +00001273 s = regsub.gsub("&", "&amp;", s) # Must be done first!
1274 s = regsub.gsub("<", "&lt;", s)
1275 s = regsub.gsub(">", "&gt;", s)
1276 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001277
Guido van Rossum9a22de11995-01-12 12:29:47 +00001278
Guido van Rossum72755611996-03-06 07:20:06 +00001279# Invoke mainline
1280# ===============
1281
1282# Call test() when this file is run as a script (not imported as a module)
1283if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001284 test()