diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7d4b23bbb..a99adc176 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ django-storages CHANGELOG ========================= +1.7.1 (2018-09-XX) +****************** + +- Fix off-by-1 error in ``get_available_name`` whenever ``file_overwrite`` or ``overwrite_files`` is ``True`` (`#588`_, `#589`_) + +.. _#588: https://github.com/jschneier/django-storages/issues/588 +.. _#589: https://github.com/jschneier/django-storages/pull/589 + 1.7 (2018-09-03) **************** diff --git a/storages/utils.py b/storages/utils.py index 5e3997352..14d47b067 100644 --- a/storages/utils.py +++ b/storages/utils.py @@ -102,7 +102,7 @@ def lookup_env(names): def get_available_overwrite_name(name, max_length): - if max_length is None or len(name) < max_length: + if max_length is None or len(name) <= max_length: return name # Adapted from Django diff --git a/tests/test_gcloud.py b/tests/test_gcloud.py index 06f0dd4ec..1d3a8f723 100644 --- a/tests/test_gcloud.py +++ b/tests/test_gcloud.py @@ -8,9 +8,7 @@ import mimetypes from datetime import datetime, timedelta -from django.core.exceptions import ( - ImproperlyConfigured, SuspiciousFileOperation, -) +from django.core.exceptions import ImproperlyConfigured from django.core.files.base import ContentFile from django.test import TestCase from django.utils import timezone @@ -376,14 +374,6 @@ def test_get_available_name_unicode(self): filename = 'ủⓝï℅ⅆℇ.txt' self.assertEqual(self.storage.get_available_name(filename), filename) - def test_get_available_name_overwrite_maxlength(self): - self.storage.file_overwrite = True - - self.assertEqual(self.storage.get_available_name('test/foo.txt', 11), 'test/fo.txt') - self.assertEqual(self.storage.get_available_name('test_a/foobar.txt', None), 'test_a/foobar.txt') - with self.assertRaises(SuspiciousFileOperation): - self.storage.get_available_name('test_a/foobar.txt', 10) - def test_cache_control(self): data = 'This is some test content.' filename = 'cache_control_file.txt' diff --git a/tests/test_utils.py b/tests/test_utils.py index 2fcee3ac3..e411d232c 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,9 +1,11 @@ import datetime from django.conf import settings +from django.core.exceptions import SuspiciousFileOperation from django.test import TestCase from storages import utils +from storages.utils import get_available_overwrite_name as gaon class SettingTest(TestCase): @@ -108,3 +110,26 @@ def test_join_nothing(self): def test_with_base_url_join_nothing(self): path = utils.safe_join('base_url') self.assertEqual(path, 'base_url/') + + +class TestGetAvailableOverwriteName(TestCase): + def test_maxlength_is_none(self): + name = 'superlong/file/with/path.txt' + self.assertEqual(gaon(name, None), name) + + def test_maxlength_equals_name(self): + name = 'parent/child.txt' + self.assertEqual(gaon(name, len(name)), name) + + def test_maxlength_is_greater_than_name(self): + name = 'parent/child.txt' + self.assertEqual(gaon(name, len(name) + 1), name) + + def test_maxlength_less_than_name(self): + name = 'parent/child.txt' + self.assertEqual(gaon(name, len(name) - 1), 'parent/chil.txt') + + def test_truncates_away_filename_raises(self): + name = 'parent/child.txt' + with self.assertRaises(SuspiciousFileOperation): + gaon(name, len(name) - 5)