List Archive

Thread

Thread Index

Message

From: Thomas Klausner <tk%giga.or.at@localhost>
To: Torsten Paul <Torsten.Paul%gmx.de@localhost>
Subject: Re: Reading 3MF files with libzip
Date: Sun, 14 Feb 2016 19:58:30 +0100

On Fri, Feb 12, 2016 at 08:43:39PM +0100, Torsten Paul wrote:
> I could not read some of the example files provided along with the
> library and found the reason for that is that libzip says the files
> are multi-disk archives. The offending files seem to be generated
> on Windows 10 using the built-in 3D-Builder application.

Try the attached patch. It allows opening torus.3mf[1], which didn't work
before.

Btw, box.3mf[2] is not in zip64 format and was already supported without
problems.

Cheers,
 Thomas

[1] 
https://github.com/3MFConsortium/3mf-samples/blob/master/geometries/torus.3mf
[2] https://github.com/3MFConsortium/3mf-samples/blob/master/geometries/box.3mf
diff -r 28233441759a lib/zip_open.c
--- a/lib/zip_open.c    Sun Feb 07 14:29:36 2016 +0100
+++ b/lib/zip_open.c    Sun Feb 14 19:58:03 2016 +0100
@@ -293,11 +293,6 @@
        return NULL;
     }
 
-    if (_zip_buffer_get_32(buffer) != 0) {
-       zip_error_set(error, ZIP_ER_MULTIDISK, 0);
-       return NULL;
-    }
-
     if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + 
eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) {
         _zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN);
         cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error);
@@ -668,7 +663,8 @@
 }
 
 
-static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t 
buf_offset, unsigned int flags, zip_error_t *error)
+static zip_cdir_t *
+_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int 
flags, zip_error_t *error)
 {
     zip_cdir_t *cd;
     zip_uint64_t i, nentry, size, offset, eocd_offset;
@@ -680,7 +676,12 @@
     
     eocd_offset = _zip_buffer_offset(buffer);
 
-    _zip_buffer_get(buffer, 8); /* magic and number of disks already verified 
*/
+    _zip_buffer_get(buffer, 4); /* magic already verified */
+
+    if (_zip_buffer_get_32(buffer) != 0) {
+       zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+       return NULL;
+    }
 
     /* number of cdir-entries on this disk */
     i = _zip_buffer_get_16(buffer);
@@ -730,10 +731,14 @@
     zip_uint64_t eocd_offset;
     zip_uint64_t size, nentry, i, eocdloc_offset;
     bool free_buffer;
+    zip_uint32_t num_disks, num_disks64, eocd_disk, eocd_disk64;
 
     eocdloc_offset = _zip_buffer_offset(buffer);
     
-    _zip_buffer_get(buffer, 8); /* magic and single disk already verified */
+    _zip_buffer_get(buffer, 4); /* magic already verified */
+
+    num_disks = _zip_buffer_get_16(buffer);
+    eocd_disk = _zip_buffer_get_16(buffer);
     eocd_offset = _zip_buffer_get_64(buffer);
     
     if (eocd_offset > ZIP_INT64_MAX || eocd_offset + EOCD64LEN < eocd_offset) {
@@ -779,8 +784,29 @@
         return NULL;
     }
 
-    _zip_buffer_get(buffer, 12); /* skip version made by/needed and num disks 
*/
-    
+    _zip_buffer_get(buffer, 4); /* skip version made by/needed */
+
+    num_disks64 = _zip_buffer_get_32(buffer);
+    eocd_disk64 = _zip_buffer_get_32(buffer);
+
+    /* if eocd values are 0xffff, we have to use eocd64 values.
+       otherwise, if the values are not the same, it's inconsistent;
+       in any case, if the value is not 0, we don't support it */
+    if (num_disks == 0xffff) {
+       num_disks = num_disks64;
+    }
+    if (eocd_disk == 0xffff) {
+       eocd_disk = eocd_disk64;
+    }
+    if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != 
num_disks64)) {
+       zip_error_set(error, ZIP_ER_INCONS, 0);
+       return NULL;
+    }
+    if (num_disks != 0 || eocd_disk != 0) {
+       zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+       return NULL;
+    }
+
     nentry = _zip_buffer_get_64(buffer);
     i = _zip_buffer_get_64(buffer);
 

Made by MHonArc.