1import re 2from cgi import parse_header 3 4from .headers import HeaderElement 5from .parsers import MultipartParser 6from .parsers import QueryStringParser 7 8 9def process_multipart(request, params): 10 headers = request.headers 11 12 ctype = headers.elements("Content-Type") 13 if ctype: 14 ctype = ctype[0] 15 else: 16 ctype = HeaderElement.from_str("application/x-www-form-urlencoded") 17 18 ib = "" 19 if "boundary" in ctype.params: 20 # http://tools.ietf.org/html/rfc2046#section-5.1.1 21 # "The grammar for parameters on the Content-type field is such that it 22 # is often necessary to enclose the boundary parameter values in quotes 23 # on the Content-type line" 24 ib = ctype.params["boundary"].strip("\"") 25 26 if not re.match("^[ -~]{0,200}[!-~]$", ib): 27 raise ValueError("Invalid boundary in multipart form: %r" % (ib,)) 28 29 parser = MultipartParser(request.body, ib) 30 for part in parser: 31 if part.filename or not part.is_buffered(): 32 params[part.name] = part 33 else: 34 params[part.name] = part.value 35 36 37def process_urlencoded(request, params, encoding="utf-8"): 38 params.update(QueryStringParser(request.qs).result) 39 body = request.body.getvalue().decode(encoding) 40 params.update(QueryStringParser(body).result) 41 42 43def process(request, params): 44 ctype = request.headers.get("Content-Type") 45 if not ctype: 46 return 47 48 mtype, mencoding = ctype.split("/", 1) if "/" in ctype else (ctype, None) 49 mencoding, extra = parse_header(mencoding) 50 51 charset = extra.get("charset", "utf-8") 52 53 if mtype == "multipart": 54 process_multipart(request, params) 55 elif mtype == "application" and mencoding == "x-www-form-urlencoded": 56 process_urlencoded(request, params, encoding=charset) 57