diff options
| -rw-r--r-- | matweb/frontend.py | 6 | ||||
| -rw-r--r-- | matweb/rest_api.py | 10 | ||||
| -rw-r--r-- | matweb/utils.py | 2 | ||||
| -rw-r--r-- | test/test.py | 12 | ||||
| -rw-r--r-- | test/test_api.py | 21 |
5 files changed, 46 insertions, 5 deletions
diff --git a/matweb/frontend.py b/matweb/frontend.py index 2e25467..8295f4e 100644 --- a/matweb/frontend.py +++ b/matweb/frontend.py | |||
| @@ -53,8 +53,12 @@ def upload_file(): | |||
| 53 | if not uploaded_file.filename: | 53 | if not uploaded_file.filename: |
| 54 | flash('No selected file') | 54 | flash('No selected file') |
| 55 | return redirect(request.url) | 55 | return redirect(request.url) |
| 56 | try: | ||
| 57 | filename, filepath = utils.save_file(uploaded_file, current_app.config['UPLOAD_FOLDER']) | ||
| 58 | except ValueError: | ||
| 59 | flash('Invalid Filename') | ||
| 60 | return redirect(request.url) | ||
| 56 | 61 | ||
| 57 | filename, filepath = utils.save_file(uploaded_file, current_app.config['UPLOAD_FOLDER']) | ||
| 58 | parser, mime = utils.get_file_parser(filepath) | 62 | parser, mime = utils.get_file_parser(filepath) |
| 59 | 63 | ||
| 60 | if parser is None: | 64 | if parser is None: |
diff --git a/matweb/rest_api.py b/matweb/rest_api.py index 4098050..a07d2d2 100644 --- a/matweb/rest_api.py +++ b/matweb/rest_api.py | |||
| @@ -28,11 +28,15 @@ class APIUpload(Resource): | |||
| 28 | args = req_parser.parse_args() | 28 | args = req_parser.parse_args() |
| 29 | try: | 29 | try: |
| 30 | file_data = base64.b64decode(args['file']) | 30 | file_data = base64.b64decode(args['file']) |
| 31 | except binascii.Error as err: | 31 | except (binascii.Error, ValueError): |
| 32 | abort(400, message='Failed decoding file: ' + str(err)) | 32 | abort(400, message='Failed decoding file') |
| 33 | 33 | ||
| 34 | file = FileStorage(stream=io.BytesIO(file_data), filename=args['file_name']) | 34 | file = FileStorage(stream=io.BytesIO(file_data), filename=args['file_name']) |
| 35 | filename, filepath = utils.save_file(file, self.upload_folder) | 35 | try: |
| 36 | filename, filepath = utils.save_file(file, self.upload_folder) | ||
| 37 | except ValueError: | ||
| 38 | abort(400, message='Invalid Filename') | ||
| 39 | |||
| 36 | parser, mime = utils.get_file_parser(filepath) | 40 | parser, mime = utils.get_file_parser(filepath) |
| 37 | 41 | ||
| 38 | if parser is None: | 42 | if parser is None: |
diff --git a/matweb/utils.py b/matweb/utils.py index ec9b99c..20c213d 100644 --- a/matweb/utils.py +++ b/matweb/utils.py | |||
| @@ -65,6 +65,8 @@ def get_supported_extensions(): | |||
| 65 | 65 | ||
| 66 | def save_file(file, upload_folder): | 66 | def save_file(file, upload_folder): |
| 67 | filename = secure_filename(file.filename) | 67 | filename = secure_filename(file.filename) |
| 68 | if not filename: | ||
| 69 | raise ValueError('Invalid Filename') | ||
| 68 | filepath = os.path.join(upload_folder, filename) | 70 | filepath = os.path.join(upload_folder, filename) |
| 69 | file.save(os.path.join(filepath)) | 71 | file.save(os.path.join(filepath)) |
| 70 | return filename, filepath | 72 | return filename, filepath |
diff --git a/test/test.py b/test/test.py index 2d09662..7431881 100644 --- a/test/test.py +++ b/test/test.py | |||
| @@ -179,6 +179,18 @@ class Mat2WebTestCase(TestCase): | |||
| 179 | self.assertIn(b'.mp2', rv.data) | 179 | self.assertIn(b'.mp2', rv.data) |
| 180 | self.assertEqual(rv.status_code, 200) | 180 | self.assertEqual(rv.status_code, 200) |
| 181 | 181 | ||
| 182 | def test_get_upload_naughty_input(self): | ||
| 183 | rv = self.client.post( | ||
| 184 | '/', | ||
| 185 | data=dict( | ||
| 186 | file=(io.BytesIO(b"a"), '﷽'), | ||
| 187 | ), | ||
| 188 | follow_redirects=True | ||
| 189 | ) | ||
| 190 | self.assertEqual(rv.status_code, 200) | ||
| 191 | self.assertIn(b'Invalid Filename', rv.data) | ||
| 192 | |||
| 193 | |||
| 182 | 194 | ||
| 183 | if __name__ == '__main__': | 195 | if __name__ == '__main__': |
| 184 | unittest.main() | 196 | unittest.main() |
diff --git a/test/test_api.py b/test/test_api.py index 4925d9e..af736af 100644 --- a/test/test_api.py +++ b/test/test_api.py | |||
| @@ -70,7 +70,7 @@ class Mat2APITestCase(unittest.TestCase): | |||
| 70 | 70 | ||
| 71 | self.assertEqual(request.status_code, 400) | 71 | self.assertEqual(request.status_code, 400) |
| 72 | error = request.get_json()['message'] | 72 | error = request.get_json()['message'] |
| 73 | self.assertEqual(error, 'Failed decoding file: Incorrect padding') | 73 | self.assertEqual(error, 'Failed decoding file') |
| 74 | 74 | ||
| 75 | def test_api_not_supported(self): | 75 | def test_api_not_supported(self): |
| 76 | request = self.app.post('/api/upload', | 76 | request = self.app.post('/api/upload', |
| @@ -400,6 +400,25 @@ class Mat2APITestCase(unittest.TestCase): | |||
| 400 | request = app.get(download_link) | 400 | request = app.get(download_link) |
| 401 | self.assertEqual(code, request.status_code) | 401 | self.assertEqual(code, request.status_code) |
| 402 | 402 | ||
| 403 | def test_upload_naughty_input(self): | ||
| 404 | request = self.app.post('/api/upload', | ||
| 405 | data='{"file_name": "\\\\", ' | ||
| 406 | '"file": "\\\\"}', | ||
| 407 | headers={'content-type': 'application/json'} | ||
| 408 | ) | ||
| 409 | error_message = request.get_json()['message'] | ||
| 410 | self.assertEqual(400, request.status_code) | ||
| 411 | self.assertEqual("Invalid Filename", error_message) | ||
| 412 | |||
| 413 | request = self.app.post('/api/upload', | ||
| 414 | data='{"file_name": "﷽", ' | ||
| 415 | '"file": "﷽"}', | ||
| 416 | headers={'content-type': 'application/json'} | ||
| 417 | ) | ||
| 418 | error_message = request.get_json()['message'] | ||
| 419 | self.assertEqual(400, request.status_code) | ||
| 420 | self.assertEqual("Failed decoding file", error_message) | ||
| 421 | |||
| 403 | 422 | ||
| 404 | if __name__ == '__main__': | 423 | if __name__ == '__main__': |
| 405 | unittest.main() | 424 | unittest.main() |
