diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dc67d033a..47a56982a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,12 @@ django-storages change log ========================== +1.6.1 (UNRELEASED) +****************** + +* Fix regression in ``safe_join()`` to allow joining a base path with an empty + string. + 1.6 (2017-06-21) ****************** @@ -363,4 +369,3 @@ since March 2013. .. _#89: https://bitbucket.org/david/django-storages/issue/89/112-broke-the-mosso-backend .. _pull request #5: https://bitbucket.org/david/django-storages/pull-request/5/fixed-path-bug-and-added-testcase-for - diff --git a/storages/utils.py b/storages/utils.py index 3637f6590..b1ff45d5d 100644 --- a/storages/utils.py +++ b/storages/utils.py @@ -60,15 +60,15 @@ def safe_join(base, *paths): """ base_path = force_text(base) base_path = base_path.rstrip('/') - paths = [force_text(p) for p in paths] + paths = [base_path + '/'] + [force_text(p) for p in paths if p] - final_path = posixpath.normpath(posixpath.join(base_path + '/', *paths)) + final_path = posixpath.normpath(posixpath.join(*paths)) # posixpath.normpath() strips the trailing /. Add it back. if paths[-1].endswith('/'): final_path += '/' # Ensure final_path starts with base_path and that the next character after - # the final path is /. + # the base path is /. base_path_len = len(base_path) if (not final_path.startswith(base_path) or final_path[base_path_len] != '/'): raise ValueError('the joined path is located outside of the base path' diff --git a/tests/test_utils.py b/tests/test_utils.py index af14a4cb5..d76697b4d 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -90,3 +90,7 @@ def test_datetime_isoformat(self): dt = datetime.datetime(2017, 5, 19, 14, 45, 37, 123456) path = utils.safe_join('base_url', dt.isoformat()) self.assertEqual(path, 'base_url/2017-05-19T14:45:37.123456') + + def test_join_empty_string(self): + path = utils.safe_join('base_url', '') + self.assertEqual(path, 'base_url/')