summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Samarchyan <anton.samarchyan@savoirfairelinux.com>2016-12-28 15:20:24 -0500
committerTim Graham <timograham@gmail.com>2016-12-28 19:14:58 -0500
commit5cf4894836bd537161df467890d9b986678a7937 (patch)
tree0ae370e4ad23c00e02943814daa2e99fdd0aaaec
parent4579c3f6b8d3a5ebd6c570836cd0552892eb0d61 (diff)
Fixed #27628 -- Fixed unarchiving a file without permission data.
-rw-r--r--AUTHORS1
-rw-r--r--django/utils/archive.py17
-rw-r--r--tests/utils_tests/archives/foobar.tarbin5632 -> 10240 bytes
-rw-r--r--tests/utils_tests/archives/foobar.tar.bz2bin265 -> 294 bytes
-rw-r--r--tests/utils_tests/archives/foobar.tar.gzbin253 -> 291 bytes
-rw-r--r--tests/utils_tests/archives/foobar.zipbin810 -> 1434 bytes
-rw-r--r--tests/utils_tests/test_archive.py4
7 files changed, 19 insertions, 3 deletions
diff --git a/AUTHORS b/AUTHORS
index 82938eea88..4a7396a7a9 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -63,6 +63,7 @@ answer newbie questions, and generally made Django that much better:
Anssi Kääriäinen <akaariai@gmail.com>
ant9000@netwise.it
Anthony Briggs <anthony.briggs@gmail.com>
+ Anton Samarchyan <desecho@gmail.com>
Antoni Aloy
Antonio Cavedoni <http://cavedoni.com/>
Antonis Christofides <anthony@itia.ntua.gr>
diff --git a/django/utils/archive.py b/django/utils/archive.py
index f8c1a0f83b..57e87658a6 100644
--- a/django/utils/archive.py
+++ b/django/utils/archive.py
@@ -23,6 +23,7 @@ THE SOFTWARE.
"""
import os
import shutil
+import stat
import tarfile
import zipfile
@@ -98,6 +99,16 @@ class BaseArchive(object):
"""
Base Archive class. Implementations should inherit this class.
"""
+ @staticmethod
+ def _copy_permissions(mode, filename):
+ """
+ If the file in the archive has some permissions (this assumes a file
+ won't be writable/executable without being readable), apply those
+ permissions to the unarchived file.
+ """
+ if mode & stat.S_IROTH:
+ os.chmod(filename, mode)
+
def split_leading_dir(self, path):
path = str(path)
path = path.lstrip('/').lstrip('\\')
@@ -164,7 +175,7 @@ class TarArchive(BaseArchive):
os.makedirs(dirname)
with open(filename, 'wb') as outfile:
shutil.copyfileobj(extracted, outfile)
- os.chmod(filename, member.mode)
+ self._copy_permissions(member.mode, filename)
finally:
if extracted:
extracted.close()
@@ -200,9 +211,9 @@ class ZipArchive(BaseArchive):
else:
with open(filename, 'wb') as outfile:
outfile.write(data)
- # convert ZipInfo.external_attr to mode
+ # Convert ZipInfo.external_attr to mode
mode = info.external_attr >> 16
- os.chmod(filename, mode)
+ self._copy_permissions(mode, filename)
def close(self):
self._archive.close()
diff --git a/tests/utils_tests/archives/foobar.tar b/tests/utils_tests/archives/foobar.tar
index 44886fb33b..7e619b41d6 100644
--- a/tests/utils_tests/archives/foobar.tar
+++ b/tests/utils_tests/archives/foobar.tar
Binary files differ
diff --git a/tests/utils_tests/archives/foobar.tar.bz2 b/tests/utils_tests/archives/foobar.tar.bz2
index 5a3d8a402e..e4e6c6ab68 100644
--- a/tests/utils_tests/archives/foobar.tar.bz2
+++ b/tests/utils_tests/archives/foobar.tar.bz2
Binary files differ
diff --git a/tests/utils_tests/archives/foobar.tar.gz b/tests/utils_tests/archives/foobar.tar.gz
index 8582a87139..a5f06b1308 100644
--- a/tests/utils_tests/archives/foobar.tar.gz
+++ b/tests/utils_tests/archives/foobar.tar.gz
Binary files differ
diff --git a/tests/utils_tests/archives/foobar.zip b/tests/utils_tests/archives/foobar.zip
index b02bb3e95a..9956385ee2 100644
--- a/tests/utils_tests/archives/foobar.zip
+++ b/tests/utils_tests/archives/foobar.zip
Binary files differ
diff --git a/tests/utils_tests/test_archive.py b/tests/utils_tests/test_archive.py
index 42f445ce9c..b207a1290a 100644
--- a/tests/utils_tests/test_archive.py
+++ b/tests/utils_tests/test_archive.py
@@ -51,6 +51,10 @@ class ArchiveTester(object):
filepath = os.path.join(self.tmpdir, 'executable')
# The file has executable permission.
self.assertTrue(os.stat(filepath).st_mode & stat.S_IXOTH)
+ filepath = os.path.join(self.tmpdir, 'no_permissions')
+ # The file is readable even though it doesn't have permission data in
+ # the archive.
+ self.assertTrue(os.stat(filepath).st_mode & stat.S_IROTH)
def test_extract_function_with_leadpath(self):
extract(self.archive_lead_path, self.tmpdir)