diff --git a/django/core/files/uploadedfile.py b/django/core/files/uploadedfile.py
index 20eaece..81dce38 100644
a
|
b
|
Classes representing uploaded files.
|
3 | 3 | """ |
4 | 4 | |
5 | 5 | import errno |
6 | | import os |
| 6 | import ntpath |
7 | 7 | from io import BytesIO |
8 | 8 | |
9 | 9 | from django.conf import settings |
… |
… |
class UploadedFile(File):
|
42 | 42 | def _set_name(self, name): |
43 | 43 | # Sanitize the file name so that it can't be dangerous. |
44 | 44 | if name is not None: |
| 45 | # If name ends in backslash replace with 0 |
| 46 | if name[-1] == "\\": |
| 47 | name = name[:-1] + "0" |
45 | 48 | # Just use the basename of the file -- anything else is dangerous. |
46 | | name = os.path.basename(name) |
| 49 | name = ntpath.basename(name) |
47 | 50 | |
48 | 51 | # File names longer than 255 characters can cause problems on older OSes. |
49 | 52 | if len(name) > 255: |
50 | | name, ext = os.path.splitext(name) |
| 53 | name, ext = ntpath.splitext(name) |
51 | 54 | ext = ext[:255] |
52 | 55 | name = name[:255 - len(ext)] + ext |
53 | 56 | |
diff --git a/django/http/multipartparser.py b/django/http/multipartparser.py
index 53e4149..474619e 100644
a
|
b
|
class MultiPartParser(object):
|
184 | 184 | if not file_name: |
185 | 185 | continue |
186 | 186 | file_name = force_text(file_name, encoding, errors='replace') |
187 | | file_name = self.IE_sanitize(unescape_entities(file_name)) |
| 187 | file_name = unescape_entities(file_name) |
188 | 188 | |
189 | 189 | content_type, content_type_extra = meta_data.get('content-type', ('', {})) |
190 | 190 | content_type = content_type.strip() |
… |
… |
class MultiPartParser(object):
|
274 | 274 | file_obj) |
275 | 275 | break |
276 | 276 | |
277 | | def IE_sanitize(self, filename): |
278 | | """Cleanup filename from Internet Explorer full paths.""" |
279 | | return filename and filename[filename.rfind("\\") + 1:].strip() |
280 | | |
281 | 277 | def _close_files(self): |
282 | 278 | # Free up all file handles. |
283 | 279 | # FIXME: this currently assumes that upload handlers store the file as 'file' |
diff --git a/tests/file_uploads/tests.py b/tests/file_uploads/tests.py
old mode 100644
new mode 100755
index 91b959b..9a5680d
a
|
b
|
|
1 | 1 | #! -*- coding: utf-8 -*- |
| 2 | # coding: utf-8 |
| 3 | |
2 | 4 | from __future__ import unicode_literals |
3 | 5 | |
4 | 6 | import base64 |
… |
… |
class FileUploadTests(TestCase):
|
507 | 509 | # shouldn't differ. |
508 | 510 | self.assertEqual(os.path.basename(obj.testfile.path), 'MiXeD_cAsE.txt') |
509 | 511 | |
| 512 | def test_fail_backslash(self): |
| 513 | """ |
| 514 | Tests filename ending with a backslash, issue #18150 reports crashes |
| 515 | when a filename ends with a backslash |
| 516 | """ |
| 517 | name_backslash = "backslash.jpg\\" |
| 518 | payload = client.FakePayload() |
| 519 | payload.write('\r\n'.join([ |
| 520 | '--' + client.BOUNDARY, |
| 521 | 'Content-Disposition: form-data; name="file1"; filename="%s"' % name_backslash, |
| 522 | 'Content-Type: application/octet-stream', |
| 523 | '', |
| 524 | '' |
| 525 | ])) |
| 526 | payload.write('\r\n--' + client.BOUNDARY + '--\r\n') |
| 527 | |
| 528 | r = { |
| 529 | 'CONTENT_LENGTH': len(payload), |
| 530 | 'CONTENT_TYPE': client.MULTIPART_CONTENT, |
| 531 | 'PATH_INFO': "/file_uploads/echo/", |
| 532 | 'REQUEST_METHOD': 'POST', |
| 533 | 'wsgi.input': payload, |
| 534 | } |
| 535 | response = self.client.request(**r) |
| 536 | self.assertEqual(response.status_code, 200) |
| 537 | |
510 | 538 | |
511 | 539 | @override_settings(MEDIA_ROOT=MEDIA_ROOT) |
512 | 540 | class DirectoryCreationTests(TestCase): |