From 4f0f3754cf5557e1d84b26ba9218177142b81089 Mon Sep 17 00:00:00 2001 From: Vladislav Vlastovskiy Date: Mon, 14 Apr 2014 14:18:10 +0400 Subject: [PATCH 1/4] Added get filename as encoded This filename described in RFC 6266 --- rest_framework/parsers.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/rest_framework/parsers.py b/rest_framework/parsers.py index 4990971b8..fea5b0e69 100644 --- a/rest_framework/parsers.py +++ b/rest_framework/parsers.py @@ -10,7 +10,7 @@ from django.core.files.uploadhandler import StopFutureHandlers from django.http import QueryDict from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser from django.http.multipartparser import MultiPartParserError, parse_header, ChunkIter -from rest_framework.compat import etree, six, yaml, force_text +from rest_framework.compat import etree, six, yaml, force_text, urlparse from rest_framework.exceptions import ParseError from rest_framework import renderers import json @@ -289,6 +289,17 @@ class FileUploadParser(BaseParser): try: meta = parser_context['request'].META disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'].encode('utf-8')) - return force_text(disposition[1]['filename']) + + filename = force_text(disposition[1]['filename']) + + if 'filename*' in disposition[1]: + filename_encoded = force_text(disposition[1]['filename*']) + try: + charset, filename_encoded = filename_encoded.split('\'\'', 1) + filename = urlparse.unquote(filename_encoded, charset) + except (ValueError, LookupError): + pass + + return filename except (AttributeError, KeyError): pass From 79b709282d87dc3261837e29d0acaf4240b191a3 Mon Sep 17 00:00:00 2001 From: Vladislav Vlastovskiy Date: Mon, 14 Apr 2014 14:25:30 +0400 Subject: [PATCH 2/4] Added test for encoded filename --- rest_framework/tests/test_parsers.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/rest_framework/tests/test_parsers.py b/rest_framework/tests/test_parsers.py index 8af906772..aafb431a2 100644 --- a/rest_framework/tests/test_parsers.py +++ b/rest_framework/tests/test_parsers.py @@ -113,3 +113,27 @@ class TestFileUploadParser(TestCase): parser = FileUploadParser() filename = parser.get_filename(self.stream, None, self.parser_context) self.assertEqual(filename, 'file.txt') + + def test_get_encoded_filename(self): + parser = FileUploadParser() + + self.__replace_content_disposition('inline; filename*=utf-8\'\'ÀĥƦ.txt') + filename = parser.get_filename(self.stream, None, self.parser_context) + self.assertEqual(filename, 'ÀĥƦ.txt') + + self.__replace_content_disposition('inline; filename=fallback.txt; filename*=utf-8\'\'ÀĥƦ.txt') + filename = parser.get_filename(self.stream, None, self.parser_context) + self.assertEqual(filename, 'ÀĥƦ.txt') + + self.__replace_content_disposition('inline; filename=fallback.txt; filename*=utf-8--ÀĥƦ.txt') + filename = parser.get_filename(self.stream, None, self.parser_context) + self.assertEqual(filename, 'fallback.txt') + + self.__replace_content_disposition('inline; filename=fallback.txt; filename*=WRONG\'\'ÀĥƦ.txt') + filename = parser.get_filename(self.stream, None, self.parser_context) + self.assertEqual(filename, 'fallback.txt') + + def __replace_content_disposition(self, disposition): + self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = disposition + + From 37abb62b9dd1eac4676b5c356409a65138870e53 Mon Sep 17 00:00:00 2001 From: Vladislav Vlastovskiy Date: Mon, 14 Apr 2014 15:02:52 +0400 Subject: [PATCH 3/4] Removed assert for wrong charset --- rest_framework/tests/test_parsers.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/rest_framework/tests/test_parsers.py b/rest_framework/tests/test_parsers.py index aafb431a2..d19b46519 100644 --- a/rest_framework/tests/test_parsers.py +++ b/rest_framework/tests/test_parsers.py @@ -1,3 +1,5 @@ +#-*- coding: utf-8 -*- + from __future__ import unicode_literals from rest_framework.compat import StringIO from django import forms @@ -129,10 +131,6 @@ class TestFileUploadParser(TestCase): filename = parser.get_filename(self.stream, None, self.parser_context) self.assertEqual(filename, 'fallback.txt') - self.__replace_content_disposition('inline; filename=fallback.txt; filename*=WRONG\'\'ÀĥƦ.txt') - filename = parser.get_filename(self.stream, None, self.parser_context) - self.assertEqual(filename, 'fallback.txt') - def __replace_content_disposition(self, disposition): self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = disposition From d170595723b20f82510f209728e2154bfa574191 Mon Sep 17 00:00:00 2001 From: Vladislav Vlastovskiy Date: Mon, 14 Apr 2014 15:03:50 +0400 Subject: [PATCH 4/4] Removed use encoding available only in py3 --- rest_framework/parsers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rest_framework/parsers.py b/rest_framework/parsers.py index fea5b0e69..529e640ea 100644 --- a/rest_framework/parsers.py +++ b/rest_framework/parsers.py @@ -290,15 +290,15 @@ class FileUploadParser(BaseParser): meta = parser_context['request'].META disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'].encode('utf-8')) - filename = force_text(disposition[1]['filename']) - if 'filename*' in disposition[1]: filename_encoded = force_text(disposition[1]['filename*']) try: charset, filename_encoded = filename_encoded.split('\'\'', 1) - filename = urlparse.unquote(filename_encoded, charset) + filename = urlparse.unquote(filename_encoded) except (ValueError, LookupError): - pass + filename = force_text(disposition[1]['filename']) + else: + filename = force_text(disposition[1]['filename']) return filename except (AttributeError, KeyError):