diff options
Diffstat (limited to 'ext/zip/lib')
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); |