diff -r 69ed936deb0f Doc/library/cgi.rst --- a/Doc/library/cgi.rst Thu May 03 03:36:40 2012 +0200 +++ b/Doc/library/cgi.rst Wed May 09 08:55:39 2012 +0200 @@ -4,7 +4,7 @@ .. module:: cgi :synopsis: Helpers for running Python scripts via the Common Gateway Interface. - + .. index:: pair: WWW; server pair: CGI; protocol @@ -29,7 +29,7 @@ .. _cgi-intro: A CGI script is invoked by an HTTP server, usually to process user input -submitted through an HTML ``
`` or ```` element. +submitted through an HTML ```` element. Most often, CGI scripts live in the server's special :file:`cgi-bin` directory. The HTTP server places all sorts of information about the request (such as the @@ -41,8 +41,7 @@ is read this way; at other times the form data is passed via the "query string" part of the URL. This module is intended to take care of the different cases and provide a simpler interface to the Python script. It also provides a number -of utilities that help in debugging scripts, and the latest addition is support -for file uploads from a form (if your browser supports it). +of utilities that help in debugging scripts. The output of a CGI script should consist of two sections, separated by a blank line. The first section contains a number of headers, telling the client what @@ -86,22 +85,57 @@ tracking down bugs. You can always remove the ``cgitb`` line later when you have tested your script and are confident that it works correctly. -To get at submitted form data, use the :class:`FieldStorage` class. If the form -contains non-ASCII characters, use the *encoding* keyword parameter set to the -value of the encoding defined for the document. It is usually contained in the -META tag in the HEAD section of the HTML document or by the -:mailheader:`Content-Type` header). This reads the form contents from the -standard input or the environment (depending on the value of various -environment variables set according to the CGI standard). Since it may consume -standard input, it should be instantiated only once. +To get at submitted form data, use the :class:`FieldStorage` class. -The :class:`FieldStorage` instance can be indexed like a Python dictionary. -It allows membership testing with the :keyword:`in` operator, and also supports -the standard dictionary method :meth:`keys` and the built-in function -:func:`len`. Form fields containing empty strings are ignored and do not appear -in the dictionary; to keep such values, provide a true value for the optional -*keep_blank_values* keyword parameter when creating the :class:`FieldStorage` -instance. +.. class:: FieldStorage([encoding[,errors[,keep_blank_values]]]) + + Creating an instance of this class reads the form contents from the + standard input or the environment (depending on the value of various + environment variables set according to the CGI standard). Since it may + consume standard input, it should be instantiated only once. + + If the form contains non-ASCII characters, use the *encoding* keyword + parameter set to the value of the encoding defined for the document. It + is usually contained in the META tag in the HEAD section of the HTML + document or in the :mailheader:`Content-Type` header. The *errors* + argument indicates how to manage encoding errors (see the :mod:`str` + documentation) + + Form fields containing empty strings are ignored and do not appear + in the dictionary; to keep such values, provide a true value for the + optional *keep_blank_values* keyword parameter when creating the + :class:`FieldStorage` instance. + +The :class:`FieldStorage` instance is a dictionary-like object, mapping each +form field name to an object that can be : + + * another instance of :class:`FieldStorage` for data sent in the body of a + POST request with a :mimetype:`multipart` encoding type + + * an instance of the :class:`MiniFieldStorage` class for data sent as the + URL query string or as a single data part of type + :mimetype:`application/x-www-form-urlencoded` + + * a list of :class:`FieldStorage` or :class:`MiniFieldStorage` in the case + of multiple fields with the same name (see next section) + +A form submitted via POST that also has a query string will contain both +:class:`FieldStorage` and :class:`MiniFieldStorage` items. + +In all cases, the object associated to a field name has an attribute +:attr:`value`. It is set to + + * the field value as a string, or as bytes for file uploads, if there is a + single value for this field name + + * the list of values if there are several values for this field name + +For instances of :class:`FieldStorage` the value can be obtained by the method + +.. method:: FieldStorage.getvalue(name[,default]) + + Returns the value for the specified field name ; the optional argument + *default* is returned if the requested name is not present. For instance, the following code (which assumes that the :mailheader:`Content-Type` header and blank line have already been printed) @@ -120,23 +154,61 @@ Here the fields, accessed through ``form[key]``, are themselves instances of :class:`FieldStorage` (or :class:`MiniFieldStorage`, depending on the form encoding). The :attr:`value` attribute of the instance yields the string value -of the field. The :meth:`getvalue` method returns this string value directly; -it also accepts an optional second argument as a default to return if the -requested key is not present. +of the field -If the submitted form data contains more than one field with the same name, the -object retrieved by ``form[key]`` is not a :class:`FieldStorage` or -:class:`MiniFieldStorage` instance but a list of such instances. Similarly, in -this situation, ``form.getvalue(key)`` would return a list of strings. If you -expect this possibility (when your HTML form contains multiple fields with the -same name), use the :func:`getlist` function, which always returns a list of -values (so that you do not need to special-case the single item case). For -example, this code concatenates any number of username fields, separated by -commas:: +Multiple fields with the same name +---------------------------------- + +The submitted form data may contain more than one field with the same name. +This situation is common for example when a form contains a group of multiple +checkboxes with the same name:: + + + + +In this case, the object retrieved by ``form["item"]`` is not a +:class:`FieldStorage` or :class:`MiniFieldStorage` instance but a list of such +instances. Similarly, in this situation, ``form.getvalue(key)`` would return +a list of strings. If you expect this possibility (when your HTML form +contains multiple fields with the same name), use the following methods: + +.. method:: FieldStorage.getlist(name) + + This method always returns a list of values associated with form field *name*. + The method returns an empty list if no such form field or value exists for + *name*. It returns a list consisting of one item if only one such value exists. + + +.. method:: FieldStorage.getfirst(name, default=None) + + This method always returns only one value associated with form field *name*. + The method returns only the first value in case that more values were posted + under such name. Please note that the order in which the values are received + may vary from browser to browser and should not be counted on. [#]_ If no such + form field or value exists then the method returns the value specified by the + optional parameter *default*. This parameter defaults to ``None`` if not + specified. + + +For example, this code concatenates any number of fields called ``username``, +separated by commas:: value = form.getlist("username") usernames = ",".join(value) +Using these methods you can write code that handles all cases without having to +test if the value is a single instance or a list of instances:: + + import cgi + form = cgi.FieldStorage() + user = form.getfirst("user", "").upper() # This way it's safe. + for item in form.getlist("item"): + do_something(item) + + +File uploads +------------ + If a field represents an uploaded file, accessing the value via the :attr:`value` attribute or the :func:`getvalue` method reads the entire file in memory as bytes. This may not be what you want. You can test for an uploaded @@ -166,93 +238,6 @@ :mimetype:`multipart/\*`). In this case, it can be iterated over recursively just like the top-level form object. -When a form is submitted in the "old" format (as the query string or as a single -data part of type :mimetype:`application/x-www-form-urlencoded`), the items will -actually be instances of the class :class:`MiniFieldStorage`. In this case, the -:attr:`!list`, :attr:`!file`, and :attr:`filename` attributes are always ``None``. - -A form submitted via POST that also has a query string will contain both -:class:`FieldStorage` and :class:`MiniFieldStorage` items. - -Higher Level Interface ----------------------- - -The previous section explains how to read CGI form data using the -:class:`FieldStorage` class. This section describes a higher level interface -which was added to this class to allow one to do it in a more readable and -intuitive way. The interface doesn't make the techniques described in previous -sections obsolete --- they are still useful to process file uploads efficiently, -for example. - -.. XXX: Is this true ? - -The interface consists of two simple methods. Using the methods you can process -form data in a generic way, without the need to worry whether only one or more -values were posted under one name. - -In the previous section, you learned to write following code anytime you -expected a user to post more than one value under one name:: - - item = form.getvalue("item") - if isinstance(item, list): - # The user is requesting more than one item. - else: - # The user is requesting only one item. - -This situation is common for example when a form contains a group of multiple -checkboxes with the same name:: - - - - -In most situations, however, there's only one form control with a particular -name in a form and then you expect and need only one value associated with this -name. So you write a script containing for example this code:: - - user = form.getvalue("user").upper() - -The problem with the code is that you should never expect that a client will -provide valid input to your scripts. For example, if a curious user appends -another ``user=foo`` pair to the query string, then the script would crash, -because in this situation the ``getvalue("user")`` method call returns a list -instead of a string. Calling the :meth:`~str.upper` method on a list is not valid -(since lists do not have a method of this name) and results in an -:exc:`AttributeError` exception. - -Therefore, the appropriate way to read form data values was to always use the -code which checks whether the obtained value is a single value or a list of -values. That's annoying and leads to less readable scripts. - -A more convenient approach is to use the methods :meth:`getfirst` and -:meth:`getlist` provided by this higher level interface. - - -.. method:: FieldStorage.getfirst(name, default=None) - - This method always returns only one value associated with form field *name*. - The method returns only the first value in case that more values were posted - under such name. Please note that the order in which the values are received - may vary from browser to browser and should not be counted on. [#]_ If no such - form field or value exists then the method returns the value specified by the - optional parameter *default*. This parameter defaults to ``None`` if not - specified. - - -.. method:: FieldStorage.getlist(name) - - This method always returns a list of values associated with form field *name*. - The method returns an empty list if no such form field or value exists for - *name*. It returns a list consisting of one item if only one such value exists. - -Using these methods you can write nice compact code:: - - import cgi - form = cgi.FieldStorage() - user = form.getfirst("user", "").upper() # This way it's safe. - for item in form.getlist("item"): - do_something(item) - - .. _functions-in-cgi-module: Functions diff -r 69ed936deb0f Doc/make.bat --- a/Doc/make.bat Thu May 03 03:36:40 2012 +0200 +++ b/Doc/make.bat Wed May 09 08:55:39 2012 +0200 @@ -2,7 +2,7 @@ setlocal set SVNROOT=http://svn.python.org/projects -if "%PYTHON%" EQU "" set PYTHON=..\pcbuild\python +if "%PYTHON%" EQU "" set PYTHON=c:/python27/python.exe if "%HTMLHELP%" EQU "" set HTMLHELP=%ProgramFiles%\HTML Help Workshop\hhc.exe if "%DISTVERSION%" EQU "" for /f "usebackq" %%v in (`%PYTHON% tools/sphinxext/patchlevel.py`) do set DISTVERSION=%%v diff -r 69ed936deb0f Lib/http/server.py --- a/Lib/http/server.py Thu May 03 03:36:40 2012 +0200 +++ b/Lib/http/server.py Wed May 09 08:55:39 2012 +0200 @@ -1137,20 +1137,38 @@ nbytes = int(length) except (TypeError, ValueError): nbytes = 0 + stdin = subprocess.PIPE + data = None + if self.command.lower() == "post" and nbytes > 0: + # try to read all bytes in one read + data = self.rfile.read(nbytes) + if len(data) 0: - data = self.rfile.read(nbytes) - else: - data = None - # throw away additional data [see bug #427345] - while select.select([self.rfile._sock], [], [], 0)[0]: - if not self.rfile._sock.recv(1): - break stdout, stderr = p.communicate(data) self.wfile.write(stdout) if stderr: