diff options
44 files changed, 788 insertions, 312 deletions
diff --git a/src/Common/libzip/LICENSE b/src/Common/libzip/LICENSE index 8e3a62c7..1c2e86bf 100644 --- a/src/Common/libzip/LICENSE +++ b/src/Common/libzip/LICENSE @@ -29,3 +29,38 @@ 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. + + + +For AES encryption support, files under the following license are used: + +--------------------------------------------------------------------------- +Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK. +All rights reserved. + +LICENSE TERMS + +The free distribution and use of this software in both source and binary +form is allowed (with or without changes) provided that: + + 1. distributions of this source code include the above copyright + notice, this list of conditions and the following disclaimer; + + 2. distributions in binary form include the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other associated materials; + + 3. the copyright holder's name is not used to endorse products + built using this software without specific written permission. + +ALTERNATIVELY, provided that this notice is retained in full, this product +may be distributed under the terms of the GNU General Public License (GPL), +in which case the provisions of the GPL apply INSTEAD OF those given above. + +DISCLAIMER + +This software is provided 'as is' with no explicit or implied warranties +in respect of its properties, including, but not limited to, correctness +and/or fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 18th November 2008 diff --git a/src/Common/libzip/NEWS.md b/src/Common/libzip/NEWS.md index c915ce62..97bf2dea 100644 --- a/src/Common/libzip/NEWS.md +++ b/src/Common/libzip/NEWS.md @@ -1,3 +1,14 @@ +1.2.0 [2017-02-19] +================== + +* Support for AES encryption (Winzip version), both encryption + and decryption. +* Support legacy zip files with >64k entries. +* Fix seeking in zip_source_file if start > 0. +* Add zip_fseek() for seeking in uncompressed data. +* Add zip_ftell() for telling position in uncompressed data. +* Add zip_register_progress_callback() for UI updates during zip_close() + 1.1.3 [2016-05-28] ================== diff --git a/src/Common/libzip/compat.h b/src/Common/libzip/compat.h index ed1f8726..dc73f5ce 100644 --- a/src/Common/libzip/compat.h +++ b/src/Common/libzip/compat.h @@ -105,6 +105,12 @@ typedef char bool; #if !defined(HAVE__SETMODE) && defined(HAVE_SETMODE) #define _setmode setmode #endif +#if !defined(HAVE_STRTOLL) && defined(HAVE__STRTOI64) +#define strtoll _strtoi64 +#endif +#if !defined(HAVE_STRTOULL) && defined(HAVE__STRTOUI64) +#define strtoull _strtoui64 +#endif #endif #ifndef HAVE_FSEEKO diff --git a/src/Common/libzip/config.h b/src/Common/libzip/config.h index f4dec478..6212383c 100644 --- a/src/Common/libzip/config.h +++ b/src/Common/libzip/config.h @@ -14,6 +14,8 @@ #define HAVE__SNPRINTF #define HAVE__STRDUP #define HAVE__STRICMP +#define HAVE__STRTOI64 +#define HAVE__STRTOUI64 #define HAVE_FILENO /* #undef HAVE_FSEEKO */ /* #undef HAVE_FTELLO */ @@ -26,6 +28,8 @@ /* #undef HAVE_STRCASECMP */ #define HAVE_STRDUP #define HAVE_STRICMP +/* #undef HAVE_STRTOLL */ +/* #undef HAVE_STRTOULL */ /* #undef HAVE_STRUCT_TM_TM_ZONE */ /* #undef HAVE_STDBOOL_H */ /* #undef HAVE_STRINGS_H */ @@ -53,9 +57,10 @@ /* #undef HAVE_NDIR_H */ /* #undef HAVE_SYS_DIR_H */ /* #undef HAVE_SYS_NDIR_H */ +/* #undef WORDS_BIGENDIAN */ /* END DEFINES */ #define PACKAGE "libzip" -#define VERSION "1.1.3" +#define VERSION "1.2.0" #ifndef HAVE_SSIZE_T_LIBZIP # if SIZE_T_LIBZIP == INT_LIBZIP diff --git a/src/Common/libzip/zip.h b/src/Common/libzip/zip.h index 27141b34..abdaf07a 100644 --- a/src/Common/libzip/zip.h +++ b/src/Common/libzip/zip.h @@ -3,7 +3,7 @@ /* zip.h -- exported 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> @@ -20,7 +20,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 @@ -127,7 +127,7 @@ extern "C" { #define ZIP_ER_REMOVE 22 /* S Can't remove file */ #define ZIP_ER_DELETED 23 /* N Entry has been deleted */ #define ZIP_ER_ENCRNOTSUPP 24 /* N Encryption method not supported */ -#define ZIP_ER_RDONLY 25 /* N Read-only archive */ +#define ZIP_ER_RDONLY 25 /* N Read-only archive */ #define ZIP_ER_NOPASSWD 26 /* N No password provided */ #define ZIP_ER_WRONGPASSWD 27 /* N Wrong password provided */ #define ZIP_ER_OPNOTSUPP 28 /* N Operation not supported */ @@ -161,6 +161,8 @@ extern "C" { /* 15-17 - Reserved by PKWARE */ #define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */ #define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */ +#define ZIP_CM_XZ 95 /* XZ compressed data */ +#define ZIP_CM_JPEG 96 /* Compressed Jpeg data */ #define ZIP_CM_WAVPACK 97 /* WavPack compressed data */ #define ZIP_CM_PPMD 98 /* PPMd version I, Rev 1 */ @@ -173,12 +175,15 @@ extern "C" { #define ZIP_EM_RC2_OLD 0x6602 /* strong encryption: RC2, version < 5.2 */ #define ZIP_EM_3DES_168 0x6603 #define ZIP_EM_3DES_112 0x6609 -#define ZIP_EM_AES_128 0x660e -#define ZIP_EM_AES_192 0x660f -#define ZIP_EM_AES_256 0x6610 +#define ZIP_EM_PKZIP_AES_128 0x660e +#define ZIP_EM_PKZIP_AES_192 0x660f +#define ZIP_EM_PKZIP_AES_256 0x6610 #define ZIP_EM_RC2 0x6702 /* strong encryption: RC2, version >= 5.2 */ #define ZIP_EM_RC4 0x6801 #endif +#define ZIP_EM_AES_128 0x0101 /* Winzip AES encryption */ +#define ZIP_EM_AES_192 0x0102 +#define ZIP_EM_AES_256 0x0103 #define ZIP_EM_UNKNOWN 0xffff /* unknown algorithm */ #define ZIP_OPSYS_DOS 0x00u @@ -299,9 +304,10 @@ typedef struct zip_file zip_file_t; typedef struct zip_source zip_source_t; typedef struct zip_stat zip_stat_t; -typedef zip_uint32_t zip_flags_t; +typedef zip_uint32_t zip_flags_t; typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, zip_source_cmd_t); +typedef void (*zip_progress_callback_t)(double); #ifndef ZIP_DISABLE_DEPRECATED @@ -318,7 +324,6 @@ ZIP_EXTERN int zip_error_to_str(char *, zip_uint64_t, int, int); ZIP_EXTERN void zip_file_error_get(zip_file_t *, int *, int *); /* use zip_file_get_error, zip_error_code_zip / zip_error_code_system */ #endif -ZIP_EXTERN int zip_archive_set_tempdir(zip_t *, const char *); ZIP_EXTERN int zip_close(zip_t *); ZIP_EXTERN int zip_delete(zip_t *, zip_uint64_t); ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *, const char *, zip_flags_t); @@ -353,6 +358,7 @@ ZIP_EXTERN int zip_file_get_external_attributes(zip_t *, zip_uint64_t, zip_flags ZIP_EXTERN int zip_file_rename(zip_t *, zip_uint64_t, const char *, zip_flags_t); ZIP_EXTERN int zip_file_replace(zip_t *, zip_uint64_t, zip_source_t *, zip_flags_t); ZIP_EXTERN int zip_file_set_comment(zip_t *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_set_encryption(zip_t *, zip_uint64_t, zip_uint16_t, const char *); ZIP_EXTERN int zip_file_set_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t); ZIP_EXTERN int zip_file_set_mtime(zip_t *, zip_uint64_t, time_t, zip_flags_t); ZIP_EXTERN const char *zip_file_strerror(zip_file_t *); @@ -361,6 +367,8 @@ ZIP_EXTERN zip_file_t *zip_fopen_encrypted(zip_t *, const char *, zip_flags_t, c ZIP_EXTERN zip_file_t *zip_fopen_index(zip_t *, zip_uint64_t, zip_flags_t); ZIP_EXTERN zip_file_t *zip_fopen_index_encrypted(zip_t *, zip_uint64_t, zip_flags_t, const char *); ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *, void *, zip_uint64_t); +ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *, zip_int64_t, int); +ZIP_EXTERN zip_int64_t zip_ftell(zip_file_t *); ZIP_EXTERN const char *zip_get_archive_comment(zip_t *, int *, zip_flags_t); ZIP_EXTERN int zip_get_archive_flag(zip_t *, zip_flags_t, zip_flags_t); ZIP_EXTERN const char *zip_get_name(zip_t *, zip_uint64_t, zip_flags_t); @@ -368,6 +376,7 @@ ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *, zip_flags_t); ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *, const char *, zip_flags_t); ZIP_EXTERN zip_t *zip_open(const char *, int, int *); ZIP_EXTERN zip_t *zip_open_from_source(zip_source_t *, int, zip_error_t *); +ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t); ZIP_EXTERN int zip_set_archive_comment(zip_t *, const char *, zip_uint16_t); ZIP_EXTERN int zip_set_archive_flag(zip_t *, zip_flags_t, int); ZIP_EXTERN int zip_set_default_password(zip_t *, const char *); @@ -377,7 +386,7 @@ ZIP_EXTERN zip_source_t *zip_source_buffer(zip_t *, const void *, zip_uint64_t, ZIP_EXTERN zip_source_t *zip_source_buffer_create(const void *, zip_uint64_t, int, zip_error_t *); ZIP_EXTERN int zip_source_close(zip_source_t *); ZIP_EXTERN int zip_source_commit_write(zip_source_t *); -ZIP_EXTERN zip_error_t *zip_source_error(zip_source_t *src); +ZIP_EXTERN zip_error_t *zip_source_error(zip_source_t *); ZIP_EXTERN zip_source_t *zip_source_file(zip_t *, const char *, zip_uint64_t, zip_int64_t); ZIP_EXTERN zip_source_t *zip_source_file_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *); ZIP_EXTERN zip_source_t *zip_source_filep(zip_t *, FILE *, zip_uint64_t, zip_int64_t); diff --git a/src/Common/libzip/zip_add_entry.c b/src/Common/libzip/zip_add_entry.c index 9a9465c5..f6212f15 100644 --- a/src/Common/libzip/zip_add_entry.c +++ b/src/Common/libzip/zip_add_entry.c @@ -1,6 +1,6 @@ /* zip_add_entry.c -- create and init struct zip_entry - 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> diff --git a/src/Common/libzip/zip_buffer.c b/src/Common/libzip/zip_buffer.c index 43864f9b..7addc4b6 100644 --- a/src/Common/libzip/zip_buffer.c +++ b/src/Common/libzip/zip_buffer.c @@ -1,10 +1,10 @@ /* zip_buffer.c -- bounds checked access to memory buffer - Copyright (C) 2014 Dieter Baron and Thomas Klausner - + Copyright (C) 2014-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: @@ -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 @@ -49,11 +49,11 @@ _zip_buffer_free(zip_buffer_t *buffer) if (buffer == NULL) { return; } - + if (buffer->free_data) { free(buffer->data); } - + free(buffer); } @@ -69,14 +69,13 @@ zip_uint8_t * _zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) { zip_uint8_t *data; - - if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) { - buffer->ok = false; - return NULL; + + data = _zip_buffer_peek(buffer, length); + + if (data != NULL) { + buffer->offset += length; } - - data = buffer->data + buffer->offset; - buffer->offset += length; + return data; } @@ -85,11 +84,11 @@ zip_uint16_t _zip_buffer_get_16(zip_buffer_t *buffer) { zip_uint8_t *data = _zip_buffer_get(buffer, 2); - + if (data == NULL) { return 0; } - + return (zip_uint16_t)(data[0] + (data[1] << 8)); } @@ -98,11 +97,11 @@ zip_uint32_t _zip_buffer_get_32(zip_buffer_t *buffer) { zip_uint8_t *data = _zip_buffer_get(buffer, 4); - + if (data == NULL) { return 0; } - + return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0]; } @@ -111,7 +110,7 @@ zip_uint64_t _zip_buffer_get_64(zip_buffer_t *buffer) { zip_uint8_t *data = _zip_buffer_get(buffer, 8); - + if (data == NULL) { return 0; } @@ -125,11 +124,11 @@ zip_uint8_t _zip_buffer_get_8(zip_buffer_t *buffer) { zip_uint8_t *data = _zip_buffer_get(buffer, 1); - + if (data == NULL) { return 0; } - + return data[0]; } @@ -141,12 +140,25 @@ _zip_buffer_left(zip_buffer_t *buffer) } +zip_uint64_t +_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) +{ + if (_zip_buffer_left(buffer) < length) { + length = _zip_buffer_left(buffer); + } + + memcpy(data, _zip_buffer_get(buffer, length), length); + + return length; +} + + zip_buffer_t * _zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) { bool free_data = (data == NULL); zip_buffer_t *buffer; - + if (data == NULL) { if ((data = (zip_uint8_t *)malloc(size)) == NULL) { return NULL; @@ -159,13 +171,13 @@ _zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) } return NULL; } - + buffer->ok = true; buffer->data = data; buffer->size = size; buffer->offset = 0; buffer->free_data = free_data; - + return buffer; } @@ -174,17 +186,17 @@ zip_buffer_t * _zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error) { zip_buffer_t *buffer; - + if ((buffer = _zip_buffer_new(buf, size)) == NULL) { zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; } - + if (_zip_read(src, buffer->data, size, error) < 0) { _zip_buffer_free(buffer); return NULL; } - + return buffer; } @@ -203,15 +215,30 @@ _zip_buffer_ok(zip_buffer_t *buffer) } + +zip_uint8_t * +_zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length) +{ + zip_uint8_t *data; + + if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) { + buffer->ok = false; + return NULL; + } + + data = buffer->data + buffer->offset; + return data; +} + int _zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length) { zip_uint8_t *dst = _zip_buffer_get(buffer, length); - + if (dst == NULL) { return -1; } - + memcpy(dst, src, length); return 0; } @@ -221,14 +248,14 @@ int _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i) { zip_uint8_t *data = _zip_buffer_get(buffer, 2); - + if (data == NULL) { return -1; } data[0] = (zip_uint8_t)(i & 0xff); data[1] = (zip_uint8_t)((i >> 8) & 0xff); - + return 0; } @@ -237,16 +264,16 @@ int _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i) { zip_uint8_t *data = _zip_buffer_get(buffer, 4); - + if (data == NULL) { return -1; } - + data[0] = (zip_uint8_t)(i & 0xff); data[1] = (zip_uint8_t)((i >> 8) & 0xff); data[2] = (zip_uint8_t)((i >> 16) & 0xff); data[3] = (zip_uint8_t)((i >> 24) & 0xff); - + return 0; } @@ -255,11 +282,11 @@ int _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) { zip_uint8_t *data = _zip_buffer_get(buffer, 8); - + if (data == NULL) { return -1; } - + data[0] = (zip_uint8_t)(i & 0xff); data[1] = (zip_uint8_t)((i >> 8) & 0xff); data[2] = (zip_uint8_t)((i >> 16) & 0xff); @@ -268,7 +295,7 @@ _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) data[5] = (zip_uint8_t)((i >> 40) & 0xff); data[6] = (zip_uint8_t)((i >> 48) & 0xff); data[7] = (zip_uint8_t)((i >> 56) & 0xff); - + return 0; } @@ -277,13 +304,13 @@ int _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) { zip_uint8_t *data = _zip_buffer_get(buffer, 1); - + if (data == NULL) { return -1; } - + data[0] = i; - + return 0; } @@ -295,10 +322,10 @@ _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) buffer->ok = false; return -1; } - + buffer->ok = true; buffer->offset = offset; - + return 0; } @@ -306,7 +333,7 @@ _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; diff --git a/src/Common/libzip/zip_close.c b/src/Common/libzip/zip_close.c index b5eca67a..88fa4449 100644 --- a/src/Common/libzip/zip_close.c +++ b/src/Common/libzip/zip_close.c @@ -1,6 +1,6 @@ /* zip_close.c -- close zip archive and update changes - 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> @@ -131,10 +131,14 @@ zip_close(zip_t *za) zip_entry_t *entry; zip_dirent_t *de; + if (za->progress_callback) { + za->progress_callback((double)j/survivors); + } + i = filelist[j].idx; entry = za->entry+i; - new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD)); + new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD)); /* create new local directory entry */ if (entry->changes == NULL) { @@ -222,6 +226,10 @@ zip_close(zip_t *za) return -1; } + if (za->progress_callback) { + za->progress_callback(1); + } + zip_discard(za); return 0; @@ -233,10 +241,11 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) { zip_int64_t offstart, offdata, offend; struct zip_stat st; - zip_source_t *s2; + zip_source_t *src_final, *src_tmp; int ret; int is_zip64; zip_flags_t flags; + bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt; if (zip_source_stat(src, &st) < 0) { _zip_error_set_from_source(&za->error, src); @@ -259,6 +268,10 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) st.valid &= ~ZIP_STAT_COMP_SIZE; } + if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) { + st.valid |= ZIP_STAT_ENCRYPTION_METHOD; + st.encryption_method = ZIP_EM_NONE; + } flags = ZIP_EF_LOCAL; @@ -285,67 +298,123 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0) return -1; + needs_recompress = !((st.comp_method == de->comp_method) || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method == ZIP_CM_DEFLATE)); + needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE); + needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress; + needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE); + + needs_reencrypt = needs_recompress || (de->changed & ZIP_DIRENT_PASSWORD) || (de->encryption_method != st.encryption_method); + needs_decrypt = needs_reencrypt && (st.encryption_method != ZIP_EM_NONE); + needs_encrypt = needs_reencrypt && (de->encryption_method != ZIP_EM_NONE); + + src_final = src; + zip_source_keep(src_final); + + if (needs_decrypt) { + zip_encryption_implementation impl; + + if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + zip_source_free(src_final); + return -1; + } + if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) { + /* error set by impl */ + zip_source_free(src_final); + return -1; + } - if (st.comp_method == ZIP_CM_STORE || (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != de->comp_method)) { - zip_source_t *s_store, *s_crc; + zip_source_free(src_final); + src_final = src_tmp; + } + + if (needs_decompress) { zip_compression_implementation comp_impl; - if (st.comp_method != ZIP_CM_STORE) { - if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) { - zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); - return -1; - } - if ((s_store=comp_impl(za, src, st.comp_method, ZIP_CODEC_DECODE)) == NULL) { - /* error set by comp_impl */ - return -1; - } + if ((comp_impl = _zip_get_compression_implementation(st.comp_method, ZIP_CODEC_DECODE)) == NULL) { + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + zip_source_free(src_final); + return -1; } - else { - /* to have the same reference count to src as in the case where it's not stored */ - zip_source_keep(src); - s_store = src; + if ((src_tmp = comp_impl(za, src_final, st.comp_method, ZIP_CODEC_DECODE)) == NULL) { + /* error set by comp_impl */ + zip_source_free(src_final); + return -1; } - s_crc = zip_source_crc(za, s_store, 0); - zip_source_free(s_store); - if (s_crc == NULL) { + zip_source_free(src_final); + src_final = src_tmp; + } + + if (needs_crc) { + if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) { + zip_source_free(src_final); return -1; } - if (de->comp_method != ZIP_CM_STORE && ((st.valid & ZIP_STAT_SIZE) == 0 || st.size != 0)) { - if ((comp_impl=_zip_get_compression_implementation(de->comp_method)) == NULL) { - zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); - zip_source_free(s_crc); - return -1; - } - s2 = comp_impl(za, s_crc, de->comp_method, ZIP_CODEC_ENCODE); - zip_source_free(s_crc); - if (s2 == NULL) { - return -1; - } + zip_source_free(src_final); + src_final = src_tmp; + } + + if (needs_compress) { + zip_compression_implementation comp_impl; + + if ((comp_impl = _zip_get_compression_implementation(de->comp_method, ZIP_CODEC_ENCODE)) == NULL) { + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + zip_source_free(src_final); + return -1; } - else { - s2 = s_crc; + if ((src_tmp = comp_impl(za, src_final, de->comp_method, ZIP_CODEC_ENCODE)) == NULL) { + zip_source_free(src_final); + return -1; } + + zip_source_free(src_final); + src_final = src_tmp; } - else { - zip_source_keep(src); - s2 = src; + + + if (needs_encrypt) { + zip_encryption_implementation impl; + const char *password = NULL; + + if (de->password) { + password = de->password; + } else if (za->default_password) { + password = za->default_password; + } + + if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + zip_source_free(src_final); + return -1; + } + if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) { + /* error set by impl */ + zip_source_free(src_final); + return -1; + } + + zip_source_free(src_final); + src_final = src_tmp; } + if ((offdata = zip_source_tell_write(za->src)) < 0) { return -1; } - ret = copy_source(za, s2); + ret = copy_source(za, src_final); - if (zip_source_stat(s2, &st) < 0) + if (zip_source_stat(src_final, &st) < 0) { ret = -1; + } - zip_source_free(s2); + zip_source_free(src_final); - if (ret < 0) + if (ret < 0) { return -1; + } if ((offend = zip_source_tell_write(za->src)) < 0) { return -1; diff --git a/src/Common/libzip/zip_delete.c b/src/Common/libzip/zip_delete.c index 34520b03..e1602101 100644 --- a/src/Common/libzip/zip_delete.c +++ b/src/Common/libzip/zip_delete.c @@ -1,6 +1,6 @@ /* zip_delete.c -- delete file from zip archive - 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> diff --git a/src/Common/libzip/zip_dirent.c b/src/Common/libzip/zip_dirent.c index 74f89880..df38afd9 100644 --- a/src/Common/libzip/zip_dirent.c +++ b/src/Common/libzip/zip_dirent.c @@ -44,6 +44,7 @@ static time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t); static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str); static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t, zip_string_t *, zip_error_t *); +static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error); void @@ -66,29 +67,58 @@ zip_cdir_t * _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; } - if (nentry == 0) - cd->entry = NULL; - else if ((nentry > SIZE_MAX/sizeof(*(cd->entry))) || (cd->entry=(zip_entry_t *)malloc(sizeof(*(cd->entry))*(size_t)nentry)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - free(cd); + cd->entry = NULL; + cd->nentry = cd->nentry_alloc = 0; + cd->size = cd->offset = 0; + cd->comment = NULL; + cd->is_zip64 = false; + + if (!_zip_cdir_grow(cd, nentry, error)) { + _zip_cdir_free(cd); return NULL; } - for (i=0; i<nentry; i++) + return cd; +} + + +bool +_zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) +{ + zip_uint64_t i, new_alloc; + zip_entry_t *new_entry; + + if (additional_entries == 0) { + return true; + } + + new_alloc = cd->nentry_alloc + additional_entries; + + if (new_alloc < additional_entries || new_alloc > SIZE_MAX/sizeof(*(cd->entry))) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + if ((new_entry = (zip_entry_t *)realloc(cd->entry, sizeof(*(cd->entry))*(size_t)new_alloc)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + cd->entry = new_entry; + + for (i = cd->nentry; i < new_alloc; i++) { _zip_entry_init(cd->entry+i); + } - cd->nentry = cd->nentry_alloc = nentry; - cd->size = cd->offset = 0; - cd->comment = NULL; + cd->nentry = cd->nentry_alloc = new_alloc; - return cd; + return true; } @@ -222,6 +252,13 @@ _zip_dirent_finalize(zip_dirent_t *zde) _zip_string_free(zde->comment); zde->comment = NULL; } + if (!zde->cloned || zde->changed & ZIP_DIRENT_PASSWORD) { + if (zde->password) { + _zip_crypto_clear(zde->password, strlen(zde->password)); + } + free(zde->password); + zde->password = NULL; + } } @@ -243,6 +280,7 @@ _zip_dirent_init(zip_dirent_t *de) de->local_extra_fields_read = 0; de->cloned = 0; + de->crc_valid = true; de->version_madeby = 20 | (ZIP_OPSYS_DEFAULT << 8); de->version_needed = 20; /* 2.0 */ de->bitflags = 0; @@ -258,6 +296,8 @@ _zip_dirent_init(zip_dirent_t *de) de->int_attrib = 0; de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT; de->offset = 0; + de->encryption_method = ZIP_EM_NONE; + de->password = NULL; } @@ -372,6 +412,19 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo return -1; } + if (zde->bitflags & ZIP_GPBF_ENCRYPTED) { + if (zde->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) { + /* TODO */ + zde->encryption_method = ZIP_EM_UNKNOWN; + } + else { + zde->encryption_method = ZIP_EM_TRAD_PKWARE; + } + } + else { + zde->encryption_method = ZIP_EM_NONE; + } + zde->filename = NULL; zde->extra_fields = NULL; zde->comment = NULL; @@ -524,6 +577,13 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo return -1; } + if (!_zip_dirent_process_winzip_aes(zde, error)) { + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields); return (zip_int64_t)(size + variable_size); @@ -566,6 +626,90 @@ _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string } +static bool +_zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) +{ + zip_uint16_t ef_len; + zip_buffer_t *buffer; + const zip_uint8_t *ef; + bool crc_valid; + zip_uint16_t enc_method; + + + if (de->comp_method != ZIP_CM_WINZIP_AES) { + return true; + } + + ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL); + + if (ef == NULL || ef_len < 7) { + zip_error_set(error, ZIP_ER_INCONS, 0); + return false; + } + + if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return false; + } + + /* version */ + + crc_valid = true; + switch (_zip_buffer_get_16(buffer)) { + case 1: + break; + + case 2: + if (de->uncomp_size < 20 /* TODO: constant */) { + crc_valid = false; + } + break; + + default: + zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); + _zip_buffer_free(buffer); + return false; + } + + /* vendor */ + if (memcmp(_zip_buffer_get(buffer, 2), "AE", 2) != 0) { + zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); + _zip_buffer_free(buffer); + return false; + } + + /* mode */ + switch (_zip_buffer_get_8(buffer)) { + case 1: + enc_method = ZIP_EM_AES_128; + break; + case 2: + enc_method = ZIP_EM_AES_192; + break; + case 3: + enc_method = ZIP_EM_AES_256; + break; + default: + zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0); + _zip_buffer_free(buffer); + return false; + } + + if (ef_len != 7) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_buffer_free(buffer); + return false; + } + + de->crc_valid = crc_valid; + de->encryption_method = enc_method; + de->comp_method = _zip_buffer_get_16(buffer); + + _zip_buffer_free(buffer); + return true; +} + + zip_int32_t _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) { @@ -621,6 +765,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) zip_uint32_t ef_total_size; bool is_zip64; bool is_really_zip64; + bool is_winzip_aes; zip_uint8_t buf[CDENTRYSIZE]; zip_buffer_t *buffer; @@ -651,8 +796,16 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) } } + if (de->encryption_method == ZIP_EM_NONE) { + de->bitflags &= ~ZIP_GPBF_ENCRYPTED; + } + else { + de->bitflags |= ZIP_GPBF_ENCRYPTED; + } + 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; + is_winzip_aes = de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256; if (is_zip64) { zip_uint8_t ef_zip64[EFZIP64SIZE]; @@ -696,6 +849,35 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) ef = ef64; } + if (is_winzip_aes) { + zip_uint8_t data[EF_WINZIP_AES_SIZE]; + zip_buffer_t *ef_buffer = _zip_buffer_new(data, sizeof(data)); + zip_extra_field_t *ef_winzip; + + if (ef_buffer == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_ef_free(ef); + return -1; + } + + _zip_buffer_put_16(ef_buffer, 2); + _zip_buffer_put(ef_buffer, "AE", 2); + _zip_buffer_put_8(ef_buffer, (de->encryption_method & 0xff)); + _zip_buffer_put_16(ef_buffer, (zip_uint16_t)de->comp_method); + + if (!_zip_buffer_ok(ef_buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(ef_buffer); + _zip_ef_free(ef); + return -1; + } + + ef_winzip = _zip_ef_new(ZIP_EF_WINZIP_AES, EF_WINZIP_AES_SIZE, data, ZIP_EF_BOTH); + _zip_buffer_free(ef_buffer); + ef_winzip->next = ef; + ef = ef_winzip; + } + if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) { zip_error_set(&za->error, ZIP_ER_MEMORY, 0); _zip_ef_free(ef); @@ -709,13 +891,23 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) } _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_needed)); _zip_buffer_put_16(buffer, de->bitflags&0xfff9); /* clear compression method specific flags */ - _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method); + if (is_winzip_aes) { + _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES); + } + else { + _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method); + } _zip_u2d_time(de->last_mod, &dostime, &dosdate); _zip_buffer_put_16(buffer, dostime); _zip_buffer_put_16(buffer, dosdate); - _zip_buffer_put_32(buffer, de->crc); + if (is_winzip_aes && de->uncomp_size < 20) { + _zip_buffer_put_32(buffer, 0); + } + else { + _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 diff --git a/src/Common/libzip/zip_discard.c b/src/Common/libzip/zip_discard.c index 1876c84f..ef891e38 100644 --- a/src/Common/libzip/zip_discard.c +++ b/src/Common/libzip/zip_discard.c @@ -1,6 +1,6 @@ /* zip_discard.c -- discard and free struct zip - 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> diff --git a/src/Common/libzip/zip_err_str.c b/src/Common/libzip/zip_err_str.c index 65698be0..9c9adb55 100644 --- a/src/Common/libzip/zip_err_str.c +++ b/src/Common/libzip/zip_err_str.c @@ -31,7 +31,7 @@ const char * const _zip_err_str[] = { "Can't remove file", "Entry has been deleted", "Encryption method not supported", - "Read-only archive", + "Read-only archive", "No password provided", "Wrong password provided", "Operation not supported", @@ -71,7 +71,7 @@ const int _zip_err_type[] = { S, N, N, - N, + N, N, N, N, diff --git a/src/Common/libzip/zip_error.c b/src/Common/libzip/zip_error.c index 43ddf4f9..5f4e07dc 100644 --- a/src/Common/libzip/zip_error.c +++ b/src/Common/libzip/zip_error.c @@ -1,6 +1,6 @@ /* zip_error.c -- zip_error_t helper functions - 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> diff --git a/src/Common/libzip/zip_error_strerror.c b/src/Common/libzip/zip_error_strerror.c index 29efc8a9..bdc1e44c 100644 --- a/src/Common/libzip/zip_error_strerror.c +++ b/src/Common/libzip/zip_error_strerror.c @@ -1,6 +1,6 @@ /* zip_error_sterror.c -- get string representation of struct zip_error - 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> diff --git a/src/Common/libzip/zip_error_to_str.c b/src/Common/libzip/zip_error_to_str.c index 22de1778..019feff8 100644 --- a/src/Common/libzip/zip_error_to_str.c +++ b/src/Common/libzip/zip_error_to_str.c @@ -1,6 +1,6 @@ /* zip_error_to_str.c -- get string representation of zip error code - 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> diff --git a/src/Common/libzip/zip_extra_field.c b/src/Common/libzip/zip_extra_field.c index 03504782..a01ff790 100644 --- a/src/Common/libzip/zip_extra_field.c +++ b/src/Common/libzip/zip_extra_field.c @@ -1,6 +1,6 @@ /* zip_extra_field.c -- manipulate extra fields - Copyright (C) 2012-2015 Dieter Baron and Thomas Klausner + Copyright (C) 2012-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> diff --git a/src/Common/libzip/zip_fdopen.c b/src/Common/libzip/zip_fdopen.c index bbcdf4f6..a058f811 100644 --- a/src/Common/libzip/zip_fdopen.c +++ b/src/Common/libzip/zip_fdopen.c @@ -1,6 +1,6 @@ /* zip_fdopen.c -- open read-only archive from file descriptor - 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> diff --git a/src/Common/libzip/zip_file_get_offset.c b/src/Common/libzip/zip_file_get_offset.c index 0257b042..826650e5 100644 --- a/src/Common/libzip/zip_file_get_offset.c +++ b/src/Common/libzip/zip_file_get_offset.c @@ -1,6 +1,6 @@ /* zip_file_get_offset.c -- get offset of file data in archive. - 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> diff --git a/src/Common/libzip/zip_filerange_crc.c b/src/Common/libzip/zip_filerange_crc.c index f2a27fab..775af9ad 100644 --- a/src/Common/libzip/zip_filerange_crc.c +++ b/src/Common/libzip/zip_filerange_crc.c @@ -1,6 +1,6 @@ /* zip_filerange_crc.c -- compute CRC32 for a range of a file - Copyright (C) 2008-2015 Dieter Baron and Thomas Klausner + Copyright (C) 2008-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> diff --git a/src/Common/libzip/zip_fopen_index.c b/src/Common/libzip/zip_fopen_index.c index 7496f982..0fb150b2 100644 --- a/src/Common/libzip/zip_fopen_index.c +++ b/src/Common/libzip/zip_fopen_index.c @@ -1,6 +1,6 @@ /* zip_fopen_index.c -- open file in zip archive for reading by index - 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> diff --git a/src/Common/libzip/zip_fopen_index_encrypted.c b/src/Common/libzip/zip_fopen_index_encrypted.c index 92258e85..4c32e026 100644 --- a/src/Common/libzip/zip_fopen_index_encrypted.c +++ b/src/Common/libzip/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-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> diff --git a/src/Common/libzip/zip_get_compression_implementation.c b/src/Common/libzip/zip_get_compression_implementation.c index c1120d3e..5f8d0c7b 100644 --- a/src/Common/libzip/zip_get_compression_implementation.c +++ b/src/Common/libzip/zip_get_compression_implementation.c @@ -1,6 +1,6 @@ /* zip_get_compression_implementation.c -- get compression implementation - 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> @@ -36,7 +36,7 @@ zip_compression_implementation -_zip_get_compression_implementation(zip_int32_t cm) +_zip_get_compression_implementation(zip_int32_t cm, int operation) { if (cm == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(cm)) return zip_source_deflate; diff --git a/src/Common/libzip/zip_get_encryption_implementation.c b/src/Common/libzip/zip_get_encryption_implementation.c index e2f833b4..f8af7b02 100644 --- a/src/Common/libzip/zip_get_encryption_implementation.c +++ b/src/Common/libzip/zip_get_encryption_implementation.c @@ -1,6 +1,6 @@ /* zip_get_encryption_implementation.c -- get encryption implementation - 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> @@ -36,9 +36,21 @@ zip_encryption_implementation -_zip_get_encryption_implementation(zip_uint16_t em) +_zip_get_encryption_implementation(zip_uint16_t em, int operation) { - if (em == ZIP_EM_TRAD_PKWARE) + switch (em) { + case ZIP_EM_TRAD_PKWARE: + if (operation == ZIP_CODEC_ENCODE) { + return NULL; + } return zip_source_pkware; - return NULL; + + case ZIP_EM_AES_128: + case ZIP_EM_AES_192: + case ZIP_EM_AES_256: + return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode; + + default: + return NULL; + } } diff --git a/src/Common/libzip/zip_io_util.c b/src/Common/libzip/zip_io_util.c index b16927de..53a5dd26 100644 --- a/src/Common/libzip/zip_io_util.c +++ b/src/Common/libzip/zip_io_util.c @@ -1,6 +1,6 @@ /* zip_io_util.c -- I/O helper functions - 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> diff --git a/src/Common/libzip/zip_name_locate.c b/src/Common/libzip/zip_name_locate.c index 50ca40b1..706093f1 100644 --- a/src/Common/libzip/zip_name_locate.c +++ b/src/Common/libzip/zip_name_locate.c @@ -1,6 +1,6 @@ /* zip_name_locate.c -- get index by name - 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> diff --git a/src/Common/libzip/zip_new.c b/src/Common/libzip/zip_new.c index 562dd76a..c05c2a3c 100644 --- a/src/Common/libzip/zip_new.c +++ b/src/Common/libzip/zip_new.c @@ -1,6 +1,6 @@ /* zip_new.c -- create and init struct zip - 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> @@ -68,7 +68,7 @@ _zip_new(zip_error_t *error) za->entry = NULL; za->nopen_source = za->nopen_source_alloc = 0; za->open_source = NULL; - za->tempdir = NULL; + za->progress_callback = NULL; return za; } diff --git a/src/Common/libzip/zip_open.c b/src/Common/libzip/zip_open.c index d6209ee1..f62f95f6 100644 --- a/src/Common/libzip/zip_open.c +++ b/src/Common/libzip/zip_open.c @@ -1,6 +1,6 @@ /* zip_open.c -- open zip archive by name - 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 @@ -88,17 +88,17 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) { static zip_int64_t needed_support_read = -1; static zip_int64_t needed_support_write = -1; - + unsigned int flags; zip_int64_t supported; exists_t exists; - + if (_flags < 0 || src == NULL) { zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } flags = (unsigned int)_flags; - + supported = zip_source_supports(src); if (needed_support_read == -1) { needed_support_read = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_STAT, -1); @@ -118,7 +118,7 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) } exists = _zip_file_exists(src, error); - switch (exists) { + switch (exists) { case EXISTS_ERROR: return NULL; @@ -157,26 +157,13 @@ zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) } } -ZIP_EXTERN int -zip_archive_set_tempdir(zip_t *za, const char *tempdir) +ZIP_EXTERN void +zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback) { - char *new_tempdir; - - if (tempdir) { - if ((new_tempdir = strdup(tempdir)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, errno); - return -1; - } - } - else - new_tempdir = NULL; - - free(za->tempdir); - za->tempdir = new_tempdir; - - return 0; + za->progress_callback = progress_callback; } + zip_t * _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) { @@ -209,7 +196,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) if ((za=_zip_allocate_new(src, flags, error)) == NULL) { return NULL; } - + if ((cdir = _zip_find_central_dir(za, len)) == NULL) { _zip_error_copy(error, &za->error); /* keep src so discard does not get rid of it */ @@ -233,7 +220,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) 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); @@ -244,7 +231,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) } } } - + za->ch_flags = za->flags; return za; @@ -269,7 +256,7 @@ _zip_set_open_error(int *zep, const zip_error_t *err, int ze) /* _zip_readcdir: tries to find a valid end-of-central-directory at the beginning of buf, and then the corresponding central directory entries. - Returns a struct zip_cdir which contains the central directory + Returns a struct zip_cdir which contains the central directory entries, or NULL if unsuccessful. */ static zip_cdir_t * @@ -286,7 +273,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err zip_error_set(error, ZIP_ER_NOZIP, 0); return NULL; } - + /* check for end-of-central-dir magic */ if (memcmp(_zip_buffer_get(buffer, 4), EOCD_MAGIC, 4) != 0) { zip_error_set(error, ZIP_ER_NOZIP, 0); @@ -317,10 +304,10 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err if (comment_len || (za->open_flags & ZIP_CHECKCONS)) { zip_uint64_t tail_len; - + _zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN); tail_len = _zip_buffer_left(buffer); - + if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) { zip_error_set(error, ZIP_ER_INCONS, 0); _zip_cdir_free(cd); @@ -339,7 +326,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err zip_uint8_t *data; /* if buffer already read in, use it */ _zip_buffer_set_offset(buffer, cd->offset - buf_offset); - + if ((data = _zip_buffer_get(buffer, cd->size)) == NULL) { zip_error_set(error, ZIP_ER_INCONS, 0); _zip_cdir_free(cd); @@ -353,7 +340,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err } else { cd_buffer = NULL; - + if (zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) { _zip_error_set_from_source(error, za->src); _zip_cdir_free(cd); @@ -370,9 +357,30 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err left = (zip_uint64_t)cd->size; i=0; - while (i<cd->nentry && left > 0) { + while (left > 0) { + bool grown = false; zip_int64_t entry_size; + + if (i == cd->nentry) { + /* InfoZIP has a hack to avoid using Zip64: it stores nentries % 0x10000 */ + /* This hack isn't applicable if we're using Zip64, or if there is no central directory entry following. */ + + if (cd->is_zip64 || left < CDENTRYSIZE) { + break; + } + + if (!_zip_cdir_grow(cd, 0x10000, error)) { + _zip_cdir_free(cd); + _zip_buffer_free(cd_buffer); + return NULL; + } + grown = true; + } + if ((cd->entry[i].orig=_zip_dirent_new()) == NULL || (entry_size = _zip_dirent_read(cd->entry[i].orig, za->src, cd_buffer, false, error)) < 0) { + if (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) { + zip_error_set(error, ZIP_ER_INCONS, 0); + } _zip_cdir_free(cd); _zip_buffer_free(cd_buffer); return NULL; @@ -380,23 +388,23 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err i++; left -= (zip_uint64_t)entry_size; } - - if (i != cd->nentry) { + + if (i != cd->nentry || left > 0) { zip_error_set(error, ZIP_ER_INCONS, 0); _zip_buffer_free(cd_buffer); _zip_cdir_free(cd); return NULL; } - + if (za->open_flags & ZIP_CHECKCONS) { bool ok; - + if (cd_buffer) { ok = _zip_buffer_eof(cd_buffer); } else { zip_int64_t offset = zip_source_tell(za->src); - + if (offset < 0) { _zip_error_set_from_source(error, za->src); _zip_buffer_free(cd_buffer); @@ -405,7 +413,7 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err } ok = ((zip_uint64_t)offset == cd->offset + cd->size); } - + if (!ok) { zip_error_set(error, ZIP_ER_INCONS, 0); _zip_buffer_free(cd_buffer); @@ -447,7 +455,7 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } - + j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE; if (j > max) @@ -456,27 +464,27 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) zip_error_set(error, ZIP_ER_NOZIP, 0); return -1; } - + if (zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) { _zip_error_set_from_source(error, za->src); return -1; } - + if (_zip_dirent_read(&temp, za->src, NULL, true, error) == -1) { _zip_dirent_finalize(&temp); return -1; } - + if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) { zip_error_set(error, ZIP_ER_INCONS, 0); _zip_dirent_finalize(&temp); return -1; } - + cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields); cd->entry[i].orig->local_extra_fields_read = 1; temp.extra_fields = NULL; - + _zip_dirent_finalize(&temp); } @@ -491,7 +499,7 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) static int _zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) { - if ((central->version_needed != local->version_needed) + if ((central->version_needed < local->version_needed) #if 0 /* some zip-files have different values in local and global headers for the bitflags */ @@ -586,7 +594,7 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len) _zip_error_set_from_source(&za->error, za->src); return NULL; } - + if ((buffer = _zip_buffer_new_from_source(za->src, buflen, NULL, &za->error)) == NULL) { return NULL; } @@ -607,7 +615,7 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len) if (best <= 0) { best = _zip_checkcons(za, cdir, &error); } - + a = _zip_checkcons(za, cdirnew, &error); if (best < a) { _zip_cdir_free(cdir); @@ -628,13 +636,13 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len) } cdirnew = NULL; } - + match++; _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer))); } _zip_buffer_free(buffer); - + if (best < 0) { _zip_error_copy(&za->error, &error); _zip_cdir_free(cdir); @@ -649,7 +657,7 @@ static unsigned char * _zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen) { const unsigned char *p; - + if ((biglen < littlelen) || (littlelen == 0)) return NULL; p = big-1; @@ -673,7 +681,7 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags zip_error_set(error, ZIP_ER_INCONS, 0); return NULL; } - + eocd_offset = _zip_buffer_offset(buffer); _zip_buffer_get(buffer, 4); /* magic already verified */ @@ -700,7 +708,7 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags zip_error_set(error, ZIP_ER_SEEK, EFBIG); return NULL; } - + if (offset+size > buf_offset + eocd_offset) { /* cdir spans past EOCD record */ zip_error_set(error, ZIP_ER_INCONS, 0); @@ -715,9 +723,10 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags if ((cd=_zip_cdir_new(nentry, error)) == NULL) return NULL; + cd->is_zip64 = false; cd->size = size; cd->offset = offset; - + return cd; } @@ -734,13 +743,13 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse zip_uint32_t num_disks, num_disks64, eocd_disk, eocd_disk64; eocdloc_offset = _zip_buffer_offset(buffer); - + _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) { zip_error_set(error, ZIP_ER_SEEK, EFBIG); return NULL; @@ -773,7 +782,7 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse } return NULL; } - + size = _zip_buffer_get_64(buffer); if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) { @@ -820,7 +829,7 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse size = _zip_buffer_get_64(buffer); offset = _zip_buffer_get_64(buffer); - + if (!_zip_buffer_ok(buffer)) { zip_error_set(error, ZIP_ER_INTERNAL, 0); if (free_buffer) { @@ -845,7 +854,7 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse if ((cd=_zip_cdir_new(nentry, error)) == NULL) return NULL; - + cd->is_zip64 = true; cd->size = size; cd->offset = offset; diff --git a/src/Common/libzip/zip_set_default_password.c b/src/Common/libzip/zip_set_default_password.c index 10b48062..ff7e35a6 100644 --- a/src/Common/libzip/zip_set_default_password.c +++ b/src/Common/libzip/zip_set_default_password.c @@ -1,6 +1,6 @@ /* zip_set_default_password.c -- set default password for decryption - 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> diff --git a/src/Common/libzip/zip_set_name.c b/src/Common/libzip/zip_set_name.c index 2a461437..34b76154 100644 --- a/src/Common/libzip/zip_set_name.c +++ b/src/Common/libzip/zip_set_name.c @@ -1,6 +1,6 @@ /* zip_set_name.c -- rename helper function - 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> diff --git a/src/Common/libzip/zip_source_error.c b/src/Common/libzip/zip_source_error.c index e09199bb..91e2dd64 100644 --- a/src/Common/libzip/zip_source_error.c +++ b/src/Common/libzip/zip_source_error.c @@ -1,6 +1,6 @@ /* zip_source_error.c -- get last error from zip_source - 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> @@ -40,3 +40,9 @@ zip_source_error(zip_source_t *src) { return &src->error; } + +bool +_zip_source_had_error(zip_source_t *src) +{ + return zip_source_error(src)->zip_err != ZIP_ER_OK; +} diff --git a/src/Common/libzip/zip_source_file.c b/src/Common/libzip/zip_source_file.c index 8678c1a0..6a10c010 100644 --- a/src/Common/libzip/zip_source_file.c +++ b/src/Common/libzip/zip_source_file.c @@ -1,6 +1,6 @@ /* zip_source_file.c -- create data source from file - 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 @@ -46,7 +46,7 @@ zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t le { if (za == NULL) return NULL; - + return zip_source_file_create(fname, start, len, &za->error); } diff --git a/src/Common/libzip/zip_source_filep.c b/src/Common/libzip/zip_source_filep.c index 70255dec..a8a271a8 100644 --- a/src/Common/libzip/zip_source_filep.c +++ b/src/Common/libzip/zip_source_filep.c @@ -1,6 +1,6 @@ /* zip_source_filep.c -- create data source from FILE * - 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 @@ -72,10 +72,11 @@ struct read_file { char *fname; /* name of file to read from */ FILE *f; /* file to read from */ struct zip_stat st; /* stat information passed in */ + zip_error_t stat_error; /* error returned for stat */ zip_uint64_t start; /* start offset of data to read */ - zip_uint64_t end; /* end offset of data to read, 0 for up to EOF */ - zip_uint64_t current; /* current offset */ - + zip_uint64_t end; /* end offset of data to read relative to start, 0 for up to EOF */ + zip_uint64_t current; /* current offset relative to start (0 is beginning of part we read) */ + /* writing */ char *tmpname; FILE *fout; @@ -92,7 +93,7 @@ zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) { if (za == NULL) return NULL; - + return zip_source_filep_create(file, start, len, &za->error); } @@ -114,12 +115,21 @@ _zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int { struct read_file *ctx; zip_source_t *zs; - + if (file == NULL && fname == NULL) { zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } - + + if (len < 0) { + len = 0; + } + + if (start > ZIP_INT64_MAX || start + (zip_uint64_t)len < start) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + if ((ctx=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) { zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; @@ -135,7 +145,7 @@ _zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int } ctx->f = file; ctx->start = start; - ctx->end = (len < 0 ? 0 : start+(zip_uint64_t)len); + ctx->end = (zip_uint64_t)len; if (st) { memcpy(&ctx->st, st, sizeof(ctx->st)); ctx->st.name = NULL; @@ -144,18 +154,53 @@ _zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int else { zip_stat_init(&ctx->st); } - + + if (ctx->end > 0) { + ctx->st.size = ctx->end; + ctx->st.valid |= ZIP_STAT_SIZE; + } + + zip_error_init(&ctx->stat_error); + ctx->tmpname = NULL; ctx->fout = NULL; - + zip_error_init(&ctx->error); ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1); + if (ctx->fname) { struct stat sb; + if (stat(ctx->fname, &sb) < 0) { + zip_error_set(&ctx->stat_error, ZIP_ER_READ, errno); + if (ctx->start == 0 && ctx->end == 0) { + ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + } + } + else { + if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) { + ctx->st.mtime = sb.st_mtime; + ctx->st.valid |= ZIP_STAT_MTIME; + } + if (S_ISREG(sb.st_mode)) { + ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE; + + if (ctx->start + ctx->end > (zip_uint64_t)sb.st_size) { + zip_error_set(error, ZIP_ER_INVAL, 0); + free(ctx->fname); + free(ctx); + return NULL; + } - if (stat(ctx->fname, &sb) < 0 || S_ISREG(sb.st_mode)) { - ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + if (ctx->end == 0) { + ctx->st.size = (zip_uint64_t)sb.st_size - ctx->start; + ctx->st.valid |= ZIP_STAT_SIZE; + + if (start == 0) { + ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + } + } + } } } else if (fseeko(ctx->f, 0, SEEK_CUR) == 0) { @@ -179,7 +224,7 @@ create_temp_output(struct read_file *ctx) int tfd; mode_t mask; FILE *tfp; - + if ((temp=(char *)malloc(strlen(ctx->fname)+8)) == NULL) { zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); return -1; @@ -202,7 +247,7 @@ create_temp_output(struct read_file *ctx) free(temp); return -1; } - + #ifdef _WIN32 /* According to Pierre Joye, Windows in some environments per @@ -210,10 +255,10 @@ create_temp_output(struct read_file *ctx) */ _setmode(_fileno(tfp), _O_BINARY ); #endif - + ctx->fout = tfp; ctx->tmpname = temp; - + return 0; } @@ -236,7 +281,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) return -1; } return create_temp_output(ctx); - + case ZIP_SOURCE_COMMIT_WRITE: { mode_t mask; @@ -257,17 +302,17 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) ctx->tmpname = NULL; return 0; } - + case ZIP_SOURCE_CLOSE: if (ctx->fname) { fclose(ctx->f); ctx->f = NULL; } return 0; - + case ZIP_SOURCE_ERROR: return zip_error_to_data(&ctx->error, data, len); - + case ZIP_SOURCE_FREE: free(ctx->fname); free(ctx->tmpname); @@ -275,7 +320,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) fclose(ctx->f); free(ctx); return 0; - + case ZIP_SOURCE_OPEN: if (ctx->fname) { if ((ctx->f=fopen(ctx->fname, "rb")) == NULL) { @@ -283,18 +328,19 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) return -1; } } - + if (ctx->start > 0) { if (_zip_fseek_u(ctx->f, ctx->start, SEEK_SET, &ctx->error) < 0) { + /* TODO: skip by reading */ return -1; } } - ctx->current = ctx->start; + ctx->current = 0; return 0; - + case ZIP_SOURCE_READ: if (ctx->end > 0) { - n = ctx->end-ctx->current; + n = ctx->end - ctx->current; if (n > len) { n = len; } @@ -302,7 +348,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) else { n = len; } - + if (n > SIZE_MAX) n = SIZE_MAX; @@ -315,14 +361,14 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) ctx->current += i; return (zip_int64_t)i; - + case ZIP_SOURCE_REMOVE: if (remove(ctx->fname) < 0) { zip_error_set(&ctx->error, ZIP_ER_REMOVE, errno); return -1; } return 0; - + case ZIP_SOURCE_ROLLBACK_WRITE: if (ctx->fout) { fclose(ctx->fout); @@ -332,7 +378,7 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) free(ctx->tmpname); ctx->tmpname = NULL; return 0; - + case ZIP_SOURCE_SEEK: { zip_int64_t new_current; int need_seek; @@ -340,14 +386,14 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) if (args == NULL) return -1; - + need_seek = 1; - + switch (args->whence) { case SEEK_SET: new_current = args->offset; break; - + case SEEK_END: if (ctx->end == 0) { if (_zip_fseek(ctx->f, args->offset, SEEK_END, &ctx->error) < 0) { @@ -357,12 +403,14 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); return -1; } + new_current -= (zip_int64_t)ctx->start; need_seek = 0; } else { new_current = (zip_int64_t)ctx->end + args->offset; } break; + case SEEK_CUR: new_current = (zip_int64_t)ctx->current + args->offset; break; @@ -372,29 +420,30 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) return -1; } - if (new_current < 0 || (zip_uint64_t)new_current < ctx->start || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end)) { + if (new_current < 0 || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end) + || (zip_uint64_t)new_current + ctx->start < ctx->start) { zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); return -1; } - + ctx->current = (zip_uint64_t)new_current; if (need_seek) { - if (_zip_fseek_u(ctx->f, ctx->current, SEEK_SET, &ctx->error) < 0) { + if (_zip_fseek_u(ctx->f, ctx->current + ctx->start, SEEK_SET, &ctx->error) < 0) { return -1; } } return 0; } - + case ZIP_SOURCE_SEEK_WRITE: { zip_source_args_seek_t *args; - + args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); if (args == NULL) { return -1; } - + if (_zip_fseek(ctx->fout, args->offset, args->whence, &ctx->error) < 0) { return -1; } @@ -405,68 +454,43 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) if (len < sizeof(ctx->st)) return -1; - if (ctx->st.valid != 0) - memcpy(data, &ctx->st, sizeof(ctx->st)); - else { - zip_stat_t *st; - struct stat fst; - int err; - - if (ctx->f) - err = fstat(fileno(ctx->f), &fst); - else - err = stat(ctx->fname, &fst); - - if (err != 0) { - zip_error_set(&ctx->error, ZIP_ER_READ, errno); - return -1; - } - - st = (zip_stat_t *)data; - - zip_stat_init(st); - st->mtime = fst.st_mtime; - st->valid |= ZIP_STAT_MTIME; - if (ctx->end != 0) { - st->size = ctx->end - ctx->start; - st->valid |= ZIP_STAT_SIZE; - } - else if ((fst.st_mode&S_IFMT) == S_IFREG) { - st->size = (zip_uint64_t)fst.st_size; - st->valid |= ZIP_STAT_SIZE; - } + if (zip_error_code_zip(&ctx->stat_error) != 0) { + zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error)); + return -1; } + + memcpy(data, &ctx->st, sizeof(ctx->st)); return sizeof(ctx->st); } case ZIP_SOURCE_SUPPORTS: return ctx->supports; - + case ZIP_SOURCE_TELL: return (zip_int64_t)ctx->current; - + case ZIP_SOURCE_TELL_WRITE: { off_t ret = ftello(ctx->fout); - + if (ret < 0) { zip_error_set(&ctx->error, ZIP_ER_TELL, errno); return -1; } return ret; } - + case ZIP_SOURCE_WRITE: { size_t ret; - + clearerr(ctx->fout); ret = fwrite(data, 1, len, ctx->fout); if (ret != len || ferror(ctx->fout)) { zip_error_set(&ctx->error, ZIP_ER_WRITE, errno); return -1; } - + return (zip_int64_t)ret; } diff --git a/src/Common/libzip/zip_source_function.c b/src/Common/libzip/zip_source_function.c index 1d4be93c..06ce5c97 100644 --- a/src/Common/libzip/zip_source_function.c +++ b/src/Common/libzip/zip_source_function.c @@ -1,6 +1,6 @@ /* zip_source_function.c -- create zip data source from callback function - 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> @@ -94,6 +94,7 @@ _zip_source_new(zip_error_t *error) src->source_archive = NULL; src->refcount = 1; zip_error_init(&src->error); + src->eof = false; return src; } diff --git a/src/Common/libzip/zip_source_open.c b/src/Common/libzip/zip_source_open.c index ec5e39d5..a5712b27 100644 --- a/src/Common/libzip/zip_source_open.c +++ b/src/Common/libzip/zip_source_open.c @@ -1,6 +1,6 @@ /* zip_source_open.c -- open zip_source (prepare for reading) - 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> @@ -67,6 +67,8 @@ zip_source_open(zip_source_t *src) } } + src->eof = false; + _zip_error_clear(&src->error); src->open_count++; return 0; diff --git a/src/Common/libzip/zip_source_pkware.c b/src/Common/libzip/zip_source_pkware.c index 125e4e2c..3957d993 100644 --- a/src/Common/libzip/zip_source_pkware.c +++ b/src/Common/libzip/zip_source_pkware.c @@ -1,6 +1,6 @@ /* zip_source_pkware.c -- Traditional PKWARE de/encryption routines - Copyright (C) 2009-2015 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> diff --git a/src/Common/libzip/zip_source_read.c b/src/Common/libzip/zip_source_read.c index 061a6f91..267128ba 100644 --- a/src/Common/libzip/zip_source_read.c +++ b/src/Common/libzip/zip_source_read.c @@ -1,6 +1,6 @@ /* zip_source_read.c -- read data from zip_source - 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> @@ -38,6 +38,9 @@ zip_int64_t zip_source_read(zip_source_t *src, void *data, zip_uint64_t len) { + zip_uint64_t bytes_read; + zip_int64_t n; + if (src->source_closed) { return -1; } @@ -46,5 +49,39 @@ zip_source_read(zip_source_t *src, void *data, zip_uint64_t len) return -1; } - return _zip_source_call(src, data, len, ZIP_SOURCE_READ); + if (_zip_source_had_error(src)) { + return -1; + } + + if (_zip_source_eof(src)) { + return 0; + } + + bytes_read = 0; + while (bytes_read < len) { + if ((n = _zip_source_call(src, (zip_uint8_t *)data + bytes_read, len - bytes_read, ZIP_SOURCE_READ)) < 0) { + if (bytes_read == 0) { + return -1; + } + else { + return (zip_int64_t)bytes_read; + } + } + + if (n == 0) { + src->eof = 1; + break; + } + + bytes_read += (zip_uint64_t)n; + } + + return (zip_int64_t)bytes_read; +} + + +bool +_zip_source_eof(zip_source_t *src) +{ + return src->eof; } diff --git a/src/Common/libzip/zip_source_stat.c b/src/Common/libzip/zip_source_stat.c index a6b46d06..864507e1 100644 --- a/src/Common/libzip/zip_source_stat.c +++ b/src/Common/libzip/zip_source_stat.c @@ -1,6 +1,6 @@ /* zip_source_stat.c -- get meta information from zip_source - Copyright (C) 2009-2015 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> diff --git a/src/Common/libzip/zip_source_supports.c b/src/Common/libzip/zip_source_supports.c index 75a4a462..c59aa1f8 100644 --- a/src/Common/libzip/zip_source_supports.c +++ b/src/Common/libzip/zip_source_supports.c @@ -1,6 +1,6 @@ /* zip_source_supports.c -- check for supported functions - Copyright (C) 2014-2015 Dieter Baron and Thomas Klausner + Copyright (C) 2014-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> diff --git a/src/Common/libzip/zip_source_win32handle.c b/src/Common/libzip/zip_source_win32handle.c index 35e2e679..7fe003dc 100644 --- a/src/Common/libzip/zip_source_win32handle.c +++ b/src/Common/libzip/zip_source_win32handle.c @@ -344,9 +344,12 @@ _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd } else { h = ctx->ops->op_open(ctx); - if (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) { - zip_error_set(&ctx->error, ZIP_ER_READ, ENOENT); - return -1; + if (h == INVALID_HANDLE_VALUE) { + win32err = GetLastError(); + if (win32err == ERROR_FILE_NOT_FOUND || win32err == ERROR_PATH_NOT_FOUND) { + zip_error_set(&ctx->error, ZIP_ER_READ, ENOENT); + return -1; + } } } diff --git a/src/Common/libzip/zip_source_zip_new.c b/src/Common/libzip/zip_source_zip_new.c index 40f1195f..92562558 100644 --- a/src/Common/libzip/zip_source_zip_new.c +++ b/src/Common/libzip/zip_source_zip_new.c @@ -1,6 +1,6 @@ /* zip_source_zip_new.c -- prepare data structures for zip_fopen/zip_source_zip - Copyright (C) 2012-2015 Dieter Baron and Thomas Klausner + Copyright (C) 2012-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> @@ -81,11 +81,14 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl enc_impl = NULL; if (((flags & ZIP_FL_ENCRYPTED) == 0) && (st.encryption_method != ZIP_EM_NONE)) { + if (password == NULL) { + password = za->default_password; + } if (password == NULL) { zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0); return NULL; } - if ((enc_impl=_zip_get_encryption_implementation(st.encryption_method)) == NULL) { + if ((enc_impl=_zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) { zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); return NULL; } @@ -94,7 +97,7 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl comp_impl = NULL; if ((flags & ZIP_FL_COMPRESSED) == 0) { if (st.comp_method != ZIP_CM_STORE) { - if ((comp_impl=_zip_get_compression_implementation(st.comp_method)) == NULL) { + if ((comp_impl=_zip_get_compression_implementation(st.comp_method, ZIP_CODEC_DECODE)) == NULL) { zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); return NULL; } diff --git a/src/Common/libzip/zip_stat_index.c b/src/Common/libzip/zip_stat_index.c index 601e3f70..a2ef59bb 100644 --- a/src/Common/libzip/zip_stat_index.c +++ b/src/Common/libzip/zip_stat_index.c @@ -1,6 +1,6 @@ /* zip_stat_index.c -- get information about file by index - 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> @@ -64,17 +64,8 @@ zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, st->mtime = de->last_mod; st->comp_size = de->comp_size; st->comp_method = (zip_uint16_t)de->comp_method; - if (de->bitflags & ZIP_GPBF_ENCRYPTED) { - if (de->bitflags & ZIP_GPBF_STRONG_ENCRYPTION) { - /* TODO */ - st->encryption_method = ZIP_EM_UNKNOWN; - } - else - st->encryption_method = ZIP_EM_TRAD_PKWARE; - } - else - st->encryption_method = ZIP_EM_NONE; - st->valid = ZIP_STAT_CRC|ZIP_STAT_SIZE|ZIP_STAT_MTIME + st->encryption_method = de->encryption_method; + st->valid = (de->crc_valid ? ZIP_STAT_CRC : 0) | ZIP_STAT_SIZE|ZIP_STAT_MTIME |ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD; } diff --git a/src/Common/libzip/zip_unchange.c b/src/Common/libzip/zip_unchange.c index 5ef54621..4a3d6426 100644 --- a/src/Common/libzip/zip_unchange.c +++ b/src/Common/libzip/zip_unchange.c @@ -1,6 +1,6 @@ /* zip_unchange.c -- undo changes to file in zip archive - 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> diff --git a/src/Common/libzip/zip_unchange_all.c b/src/Common/libzip/zip_unchange_all.c index dc89f7fd..2221d6cb 100644 --- a/src/Common/libzip/zip_unchange_all.c +++ b/src/Common/libzip/zip_unchange_all.c @@ -1,6 +1,6 @@ /* zip_unchange.c -- undo changes to all files in zip archive - 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> diff --git a/src/Common/libzip/zipint.h b/src/Common/libzip/zipint.h index 6939d73f..2c5c6b9b 100644 --- a/src/Common/libzip/zipint.h +++ b/src/Common/libzip/zipint.h @@ -20,7 +20,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 @@ -64,16 +64,19 @@ #define CDBUFSIZE (MAXCOMLEN+EOCDLEN+EOCD64LOCLEN) #define BUFSIZE 8192 #define EFZIP64SIZE 28 +#define EF_WINZIP_AES_SIZE 7 #define ZIP_CM_REPLACED_DEFAULT (-2) +#define ZIP_CM_WINZIP_AES 99 /* Winzip AES encrypted */ #define ZIP_CM_IS_DEFAULT(x) ((x) == ZIP_CM_DEFAULT || (x) == ZIP_CM_REPLACED_DEFAULT) #define ZIP_EF_UTF_8_COMMENT 0x6375 #define ZIP_EF_UTF_8_NAME 0x7075 +#define ZIP_EF_WINZIP_AES 0x9901 #define ZIP_EF_ZIP64 0x0001 -#define ZIP_EF_IS_INTERNAL(id) ((id) == ZIP_EF_UTF_8_COMMENT || (id) == ZIP_EF_UTF_8_NAME || (id) == ZIP_EF_ZIP64) +#define ZIP_EF_IS_INTERNAL(id) ((id) == ZIP_EF_UTF_8_COMMENT || (id) == ZIP_EF_UTF_8_NAME || (id) == ZIP_EF_WINZIP_AES || (id) == ZIP_EF_ZIP64) /* according to unzip-6.0's zipinfo.c, this corresponds to a regular file with rw permissions for everyone */ #define ZIP_EXT_ATTRIB_DEFAULT (0100666u<<16) @@ -96,8 +99,8 @@ typedef zip_source_t *(*zip_compression_implementation)(zip_t *, zip_source_t *, zip_int32_t, int); typedef zip_source_t *(*zip_encryption_implementation)(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); -zip_compression_implementation _zip_get_compression_implementation(zip_int32_t); -zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t); +zip_compression_implementation _zip_get_compression_implementation(zip_int32_t method, int operation); +zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t method, int operation); @@ -118,6 +121,8 @@ zip_source_t *zip_source_pkware(zip_t *, zip_source_t *, zip_uint16_t, int, cons int zip_source_remove(zip_source_t *); zip_int64_t zip_source_supports(zip_source_t *src); zip_source_t *zip_source_window(zip_t *, zip_source_t *, zip_uint64_t, zip_uint64_t); +zip_source_t *zip_source_winzip_aes_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); +zip_source_t *zip_source_winzip_aes_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); /* error source for layered sources */ @@ -193,8 +198,8 @@ struct zip { 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) */ + + zip_progress_callback_t progress_callback; /* progress callback for zip_close() */ }; /* file in zip archive, part of API */ @@ -208,18 +213,22 @@ struct zip_file { /* zip archive directory entry (central or local) */ -#define ZIP_DIRENT_COMP_METHOD 0x0001u -#define ZIP_DIRENT_FILENAME 0x0002u -#define ZIP_DIRENT_COMMENT 0x0004u -#define ZIP_DIRENT_EXTRA_FIELD 0x0008u -#define ZIP_DIRENT_ATTRIBUTES 0x0010u -#define ZIP_DIRENT_LAST_MOD 0x0020u -#define ZIP_DIRENT_ALL 0xffffu +#define ZIP_DIRENT_COMP_METHOD 0x0001u +#define ZIP_DIRENT_FILENAME 0x0002u +#define ZIP_DIRENT_COMMENT 0x0004u +#define ZIP_DIRENT_EXTRA_FIELD 0x0008u +#define ZIP_DIRENT_ATTRIBUTES 0x0010u +#define ZIP_DIRENT_LAST_MOD 0x0020u +#define ZIP_DIRENT_ENCRYPTION_METHOD 0x0040u +#define ZIP_DIRENT_PASSWORD 0x0080u +#define ZIP_DIRENT_ALL ZIP_UINT32_MAX 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 */ + + bool crc_valid; /* if CRC is valid (sometimes not for encrypted archives) */ zip_uint16_t version_madeby; /* (c) version of creator */ zip_uint16_t version_needed; /* (cl) version needed to extract */ @@ -236,6 +245,9 @@ struct zip_dirent { zip_uint16_t int_attrib; /* (c) internal file attributes */ zip_uint32_t ext_attrib; /* (c) external file attributes */ zip_uint64_t offset; /* (c) offset of local header */ + + zip_uint16_t encryption_method; /* encryption method, computed from other fields */ + char *password; /* file specific encryption password */ }; /* zip archive central directory */ @@ -248,6 +260,7 @@ struct zip_cdir { zip_uint64_t size; /* size of central directory */ zip_uint64_t offset; /* offset of central directory in file */ zip_string_t *comment; /* zip archive comment */ + bool is_zip64; /* central directory in zip64 format */ }; struct zip_extra_field { @@ -280,6 +293,7 @@ struct zip_source { bool source_closed; /* set if source archive is closed */ zip_t *source_archive; /* zip archive we're reading from, NULL if not from archive */ unsigned int refcount; + bool eof; /* EOF reached */ }; #define ZIP_SOURCE_IS_OPEN_READING(src) ((src)->open_count > 0) @@ -312,7 +326,7 @@ struct zip_string { struct zip_buffer { bool ok; bool free_data; - + zip_uint8_t *data; zip_uint64_t size; zip_uint64_t offset; @@ -332,6 +346,8 @@ extern const char * const _zip_err_str[]; extern const int _zip_nerr_str; extern const int _zip_err_type[]; +#define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b)) #define ZIP_ENTRY_CHANGED(e, f) ((e)->changes && ((e)->changes->changed & (f))) @@ -340,6 +356,17 @@ extern const int _zip_err_type[]; #define ZIP_IS_RDONLY(za) ((za)->ch_flags & ZIP_AFL_RDONLY) +#ifdef HAVE_EXPLICIT_MEMSET +#define _zip_crypto_clear(b, l) explicit_memset((b), 0, (l)) +#else +#ifdef HAVE_EXPLICIT_BZERO +#define _zip_crypto_clear(b, l) explicit_bzero((b), (l)) +#else +#define _zip_crypto_clear(b, l) memset((b), 0, (l)) +#endif +#endif + + zip_int64_t _zip_add_entry(zip_t *); zip_uint8_t *_zip_buffer_data(zip_buffer_t *buffer); @@ -355,17 +382,20 @@ zip_buffer_t *_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size); zip_buffer_t *_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error); zip_uint64_t _zip_buffer_offset(zip_buffer_t *buffer); bool _zip_buffer_ok(zip_buffer_t *buffer); +zip_uint8_t *_zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length); int _zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length); 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); +zip_uint64_t _zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length); 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); int _zip_cdir_compute_crc(zip_t *, uLong *); void _zip_cdir_free(zip_cdir_t *); +bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error); zip_cdir_t *_zip_cdir_new(zip_uint64_t, zip_error_t *); zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors); void _zip_deregister_source(zip_t *za, zip_source_t *src); @@ -422,6 +452,8 @@ void _zip_hash_revert(zip_hash_t *hash); zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *); +bool zip_random(zip_uint8_t *buffer, zip_uint16_t length); + int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_error_t *error); int _zip_read_at_offset(zip_source_t *src, zip_uint64_t offset, unsigned char *b, size_t length, zip_error_t *error); zip_uint8_t *_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error); @@ -432,8 +464,10 @@ int _zip_register_source(zip_t *za, zip_source_t *src); void _zip_set_open_error(int *zep, const zip_error_t *err, int ze); zip_int64_t _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command); +bool _zip_source_eof(zip_source_t *); zip_source_t *_zip_source_file_or_p(const char *, FILE *, zip_uint64_t, zip_int64_t, const zip_stat_t *, zip_error_t *error); void _zip_source_invalidate(zip_source_t *src); +bool _zip_source_had_error(zip_source_t *); zip_source_t *_zip_source_new(zip_error_t *error); int _zip_source_set_source_archive(zip_source_t *, zip_t *); zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_error_t *error); |