| 1 | """Tests the SafeMultipartFilter for handling dodgy multipart requests.""" |
|---|
| 2 | |
|---|
| 3 | from turbogears import config, controllers, expose, testutil |
|---|
| 4 | from webtest import TestRequest |
|---|
| 5 | |
|---|
| 6 | class TestRoot(controllers.RootController): |
|---|
| 7 | |
|---|
| 8 | @expose() |
|---|
| 9 | def flashupload(self, filedata, upload, filename): |
|---|
| 10 | return dict( |
|---|
| 11 | filedata = filedata.file.read(), |
|---|
| 12 | filename = filename, |
|---|
| 13 | upload = upload, |
|---|
| 14 | ) |
|---|
| 15 | |
|---|
| 16 | class SafeMultipartFilterTest(testutil.TGTest): |
|---|
| 17 | |
|---|
| 18 | def setUp(self): |
|---|
| 19 | config.update({ |
|---|
| 20 | '/flashupload': { |
|---|
| 21 | 'safempfilter.on': True |
|---|
| 22 | } |
|---|
| 23 | }) |
|---|
| 24 | self.root = TestRoot |
|---|
| 25 | super(SafeMultipartFilterTest, self).setUp() |
|---|
| 26 | |
|---|
| 27 | def test_flash_upload(self): |
|---|
| 28 | """SafeMultipartFilter correctly handles file uploads from Flash client |
|---|
| 29 | """ |
|---|
| 30 | headers = [ |
|---|
| 31 | ('Accept', 'text/*'), |
|---|
| 32 | ('Content-Type', 'multipart/form-data; ' |
|---|
| 33 | 'boundary=----------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6'), |
|---|
| 34 | ('User-Agent', 'Shockwave Flash'), |
|---|
| 35 | ('Host', 'www.example.com:8080'), |
|---|
| 36 | ('Content-Length', '499'), |
|---|
| 37 | ('Connection', 'Keep-Alive'), |
|---|
| 38 | ('Cache-Control', 'no-cache'), |
|---|
| 39 | ] |
|---|
| 40 | filedata = ('<?xml version="1.0" encoding="UTF-8"?>\r\n' |
|---|
| 41 | '<projectDescription>\r\n' |
|---|
| 42 | '</projectDescription>\r\n') |
|---|
| 43 | body = ( |
|---|
| 44 | '------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6\r\n' |
|---|
| 45 | 'Content-Disposition: form-data; name="filename"\r\n' |
|---|
| 46 | '\r\n' |
|---|
| 47 | '.project\r\n' |
|---|
| 48 | '------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6\r\n' |
|---|
| 49 | 'Content-Disposition: form-data; ' |
|---|
| 50 | 'name="filedata"; filename=".project"\r\n' |
|---|
| 51 | 'Content-Type: application/octet-stream\r\n' |
|---|
| 52 | '\r\n' |
|---|
| 53 | + filedata + |
|---|
| 54 | '\r\n' |
|---|
| 55 | '------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6\r\n' |
|---|
| 56 | 'Content-Disposition: form-data; name="upload"\r\n' |
|---|
| 57 | '\r\n' |
|---|
| 58 | 'Submit Query\r\n' |
|---|
| 59 | # Flash apps omit the trailing \r\n on the last line: |
|---|
| 60 | '------------KM7Ij5cH2KM7Ef1gL6ae0ae0cH2gL6--' |
|---|
| 61 | ) |
|---|
| 62 | environ = self.app._make_environ(dict(REQUEST_METHOD='POST')) |
|---|
| 63 | req = TestRequest.blank('/flashupload', environ) |
|---|
| 64 | req.headers.update(dict(headers)) |
|---|
| 65 | req.body = body |
|---|
| 66 | print repr(str(req)) |
|---|
| 67 | response = self.app.do_request(req, 200, True) |
|---|
| 68 | print response |
|---|
| 69 | assert response.raw['upload'] == 'Submit Query' |
|---|
| 70 | assert response.raw['filename'] == '.project' |
|---|
| 71 | assert response.raw['filedata'] == filedata |
|---|