Improved Content-Disposition parsing for --download mode

Closes #168.
This commit is contained in:
Jakub Roztocil 2013-09-24 19:50:37 +02:00
parent 354aaa94bd
commit 29f6b6a2a9
3 changed files with 19 additions and 7 deletions

View File

@ -1216,6 +1216,7 @@ Changelog
* `0.7.0-dev`_ * `0.7.0-dev`_
* Added ``--ignore-stdin``. * Added ``--ignore-stdin``.
* Added support for auth plugins. * Added support for auth plugins.
* Improved ``Content-Disposition`` parsing for ``--download`` mode.
* `0.6.0`_ (2013-06-03) * `0.6.0`_ (2013-06-03)
* XML data is now formatted. * XML data is now formatted.
* ``--session`` and ``--session-read-only`` now also accept paths to * ``--session`` and ``--session-read-only`` now also accept paths to

View File

@ -10,6 +10,7 @@ import sys
import mimetypes import mimetypes
import threading import threading
from time import sleep, time from time import sleep, time
from mailbox import Message
from .output import RawStream from .output import RawStream
from .models import HTTPResponse from .models import HTTPResponse
@ -104,11 +105,14 @@ def filename_from_content_disposition(content_disposition):
""" """
# attachment; filename=jkbr-httpie-0.4.1-20-g40bd8f6.tar.gz # attachment; filename=jkbr-httpie-0.4.1-20-g40bd8f6.tar.gz
match = re.search('filename=(\S+)', content_disposition)
if match and match.group(1): msg = Message('Content-Disposition: %s' % content_disposition)
fn = match.group(1).strip('."') filename = msg.get_filename()
if re.match('^[a-zA-Z0-9._-]+$', fn): if filename:
return fn # Basic sanitation.
filename = os.path.basename(filename).lstrip('.').strip()
if filename:
return filename
def filename_from_url(url, content_type): def filename_from_url(url, content_type):

View File

@ -1562,9 +1562,16 @@ class DownloadUtilsTest(BaseTestCase):
parse('attachment; filename=".hello-WORLD_123.txt"'), parse('attachment; filename=".hello-WORLD_123.txt"'),
'hello-WORLD_123.txt' 'hello-WORLD_123.txt'
) )
self.assertEqual(
parse('attachment; filename="white space.txt"'),
'white space.txt'
)
self.assertEqual(
parse(r'attachment; filename="\"quotes\".txt"'),
'"quotes".txt'
)
self.assertEqual(parse('attachment; filename=/etc/hosts'), 'hosts')
self.assertIsNone(parse('attachment; filename=')) self.assertIsNone(parse('attachment; filename='))
self.assertIsNone(parse('attachment; filename=/etc/hosts'))
self.assertIsNone(parse('attachment; filename=hello@world'))
def test_filename_from_url(self): def test_filename_from_url(self):
self.assertEqual(filename_from_url( self.assertEqual(filename_from_url(