]> granicus.if.org Git - php/commitdiff
update bundled libzip to 1.1.2
authorRemi Collet <remi@php.net>
Mon, 22 Feb 2016 17:18:30 +0000 (18:18 +0100)
committerRemi Collet <remi@php.net>
Mon, 22 Feb 2016 17:18:30 +0000 (18:18 +0100)
41 files changed:
NEWS
ext/zip/config.m4
ext/zip/config.w32
ext/zip/lib/zip_add_entry.c
ext/zip/lib/zip_buffer.c
ext/zip/lib/zip_close.c
ext/zip/lib/zip_delete.c
ext/zip/lib/zip_dirent.c
ext/zip/lib/zip_discard.c
ext/zip/lib/zip_error.c
ext/zip/lib/zip_error_strerror.c
ext/zip/lib/zip_error_to_str.c
ext/zip/lib/zip_extra_field.c
ext/zip/lib/zip_fdopen.c
ext/zip/lib/zip_file_get_offset.c
ext/zip/lib/zip_filerange_crc.c
ext/zip/lib/zip_fopen_index.c
ext/zip/lib/zip_fopen_index_encrypted.c
ext/zip/lib/zip_hash.c [new file with mode: 0644]
ext/zip/lib/zip_io_util.c
ext/zip/lib/zip_name_locate.c
ext/zip/lib/zip_new.c
ext/zip/lib/zip_open.c
ext/zip/lib/zip_set_default_password.c
ext/zip/lib/zip_set_name.c
ext/zip/lib/zip_source_buffer.c
ext/zip/lib/zip_source_crc.c
ext/zip/lib/zip_source_file.c
ext/zip/lib/zip_source_filep.c
ext/zip/lib/zip_source_pkware.c
ext/zip/lib/zip_source_stat.c
ext/zip/lib/zip_source_supports.c
ext/zip/lib/zip_source_win32a.c
ext/zip/lib/zip_source_win32handle.c
ext/zip/lib/zip_source_win32utf8.c
ext/zip/lib/zip_source_win32w.c
ext/zip/lib/zip_unchange.c
ext/zip/lib/zip_unchange_all.c
ext/zip/lib/zipconf.h
ext/zip/lib/zipint.h
ext/zip/php_zip.h

diff --git a/NEWS b/NEWS
index 4688f14641d1a63e4f602f3d53cd049cc02c361f..2d6bf694334b07b162a901ec984bc0aa8e9912ab 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -81,6 +81,7 @@ PHP                                                                        NEWS
 
 - Zip:
   . Fixed bug #71561 (NULL pointer dereference in Zip::ExtractTo). (Laruence)
+  . Update bundled libzip to 1.1.2. (Remi, Anatol)
 
 04 Feb 2016 PHP 7.0.3
 
index 6dbc1e292bbdc9f52327d6f74c1b80f50bbf4a17..81f47df5567703de7e0bf733f0b3739cad791749 100644 (file)
@@ -122,6 +122,7 @@ if test "$PHP_ZIP" != "no"; then
                        lib/zip_get_archive_comment.c lib/zip_get_archive_flag.c lib/zip_get_compression_implementation.c\
                        lib/zip_get_encryption_implementation.c lib/zip_get_file_comment.c lib/zip_get_name.c lib/zip_get_num_entries.c \
                        lib/zip_get_num_files.c lib/zip_memdup.c lib/zip_name_locate.c lib/zip_new.c lib/zip_open.c lib/zip_rename.c lib/zip_replace.c\
+                       lib/zip_hash.c \
                        lib/zip_set_archive_comment.c lib/zip_set_archive_flag.c lib/zip_set_default_password.c lib/zip_set_file_comment.c\
                        lib/zip_set_file_compression.c lib/zip_set_name.c lib/zip_source_buffer.c lib/zip_source_close.c lib/zip_source_crc.c\
                        lib/zip_source_deflate.c lib/zip_source_error.c lib/zip_source_file.c lib/zip_source_filep.c lib/zip_source_free.c\
index 0aa9f3eaa025d75fb325713853995928b1249826..5460b6d6bd0173d4ac3e38b5c75370acc58c7229 100644 (file)
@@ -21,6 +21,7 @@ if (PHP_ZIP != "no") {
                        zip_get_archive_comment.c zip_get_archive_flag.c zip_get_compression_implementation.c\
                        zip_get_encryption_implementation.c zip_get_file_comment.c zip_get_name.c zip_get_num_entries.c \
                        zip_get_num_files.c zip_memdup.c zip_name_locate.c zip_new.c zip_open.c zip_rename.c zip_replace.c\
+                       zip_hash.c \
                        zip_set_archive_comment.c zip_set_archive_flag.c zip_set_default_password.c zip_set_file_comment.c\
                        zip_set_file_compression.c zip_set_name.c zip_source_buffer.c zip_source_close.c zip_source_crc.c\
                        zip_source_deflate.c zip_source_error.c zip_source_filep.c zip_source_free.c\
index 24dbdaf47c32117f45434a1da161f9f4f39ddbc0..9a9465c5f092422f8c3ae50b7bb952bf0aff3186 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_add_entry.c -- create and init struct zip_entry
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -46,8 +46,19 @@ _zip_add_entry(zip_t *za)
 
     if (za->nentry+1 >= za->nentry_alloc) {
        zip_entry_t *rentries;
-       zip_uint64_t nalloc = za->nentry_alloc + 16;
-       zip_uint64_t realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
+       zip_uint64_t nalloc = za->nentry_alloc;
+       zip_uint64_t additional_entries = 2 * nalloc;
+       zip_uint64_t realloc_size;
+
+       if (additional_entries < 16) {
+           additional_entries = 16;
+       }
+       else if (additional_entries > 1024) {
+           additional_entries = 1024;
+       }
+       /* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
+       nalloc += additional_entries;
+       realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
 
        if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
            zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
index 3d79b09f135eddcf5349b89889cde36095abe3cc..43864f9ba9f6eaea052118d1f38f182e52534986 100644 (file)
@@ -303,6 +303,17 @@ _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset)
 }
 
 
+int
+_zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) {
+    zip_uint64_t offset = buffer->offset + length;
+    
+    if (offset < buffer->offset) {
+        buffer->ok = false;
+        return -1;
+    }
+    return _zip_buffer_set_offset(buffer, offset);
+}
+
 zip_uint64_t
 _zip_buffer_size(zip_buffer_t *buffer)
 {
index a13e4466b3e9298e538d2e91600dfd46b9063178..b5eca67a463fc101f266a5c4617590fe8cd53ca1 100644 (file)
@@ -40,7 +40,6 @@
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
 #endif
-#include <errno.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
index b3e7abb848a210e908201107a12e90f669c0cc2b..34520b0310963df1b199dbd427d5a66a72b6c3ec 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_delete.c -- delete file from zip archive
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -38,6 +38,8 @@
 ZIP_EXTERN int
 zip_delete(zip_t *za, zip_uint64_t idx)
 {
+    const char *name;
+
     if (idx >= za->nentry) {
        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
        return -1;
@@ -48,6 +50,14 @@ zip_delete(zip_t *za, zip_uint64_t idx)
        return -1;
     }
 
+    if ((name=_zip_get_name(za, idx, 0, &za->error)) == NULL) {
+       return -1;
+    }
+
+    if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) {
+       return -1;
+    }
+
     /* allow duplicate file names, because the file will
      * be removed directly afterwards */
     if (_zip_unchange(za, idx, 1) != 0)
index e3a78b31465eb4764abbd0bc21501aa64b0f64fa..630b6a49cb3b10d16d2710ac9a03b0324992077d 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_dirent.c -- read directory entry (local or central), clean dirent
-  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -17,7 +17,7 @@
   3. The names of the authors may not be used to endorse or promote
      products derived from this software without specific prior
      written permission.
+
   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -35,7 +35,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -67,7 +66,7 @@ _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error)
 {
     zip_cdir_t *cd;
     zip_uint64_t i;
-    
+
     if ((cd=(zip_cdir_t *)malloc(sizeof(*cd))) == NULL) {
        zip_error_set(error, ZIP_ER_MEMORY, 0);
        return NULL;
@@ -110,7 +109,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
     }
     offset = (zip_uint64_t)off;
 
-    is_zip64 = 0;
+    is_zip64 = false;
 
     for (i=0; i<survivors; i++) {
        zip_entry_t *entry = za->entry+filelist[i].idx;
@@ -135,7 +134,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
         zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
         return -1;
     }
-    
+
     if (is_zip64) {
        _zip_buffer_put(buffer, EOCD64_MAGIC, 4);
         _zip_buffer_put_64(buffer, EOCD64LEN-12);
@@ -152,7 +151,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
        _zip_buffer_put_64(buffer, offset+size);
        _zip_buffer_put_32(buffer, 1);
     }
-    
+
     _zip_buffer_put(buffer, EOCD_MAGIC, 4);
     _zip_buffer_put_32(buffer, 0);
     _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
@@ -163,7 +162,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
     comment = za->comment_changed ? za->comment_changes : za->comment_orig;
 
     _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
-    
+
     if (!_zip_buffer_ok(buffer)) {
         zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
         _zip_buffer_free(buffer);
@@ -199,7 +198,7 @@ _zip_dirent_clone(const zip_dirent_t *sde)
        memcpy(tde, sde, sizeof(*sde));
     else
        _zip_dirent_init(tde);
-    
+
     tde->changed = 0;
     tde->cloned = 1;
 
@@ -289,7 +288,7 @@ _zip_dirent_new(void)
    Fills the zip directory entry zde.
 
    If buffer is non-NULL, data is taken from there; otherwise data is read from fp as needed.
-   
+
    If local is true, it reads a local header instead of a central directory entry.
 
    Returns size of dirent read if successful. On error, error is filled in and -1 is returned.
@@ -304,7 +303,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
     zip_uint16_t filename_len, comment_len, ef_len;
 
     bool from_buffer = (buffer != NULL);
-    
+
     size = local ? LENTRYSIZE : CDENTRYSIZE;
 
     if (buffer) {
@@ -337,19 +336,19 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
     zde->version_needed = _zip_buffer_get_16(buffer);
     zde->bitflags = _zip_buffer_get_16(buffer);
     zde->comp_method = _zip_buffer_get_16(buffer);
-    
+
     /* convert to time_t */
     dostime = _zip_buffer_get_16(buffer);
     dosdate = _zip_buffer_get_16(buffer);
     zde->last_mod = _zip_d2u_time(dostime, dosdate);
-    
+
     zde->crc = _zip_buffer_get_32(buffer);
     zde->comp_size = _zip_buffer_get_32(buffer);
     zde->uncomp_size = _zip_buffer_get_32(buffer);
-    
+
     filename_len = _zip_buffer_get_16(buffer);
     ef_len = _zip_buffer_get_16(buffer);
-    
+
     if (local) {
        comment_len = 0;
        zde->disk_number = 0;
@@ -363,7 +362,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
        zde->ext_attrib = _zip_buffer_get_32(buffer);
        zde->offset = _zip_buffer_get_32(buffer);
     }
-    
+
     if (!_zip_buffer_ok(buffer)) {
         zip_error_set(error, ZIP_ER_INTERNAL, 0);
         if (!from_buffer) {
@@ -386,7 +385,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
     }
     else {
         _zip_buffer_free(buffer);
-        
+
         if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
             return -1;
         }
@@ -424,7 +423,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
             }
            return -1;
         }
-        if ((zde->extra_fields=_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error)) == NULL) {
+        if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) {
            free(ef);
             if (!from_buffer) {
                 _zip_buffer_free(buffer);
@@ -471,7 +470,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
             }
            return -1;
         }
-        
+
         if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
             zip_error_set(error, ZIP_ER_MEMORY, 0);
             if (!from_buffer) {
@@ -479,11 +478,14 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
             }
             return -1;
         }
-       
+
        if (zde->uncomp_size == ZIP_UINT32_MAX)
            zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
-       else if (local)
-           ef += 8;
+       else if (local) {
+           /* From appnote.txt: This entry in the Local header MUST
+              include BOTH original and compressed file size fields. */
+            (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */
+       }
        if (zde->comp_size == ZIP_UINT32_MAX)
            zde->comp_size = _zip_buffer_get_64(ef_buffer);
        if (!local) {
@@ -492,7 +494,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
            if (zde->disk_number == ZIP_UINT16_MAX)
                zde->disk_number = _zip_buffer_get_32(buffer);
        }
-        
+
         if (!_zip_buffer_eof(ef_buffer)) {
             zip_error_set(error, ZIP_ER_INCONS, 0);
             _zip_buffer_free(ef_buffer);
@@ -503,7 +505,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
         }
         _zip_buffer_free(ef_buffer);
     }
-    
+
     if (!_zip_buffer_ok(buffer)) {
         zip_error_set(error, ZIP_ER_INTERNAL, 0);
         if (!from_buffer) {
@@ -520,7 +522,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
        zip_error_set(error, ZIP_ER_SEEK, EFBIG);
        return -1;
     }
-    
+
     zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
 
     return (zip_int64_t)(size + variable_size);
@@ -535,15 +537,15 @@ _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string
     zip_buffer_t *buffer;
 
     const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
-    
+
     if (ef == NULL || ef_len < 5 || ef[0] != 1) {
        return str;
     }
-    
+
     if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
         return str;
     }
-    
+
     _zip_buffer_get_8(buffer);
     ef_crc = _zip_buffer_get_32(buffer);
 
@@ -556,9 +558,9 @@ _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string
            str = ef_str;
        }
     }
-    
+
     _zip_buffer_free(buffer);
-    
+
     return str;
 }
 
@@ -578,7 +580,7 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error)
         _zip_error_set_from_source(error, src);
        return -1;
     }
-    
+
     if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) {
        return -1;
     }
@@ -586,7 +588,7 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error)
     for (i=0; i<(local ? 2 : 3); i++) {
        size += _zip_buffer_get_16(buffer);
     }
-    
+
     if (!_zip_buffer_eof(buffer)) {
         zip_error_set(error, ZIP_ER_INTERNAL, 0);
        _zip_buffer_free(buffer);
@@ -614,16 +616,15 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
     zip_uint16_t dostime, dosdate;
     zip_encoding_type_t com_enc, name_enc;
     zip_extra_field_t *ef;
+    zip_extra_field_t *ef64;
+    zip_uint32_t ef_total_size;
     bool is_zip64;
     bool is_really_zip64;
     zip_uint8_t buf[CDENTRYSIZE];
     zip_buffer_t *buffer;
-    zip_uint32_t ef_total_size;
 
     ef = NULL;
 
-    is_zip64 = false;
-
     name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
     com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
 
@@ -648,20 +649,19 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
            ef = ef2;
        }
     }
-    
+
     is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
     is_zip64 = (flags & (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64) || is_really_zip64;
-    
+
     if (is_zip64) {
         zip_uint8_t ef_zip64[EFZIP64SIZE];
         zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64));
-        zip_extra_field_t *ef64;
         if (ef_buffer == NULL) {
             zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
            _zip_ef_free(ef);
             return -1;
         }
-        
+
         if (flags & ZIP_FL_LOCAL) {
             if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
                 _zip_buffer_put_64(ef_buffer, de->uncomp_size);
@@ -681,7 +681,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
                 }
             }
         }
-        
+
         if (!_zip_buffer_ok(ef_buffer)) {
             zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
             _zip_buffer_free(ef_buffer);
@@ -700,9 +700,9 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
         _zip_ef_free(ef);
         return -1;
     }
-    
+
     _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
-    
+
     if ((flags & ZIP_FL_LOCAL) == 0) {
         _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby));
     }
@@ -715,7 +715,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
     _zip_buffer_put_16(buffer, dosdate);
 
     _zip_buffer_put_32(buffer, de->crc);
-    
+
     if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) {
        /* In local headers, if a ZIP64 EF is written, it MUST contain
         * both compressed and uncompressed sizes (even if one of the
@@ -744,7 +744,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
     /* TODO: check for overflow */
     ef_total_size = (zip_uint32_t)_zip_ef_size(de->extra_fields, flags) + (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
     _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size);
-    
+
     if ((flags & ZIP_FL_LOCAL) == 0) {
        _zip_buffer_put_16(buffer, _zip_string_length(de->comment));
        _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
@@ -755,7 +755,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
        else
            _zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
     }
-    
+
     if (!_zip_buffer_ok(buffer)) {
         zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
         _zip_buffer_free(buffer);
@@ -768,7 +768,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
         _zip_ef_free(ef);
         return -1;
     }
-    
+
     _zip_buffer_free(buffer);
 
     if (de->filename) {
@@ -810,10 +810,10 @@ _zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate)
     struct tm tm;
 
     memset(&tm, 0, sizeof(tm));
-    
+
     /* let mktime decide if DST is in effect */
     tm.tm_isdst = -1;
-    
+
     tm.tm_year = ((ddate>>9)&127) + 1980 - 1900;
     tm.tm_mon = ((ddate>>5)&15) - 1;
     tm.tm_mday = ddate&31;
@@ -834,13 +834,16 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error)
     zip_buffer_t *buffer;
     zip_extra_field_t *ef;
 
-    raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL);
+    if ((raw=_zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
+       /* error already set */
+       return NULL;
+    }
 
     if (len+5 > ZIP_UINT16_MAX) {
         zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
         return NULL;
     }
-    
+
     if ((buffer = _zip_buffer_new(NULL, len+5)) == NULL) {
        zip_error_set(error, ZIP_ER_MEMORY, 0);
        return NULL;
@@ -855,7 +858,7 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error)
         _zip_buffer_free(buffer);
         return NULL;
     }
-    
+
     ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH);
     _zip_buffer_free(buffer);
 
@@ -898,6 +901,10 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate)
     struct tm *tm;
 
     tm = localtime(&intime);
+    if (tm->tm_year < 80) {
+       tm->tm_year = 80;
+    }
+
     *ddate = (zip_uint16_t)(((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday);
     *dtime = (zip_uint16_t)(((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1));
 
index db22370842c59ad12e6b67450fc4e8bbd738c81c..1876c84f0c604502b55e0806b109f733f0200068 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_discard.c -- discard and free struct zip
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -58,6 +58,8 @@ zip_discard(zip_t *za)
     _zip_string_free(za->comment_orig);
     _zip_string_free(za->comment_changes);
 
+    _zip_hash_free(za->names);
+
     if (za->entry) {
        for (i=0; i<za->nentry; i++)
            _zip_entry_finalize(za->entry+i);
index a21a00bc2992c6d06ac3215475698204631ea912..43ddf4f9cb15226a4a5e59d7647723933fa4f6c4 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_error.c -- zip_error_t helper functions
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -31,7 +31,6 @@
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#include <errno.h>
 #include <stdlib.h>
 
 #include "zipint.h"
index 2f124ccd46675816e822d09e2bfa25c1cbb0c8f0..29efc8a91c5ac88effde4cc658bff91e52395dee 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_error_sterror.c -- get string representation of struct zip_error
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@
 */
 
 
-#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index d4119253f766ec9282ed64690b66a5c42c2c5749..22de177842bd192191c7e7bf5eb88bc3294891c5 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_error_to_str.c -- get string representation of zip error code
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@
 */
 
 
-#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index b2566c68875ba42a6dd324a504d976edc1efe410..035047827ee33b87318229a714379657b1f1035f 100644 (file)
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-
-#include "zipint.h"
-
-#include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include "zipint.h"
+
 
 zip_extra_field_t *
 _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error)
@@ -207,20 +205,20 @@ _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_fla
 }
 
 
-zip_extra_field_t *
-_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_error_t *error)
+bool
+_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_extra_field_t **ef_head_p, zip_error_t *error)
 {
     zip_buffer_t *buffer;
     zip_extra_field_t *ef, *ef2, *ef_head;
 
     if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) {
         zip_error_set(error, ZIP_ER_MEMORY, 0);
-        return NULL;
+        return false;
     }
     
     ef_head = ef = NULL;
     
-    while (_zip_buffer_ok(buffer) && !_zip_buffer_eof(buffer)) {
+    while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) {
         zip_uint16_t fid, flen;
         zip_uint8_t *ef_data;
         
@@ -229,14 +227,17 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_
         ef_data = _zip_buffer_get(buffer, flen);
 
         if (ef_data == NULL) {
-            break;
+           zip_error_set(error, ZIP_ER_INCONS, 0);
+            _zip_buffer_free(buffer);
+           _zip_ef_free(ef_head);
+           return false;
         }
         
        if ((ef2=_zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
            zip_error_set(error, ZIP_ER_MEMORY, 0);
             _zip_buffer_free(buffer);
            _zip_ef_free(ef_head);
-           return NULL;
+           return false;
        }
 
        if (ef_head) {
@@ -248,15 +249,29 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_
     }
 
     if (!_zip_buffer_eof(buffer)) {
-        zip_error_set(error, ZIP_ER_INCONS, 0);
-        _zip_buffer_free(buffer);
-        _zip_ef_free(ef_head);
-        return NULL;
+       /* Android APK files align stored file data with padding in extra fields; ignore. */
+       /* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */
+       size_t glen = _zip_buffer_left(buffer);
+       zip_uint8_t *garbage;
+       garbage = _zip_buffer_get(buffer, glen);
+       if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) {
+           zip_error_set(error, ZIP_ER_INCONS, 0);
+           _zip_buffer_free(buffer);
+           _zip_ef_free(ef_head);
+           return false;
+       }
     }
 
     _zip_buffer_free(buffer);
+
+    if (ef_head_p) {
+       *ef_head_p = ef_head;
+    }
+    else {
+        _zip_ef_free(ef_head);
+    }
     
-    return ef_head;
+    return true;
 }
 
 
@@ -400,14 +415,16 @@ _zip_read_local_ef(zip_t *za, zip_uint64_t idx)
        if (ef_raw == NULL)
            return -1;
 
-       if ((ef=_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &za->error)) == NULL) {
+       if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) {
            free(ef_raw);
            return -1;
        }
        free(ef_raw);
-       
-        ef = _zip_ef_remove_internal(ef);
-       e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
+
+       if (ef) {
+           ef = _zip_ef_remove_internal(ef);
+           e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
+       }
     }
 
     e->orig->local_extra_fields_read = 1;
index c5b55311d2f4705c454a1d30e5cc177ea9ce88e9..bbcdf4f6bf726d756d34480a66dd94b8b57cd7c2 100644 (file)
@@ -33,6 +33,9 @@
 
 
 #include "zipint.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 
 
 ZIP_EXTERN zip_t *
index 1aaca712d743b3ace7ca484cb22b4f28693ede9b..0257b042bc5d5ab28bc9a6401a5e0059dbd21140 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_file_get_offset.c -- get offset of file data in archive.
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -35,7 +35,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
index 8e06e8fa8bed6611f3719318ab8d76aebe1dbff9..f2a27fab34803603e30141018b6a60108b3dfd97 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_filerange_crc.c -- compute CRC32 for a range of a file
-  Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 2008-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -33,7 +33,6 @@
 
 
 #include <stdio.h>
-#include <errno.h>
 
 #include "zipint.h"
 
index e9a169a2e1aaee0b658ca04c407dbae13aa379e8..7496f9829f3cb7fefe1401ad08edde865d051d15 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fopen_index.c -- open file in zip archive for reading by index
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@
 */
 
 
-#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 
index 21cc43333c8f7bb8db79c0942b9c79556b4e926a..92258e85fe44871e5ba8eb3bc5bb64006a007b50 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_fopen_index_encrypted.c -- open file for reading by index w/ password
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@
 */
 
 
-#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 
diff --git a/ext/zip/lib/zip_hash.c b/ext/zip/lib/zip_hash.c
new file mode 100644 (file)
index 0000000..23f9708
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+  zip_hash.c -- hash table string -> uint64
+  Copyright (C) 2015-2016 Dieter Baron and Thomas Klausner
+
+  This file is part of libzip, a library to manipulate ZIP archives.
+  The authors can be contacted at <libzip@nih.at>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+  3. The names of the authors may not be used to endorse or promote
+     products derived from this software without specific prior
+     written permission.
+  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "zipint.h"
+
+struct zip_hash_entry {
+    const zip_uint8_t *name;
+    zip_int64_t orig_index;
+    zip_int64_t current_index;
+    struct zip_hash_entry *next;
+};
+typedef struct zip_hash_entry zip_hash_entry_t;
+
+struct zip_hash {
+    zip_uint16_t table_size;
+    zip_hash_entry_t **table;
+};
+
+zip_hash_t *
+_zip_hash_new(zip_uint16_t table_size, zip_error_t *error)
+{
+    zip_hash_t *hash;
+
+    if (table_size == 0) {
+       zip_error_set(error, ZIP_ER_INTERNAL, 0);
+       return NULL;
+    }
+
+    if ((hash=(zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) {
+       zip_error_set(error, ZIP_ER_MEMORY, 0);
+       return NULL;
+    }
+    hash->table_size = table_size;
+    if ((hash->table=(zip_hash_entry_t**)calloc(table_size, sizeof(zip_hash_entry_t *))) == NULL) {
+       free(hash);
+       zip_error_set(error, ZIP_ER_MEMORY, 0);
+       return NULL;
+    }
+
+    return hash;
+}
+
+static void
+_free_list(zip_hash_entry_t *entry)
+{
+    zip_hash_entry_t *next;
+    do {
+       next = entry->next;
+       free(entry);
+       entry = next;
+    } while (entry != NULL);
+}
+
+void
+_zip_hash_free(zip_hash_t *hash)
+{
+    zip_uint16_t i;
+
+    if (hash == NULL) {
+       return;
+    }
+
+    for (i=0; i<hash->table_size; i++) {
+       if (hash->table[i] != NULL) {
+           _free_list(hash->table[i]);
+       }
+    }
+    free(hash->table);
+    free(hash);
+}
+
+static zip_uint16_t
+_hash_string(const zip_uint8_t *name, zip_uint16_t size)
+{
+#define HASH_MULTIPLIER 33
+    zip_uint16_t value = 5381;
+
+    if (name == NULL)
+       return 0;
+
+    while (*name != 0) {
+       value = (zip_uint16_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % size);
+       name++;
+    }
+
+    return value;
+}
+
+/* insert into hash, return error on existence or memory issues */
+bool
+_zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error)
+{
+    zip_uint16_t hash_value;
+    zip_hash_entry_t *entry;
+
+    if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
+       zip_error_set(error, ZIP_ER_INVAL, 0);
+       return false;
+    }
+
+    hash_value = _hash_string(name, hash->table_size);
+    for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
+       if (strcmp((const char *)name, (const char *)entry->name) == 0) {
+           if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
+               zip_error_set(error, ZIP_ER_EXISTS, 0);
+               return false;
+           }
+           else {
+               break;
+           }
+       }
+    }
+
+    if (entry == NULL) {
+       if ((entry=(zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
+           zip_error_set(error, ZIP_ER_MEMORY, 0);
+           return false;
+       }
+       entry->name = name;
+       entry->next = hash->table[hash_value];
+       hash->table[hash_value] = entry;
+       entry->orig_index = -1;
+    }
+
+    if (flags & ZIP_FL_UNCHANGED) {
+       entry->orig_index = (zip_int64_t)index;
+    }
+    entry->current_index = (zip_int64_t)index;
+
+    return true;
+}
+
+/* remove entry from hash, error if not found */
+bool
+_zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
+{
+    zip_uint16_t hash_value;
+    zip_hash_entry_t *entry, *previous;
+
+    if (hash == NULL || name == NULL) {
+       zip_error_set(error, ZIP_ER_INVAL, 0);
+       return false;
+    }
+
+    hash_value = _hash_string(name, hash->table_size);
+    previous = NULL;
+    entry = hash->table[hash_value];
+    while (entry) {
+       if (strcmp((const char *)name, (const char *)entry->name) == 0) {
+           if (entry->orig_index == -1) {
+               if (previous) {
+                   previous->next = entry->next;
+               }
+               else {
+                   hash->table[hash_value] = entry->next;
+               }
+               free(entry);
+           }
+           else {
+               entry->current_index = -1;
+           }
+           return true;
+       }
+       previous = entry;
+       entry = entry->next;
+    };
+
+    zip_error_set(error, ZIP_ER_NOENT, 0);
+    return false;
+}
+
+/* find value for entry in hash, -1 if not found */
+zip_int64_t
+_zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error)
+{
+    zip_uint16_t hash_value;
+    zip_hash_entry_t *entry;
+
+    if (hash == NULL || name == NULL) {
+       zip_error_set(error, ZIP_ER_INVAL, 0);
+       return -1;
+    }
+
+    hash_value = _hash_string(name, hash->table_size);
+    for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
+       if (strcmp((const char *)name, (const char *)entry->name) == 0) {
+           if (flags & ZIP_FL_UNCHANGED) {
+               if (entry->orig_index != -1) {
+                   return entry->orig_index;
+               }
+           }
+           else {
+               if (entry->current_index != -1) {
+                   return entry->current_index;
+               }
+           }
+           break;
+       }
+    }
+
+    zip_error_set(error, ZIP_ER_NOENT, 0);
+    return -1;    
+}
+
+void
+_zip_hash_revert(zip_hash_t *hash)
+{
+    zip_uint16_t i;
+    zip_hash_entry_t *entry, *previous;
+    
+    for (i = 0; i < hash->table_size; i++) {
+       previous = NULL;
+       entry = hash->table[i];
+       while (entry) {
+           if (entry->orig_index == -1) {
+               zip_hash_entry_t *p;
+               if (previous) {
+                   previous->next = entry->next;
+               }
+               else {
+                   hash->table[i] = entry->next;
+               }
+               p = entry;
+               entry = entry->next;
+               /* previous does not change */
+               free(p);
+           }
+           else {
+               entry->current_index = entry->orig_index;
+               previous = entry;
+               entry = entry->next;
+           }
+       }
+    }
+}
index 4a6bc1ddc1f3f36185976586203b092516aa0199..b16927defb061a9c5465ce8c830694c2b63e529f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  zip_io_util.c -- I/O helper functions
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
  
  This file is part of libzip, a library to manipulate ZIP archives.
  The authors can be contacted at <libzip@nih.at>
@@ -31,7 +31,6 @@
  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 
index 820ea0ca7fad629c05947abc8214b2bc9a140c64..50ca40b1a9848e0d04777535f60b77e64bfe1d50 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_name_locate.c -- get index by name
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -62,27 +62,33 @@ _zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *e
        return -1;
     }
 
-    cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
-
-    for (i=0; i<za->nentry; i++) {
-       fn = _zip_get_name(za, i, flags, error);
-
-       /* newly added (partially filled) entry or error */
-       if (fn == NULL)
-           continue;
-       
-       if (flags & ZIP_FL_NODIR) {
-           p = strrchr(fn, '/');
-           if (p)
-               fn = p+1;
+    if (flags & (ZIP_FL_NOCASE|ZIP_FL_NODIR|ZIP_FL_ENC_CP437)) {
+       /* can't use hash table */
+       cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
+
+       for (i=0; i<za->nentry; i++) {
+           fn = _zip_get_name(za, i, flags, error);
+           
+           /* newly added (partially filled) entry or error */
+           if (fn == NULL)
+               continue;
+           
+           if (flags & ZIP_FL_NODIR) {
+               p = strrchr(fn, '/');
+               if (p)
+                   fn = p+1;
+           }
+           
+           if (cmp(fname, fn) == 0) {
+               _zip_error_clear(error);
+               return (zip_int64_t)i;
+           }
        }
 
-       if (cmp(fname, fn) == 0) {
-           _zip_error_clear(error);
-           return (zip_int64_t)i;
-       }
+       zip_error_set(error, ZIP_ER_NOENT, 0);
+       return -1;
+    }
+    else {
+       return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
     }
-
-    zip_error_set(error, ZIP_ER_NOENT, 0);
-    return -1;
 }
index d54a247c29e622da0d51011c6d9626ed345ea273..562dd76a36f007154c95d05c893c63f24d412cf8 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_new.c -- create and init struct zip
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -52,6 +52,11 @@ _zip_new(zip_error_t *error)
        return NULL;
     }
 
+    if ((za->names = _zip_hash_new(ZIP_HASH_TABLE_SIZE, error)) == NULL) {
+       free(za);
+       return NULL;
+    }
+
     za->src = NULL;
     za->open_flags = 0;
     zip_error_init(&za->error);
index fb9c566cb1e7bb18e96ca98ff6e9cca70c01ca60..d6209ee1e769e62fffbe858cf34a8d210319f8f0 100644 (file)
@@ -33,7 +33,6 @@
 
 
 #include <sys/stat.h>
-#include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -184,7 +183,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
     zip_t *za;
     zip_cdir_t *cdir;
     struct zip_stat st;
-    zip_uint64_t len;
+    zip_uint64_t len, idx;
 
     zip_stat_init(&st);
     if (zip_source_stat(src, &st) < 0) {
@@ -223,11 +222,31 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
     za->nentry = cdir->nentry;
     za->nentry_alloc = cdir->nentry_alloc;
     za->comment_orig = cdir->comment;
-    
-    za->ch_flags = za->flags;
 
     free(cdir);
 
+    for (idx = 0; idx < za->nentry; idx++) {
+       const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error);
+       if (name == NULL) {
+               /* keep src so discard does not get rid of it */
+               zip_source_keep(src);
+               zip_discard(za);
+               return NULL;
+       }
+       
+       if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) {
+           if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) {
+               _zip_error_copy(error, &za->error);
+               /* keep src so discard does not get rid of it */
+               zip_source_keep(src);
+               zip_discard(za);
+               return NULL;
+           }
+       }
+    }
+    
+    za->ch_flags = za->flags;
+
     return za;
 }
 
@@ -274,11 +293,6 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
        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);
@@ -649,7 +663,8 @@ _zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little
 }
 
 
-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;
@@ -661,7 +676,12 @@ static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset,
     
     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);
@@ -711,10 +731,14 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
     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) {
@@ -760,8 +784,29 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
         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);
 
index ac098dc5fc123ee92254abc5cb5ee014ac847e8c..10b48062fdc2cf59febdb214928060f79089b693 100644 (file)
@@ -44,8 +44,7 @@ zip_set_default_password(zip_t *za, const char *passwd)
     if (za == NULL)
        return -1;
 
-    if (za->default_password)
-       free(za->default_password);
+    free(za->default_password);
     
     if (passwd) {
        if ((za->default_password=strdup(passwd)) == NULL) {
index 5a103817530a32e7e1642689b4acc28c28752474..2a461437e2c0eb31b406ab1bafe4e3dff821fa26 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_set_name.c -- rename helper function
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -43,8 +43,10 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
 {
     zip_entry_t *e;
     zip_string_t *str;
-    int changed;
+    bool same_as_orig;
     zip_int64_t i;
+    const zip_uint8_t *old_name, *new_name;
+    zip_string_t *old_str;
 
     if (idx >= za->nentry) {
        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
@@ -56,7 +58,7 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
        return -1;
     }
 
-    if (name && strlen(name) > 0) {
+    if (name && name[0] != '\0') {
         /* TODO: check for string too long */
        if ((str=_zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL)
            return -1;
@@ -81,34 +83,75 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
 
     e = za->entry+idx;
 
-    if (e->changes) {
-       _zip_string_free(e->changes->filename);
-       e->changes->filename = NULL;
-       e->changes->changed &= ~ZIP_DIRENT_FILENAME;
-    }
-
     if (e->orig)
-       changed = !_zip_string_equal(e->orig->filename, str);
+       same_as_orig = _zip_string_equal(e->orig->filename, str);
     else
-       changed = 1;
-       
-    if (changed) {
-        if (e->changes == NULL) {
-            if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
-                zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
-               _zip_string_free(str);
-                return -1;
-            }
-        }
-        e->changes->filename = str;
-        e->changes->changed |= ZIP_DIRENT_FILENAME;
+       same_as_orig = false;
+
+    if (!same_as_orig && e->changes == NULL) {
+       if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
+           zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+           _zip_string_free(str);
+           return -1;
+       }
+    }
+
+    if ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) {
+       _zip_string_free(str);
+       return -1;
+    }
+
+    if (e->changes) {
+       old_str = e->changes->filename;
+    }
+    else if (e->orig) {
+       old_str = e->orig->filename;
     }
     else {
+       old_str = NULL;
+    }
+    
+    if (old_str) {
+       if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) {
+           _zip_string_free(str);
+           return -1;
+       }
+    }
+    else {
+       old_name = NULL;
+    }
+
+    if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) {
+       _zip_string_free(str);
+       return -1;
+    }
+    if (old_name) {
+       _zip_hash_delete(za->names, old_name, NULL);
+    }
+
+    if (same_as_orig) {
+       if (e->changes) {
+           if (e->changes->changed & ZIP_DIRENT_FILENAME) {
+               _zip_string_free(e->changes->filename);
+               e->changes->changed &= ~ZIP_DIRENT_FILENAME;
+               if (e->changes->changed == 0) {
+                   _zip_dirent_free(e->changes);
+                   e->changes = NULL;
+               }
+               else {
+                   /* TODO: what if not cloned? can that happen? */
+                   e->changes->filename = e->orig->filename;
+               }
+           }
+       }
        _zip_string_free(str);
-       if (e->changes && e->changes->changed == 0) {
-           _zip_dirent_free(e->changes);
-           e->changes = NULL;
+    }
+    else {
+       if (e->changes->changed & ZIP_DIRENT_FILENAME) {
+           _zip_string_free(e->changes->filename);
        }
+       e->changes->changed |= ZIP_DIRENT_FILENAME;
+       e->changes->filename = str;
     }
 
     return 0;
index aadf6e40b058a2243276a8a3a3c18057960b82e8..f3f8ee0d5835a74741f89611e37d380a15889660 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_buffer.c -- create zip data source from buffer
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -31,7 +31,6 @@
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -376,6 +375,7 @@ static zip_int64_t
 buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *error)
 {
     zip_uint64_t n, i, fragment_offset;
+    zip_uint8_t **fragments;
 
     if (buffer->offset + length + buffer->fragment_size - 1 < length) {
        zip_error_set(error, ZIP_ER_INVAL, 0);
@@ -388,7 +388,6 @@ buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip
        
        if (needed_fragments > buffer->fragments_capacity) {
            zip_uint64_t new_capacity = buffer->fragments_capacity;
-           zip_uint8_t **fragments;
 
            while (new_capacity < needed_fragments) {
                new_capacity *= 2;
index eed726616aba97385c34a75707241fb7b66a8209..01f526c647a732b3c69da23b0669a74c54eeee50 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_crc.c -- pass-through source that calculates CRC32 and size
-  Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
 #include "zipint.h"
 
 struct crc_context {
-    int eof;
-    int validate;
+    int validate; /* whether to check CRC on EOF and return error on mismatch */
+    int crc_complete; /* whether CRC was computed for complete file */
     zip_error_t error;
     zip_uint64_t size;
+    zip_uint64_t position; /* current reading position */
+    zip_uint64_t crc_position; /* how far we've computed the CRC */
     zip_uint32_t crc;
 };
 
@@ -64,12 +66,13 @@ zip_source_crc(zip_t *za, zip_source_t *src, int validate)
        return NULL;
     }
 
-    ctx->eof = 0;
-    ctx->validate = validate;
     zip_error_init(&ctx->error);
+    ctx->validate = validate;
+    ctx->crc_complete = 0;
+    ctx->crc_position = 0;
+    ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
     ctx->size = 0;
-    ctx->crc = 0;
-    
+
     return zip_source_layered(za, src, crc_read, ctx);
 }
 
@@ -84,51 +87,50 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
 
     switch (cmd) {
         case ZIP_SOURCE_OPEN:
-            ctx->eof = 0;
-            ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
-            ctx->size = 0;
-            
+            ctx->position = 0;
             return 0;
             
         case ZIP_SOURCE_READ:
-            if (ctx->eof || len == 0)
-                return 0;
-            
-            if ((n=zip_source_read(src, data, len)) < 0) {
+            if ((n = zip_source_read(src, data, len)) < 0) {
                 _zip_error_set_from_source(&ctx->error, src);
                 return -1;
             }
             
             if (n == 0) {
-                ctx->eof = 1;
-                if (ctx->validate) {
-                    struct zip_stat st;
+                if (ctx->crc_position == ctx->position) {
+                    ctx->crc_complete = 1;
+                    ctx->size = ctx->position;
+
+                    if (ctx->validate) {
+                        struct zip_stat st;
                     
-                    if (zip_source_stat(src, &st) < 0) {
-                        _zip_error_set_from_source(&ctx->error, src);
-                        return -1;
-                    }
+                        if (zip_source_stat(src, &st) < 0) {
+                            _zip_error_set_from_source(&ctx->error, src);
+                            return -1;
+                        }
                     
-                    if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
-                        zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
-                        return -1;
-                    }
-                    if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
-                        zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
-                        return -1;
+                        if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
+                            zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
+                            return -1;
+                        }
+                        if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
+                            zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
+                            return -1;
+                        }
                     }
                 }
             }
-            else {
+            else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) {
                zip_uint64_t i, nn;
 
-               for (i=0; i < (zip_uint64_t)n; i += nn) {
+               for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
                    nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n-i);
 
                    ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn);
+                    ctx->crc_position += nn;
                }
-                ctx->size += (zip_uint64_t)n;
             }
+            ctx->position += (zip_uint64_t)n;
             return n;
 
         case ZIP_SOURCE_CLOSE:
@@ -140,7 +142,7 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
 
            st = (zip_stat_t *)data;
 
-           if (ctx->eof) {
+           if (ctx->crc_complete) {
                /* TODO: Set comp_size, comp_method, encryption_method?
                        After all, this only works for uncompressed data. */
                st->size = ctx->size;
@@ -161,7 +163,37 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
             return 0;
             
         case ZIP_SOURCE_SUPPORTS:
-            return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
+        {
+            zip_int64_t mask = zip_source_supports(src);
+
+            if (mask < 0) {
+                _zip_error_set_from_source(&ctx->error, src);
+                return -1;
+            }
+
+            return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1);
+        }
+
+        case ZIP_SOURCE_SEEK:
+        {
+            zip_int64_t new_position;
+            zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
+
+           if (args == NULL) {
+               return -1;
+           }
+            if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) {
+                _zip_error_set_from_source(&ctx->error, src);
+                return -1;
+            }
+
+            ctx->position = (zip_uint64_t)new_position;
+
+            return 0;
+        }
+
+        case ZIP_SOURCE_TELL:
+            return (zip_int64_t)ctx->position;
             
         default:
             zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
index 1465e1700ea3ecc150a37bf41693d8a64db196e1..b3cd7ab29f3f02692bdac909503f269d732ef16e 100644 (file)
@@ -32,7 +32,6 @@
 */
 
 
-#include <errno.h>
 #include <stdio.h>
 
 #include "zipint.h"
index e541305d7f555246ba2c603c71a33837e90aff53..70255dec419db8ba3cc80d0e33336ee1bf052065 100644 (file)
   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-
-#include "zipint.h"
-
 #include <sys/stat.h>
-#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#include "zipint.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
 #ifdef _WIN32
 /* WIN32 needs <fcntl.h> for _O_BINARY */
 #include <fcntl.h>
 #ifndef S_ISREG
 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
 #endif
-#ifndef S_IRWXG
-#define S_IRWXG (S_IRWXU >> 3)
-#endif
-#ifndef S_IRWXO
-#define S_IRWXO (S_IRWXG >> 3)
+#if defined(S_IXUSR) && defined(S_IRWXG) && defined(S_IRWXO)
+#define _SAFE_MASK (S_IXUSR | S_IRWXG | S_IRWXO)
+#elif defined(_S_IWRITE)
+#define _SAFE_MASK (_S_IWRITE)
+#else
+#error do not know safe values for umask, please report this
 #endif
 
 #ifdef _MSC_VER
@@ -183,13 +186,7 @@ create_temp_output(struct read_file *ctx)
     }
     sprintf(temp, "%s.XXXXXX", ctx->fname);
 
-#ifdef _WIN32
-    /* This might work under VS2015, however there's no good documentation
-       about it. So let it be for now. */
-    mask = 0;
-#else
-    mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
-#endif
+    mask = umask(_SAFE_MASK);
     if ((tfd=mkstemp(temp)) == -1) {
         zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
        umask(mask);
index ce281ac1483548099b8b9e4cced79cf83d2963ce..125e4e2c2af14906bc8a27423870294272d8452c 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_pkware.c -- Traditional PKWARE de/encryption routines
-  Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -107,7 +107,7 @@ decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in,
        if (!update_only) {
            /* decrypt next byte */
            tmp = (zip_uint16_t)(ctx->key[2] | 2);
-           tmp = (zip_uint16_t)((tmp * (tmp ^ 1)) >> 8);
+           tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8);
            b ^= (Bytef)tmp;
        }
 
index 34cb05f4523bd658248762c3692e7cc02e92d6ec..a6b46d06a630e295f7693a934d16fdc1d90a94f1 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_stat.c -- get meta information from zip_source
-  Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -35,7 +35,7 @@
 #include "zipint.h"
 
 
-int
+ZIP_EXTERN int
 zip_source_stat(zip_source_t *src, zip_stat_t *st)
 {
     if (src->source_closed) {
index 3c100fb71f5df628444b98965d00c7e3af1f9c8f..75a4a4626db70ffebeadc1a12125a4b3121e2d8a 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_source_supports.c -- check for supported functions
-  Copyright (C) 2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 2014-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -44,7 +44,7 @@ zip_source_supports(zip_source_t *src)
 }
 
 
-zip_int64_t
+ZIP_EXTERN zip_int64_t
 zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...)
 {
     zip_int64_t bitmap;
index e9786c473ebb615612ca880cfb863e95bd5a2305..85493b660e36c5bc7cba62203cd94176ed3986df 100644 (file)
@@ -1,6 +1,6 @@
 /*
 zip_source_win32a.c -- create data source from Windows file (ANSI)
-Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
 
 This file is part of libzip, a library to manipulate ZIP archives.
 The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 
-#include <errno.h>
 #include <stdio.h>
 
 #include "zipint.h"
index d195a119db1fca100b28daf58928195d58288198..35e2e679725fd4f2dc8fcd80d01f300034f4b8e5 100644 (file)
@@ -1,6 +1,6 @@
 /*
 zip_source_win32file.c -- create data source from HANDLE (Win32)
-Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
 
 This file is part of libzip, a library to manipulate ZIP archives.
 The authors can be contacted at <libzip@nih.at>
@@ -33,7 +33,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include <wchar.h>
-#include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -409,6 +408,7 @@ _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd
 static int
 _win32_create_temp_file(_zip_source_win32_read_file_t *ctx)
 {
+    zip_uint32_t value;
     /*
     Windows has GetTempFileName(), but it closes the file after
     creation, leaving it open to a horrible race condition. So
@@ -423,7 +423,6 @@ _win32_create_temp_file(_zip_source_win32_read_file_t *ctx)
     PSECURITY_ATTRIBUTES psa = NULL;
     DWORD len;
     BOOL success;
-       zip_uint32_t value;
 
     /*
     Read the DACL from the original file, so we can copy it to the temp file.
index e11214ba05b65a0d45520a0f3680edd19d6ff8c4..004c66ac2b33fce12c392e43e539c57ecf183f4e 100644 (file)
@@ -32,7 +32,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 
-#include <errno.h>
 #include <stdio.h>
 
 #include "zipint.h"
index 34134561f13d226d643fc7b855ae6f75e7401e8a..551aba5f37dc31abf2fdd47e5456321a7dcffcee 100644 (file)
@@ -1,6 +1,6 @@
 /*
 zip_source_win32w.c -- create data source from Windows file (UTF-16)
-Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
 
 This file is part of libzip, a library to manipulate ZIP archives.
 The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 
-#include <errno.h>
 #include <stdio.h>
 
 #include "zipint.h"
@@ -100,7 +99,7 @@ _win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32
            return INVALID_HANDLE_VALUE;
        }
     }
-    if (swprintf((wchar_t *)*temp, len, L"%s.%08x", (const wchar_t *)ctx->fname, value) != len - 1) {
+    if (_snwprintf((wchar_t *)*temp, len, L"%s.%08x", (const wchar_t *)ctx->fname, value) != len - 1) {
        return INVALID_HANDLE_VALUE;
     }
 
index 6c8a495c78d9c207c2317423cc4278fa723b090d..5ef5462127ec6771863dcb3b31eb1df31b942508 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_unchange.c -- undo changes to file in zip archive
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -48,6 +48,7 @@ int
 _zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates)
 {
     zip_int64_t i;
+    const char *orig_name, *changed_name;
     
     if (idx >= za->nentry) {
        zip_error_set(&za->error, ZIP_ER_INVAL, 0);
@@ -55,9 +56,32 @@ _zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates)
     }
 
     if (!allow_duplicates && za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME)) {
-       i = _zip_name_locate(za, _zip_get_name(za, idx, ZIP_FL_UNCHANGED, NULL), 0, NULL);
-       if (i >= 0 && (zip_uint64_t)i != idx) {
-           zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
+       if (za->entry[idx].orig != NULL) {
+           if ((orig_name=_zip_get_name(za, idx, ZIP_FL_UNCHANGED, &za->error)) == NULL) {
+               return -1;
+           }
+
+           i = _zip_name_locate(za, orig_name, 0, NULL);
+           if (i >= 0 && (zip_uint64_t)i != idx) {
+               zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
+               return -1;
+           }
+       }
+       else {
+           orig_name = NULL;
+       }
+           
+       if ((changed_name=_zip_get_name(za, idx, 0, &za->error)) == NULL) {
+           return -1;
+       }
+
+       if (orig_name) {
+           if (_zip_hash_add(za->names, (const zip_uint8_t *)orig_name, idx, 0, &za->error) == false) {
+               return -1;
+           }
+       }
+       if (_zip_hash_delete(za->names, (const zip_uint8_t *)changed_name, &za->error) == false) {
+           _zip_hash_delete(za->names, (const zip_uint8_t *)orig_name, NULL);
            return -1;
        }
     }
index 60076838d4e1ab776270e39e5dfdeccce415e625..dc89f7fdaff14362e0e11d51bbc35e2f76382353 100644 (file)
@@ -1,6 +1,6 @@
 /*
   zip_unchange.c -- undo changes to all files in zip archive
-  Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -43,6 +43,8 @@ zip_unchange_all(zip_t *za)
     int ret;
     zip_uint64_t i;
 
+    _zip_hash_revert(za->names);
+    
     ret = 0;
     for (i=0; i<za->nentry; i++)
        ret |= _zip_unchange(za, i, 1);
index c8716fb952bf9eddb2e14c3e7b97760af47f70b6..8ac2652e1d205d561c274fac96fe625eee979e67 100644 (file)
@@ -7,10 +7,10 @@
    This file was generated automatically by CMake
    based on ../cmake-zipconf.h.in.
  */
-#define LIBZIP_VERSION "1.0.1"
+#define LIBZIP_VERSION "1.1.2"
 #define LIBZIP_VERSION_MAJOR 1
-#define LIBZIP_VERSION_MINOR 0
-#define LIBZIP_VERSION_MICRO 1
+#define LIBZIP_VERSION_MINOR 1
+#define LIBZIP_VERSION_MICRO 2
 
 /* #undef HAVE_INTTYPES_H_LIBZIP */
 
index d13bab42abfbdb06cb47f40b9a55b0a54a0522a5..323b3f1ea7eac468fca04836046cf756211c26aa 100644 (file)
@@ -3,7 +3,7 @@
 
 /*
   zipint.h -- internal declarations.
-  Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+  Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
 
   This file is part of libzip, a library to manipulate ZIP archives.
   The authors can be contacted at <libzip@nih.at>
@@ -37,7 +37,9 @@
 #ifdef PHP_WIN32
 # include "php_zip_config.w32.h"
 #else
-# include "config.h"
+# ifdef HAVE_CONFIG_H
+#  include "config.h"
+# endif
 #endif
 
 /* to have *_MAX definitions for all types when compiling with g++ */
@@ -65,6 +67,22 @@ typedef char bool;
 #define false   0
 #endif
 
+#include <errno.h>
+
+/* at least MinGW does not provide EOPNOTSUPP, see
+ * http://sourceforge.net/p/mingw/bugs/263/
+ */
+#ifndef EOPNOTSUPP
+#define EOPNOTSUPP EINVAL
+#endif
+
+/* at least MinGW does not provide EOVERFLOW, see
+ * http://sourceforge.net/p/mingw/bugs/242/
+ */
+#ifndef EOVERFLOW
+#define EOVERFLOW EFBIG
+#endif
+
 #ifdef _WIN32
 #if defined(HAVE__CLOSE)
 #define close          _close
@@ -76,7 +94,7 @@ typedef char bool;
 #if defined(HAVE__FDOPEN)
 #define fdopen         _fdopen
 #endif
-#if defined(HAVE__FILENO)
+#if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
 #define fileno         _fileno
 #endif
 /* Windows' open() doesn't understand Unix permissions */
@@ -92,6 +110,9 @@ typedef char bool;
 #define strdup         _strdup
 #endif
 #endif
+#if !defined(HAVE__SETMODE) && defined(HAVE_SETMODE)
+#define _setmode       setmode
+#endif
 #endif
 
 #ifndef HAVE_FSEEKO
@@ -110,6 +131,8 @@ int _zip_mkstemp(char *);
 #if !defined(HAVE_STRCASECMP)
 #if defined(HAVE__STRICMP)
 #define strcasecmp     _stricmp
+#elif defined(HAVE_STRICMP)
+#define strcasecmp     stricmp
 #endif
 #endif
 
@@ -129,12 +152,10 @@ int _zip_mkstemp(char *);
 #if defined(HAVE_FTELLO) && defined(HAVE_FSEEKO)
 #define ZIP_FSEEK_MAX ZIP_OFF_MAX
 #define ZIP_FSEEK_MIN ZIP_OFF_MIN
-#elif SIZEOF_LONG >= 8
-#define ZIP_FSEEK_MAX (long)ZIP_INT64_MAX
-#define ZIP_FSEEK_MIN (long)ZIP_INT64_MIN
 #else
-#define ZIP_FSEEK_MAX (long)ZIP_INT32_MAX
-#define ZIP_FSEEK_MIN (long)ZIP_INT32_MIN
+#include <limits.h>
+#define ZIP_FSEEK_MAX LONG_MAX
+#define ZIP_FSEEK_MIN LONG_MIN
 #endif
 
 #ifndef SIZE_MAX
@@ -255,13 +276,19 @@ enum zip_encoding_type {
 
 typedef enum zip_encoding_type zip_encoding_type_t;
 
+#ifndef ZIP_HASH_TABLE_SIZE
+#define ZIP_HASH_TABLE_SIZE 8192
+#endif
+
+struct zip_hash;
+
 typedef struct zip_cdir zip_cdir_t;
 typedef struct zip_dirent zip_dirent_t;
 typedef struct zip_entry zip_entry_t;
 typedef struct zip_extra_field zip_extra_field_t;
 typedef struct zip_string zip_string_t;
 typedef struct zip_buffer zip_buffer_t;
-
+typedef struct zip_hash zip_hash_t;
 
 /* zip archive, part of API */
 
@@ -276,7 +303,7 @@ struct zip {
     char *default_password;            /* password used when no other supplied */
 
     zip_string_t *comment_orig;         /* archive comment */
-    zip_string_t *comment_changes;  /* changed archive comment */
+    zip_string_t *comment_changes;     /* changed archive comment */
     bool comment_changed;              /* whether archive comment was changed */
 
     zip_uint64_t nentry;               /* number of entries */
@@ -286,6 +313,8 @@ struct zip {
     unsigned int nopen_source;         /* number of open sources using archive */
     unsigned int nopen_source_alloc;   /* number of sources allocated */
     zip_source_t **open_source;         /* open sources using archive */
+
+    zip_hash_t *names;                 /* hash table for name lookup */
     
     char *tempdir;                      /* custom temp dir (needed e.g. for OS X sandboxing) */
 };
@@ -312,7 +341,7 @@ struct zip_file {
 struct zip_dirent {
     zip_uint32_t changed;
     bool local_extra_fields_read;      /*      whether we already read in local header extra fields */
-    bool cloned;                         /*      whether this instance is cloned, and thus shares non-changed strings */
+    bool cloned;                        /*      whether this instance is cloned, and thus shares non-changed strings */
 
     zip_uint16_t version_madeby;       /* (c)  version of creator */
     zip_uint16_t version_needed;       /* (cl) version needed to extract */
@@ -415,7 +444,7 @@ struct zip_buffer {
 
 struct zip_filelist {
     zip_uint64_t idx;
-// TODO    const char *name;
+/* TODO    const char *name; */
 };
 
 typedef struct zip_filelist zip_filelist_t;
@@ -453,6 +482,7 @@ int _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i);
 int _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i);
 int _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i);
 int _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i);
+int _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length);
 int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset);
 zip_uint64_t _zip_buffer_size(zip_buffer_t *buffer);
 
@@ -478,7 +508,7 @@ void _zip_ef_free(zip_extra_field_t *);
 const zip_uint8_t *_zip_ef_get_by_id(const zip_extra_field_t *, zip_uint16_t *, zip_uint16_t, zip_uint16_t, zip_flags_t, zip_error_t *);
 zip_extra_field_t *_zip_ef_merge(zip_extra_field_t *, zip_extra_field_t *);
 zip_extra_field_t *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_flags_t);
-zip_extra_field_t *_zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_error_t *);
+bool _zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_extra_field_t **, zip_error_t *);
 zip_extra_field_t *_zip_ef_remove_internal(zip_extra_field_t *);
 zip_uint16_t _zip_ef_size(const zip_extra_field_t *, zip_flags_t);
 int _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags);
@@ -505,6 +535,13 @@ zip_dirent_t *_zip_get_dirent(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *)
 enum zip_encoding_type _zip_guess_encoding(zip_string_t *, enum zip_encoding_type);
 zip_uint8_t *_zip_cp437_to_utf8(const zip_uint8_t * const, zip_uint32_t, zip_uint32_t *, zip_error_t *);
 
+bool _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error);
+bool _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *key, zip_error_t *error);
+void _zip_hash_free(zip_hash_t *hash);
+zip_int64_t _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error);
+zip_hash_t *_zip_hash_new(zip_uint16_t hash_size, zip_error_t *error);
+void _zip_hash_revert(zip_hash_t *hash);
+
 zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *);
 
 int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_error_t *error);
index ceedfce57221e0a8f4345b98220061a41223e6ae..f5df19e79a1a916519aef93ab5ef251c87f7a443 100644 (file)
@@ -37,7 +37,7 @@ extern zend_module_entry zip_module_entry;
 #define ZIP_OVERWRITE ZIP_TRUNCATE
 #endif
 
-#define PHP_ZIP_VERSION "1.13.0"
+#define PHP_ZIP_VERSION "1.13.2"
 
 #ifndef  Z_SET_REFCOUNT_P
 # if PHP_MAJOR_VERSION < 6 && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3)