From a265b26e4109a4b3f9f6a633f57495f7544f4ff1 Mon Sep 17 00:00:00 2001 From: Jack O'Connor Date: Wed, 17 Dec 2014 17:40:12 -0800 Subject: [PATCH] handle quotes in Content-Disposition filenames Summary: The HTTP standard specifies (http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1) that `Content-Disposition` filenames can be quoted. I forgot to handle that. Closes https://github.com/buildinspace/peru/issues/70. Test Plan: Add a couple extra cases to the existing test. Reviewers: sean Reviewed By: sean Differential Revision: https://phabricator.buildinspace.com/D144 --- peru/resources/plugins/curl/curl_plugin.py | 10 +++++++++- tests/test_curl_plugin.py | 10 ++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/peru/resources/plugins/curl/curl_plugin.py b/peru/resources/plugins/curl/curl_plugin.py index cc956cd..5fd04e3 100755 --- a/peru/resources/plugins/curl/curl_plugin.py +++ b/peru/resources/plugins/curl/curl_plugin.py @@ -16,7 +16,15 @@ def get_request_filename(request): pieces = re.split('\s*;\s*', disposition) for piece in pieces: if piece.startswith('filename='): - return piece[len('filename='):] + filename = piece[len('filename='):] + # Strip exactly one " from each end. + if filename.startswith('"'): + filename = filename[1:] + if filename.endswith('"'): + filename = filename[:-1] + # Interpret backslashed quotes. + filename = filename.replace('\\"', '"') + return filename # If no filename was specified, pick a reasonable default. return os.path.basename(urlsplit(request.url).path) or 'index.html' diff --git a/tests/test_curl_plugin.py b/tests/test_curl_plugin.py index 1d83f5d..0957cca 100644 --- a/tests/test_curl_plugin.py +++ b/tests/test_curl_plugin.py @@ -46,6 +46,16 @@ class CurlPluginTest(unittest.TestCase): 'attachment; filename=bar'} self.assertEqual('bar', curl_plugin.get_request_filename(request)) + # Check quoted filenames. + request._info = {'Content-Disposition': + 'attachment; filename="bar"'} + self.assertEqual('bar', + curl_plugin.get_request_filename(request)) + # Check backslashed quotes in filenames. + request._info = {'Content-Disposition': + 'attachment; filename="bar\\""'} + self.assertEqual('bar"', + curl_plugin.get_request_filename(request)) def test_download_file_with_length(self): content = b'xy' * 4096