Unverified Commit 64f1848d authored by Diederik van der Boor's avatar Diederik van der Boor
Browse files

Fixed python 3 encoding issues with content-disposition

parent 5044b804
# encoding: utf-8
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import RequestFactory from django.test import RequestFactory
...@@ -68,3 +69,40 @@ class ViewTests(PrivateFileTestCase): ...@@ -68,3 +69,40 @@ class ViewTests(PrivateFileTestCase):
self.assertEqual(response['Content-Length'], '5') self.assertEqual(response['Content-Length'], '5')
self.assertEqual(response['Content-Disposition'], "attachment; filename*=UTF-8''test5.txt") self.assertEqual(response['Content-Disposition'], "attachment; filename*=UTF-8''test5.txt")
self.assertIn('Last-Modified', response) self.assertIn('Last-Modified', response)
def test_private_file_view_utf8(self):
"""
Test the detail view that returns the object
"""
obj = CustomerDossier.objects.create(
customer='cust2',
file=SimpleUploadedFile(u'Heizölrückstoßabdämpfung.txt', b'test5')
)
self.assertExists('CustomerDossier', 'cust2', u'Heizölrückstoßabdämpfung.txt')
# Initialize locally, no need for urls.py etc..
# This behaves like a standard DetailView
view = PrivateStorageView.as_view(
content_disposition='attachment',
)
admin = User.objects.create_superuser('admin', 'admin@example.com', 'admin')
for user_agent, expect_header in [
('Firefox', "attachment; filename*=UTF-8''Heiz%C3%B6lr%C3%BCcksto%C3%9Fabd%C3%A4mpfung.txt"),
('WebKit', 'attachment; filename=Heiz\xc3\xb6lr\xc3\xbccksto\xc3\x9fabd\xc3\xa4mpfung.txt'),
('MSIE', 'attachment; '),
]:
request = RequestFactory().get('/cust1/file/')
request.user = admin
request.META['HTTP_USER_AGENT'] = user_agent
response = view(
request,
path=u'CustomerDossier/cust2/Heizölrückstoßabdämpfung.txt'
)
self.assertEqual(list(response.streaming_content), [b'test5'])
self.assertEqual(response['Content-Type'], 'text/plain')
self.assertEqual(response['Content-Length'], '5')
self.assertEqual(response['Content-Disposition'], expect_header, user_agent)
self.assertIn('Last-Modified', response)
...@@ -96,10 +96,12 @@ class PrivateStorageView(View): ...@@ -96,10 +96,12 @@ class PrivateStorageView(View):
response = self.server_class().serve(private_file) response = self.server_class().serve(private_file)
if self.content_disposition: if self.content_disposition:
# Python 3 doesn't support b'..'.format(), and % formatting
# was added in 3.4: # https://bugs.python.org/issue3982
filename = self.get_content_disposition_filename(private_file) filename = self.get_content_disposition_filename(private_file)
response['Content-Disposition'] = '{}; {}'.format( response['Content-Disposition'] = b'; '.join([
self.content_disposition, self._encode_filename_header(filename) self.content_disposition.encode(), self._encode_filename_header(filename)
) ])
return response return response
...@@ -117,16 +119,15 @@ class PrivateStorageView(View): ...@@ -117,16 +119,15 @@ class PrivateStorageView(View):
user_agent = self.request.META.get('HTTP_USER_AGENT', None) user_agent = self.request.META.get('HTTP_USER_AGENT', None)
if 'WebKit' in user_agent: if 'WebKit' in user_agent:
# Support available for UTF-8 encoded strings. # Support available for UTF-8 encoded strings.
utf8_filename = filename.encode("utf-8") return u'filename={}'.format(filename).encode("utf-8")
return 'filename={}'.format(utf8_filename)
elif 'MSIE' in user_agent: elif 'MSIE' in user_agent:
# IE does not support internationalized filename at all. # IE does not support internationalized filename at all.
# It can only recognize internationalized URL, so we should perform a trick via URL names. # It can only recognize internationalized URL, so we should perform a trick via URL names.
return '' return b''
else: else:
# For others like Firefox, we follow RFC2231 (encoding extension in HTTP headers). # For others like Firefox, we follow RFC2231 (encoding extension in HTTP headers).
rfc2231_filename = quote(filename.encode("utf-8")) rfc2231_filename = quote(filename.encode("utf-8"))
return "filename*=UTF-8''{}".format(rfc2231_filename) return "filename*=UTF-8''{}".format(rfc2231_filename).encode("utf-8")
class PrivateStorageDetailView(SingleObjectMixin, PrivateStorageView): class PrivateStorageDetailView(SingleObjectMixin, PrivateStorageView):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment