8 buf.update(urlparse.parse_qsl(req.query))
9 if req.ihead.get("Content-Type") == "application/x-www-form-urlencoded":
11 rbody = req.input.read(2 ** 20)
12 except IOError as exc:
14 if len(rbody) >= 2 ** 20:
15 return ValueError("x-www-form-urlencoded data is absurdly long")
16 buf.update(urlparse.parse_qsl(rbody))
19 class badmultipart(Exception):
22 class formpart(object):
23 def __init__(self, form):
32 def fillbuf(self, sz):
34 mboundary = "\r\n--" + self.form.boundary + "\r\n"
35 lboundary = "\r\n--" + self.form.boundary + "--\r\n"
37 p = self.form.buf.find(mboundary)
39 self.buf += self.form.buf[:p]
40 self.form.buf = self.form.buf[p + len(mboundary):]
43 p = self.form.buf.find(lboundary)
45 self.buf += self.form.buf[:p]
46 self.form.buf = self.form.buf[p + len(lboundary):]
50 self.buf += self.form.buf[:-len(lboundary)]
51 self.form.buf = self.form.buf[-len(lboundary):]
52 if sz >= 0 and len(self.buf) >= sz:
54 while len(self.form.buf) <= len(lboundary):
55 ret = req.input.read(8192)
57 raise badmultipart("Missing last multipart boundary")
60 def read(self, limit=-1):
63 ret = self.buf[:limit]
64 self.buf = self.buf[limit:]
70 def readline(self, limit=-1):
73 p = self.buf.find('\n', last)
80 self.fillbuf(last + 128)
82 ret = self.buf[:p + 1]
83 self.buf = self.buf[p + 1:]
88 if self.read(8192) == "":
94 def __exit__(self, *excinfo):
100 ln = self.readline(256)
102 raise badmultipart("Too long header line in part")
112 if not ln[1:].isspace():
117 raise badmultipart("Malformed multipart header line")
118 self.head[buf[:p].strip().lower()] = buf[p + 1:].lstrip()
120 val, par = proto.pmimehead(self.head.get("content-disposition", ""))
121 if val != "form-data":
122 raise badmultipart("Unexpected Content-Disposition in form part: %r" % val)
123 if not "name" in par:
124 raise badmultipart("Missing name in form part")
125 self.name = par["name"]
126 self.filename = par.get("filename")
127 val, par = proto.pmimehead(self.head.get("content-type", ""))
129 self.charset = par.get("charset")
130 encoding = self.head.get("content-transfer-encoding", "binary")
131 if encoding != "binary":
132 raise badmultipart("Form part uses unexpected transfer encoding: %r" % encoding)
134 class multipart(object):
135 def __init__(self, req):
136 val, par = proto.pmimehead(req.ihead.get("Content-Type", ""))
137 if req.method != "POST" or val != "multipart/form-data":
138 raise badmultipart("Request is not a multipart form")
139 if "boundary" not in par:
140 raise badmultipart("Multipart form lacks boundary")
141 self.boundary = par["boundary"]
145 self.lastpart = formpart(self)
146 self.lastpart.close()
152 if not self.lastpart.eof:
153 raise RuntimeError("All form parts must be read entirely")
155 raise StopIteration()
156 self.lastpart = formpart(self)
157 self.lastpart.parsehead()
160 def formdata(req, onerror=Exception):
161 data = req.item(formparse)
162 if isinstance(data, Exception):
163 if onerror is Exception: