"""FieldStorage.py
This module defines a subclass of the standard Python cgi.FieldStorage class
with an extra method that will allow a FieldStorage to parse a query string
even in a POST request.
"""
import cgi, os, urllib
class FieldStorage(cgi.FieldStorage):
def __init__(self, fp=None, headers=None, outerboundary="",
environ=os.environ, keep_blank_values=0, strict_parsing=0):
self._environ = environ
self._strict_parsing = strict_parsing
self._keep_blank_values = keep_blank_values
cgi.FieldStorage.__init__(self, fp, headers, outerboundary,
environ, keep_blank_values, strict_parsing)
def parse_qs(self):
"""Explicitly parse the query string, even if it's a POST request."""
self._method = self._environ.get('REQUEST_METHOD', '').upper()
if self._method == "GET" or self._method == "HEAD":
# print __file__, "bailing on GET or HEAD request"
return # bail because cgi.FieldStorage already did this
self._qs = self._environ.get('QUERY_STRING', None)
if not self._qs:
# print __file__, "bailing on no query_string"
return # bail if no query string
r = {}
for name_value in self._qs.split('&'):
nv = name_value.split('=', 2)
if len(nv) != 2:
if self._strict_parsing:
raise ValueError, "bad query field: %r" % (name_value,)
continue
name = urllib.unquote(nv[0].replace('+', ' '))
value = urllib.unquote(nv[1].replace('+', ' '))
if len(value) or self._keep_blank_values:
if r.has_key(name):
r[name].append(value)
else:
r[name] = [value]
# Only append values that aren't already in the FieldStorage's keys;
# This makes POSTed vars override vars on the query string
if not self.list:
# This makes sure self.keys() are available, even
# when valid POST data wasn't encountered.
self.list = []
for key, values in r.items():
if not self.has_key(key):
for value in values:
self.list.append(cgi.MiniFieldStorage(key, value))
|