diff options
author | Marcel Hellkamp <marc@gsites.de> | 2014-02-06 09:55:37 -0600 |
---|---|---|
committer | Marcel Hellkamp <marc@gsites.de> | 2014-02-06 09:56:10 -0600 |
commit | 4f6f71b4a2b06be0757f10a1af53a9b849a534dc (patch) | |
tree | d839ecae8ce19d52da72efe0e4dc9b8c129067b7 | |
parent | 58d009e5921670f7b99300cdc0e6287d73351852 (diff) | |
download | bottle-4f6f71b4a2b06be0757f10a1af53a9b849a534dc.tar.gz |
fix 582: Unnecessary lowercasing in FileUpload.filename
-rw-r--r-- | bottle.py | 24 | ||||
-rw-r--r-- | test/test_fileupload.py | 8 |
2 files changed, 20 insertions, 12 deletions
@@ -42,6 +42,8 @@ from datetime import date as datedate, datetime, timedelta from tempfile import TemporaryFile from traceback import format_exc, print_exc from inspect import getargspec +from unicodedata import normalize + try: from simplejson import dumps as json_dumps, loads as json_lds except ImportError: # pragma: no cover @@ -2258,19 +2260,21 @@ class FileUpload(object): @cached_property def filename(self): ''' Name of the file on the client file system, but normalized to ensure - file system compatibility (lowercase, no whitespace, no path - separators, no unsafe characters, ASCII only). An empty filename - is returned as 'empty'. + file system compatibility. An empty filename is returned as 'empty'. + + Only ASCII letters, digits, dashes, underscores and dots are + allowed in the final filename. Accents are removed, if possible. + Whitespace is replaced by a single dash. Leading or tailing dots + or dashes are removed. The filename is limited to 255 characters. ''' - from unicodedata import normalize #TODO: Module level import? fname = self.raw_filename - if isinstance(fname, unicode): - fname = normalize('NFKD', fname).encode('ASCII', 'ignore') - fname = fname.decode('ASCII', 'ignore') + if not isinstance(fname, unicode): + fname = fname.decode('utf8', 'ignore') + fname = normalize('NFKD', fname).encode('ASCII', 'ignore').decode('ASCII') fname = os.path.basename(fname.replace('\\', os.path.sep)) - fname = re.sub(r'[^a-zA-Z0-9-_.\s]', '', fname).strip().lower() - fname = re.sub(r'[-\s]+', '-', fname.strip('.').strip()) - return fname or 'empty' + fname = re.sub(r'[^a-zA-Z0-9-_.\s]', '', fname).strip() + fname = re.sub(r'[-\s]+', '-', fname).strip('.-') + return fname[:255] or 'empty' def _copy_file(self, fp, chunk_size=2**16): read, write, offset = self.file.read, fp.write, self.file.tell() diff --git a/test/test_fileupload.py b/test/test_fileupload.py index c1a2130..13e8c7a 100644 --- a/test/test_fileupload.py +++ b/test/test_fileupload.py @@ -21,17 +21,21 @@ class TestFileUpload(unittest.TestCase): def test_filename(self): self.assertFilename('with space', 'with-space') self.assertFilename('with more \t\n\r space', 'with-more-space') - self.assertFilename('UpperCase', 'uppercase') self.assertFilename('with/path', 'path') self.assertFilename('../path', 'path') self.assertFilename('..\\path', 'path') self.assertFilename('..', 'empty') self.assertFilename('.name.', 'name') + self.assertFilename('.name.cfg', 'name.cfg') self.assertFilename(' . na me . ', 'na-me') self.assertFilename('path/', 'empty') - self.assertFilename(bottle.tob('ümläüts$'), 'mlts') + self.assertFilename(bottle.tob('ümläüts$'), 'umlauts') self.assertFilename(bottle.touni('ümläüts$'), 'umlauts') self.assertFilename('', 'empty') + self.assertFilename('a'+'b'*1337+'c', 'a'+'b'*254) + + def test_preserve_case_issue_582(self): + self.assertFilename('UpperCase', 'UpperCase') def test_save_buffer(self): fu = FileUpload(open(__file__, 'rb'), 'testfile', __file__) |