summaryrefslogtreecommitdiff
path: root/ext/zip/lib
diff options
context:
space:
mode:
Diffstat (limited to 'ext/zip/lib')
-rw-r--r--ext/zip/lib/zip_add_entry.c17
-rw-r--r--ext/zip/lib/zip_buffer.c11
-rw-r--r--ext/zip/lib/zip_close.c1
-rw-r--r--ext/zip/lib/zip_delete.c12
-rw-r--r--ext/zip/lib/zip_dirent.c109
-rw-r--r--ext/zip/lib/zip_discard.c4
-rw-r--r--ext/zip/lib/zip_error.c3
-rw-r--r--ext/zip/lib/zip_error_strerror.c3
-rw-r--r--ext/zip/lib/zip_error_to_str.c3
-rw-r--r--ext/zip/lib/zip_extra_field.c55
-rw-r--r--ext/zip/lib/zip_fdopen.c3
-rw-r--r--ext/zip/lib/zip_file_get_offset.c3
-rw-r--r--ext/zip/lib/zip_filerange_crc.c3
-rw-r--r--ext/zip/lib/zip_fopen_index.c3
-rw-r--r--ext/zip/lib/zip_fopen_index_encrypted.c3
-rw-r--r--ext/zip/lib/zip_hash.c267
-rw-r--r--ext/zip/lib/zip_io_util.c3
-rw-r--r--ext/zip/lib/zip_name_locate.c48
-rw-r--r--ext/zip/lib/zip_new.c7
-rw-r--r--ext/zip/lib/zip_open.c73
-rw-r--r--ext/zip/lib/zip_set_default_password.c3
-rw-r--r--ext/zip/lib/zip_set_name.c93
-rw-r--r--ext/zip/lib/zip_source_buffer.c5
-rw-r--r--ext/zip/lib/zip_source_crc.c100
-rw-r--r--ext/zip/lib/zip_source_file.c1
-rw-r--r--ext/zip/lib/zip_source_filep.c29
-rw-r--r--ext/zip/lib/zip_source_pkware.c4
-rw-r--r--ext/zip/lib/zip_source_stat.c4
-rw-r--r--ext/zip/lib/zip_source_supports.c4
-rw-r--r--ext/zip/lib/zip_source_win32a.c3
-rw-r--r--ext/zip/lib/zip_source_win32handle.c5
-rw-r--r--ext/zip/lib/zip_source_win32utf8.c1
-rw-r--r--ext/zip/lib/zip_source_win32w.c5
-rw-r--r--ext/zip/lib/zip_unchange.c32
-rw-r--r--ext/zip/lib/zip_unchange_all.c4
-rw-r--r--ext/zip/lib/zipconf.h6
-rw-r--r--ext/zip/lib/zipint.h63
37 files changed, 748 insertions, 245 deletions
diff --git a/ext/zip/lib/zip_add_entry.c b/ext/zip/lib/zip_add_entry.c
index 24dbdaf47c..9a9465c5f0 100644
--- a/ext/zip/lib/zip_add_entry.c
+++ b/ext/zip/lib/zip_add_entry.c
@@ -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);
diff --git a/ext/zip/lib/zip_buffer.c b/ext/zip/lib/zip_buffer.c
index 3d79b09f13..43864f9ba9 100644
--- a/ext/zip/lib/zip_buffer.c
+++ b/ext/zip/lib/zip_buffer.c
@@ -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)
{
diff --git a/ext/zip/lib/zip_close.c b/ext/zip/lib/zip_close.c
index a13e4466b3..b5eca67a46 100644
--- a/ext/zip/lib/zip_close.c
+++ b/ext/zip/lib/zip_close.c
@@ -40,7 +40,6 @@
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
-#include <errno.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
diff --git a/ext/zip/lib/zip_delete.c b/ext/zip/lib/zip_delete.c
index b3e7abb848..34520b0310 100644
--- a/ext/zip/lib/zip_delete.c
+++ b/ext/zip/lib/zip_delete.c
@@ -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)
diff --git a/ext/zip/lib/zip_dirent.c b/ext/zip/lib/zip_dirent.c
index e3a78b3146..630b6a49cb 100644
--- a/ext/zip/lib/zip_dirent.c
+++ b/ext/zip/lib/zip_dirent.c
@@ -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));
diff --git a/ext/zip/lib/zip_discard.c b/ext/zip/lib/zip_discard.c
index db22370842..1876c84f0c 100644
--- a/ext/zip/lib/zip_discard.c
+++ b/ext/zip/lib/zip_discard.c
@@ -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);
diff --git a/ext/zip/lib/zip_error.c b/ext/zip/lib/zip_error.c
index a21a00bc29..43ddf4f9cb 100644
--- a/ext/zip/lib/zip_error.c
+++ b/ext/zip/lib/zip_error.c
@@ -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"
diff --git a/ext/zip/lib/zip_error_strerror.c b/ext/zip/lib/zip_error_strerror.c
index 2f124ccd46..29efc8a91c 100644
--- a/ext/zip/lib/zip_error_strerror.c
+++ b/ext/zip/lib/zip_error_strerror.c
@@ -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>
diff --git a/ext/zip/lib/zip_error_to_str.c b/ext/zip/lib/zip_error_to_str.c
index d4119253f7..22de177842 100644
--- a/ext/zip/lib/zip_error_to_str.c
+++ b/ext/zip/lib/zip_error_to_str.c
@@ -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>
diff --git a/ext/zip/lib/zip_extra_field.c b/ext/zip/lib/zip_extra_field.c
index b2566c6887..035047827e 100644
--- a/ext/zip/lib/zip_extra_field.c
+++ b/ext/zip/lib/zip_extra_field.c
@@ -31,13 +31,11 @@
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;
diff --git a/ext/zip/lib/zip_fdopen.c b/ext/zip/lib/zip_fdopen.c
index c5b55311d2..bbcdf4f6bf 100644
--- a/ext/zip/lib/zip_fdopen.c
+++ b/ext/zip/lib/zip_fdopen.c
@@ -33,6 +33,9 @@
#include "zipint.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
ZIP_EXTERN zip_t *
diff --git a/ext/zip/lib/zip_file_get_offset.c b/ext/zip/lib/zip_file_get_offset.c
index 1aaca712d7..0257b042bc 100644
--- a/ext/zip/lib/zip_file_get_offset.c
+++ b/ext/zip/lib/zip_file_get_offset.c
@@ -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>
diff --git a/ext/zip/lib/zip_filerange_crc.c b/ext/zip/lib/zip_filerange_crc.c
index 8e06e8fa8b..f2a27fab34 100644
--- a/ext/zip/lib/zip_filerange_crc.c
+++ b/ext/zip/lib/zip_filerange_crc.c
@@ -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"
diff --git a/ext/zip/lib/zip_fopen_index.c b/ext/zip/lib/zip_fopen_index.c
index e9a169a2e1..7496f9829f 100644
--- a/ext/zip/lib/zip_fopen_index.c
+++ b/ext/zip/lib/zip_fopen_index.c
@@ -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>
diff --git a/ext/zip/lib/zip_fopen_index_encrypted.c b/ext/zip/lib/zip_fopen_index_encrypted.c
index 21cc43333c..92258e85fe 100644
--- a/ext/zip/lib/zip_fopen_index_encrypted.c
+++ b/ext/zip/lib/zip_fopen_index_encrypted.c
@@ -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
index 0000000000..23f9708dfd
--- /dev/null
+++ b/ext/zip/lib/zip_hash.c
@@ -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;
+ }
+ }
+ }
+}
diff --git a/ext/zip/lib/zip_io_util.c b/ext/zip/lib/zip_io_util.c
index 4a6bc1ddc1..b16927defb 100644
--- a/ext/zip/lib/zip_io_util.c
+++ b/ext/zip/lib/zip_io_util.c
@@ -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>
diff --git a/ext/zip/lib/zip_name_locate.c b/ext/zip/lib/zip_name_locate.c
index 820ea0ca7f..50ca40b1a9 100644
--- a/ext/zip/lib/zip_name_locate.c
+++ b/ext/zip/lib/zip_name_locate.c
@@ -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;
}
diff --git a/ext/zip/lib/zip_new.c b/ext/zip/lib/zip_new.c
index d54a247c29..562dd76a36 100644
--- a/ext/zip/lib/zip_new.c
+++ b/ext/zip/lib/zip_new.c
@@ -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);
diff --git a/ext/zip/lib/zip_open.c b/ext/zip/lib/zip_open.c
index fb9c566cb1..d6209ee1e7 100644
--- a/ext/zip/lib/zip_open.c
+++ b/ext/zip/lib/zip_open.c
@@ -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);
diff --git a/ext/zip/lib/zip_set_default_password.c b/ext/zip/lib/zip_set_default_password.c
index ac098dc5fc..10b48062fd 100644
--- a/ext/zip/lib/zip_set_default_password.c
+++ b/ext/zip/lib/zip_set_default_password.c
@@ -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) {
diff --git a/ext/zip/lib/zip_set_name.c b/ext/zip/lib/zip_set_name.c
index 5a10381753..2a461437e2 100644
--- a/ext/zip/lib/zip_set_name.c
+++ b/ext/zip/lib/zip_set_name.c
@@ -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;
diff --git a/ext/zip/lib/zip_source_buffer.c b/ext/zip/lib/zip_source_buffer.c
index aadf6e40b0..f3f8ee0d58 100644
--- a/ext/zip/lib/zip_source_buffer.c
+++ b/ext/zip/lib/zip_source_buffer.c
@@ -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;
diff --git a/ext/zip/lib/zip_source_crc.c b/ext/zip/lib/zip_source_crc.c
index eed726616a..01f526c647 100644
--- a/ext/zip/lib/zip_source_crc.c
+++ b/ext/zip/lib/zip_source_crc.c
@@ -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>
@@ -39,10 +39,12 @@
#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);
diff --git a/ext/zip/lib/zip_source_file.c b/ext/zip/lib/zip_source_file.c
index 1465e1700e..b3cd7ab29f 100644
--- a/ext/zip/lib/zip_source_file.c
+++ b/ext/zip/lib/zip_source_file.c
@@ -32,7 +32,6 @@
*/
-#include <errno.h>
#include <stdio.h>
#include "zipint.h"
diff --git a/ext/zip/lib/zip_source_filep.c b/ext/zip/lib/zip_source_filep.c
index e541305d7f..70255dec41 100644
--- a/ext/zip/lib/zip_source_filep.c
+++ b/ext/zip/lib/zip_source_filep.c
@@ -31,15 +31,17 @@
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>
@@ -49,11 +51,12 @@
#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);
diff --git a/ext/zip/lib/zip_source_pkware.c b/ext/zip/lib/zip_source_pkware.c
index ce281ac148..125e4e2c2a 100644
--- a/ext/zip/lib/zip_source_pkware.c
+++ b/ext/zip/lib/zip_source_pkware.c
@@ -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;
}
diff --git a/ext/zip/lib/zip_source_stat.c b/ext/zip/lib/zip_source_stat.c
index 34cb05f452..a6b46d06a6 100644
--- a/ext/zip/lib/zip_source_stat.c
+++ b/ext/zip/lib/zip_source_stat.c
@@ -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) {
diff --git a/ext/zip/lib/zip_source_supports.c b/ext/zip/lib/zip_source_supports.c
index 3c100fb71f..75a4a4626d 100644
--- a/ext/zip/lib/zip_source_supports.c
+++ b/ext/zip/lib/zip_source_supports.c
@@ -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;
diff --git a/ext/zip/lib/zip_source_win32a.c b/ext/zip/lib/zip_source_win32a.c
index e9786c473e..85493b660e 100644
--- a/ext/zip/lib/zip_source_win32a.c
+++ b/ext/zip/lib/zip_source_win32a.c
@@ -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"
diff --git a/ext/zip/lib/zip_source_win32handle.c b/ext/zip/lib/zip_source_win32handle.c
index d195a119db..35e2e67972 100644
--- a/ext/zip/lib/zip_source_win32handle.c
+++ b/ext/zip/lib/zip_source_win32handle.c
@@ -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.
diff --git a/ext/zip/lib/zip_source_win32utf8.c b/ext/zip/lib/zip_source_win32utf8.c
index e11214ba05..004c66ac2b 100644
--- a/ext/zip/lib/zip_source_win32utf8.c
+++ b/ext/zip/lib/zip_source_win32utf8.c
@@ -32,7 +32,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
#include <stdio.h>
#include "zipint.h"
diff --git a/ext/zip/lib/zip_source_win32w.c b/ext/zip/lib/zip_source_win32w.c
index 34134561f1..551aba5f37 100644
--- a/ext/zip/lib/zip_source_win32w.c
+++ b/ext/zip/lib/zip_source_win32w.c
@@ -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;
}
diff --git a/ext/zip/lib/zip_unchange.c b/ext/zip/lib/zip_unchange.c
index 6c8a495c78..5ef5462127 100644
--- a/ext/zip/lib/zip_unchange.c
+++ b/ext/zip/lib/zip_unchange.c
@@ -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;
}
}
diff --git a/ext/zip/lib/zip_unchange_all.c b/ext/zip/lib/zip_unchange_all.c
index 60076838d4..dc89f7fdaf 100644
--- a/ext/zip/lib/zip_unchange_all.c
+++ b/ext/zip/lib/zip_unchange_all.c
@@ -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);
diff --git a/ext/zip/lib/zipconf.h b/ext/zip/lib/zipconf.h
index c8716fb952..8ac2652e1d 100644
--- a/ext/zip/lib/zipconf.h
+++ b/ext/zip/lib/zipconf.h
@@ -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 */
diff --git a/ext/zip/lib/zipint.h b/ext/zip/lib/zipint.h
index d13bab42ab..323b3f1ea7 100644
--- a/ext/zip/lib/zipint.h
+++ b/ext/zip/lib/zipint.h
@@ -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);