diff options
Diffstat (limited to 'Lib/cgi.py')
| -rwxr-xr-x | Lib/cgi.py | 144 |
1 files changed, 62 insertions, 82 deletions
@@ -38,9 +38,19 @@ from operator import attrgetter import sys import os import urllib -import mimetools -import rfc822 import UserDict +import urlparse + +from warnings import filterwarnings, catch_warnings, warn +with catch_warnings(): + if sys.py3kwarning: + filterwarnings("ignore", ".*mimetools has been removed", + DeprecationWarning) + import mimetools + if sys.py3kwarning: + filterwarnings("ignore", ".*rfc822 has been removed", DeprecationWarning) + import rfc822 + try: from cStringIO import StringIO except ImportError: @@ -162,75 +172,24 @@ def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0): else: qs = "" environ['QUERY_STRING'] = qs # XXX Shouldn't, really - return parse_qs(qs, keep_blank_values, strict_parsing) - + return urlparse.parse_qs(qs, keep_blank_values, strict_parsing) -def parse_qs(qs, keep_blank_values=0, strict_parsing=0): - """Parse a query given as a string argument. - Arguments: +# parse query string function called from urlparse, +# this is done in order to maintain backward compatiblity. - qs: URL-encoded query string to be parsed - - keep_blank_values: flag indicating whether blank values in - URL encoded queries should be treated as blank strings. - A true value indicates that blanks should be retained as - blank strings. The default false value indicates that - blank values are to be ignored and treated as if they were - not included. +def parse_qs(qs, keep_blank_values=0, strict_parsing=0): + """Parse a query given as a string argument.""" + warn("cgi.parse_qs is deprecated, use urlparse.parse_qs \ + instead", PendingDeprecationWarning, 2) + return urlparse.parse_qs(qs, keep_blank_values, strict_parsing) - strict_parsing: flag indicating what to do with parsing errors. - If false (the default), errors are silently ignored. - If true, errors raise a ValueError exception. - """ - dict = {} - for name, value in parse_qsl(qs, keep_blank_values, strict_parsing): - if name in dict: - dict[name].append(value) - else: - dict[name] = [value] - return dict def parse_qsl(qs, keep_blank_values=0, strict_parsing=0): - """Parse a query given as a string argument. - - Arguments: - - qs: URL-encoded query string to be parsed - - keep_blank_values: flag indicating whether blank values in - URL encoded queries should be treated as blank strings. A - true value indicates that blanks should be retained as blank - strings. The default false value indicates that blank values - are to be ignored and treated as if they were not included. - - strict_parsing: flag indicating what to do with parsing errors. If - false (the default), errors are silently ignored. If true, - errors raise a ValueError exception. - - Returns a list, as G-d intended. - """ - pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')] - r = [] - for name_value in pairs: - if not name_value and not strict_parsing: - continue - nv = name_value.split('=', 1) - if len(nv) != 2: - if strict_parsing: - raise ValueError, "bad query field: %r" % (name_value,) - # Handle case of a control-name with no equal sign - if keep_blank_values: - nv.append('') - else: - continue - if len(nv[1]) or keep_blank_values: - name = urllib.unquote(nv[0].replace('+', ' ')) - value = urllib.unquote(nv[1].replace('+', ' ')) - r.append((name, value)) - - return r - + """Parse a query given as a string argument.""" + warn("cgi.parse_qsl is deprecated, use urlparse.parse_qsl instead", + PendingDeprecationWarning, 2) + return urlparse.parse_qsl(qs, keep_blank_values, strict_parsing) def parse_multipart(fp, pdict): """Parse multipart input. @@ -330,16 +289,28 @@ def parse_multipart(fp, pdict): return partdict +def _parseparam(s): + while s[:1] == ';': + s = s[1:] + end = s.find(';') + while end > 0 and s.count('"', 0, end) % 2: + end = s.find(';', end + 1) + if end < 0: + end = len(s) + f = s[:end] + yield f.strip() + s = s[end:] + def parse_header(line): """Parse a Content-type like header. Return the main content-type and a dictionary of options. """ - plist = [x.strip() for x in line.split(';')] - key = plist.pop(0).lower() + parts = _parseparam(';' + line) + key = parts.next() pdict = {} - for p in plist: + for p in parts: i = p.find('=') if i >= 0: name = p[:i].strip().lower() @@ -456,6 +427,7 @@ class FieldStorage: self.strict_parsing = strict_parsing if 'REQUEST_METHOD' in environ: method = environ['REQUEST_METHOD'].upper() + self.qs_on_post = None if method == 'GET' or method == 'HEAD': if 'QUERY_STRING' in environ: qs = environ['QUERY_STRING'] @@ -474,6 +446,8 @@ class FieldStorage: headers['content-type'] = "application/x-www-form-urlencoded" if 'CONTENT_TYPE' in environ: headers['content-type'] = environ['CONTENT_TYPE'] + if 'QUERY_STRING' in environ: + self.qs_on_post = environ['QUERY_STRING'] if 'CONTENT_LENGTH' in environ: headers['content-length'] = environ['CONTENT_LENGTH'] self.fp = fp or sys.stdin @@ -607,37 +581,35 @@ class FieldStorage: """Dictionary style keys() method.""" if self.list is None: raise TypeError, "not indexable" - keys = [] - for item in self.list: - if item.name not in keys: keys.append(item.name) - return keys + return list(set(item.name for item in self.list)) def has_key(self, key): """Dictionary style has_key() method.""" if self.list is None: raise TypeError, "not indexable" - for item in self.list: - if item.name == key: return True - return False + return any(item.name == key for item in self.list) def __contains__(self, key): """Dictionary style __contains__ method.""" if self.list is None: raise TypeError, "not indexable" - for item in self.list: - if item.name == key: return True - return False + return any(item.name == key for item in self.list) def __len__(self): """Dictionary style len(x) support.""" return len(self.keys()) + def __nonzero__(self): + return bool(self.list) + def read_urlencoded(self): """Internal: read data in query string format.""" qs = self.fp.read(self.length) + if self.qs_on_post: + qs += '&' + self.qs_on_post self.list = list = [] - for key, value in parse_qsl(qs, self.keep_blank_values, - self.strict_parsing): + for key, value in urlparse.parse_qsl(qs, self.keep_blank_values, + self.strict_parsing): list.append(MiniFieldStorage(key, value)) self.skip_lines() @@ -649,6 +621,12 @@ class FieldStorage: if not valid_boundary(ib): raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,) self.list = [] + if self.qs_on_post: + for key, value in urlparse.parse_qsl(self.qs_on_post, + self.keep_blank_values, self.strict_parsing): + self.list.append(MiniFieldStorage(key, value)) + FieldStorageClass = None + klass = self.FieldStorageClass or self.__class__ part = klass(self.fp, {}, ib, environ, keep_blank_values, strict_parsing) @@ -807,8 +785,10 @@ class FormContentDict(UserDict.UserDict): form.dict == {key: [val, val, ...], ...} """ - def __init__(self, environ=os.environ): - self.dict = self.data = parse(environ=environ) + def __init__(self, environ=os.environ, keep_blank_values=0, strict_parsing=0): + self.dict = self.data = parse(environ=environ, + keep_blank_values=keep_blank_values, + strict_parsing=strict_parsing) self.query_string = environ['QUERY_STRING'] |
