@@ -198,105 +198,28 @@ def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
198
198
DeprecationWarning , 2 )
199
199
return urllib .parse .parse_qsl (qs , keep_blank_values , strict_parsing )
200
200
201
- def parse_multipart (fp , pdict ):
201
+ def parse_multipart (fp , pdict , encoding = "utf-8" ):
202
202
"""Parse multipart input.
203
203
204
204
Arguments:
205
205
fp : input file
206
206
pdict: dictionary containing other parameters of content-type header
207
+ encoding: request encoding
207
208
208
209
Returns a dictionary just like parse_qs(): keys are the field names, each
209
- value is a list of values for that field. This is easy to use but not
210
- much good if you are expecting megabytes to be uploaded -- in that case,
211
- use the FieldStorage class instead which is much more flexible. Note
212
- that content-type is the raw, unparsed contents of the content-type
213
- header.
214
-
215
- XXX This does not parse nested multipart parts -- use FieldStorage for
216
- that.
217
-
218
- XXX This should really be subsumed by FieldStorage altogether -- no
219
- point in having two implementations of the same parsing algorithm.
220
- Also, FieldStorage protects itself better against certain DoS attacks
221
- by limiting the size of the data read in one chunk. The API here
222
- does not support that kind of protection. This also affects parse()
223
- since it can call parse_multipart().
224
-
210
+ value is a list of values for that field. For non-file fields, the value
211
+ is a list of strings.
225
212
"""
226
- import http .client
227
-
228
- boundary = b""
229
- if 'boundary' in pdict :
230
- boundary = pdict ['boundary' ]
231
- if not valid_boundary (boundary ):
232
- raise ValueError ('Invalid boundary in multipart form: %r'
233
- % (boundary ,))
234
-
235
- nextpart = b"--" + boundary
236
- lastpart = b"--" + boundary + b"--"
237
- partdict = {}
238
- terminator = b""
239
-
240
- while terminator != lastpart :
241
- bytes = - 1
242
- data = None
243
- if terminator :
244
- # At start of next part. Read headers first.
245
- headers = http .client .parse_headers (fp )
246
- clength = headers .get ('content-length' )
247
- if clength :
248
- try :
249
- bytes = int (clength )
250
- except ValueError :
251
- pass
252
- if bytes > 0 :
253
- if maxlen and bytes > maxlen :
254
- raise ValueError ('Maximum content length exceeded' )
255
- data = fp .read (bytes )
256
- else :
257
- data = b""
258
- # Read lines until end of part.
259
- lines = []
260
- while 1 :
261
- line = fp .readline ()
262
- if not line :
263
- terminator = lastpart # End outer loop
264
- break
265
- if line .startswith (b"--" ):
266
- terminator = line .rstrip ()
267
- if terminator in (nextpart , lastpart ):
268
- break
269
- lines .append (line )
270
- # Done with part.
271
- if data is None :
272
- continue
273
- if bytes < 0 :
274
- if lines :
275
- # Strip final line terminator
276
- line = lines [- 1 ]
277
- if line [- 2 :] == b"\r \n " :
278
- line = line [:- 2 ]
279
- elif line [- 1 :] == b"\n " :
280
- line = line [:- 1 ]
281
- lines [- 1 ] = line
282
- data = b"" .join (lines )
283
- line = headers ['content-disposition' ]
284
- if not line :
285
- continue
286
- key , params = parse_header (line )
287
- if key != 'form-data' :
288
- continue
289
- if 'name' in params :
290
- name = params ['name' ]
291
- else :
292
- continue
293
- if name in partdict :
294
- partdict [name ].append (data )
295
- else :
296
- partdict [name ] = [data ]
297
-
298
- return partdict
299
-
213
+ # RFC 2026, Section 5.1 : The "multipart" boundary delimiters are always
214
+ # represented as 7bit US-ASCII.
215
+ boundary = pdict ['boundary' ].decode ('ascii' )
216
+ ctype = "multipart/form-data; boundary={}" .format (boundary )
217
+ headers = Message ()
218
+ headers .set_type (ctype )
219
+ headers ['Content-Length' ] = pdict ['CONTENT-LENGTH' ]
220
+ fs = FieldStorage (fp , headers = headers , encoding = encoding ,
221
+ environ = {'REQUEST_METHOD' : 'POST' })
222
+ return {k : fs .getlist (k ) for k in fs }
300
223
301
224
def _parseparam (s ):
302
225
while s [:1 ] == ';' :
0 commit comments