def test_save_as(self): ''' save_as stores data in a file keeping the file position. ''' def tmp_file_name(): # create a temporary file name (on Python 2.6+ NamedTemporaryFile # with delete=False could be used) fd, fname = tempfile.mkstemp() f = os.fdopen(fd) f.close() return fname test_file = 'abc' * 1024 boundary = '---------------------------186454651713519341951581030105' request = BytesIO( to_bytes('\r\n').join( map(to_bytes, [ '--' + boundary, 'Content-Disposition: form-data; name="file1"; filename="random.png"', 'Content-Type: image/png', '', test_file, '--' + boundary + '--', '' ]))) p = mp.MultipartParser(request, boundary) self.assertEqual( p.get('file1').file.read(1024), to_bytes(test_file)[:1024]) tfn = tmp_file_name() p.get('file1').save_as(tfn) tf = open(tfn, 'rb') self.assertEqual(tf.read(), to_bytes(test_file)) tf.close() self.assertEqual( p.get('file1').file.read(), to_bytes(test_file)[1024:])
def test_big_file(self): ''' If the size of an uploaded part exceeds memfile_limit, it is written to disk. ''' test_file = 'abc' * 1024 boundary = '---------------------------186454651713519341951581030105' request = BytesIO( to_bytes('\r\n').join( map(to_bytes, [ '--' + boundary, 'Content-Disposition: form-data; name="file1"; filename="random.png"', 'Content-Type: image/png', '', test_file, '--' + boundary, 'Content-Disposition: form-data; name="file2"; filename="random.png"', 'Content-Type: image/png', '', test_file + 'a', '--' + boundary, 'Content-Disposition: form-data; name="file3"; filename="random.png"', 'Content-Type: image/png', '', test_file * 2, '--' + boundary + '--', '' ]))) p = mp.MultipartParser(request, boundary, memfile_limit=len(test_file)) self.assertEqual(p.get('file1').file.read(), to_bytes(test_file)) self.assertTrue(p.get('file1').is_buffered()) self.assertEqual(p.get('file2').file.read(), to_bytes(test_file + 'a')) self.assertFalse(p.get('file2').is_buffered()) self.assertEqual(p.get('file3').file.read(), to_bytes(test_file * 2)) self.assertFalse(p.get('file3').is_buffered())
def test_iterlines_maxbuf(self): data, limit = 'abcdefgh\nijklmnop\r\nq', 9 result = [(to_bytes('abcdefgh'),to_bytes('\n')),(to_bytes('ijklmnop'),to_bytes('')),(to_bytes(''),to_bytes('\r\n')),(to_bytes('q'),to_bytes(''))] i = mp.MultipartParser(BytesIO(to_bytes(data)), 'foo', buffer_size=limit)._lineiter() self.assertEqual(list(i), result) data, limit = ('X'*3*1024)+'x\n', 1024 result = [(to_bytes('X'*1024),to_bytes('')),(to_bytes('X'*1024),to_bytes('')),(to_bytes('X'*1024),to_bytes('')),(to_bytes('x'),to_bytes('\n'))] i = mp.MultipartParser(BytesIO(to_bytes(data)), 'foo', buffer_size=limit)._lineiter() self.assertEqual(list(i), result)
def test_iterlines_limit(self): data, limit = 'abc\ndef\r\nghi', 10 result = [(to_bytes('abc'),to_bytes('\n')),(to_bytes('def'),to_bytes('\r\n')),(to_bytes('g'),to_bytes(''))] i = mp.MultipartParser(BytesIO(to_bytes(data)), 'foo', limit)._lineiter() self.assertEqual(list(i), result) data, limit = 'abc\ndef\r\nghi', 8 result = [(to_bytes('abc'),to_bytes('\n')),(to_bytes('def'),to_bytes('\r'))] i = mp.MultipartParser(BytesIO(to_bytes(data)), 'foo', limit)._lineiter() self.assertEqual(list(i), result)
def test_file_seek(self): ''' The file object should be readable withoud a seek(0). ''' test_file = 'abc'*1024 boundary = '---------------------------186454651713519341951581030105' request = BytesIO(to_bytes('\r\n').join(map(to_bytes,[ '--' + boundary, 'Content-Disposition: form-data; name="file1"; filename="random.png"', 'Content-Type: image/png', '', test_file, '--' + boundary + '--','']))) p = mp.MultipartParser(request, boundary) self.assertEqual(p.get('file1').file.read(), to_bytes(test_file)) self.assertEqual(p.get('file1').value, test_file)
def test_unicode_value(self): ''' The .value property always returns unicode ''' test_file = 'abc'*1024 boundary = '---------------------------186454651713519341951581030105' request = BytesIO(to_bytes('\r\n').join(map(to_bytes,[ '--' + boundary, 'Content-Disposition: form-data; name="file1"; filename="random.png"', 'Content-Type: image/png', '', test_file, '--' + boundary + '--','']))) p = mp.MultipartParser(request, boundary) self.assertEqual(p.get('file1').file.read(), to_bytes(test_file)) self.assertEqual(p.get('file1').value, test_file) self.assertTrue(hasattr(p.get('file1').value, 'encode'))
def test_get_all(self): ''' Test the get() and get_all() methods. ''' boundary = '---------------------------186454651713519341951581030105' request = BytesIO(to_bytes('\r\n').join(map(to_bytes,[ '--' + boundary, 'Content-Disposition: form-data; name="file1"; filename="random.png"', 'Content-Type: image/png', '', 'abc'*1024, '--' + boundary, 'Content-Disposition: form-data; name="file1"; filename="random.png"', 'Content-Type: image/png', '', 'def'*1024, '--' + boundary + '--','']))) p = mp.MultipartParser(request, boundary) self.assertEqual(p.get('file1').file.read(), to_bytes('abc'*1024)) self.assertEqual(p.get('file2'), None) self.assertEqual(len(p.get_all('file1')), 2) self.assertEqual(p.get_all('file1')[1].file.read(), to_bytes('def'*1024)) self.assertEqual(p.get_all('file1'), p.parts())
def decode_multiform_data(data): s_pat = data.split(b"\r")[0][2:] parts = multipart.MultipartParser(BytesIO(multipart.to_bytes(data)), s_pat).parts() d_d = {} for part_t in parts: if part_t.content_type != '': d_d[part_t.name] = { 'isfile': True, 'filename': part_t.filename, 'name': part_t.name, 'file': part_t.file, 'size': part_t.size, } else: try: value = tornado.escape.json_decode(part_t.value) except: value = part_t.value # endtry d_d[part_t.name] = { 'isfile': False, 'name': part_t.name, 'value': value, } # endif # endfor return d_d
def test_multiline_header(self): ''' HTTP allows headers to be multiline. ''' test_file = to_bytes('abc'*1024) test_text = u'Test text\n with\r\n ümläuts!' boundary = '---------------------------186454651713519341951581030105' request = BytesIO(to_bytes('\r\n').join(map(to_bytes,[ '--' + boundary, 'Content-Disposition: form-data;', '\tname="file1"; filename="random.png"', 'Content-Type: image/png', '', test_file, '--' + boundary, 'Content-Disposition: form-data;', ' name="text"', '', test_text, '--' + boundary + '--','']))) p = mp.MultipartParser(request, boundary, charset='utf8') self.assertEqual(p.get('file1').file.read(), test_file) self.assertEqual(p.get('file1').filename, 'random.png') self.assertEqual(p.get('text').value, test_text)
def test_no_newline_after_middle_content(self): forms, files = self.parse('--foo\r\n', 'Content-Disposition: form-data; name="file1"; filename="random.png"\r\n', 'Content-Type: image/png\r\n', '\r\n', 'abc', '--foo\r\n' 'Content-Disposition: form-data; name="file2"; filename="random.png"\r\n', 'Content-Type: image/png\r\n', '\r\n', 'abc\r\n', '--foo--') self.assertEqual(len(files), 1) self.assertTrue(to_bytes('name="file2"') in files['file1'].file.read())
def test_preamble_before_start_boundary(self): forms, files = self.parse('Preamble\r\n', '--foo\r\n' 'Content-Disposition: form-data; name="file1"; filename="random.png"\r\n', 'Content-Type: image/png\r\n', '\r\n', 'abc\r\n', '--foo--') self.assertEqual(files['file1'].file.read(), to_bytes('abc')) self.assertEqual(files['file1'].filename, 'random.png') self.assertEqual(files['file1'].name, 'file1') self.assertEqual(files['file1'].content_type, 'image/png')
def test_iterlines(self): data = 'abc\ndef\r\nghi' result = [(to_bytes('abc'), to_bytes('\n')), (to_bytes('def'), to_bytes('\r\n')), (to_bytes('ghi'), to_bytes(''))] i = mp.MultipartParser(BytesIO(to_bytes(data)), 'foo')._lineiter() self.assertEqual(list(i), result)
def read_form_data(self): content_length = int(self.headers['Content-Length']) post_data = self.rfile.read(content_length).decode("utf8") parser = multipart.MultipartParser( BytesIO(multipart.to_bytes(post_data)), post_data.split("\r")[0][2:]) parts = parser.parts() return {part.name: part.value for part in parts}
def test_multipart(self): forms, files = self.parse('--foo\r\n', 'Content-Disposition: form-data; name="file1"; filename="random.png"\r\n', 'Content-Type: image/png\r\n', '\r\n', 'abc\r\n', '--foo\r\n', 'Content-Disposition: form-data; name="text1"\r\n', '\r\n', 'abc\r\n', '--foo--') self.assertEqual(forms['text1'], 'abc') self.assertEqual(files['file1'].file.read(), to_bytes('abc')) self.assertEqual(files['file1'].filename, 'random.png') self.assertEqual(files['file1'].name, 'file1') self.assertEqual(files['file1'].content_type, 'image/png')
def test_werkzeug_examples(self): """Tests multipart parsing against data collected from webbrowsers""" for name in browser_test_cases: boundary = browser_test_cases[name]['boundary'] files = browser_test_cases[name]['files'] forms = browser_test_cases[name]['forms'] env = {'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': 'multipart/form-data; boundary=%s'%boundary, 'wsgi.input': BytesIO(browser_test_cases[name]['data'])} rforms, rfiles = mp.parse_form_data(env, strict=True, charset='utf8') for field in files: self.assertEqual(rfiles[field].name, field) self.assertEqual(rfiles[field].filename, files[field][0]) self.assertEqual(rfiles[field].content_type, files[field][1]) self.assertEqual(rfiles[field].file.read(), to_bytes(files[field][2])) for field in forms: self.assertEqual(rforms[field], forms[field])
def test_line_parser(self): for line in ('foo', ''): for ending in ('\n', '\r', '\r\n'): i = mp.MultipartParser(BytesIO(to_bytes(line + ending)), 'foo') i = next(i._lineiter()) self.assertEqual(i, (to_bytes(line), to_bytes(ending)))
def write(self, *lines): for line in lines: self.data.write(to_bytes(line))
def test_copyfile(self): source = BytesIO(to_bytes('abc')) target = BytesIO() self.assertEqual(mp.copy_file(source, target), 3) target.seek(0) self.assertEqual(target.read(), to_bytes('abc'))
to_bytes(''' LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0xODY0NTQ2NTE3MTM1MTkzNDE5NTE1ODEwMzAx MDUNCkNvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iZmlsZTEiOyBmaWxlbmFt ZT0iYW5jaG9yLnBuZyINCkNvbnRlbnQtVHlwZTogaW1hZ2UvcG5nDQoNColQTkcNChoKAAAADUlI RFIAAAAQAAAAEAgGAAAAH/P/YQAAAARnQU1BAACvyDcFiukAAAAZdEVYdFNvZnR3YXJlAEFkb2Jl IEltYWdlUmVhZHlxyWU8AAABnUlEQVQ4y6VTMWvCQBS+qwEFB10KGaS1P6FDpw7SrVvzAwRRx04V Ck4K6iAoDhLXdhFcW9qhZCk4FQoW0gp2U4lQRDAUS4hJmn5Xgg2lsQ198PHu3b3vu5d3L9S2bfIf 47wOer1ewzTNtGEYBP48kUjkfsrb8BIAMb1cLovwRfi07wrYzcCr4/1/Am4FzzhzBGZeefR7E7vd 7j0Iu4wYjUYDBMfD0dBiMUQfstns3toKkHgF6EgmqqruW6bFiHcsxr70awVu63Q6NiOmUinquwfM dF1f28CVgCRJx0jMAQ1BEFquRn7CbYVCYZVbr9dbnJMohoIh9kViu90WEW9nMpmxu4JyubyF/VEs FiNcgCPyoyxiu7XhCPBzdU4s652VnUccbDabPLyN2C6VSmwdhFgel5DB84AJb64mEUlvmqadTKcv 40gkUkUsg1DjeZ7iRsrWgByP71T7/afxYrHIYry/eoBD9mxsaK4VRamFw2EBQknMAWGvRClNTpQJ AfkCxFNgBmiez1ipVA4hdgQcOD/TLfylKIo3vubgL/YBnIw+ioOMLtwAAAAASUVORK5CYIINCi0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTg2NDU0NjUxNzEzNTE5MzQxOTUxNTgxMDMwMTA1 DQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImZpbGUyIjsgZmlsZW5hbWU9 ImFwcGxpY2F0aW9uX2VkaXQucG5nIg0KQ29udGVudC1UeXBlOiBpbWFnZS9wbmcNCg0KiVBORw0K GgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdh cmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJRSURBVBgZpcHda81xHMDx9+d3fudYzuYw2RaZ5yTW olEiuZpCSjGJFEktUUr8A6ZxQZGHmDtqdrGUXHgoeZqSp1F2bLFWjtkOB8PZzvmd7+djv5XaBRfL 6yVmxv+QjQeu7l25uuZYJmtxM0AVU8Wpw9RQU8w51AxzDqfKhFjwq6Mjdbj1RN0Zv2ZFzaloUdwr L2Is4r+y7hRwxs8G5mUzPxmrwcA8hvnmjIZtcxmr3Y09hHwzJZQvOAwwNZyCYqgaThVXMFzBCD7f Jfv8MpHiKvaV3ePV2f07fMwIiSeIGeYJJoao4HmCiIeIQzPXifY+paJqO4lZi/nWPZ/krabjvlNH yANMBAQiBiqgakQMCunbxHJviM9bQeZdBzHJUzKhguLJlQnf1BghAmZ4gImAgAjk++8jP56QmL2G XG8zsfFCz8skA1mQXKbaU3X8ISIgQsgDcun7FL7cJjFnLUMfLyLRr0SLS4hbhiup5Szd19rpFYKA ESKICCERoS95neyHmyTmbmAodQ4vGpAfmEn6YTtTahv4ODiRkGdOCUUAAUSE/uQNfqTaKFu4jvyn JiIxIzcwg/SjF1RsOk9R+QJMlZCvqvwhQFdbM4XvrynIVHpfn2ZSWYyhzHS+PUtSueUC0cQ0QmpG yE9197TUnwzq1DnUKbXSxOb6S7xtPkjngzbGVVbzvS/FjaGt9DU8xlRRJdTCMDEzRjuyZ1FwaFe9 j+d4eecaPd1dPxNTSlfWHm1v5y/EzBitblXp4JLZ5f6yBbOwaK5tsD+9c33jq/f8w2+mRSjOllPh kAAAAABJRU5ErkJggg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0xODY0NTQ2NTE3MTM1 MTkzNDE5NTE1ODEwMzAxMDUNCkNvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0i dGV4dCINCg0KZXhhbXBsZSB0ZXh0DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTE4NjQ1 NDY1MTcxMzUxOTM0MTk1MTU4MTAzMDEwNS0tDQo=''')),