blob: 4eaa983e4d136b25345871f46d2be2c310da2eff [file] [log] [blame]
Guido van Rossum152f9d91997-02-18 16:55:33 +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 Rossum45e2fbc1998-03-26 21:13:24 +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
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000042 print "<TITLE>CGI script output</TITLE>"
43 print "<H1>This is my first CGI script</H1>"
44 print "Hello, world!"
Guido van Rossum72755611996-03-06 07:20:06 +000045
Guido van Rossum43055421997-05-28 15:11:01 +000046It 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 Rossum45e2fbc1998-03-26 21:13:24 +000069 form = cgi.FieldStorage()
70 form_ok = 0
71 if form.has_key("name") and form.has_key("addr"):
72 if form["name"].value != "" and form["addr"].value != "":
73 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
78 ...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
Guido van Rossum43055421997-05-28 15:11:01 +000085instance but a list of such instances. If you are expecting this
86possibility (i.e., when your HTML form comtains multiple fields with
87the same name), use the type() function to determine whether you have
88a single instance or a list of instances. For example, here's code
89that concatenates any number of username fields, separated by commas:
Guido van Rossum4032c2c1996-03-09 04:04:35 +000090
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000091 username = form["username"]
92 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
104 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
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000112 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
Guido van Rossum0147db01996-03-09 03:16:04 +0000120
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
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000166string (data of type application/x-www-form-urlencoded). Data are
167returned as a dictionary. The dictionary keys are the unique query
168variable names and the values are lists of vales for each name.
169
170parse_qsl(qs, [keep_blank_values, [strict_parsing]]): parse a query
171string (data of type application/x-www-form-urlencoded). Data are
172returned as a list of (name, value) pairs.
Guido van Rossum72755611996-03-06 07:20:06 +0000173
Guido van Rossum0147db01996-03-09 03:16:04 +0000174parse_multipart(fp, pdict): parse input of type multipart/form-data (for
Guido van Rossum391b4e61996-03-06 19:11:33 +0000175file uploads).
Guido van Rossum72755611996-03-06 07:20:06 +0000176
Guido van Rossum391b4e61996-03-06 19:11:33 +0000177parse_header(string): parse a header like Content-type into a main
178value and a dictionary of parameters.
Guido van Rossum72755611996-03-06 07:20:06 +0000179
180test(): complete test program.
181
182print_environ(): format the shell environment in HTML.
183
184print_form(form): format a form in HTML.
185
Guido van Rossum391b4e61996-03-06 19:11:33 +0000186print_environ_usage(): print a list of useful environment variables in
187HTML.
Guido van Rossum72755611996-03-06 07:20:06 +0000188
Guido van Rossum391b4e61996-03-06 19:11:33 +0000189escape(): convert the characters "&", "<" and ">" to HTML-safe
190sequences. Use this if you need to display text that might contain
191such characters in HTML. To translate URLs for inclusion in the HREF
192attribute of an <A> tag, use urllib.quote().
Guido van Rossum72755611996-03-06 07:20:06 +0000193
Guido van Rossumc204c701996-09-05 19:07:11 +0000194log(fmt, ...): write a line to a log file; see docs for initlog().
195
Guido van Rossum72755611996-03-06 07:20:06 +0000196
197Caring about security
198---------------------
199
Guido van Rossum391b4e61996-03-06 19:11:33 +0000200There's one important rule: if you invoke an external program (e.g.
201via the os.system() or os.popen() functions), make very sure you don't
202pass arbitrary strings received from the client to the shell. This is
203a well-known security hole whereby clever hackers anywhere on the web
204can exploit a gullible CGI script to invoke arbitrary shell commands.
205Even parts of the URL or field names cannot be trusted, since the
206request doesn't have to come from your form!
Guido van Rossum72755611996-03-06 07:20:06 +0000207
Guido van Rossum391b4e61996-03-06 19:11:33 +0000208To be on the safe side, if you must pass a string gotten from a form
209to a shell command, you should make sure the string contains only
210alphanumeric characters, dashes, underscores, and periods.
Guido van Rossum72755611996-03-06 07:20:06 +0000211
212
213Installing your CGI script on a Unix system
214-------------------------------------------
215
Guido van Rossum391b4e61996-03-06 19:11:33 +0000216Read the documentation for your HTTP server and check with your local
217system administrator to find the directory where CGI scripts should be
Guido van Rossum72755611996-03-06 07:20:06 +0000218installed; usually this is in a directory cgi-bin in the server tree.
219
Guido van Rossum391b4e61996-03-06 19:11:33 +0000220Make sure that your script is readable and executable by "others"; the
221Unix file mode should be 755 (use "chmod 755 filename"). Make sure
Guido van Rossum43055421997-05-28 15:11:01 +0000222that the first line of the script contains #! starting in column 1
Guido van Rossum391b4e61996-03-06 19:11:33 +0000223followed by the pathname of the Python interpreter, for instance:
Guido van Rossum72755611996-03-06 07:20:06 +0000224
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000225 #! /usr/local/bin/python
Guido van Rossum72755611996-03-06 07:20:06 +0000226
Guido van Rossum391b4e61996-03-06 19:11:33 +0000227Make sure the Python interpreter exists and is executable by "others".
Guido van Rossum72755611996-03-06 07:20:06 +0000228
Guido van Rossum43055421997-05-28 15:11:01 +0000229Note that it's probably not a good idea to use #! /usr/bin/env python
Guido van Rossumf06ee5f1996-11-27 19:52:01 +0000230here, since the Python interpreter may not be on the default path
Guido van Rossum43055421997-05-28 15:11:01 +0000231given to CGI scripts!!!
Guido van Rossumf06ee5f1996-11-27 19:52:01 +0000232
Guido van Rossum391b4e61996-03-06 19:11:33 +0000233Make sure that any files your script needs to read or write are
234readable or writable, respectively, by "others" -- their mode should
235be 644 for readable and 666 for writable. This is because, for
236security reasons, the HTTP server executes your script as user
237"nobody", without any special privileges. It can only read (write,
238execute) files that everybody can read (write, execute). The current
239directory at execution time is also different (it is usually the
240server's cgi-bin directory) and the set of environment variables is
241also different from what you get at login. in particular, don't count
242on the shell's search path for executables ($PATH) or the Python
243module search path ($PYTHONPATH) to be set to anything interesting.
Guido van Rossum72755611996-03-06 07:20:06 +0000244
Guido van Rossum391b4e61996-03-06 19:11:33 +0000245If you need to load modules from a directory which is not on Python's
246default module search path, you can change the path in your script,
247before importing other modules, e.g.:
Guido van Rossum72755611996-03-06 07:20:06 +0000248
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000249 import sys
250 sys.path.insert(0, "/usr/home/joe/lib/python")
251 sys.path.insert(0, "/usr/local/lib/python")
Guido van Rossum72755611996-03-06 07:20:06 +0000252
Guido van Rossum43055421997-05-28 15:11:01 +0000253This way, the directory inserted last will be searched first!
Guido van Rossum72755611996-03-06 07:20:06 +0000254
Guido van Rossum391b4e61996-03-06 19:11:33 +0000255Instructions for non-Unix systems will vary; check your HTTP server's
Guido van Rossum72755611996-03-06 07:20:06 +0000256documentation (it will usually have a section on CGI scripts).
257
258
259Testing your CGI script
260-----------------------
261
Guido van Rossum391b4e61996-03-06 19:11:33 +0000262Unfortunately, a CGI script will generally not run when you try it
263from the command line, and a script that works perfectly from the
264command line may fail mysteriously when run from the server. There's
265one reason why you should still test your script from the command
266line: if it contains a syntax error, the python interpreter won't
267execute it at all, and the HTTP server will most likely send a cryptic
268error to the client.
Guido van Rossum72755611996-03-06 07:20:06 +0000269
Guido van Rossum391b4e61996-03-06 19:11:33 +0000270Assuming your script has no syntax errors, yet it does not work, you
271have no choice but to read the next section:
Guido van Rossum72755611996-03-06 07:20:06 +0000272
273
274Debugging CGI scripts
275---------------------
276
Guido van Rossum391b4e61996-03-06 19:11:33 +0000277First of all, check for trivial installation errors -- reading the
278section above on installing your CGI script carefully can save you a
279lot of time. If you wonder whether you have understood the
280installation procedure correctly, try installing a copy of this module
281file (cgi.py) as a CGI script. When invoked as a script, the file
282will dump its environment and the contents of the form in HTML form.
283Give it the right mode etc, and send it a request. If it's installed
284in the standard cgi-bin directory, it should be possible to send it a
285request by entering a URL into your browser of the form:
Guido van Rossum72755611996-03-06 07:20:06 +0000286
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000287 http://yourhostname/cgi-bin/cgi.py?name=Joe+Blow&addr=At+Home
Guido van Rossum72755611996-03-06 07:20:06 +0000288
Guido van Rossum391b4e61996-03-06 19:11:33 +0000289If this gives an error of type 404, the server cannot find the script
290-- perhaps you need to install it in a different directory. If it
291gives another error (e.g. 500), there's an installation problem that
292you should fix before trying to go any further. If you get a nicely
293formatted listing of the environment and form content (in this
294example, the fields should be listed as "addr" with value "At Home"
295and "name" with value "Joe Blow"), the cgi.py script has been
296installed correctly. If you follow the same procedure for your own
297script, you should now be able to debug it.
Guido van Rossum72755611996-03-06 07:20:06 +0000298
Guido van Rossum391b4e61996-03-06 19:11:33 +0000299The next step could be to call the cgi module's test() function from
300your script: replace its main code with the single statement
Guido van Rossum72755611996-03-06 07:20:06 +0000301
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000302 cgi.test()
303
Guido van Rossum391b4e61996-03-06 19:11:33 +0000304This should produce the same results as those gotten from installing
305the cgi.py file itself.
Guido van Rossum72755611996-03-06 07:20:06 +0000306
Guido van Rossum43055421997-05-28 15:11:01 +0000307When an ordinary Python script raises an unhandled exception (e.g.,
308because of a typo in a module name, a file that can't be opened,
Guido van Rossum391b4e61996-03-06 19:11:33 +0000309etc.), the Python interpreter prints a nice traceback and exits.
310While the Python interpreter will still do this when your CGI script
311raises an exception, most likely the traceback will end up in one of
312the HTTP server's log file, or be discarded altogether.
Guido van Rossum72755611996-03-06 07:20:06 +0000313
Guido van Rossum391b4e61996-03-06 19:11:33 +0000314Fortunately, once you have managed to get your script to execute
315*some* code, it is easy to catch exceptions and cause a traceback to
316be printed. The test() function below in this module is an example.
317Here are the rules:
Guido van Rossum72755611996-03-06 07:20:06 +0000318
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000319 1. Import the traceback module (before entering the
320 try-except!)
321
322 2. Make sure you finish printing the headers and the blank
323 line early
324
325 3. Assign sys.stderr to sys.stdout
326
327 3. Wrap all remaining code in a try-except statement
328
329 4. In the except clause, call traceback.print_exc()
Guido van Rossum72755611996-03-06 07:20:06 +0000330
331For example:
332
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000333 import sys
334 import traceback
335 print "Content-type: text/html"
336 print
337 sys.stderr = sys.stdout
338 try:
339 ...your code here...
340 except:
341 print "\n\n<PRE>"
342 traceback.print_exc()
Guido van Rossum72755611996-03-06 07:20:06 +0000343
Guido van Rossum391b4e61996-03-06 19:11:33 +0000344Notes: The assignment to sys.stderr is needed because the traceback
345prints to sys.stderr. The print "\n\n<PRE>" statement is necessary to
346disable the word wrapping in HTML.
Guido van Rossum72755611996-03-06 07:20:06 +0000347
Guido van Rossum391b4e61996-03-06 19:11:33 +0000348If you suspect that there may be a problem in importing the traceback
349module, you can use an even more robust approach (which only uses
350built-in modules):
Guido van Rossum72755611996-03-06 07:20:06 +0000351
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000352 import sys
353 sys.stderr = sys.stdout
354 print "Content-type: text/plain"
355 print
356 ...your code here...
Guido van Rossum72755611996-03-06 07:20:06 +0000357
Guido van Rossum391b4e61996-03-06 19:11:33 +0000358This relies on the Python interpreter to print the traceback. The
359content type of the output is set to plain text, which disables all
360HTML processing. If your script works, the raw HTML will be displayed
361by your client. If it raises an exception, most likely after the
362first two lines have been printed, a traceback will be displayed.
363Because no HTML interpretation is going on, the traceback will
364readable.
Guido van Rossum72755611996-03-06 07:20:06 +0000365
Guido van Rossumc204c701996-09-05 19:07:11 +0000366When all else fails, you may want to insert calls to log() to your
367program or even to a copy of the cgi.py file. Note that this requires
368you to set cgi.logfile to the name of a world-writable file before the
369first call to log() is made!
370
Guido van Rossum72755611996-03-06 07:20:06 +0000371Good luck!
372
373
374Common problems and solutions
375-----------------------------
376
Guido van Rossum391b4e61996-03-06 19:11:33 +0000377- Most HTTP servers buffer the output from CGI scripts until the
378script is completed. This means that it is not possible to display a
379progress report on the client's display while the script is running.
Guido van Rossum72755611996-03-06 07:20:06 +0000380
381- Check the installation instructions above.
382
Guido van Rossum391b4e61996-03-06 19:11:33 +0000383- Check the HTTP server's log files. ("tail -f logfile" in a separate
Guido van Rossum72755611996-03-06 07:20:06 +0000384window may be useful!)
385
Guido van Rossum391b4e61996-03-06 19:11:33 +0000386- Always check a script for syntax errors first, by doing something
387like "python script.py".
Guido van Rossum72755611996-03-06 07:20:06 +0000388
389- When using any of the debugging techniques, don't forget to add
390"import sys" to the top of the script.
391
Guido van Rossum391b4e61996-03-06 19:11:33 +0000392- When invoking external programs, make sure they can be found.
393Usually, this means using absolute path names -- $PATH is usually not
394set to a very useful value in a CGI script.
Guido van Rossum72755611996-03-06 07:20:06 +0000395
Guido van Rossum391b4e61996-03-06 19:11:33 +0000396- When reading or writing external files, make sure they can be read
397or written by every user on the system.
Guido van Rossum72755611996-03-06 07:20:06 +0000398
Guido van Rossum391b4e61996-03-06 19:11:33 +0000399- Don't try to give a CGI script a set-uid mode. This doesn't work on
400most systems, and is a security liability as well.
Guido van Rossum72755611996-03-06 07:20:06 +0000401
Guido van Rossum72755611996-03-06 07:20:06 +0000402"""
403
Guido van Rossum98d9fd32000-02-28 15:12:25 +0000404# XXX The module is getting pretty heavy with all those docstrings.
405# Perhaps there should be a slimmed version that doesn't contain all those
406# backwards compatible and debugging classes and functions?
407
408# History
409# -------
410#
411# Michael McLay started this module. Steve Majewski changed the
412# interface to SvFormContentDict and FormContentDict. The multipart
413# parsing was inspired by code submitted by Andreas Paepcke. Guido van
414# Rossum rewrote, reformatted and documented the module and is currently
415# responsible for its maintenance.
416#
417
Guido van Rossum5f322481997-04-11 18:20:42 +0000418__version__ = "2.2"
Guido van Rossum0147db01996-03-09 03:16:04 +0000419
Guido van Rossum72755611996-03-06 07:20:06 +0000420
421# Imports
422# =======
423
424import string
Guido van Rossum72755611996-03-06 07:20:06 +0000425import sys
426import os
Guido van Rossuma5e9fb61997-08-12 18:18:13 +0000427import urllib
Guido van Rossuma5e9fb61997-08-12 18:18:13 +0000428import mimetools
429import rfc822
430from StringIO import StringIO
Guido van Rossum72755611996-03-06 07:20:06 +0000431
Guido van Rossumc204c701996-09-05 19:07:11 +0000432
433# Logging support
434# ===============
435
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000436logfile = "" # Filename to log to, if not empty
437logfp = None # File object to log to, if not None
Guido van Rossumc204c701996-09-05 19:07:11 +0000438
439def initlog(*allargs):
440 """Write a log message, if there is a log file.
441
442 Even though this function is called initlog(), you should always
443 use log(); log is a variable that is set either to initlog
444 (initially), to dolog (once the log file has been opened), or to
445 nolog (when logging is disabled).
446
447 The first argument is a format string; the remaining arguments (if
448 any) are arguments to the % operator, so e.g.
449 log("%s: %s", "a", "b")
450 will write "a: b" to the log file, followed by a newline.
451
452 If the global logfp is not None, it should be a file object to
453 which log data is written.
454
455 If the global logfp is None, the global logfile may be a string
456 giving a filename to open, in append mode. This file should be
457 world writable!!! If the file can't be opened, logging is
458 silently disabled (since there is no safe place where we could
459 send an error message).
460
461 """
462 global logfp, log
463 if logfile and not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000464 try:
465 logfp = open(logfile, "a")
466 except IOError:
467 pass
Guido van Rossumc204c701996-09-05 19:07:11 +0000468 if not logfp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000469 log = nolog
Guido van Rossumc204c701996-09-05 19:07:11 +0000470 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000471 log = dolog
Guido van Rossumc204c701996-09-05 19:07:11 +0000472 apply(log, allargs)
473
474def dolog(fmt, *args):
475 """Write a log message to the log file. See initlog() for docs."""
476 logfp.write(fmt%args + "\n")
477
478def nolog(*allargs):
479 """Dummy function, assigned to log when logging is disabled."""
480 pass
481
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000482log = initlog # The current logging function
Guido van Rossumc204c701996-09-05 19:07:11 +0000483
484
Guido van Rossum72755611996-03-06 07:20:06 +0000485# Parsing functions
486# =================
487
Guido van Rossumad164711997-05-13 19:03:23 +0000488# Maximum input we will accept when REQUEST_METHOD is POST
489# 0 ==> unlimited input
490maxlen = 0
491
Guido van Rossume08c04c1996-11-11 19:29:11 +0000492def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
Guido van Rossum773ab271996-07-23 03:46:24 +0000493 """Parse a query in the environment or from a file (default stdin)
494
495 Arguments, all optional:
496
497 fp : file pointer; default: sys.stdin
498
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000499 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000500
501 keep_blank_values: flag indicating whether blank values in
502 URL encoded forms should be treated as blank strings.
503 A true value inicates that blanks should be retained as
504 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000505 blank values are to be ignored and treated as if they were
506 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000507
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000508 strict_parsing: flag indicating what to do with parsing errors.
509 If false (the default), errors are silently ignored.
510 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000511 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000512 if not fp:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000513 fp = sys.stdin
Guido van Rossum7aee3841996-03-07 18:00:44 +0000514 if not environ.has_key('REQUEST_METHOD'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000515 environ['REQUEST_METHOD'] = 'GET' # For testing stand-alone
Guido van Rossum7aee3841996-03-07 18:00:44 +0000516 if environ['REQUEST_METHOD'] == 'POST':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000517 ctype, pdict = parse_header(environ['CONTENT_TYPE'])
518 if ctype == 'multipart/form-data':
519 return parse_multipart(fp, pdict)
520 elif ctype == 'application/x-www-form-urlencoded':
521 clength = string.atoi(environ['CONTENT_LENGTH'])
522 if maxlen and clength > maxlen:
523 raise ValueError, 'Maximum content length exceeded'
524 qs = fp.read(clength)
525 else:
526 qs = '' # Unknown content-type
527 if environ.has_key('QUERY_STRING'):
528 if qs: qs = qs + '&'
529 qs = qs + environ['QUERY_STRING']
530 elif sys.argv[1:]:
531 if qs: qs = qs + '&'
532 qs = qs + sys.argv[1]
533 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossum7aee3841996-03-07 18:00:44 +0000534 elif environ.has_key('QUERY_STRING'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000535 qs = environ['QUERY_STRING']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000536 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000537 if sys.argv[1:]:
538 qs = sys.argv[1]
539 else:
540 qs = ""
541 environ['QUERY_STRING'] = qs # XXX Shouldn't, really
Guido van Rossume08c04c1996-11-11 19:29:11 +0000542 return parse_qs(qs, keep_blank_values, strict_parsing)
Guido van Rossume7808771995-08-07 20:12:09 +0000543
544
Guido van Rossume08c04c1996-11-11 19:29:11 +0000545def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
546 """Parse a query given as a string argument.
Guido van Rossum773ab271996-07-23 03:46:24 +0000547
548 Arguments:
549
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000550 qs: URL-encoded query string to be parsed
Guido van Rossum773ab271996-07-23 03:46:24 +0000551
552 keep_blank_values: flag indicating whether blank values in
553 URL encoded queries should be treated as blank strings.
554 A true value inicates that blanks should be retained as
555 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000556 blank values are to be ignored and treated as if they were
557 not included.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000558
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000559 strict_parsing: flag indicating what to do with parsing errors.
560 If false (the default), errors are silently ignored.
561 If true, errors raise a ValueError exception.
Guido van Rossum773ab271996-07-23 03:46:24 +0000562 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000563 dict = {}
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000564 for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
565 if len(value) or keep_blank_values:
566 if dict.has_key(name):
567 dict[name].append(value)
568 else:
569 dict[name] = [value]
570 return dict
571
572def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
573 """Parse a query given as a string argument.
574
575 Arguments:
576
577 qs: URL-encoded query string to be parsed
578
579 keep_blank_values: flag indicating whether blank values in
580 URL encoded queries should be treated as blank strings.
581 A true value inicates that blanks should be retained as
582 blank strings. The default false value indicates that
583 blank values are to be ignored and treated as if they were
584 not included.
585
586 strict_parsing: flag indicating what to do with parsing errors.
587 If false (the default), errors are silently ignored.
588 If true, errors raise a ValueError exception.
589
590 Returns a list, as God intended.
591 """
592 name_value_pairs = string.splitfields(qs, '&')
593 r=[]
Guido van Rossum7aee3841996-03-07 18:00:44 +0000594 for name_value in name_value_pairs:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000595 nv = string.splitfields(name_value, '=')
596 if len(nv) != 2:
597 if strict_parsing:
598 raise ValueError, "bad query field: %s" % `name_value`
599 continue
600 name = urllib.unquote(string.replace(nv[0], '+', ' '))
601 value = urllib.unquote(string.replace(nv[1], '+', ' '))
Guido van Rossum3af7b052000-02-25 11:44:03 +0000602 r.append((name, value))
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000603
604 return r
Guido van Rossum9a22de11995-01-12 12:29:47 +0000605
606
Guido van Rossum0147db01996-03-09 03:16:04 +0000607def parse_multipart(fp, pdict):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000608 """Parse multipart input.
Guido van Rossum9a22de11995-01-12 12:29:47 +0000609
Guido van Rossum7aee3841996-03-07 18:00:44 +0000610 Arguments:
611 fp : input file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000612 pdict: dictionary containing other parameters of conten-type header
Guido van Rossum72755611996-03-06 07:20:06 +0000613
Guido van Rossum0147db01996-03-09 03:16:04 +0000614 Returns a dictionary just like parse_qs(): keys are the field names, each
615 value is a list of values for that field. This is easy to use but not
616 much good if you are expecting megabytes to be uploaded -- in that case,
617 use the FieldStorage class instead which is much more flexible. Note
618 that content-type is the raw, unparsed contents of the content-type
619 header.
620
621 XXX This does not parse nested multipart parts -- use FieldStorage for
622 that.
623
624 XXX This should really be subsumed by FieldStorage altogether -- no
625 point in having two implementations of the same parsing algorithm.
Guido van Rossum72755611996-03-06 07:20:06 +0000626
Guido van Rossum7aee3841996-03-07 18:00:44 +0000627 """
Guido van Rossum7aee3841996-03-07 18:00:44 +0000628 if pdict.has_key('boundary'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000629 boundary = pdict['boundary']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000630 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000631 boundary = ""
Guido van Rossum7aee3841996-03-07 18:00:44 +0000632 nextpart = "--" + boundary
633 lastpart = "--" + boundary + "--"
634 partdict = {}
635 terminator = ""
636
637 while terminator != lastpart:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000638 bytes = -1
639 data = None
640 if terminator:
641 # At start of next part. Read headers first.
642 headers = mimetools.Message(fp)
643 clength = headers.getheader('content-length')
644 if clength:
645 try:
646 bytes = string.atoi(clength)
647 except string.atoi_error:
648 pass
649 if bytes > 0:
650 if maxlen and bytes > maxlen:
651 raise ValueError, 'Maximum content length exceeded'
652 data = fp.read(bytes)
653 else:
654 data = ""
655 # Read lines until end of part.
656 lines = []
657 while 1:
658 line = fp.readline()
659 if not line:
660 terminator = lastpart # End outer loop
661 break
662 if line[:2] == "--":
663 terminator = string.strip(line)
664 if terminator in (nextpart, lastpart):
665 break
666 lines.append(line)
667 # Done with part.
668 if data is None:
669 continue
670 if bytes < 0:
671 if lines:
672 # Strip final line terminator
673 line = lines[-1]
674 if line[-2:] == "\r\n":
675 line = line[:-2]
676 elif line[-1:] == "\n":
677 line = line[:-1]
678 lines[-1] = line
679 data = string.joinfields(lines, "")
680 line = headers['content-disposition']
681 if not line:
682 continue
683 key, params = parse_header(line)
684 if key != 'form-data':
685 continue
686 if params.has_key('name'):
687 name = params['name']
688 else:
689 continue
690 if partdict.has_key(name):
691 partdict[name].append(data)
692 else:
693 partdict[name] = [data]
Guido van Rossum72755611996-03-06 07:20:06 +0000694
Guido van Rossum7aee3841996-03-07 18:00:44 +0000695 return partdict
Guido van Rossum9a22de11995-01-12 12:29:47 +0000696
697
Guido van Rossum72755611996-03-06 07:20:06 +0000698def parse_header(line):
Guido van Rossum7aee3841996-03-07 18:00:44 +0000699 """Parse a Content-type like header.
700
701 Return the main content-type and a dictionary of options.
702
703 """
704 plist = map(string.strip, string.splitfields(line, ';'))
705 key = string.lower(plist[0])
706 del plist[0]
707 pdict = {}
708 for p in plist:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000709 i = string.find(p, '=')
710 if i >= 0:
711 name = string.lower(string.strip(p[:i]))
712 value = string.strip(p[i+1:])
713 if len(value) >= 2 and value[0] == value[-1] == '"':
714 value = value[1:-1]
715 pdict[name] = value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000716 return key, pdict
Guido van Rossum72755611996-03-06 07:20:06 +0000717
718
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000719# Classes for field storage
720# =========================
721
722class MiniFieldStorage:
723
Guido van Rossum0147db01996-03-09 03:16:04 +0000724 """Like FieldStorage, for use when no file uploads are possible."""
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000725
Guido van Rossum7aee3841996-03-07 18:00:44 +0000726 # Dummy attributes
727 filename = None
728 list = None
729 type = None
Guido van Rossum773ab271996-07-23 03:46:24 +0000730 file = None
Guido van Rossum4032c2c1996-03-09 04:04:35 +0000731 type_options = {}
Guido van Rossum7aee3841996-03-07 18:00:44 +0000732 disposition = None
733 disposition_options = {}
734 headers = {}
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000735
Guido van Rossum7aee3841996-03-07 18:00:44 +0000736 def __init__(self, name, value):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000737 """Constructor from field name and value."""
738 self.name = name
739 self.value = value
Guido van Rossum773ab271996-07-23 03:46:24 +0000740 # self.file = StringIO(value)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000741
742 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000743 """Return printable representation."""
744 return "MiniFieldStorage(%s, %s)" % (`self.name`, `self.value`)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000745
746
747class FieldStorage:
748
Guido van Rossum7aee3841996-03-07 18:00:44 +0000749 """Store a sequence of fields, reading multipart/form-data.
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000750
Guido van Rossum7aee3841996-03-07 18:00:44 +0000751 This class provides naming, typing, files stored on disk, and
752 more. At the top level, it is accessible like a dictionary, whose
753 keys are the field names. (Note: None can occur as a field name.)
754 The items are either a Python list (if there's multiple values) or
755 another FieldStorage or MiniFieldStorage object. If it's a single
756 object, it has the following attributes:
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000757
Guido van Rossum7aee3841996-03-07 18:00:44 +0000758 name: the field name, if specified; otherwise None
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000759
Guido van Rossum7aee3841996-03-07 18:00:44 +0000760 filename: the filename, if specified; otherwise None; this is the
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000761 client side filename, *not* the file name on which it is
762 stored (that's a temporary file you don't deal with)
Guido van Rossum243ddcd1996-03-07 06:33:07 +0000763
Guido van Rossum7aee3841996-03-07 18:00:44 +0000764 value: the value as a *string*; for file uploads, this
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000765 transparently reads the file every time you request the value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000766
767 file: the file(-like) object from which you can read the data;
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000768 None if the data is stored a simple string
Guido van Rossum7aee3841996-03-07 18:00:44 +0000769
770 type: the content-type, or None if not specified
771
772 type_options: dictionary of options specified on the content-type
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000773 line
Guido van Rossum7aee3841996-03-07 18:00:44 +0000774
775 disposition: content-disposition, or None if not specified
776
777 disposition_options: dictionary of corresponding options
778
779 headers: a dictionary(-like) object (sometimes rfc822.Message or a
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000780 subclass thereof) containing *all* headers
Guido van Rossum7aee3841996-03-07 18:00:44 +0000781
782 The class is subclassable, mostly for the purpose of overriding
783 the make_file() method, which is called internally to come up with
784 a file open for reading and writing. This makes it possible to
785 override the default choice of storing all files in a temporary
786 directory and unlinking them as soon as they have been opened.
787
788 """
789
Guido van Rossum773ab271996-07-23 03:46:24 +0000790 def __init__(self, fp=None, headers=None, outerboundary="",
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000791 environ=os.environ, keep_blank_values=0, strict_parsing=0):
792 """Constructor. Read multipart/* until last part.
Guido van Rossum7aee3841996-03-07 18:00:44 +0000793
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000794 Arguments, all optional:
Guido van Rossum7aee3841996-03-07 18:00:44 +0000795
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000796 fp : file pointer; default: sys.stdin
Guido van Rossumb1b4f941998-05-08 19:55:51 +0000797 (not used when the request method is GET)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000798
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000799 headers : header dictionary-like object; default:
800 taken from environ as per CGI spec
Guido van Rossum7aee3841996-03-07 18:00:44 +0000801
Guido van Rossum773ab271996-07-23 03:46:24 +0000802 outerboundary : terminating multipart boundary
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000803 (for internal use only)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000804
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000805 environ : environment dictionary; default: os.environ
Guido van Rossum773ab271996-07-23 03:46:24 +0000806
807 keep_blank_values: flag indicating whether blank values in
808 URL encoded forms should be treated as blank strings.
809 A true value inicates that blanks should be retained as
810 blank strings. The default false value indicates that
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000811 blank values are to be ignored and treated as if they were
812 not included.
Guido van Rossum773ab271996-07-23 03:46:24 +0000813
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000814 strict_parsing: flag indicating what to do with parsing errors.
815 If false (the default), errors are silently ignored.
816 If true, errors raise a ValueError exception.
Guido van Rossume08c04c1996-11-11 19:29:11 +0000817
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000818 """
819 method = 'GET'
820 self.keep_blank_values = keep_blank_values
821 self.strict_parsing = strict_parsing
822 if environ.has_key('REQUEST_METHOD'):
823 method = string.upper(environ['REQUEST_METHOD'])
Guido van Rossum01852831998-06-25 02:40:17 +0000824 if method == 'GET' or method == 'HEAD':
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000825 if environ.has_key('QUERY_STRING'):
826 qs = environ['QUERY_STRING']
827 elif sys.argv[1:]:
828 qs = sys.argv[1]
829 else:
830 qs = ""
831 fp = StringIO(qs)
832 if headers is None:
833 headers = {'content-type':
834 "application/x-www-form-urlencoded"}
835 if headers is None:
Guido van Rossumcff311a1998-06-11 14:06:59 +0000836 headers = {}
837 if method == 'POST':
838 # Set default content-type for POST to what's traditional
839 headers['content-type'] = "application/x-www-form-urlencoded"
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000840 if environ.has_key('CONTENT_TYPE'):
841 headers['content-type'] = environ['CONTENT_TYPE']
842 if environ.has_key('CONTENT_LENGTH'):
843 headers['content-length'] = environ['CONTENT_LENGTH']
844 self.fp = fp or sys.stdin
845 self.headers = headers
846 self.outerboundary = outerboundary
Guido van Rossum7aee3841996-03-07 18:00:44 +0000847
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000848 # Process content-disposition header
849 cdisp, pdict = "", {}
850 if self.headers.has_key('content-disposition'):
851 cdisp, pdict = parse_header(self.headers['content-disposition'])
852 self.disposition = cdisp
853 self.disposition_options = pdict
854 self.name = None
855 if pdict.has_key('name'):
856 self.name = pdict['name']
857 self.filename = None
858 if pdict.has_key('filename'):
859 self.filename = pdict['filename']
Guido van Rossum7aee3841996-03-07 18:00:44 +0000860
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000861 # Process content-type header
Barry Warsaw302331a1999-01-08 17:42:03 +0000862 #
863 # Honor any existing content-type header. But if there is no
864 # content-type header, use some sensible defaults. Assume
865 # outerboundary is "" at the outer level, but something non-false
866 # inside a multi-part. The default for an inner part is text/plain,
867 # but for an outer part it should be urlencoded. This should catch
868 # bogus clients which erroneously forget to include a content-type
869 # header.
870 #
871 # See below for what we do if there does exist a content-type header,
872 # but it happens to be something we don't understand.
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000873 if self.headers.has_key('content-type'):
874 ctype, pdict = parse_header(self.headers['content-type'])
Guido van Rossumce900de1999-06-02 18:44:22 +0000875 elif self.outerboundary or method != 'POST':
Barry Warsaw302331a1999-01-08 17:42:03 +0000876 ctype, pdict = "text/plain", {}
877 else:
878 ctype, pdict = 'application/x-www-form-urlencoded', {}
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000879 self.type = ctype
880 self.type_options = pdict
881 self.innerboundary = ""
882 if pdict.has_key('boundary'):
883 self.innerboundary = pdict['boundary']
884 clen = -1
885 if self.headers.has_key('content-length'):
886 try:
887 clen = string.atoi(self.headers['content-length'])
888 except:
889 pass
890 if maxlen and clen > maxlen:
891 raise ValueError, 'Maximum content length exceeded'
892 self.length = clen
Guido van Rossum7aee3841996-03-07 18:00:44 +0000893
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000894 self.list = self.file = None
895 self.done = 0
896 self.lines = []
897 if ctype == 'application/x-www-form-urlencoded':
898 self.read_urlencoded()
899 elif ctype[:10] == 'multipart/':
Guido van Rossumf5745001998-10-20 14:43:02 +0000900 self.read_multi(environ, keep_blank_values, strict_parsing)
Barry Warsaw302331a1999-01-08 17:42:03 +0000901 else:
Guido van Rossum60a3bd81999-06-11 18:26:09 +0000902 self.read_single()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000903
904 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000905 """Return a printable representation."""
906 return "FieldStorage(%s, %s, %s)" % (
907 `self.name`, `self.filename`, `self.value`)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000908
909 def __getattr__(self, name):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000910 if name != 'value':
911 raise AttributeError, name
912 if self.file:
913 self.file.seek(0)
914 value = self.file.read()
915 self.file.seek(0)
916 elif self.list is not None:
917 value = self.list
918 else:
919 value = None
920 return value
Guido van Rossum7aee3841996-03-07 18:00:44 +0000921
922 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000923 """Dictionary style indexing."""
924 if self.list is None:
925 raise TypeError, "not indexable"
926 found = []
927 for item in self.list:
928 if item.name == key: found.append(item)
929 if not found:
930 raise KeyError, key
931 if len(found) == 1:
932 return found[0]
933 else:
934 return found
Guido van Rossum7aee3841996-03-07 18:00:44 +0000935
936 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000937 """Dictionary style keys() method."""
938 if self.list is None:
939 raise TypeError, "not indexable"
940 keys = []
941 for item in self.list:
942 if item.name not in keys: keys.append(item.name)
943 return keys
Guido van Rossum7aee3841996-03-07 18:00:44 +0000944
Guido van Rossum0147db01996-03-09 03:16:04 +0000945 def has_key(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000946 """Dictionary style has_key() method."""
947 if self.list is None:
948 raise TypeError, "not indexable"
949 for item in self.list:
950 if item.name == key: return 1
951 return 0
Guido van Rossum0147db01996-03-09 03:16:04 +0000952
Guido van Rossum88b85d41997-01-11 19:21:33 +0000953 def __len__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000954 """Dictionary style len(x) support."""
955 return len(self.keys())
Guido van Rossum88b85d41997-01-11 19:21:33 +0000956
Guido van Rossum7aee3841996-03-07 18:00:44 +0000957 def read_urlencoded(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000958 """Internal: read data in query string format."""
959 qs = self.fp.read(self.length)
Guido van Rossum1946f0d1999-06-04 17:54:39 +0000960 self.list = list = []
961 for key, value in parse_qsl(qs, self.keep_blank_values,
962 self.strict_parsing):
963 list.append(MiniFieldStorage(key, value))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000964 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000965
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000966 FieldStorageClass = None
967
Guido van Rossumf5745001998-10-20 14:43:02 +0000968 def read_multi(self, environ, keep_blank_values, strict_parsing):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000969 """Internal: read a part that is itself multipart."""
970 self.list = []
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000971 klass = self.FieldStorageClass or self.__class__
972 part = klass(self.fp, {}, self.innerboundary,
973 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000974 # Throw first part away
975 while not part.done:
976 headers = rfc822.Message(self.fp)
Guido van Rossum030d2ec1998-12-09 22:16:46 +0000977 part = klass(self.fp, headers, self.innerboundary,
978 environ, keep_blank_values, strict_parsing)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000979 self.list.append(part)
980 self.skip_lines()
Guido van Rossum7aee3841996-03-07 18:00:44 +0000981
982 def read_single(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000983 """Internal: read an atomic part."""
984 if self.length >= 0:
985 self.read_binary()
986 self.skip_lines()
987 else:
988 self.read_lines()
989 self.file.seek(0)
Guido van Rossum7aee3841996-03-07 18:00:44 +0000990
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000991 bufsize = 8*1024 # I/O buffering size for copy to file
Guido van Rossum7aee3841996-03-07 18:00:44 +0000992
993 def read_binary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000994 """Internal: read binary data."""
995 self.file = self.make_file('b')
996 todo = self.length
997 if todo >= 0:
998 while todo > 0:
999 data = self.fp.read(min(todo, self.bufsize))
1000 if not data:
1001 self.done = -1
1002 break
1003 self.file.write(data)
1004 todo = todo - len(data)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001005
1006 def read_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001007 """Internal: read lines until EOF or outerboundary."""
1008 self.file = self.make_file('')
1009 if self.outerboundary:
1010 self.read_lines_to_outerboundary()
1011 else:
1012 self.read_lines_to_eof()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001013
1014 def read_lines_to_eof(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001015 """Internal: read lines until EOF."""
1016 while 1:
1017 line = self.fp.readline()
1018 if not line:
1019 self.done = -1
1020 break
1021 self.lines.append(line)
1022 self.file.write(line)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001023
1024 def read_lines_to_outerboundary(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001025 """Internal: read lines until outerboundary."""
1026 next = "--" + self.outerboundary
1027 last = next + "--"
1028 delim = ""
1029 while 1:
1030 line = self.fp.readline()
1031 if not line:
1032 self.done = -1
1033 break
1034 self.lines.append(line)
1035 if line[:2] == "--":
1036 strippedline = string.strip(line)
1037 if strippedline == next:
1038 break
1039 if strippedline == last:
1040 self.done = 1
1041 break
1042 odelim = delim
1043 if line[-2:] == "\r\n":
1044 delim = "\r\n"
1045 line = line[:-2]
1046 elif line[-1] == "\n":
1047 delim = "\n"
1048 line = line[:-1]
1049 else:
1050 delim = ""
1051 self.file.write(odelim + line)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001052
1053 def skip_lines(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001054 """Internal: skip lines until outer boundary if defined."""
1055 if not self.outerboundary or self.done:
1056 return
1057 next = "--" + self.outerboundary
1058 last = next + "--"
1059 while 1:
1060 line = self.fp.readline()
1061 if not line:
1062 self.done = -1
1063 break
1064 self.lines.append(line)
1065 if line[:2] == "--":
1066 strippedline = string.strip(line)
1067 if strippedline == next:
1068 break
1069 if strippedline == last:
1070 self.done = 1
1071 break
Guido van Rossum7aee3841996-03-07 18:00:44 +00001072
Guido van Rossuma5e9fb61997-08-12 18:18:13 +00001073 def make_file(self, binary=None):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001074 """Overridable: return a readable & writable file.
Guido van Rossum7aee3841996-03-07 18:00:44 +00001075
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001076 The file will be used as follows:
1077 - data is written to it
1078 - seek(0)
1079 - data is read from it
Guido van Rossum7aee3841996-03-07 18:00:44 +00001080
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001081 The 'binary' argument is unused -- the file is always opened
1082 in binary mode.
Guido van Rossum7aee3841996-03-07 18:00:44 +00001083
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001084 This version opens a temporary file for reading and writing,
1085 and immediately deletes (unlinks) it. The trick (on Unix!) is
1086 that the file can still be used, but it can't be opened by
1087 another process, and it will automatically be deleted when it
1088 is closed or when the current process terminates.
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001089
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001090 If you want a more permanent file, you derive a class which
1091 overrides this method. If you want a visible temporary file
1092 that is nevertheless automatically deleted when the script
1093 terminates, try defining a __del__ method in a derived class
1094 which unlinks the temporary files you have created.
Guido van Rossum7aee3841996-03-07 18:00:44 +00001095
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001096 """
1097 import tempfile
1098 return tempfile.TemporaryFile("w+b")
1099
Guido van Rossum243ddcd1996-03-07 06:33:07 +00001100
1101
Guido van Rossum4032c2c1996-03-09 04:04:35 +00001102# Backwards Compatibility Classes
1103# ===============================
Guido van Rossum9a22de11995-01-12 12:29:47 +00001104
1105class FormContentDict:
Guido van Rossum7aee3841996-03-07 18:00:44 +00001106 """Basic (multiple values per field) form content as dictionary.
Guido van Rossum72755611996-03-06 07:20:06 +00001107
Guido van Rossum7aee3841996-03-07 18:00:44 +00001108 form = FormContentDict()
1109
1110 form[key] -> [value, value, ...]
1111 form.has_key(key) -> Boolean
1112 form.keys() -> [key, key, ...]
1113 form.values() -> [[val, val, ...], [val, val, ...], ...]
1114 form.items() -> [(key, [val, val, ...]), (key, [val, val, ...]), ...]
1115 form.dict == {key: [val, val, ...], ...}
1116
1117 """
Guido van Rossum773ab271996-07-23 03:46:24 +00001118 def __init__(self, environ=os.environ):
Guido van Rossumafb5e931996-08-08 18:42:12 +00001119 self.dict = parse(environ=environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001120 self.query_string = environ['QUERY_STRING']
Guido van Rossum7aee3841996-03-07 18:00:44 +00001121 def __getitem__(self,key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001122 return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +00001123 def keys(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001124 return self.dict.keys()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001125 def has_key(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001126 return self.dict.has_key(key)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001127 def values(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001128 return self.dict.values()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001129 def items(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001130 return self.dict.items()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001131 def __len__( self ):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001132 return len(self.dict)
Guido van Rossum9a22de11995-01-12 12:29:47 +00001133
1134
Guido van Rossum9a22de11995-01-12 12:29:47 +00001135class SvFormContentDict(FormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001136 """Strict single-value expecting form content as dictionary.
1137
1138 IF you only expect a single value for each field, then form[key]
1139 will return that single value. It will raise an IndexError if
1140 that expectation is not true. IF you expect a field to have
1141 possible multiple values, than you can use form.getlist(key) to
1142 get all of the values. values() and items() are a compromise:
1143 they return single strings where there is a single value, and
1144 lists of strings otherwise.
1145
1146 """
1147 def __getitem__(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001148 if len(self.dict[key]) > 1:
1149 raise IndexError, 'expecting a single value'
1150 return self.dict[key][0]
Guido van Rossum7aee3841996-03-07 18:00:44 +00001151 def getlist(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001152 return self.dict[key]
Guido van Rossum7aee3841996-03-07 18:00:44 +00001153 def values(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001154 lis = []
1155 for each in self.dict.values():
1156 if len( each ) == 1 :
1157 lis.append(each[0])
1158 else: lis.append(each)
1159 return lis
Guido van Rossum7aee3841996-03-07 18:00:44 +00001160 def items(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001161 lis = []
1162 for key,value in self.dict.items():
1163 if len(value) == 1 :
1164 lis.append((key, value[0]))
1165 else: lis.append((key, value))
1166 return lis
Guido van Rossum9a22de11995-01-12 12:29:47 +00001167
1168
Guido van Rossum9a22de11995-01-12 12:29:47 +00001169class InterpFormContentDict(SvFormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001170 """This class is present for backwards compatibility only."""
1171 def __getitem__( self, key ):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001172 v = SvFormContentDict.__getitem__( self, key )
1173 if v[0] in string.digits+'+-.' :
1174 try: return string.atoi( v )
1175 except ValueError:
1176 try: return string.atof( v )
1177 except ValueError: pass
1178 return string.strip(v)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001179 def values( self ):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001180 lis = []
1181 for key in self.keys():
1182 try:
1183 lis.append( self[key] )
1184 except IndexError:
1185 lis.append( self.dict[key] )
1186 return lis
Guido van Rossum7aee3841996-03-07 18:00:44 +00001187 def items( self ):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001188 lis = []
1189 for key in self.keys():
1190 try:
1191 lis.append( (key, self[key]) )
1192 except IndexError:
1193 lis.append( (key, self.dict[key]) )
1194 return lis
Guido van Rossum9a22de11995-01-12 12:29:47 +00001195
1196
Guido van Rossum9a22de11995-01-12 12:29:47 +00001197class FormContent(FormContentDict):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001198 """This class is present for backwards compatibility only."""
Guido van Rossum0147db01996-03-09 03:16:04 +00001199 def values(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001200 if self.dict.has_key(key) :return self.dict[key]
1201 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001202 def indexed_value(self, key, location):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001203 if self.dict.has_key(key):
1204 if len (self.dict[key]) > location:
1205 return self.dict[key][location]
1206 else: return None
1207 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001208 def value(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001209 if self.dict.has_key(key): return self.dict[key][0]
1210 else: return None
Guido van Rossum0147db01996-03-09 03:16:04 +00001211 def length(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001212 return len(self.dict[key])
Guido van Rossum0147db01996-03-09 03:16:04 +00001213 def stripped(self, key):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001214 if self.dict.has_key(key): return string.strip(self.dict[key][0])
1215 else: return None
Guido van Rossum7aee3841996-03-07 18:00:44 +00001216 def pars(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001217 return self.dict
Guido van Rossum9a22de11995-01-12 12:29:47 +00001218
1219
Guido van Rossum72755611996-03-06 07:20:06 +00001220# Test/debug code
1221# ===============
Guido van Rossum9a22de11995-01-12 12:29:47 +00001222
Guido van Rossum773ab271996-07-23 03:46:24 +00001223def test(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001224 """Robust test CGI script, usable as main program.
Guido van Rossum9a22de11995-01-12 12:29:47 +00001225
Guido van Rossum7aee3841996-03-07 18:00:44 +00001226 Write minimal HTTP headers and dump all information provided to
1227 the script in HTML form.
1228
1229 """
1230 import traceback
1231 print "Content-type: text/html"
1232 print
1233 sys.stderr = sys.stdout
1234 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001235 form = FieldStorage() # Replace with other classes to test those
1236 print_form(form)
Guido van Rossum773ab271996-07-23 03:46:24 +00001237 print_environ(environ)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001238 print_directory()
1239 print_arguments()
1240 print_environ_usage()
1241 def f():
1242 exec "testing print_exception() -- <I>italics?</I>"
1243 def g(f=f):
1244 f()
1245 print "<H3>What follows is a test, not an actual exception:</H3>"
1246 g()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001247 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001248 print_exception()
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001249
Guido van Rossumad164711997-05-13 19:03:23 +00001250 # Second try with a small maxlen...
1251 global maxlen
1252 maxlen = 50
1253 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001254 form = FieldStorage() # Replace with other classes to test those
1255 print_form(form)
1256 print_environ(environ)
1257 print_directory()
1258 print_arguments()
1259 print_environ_usage()
Guido van Rossumad164711997-05-13 19:03:23 +00001260 except:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001261 print_exception()
Guido van Rossumad164711997-05-13 19:03:23 +00001262
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001263def print_exception(type=None, value=None, tb=None, limit=None):
1264 if type is None:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001265 type, value, tb = sys.exc_info()
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001266 import traceback
1267 print
1268 print "<H3>Traceback (innermost last):</H3>"
1269 list = traceback.format_tb(tb, limit) + \
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001270 traceback.format_exception_only(type, value)
Guido van Rossumf85de8a1996-08-20 20:22:39 +00001271 print "<PRE>%s<B>%s</B></PRE>" % (
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001272 escape(string.join(list[:-1], "")),
1273 escape(list[-1]),
1274 )
Guido van Rossumf15d1591997-09-29 23:22:12 +00001275 del tb
Guido van Rossum9a22de11995-01-12 12:29:47 +00001276
Guido van Rossum773ab271996-07-23 03:46:24 +00001277def print_environ(environ=os.environ):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001278 """Dump the shell environment as HTML."""
1279 keys = environ.keys()
1280 keys.sort()
1281 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001282 print "<H3>Shell Environment:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +00001283 print "<DL>"
1284 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001285 print "<DT>", escape(key), "<DD>", escape(environ[key])
Guido van Rossum7aee3841996-03-07 18:00:44 +00001286 print "</DL>"
1287 print
Guido van Rossum72755611996-03-06 07:20:06 +00001288
1289def print_form(form):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001290 """Dump the contents of a form as HTML."""
1291 keys = form.keys()
1292 keys.sort()
1293 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001294 print "<H3>Form Contents:</H3>"
Guido van Rossum7aee3841996-03-07 18:00:44 +00001295 print "<DL>"
1296 for key in keys:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001297 print "<DT>" + escape(key) + ":",
1298 value = form[key]
1299 print "<i>" + escape(`type(value)`) + "</i>"
1300 print "<DD>" + escape(`value`)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001301 print "</DL>"
1302 print
1303
1304def print_directory():
1305 """Dump the current directory as HTML."""
1306 print
1307 print "<H3>Current Working Directory:</H3>"
1308 try:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001309 pwd = os.getcwd()
Guido van Rossum7aee3841996-03-07 18:00:44 +00001310 except os.error, msg:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001311 print "os.error:", escape(str(msg))
Guido van Rossum7aee3841996-03-07 18:00:44 +00001312 else:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001313 print escape(pwd)
Guido van Rossum7aee3841996-03-07 18:00:44 +00001314 print
Guido van Rossum9a22de11995-01-12 12:29:47 +00001315
Guido van Rossuma8738a51996-03-14 21:30:28 +00001316def print_arguments():
1317 print
Guido van Rossum503e50b1996-05-28 22:57:20 +00001318 print "<H3>Command Line Arguments:</H3>"
Guido van Rossuma8738a51996-03-14 21:30:28 +00001319 print
1320 print sys.argv
1321 print
1322
Guido van Rossum9a22de11995-01-12 12:29:47 +00001323def print_environ_usage():
Guido van Rossum7aee3841996-03-07 18:00:44 +00001324 """Dump a list of environment variables used by CGI as HTML."""
1325 print """
Guido van Rossum72755611996-03-06 07:20:06 +00001326<H3>These environment variables could have been set:</H3>
1327<UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001328<LI>AUTH_TYPE
1329<LI>CONTENT_LENGTH
1330<LI>CONTENT_TYPE
1331<LI>DATE_GMT
1332<LI>DATE_LOCAL
1333<LI>DOCUMENT_NAME
1334<LI>DOCUMENT_ROOT
1335<LI>DOCUMENT_URI
1336<LI>GATEWAY_INTERFACE
1337<LI>LAST_MODIFIED
1338<LI>PATH
1339<LI>PATH_INFO
1340<LI>PATH_TRANSLATED
1341<LI>QUERY_STRING
1342<LI>REMOTE_ADDR
1343<LI>REMOTE_HOST
1344<LI>REMOTE_IDENT
1345<LI>REMOTE_USER
1346<LI>REQUEST_METHOD
1347<LI>SCRIPT_NAME
1348<LI>SERVER_NAME
1349<LI>SERVER_PORT
1350<LI>SERVER_PROTOCOL
1351<LI>SERVER_ROOT
1352<LI>SERVER_SOFTWARE
1353</UL>
Guido van Rossum7aee3841996-03-07 18:00:44 +00001354In addition, HTTP headers sent by the server may be passed in the
1355environment as well. Here are some common variable names:
1356<UL>
1357<LI>HTTP_ACCEPT
1358<LI>HTTP_CONNECTION
1359<LI>HTTP_HOST
1360<LI>HTTP_PRAGMA
1361<LI>HTTP_REFERER
1362<LI>HTTP_USER_AGENT
1363</UL>
Guido van Rossum9a22de11995-01-12 12:29:47 +00001364"""
1365
Guido van Rossum9a22de11995-01-12 12:29:47 +00001366
Guido van Rossum72755611996-03-06 07:20:06 +00001367# Utilities
1368# =========
Guido van Rossum9a22de11995-01-12 12:29:47 +00001369
Guido van Rossum64c66201997-07-19 20:11:53 +00001370def escape(s, quote=None):
Guido van Rossum7aee3841996-03-07 18:00:44 +00001371 """Replace special characters '&', '<' and '>' by SGML entities."""
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001372 s = string.replace(s, "&", "&amp;") # Must be done first!
Guido van Rossum00f9fea1997-12-24 21:18:41 +00001373 s = string.replace(s, "<", "&lt;")
1374 s = string.replace(s, ">", "&gt;",)
Guido van Rossum64c66201997-07-19 20:11:53 +00001375 if quote:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +00001376 s = string.replace(s, '"', "&quot;")
Guido van Rossum7aee3841996-03-07 18:00:44 +00001377 return s
Guido van Rossum9a22de11995-01-12 12:29:47 +00001378
Guido van Rossum9a22de11995-01-12 12:29:47 +00001379
Guido van Rossum72755611996-03-06 07:20:06 +00001380# Invoke mainline
1381# ===============
1382
1383# Call test() when this file is run as a script (not imported as a module)
1384if __name__ == '__main__':
Guido van Rossum7aee3841996-03-07 18:00:44 +00001385 test()