]> granicus.if.org Git - python/commitdiff
Change the zipimport implementation to accept files containing
authorThomas Heller <theller@ctypes.org>
Tue, 22 Jul 2003 18:10:15 +0000 (18:10 +0000)
committerThomas Heller <theller@ctypes.org>
Tue, 22 Jul 2003 18:10:15 +0000 (18:10 +0000)
arbitrary bytes before the actual zip compatible archive.  Zipfiles
containing comments at the end of the file are still not supported.

Add a testcase to test_zipimport, and update NEWS.

This closes sf #775637 and sf #669036.

Lib/test/test_zipimport.py
Misc/NEWS
Modules/zipimport.c

index 26a2f1f4365cffbe5fa6d9bf2d8f56048c2b1c48..86acdd20918a669a54adb9393f2a44f24884e649 100644 (file)
@@ -49,7 +49,7 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
         zipimport._zip_directory_cache.clear()
         ImportHooksBaseTestCase.setUp(self)
 
-    def doTest(self, expected_ext, files, *modules):
+    def doTest(self, expected_ext, files, *modules, **kw):
         z = ZipFile(TEMP_ZIP, "w")
         try:
             for name, (mtime, data) in files.items():
@@ -57,6 +57,19 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
                 zinfo.compress_type = self.compression
                 z.writestr(zinfo, data)
             z.close()
+
+            stuff = kw.get("stuff", None)
+            if stuff is not None:
+                # Prepend 'stuff' to the start of the zipfile
+                f = open(TEMP_ZIP, "rb")
+                data = f.read()
+                f.close()
+
+                f = open(TEMP_ZIP, "wb")
+                f.write(stuff)
+                f.write(data)
+                f.close()
+
             sys.path.insert(0, TEMP_ZIP)
 
             mod = __import__(".".join(modules), globals(), locals(),
@@ -181,6 +194,12 @@ class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
                  "some.data": (NOW, "some data")}
         self.doTest(pyc_ext, files, TESTMOD)
 
+    def testImport_WithStuff(self):
+        # try importing from a zipfile which contains additional
+        # stuff at the beginning of the file
+        files = {TESTMOD + ".py": (NOW, test_src)}
+        self.doTest(".py", files, TESTMOD,
+                    stuff="Some Stuff"*31)
 
 class CompressedZipImportTestCase(UncompressedZipImportTestCase):
     compression = ZIP_DEFLATED
index 7ba12183df28512a8044abebb248705bd2b11f14..af56c7789e62ceb624df5cbe3955fd8f45018280 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,10 @@ What's New in Python 2.3 release candidate 2?
 Core and builtins
 -----------------
 
+- It is now possible to import from zipfiles containing additional
+  data bytes before the zip compatible archive. Zipfiles containing a
+  comment at the end are still unsupported.
+
 Extension modules
 -----------------
 
index 1c95d5a98505bbe10a9a01339db087b0cb7bf1fe..afcd4211742dd0dbe3130856a9deaf28a738dc55 100644 (file)
@@ -655,11 +655,12 @@ read_directory(char *archive)
        PyObject *files = NULL;
        FILE *fp;
        long compress, crc, data_size, file_size, file_offset, date, time;
-       long header_offset, name_size, header_size;
+       long header_offset, name_size, header_size, header_position;
        long i, l, length, count;
        char path[MAXPATHLEN + 5];
        char name[MAXPATHLEN + 5];
        char *p, endof_central_dir[22];
+       long arc_offset; /* offset from beginning of file to start of zip-archive */
 
        if (strlen(archive) > MAXPATHLEN) {
                PyErr_SetString(PyExc_OverflowError,
@@ -675,6 +676,7 @@ read_directory(char *archive)
                return NULL;
        }
        fseek(fp, -22, SEEK_END);
+       header_position = ftell(fp);
        if (fread(endof_central_dir, 1, 22, fp) != 22) {
                fclose(fp);
                PyErr_Format(ZipImportError, "can't read Zip file: "
@@ -689,7 +691,10 @@ read_directory(char *archive)
                return NULL;
        }
 
+       header_size = get_long((unsigned char *)endof_central_dir + 12);
        header_offset = get_long((unsigned char *)endof_central_dir + 16);
+       arc_offset = header_position - header_offset - header_size;
+       header_offset += arc_offset;
 
        files = PyDict_New();
        if (files == NULL)
@@ -720,7 +725,7 @@ read_directory(char *archive)
                   PyMarshal_ReadShortFromFile(fp) +
                   PyMarshal_ReadShortFromFile(fp);
                fseek(fp, header_offset + 42, 0);
-               file_offset = PyMarshal_ReadLongFromFile(fp);
+               file_offset = PyMarshal_ReadLongFromFile(fp) + arc_offset;
                if (name_size > MAXPATHLEN)
                        name_size = MAXPATHLEN;