Skip to content

Commit

Permalink
Use us-ascii encoding for the content-disposition header
Browse files Browse the repository at this point in the history
modified:   src/Testing/ZopeTestCase/testZODBCompat.py
modified:   src/ZPublisher/http_header_utils.py
modified:   src/ZPublisher/tests/test_http_header_utils.py
  • Loading branch information
jugmac00 committed Sep 29, 2020
1 parent 514c373 commit 8381276
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 6 deletions.
4 changes: 2 additions & 2 deletions src/Testing/ZopeTestCase/testZODBCompat.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ def testExportNonLatinFileNames(self):
found = False
for header in response.listHeaders():
if header[0] == 'Content-Disposition':
# value needs to be latin-1 compatible
assert header[1].encode("latin-1")
# value needs to be `us-ascii` compatible
assert header[1].encode("us-ascii")
found = True
self.assertTrue(found)

Expand Down
8 changes: 5 additions & 3 deletions src/ZPublisher/http_header_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ def make_content_disposition(disposition, file_name):
"""
header = f'{disposition}'
try:
file_name.encode("latin-1")
file_name.encode('us-ascii')
except UnicodeEncodeError:
# the file cannot be encoded using the `latin-1` encoding
# which is required for HTTP headers
# the file cannot be encoded using the `us-ascii` encoding
# which is advocated by RFC 7230 - 7237
#
# a special header has to be crafted
# also see https://tools.ietf.org/html/rfc6266#appendix-D
encoded_file_name = file_name.encode('us-ascii', errors='ignore')
header += f'; filename="{encoded_file_name}"'
quoted_file_name = urllib.parse.quote(file_name)
header += f'; filename*=UTF-8\'\'{quoted_file_name}'
return header
Expand Down
8 changes: 7 additions & 1 deletion src/ZPublisher/tests/test_http_header_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ def test_ascii(self):
make_content_disposition("inline", "iq.png"),
'inline; filename="iq.png"')

def test_latin_one(self):
self.assertEqual(
make_content_disposition('inline', 'Dänemark.png'),
'inline; filename="b\'Dnemark.png\'"; filename*=UTF-8\'\'D%C3%A4nemark.png' # noqa: E501
)

def test_unicode(self):
"""HTTP headers need to be latin-1 compatible
Expand All @@ -33,5 +39,5 @@ def test_unicode(self):
"""
self.assertEqual(
make_content_disposition("inline", "ıq.png"),
"""inline; filename*=UTF-8''%C4%B1q.png"""
'inline; filename="b\'q.png\'"; filename*=UTF-8\'\'%C4%B1q.png'
)

0 comments on commit 8381276

Please sign in to comment.