def test_tooManyFields(self): """ Test when breaking the maximum number of fields. """ boundary = 'xyz' data = """--xyz\r Content-Disposition: form-data; name="foo"\r \r Foo Bar\r --xyz\r Content-Disposition: form-data; name="foo"\r \r Baz\r --xyz\r Content-Disposition: form-data; name="file"; filename="filename"\r Content-Type: text/html\r \r blah\r --xyz\r Content-Disposition: form-data; name="file"; filename="filename"\r Content-Type: text/plain\r \r bleh\r --xyz--\r """ s = stream.IStream(data) return self.assertFailure( fileupload.parseMultipartFormData(s, boundary, maxFields=3), fileupload.MimeFormatError)
def doTestError(self, boundary, data, expected_error): # Test different amounts of data at a time. ds = [fileupload.parseMultipartFormData(TestStream(data, maxReturn=bytes), boundary) for bytes in range(1, 20)] d = defer.DeferredList(ds, consumeErrors=True) d.addCallback(self._assertFailures, expected_error) return d
def doTestError(self, boundary, data, expected_error): # Test different amounts of data at a time. ds = [ fileupload.parseMultipartFormData( TestStream(data, maxReturn=bytes), boundary) for bytes in range(1, 20) ] d = defer.DeferredList(ds, consumeErrors=True) d.addCallback(self._assertFailures, expected_error) return d
def doTest(self, boundary, data, expected_args, expected_files): #import time, gc, cgi, cStringIO for bytes in range(1, 20): #s = TestStream(data, maxReturn=bytes) s = stream.IStream(data) #t=time.time() d = waitForDeferred(fileupload.parseMultipartFormData(s, boundary)) yield d; args, files = d.getResult() #e=time.time() #print "%.2g"%(e-t) self.assertEquals(args, expected_args) # Read file data back into memory to compare. out = {} for name, l in files.items(): out[name] = [(filename, ctype, f.read()) for (filename, ctype, f) in l] self.assertEquals(out, expected_files)
def doTest(self, boundary, data, expected_args, expected_files): #import time, gc, cgi, cStringIO for bytes in range(1, 20): #s = TestStream(data, maxReturn=bytes) s = stream.IStream(data) #t=time.time() d = waitForDeferred(fileupload.parseMultipartFormData(s, boundary)) yield d args, files = d.getResult() #e=time.time() #print "%.2g"%(e-t) self.assertEquals(args, expected_args) # Read file data back into memory to compare. out = {} for name, l in files.items(): out[name] = [(filename, ctype, f.read()) for (filename, ctype, f) in l] self.assertEquals(out, expected_files)
def test_tooBigUpload(self): """ Test that a too big form post fails. """ boundary = '---------------------------155781040421463194511908194298' data = """-----------------------------155781040421463194511908194298\r Content-Disposition: form-data; name="foo"\r \r Foo Bar\r -----------------------------155781040421463194511908194298\r Content-Disposition: form-data; name="file"; filename="filename"\r Content-Type: text/html\r \r Contents of a file blah blah\r -----------------------------155781040421463194511908194298--\r """ s = stream.IStream(data) return self.assertFailure( fileupload.parseMultipartFormData(s, boundary, maxSize=200), fileupload.MimeFormatError)
def test_maxMem(self): """ An attachment with no filename goes to memory: check that the C{maxMem} parameter limits the size of this kind of attachment. """ boundary = '---------------------------155781040421463194511908194298' data = """-----------------------------155781040421463194511908194298\r Content-Disposition: form-data; name="foo"\r \r Foo Bar and more content\r -----------------------------155781040421463194511908194298\r Content-Disposition: form-data; name="file"; filename="filename"\r Content-Type: text/html\r \r Contents of a file blah blah\r -----------------------------155781040421463194511908194298--\r """ s = stream.IStream(data) return self.assertFailure( fileupload.parseMultipartFormData(s, boundary, maxMem=10), fileupload.MimeFormatError)
def parsePOSTData(request, maxMem=100 * 1024, maxFields=1024, maxSize=10 * 1024 * 1024): """ Parse data of a POST request. @param request: the request to parse. @type request: L{txweb2.http.Request}. @param maxMem: maximum memory used during the parsing of the data. @type maxMem: C{int} @param maxFields: maximum number of form fields allowed. @type maxFields: C{int} @param maxSize: maximum size of file upload allowed. @type maxSize: C{int} @return: a deferred that will fire when the parsing is done. The deferred itself doesn't hold a return value, the request is modified directly. @rtype: C{defer.Deferred} """ if request.stream.length == 0: return defer.succeed(None) ctype = request.headers.getHeader('content-type') if ctype is None: return defer.succeed(None) def updateArgs(data): args = data request.args.update(args) def updateArgsAndFiles(data): args, files = data request.args.update(args) request.files.update(files) def error(f): f.trap(fileupload.MimeFormatError) raise http.HTTPError( http.StatusResponse(responsecode.BAD_REQUEST, str(f.value))) if (ctype.mediaType == 'application' and ctype.mediaSubtype == 'x-www-form-urlencoded'): d = fileupload.parse_urlencoded(request.stream) d.addCallbacks(updateArgs, error) return d elif (ctype.mediaType == 'multipart' and ctype.mediaSubtype == 'form-data'): boundary = ctype.params.get('boundary') if boundary is None: return defer.fail( http.HTTPError( http.StatusResponse( responsecode.BAD_REQUEST, "Boundary not specified in Content-Type."))) d = fileupload.parseMultipartFormData(request.stream, boundary, maxMem, maxFields, maxSize) d.addCallbacks(updateArgsAndFiles, error) return d else: return defer.fail( http.HTTPError( http.StatusResponse( responsecode.BAD_REQUEST, "Invalid content-type: %s/%s" % (ctype.mediaType, ctype.mediaSubtype))))
def parsePOSTData(request, maxMem=100*1024, maxFields=1024, maxSize=10*1024*1024): """ Parse data of a POST request. @param request: the request to parse. @type request: L{txweb2.http.Request}. @param maxMem: maximum memory used during the parsing of the data. @type maxMem: C{int} @param maxFields: maximum number of form fields allowed. @type maxFields: C{int} @param maxSize: maximum size of file upload allowed. @type maxSize: C{int} @return: a deferred that will fire when the parsing is done. The deferred itself doesn't hold a return value, the request is modified directly. @rtype: C{defer.Deferred} """ if request.stream.length == 0: return defer.succeed(None) ctype = request.headers.getHeader('content-type') if ctype is None: return defer.succeed(None) def updateArgs(data): args = data request.args.update(args) def updateArgsAndFiles(data): args, files = data request.args.update(args) request.files.update(files) def error(f): f.trap(fileupload.MimeFormatError) raise http.HTTPError( http.StatusResponse(responsecode.BAD_REQUEST, str(f.value))) if (ctype.mediaType == 'application' and ctype.mediaSubtype == 'x-www-form-urlencoded'): d = fileupload.parse_urlencoded(request.stream) d.addCallbacks(updateArgs, error) return d elif (ctype.mediaType == 'multipart' and ctype.mediaSubtype == 'form-data'): boundary = ctype.params.get('boundary') if boundary is None: return defer.fail(http.HTTPError( http.StatusResponse( responsecode.BAD_REQUEST, "Boundary not specified in Content-Type."))) d = fileupload.parseMultipartFormData(request.stream, boundary, maxMem, maxFields, maxSize) d.addCallbacks(updateArgsAndFiles, error) return d else: return defer.fail(http.HTTPError( http.StatusResponse( responsecode.BAD_REQUEST, "Invalid content-type: %s/%s" % ( ctype.mediaType, ctype.mediaSubtype))))