blob: 7fab38d87535c2f8c8a3a13ac45730f5e765085d [file] [log] [blame]
Guido van Rossumf06ee5f1996-11-27 19:52:01 +00001#! /usr/bin/env python
Guido van Rossum1c9daa81995-09-18 21:52:37 +00002
Guido van Rossum72755611996-03-06 07:20:06 +00003"""Support module for CGI (Common Gateway Interface) scripts.
Guido van Rossum1c9daa81995-09-18 21:52:37 +00004
Guido van Rossum7aee3841996-03-07 18:00:44 +00005This module defines a number of utilities for use by CGI scripts
6written in Python.
Guido van Rossum9a22de11995-01-12 12:29:47 +00007
8
Guido van Rossum72755611996-03-06 07:20:06 +00009Introduction
10------------
11
Guido van Rossum391b4e61996-03-06 19:11:33 +000012A CGI script is invoked by an HTTP server, usually to process user
13input submitted through an HTML <FORM> or <ISINPUT> element.
Guido van Rossum72755611996-03-06 07:20:06 +000014
Guido van Rossum391b4e61996-03-06 19:11:33 +000015Most often, CGI scripts live in the server's special cgi-bin
16directory. The HTTP server places all sorts of information about the
17request (such as the client's hostname, the requested URL, the query
18string, and lots of other goodies) in the script's shell environment,
19executes the script, and sends the script's output back to the client.
Guido van Rossum72755611996-03-06 07:20:06 +000020
Guido van Rossum391b4e61996-03-06 19:11:33 +000021The script's input is connected to the client too, and sometimes the
22form data is read this way; at other times the form data is passed via
23the "query string" part of the URL. This module (cgi.py) is intended
24to take care of the different cases and provide a simpler interface to
25the Python script. It also provides a number of utilities that help
26in debugging scripts, and the latest addition is support for file
27uploads from a form (if your browser supports it -- Grail 0.3 and
28Netscape 2.0 do).
Guido van Rossum72755611996-03-06 07:20:06 +000029
Guido van Rossum391b4e61996-03-06 19:11:33 +000030The output of a CGI script should consist of two sections, separated
31by a blank line. The first section contains a number of headers,
32telling the client what kind of data is following. Python code to
33generate a minimal header section looks like this:
Guido van Rossum72755611996-03-06 07:20:06 +000034
Guido van Rossum243ddcd1996-03-07 06:33:07 +000035 print "Content-type: text/html" # HTML is following
36 print # blank line, end of headers
Guido van Rossum72755611996-03-06 07:20:06 +000037
Guido van Rossum391b4e61996-03-06 19:11:33 +000038The second section is usually HTML, which allows the client software
39to display nicely formatted text with header, in-line images, etc.
40Here's Python code that prints a simple piece of HTML:
Guido van Rossum72755611996-03-06 07:20:06 +000041
42 print "<TITLE>CGI script output</TITLE>"
43 print "<H1>This is my first CGI script</H1>"
44 print "Hello, world!"
45
Guido van Rossum391b4e61996-03-06 19:11:33 +000046(It may not be fully legal HTML according to the letter of the
47standard, but any browser will understand it.)
Guido van Rossum72755611996-03-06 07:20:06 +000048
49
50Using the cgi module
51--------------------
52
Guido van Rossum391b4e61996-03-06 19:11:33 +000053Begin by writing "import cgi". Don't use "from cgi import *" -- the
Guido van Rossum0147db01996-03-09 03:16:04 +000054module defines all sorts of names for its own use or for backward
55compatibility that you don't want in your namespace.
Guido van Rossum72755611996-03-06 07:20:06 +000056
Guido van Rossum0147db01996-03-09 03:16:04 +000057It's best to use the FieldStorage class. The other classes define in this
58module are provided mostly for backward compatibility. Instantiate it
59exactly once, without arguments. This reads the form contents from
60standard input or the environment (depending on the value of various
61environment variables set according to the CGI standard). Since it may
62consume standard input, it should be instantiated only once.
Guido van Rossum72755611996-03-06 07:20:06 +000063
Guido van Rossum0147db01996-03-09 03:16:04 +000064The FieldStorage instance can be accessed as if it were a Python
65dictionary. For instance, the following code (which assumes that the
66Content-type header and blank line have already been printed) checks that
67the fields "name" and "addr" are both set to a non-empty string:
Guido van Rossum72755611996-03-06 07:20:06 +000068
Guido van Rossum503e50b1996-05-28 22:57:20 +000069 form = cgi.FieldStorage()
Guido van Rossum72755611996-03-06 07:20:06 +000070 form_ok = 0
71 if form.has_key("name") and form.has_key("addr"):
Guido van Rossum0147db01996-03-09 03:16:04 +000072 if form["name"].value != "" and form["addr"].value != "":
Guido van Rossum72755611996-03-06 07:20:06 +000073 form_ok = 1
74 if not form_ok:
75 print "<H1>Error</H1>"
76 print "Please fill in the name and addr fields."
77 return
Guido van Rossum0147db01996-03-09 03:16:04 +000078 ...further form processing here...
Guido van Rossum72755611996-03-06 07:20:06 +000079
Guido van Rossum4032c2c1996-03-09 04:04:35 +000080Here the fields, accessed through form[key], are themselves instances
81of FieldStorage (or MiniFieldStorage, depending on the form encoding).
Guido van Rossum72755611996-03-06 07:20:06 +000082
Guido van Rossum4032c2c1996-03-09 04:04:35 +000083If the submitted form data contains more than one field with the same
84name, the object retrieved by form[key] is not a (Mini)FieldStorage
85instance but a list of such instances. If you expect this possibility
86(i.e., when your HTML form comtains multiple fields with the same
87name), use the type() function to determine whether you have a single
88instance or a list of instances. For example, here's code that
89concatenates any number of username fields, separated by commas:
90
91 username = form["username"]
Guido van Rossum0147db01996-03-09 03:16:04 +000092 if type(username) is type([]):
93 # Multiple username fields specified
94 usernames = ""
95 for item in username:
96 if usernames:
97 # Next item -- insert comma
98 usernames = usernames + "," + item.value
99 else:
100 # First item -- don't insert comma
101 usernames = item.value
102 else:
103 # Single username field specified
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000104 usernames = username.value
Guido van Rossum0147db01996-03-09 03:16:04 +0000105
106If a field represents an uploaded file, the value attribute reads the
107entire file in memory as a string. This may not be what you want. You can
108test for an uploaded file by testing either the filename attribute or the
109file attribute. You can then read the data at leasure from the file
110attribute:
111
112 fileitem = form["userfile"]
113 if fileitem.file:
114 # It's an uploaded file; count lines
115 linecount = 0
116 while 1:
117 line = fileitem.file.readline()
118 if not line: break
119 linecount = linecount + 1
120
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000121The file upload draft standard entertains the possibility of uploading
122multiple files from one field (using a recursive multipart/*
123encoding). When this occurs, the item will be a dictionary-like
124FieldStorage item. This can be determined by testing its type
125attribute, which should have the value "multipart/form-data" (or
126perhaps another string beginning with "multipart/"). It this case, it
127can be iterated over recursively just like the top-level form object.
128
Guido van Rossum0147db01996-03-09 03:16:04 +0000129When a form is submitted in the "old" format (as the query string or as a
130single data part of type application/x-www-form-urlencoded), the items
131will actually be instances of the class MiniFieldStorage. In this case,
132the list, file and filename attributes are always None.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000133
Guido van Rossum72755611996-03-06 07:20:06 +0000134
Guido van Rossum0147db01996-03-09 03:16:04 +0000135Old classes
136-----------
Guido van Rossum72755611996-03-06 07:20:06 +0000137
Guido van Rossum0147db01996-03-09 03:16:04 +0000138These classes, present in earlier versions of the cgi module, are still
Guido van Rossum16d5b111996-10-24 14:44:32 +0000139supported for backward compatibility. New applications should use the
140FieldStorage class.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000141
Guido van Rossum0147db01996-03-09 03:16:04 +0000142SvFormContentDict: single value form content as dictionary; assumes each
143field name occurs in the form only once.
Guido van Rossum72755611996-03-06 07:20:06 +0000144
Guido van Rossum391b4e61996-03-06 19:11:33 +0000145FormContentDict: multiple value form content as dictionary (the form
146items are lists of values). Useful if your form contains multiple
147fields with the same name.
Guido van Rossum72755611996-03-06 07:20:06 +0000148
Guido van Rossum391b4e61996-03-06 19:11:33 +0000149Other classes (FormContent, InterpFormContentDict) are present for
Guido van Rossum0147db01996-03-09 03:16:04 +0000150backwards compatibility with really old applications only. If you still
151use these and would be inconvenienced when they disappeared from a next
152version of this module, drop me a note.
Guido van Rossum72755611996-03-06 07:20:06 +0000153
154
Guido van Rossum0147db01996-03-09 03:16:04 +0000155Functions
156---------
Guido van Rossum72755611996-03-06 07:20:06 +0000157
Guido van Rossum391b4e61996-03-06 19:11:33 +0000158These are useful if you want more control, or if you want to employ
159some of the algorithms implemented in this module in other
160circumstances.
Guido van Rossum72755611996-03-06 07:20:06 +0000161
Guido van Rossume08c04c1996-11-11 19:29:11 +0000162parse(fp, [environ, [keep_blank_values, [strict_parsing]]]): parse a
163form into a Python dictionary.
Guido van Rossum72755611996-03-06 07:20:06 +0000164
Guido van Rossume08c04c1996-11-11 19:29:11 +0000165parse_qs(qs, [keep_blank_values, [strict_parsing]]): parse a query
166string (data of type application/x-www-form-urlencoded).
Guido van Rossum72755611996-03-06 07:20:06 +0000167
Guido van Rossum0147db01996-03-09 03:16:04 +0000168parse_multipart(fp, pdict): parse input of type multipart/form-data (for
Guido van Rossum391b4e61996-03-06 19:11:33 +0000169file uploads).
Guido van Rossum72755611996-03-06 07:20:06 +0000170
Guido van Rossum391b4e61996-03-06 19:11:33 +0000171parse_header(string): parse a header like Content-type into a main
172value and a dictionary of parameters.
Guido van Rossum72755611996-03-06 07:20:06 +0000173
174test(): complete test program.
175
176print_environ(): format the shell environment in HTML.
177
178print_form(form): format a form in HTML.
179
Guido van Rossum391b4e61996-03-06 19:11:33 +0000180print_environ_usage(): print a list of useful environment variables in
181HTML.
Guido van Rossum72755611996-03-06 07:20:06 +0000182
Guido van Rossum391b4e61996-03-06 19:11:33 +0000183escape(): convert the characters "&", "<" and ">" to HTML-safe
184sequences. Use this if you need to display text that might contain
185such characters in HTML. To translate URLs for inclusion in the HREF
186attribute of an <A> tag, use urllib.quote().
Guido van Rossum72755611996-03-06 07:20:06 +0000187
Guido van Rossumc204c701996-09-05 19:07:11 +0000188log(fmt, ...): write a line to a log file; see docs for initlog().
189
Guido van Rossum72755611996-03-06 07:20:06 +0000190
191Caring about security
192---------------------
193
Guido van Rossum391b4e61996-03-06 19:11:33 +0000194There's one important rule: if you invoke an external program (e.g.
195via the os.system() or os.popen() functions), make very sure you don't
196pass arbitrary strings received from the client to the shell. This is
197a well-known security hole whereby clever hackers anywhere on the web
198can exploit a gullible CGI script to invoke arbitrary shell commands.
199Even parts of the URL or field names cannot be trusted, since the
200request doesn't have to come from your form!
Guido van Rossum72755611996-03-06 07:20:06 +0000201
Guido van Rossum391b4e61996-03-06 19:11:33 +0000202To be on the safe side, if you must pass a string gotten from a form
203to a shell command, you should make sure the string contains only
204alphanumeric characters, dashes, underscores, and periods.
Guido van Rossum72755611996-03-06 07:20:06 +0000205
206
207Installing your CGI script on a Unix system
208-------------------------------------------
209
Guido van Rossum391b4e61996-03-06 19:11:33 +0000210Read the documentation for your HTTP server and check with your local
211system administrator to find the directory where CGI scripts should be
Guido van Rossum72755611996-03-06 07:20:06 +0000212installed; usually this is in a directory cgi-bin in the server tree.
213
Guido van Rossum391b4e61996-03-06 19:11:33 +0000214Make sure that your script is readable and executable by "others"; the
215Unix file mode should be 755 (use "chmod 755 filename"). Make sure
216that the first line of the script contains "#!" starting in column 1
217followed by the pathname of the Python interpreter, for instance:
Guido van Rossum72755611996-03-06 07:20:06 +0000218
Guido van Rossumf06ee5f1996-11-27 19:52:01 +0000219 #! /usr/local/bin/python
Guido van Rossum72755611996-03-06 07:20:06 +0000220
Guido van Rossum391b4e61996-03-06 19:11:33 +0000221Make sure the Python interpreter exists and is executable by "others".
Guido van Rossum72755611996-03-06 07:20:06 +0000222
Guido van Rossumf06ee5f1996-11-27 19:52:01 +0000223(Note that it's probably not a good idea to use #! /usr/bin/env python
224here, since the Python interpreter may not be on the default path
225given to CGI scripts!!!)
226
Guido van Rossum391b4e61996-03-06 19:11:33 +0000227Make sure that any files your script needs to read or write are
228readable or writable, respectively, by "others" -- their mode should
229be 644 for readable and 666 for writable. This is because, for
230security reasons, the HTTP server executes your script as user
231"nobody", without any special privileges. It can only read (write,
232execute) files that everybody can read (write, execute). The current
233directory at execution time is also different (it is usually the
234server's cgi-bin directory) and the set of environment variables is
235also different from what you get at login. in particular, don't count
236on the shell's search path for executables ($PATH) or the Python
237module search path ($PYTHONPATH) to be set to anything interesting.
Guido van Rossum72755611996-03-06 07:20:06 +0000238
Guido van Rossum391b4e61996-03-06 19:11:33 +0000239If you need to load modules from a directory which is not on Python's
240default module search path, you can change the path in your script,
241before importing other modules, e.g.:
Guido van Rossum72755611996-03-06 07:20:06 +0000242
243 import sys
244 sys.path.insert(0, "/usr/home/joe/lib/python")
245 sys.path.insert(0, "/usr/local/lib/python")
246
247(This way, the directory inserted last will be searched first!)
248
Guido van Rossum391b4e61996-03-06 19:11:33 +0000249Instructions for non-Unix systems will vary; check your HTTP server's
Guido van Rossum72755611996-03-06 07:20:06 +0000250documentation (it will usually have a section on CGI scripts).
251
252
253Testing your CGI script
254-----------------------
255
Guido van Rossum391b4e61996-03-06 19:11:33 +0000256Unfortunately, a CGI script will generally not run when you try it
257from the command line, and a script that works perfectly from the
258command line may fail mysteriously when run from the server. There's
259one reason why you should still test your script from the command
260line: if it contains a syntax error, the python interpreter won't
261execute it at all, and the HTTP server will most likely send a cryptic
262error to the client.
Guido van Rossum72755611996-03-06 07:20:06 +0000263
Guido van Rossum391b4e61996-03-06 19:11:33 +0000264Assuming your script has no syntax errors, yet it does not work, you
265have no choice but to read the next section:
Guido van Rossum72755611996-03-06 07:20:06 +0000266
267
268Debugging CGI scripts
269---------------------
270
Guido van Rossum391b4e61996-03-06 19:11:33 +0000271First of all, check for trivial installation errors -- reading the
272section above on installing your CGI script carefully can save you a
273lot of time. If you wonder whether you have understood the
274installation procedure correctly, try installing a copy of this module
275file (cgi.py) as a CGI script. When invoked as a script, the file
276will dump its environment and the contents of the form in HTML form.
277Give it the right mode etc, and send it a request. If it's installed
278in the standard cgi-bin directory, it should be possible to send it a
279request by entering a URL into your browser of the form:
Guido van Rossum72755611996-03-06 07:20:06 +0000280
281 http://yourhostname/cgi-bin/cgi.py?name=Joe+Blow&addr=At+Home
282
Guido van Rossum391b4e61996-03-06 19:11:33 +0000283If this gives an error of type 404, the server cannot find the script
284-- perhaps you need to install it in a different directory. If it
285gives another error (e.g. 500), there's an installation problem that
286you should fix before trying to go any further. If you get a nicely
287formatted listing of the environment and form content (in this
288example, the fields should be listed as "addr" with value "At Home"
289and "name" with value "Joe Blow"), the cgi.py script has been
290installed correctly. If you follow the same procedure for your own
291script, you should now be able to debug it.
Guido van Rossum72755611996-03-06 07:20:06 +0000292
Guido van Rossum391b4e61996-03-06 19:11:33 +0000293The next step could be to call the cgi module's test() function from
294your script: replace its main code with the single statement
Guido van Rossum72755611996-03-06 07:20:06 +0000295
296 cgi.test()
297
Guido van Rossum391b4e61996-03-06 19:11:33 +0000298This should produce the same results as those gotten from installing
299the cgi.py file itself.
Guido van Rossum72755611996-03-06 07:20:06 +0000300
Guido van Rossum391b4e61996-03-06 19:11:33 +0000301When an ordinary Python script raises an unhandled exception
302(e.g. because of a typo in a module name, a file that can't be opened,
303etc.), the Python interpreter prints a nice traceback and exits.
304While the Python interpreter will still do this when your CGI script
305raises an exception, most likely the traceback will end up in one of
306the HTTP server's log file, or be discarded altogether.
Guido van Rossum72755611996-03-06 07:20:06 +0000307
Guido van Rossum391b4e61996-03-06 19:11:33 +0000308Fortunately, once you have managed to get your script to execute
309*some* code, it is easy to catch exceptions and cause a traceback to
310be printed. The test() function below in this module is an example.
311Here are the rules:
Guido van Rossum72755611996-03-06 07:20:06 +0000312
Guido van Rossum391b4e61996-03-06 19:11:33 +0000313 1. Import the traceback module (before entering the
314 try-except!)
Guido van Rossum72755611996-03-06 07:20:06 +0000315
Guido van Rossum391b4e61996-03-06 19:11:33 +0000316 2. Make sure you finish printing the headers and the blank
317 line early
Guido van Rossum72755611996-03-06 07:20:06 +0000318
319 3. Assign sys.stderr to sys.stdout
320
321 3. Wrap all remaining code in a try-except statement
322
323 4. In the except clause, call traceback.print_exc()
324
325For example:
326
327 import sys
328 import traceback
329 print "Content-type: text/html"
330 print
331 sys.stderr = sys.stdout
332 try:
333 ...your code here...
334 except:
335 print "\n\n<PRE>"
336 traceback.print_exc()
337
Guido van Rossum391b4e61996-03-06 19:11:33 +0000338Notes: The assignment to sys.stderr is needed because the traceback
339prints to sys.stderr. The print "\n\n<PRE>" statement is necessary to
340disable the word wrapping in HTML.
Guido van Rossum72755611996-03-06 07:20:06 +0000341
Guido van Rossum391b4e61996-03-06 19:11:33 +0000342If you suspect that there may be a problem in importing the traceback
343module, you can use an even more robust approach (which only uses
344built-in modules):
Guido van Rossum72755611996-03-06 07:20:06 +0000345
346 import sys
347 sys.stderr = sys.stdout
348 print "Content-type: text/plain"
349 print
350 ...your code here...
351
Guido van Rossum391b4e61996-03-06 19:11:33 +0000352This relies on the Python interpreter to print the traceback. The
353content type of the output is set to plain text, which disables all
354HTML processing. If your script works, the raw HTML will be displayed
355by your client. If it raises an exception, most likely after the
356first two lines have been printed, a traceback will be displayed.
357Because no HTML interpretation is going on, the traceback will
358readable.
Guido van Rossum72755611996-03-06 07:20:06 +0000359
Guido van Rossumc204c701996-09-05 19:07:11 +0000360When all else fails, you may want to insert calls to log() to your
361program or even to a copy of the cgi.py file. Note that this requires
362you to set cgi.logfile to the name of a world-writable file before the
363first call to log() is made!
364
Guido van Rossum72755611996-03-06 07:20:06 +0000365Good luck!
366
367
368Common problems and solutions
369-----------------------------
370
Guido van Rossum391b4e61996-03-06 19:11:33 +0000371- Most HTTP servers buffer the output from CGI scripts until the
372script is completed. This means that it is not possible to display a
373progress report on the client's display while the script is running.
Guido van Rossum72755611996-03-06 07:20:06 +0000374
375- Check the installation instructions above.
376
Guido van Rossum391b4e61996-03-06 19:11:33 +0000377- Check the HTTP server's log files. ("tail -f logfile" in a separate
Guido van Rossum72755611996-03-06 07:20:06 +0000378window may be useful!)
379
Guido van Rossum391b4e61996-03-06 19:11:33 +0000380- Always check a script for syntax errors first, by doing something
381like "python script.py".
Guido van Rossum72755611996-03-06 07:20:06 +0000382
383- When using any of the debugging techniques, don't forget to add
384"import sys" to the top of the script.
385
Guido van Rossum391b4e61996-03-06 19:11:33 +0000386- When invoking external programs, make sure they can be found.
387Usually, this means using absolute path names -- $PATH is usually not
388set to a very useful value in a CGI script.
Guido van Rossum72755611996-03-06 07:20:06 +0000389
Guido van Rossum391b4e61996-03-06 19:11:33 +0000390- When reading or writing external files, make sure they can be read
391or written by every user on the system.
Guido van Rossum72755611996-03-06 07:20:06 +0000392
Guido van Rossum391b4e61996-03-06 19:11:33 +0000393- Don't try to give a CGI script a set-uid mode. This doesn't work on
394most systems, and is a security liability as well.
Guido van Rossum72755611996-03-06 07:20:06 +0000395
396
397History
398-------
399
Guido van Rossum391b4e61996-03-06 19:11:33 +0000400Michael McLay started this module. Steve Majewski changed the
401interface to SvFormContentDict and FormContentDict. The multipart
402parsing was inspired by code submitted by Andreas Paepcke. Guido van
403Rossum rewrote, reformatted and documented the module and is currently
404responsible for its maintenance.
Guido van Rossum72755611996-03-06 07:20:06 +0000405
Guido van Rossum0147db01996-03-09 03:16:04 +0000406
407XXX The module is getting pretty heavy with all those docstrings.
408Perhaps there should be a slimmed version that doesn't contain all those
409backwards compatible and debugging classes and functions?
410
Guido van Rossum72755611996-03-06 07:20:06 +0000411"""
412
Guido van Rossum9e3f4291996-08-26 15:46:13 +0000413# " <== Emacs font-lock de-bogo-kludgificocity
414
Guido van Rossume08c04c1996-11-11 19:29:11 +0000415__version__ = "2.1"
Guido van Rossum0147db01996-03-09 03:16:04 +0000416
Guido van Rossum72755611996-03-06 07:20:06 +0000417
418# Imports
419# =======
420
421import string
Guido van Rossum72755611996-03-06 07:20:06 +0000422import sys
423import os
Guido van Rossum72755611996-03-06 07:20:06 +0000424
Guido van Rossumc204c701996-09-05 19:07:11 +0000425
426# Logging support
427# ===============
428
429logfile = "" # Filename to log to, if not empty
430logfp = None # File object to log to, if not None
431
432def initlog(*allargs):
433 """Write a log message, if there is a log file.
434
435 Even though this function is called initlog(), you should always
436 use log(); log is a variable that is set either to initlog
437 (initially), to dolog (once the log file has been opened), or to
438 nolog (when logging is disabled).
439
440 The first argument is a format string; the remaining arguments (if
441 any) are arguments to the % operator, so e.g.
442 log("%s: %s", "a", "b")
443 will write "a: b" to the log file, followed by a newline.
444
445 If the global logfp is not None, it should be a file object to
446 which log data is written.
447
448 If the global logfp is None, the global logfile may be a string
449 giving a filename to open, in append mode. This file should be
450 world writable!!! If the file can't be opened, logging is
451 silently disabled (since there is no safe place where we could
452 send an error message).
453
454 """
455 global logfp, log
456 if logfile and not logfp:
457 try:
458 logfp = open(logfile, "a")
459 except IOError:
460 pass
461 if not logfp:
462 log = nolog
463 else:
464 log = dolog
465 apply(log, allargs)
466
467def dolog(fmt, *args):
468 """Write a log message to the log file. See initlog() for docs."""
469 logfp.write(fmt%args + "\n")
470
471def nolog(*allargs):
472 """Dummy function, assigned to log when logging is disabled."""
473 pass
474
475log = initlog # The current logging function
476
477
Guido van Rossum72755611996-03-06 07:20:06 +0000478# Parsing functions
479# =================
480
Guido van Rossume08c04c1996-11-11 19:29:11 +0000481def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum773ab271996-07-23 03:46:24 +0000482 """Parse a query in the environment or from a file (default stdin)
483
484 Arguments, all optional:
485
486 fp : file pointer; default: sys.stdin
487
488 environ : environment dictionary; default: os.environ
489
490 keep_blank_values: flag indicating whether blank values in
491 URL encoded forms should be treated as blank strings.
492 A true value inicates that blanks should be retained as
493 blank strings. The default false value indicates that
494 blank values are to be ignored and treated as if they were
495 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000496
497 strict_parsing: flag indicating what to do with parsing errors.
498 If false (the default), errors are silently ignored.
499 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000500 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000501 if not fp:
502 fp = sys.stdin
503 if not environ.has_key('REQUEST_METHOD'):
504 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
505 if environ['REQUEST_METHOD'] == 'POST':
506 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
507 if ctype == 'multipart/form-data':
Guido van Rossum0147db01996-03-09 03:16:04 +0000508 return parse_multipart(fp, pdict)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000509 elif ctype == 'application/x-www-form-urlencoded':
510 clength = string.atoi(environ['CONTENT_LENGTH'])
511 qs = fp.read(clength)
Guido van Rossum1c9daa81995-09-18 21:52:37 +0000512 else:
Guido van Rossum0147db01996-03-09 03:16:04 +0000513 qs = '' # Unknown content-type
Guido van Rossumafb5e931996-08-08 18:42:12 +0000514 if environ.has_key('QUERY_STRING'):
515 if qs: qs = qs + '&'
516 qs = qs + environ['QUERY_STRING']
517 elif sys.argv[1:]:
518 if qs: qs = qs + '&'
519 qs = qs + sys.argv[1]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000520 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
521 elif environ.has_key('QUERY_STRING'):
522 qs = environ['QUERY_STRING']
523 else:
524 if sys.argv[1:]:
525 qs = sys.argv[1]
526 else:
527 qs = ""
528 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossume08c04c1996-11-11 19:29:11 +0000529 return parse_qs(qs, keep_blank_values, strict_parsing)
Guido van Rossume7808771995-08-07 20:12:09 +0000530
531
Guido van Rossume08c04c1996-11-11 19:29:11 +0000532def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
533 """Parse a query given as a string argument.
Guido van Rossum773ab271996-07-23 03:46:24 +0000534
535 Arguments:
536
Guido van Rossume08c04c1996-11-11 19:29:11 +0000537 qs: URL-encoded query string to be parsed
Guido van Rossum773ab271996-07-23 03:46:24 +0000538
539 keep_blank_values: flag indicating whether blank values in
540 URL encoded queries should be treated as blank strings.
541 A true value inicates that blanks should be retained as
542 blank strings. The default false value indicates that
543 blank values are to be ignored and treated as if they were
544 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000545
546 strict_parsing: flag indicating what to do with parsing errors.
547 If false (the default), errors are silently ignored.
548 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000549 """
Guido van Rossum0147db01996-03-09 03:16:04 +0000550 import urllib, regsub
Guido van Rossum7aee3841996-03-07 18:00:44 +0000551 name_value_pairs = string.splitfields(qs, '&')
552 dict = {}
553 for name_value in name_value_pairs:
554 nv = string.splitfields(name_value, '=')
555 if len(nv) != 2:
Guido van Rossume08c04c1996-11-11 19:29:11 +0000556 if strict_parsing:
557 raise ValueError, "bad query field: %s" % `name_value`
Guido van Rossum7aee3841996-03-07 18:00:44 +0000558 continue
559 name = nv[0]
560 value = urllib.unquote(regsub.gsub('+', ' ', nv[1]))
Guido van Rossum773ab271996-07-23 03:46:24 +0000561 if len(value) or keep_blank_values:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000562 if dict.has_key (name):
563 dict[name].append(value)
564 else:
565 dict[name] = [value]
566 return dict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000567
568
Guido van Rossum0147db01996-03-09 03:16:04 +0000569def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000570 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000571
Guido van Rossum7aee3841996-03-07 18:00:44 +0000572 Arguments:
573 fp : input file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000574 pdict: dictionary containing other parameters of conten-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000575
Guido van Rossum0147db01996-03-09 03:16:04 +0000576 Returns a dictionary just like parse_qs(): keys are the field names, each
577 value is a list of values for that field. This is easy to use but not
578 much good if you are expecting megabytes to be uploaded -- in that case,
579 use the FieldStorage class instead which is much more flexible. Note
580 that content-type is the raw, unparsed contents of the content-type
581 header.
582
583 XXX This does not parse nested multipart parts -- use FieldStorage for
584 that.
585
586 XXX This should really be subsumed by FieldStorage altogether -- no
587 point in having two implementations of the same parsing algorithm.
Guido van Rossum72755611996-03-06 07:20:06 +0000588
Guido van Rossum7aee3841996-03-07 18:00:44 +0000589 """
590 import mimetools
591 if pdict.has_key('boundary'):
592 boundary = pdict['boundary']
593 else:
594 boundary = ""
595 nextpart = "--" + boundary
596 lastpart = "--" + boundary + "--"
597 partdict = {}
598 terminator = ""
599
600 while terminator != lastpart:
601 bytes = -1
602 data = None
603 if terminator:
604 # At start of next part. Read headers first.
605 headers = mimetools.Message(fp)
606 clength = headers.getheader('content-length')
607 if clength:
608 try:
609 bytes = string.atoi(clength)
610 except string.atoi_error:
611 pass
612 if bytes > 0:
613 data = fp.read(bytes)
614 else:
615 data = ""
616 # Read lines until end of part.
617 lines = []
618 while 1:
619 line = fp.readline()
620 if not line:
621 terminator = lastpart # End outer loop
622 break
623 if line[:2] == "--":
624 terminator = string.strip(line)
625 if terminator in (nextpart, lastpart):
626 break
Guido van Rossum7aee3841996-03-07 18:00:44 +0000627 lines.append(line)
628 # Done with part.
629 if data is None:
630 continue
631 if bytes < 0:
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000632 if lines:
633 # Strip final line terminator
634 line = lines[-1]
635 if line[-2:] == "\r\n":
636 line = line[:-2]
637 elif line[-1:] == "\n":
638 line = line[:-1]
639 lines[-1] = line
640 data = string.joinfields(lines, "")
Guido van Rossum7aee3841996-03-07 18:00:44 +0000641 line = headers['content-disposition']
642 if not line:
643 continue
644 key, params = parse_header(line)
645 if key != 'form-data':
646 continue
647 if params.has_key('name'):
648 name = params['name']
Guido van Rossum72755611996-03-06 07:20:06 +0000649 else:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000650 continue
Guido van Rossum7aee3841996-03-07 18:00:44 +0000651 if partdict.has_key(name):
652 partdict[name].append(data)
653 else:
654 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000655
Guido van Rossum7aee3841996-03-07 18:00:44 +0000656 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000657
658
Guido van Rossum72755611996-03-06 07:20:06 +0000659def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000660 """Parse a Content-type like header.
661
662 Return the main content-type and a dictionary of options.
663
664 """
665 plist = map(string.strip, string.splitfields(line, ';'))
666 key = string.lower(plist[0])
667 del plist[0]
668 pdict = {}
669 for p in plist:
670 i = string.find(p, '=')
671 if i >= 0:
672 name = string.lower(string.strip(p[:i]))
673 value = string.strip(p[i+1:])
674 if len(value) >= 2 and value[0] == value[-1] == '"':
675 value = value[1:-1]
676 pdict[name] = value
677 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000678
679
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000680# Classes for field storage
681# =========================
682
683class MiniFieldStorage:
684
Guido van Rossum0147db01996-03-09 03:16:04 +0000685 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000686
Guido van Rossum7aee3841996-03-07 18:00:44 +0000687 # Dummy attributes
688 filename = None
689 list = None
690 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000691 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000692 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000693 disposition = None
694 disposition_options = {}
695 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000696
Guido van Rossum7aee3841996-03-07 18:00:44 +0000697 def __init__(self, name, value):
698 """Constructor from field name and value."""
699 from StringIO import StringIO
700 self.name = name
701 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000702 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000703
704 def __repr__(self):
705 """Return printable representation."""
706 return "MiniFieldStorage(%s, %s)" % (`self.name`, `self.value`)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000707
708
709class FieldStorage:
710
Guido van Rossum7aee3841996-03-07 18:00:44 +0000711 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000712
Guido van Rossum7aee3841996-03-07 18:00:44 +0000713 This class provides naming, typing, files stored on disk, and
714 more. At the top level, it is accessible like a dictionary, whose
715 keys are the field names. (Note: None can occur as a field name.)
716 The items are either a Python list (if there's multiple values) or
717 another FieldStorage or MiniFieldStorage object. If it's a single
718 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000719
Guido van Rossum7aee3841996-03-07 18:00:44 +0000720 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000721
Guido van Rossum7aee3841996-03-07 18:00:44 +0000722 filename: the filename, if specified; otherwise None; this is the
723 client side filename, *not* the file name on which it is
Guido van Rossum0147db01996-03-09 03:16:04 +0000724 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000725
Guido van Rossum7aee3841996-03-07 18:00:44 +0000726 value: the value as a *string*; for file uploads, this
727 transparently reads the file every time you request the value
728
729 file: the file(-like) object from which you can read the data;
730 None if the data is stored a simple string
731
732 type: the content-type, or None if not specified
733
734 type_options: dictionary of options specified on the content-type
735 line
736
737 disposition: content-disposition, or None if not specified
738
739 disposition_options: dictionary of corresponding options
740
741 headers: a dictionary(-like) object (sometimes rfc822.Message or a
742 subclass thereof) containing *all* headers
743
744 The class is subclassable, mostly for the purpose of overriding
745 the make_file() method, which is called internally to come up with
746 a file open for reading and writing. This makes it possible to
747 override the default choice of storing all files in a temporary
748 directory and unlinking them as soon as they have been opened.
749
750 """
751
Guido van Rossum773ab271996-07-23 03:46:24 +0000752 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossume08c04c1996-11-11 19:29:11 +0000753 environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000754 """Constructor. Read multipart/* until last part.
755
756 Arguments, all optional:
757
758 fp : file pointer; default: sys.stdin
759
760 headers : header dictionary-like object; default:
761 taken from environ as per CGI spec
762
Guido van Rossum773ab271996-07-23 03:46:24 +0000763 outerboundary : terminating multipart boundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000764 (for internal use only)
765
Guido van Rossum773ab271996-07-23 03:46:24 +0000766 environ : environment dictionary; default: os.environ
767
768 keep_blank_values: flag indicating whether blank values in
769 URL encoded forms should be treated as blank strings.
770 A true value inicates that blanks should be retained as
771 blank strings. The default false value indicates that
772 blank values are to be ignored and treated as if they were
773 not included.
774
Guido van Rossume08c04c1996-11-11 19:29:11 +0000775 strict_parsing: flag indicating what to do with parsing errors.
776 If false (the default), errors are silently ignored.
777 If true, errors raise a ValueError exception.
778
Guido van Rossum7aee3841996-03-07 18:00:44 +0000779 """
780 method = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000781 self.keep_blank_values = keep_blank_values
Guido van Rossume08c04c1996-11-11 19:29:11 +0000782 self.strict_parsing = strict_parsing
Guido van Rossum7aee3841996-03-07 18:00:44 +0000783 if environ.has_key('REQUEST_METHOD'):
784 method = string.upper(environ['REQUEST_METHOD'])
785 if not fp and method == 'GET':
786 qs = None
787 if environ.has_key('QUERY_STRING'):
788 qs = environ['QUERY_STRING']
789 from StringIO import StringIO
790 fp = StringIO(qs or "")
791 if headers is None:
792 headers = {'content-type':
793 "application/x-www-form-urlencoded"}
794 if headers is None:
795 headers = {}
796 if environ.has_key('CONTENT_TYPE'):
797 headers['content-type'] = environ['CONTENT_TYPE']
798 if environ.has_key('CONTENT_LENGTH'):
799 headers['content-length'] = environ['CONTENT_LENGTH']
800 self.fp = fp or sys.stdin
801 self.headers = headers
802 self.outerboundary = outerboundary
803
804 # Process content-disposition header
805 cdisp, pdict = "", {}
806 if self.headers.has_key('content-disposition'):
807 cdisp, pdict = parse_header(self.headers['content-disposition'])
808 self.disposition = cdisp
809 self.disposition_options = pdict
810 self.name = None
811 if pdict.has_key('name'):
812 self.name = pdict['name']
813 self.filename = None
814 if pdict.has_key('filename'):
815 self.filename = pdict['filename']
816
817 # Process content-type header
818 ctype, pdict = "text/plain", {}
819 if self.headers.has_key('content-type'):
820 ctype, pdict = parse_header(self.headers['content-type'])
821 self.type = ctype
822 self.type_options = pdict
823 self.innerboundary = ""
824 if pdict.has_key('boundary'):
825 self.innerboundary = pdict['boundary']
826 clen = -1
827 if self.headers.has_key('content-length'):
828 try:
829 clen = string.atoi(self.headers['content-length'])
830 except:
831 pass
832 self.length = clen
833
834 self.list = self.file = None
835 self.done = 0
836 self.lines = []
837 if ctype == 'application/x-www-form-urlencoded':
838 self.read_urlencoded()
839 elif ctype[:10] == 'multipart/':
840 self.read_multi()
841 else:
842 self.read_single()
843
844 def __repr__(self):
845 """Return a printable representation."""
846 return "FieldStorage(%s, %s, %s)" % (
847 `self.name`, `self.filename`, `self.value`)
848
849 def __getattr__(self, name):
850 if name != 'value':
851 raise AttributeError, name
852 if self.file:
853 self.file.seek(0)
854 value = self.file.read()
855 self.file.seek(0)
856 elif self.list is not None:
857 value = self.list
858 else:
859 value = None
860 return value
861
862 def __getitem__(self, key):
863 """Dictionary style indexing."""
864 if self.list is None:
865 raise TypeError, "not indexable"
866 found = []
867 for item in self.list:
868 if item.name == key: found.append(item)
869 if not found:
870 raise KeyError, key
Guido van Rossum0147db01996-03-09 03:16:04 +0000871 if len(found) == 1:
872 return found[0]
873 else:
874 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000875
876 def keys(self):
877 """Dictionary style keys() method."""
878 if self.list is None:
879 raise TypeError, "not indexable"
880 keys = []
881 for item in self.list:
882 if item.name not in keys: keys.append(item.name)
883 return keys
884
Guido van Rossum0147db01996-03-09 03:16:04 +0000885 def has_key(self, key):
886 """Dictionary style has_key() method."""
887 if self.list is None:
888 raise TypeError, "not indexable"
889 for item in self.list:
890 if item.name == key: return 1
891 return 0
892
Guido van Rossum7aee3841996-03-07 18:00:44 +0000893 def read_urlencoded(self):
894 """Internal: read data in query string format."""
895 qs = self.fp.read(self.length)
Guido van Rossume08c04c1996-11-11 19:29:11 +0000896 dict = parse_qs(qs, self.keep_blank_values, self.strict_parsing)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000897 self.list = []
898 for key, valuelist in dict.items():
899 for value in valuelist:
900 self.list.append(MiniFieldStorage(key, value))
901 self.skip_lines()
902
903 def read_multi(self):
904 """Internal: read a part that is itself multipart."""
905 import rfc822
906 self.list = []
907 part = self.__class__(self.fp, {}, self.innerboundary)
908 # Throw first part away
909 while not part.done:
910 headers = rfc822.Message(self.fp)
911 part = self.__class__(self.fp, headers, self.innerboundary)
912 self.list.append(part)
913 self.skip_lines()
914
915 def read_single(self):
916 """Internal: read an atomic part."""
917 if self.length >= 0:
918 self.read_binary()
919 self.skip_lines()
920 else:
921 self.read_lines()
922 self.file.seek(0)
923
924 bufsize = 8*1024 # I/O buffering size for copy to file
925
926 def read_binary(self):
927 """Internal: read binary data."""
928 self.file = self.make_file('b')
929 todo = self.length
930 if todo >= 0:
931 while todo > 0:
932 data = self.fp.read(min(todo, self.bufsize))
933 if not data:
934 self.done = -1
935 break
936 self.file.write(data)
937 todo = todo - len(data)
938
939 def read_lines(self):
940 """Internal: read lines until EOF or outerboundary."""
941 self.file = self.make_file('')
942 if self.outerboundary:
943 self.read_lines_to_outerboundary()
944 else:
945 self.read_lines_to_eof()
946
947 def read_lines_to_eof(self):
948 """Internal: read lines until EOF."""
949 while 1:
950 line = self.fp.readline()
951 if not line:
952 self.done = -1
953 break
954 self.lines.append(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000955 self.file.write(line)
956
957 def read_lines_to_outerboundary(self):
958 """Internal: read lines until outerboundary."""
959 next = "--" + self.outerboundary
960 last = next + "--"
961 delim = ""
962 while 1:
963 line = self.fp.readline()
964 if not line:
965 self.done = -1
966 break
967 self.lines.append(line)
968 if line[:2] == "--":
969 strippedline = string.strip(line)
970 if strippedline == next:
971 break
972 if strippedline == last:
973 self.done = 1
974 break
Guido van Rossume5e46e01996-09-05 19:03:36 +0000975 odelim = delim
Guido van Rossum7aee3841996-03-07 18:00:44 +0000976 if line[-2:] == "\r\n":
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000977 delim = "\r\n"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000978 line = line[:-2]
979 elif line[-1] == "\n":
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000980 delim = "\n"
Guido van Rossum7aee3841996-03-07 18:00:44 +0000981 line = line[:-1]
Guido van Rossum99aa2a41996-07-23 17:27:05 +0000982 else:
983 delim = ""
Guido van Rossume5e46e01996-09-05 19:03:36 +0000984 self.file.write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000985
986 def skip_lines(self):
987 """Internal: skip lines until outer boundary if defined."""
988 if not self.outerboundary or self.done:
989 return
990 next = "--" + self.outerboundary
991 last = next + "--"
992 while 1:
993 line = self.fp.readline()
994 if not line:
995 self.done = -1
996 break
997 self.lines.append(line)
998 if line[:2] == "--":
999 strippedline = string.strip(line)
1000 if strippedline == next:
1001 break
1002 if strippedline == last:
1003 self.done = 1
1004 break
1005
1006 def make_file(self, binary):
1007 """Overridable: return a readable & writable file.
1008
1009 The file will be used as follows:
1010 - data is written to it
1011 - seek(0)
1012 - data is read from it
1013
1014 The 'binary' argument is 'b' if the file should be created in
1015 binary mode (on non-Unix systems), '' otherwise.
1016
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001017 This version opens a temporary file for reading and writing,
1018 and immediately deletes (unlinks) it. The trick (on Unix!) is
1019 that the file can still be used, but it can't be opened by
1020 another process, and it will automatically be deleted when it
1021 is closed or when the current process terminates.
1022
1023 If you want a more permanent file, you derive a class which
1024 overrides this method. If you want a visible temporary file
1025 that is nevertheless automatically deleted when the script
1026 terminates, try defining a __del__ method in a derived class
1027 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +00001028
1029 """
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001030 import tempfile
1031 tfn = tempfile.mktemp()
1032 f = open(tfn, "w%s+" % binary)
1033 os.unlink(tfn)
1034 return f
Guido van Rossum243ddcd1996-03-07 06:33:07 +00001035
1036
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001037# Backwards Compatibility Classes
1038# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +00001039
1040class FormContentDict:
Guido van Rossum7aee3841996-03-07 18:00:44 +00001041 """Basic (multiple values per field) form content as dictionary.
Guido van Rossum72755611996-03-06 07:20:06 +00001042
Guido van Rossum7aee3841996-03-07 18:00:44 +00001043 form = FormContentDict()
1044
1045 form[key] -> [value, value, ...]
1046 form.has_key(key) -> Boolean
1047 form.keys() -> [key, key, ...]
1048 form.values() -> [[val, val, ...], [val, val, ...], ...]
1049 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
1050 form.dict == {key: [val, val, ...], ...}
1051
1052 """
Guido van Rossum773ab271996-07-23 03:46:24 +00001053 def __init__(self, environ=os.environ):
Guido van Rossumafb5e931996-08-08 18:42:12 +00001054 self.dict = parse(environ=environ)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001055 self.query_string = environ['QUERY_STRING']
1056 def __getitem__(self,key):
1057 return self.dict[key]
1058 def keys(self):
1059 return self.dict.keys()
1060 def has_key(self, key):
1061 return self.dict.has_key(key)
1062 def values(self):
1063 return self.dict.values()
1064 def items(self):
1065 return self.dict.items()
1066 def __len__( self ):
1067 return len(self.dict)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001068
1069
Guido van Rossum9a22de11995-01-12 12:29:47 +00001070class SvFormContentDict(FormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001071 """Strict single-value expecting form content as dictionary.
1072
1073 IF you only expect a single value for each field, then form[key]
1074 will return that single value. It will raise an IndexError if
1075 that expectation is not true. IF you expect a field to have
1076 possible multiple values, than you can use form.getlist(key) to
1077 get all of the values. values() and items() are a compromise:
1078 they return single strings where there is a single value, and
1079 lists of strings otherwise.
1080
1081 """
1082 def __getitem__(self, key):
1083 if len(self.dict[key]) > 1:
1084 raise IndexError, 'expecting a single value'
1085 return self.dict[key][0]
1086 def getlist(self, key):
1087 return self.dict[key]
1088 def values(self):
1089 lis = []
1090 for each in self.dict.values():
1091 if len( each ) == 1 :
1092 lis.append(each[0])
1093 else: lis.append(each)
1094 return lis
1095 def items(self):
1096 lis = []
1097 for key,value in self.dict.items():
1098 if len(value) == 1 :
1099 lis.append((key, value[0]))
1100 else: lis.append((key, value))
1101 return lis
Guido van Rossum9a22de11995-01-12 12:29:47 +00001102
1103
Guido van Rossum9a22de11995-01-12 12:29:47 +00001104class InterpFormContentDict(SvFormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001105 """This class is present for backwards compatibility only."""
1106 def __getitem__( self, key ):
1107 v = SvFormContentDict.__getitem__( self, key )
1108 if v[0] in string.digits+'+-.' :
1109 try: return string.atoi( v )
1110 except ValueError:
1111 try: return string.atof( v )
1112 except ValueError: pass
1113 return string.strip(v)
1114 def values( self ):
1115 lis = []
1116 for key in self.keys():
1117 try:
1118 lis.append( self[key] )
1119 except IndexError:
1120 lis.append( self.dict[key] )
1121 return lis
1122 def items( self ):
1123 lis = []
1124 for key in self.keys():
1125 try:
1126 lis.append( (key, self[key]) )
1127 except IndexError:
1128 lis.append( (key, self.dict[key]) )
1129 return lis
Guido van Rossum9a22de11995-01-12 12:29:47 +00001130
1131
Guido van Rossum9a22de11995-01-12 12:29:47 +00001132class FormContent(FormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001133 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +00001134 def values(self, key):
1135 if self.dict.has_key(key) :return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +00001136 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001137 def indexed_value(self, key, location):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001138 if self.dict.has_key(key):
1139 if len (self.dict[key]) > location:
1140 return self.dict[key][location]
1141 else: return None
1142 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001143 def value(self, key):
1144 if self.dict.has_key(key): return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +00001145 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001146 def length(self, key):
1147 return len(self.dict[key])
1148 def stripped(self, key):
1149 if self.dict.has_key(key): return string.strip(self.dict[key][0])
Guido van Rossum7aee3841996-03-07 18:00:44 +00001150 else: return None
1151 def pars(self):
1152 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +00001153
1154
Guido van Rossum72755611996-03-06 07:20:06 +00001155# Test/debug code
1156# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +00001157
Guido van Rossum773ab271996-07-23 03:46:24 +00001158def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001159 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +00001160
Guido van Rossum7aee3841996-03-07 18:00:44 +00001161 Write minimal HTTP headers and dump all information provided to
1162 the script in HTML form.
1163
1164 """
1165 import traceback
1166 print "Content-type: text/html"
1167 print
1168 sys.stderr = sys.stdout
1169 try:
Guido van Rossum0147db01996-03-09 03:16:04 +00001170 form = FieldStorage() # Replace with other classes to test those
1171 print_form(form)
Guido van Rossum773ab271996-07-23 03:46:24 +00001172 print_environ(environ)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001173 print_directory()
Guido van Rossuma8738a51996-03-14 21:30:28 +00001174 print_arguments()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001175 print_environ_usage()
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001176 def f():
1177 exec "testing print_exception() -- <I>italics?</I>"
1178 def g(f=f):
1179 f()
1180 print "<H3>What follows is a test, not an actual exception:</H3>"
1181 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001182 except:
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001183 print_exception()
1184
1185def print_exception(type=None, value=None, tb=None, limit=None):
1186 if type is None:
1187 type, value, tb = sys.exc_type, sys.exc_value, sys.exc_traceback
1188 import traceback
1189 print
1190 print "<H3>Traceback (innermost last):</H3>"
1191 list = traceback.format_tb(tb, limit) + \
1192 traceback.format_exception_only(type, value)
1193 print "<PRE>%s<B>%s</B></PRE>" % (
1194 escape(string.join(list[:-1], "")),
1195 escape(list[-1]),
1196 )
Guido van Rossum9a22de11995-01-12 12:29:47 +00001197
Guido van Rossum773ab271996-07-23 03:46:24 +00001198def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001199 """Dump the shell environment as HTML."""
1200 keys = environ.keys()
1201 keys.sort()
1202 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001203 print "<H3>Shell Environment:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +00001204 print "<DL>"
1205 for key in keys:
1206 print "<DT>", escape(key), "<DD>", escape(environ[key])
1207 print "</DL>"
1208 print
Guido van Rossum72755611996-03-06 07:20:06 +00001209
1210def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001211 """Dump the contents of a form as HTML."""
1212 keys = form.keys()
1213 keys.sort()
1214 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001215 print "<H3>Form Contents:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +00001216 print "<DL>"
1217 for key in keys:
1218 print "<DT>" + escape(key) + ":",
1219 value = form[key]
1220 print "<i>" + escape(`type(value)`) + "</i>"
1221 print "<DD>" + escape(`value`)
1222 print "</DL>"
1223 print
1224
1225def print_directory():
1226 """Dump the current directory as HTML."""
1227 print
1228 print "<H3>Current Working Directory:</H3>"
1229 try:
1230 pwd = os.getcwd()
1231 except os.error, msg:
1232 print "os.error:", escape(str(msg))
1233 else:
1234 print escape(pwd)
1235 print
Guido van Rossum9a22de11995-01-12 12:29:47 +00001236
Guido van Rossuma8738a51996-03-14 21:30:28 +00001237def print_arguments():
1238 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001239 print "<H3>Command Line Arguments:</H3>"
Guido van Rossuma8738a51996-03-14 21:30:28 +00001240 print
1241 print sys.argv
1242 print
1243
Guido van Rossum9a22de11995-01-12 12:29:47 +00001244def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +00001245 """Dump a list of environment variables used by CGI as HTML."""
1246 print """
Guido van Rossum72755611996-03-06 07:20:06 +00001247<H3>These environment variables could have been set:</H3>
1248<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001249<LI>AUTH_TYPE
1250<LI>CONTENT_LENGTH
1251<LI>CONTENT_TYPE
1252<LI>DATE_GMT
1253<LI>DATE_LOCAL
1254<LI>DOCUMENT_NAME
1255<LI>DOCUMENT_ROOT
1256<LI>DOCUMENT_URI
1257<LI>GATEWAY_INTERFACE
1258<LI>LAST_MODIFIED
1259<LI>PATH
1260<LI>PATH_INFO
1261<LI>PATH_TRANSLATED
1262<LI>QUERY_STRING
1263<LI>REMOTE_ADDR
1264<LI>REMOTE_HOST
1265<LI>REMOTE_IDENT
1266<LI>REMOTE_USER
1267<LI>REQUEST_METHOD
1268<LI>SCRIPT_NAME
1269<LI>SERVER_NAME
1270<LI>SERVER_PORT
1271<LI>SERVER_PROTOCOL
1272<LI>SERVER_ROOT
1273<LI>SERVER_SOFTWARE
1274</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001275In addition, HTTP headers sent by the server may be passed in the
1276environment as well. Here are some common variable names:
1277<UL>
1278<LI>HTTP_ACCEPT
1279<LI>HTTP_CONNECTION
1280<LI>HTTP_HOST
1281<LI>HTTP_PRAGMA
1282<LI>HTTP_REFERER
1283<LI>HTTP_USER_AGENT
1284</UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001285"""
1286
Guido van Rossum9a22de11995-01-12 12:29:47 +00001287
Guido van Rossum72755611996-03-06 07:20:06 +00001288# Utilities
1289# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001290
Guido van Rossum72755611996-03-06 07:20:06 +00001291def escape(s):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001292 """Replace special characters '&', '<' and '>' by SGML entities."""
Guido van Rossum0147db01996-03-09 03:16:04 +00001293 import regsub
Guido van Rossum7aee3841996-03-07 18:00:44 +00001294 s = regsub.gsub("&", "&amp;", s) # Must be done first!
1295 s = regsub.gsub("<", "&lt;", s)
1296 s = regsub.gsub(">", "&gt;", s)
1297 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001298
Guido van Rossum9a22de11995-01-12 12:29:47 +00001299
Guido van Rossum72755611996-03-06 07:20:06 +00001300# Invoke mainline
1301# ===============
1302
1303# Call test() when this file is run as a script (not imported as a module)
1304if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001305 test()