Mercurial > embed
changeset 56:056ee6b5913e
libzip: update to 1.3.0, closes #654
line wrap: on
line diff
--- a/VERSION.libzip.txt Fri Sep 22 14:07:40 2017 +0200 +++ b/VERSION.libzip.txt Tue Oct 10 20:43:12 2017 +0200 @@ -1,1 +1,1 @@ -1.1.3 +1.3.0
--- a/libzip/CMakeLists.txt Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/CMakeLists.txt Tue Oct 10 20:43:12 2017 +0200 @@ -1,3 +1,10 @@ +# TODO: +# 1. pkgconfig file not yet built. +# 2. installation not tested. +# 3. Problems generating html pages. +# 4. create usable libtool .la file +# 5. runtest not created + CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(libzip C) @@ -9,18 +16,21 @@ INCLUDE(CheckCSourceRuns) INCLUDE(CheckCSourceCompiles) INCLUDE(CheckStructHasMember) +INCLUDE(TestBigEndian) SET(PACKAGE "libzip") SET(PACKAGE_NAME ${PACKAGE}) SET(PACKAGE_VERSION_MAJOR "1") -SET(PACKAGE_VERSION_MINOR "1") -SET(PACKAGE_VERSION_PATCH "3") +SET(PACKAGE_VERSION_MINOR "3") +SET(PACKAGE_VERSION_PATCH "0") +#SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}") SET(VERSION "${PACKAGE_VERSION_MAJOR}.${PACKAGE_VERSION_MINOR}.${PACKAGE_VERSION_PATCH}") SET(PACKAGE_VERSION ${VERSION}) SET(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") # Checks +CHECK_FUNCTION_EXISTS(_chmod HAVE__CHMOD) CHECK_FUNCTION_EXISTS(_close HAVE__CLOSE) CHECK_FUNCTION_EXISTS(_dup HAVE__DUP) CHECK_FUNCTION_EXISTS(_fdopen HAVE__FDOPEN) @@ -30,6 +40,12 @@ CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF) CHECK_FUNCTION_EXISTS(_strdup HAVE__STRDUP) CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP) +CHECK_FUNCTION_EXISTS(_strtoi64 HAVE__STRTOI64) +CHECK_FUNCTION_EXISTS(_strtoui64 HAVE__STRTOUI64) +CHECK_FUNCTION_EXISTS(_umask HAVE__UMASK) +CHECK_FUNCTION_EXISTS(_unlink HAVE__UNLINK) +CHECK_FUNCTION_EXISTS(explict_bzero HAVE_EXPLICIT_BZERO) +CHECK_FUNCTION_EXISTS(explicit_memset HAVE_EXPLICIT_MEMSET) CHECK_FUNCTION_EXISTS(fileno HAVE_FILENO) CHECK_FUNCTION_EXISTS(fseeko HAVE_FSEEKO) CHECK_FUNCTION_EXISTS(ftello HAVE_FTELLO) @@ -41,6 +57,8 @@ CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP) CHECK_FUNCTION_EXISTS(strdup HAVE_STRDUP) CHECK_FUNCTION_EXISTS(stricmp HAVE_STRICMP) +CHECK_FUNCTION_EXISTS(strtoll HAVE_STRTOLL) +CHECK_FUNCTION_EXISTS(strtoull HAVE_STRTOULL) CHECK_INCLUDE_FILES(fts.h HAVE_FTS_H) CHECK_INCLUDE_FILES(stdbool.h HAVE_STDBOOL_H) @@ -51,6 +69,10 @@ CHECK_INCLUDE_FILES(stdint.h HAVE_STDINT_H_LIBZIP) CHECK_INCLUDE_FILES(sys/types.h HAVE_SYS_TYPES_H_LIBZIP) +# TODO: fix test +# this test does not find __progname even when it exists +#CHECK_SYMBOL_EXISTS(__progname stdlib.h HAVE___PROGNAME) + CHECK_TYPE_SIZE(__int8 __INT8_LIBZIP) CHECK_TYPE_SIZE(int8_t INT8_T_LIBZIP) CHECK_TYPE_SIZE(uint8_t UINT8_T_LIBZIP) @@ -71,6 +93,8 @@ CHECK_TYPE_SIZE("size_t" SIZE_T_LIBZIP) CHECK_TYPE_SIZE("ssize_t" SSIZE_T_LIBZIP) +TEST_BIG_ENDIAN(WORDS_BIGENDIAN) + FIND_PACKAGE(ZLIB REQUIRED) INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) set(CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIR}) @@ -78,15 +102,20 @@ MESSAGE(FATAL_ERROR "-- ZLIB version too old, please install at least v1.1.2") ENDIF(ZLIB_VERSION_STRING VERSION_LESS "1.1.2") +FIND_PACKAGE(BZip2) +IF(BZIP2_FOUND) + SET (HAVE_LIBBZ2 1) + + INCLUDE_DIRECTORIES(${BZIP2_INCLUDE_DIR}) + SET (OPTIONAL_LIBRARY ${BZIP2_LIBRARY}) +ENDIF(BZIP2_FOUND) + IF(MSVC) - ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS") +ADD_DEFINITIONS("-D_CRT_SECURE_NO_WARNINGS") +ADD_DEFINITIONS("-D_CRT_NONSTDC_NO_DEPRECATE") ENDIF(MSVC) +ADD_DEFINITIONS("-DHAVE_CONFIG_H") + # Targets ADD_SUBDIRECTORY(lib) - -# write out config file -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake-config.h.in - ${CMAKE_CURRENT_BINARY_DIR}/config.h) -CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/cmake-zipconf.h.in - ${CMAKE_CURRENT_BINARY_DIR}/zipconf.h)
--- a/libzip/cmake-config.h.in Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/cmake-config.h.in Tue Oct 10 20:43:12 2017 +0200 @@ -5,6 +5,7 @@ #endif /* BEGIN DEFINES */ #cmakedefine HAVE___PROGNAME +#cmakedefine HAVE__CHMOD #cmakedefine HAVE__CLOSE #cmakedefine HAVE__DUP #cmakedefine HAVE__FDOPEN @@ -14,10 +15,15 @@ #cmakedefine HAVE__SNPRINTF #cmakedefine HAVE__STRDUP #cmakedefine HAVE__STRICMP +#cmakedefine HAVE__STRTOI64 +#cmakedefine HAVE__STRTOUI64 +#cmakedefine HAVE__UMASK +#cmakedefine HAVE__UNLINK #cmakedefine HAVE_FILENO #cmakedefine HAVE_FSEEKO #cmakedefine HAVE_FTELLO #cmakedefine HAVE_GETPROGNAME +#cmakedefine HAVE_LIBBZ2 #cmakedefine HAVE_OPEN #cmakedefine HAVE_MKSTEMP #cmakedefine HAVE_SETMODE @@ -26,6 +32,8 @@ #cmakedefine HAVE_STRCASECMP #cmakedefine HAVE_STRDUP #cmakedefine HAVE_STRICMP +#cmakedefine HAVE_STRTOLL +#cmakedefine HAVE_STRTOULL #cmakedefine HAVE_STRUCT_TM_TM_ZONE #cmakedefine HAVE_STDBOOL_H #cmakedefine HAVE_STRINGS_H @@ -49,6 +57,7 @@ #cmakedefine HAVE_NDIR_H #cmakedefine HAVE_SYS_DIR_H #cmakedefine HAVE_SYS_NDIR_H +#cmakedefine WORDS_BIGENDIAN /* END DEFINES */ #define PACKAGE "@PACKAGE@" #define VERSION "@VERSION@"
--- a/libzip/lib/CMakeLists.txt Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/CMakeLists.txt Tue Oct 10 20:43:12 2017 +0200 @@ -1,9 +1,64 @@ INCLUDE(CheckFunctionExists) +INSTALL(FILES zip.h DESTINATION include) + +# from http://www.cmake.org/Wiki/CMakeMacroLibtoolFile +MACRO(GET_TARGET_PROPERTY_WITH_DEFAULT _variable _target _property _default_value) + + GET_TARGET_PROPERTY (${_variable} ${_target} ${_property}) + IF (${_variable} STREQUAL NOTFOUND) + SET (${_variable} ${_default_value}) + ENDIF (${_variable} STREQUAL NOTFOUND) + +ENDMACRO (GET_TARGET_PROPERTY_WITH_DEFAULT) + +MACRO(CREATE_LIBTOOL_FILE _target _install_DIR) + GET_TARGET_PROPERTY(_target_location ${_target} LOCATION) + GET_TARGET_PROPERTY_WITH_DEFAULT(_target_static_lib ${_target} STATIC_LIB "") + GET_TARGET_PROPERTY_WITH_DEFAULT(_target_dependency_libs ${_target} LT_DEPENDENCY_LIBS "") + GET_TARGET_PROPERTY_WITH_DEFAULT(_target_current ${_target} LT_VERSION_CURRENT 4) + GET_TARGET_PROPERTY_WITH_DEFAULT(_target_revision ${_target} LT_VERSION_REVISION 0) + GET_TARGET_PROPERTY_WITH_DEFAULT(_target_age ${_target} LT_VERSION_AGE 0) + GET_TARGET_PROPERTY_WITH_DEFAULT(_target_installed ${_target} LT_INSTALLED yes) + GET_TARGET_PROPERTY_WITH_DEFAULT(_target_shouldnotlink ${_target} LT_SHOULDNOTLINK yes) + GET_TARGET_PROPERTY_WITH_DEFAULT(_target_dlopen ${_target} LT_DLOPEN "") + GET_TARGET_PROPERTY_WITH_DEFAULT(_target_dlpreopen ${_target} LT_DLPREOPEN "") + GET_FILENAME_COMPONENT(_laname ${_target_location} NAME_WE) + GET_FILENAME_COMPONENT(_soname ${_target_location} NAME) + SET(_laname ${_laname}.la) + FILE(WRITE ${_laname} "# ${_laname} - a libtool library file, generated by cmake \n") + FILE(APPEND ${_laname} "# The name that we can dlopen(3).\n") + FILE(APPEND ${_laname} "dlname='${_soname}'\n") + FILE(APPEND ${_laname} "# Names of this library\n") + FILE(APPEND ${_laname} "library_names='${_soname}.${_target_current}.${_target_age}.${_target_revision} ${_soname}.${_target_current} ${_soname}'\n") + FILE(APPEND ${_laname} "# The name of the static archive\n") + FILE(APPEND ${_laname} "old_library='${_target_static_lib}'\n") + FILE(APPEND ${_laname} "# Libraries that this one depends upon.\n") + FILE(APPEND ${_laname} "dependency_libs='${_target_dependency_libs}'\n") + FILE(APPEND ${_laname} "# Version information.\n") + FILE(APPEND ${_laname} "current=${_target_current}\n") + FILE(APPEND ${_laname} "age=${_target_age}\n") + FILE(APPEND ${_laname} "revision=${_target_revision}\n") + FILE(APPEND ${_laname} "# Is this an already installed library?\n") + FILE(APPEND ${_laname} "installed=${_target_installed}\n") + FILE(APPEND ${_laname} "# Should we warn about portability when linking against -modules?\n") + FILE(APPEND ${_laname} "shouldnotlink=${_target_shouldnotlink}\n") + FILE(APPEND ${_laname} "# Files to dlopen/dlpreopen\n") + FILE(APPEND ${_laname} "dlopen='${_target_dlopen}'\n") + FILE(APPEND ${_laname} "dlpreopen='${_target_dlpreopen}'\n") + FILE(APPEND ${_laname} "# Directory that this library needs to be installed in:\n") + FILE(APPEND ${_laname} "libdir='${CMAKE_INSTALL_PREFIX}/${_install_DIR}'\n") + INSTALL( FILES ${_laname} ${_soname} + DESTINATION ${CMAKE_INSTALL_PREFIX}${_install_DIR}) +ENDMACRO(CREATE_LIBTOOL_FILE) + SET(LIBZIP_SOURCES + gladman-fcrypt.c zip_add.c zip_add_dir.c zip_add_entry.c + zip_algorithm_bzip2.c + zip_algorithm_deflate.c zip_buffer.c zip_close.c zip_delete.c @@ -31,6 +86,7 @@ zip_file_rename.c zip_file_replace.c zip_file_set_comment.c + zip_file_set_encryption.c zip_file_set_external_attributes.c zip_file_set_mtime.c zip_file_strerror.c @@ -40,9 +96,10 @@ zip_fopen_index.c zip_fopen_index_encrypted.c zip_fread.c + zip_fseek.c + zip_ftell.c zip_get_archive_comment.c zip_get_archive_flag.c - zip_get_compression_implementation.c zip_get_encryption_implementation.c zip_get_file_comment.c zip_get_name.c @@ -54,6 +111,7 @@ zip_name_locate.c zip_new.c zip_open.c + zip_progress.c zip_rename.c zip_replace.c zip_set_archive_comment.c @@ -67,12 +125,13 @@ zip_source_call.c zip_source_close.c zip_source_commit_write.c + zip_source_compress.c zip_source_crc.c - zip_source_deflate.c zip_source_error.c zip_source_filep.c zip_source_free.c zip_source_function.c + zip_source_get_compression_flags.c zip_source_is_deleted.c zip_source_layered.c zip_source_open.c @@ -87,6 +146,8 @@ zip_source_tell.c zip_source_tell_write.c zip_source_window.c + zip_source_winzip_aes_decode.c + zip_source_winzip_aes_encode.c zip_source_write.c zip_source_zip.c zip_source_zip_new.c @@ -104,6 +165,7 @@ IF(WIN32) SET(LIBZIP_OPSYS_FILES + zip_random_win32.c zip_source_win32a.c zip_source_win32handle.c zip_source_win32utf8.c @@ -111,19 +173,33 @@ ) ELSE(WIN32) SET(LIBZIP_OPSYS_FILES + zip_random_unix.c zip_source_file.c ) ENDIF(WIN32) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/gladman-fcrypt + ${CMAKE_CURRENT_BINARY_DIR}/..) + +# TODO: distribute instead? +#ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c +# COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/make_zip_err_str.sh +# ${CMAKE_CURRENT_SOURCE_DIR}/zip.h +# ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c +# DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/zip.h +# ${CMAKE_CURRENT_SOURCE_DIR}/make_zip_err_str.sh +#) CHECK_FUNCTION_EXISTS(mkstemp HAVE_MKSTEMP) IF(NOT HAVE_MKSTEMP) SET(LIBZIP_EXTRA_FILES mkstemp.c) ENDIF(NOT HAVE_MKSTEMP) -ADD_LIBRARY(zip STATIC ${LIBZIP_SOURCES} ${LIBZIP_EXTRA_FILES} ${LIBZIP_OPSYS_FILES}) -TARGET_LINK_LIBRARIES(zip ${ZLIB_LIBRARY}) -TARGET_COMPILE_DEFINITIONS(zip PUBLIC ZIP_STATIC HAVE_CONFIG_H) -TARGET_INCLUDE_DIRECTORIES( - zip - PUBLIC ${libzip_SOURCE_DIR}/lib ${libzip_BINARY_DIR} -) +ADD_LIBRARY(zip ${LIBZIP_SOURCES} ${LIBZIP_EXTRA_FILES} ${LIBZIP_OPSYS_FILES}) +SET_TARGET_PROPERTIES(zip PROPERTIES VERSION 3.0 SOVERSION 3 ) +TARGET_LINK_LIBRARIES(zip ${ZLIB_LIBRARY} ${OPTIONAL_LIBRARY}) +INSTALL(TARGETS zip + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib) +#CREATE_LIBTOOL_FILE(zip lib)
--- a/libzip/lib/compat.h Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/compat.h Tue Oct 10 20:43:12 2017 +0200 @@ -72,6 +72,9 @@ #endif #ifdef _WIN32 +#if defined(HAVE__CHMOD) +#define chmod _chmod +#endif #if defined(HAVE__CLOSE) #define close _close #endif @@ -101,6 +104,18 @@ #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 +#if defined(HAVE__UMASK) +#define umask _umask +#endif +#if defined(HAVE__UNLINK) +#define unlink _unlink +#endif #endif #ifndef HAVE_FSEEKO
--- a/libzip/lib/mkstemp.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/mkstemp.c Tue Oct 10 20:43:12 2017 +0200 @@ -39,7 +39,10 @@ #include <errno.h> #include <fcntl.h> #ifdef _WIN32 +#include <process.h> #include <io.h> +#else +#include <unistd.h> #endif #include <stdio.h> #include <stdlib.h>
--- a/libzip/lib/zip.h Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip.h Tue Oct 10 20:43:12 2017 +0200 @@ -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 @@ -102,37 +102,38 @@ /* libzip error codes */ -#define ZIP_ER_OK 0 /* N No error */ -#define ZIP_ER_MULTIDISK 1 /* N Multi-disk zip archives not supported */ -#define ZIP_ER_RENAME 2 /* S Renaming temporary file failed */ -#define ZIP_ER_CLOSE 3 /* S Closing zip archive failed */ -#define ZIP_ER_SEEK 4 /* S Seek error */ -#define ZIP_ER_READ 5 /* S Read error */ -#define ZIP_ER_WRITE 6 /* S Write error */ -#define ZIP_ER_CRC 7 /* N CRC error */ -#define ZIP_ER_ZIPCLOSED 8 /* N Containing zip archive was closed */ -#define ZIP_ER_NOENT 9 /* N No such file */ -#define ZIP_ER_EXISTS 10 /* N File already exists */ -#define ZIP_ER_OPEN 11 /* S Can't open file */ -#define ZIP_ER_TMPOPEN 12 /* S Failure to create temporary file */ -#define ZIP_ER_ZLIB 13 /* Z Zlib error */ -#define ZIP_ER_MEMORY 14 /* N Malloc failure */ -#define ZIP_ER_CHANGED 15 /* N Entry has been changed */ -#define ZIP_ER_COMPNOTSUPP 16 /* N Compression method not supported */ -#define ZIP_ER_EOF 17 /* N Premature end of file */ -#define ZIP_ER_INVAL 18 /* N Invalid argument */ -#define ZIP_ER_NOZIP 19 /* N Not a zip archive */ -#define ZIP_ER_INTERNAL 20 /* N Internal error */ -#define ZIP_ER_INCONS 21 /* N Zip archive inconsistent */ -#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_NOPASSWD 26 /* N No password provided */ -#define ZIP_ER_WRONGPASSWD 27 /* N Wrong password provided */ -#define ZIP_ER_OPNOTSUPP 28 /* N Operation not supported */ -#define ZIP_ER_INUSE 29 /* N Resource still in use */ -#define ZIP_ER_TELL 30 /* S Tell error */ +#define ZIP_ER_OK 0 /* N No error */ +#define ZIP_ER_MULTIDISK 1 /* N Multi-disk zip archives not supported */ +#define ZIP_ER_RENAME 2 /* S Renaming temporary file failed */ +#define ZIP_ER_CLOSE 3 /* S Closing zip archive failed */ +#define ZIP_ER_SEEK 4 /* S Seek error */ +#define ZIP_ER_READ 5 /* S Read error */ +#define ZIP_ER_WRITE 6 /* S Write error */ +#define ZIP_ER_CRC 7 /* N CRC error */ +#define ZIP_ER_ZIPCLOSED 8 /* N Containing zip archive was closed */ +#define ZIP_ER_NOENT 9 /* N No such file */ +#define ZIP_ER_EXISTS 10 /* N File already exists */ +#define ZIP_ER_OPEN 11 /* S Can't open file */ +#define ZIP_ER_TMPOPEN 12 /* S Failure to create temporary file */ +#define ZIP_ER_ZLIB 13 /* Z Zlib error */ +#define ZIP_ER_MEMORY 14 /* N Malloc failure */ +#define ZIP_ER_CHANGED 15 /* N Entry has been changed */ +#define ZIP_ER_COMPNOTSUPP 16 /* N Compression method not supported */ +#define ZIP_ER_EOF 17 /* N Premature end of file */ +#define ZIP_ER_INVAL 18 /* N Invalid argument */ +#define ZIP_ER_NOZIP 19 /* N Not a zip archive */ +#define ZIP_ER_INTERNAL 20 /* N Internal error */ +#define ZIP_ER_INCONS 21 /* N Zip archive inconsistent */ +#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_NOPASSWD 26 /* N No password provided */ +#define ZIP_ER_WRONGPASSWD 27 /* N Wrong password provided */ +#define ZIP_ER_OPNOTSUPP 28 /* N Operation not supported */ +#define ZIP_ER_INUSE 29 /* N Resource still in use */ +#define ZIP_ER_TELL 30 /* S Tell error */ +#define ZIP_ER_COMPRESSED_DATA 31 /* N Compressed data invalid */ /* type of system error value */ @@ -161,6 +162,8 @@ /* 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 +176,15 @@ #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 @@ -221,11 +227,12 @@ ZIP_SOURCE_SEEK_WRITE, /* set position for writing */ ZIP_SOURCE_TELL_WRITE, /* get write position */ ZIP_SOURCE_SUPPORTS, /* check whether source supports command */ - ZIP_SOURCE_REMOVE /* remove file */ + ZIP_SOURCE_REMOVE, /* remove file */ + ZIP_SOURCE_GET_COMPRESSION_FLAGS /* get compression flags, internal only */ }; typedef enum zip_source_cmd zip_source_cmd_t; -#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (1<<(cmd)) +#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_uint64_t)1)<<(cmd)) #define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \ | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_READ) \ @@ -299,12 +306,15 @@ 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)(zip_t *, double, void *); #ifndef ZIP_DISABLE_DEPRECATED +typedef void (*zip_progress_callback_t)(double); +ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t); + ZIP_EXTERN zip_int64_t zip_add(zip_t *, const char *, zip_source_t *); /* use zip_file_add */ ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *, const char *); /* use zip_dir_add */ ZIP_EXTERN const char *zip_get_file_comment(zip_t *, zip_uint64_t, int *, int); /* use zip_file_get_comment */ @@ -318,7 +328,6 @@ 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 +362,7 @@ 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 +371,8 @@ 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 +380,7 @@ 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 int zip_register_progress_callback_with_state(zip_t *, double, zip_progress_callback, void (*)(void *), void *); 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 +390,7 @@ 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);
--- a/libzip/lib/zip_add_entry.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_add_entry.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_buffer.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_buffer.c Tue Oct 10 20:43:12 2017 +0200 @@ -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 @@ if (buffer == NULL) { return; } - + if (buffer->free_data) { free(buffer->data); } - + free(buffer); } @@ -69,14 +69,13 @@ _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_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_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_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_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_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 @@ } 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_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_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 @@ _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 @@ _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 @@ _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 @@ 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 @@ _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 @@ buffer->ok = false; return -1; } - + buffer->ok = true; buffer->offset = offset; - + return 0; } @@ -306,7 +333,7 @@ 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;
--- a/libzip/lib/zip_close.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_close.c Tue Oct 10 20:43:12 2017 +0200 @@ -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> @@ -51,15 +51,11 @@ #endif -/* max deflate size increase: size + ceil(size/16k)*5+6 */ -#define MAX_DEFLATE_SIZE_32 4293656963u - static int add_data(zip_t *, zip_source_t *, zip_dirent_t *); static int copy_data(zip_t *, zip_uint64_t); -static int copy_source(zip_t *, zip_source_t *); +static int copy_source(zip_t *, zip_source_t *, zip_int64_t); static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t); - ZIP_EXTERN int zip_close(zip_t *za) { @@ -124,17 +120,20 @@ free(filelist); return -1; } - + + _zip_progress_start(za->progress); error = 0; for (j=0; j<survivors; j++) { int new_data; zip_entry_t *entry; zip_dirent_t *de; + _zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j+1) / (double)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 +221,8 @@ return -1; } + _zip_progress_end(za->progress); + zip_discard(za); return 0; @@ -231,13 +232,15 @@ static int add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) { - zip_int64_t offstart, offdata, offend; + zip_int64_t offstart, offdata, offend, data_length; struct zip_stat st; - zip_source_t *s2; + zip_source_t *src_final, *src_tmp; int ret; int is_zip64; zip_flags_t flags; - + zip_int8_t compression_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); return -1; @@ -259,95 +262,176 @@ 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; - if ((st.valid & ZIP_STAT_SIZE) == 0) + if ((st.valid & ZIP_STAT_SIZE) == 0) { flags |= ZIP_FL_FORCE_ZIP64; + data_length = -1; + } else { de->uncomp_size = st.size; + /* this is technically incorrect (copy_source counts compressed data), but it's the best we have */ + data_length = (zip_int64_t)st.size; if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) { - if (( ((de->comp_method == ZIP_CM_DEFLATE || ZIP_CM_IS_DEFAULT(de->comp_method)) && st.size > MAX_DEFLATE_SIZE_32) - || (de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(de->comp_method)))) + zip_uint64_t max_size; + + switch (ZIP_CM_ACTUAL(de->comp_method)) { + case ZIP_CM_BZIP2: + /* computed by looking at increase of 10 random files of size 1MB when + * compressed with bzip2, rounded up: 1.006 */ + max_size = 4269351188u; + break; + + case ZIP_CM_DEFLATE: + /* max deflate size increase: size + ceil(size/16k)*5+6 */ + max_size = 4293656963u; + break; + + case ZIP_CM_STORE: + max_size = 0xffffffffu; + break; + + default: + max_size = 0; + } + + if (st.size > max_size) { flags |= ZIP_FL_FORCE_ZIP64; + } } else de->comp_size = st.comp_size; } if ((offstart = zip_source_tell_write(za->src)) < 0) { + _zip_error_set_from_source(&za->error, za->src); return -1; } /* as long as we don't support non-seekable output, clear data descriptor bit */ de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; - if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0) + if ((is_zip64=_zip_dirent_write(za, de, flags)) < 0) { return -1; + } + needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method); + 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); - 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_compression_implementation comp_impl; + 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 (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 ((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; } - 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 = 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; } - 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_decompress) { + if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) { + zip_source_free(src_final); + return -1; + } + + 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) { + if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) { + zip_source_free(src_final); + return -1; } - else { - s2 = s_crc; - } - } - else { - zip_source_keep(src); - s2 = src; + + zip_source_free(src_final); + src_final = src_tmp; } + + 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) { + _zip_error_set_from_source(&za->error, za->src); return -1; } - ret = copy_source(za, s2); + ret = copy_source(za, src_final, data_length); - if (zip_source_stat(s2, &st) < 0) + if (zip_source_stat(src_final, &st) < 0) { + _zip_error_set_from_source(&za->error, src_final); ret = -1; + } - zip_source_free(s2); + if ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) { + _zip_error_set_from_source(&za->error, src_final); + ret = -1; + } - if (ret < 0) + zip_source_free(src_final); + + if (ret < 0) { return -1; + } if ((offend = zip_source_tell_write(za->src)) < 0) { + _zip_error_set_from_source(&za->error, za->src); return -1; } @@ -371,7 +455,9 @@ de->crc = st.crc; de->uncomp_size = st.size; de->comp_size = (zip_uint64_t)(offend - offdata); - + de->bitflags = (zip_uint16_t)((de->bitflags & (zip_uint16_t)~6) | ((zip_uint8_t)compression_flags << 1)); + _zip_dirent_set_version_needed(de, (flags & ZIP_FL_FORCE_ZIP64) != 0); + if ((ret=_zip_dirent_write(za, de, flags)) < 0) return -1; @@ -380,7 +466,6 @@ zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); return -1; } - if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) { _zip_error_set_from_source(&za->error, za->src); @@ -396,6 +481,7 @@ { zip_uint8_t buf[BUFSIZE]; size_t n; + double total = (double)len; while (len > 0) { n = len > sizeof(buf) ? sizeof(buf) : len; @@ -408,6 +494,8 @@ } len -= n; + + _zip_progress_update(za->progress, (total - (double)len) / total); } return 0; @@ -415,10 +503,10 @@ static int -copy_source(zip_t *za, zip_source_t *src) +copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) { zip_uint8_t buf[BUFSIZE]; - zip_int64_t n; + zip_int64_t n, current; int ret; if (zip_source_open(src) < 0) { @@ -427,11 +515,16 @@ } ret = 0; + current = 0; while ((n=zip_source_read(src, buf, sizeof(buf))) > 0) { if (_zip_write(za, buf, (zip_uint64_t)n) < 0) { ret = -1; break; } + if (n == sizeof(buf) && za->progress && data_length > 0) { + current += n; + _zip_progress_update(za->progress, (double)current/(double)data_length); + } } if (n < 0) { @@ -444,7 +537,6 @@ return ret; } - static int write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
--- a/libzip/lib/zip_delete.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_delete.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_dirent.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_dirent.c Tue Oct 10 20:43:12 2017 +0200 @@ -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_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++) - _zip_entry_init(cd->entry+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; - cd->nentry = cd->nentry_alloc = nentry; - cd->size = cd->offset = 0; - cd->comment = NULL; + 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; + } - return cd; + cd->entry = new_entry; + + for (i = cd->nentry; i < new_alloc; i++) { + _zip_entry_init(cd->entry+i); + } + + cd->nentry = cd->nentry_alloc = new_alloc; + + return true; } @@ -222,6 +252,13 @@ _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,8 +280,9 @@ de->local_extra_fields_read = 0; de->cloned = 0; - de->version_madeby = 20 | (ZIP_OPSYS_DEFAULT << 8); - de->version_needed = 20; /* 2.0 */ + de->crc_valid = true; + de->version_madeby = 63 | (ZIP_OPSYS_DEFAULT << 8); + de->version_needed = 10; /* 1.0 */ de->bitflags = 0; de->comp_method = ZIP_CM_DEFAULT; de->last_mod = 0; @@ -258,6 +296,9 @@ de->int_attrib = 0; de->ext_attrib = ZIP_EXT_ATTRIB_DEFAULT; de->offset = 0; + de->compression_level = 0; + de->encryption_method = ZIP_EM_NONE; + de->password = NULL; } @@ -372,6 +413,19 @@ 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 +578,10 @@ return -1; } + if (!_zip_dirent_process_winzip_aes(zde, error)) { + return -1; + } + zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields); return (zip_int64_t)(size + variable_size); @@ -566,6 +624,90 @@ } +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 +763,7 @@ 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 +794,16 @@ } } + if (de->encryption_method == ZIP_EM_NONE) { + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED; + } + else { + de->bitflags |= (zip_uint16_t)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 +847,35 @@ 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, (zip_uint8_t)(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); @@ -708,14 +888,24 @@ _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby)); } _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); + _zip_buffer_put_16(buffer, de->bitflags); + 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 @@ -911,3 +1101,39 @@ return; } + + +void +_zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64) { + zip_uint16_t length; + + if (de->comp_method == ZIP_CM_LZMA) { + de->version_needed = 63; + return; + } + + if (de->comp_method == ZIP_CM_BZIP2) { + de->version_needed = 46; + return; + } + + if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) { + de->version_needed = 45; + return; + } + + if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) { + de->version_needed = 20; + return; + } + + /* directory */ + if ((length = _zip_string_length(de->filename)) > 0) { + if (de->filename->raw[length-1] == '/') { + de->version_needed = 20; + return; + } + } + + de->version_needed = 10; +}
--- a/libzip/lib/zip_discard.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_discard.c Tue Oct 10 20:43:12 2017 +0200 @@ -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> @@ -71,6 +71,8 @@ } free(za->open_source); + _zip_progress_free(za->progress); + zip_error_fini(&za->error); free(za);
--- a/libzip/lib/zip_err_str.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_err_str.c Tue Oct 10 20:43:12 2017 +0200 @@ -31,12 +31,13 @@ "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", "Resource still in use", "Tell error", + "Compressed data invalid", }; const int _zip_nerr_str = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]); @@ -71,10 +72,11 @@ S, N, N, - N, + N, N, N, N, N, S, + N, };
--- a/libzip/lib/zip_error.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_error.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_error_strerror.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_error_strerror.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_error_to_str.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_error_to_str.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_extra_field.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_extra_field.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_fdopen.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_fdopen.c Tue Oct 10 20:43:12 2017 +0200 @@ -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> @@ -47,7 +47,7 @@ zip_source_t *src; struct zip_error error; - if (_flags < 0 || (_flags & ZIP_TRUNCATE)) { + if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS|ZIP_RDONLY))) { _zip_set_open_error(zep, NULL, ZIP_ER_INVAL); return NULL; }
--- a/libzip/lib/zip_file_get_offset.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_file_get_offset.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_filerange_crc.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_filerange_crc.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_fopen_index.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_fopen_index.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_fopen_index_encrypted.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_fopen_index_encrypted.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_get_encryption_implementation.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_get_encryption_implementation.c Tue Oct 10 20:43:12 2017 +0200 @@ -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; + } }
--- a/libzip/lib/zip_hash.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_hash.c Tue Oct 10 20:43:12 2017 +0200 @@ -35,94 +35,181 @@ #include <string.h> #include "zipint.h" +/* parameter for the string hash function */ +#define HASH_MULTIPLIER 33 +#define HASH_START 5381 + +/* hash table's fill ratio is kept between these by doubling/halfing its size as necessary */ +#define HASH_MAX_FILL .75 +#define HASH_MIN_FILL .01 + +/* but hash table size is kept between these */ +#define HASH_MIN_SIZE 256 +#define HASH_MAX_SIZE 0x80000000ul + struct zip_hash_entry { const zip_uint8_t *name; zip_int64_t orig_index; zip_int64_t current_index; struct zip_hash_entry *next; + zip_uint32_t hash_value; }; typedef struct zip_hash_entry zip_hash_entry_t; struct zip_hash { - zip_uint16_t table_size; + zip_uint32_t table_size; + zip_uint64_t nentries; zip_hash_entry_t **table; }; + +/* free list of entries */ +static void +free_list(zip_hash_entry_t *entry) +{ + while (entry != NULL) { + zip_hash_entry_t *next = entry->next; + free(entry); + entry = next; + } +} + + +/* compute hash of string, full 32 bit value */ +static zip_uint32_t +hash_string(const zip_uint8_t *name) +{ + zip_uint64_t value = HASH_START; + + if (name == NULL) { + return 0; + } + + while (*name != 0) { + value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul); + name++; + } + + return (zip_uint32_t)value; +} + + +/* resize hash table; new_size must be a power of 2, can be larger or smaller than current size */ +static bool +hash_resize(zip_hash_t *hash, zip_uint32_t new_size, zip_error_t *error) +{ + zip_hash_entry_t **new_table; + + if (new_size == hash->table_size) { + return true; + } + + if ((new_table = (zip_hash_entry_t**)calloc(new_size, sizeof(zip_hash_entry_t *))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + if (hash->nentries > 0) { + zip_uint32_t i; + + for (i = 0; i < hash->table_size; i++) { + zip_hash_entry_t *entry = hash->table[i]; + while (entry) { + zip_hash_entry_t *next = entry->next; + + zip_uint32_t new_index = entry->hash_value % new_size; + + entry->next = new_table[new_index]; + new_table[new_index] = entry; + + entry = next; + } + } + } + + free(hash->table); + hash->table = new_table; + hash->table_size = new_size; + + return true; +} + + +static zip_uint32_t +size_for_capacity(zip_uint64_t capacity) { + double needed_size = capacity / HASH_MAX_FILL; + zip_uint32_t v; + + if (needed_size > ZIP_UINT32_MAX) { + v = ZIP_UINT32_MAX; + } + else { + v = (zip_uint32_t)needed_size; + } + + if (v > HASH_MAX_SIZE) { + return HASH_MAX_SIZE; + } + + /* From Bit Twiddling Hacks by Sean Eron Anderson <seander@cs.stanford.edu> + (http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2). */ + + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + + return v; +} + + zip_hash_t * -_zip_hash_new(zip_uint16_t table_size, zip_error_t *error) +_zip_hash_new(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; } - 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; - } - + hash->table_size = 0; + hash->nentries = 0; + hash->table = 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; + zip_uint32_t i; if (hash == NULL) { return; } - for (i=0; i<hash->table_size; i++) { - if (hash->table[i] != NULL) { - _free_list(hash->table[i]); + if (hash->table != NULL) { + for (i=0; i<hash->table_size; i++) { + if (hash->table[i] != NULL) { + free_list(hash->table[i]); + } } + free(hash->table); } - 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_uint32_t hash_value, table_index; zip_hash_entry_t *entry; if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) { @@ -130,43 +217,59 @@ 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); + if (hash->table_size == 0) { + if (!hash_resize(hash, HASH_MIN_SIZE, error)) { + return false; + } + } + + hash_value = hash_string(name); + table_index = hash_value % hash->table_size; + + for (entry = hash->table[table_index]; entry != NULL; entry = entry->next) { + if (entry->hash_value == hash_value && 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[table_index]; + hash->table[table_index] = entry; + entry->hash_value = hash_value; + entry->orig_index = -1; + hash->nentries++; + if (hash->nentries > hash->table_size * HASH_MAX_FILL && hash->table_size < HASH_MAX_SIZE) { + if (!hash_resize(hash, hash->table_size * 2, error)) { 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->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_uint32_t hash_value, index; zip_hash_entry_t *entry, *previous; if (hash == NULL || name == NULL) { @@ -174,94 +277,144 @@ 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; + if (hash->nentries > 0) { + hash_value = hash_string(name); + index = hash_value % hash->table_size; + previous = NULL; + entry = hash->table[index]; + while (entry) { + if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) { + if (entry->orig_index == -1) { + if (previous) { + previous->next = entry->next; + } + else { + hash->table[index] = entry->next; + } + free(entry); + hash->nentries--; + if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) { + if (!hash_resize(hash, hash->table_size / 2, error)) { + return false; + } + } } else { - hash->table[hash_value] = entry->next; + entry->current_index = -1; } - free(entry); + return true; } - else { - entry->current_index = -1; - } - return true; + previous = entry; + entry = entry->next; } - 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_uint32_t hash_value, index; zip_hash_entry_t *entry; if (hash == NULL || name == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return -1; + 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; + if (hash->nentries > 0) { + hash_value = hash_string(name); + index = hash_value % hash->table_size; + for (entry = hash->table[index]; 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; } - else { - if (entry->current_index != -1) { - return entry->current_index; - } - } - break; } } zip_error_set(error, ZIP_ER_NOENT, 0); - return -1; + return -1; } -void -_zip_hash_revert(zip_hash_t *hash) + +bool +_zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error) { - zip_uint16_t i; + zip_uint32_t new_size; + + if (capacity == 0) { + return true; + } + + new_size = size_for_capacity(capacity); + + if (new_size <= hash->table_size) { + return true; + } + + if (!hash_resize(hash, new_size, error)) { + return false; + } + + return true; +} + + +bool +_zip_hash_revert(zip_hash_t *hash, zip_error_t *error) +{ + zip_uint32_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; - } + 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); + hash->nentries--; + } + else { + entry->current_index = entry->orig_index; + previous = entry; + entry = entry->next; + } + } + } + + if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) { + zip_uint32_t new_size = hash->table_size / 2; + while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) { + new_size /= 2; + } + if (!hash_resize(hash, new_size, error)) { + return false; } } + + return true; }
--- a/libzip/lib/zip_io_util.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_io_util.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_name_locate.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_name_locate.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_new.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_new.c Tue Oct 10 20:43:12 2017 +0200 @@ -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> @@ -52,7 +52,7 @@ return NULL; } - if ((za->names = _zip_hash_new(ZIP_HASH_TABLE_SIZE, error)) == NULL) { + if ((za->names = _zip_hash_new(error)) == NULL) { free(za); return NULL; } @@ -68,7 +68,7 @@ za->entry = NULL; za->nopen_source = za->nopen_source_alloc = 0; za->open_source = NULL; - za->tempdir = NULL; + za->progress = NULL; return za; }
--- a/libzip/lib/zip_open.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_open.c Tue Oct 10 20:43:12 2017 +0200 @@ -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 @@ { 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 @@ } exists = _zip_file_exists(src, error); - switch (exists) { + switch (exists) { case EXISTS_ERROR: return NULL; @@ -157,25 +157,6 @@ } } -ZIP_EXTERN int -zip_archive_set_tempdir(zip_t *za, const char *tempdir) -{ - 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; -} zip_t * _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) @@ -209,7 +190,7 @@ 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 */ @@ -225,6 +206,8 @@ free(cdir); + _zip_hash_reserve_capacity(za->names, za->nentry, &za->error); + 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) { @@ -233,7 +216,7 @@ 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 +227,7 @@ } } } - + za->ch_flags = za->flags; return za; @@ -269,7 +252,7 @@ /* _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 +269,7 @@ 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 +300,10 @@ 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 +322,7 @@ 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 +336,7 @@ } 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 +353,30 @@ 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,32 +384,31 @@ 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); _zip_cdir_free(cd); return NULL; } 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 +450,7 @@ 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 +459,27 @@ 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 +494,7 @@ 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 +589,7 @@ _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 +610,7 @@ if (best <= 0) { best = _zip_checkcons(za, cdir, &error); } - + a = _zip_checkcons(za, cdirnew, &error); if (best < a) { _zip_cdir_free(cdir); @@ -628,13 +631,13 @@ } 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 +652,7 @@ _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 +676,7 @@ 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 +703,7 @@ 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 +718,10 @@ if ((cd=_zip_cdir_new(nentry, error)) == NULL) return NULL; + cd->is_zip64 = false; cd->size = size; cd->offset = offset; - + return cd; } @@ -734,13 +738,13 @@ 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 +777,7 @@ } return NULL; } - + size = _zip_buffer_get_64(buffer); if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) { @@ -800,10 +804,16 @@ } if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) { zip_error_set(error, ZIP_ER_INCONS, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } return NULL; } if (num_disks != 0 || eocd_disk != 0) { zip_error_set(error, ZIP_ER_MULTIDISK, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } return NULL; } @@ -820,7 +830,7 @@ 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) { @@ -837,7 +847,12 @@ zip_error_set(error, ZIP_ER_SEEK, EFBIG); return NULL; } - if ((flags & ZIP_CHECKCONS) && offset+size != eocd_offset) { + if (offset+size > buf_offset + eocd_offset) { + /* cdir spans past EOCD record */ + zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + if ((flags & ZIP_CHECKCONS) && offset+size != buf_offset + eocd_offset) { zip_error_set(error, ZIP_ER_INCONS, 0); return NULL; } @@ -845,7 +860,7 @@ if ((cd=_zip_cdir_new(nentry, error)) == NULL) return NULL; - + cd->is_zip64 = true; cd->size = size; cd->offset = offset;
--- a/libzip/lib/zip_set_default_password.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_set_default_password.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_set_file_compression.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_set_file_compression.c Tue Oct 10 20:43:12 2017 +0200 @@ -41,7 +41,7 @@ zip_entry_t *e; zip_int32_t old_method; - if (idx >= za->nentry) { + if (idx >= za->nentry || flags > 9) { zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; } @@ -51,7 +51,7 @@ return -1; } - if (method != ZIP_CM_DEFAULT && method != ZIP_CM_STORE && method != ZIP_CM_DEFLATE) { + if (!zip_compression_method_supported(method, true)) { zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); return -1; } @@ -60,11 +60,15 @@ old_method = (e->orig == NULL ? ZIP_CM_DEFAULT : e->orig->comp_method); - /* TODO: revisit this when flags are supported, since they may require a recompression */ + /* TODO: do we want to recompress if level is set? Only if it's + * different than what bit flags tell us, but those are not + * defined for all compression methods, or not directly mappable + * to levels */ if (method == old_method) { if (e->changes) { e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD; + e->changes->compression_level = 0; if (e->changes->changed == 0) { _zip_dirent_free(e->changes); e->changes = NULL; @@ -80,6 +84,7 @@ } e->changes->comp_method = method; + e->changes->compression_level = (zip_uint16_t)flags; e->changes->changed |= ZIP_DIRENT_COMP_METHOD; }
--- a/libzip/lib/zip_set_name.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_set_name.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_source_crc.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_crc.c Tue Oct 10 20:43:12 2017 +0200 @@ -171,7 +171,7 @@ 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); + 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, ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1); } case ZIP_SOURCE_SEEK:
--- a/libzip/lib/zip_source_error.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_error.c Tue Oct 10 20:43:12 2017 +0200 @@ -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 @@ { return &src->error; } + +bool +_zip_source_had_error(zip_source_t *src) +{ + return zip_source_error(src)->zip_err != ZIP_ER_OK; +}
--- a/libzip/lib/zip_source_file.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_file.c Tue Oct 10 20:43:12 2017 +0200 @@ -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 @@ { if (za == NULL) return NULL; - + return zip_source_file_create(fname, start, len, &za->error); }
--- a/libzip/lib/zip_source_filep.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_filep.c Tue Oct 10 20:43:12 2017 +0200 @@ -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 @@ 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 @@ { if (za == NULL) return NULL; - + return zip_source_filep_create(file, start, len, &za->error); } @@ -114,12 +115,23 @@ { struct read_file *ctx; zip_source_t *zs; - + struct stat sb; + bool stat_valid; + 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 +147,7 @@ } 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,22 +156,61 @@ 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; + stat_valid = stat(ctx->fname, &sb) >= 0; - if (stat(ctx->fname, &sb) < 0 || S_ISREG(sb.st_mode)) { - ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + if (!stat_valid) { + if (ctx->start == 0 && ctx->end == 0) { + ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + } } } - else if (fseeko(ctx->f, 0, SEEK_CUR) == 0) { - ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE; + else { + stat_valid = fstat(fileno(ctx->f), &sb) >= 0; + } + + if (!stat_valid) { + zip_error_set(&ctx->stat_error, ZIP_ER_READ, errno); + } + 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 (ctx->end == 0) { + ctx->st.size = (zip_uint64_t)sb.st_size - ctx->start; + ctx->st.valid |= ZIP_STAT_SIZE; + + if (ctx->fname && start == 0) { + ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + } + } + } } if ((zs=zip_source_function_create(read_file, ctx, error)) == NULL) { @@ -179,7 +230,7 @@ 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 +253,7 @@ free(temp); return -1; } - + #ifdef _WIN32 /* According to Pierre Joye, Windows in some environments per @@ -210,10 +261,10 @@ */ _setmode(_fileno(tfp), _O_BINARY ); #endif - + ctx->fout = tfp; ctx->tmpname = temp; - + return 0; } @@ -236,7 +287,7 @@ return -1; } return create_temp_output(ctx); - + case ZIP_SOURCE_COMMIT_WRITE: { mode_t mask; @@ -257,17 +308,17 @@ 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 +326,7 @@ fclose(ctx->f); free(ctx); return 0; - + case ZIP_SOURCE_OPEN: if (ctx->fname) { if ((ctx->f=fopen(ctx->fname, "rb")) == NULL) { @@ -283,18 +334,19 @@ 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 +354,7 @@ else { n = len; } - + if (n > SIZE_MAX) n = SIZE_MAX; @@ -315,14 +367,14 @@ 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 +384,7 @@ free(ctx->tmpname); ctx->tmpname = NULL; return 0; - + case ZIP_SOURCE_SEEK: { zip_int64_t new_current; int need_seek; @@ -340,14 +392,14 @@ 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 +409,14 @@ 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 +426,30 @@ 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 +460,43 @@ 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 (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; + } - 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; - } - } + 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; }
--- a/libzip/lib/zip_source_function.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_function.c Tue Oct 10 20:43:12 2017 +0200 @@ -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 @@ src->source_archive = NULL; src->refcount = 1; zip_error_init(&src->error); + src->eof = false; return src; }
--- a/libzip/lib/zip_source_open.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_open.c Tue Oct 10 20:43:12 2017 +0200 @@ -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 @@ } } + src->eof = false; + _zip_error_clear(&src->error); src->open_count++; return 0;
--- a/libzip/lib/zip_source_pkware.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_pkware.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_source_read.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_read.c Tue Oct 10 20:43:12 2017 +0200 @@ -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 @@ 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; +}
--- a/libzip/lib/zip_source_stat.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_stat.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_source_supports.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_supports.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_source_win32a.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_win32a.c Tue Oct 10 20:43:12 2017 +0200 @@ -90,7 +90,7 @@ static HANDLE _win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa) { - int len; + size_t len; len = strlen((const char *)ctx->fname) + 10; if (*temp == NULL) {
--- a/libzip/lib/zip_source_win32handle.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_win32handle.c Tue Oct 10 20:43:12 2017 +0200 @@ -344,9 +344,12 @@ } 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; + } } }
--- a/libzip/lib/zip_source_win32w.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_win32w.c Tue Oct 10 20:43:12 2017 +0200 @@ -90,7 +90,7 @@ static HANDLE _win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa) { - int len; + size_t len; len = wcslen((const wchar_t *)ctx->fname) + 10; if (*temp == NULL) {
--- a/libzip/lib/zip_source_window.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_window.c Tue Oct 10 20:43:12 2017 +0200 @@ -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 @@ -38,10 +38,17 @@ #include "zipint.h" struct window { - zip_uint64_t start; - zip_uint64_t end; - zip_uint64_t offset; + zip_uint64_t start; /* where in file we start reading */ + zip_uint64_t end; /* where in file we stop reading */ + + /* if not NULL, read file data for this file */ + zip_t *source_archive; + zip_uint64_t source_index; + + zip_uint64_t offset; /* offset in src for next read */ + zip_stat_t stat; + zip_int8_t compression_flags; zip_error_t error; zip_int64_t supports; bool needs_seek; @@ -53,39 +60,42 @@ zip_source_t * zip_source_window(zip_t *za, zip_source_t *src, zip_uint64_t start, zip_uint64_t len) { - return _zip_source_window_new(src, start, len, NULL, &za->error); + return _zip_source_window_new(src, start, len, NULL, 0, NULL, 0, &za->error); } 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) +_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) { struct window *ctx; - - if (src == NULL || start + length < start) { + + if (src == NULL || start + length < start || (source_archive == NULL && source_index != 0)) { zip_error_set(error, ZIP_ER_INVAL, 0); return NULL; } - + if ((ctx=(struct window *)malloc(sizeof(*ctx))) == NULL) { zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; } - + ctx->start = start; ctx->end = start + length; zip_stat_init(&ctx->stat); + ctx->compression_flags = compression_flags; + ctx->source_archive = source_archive; + ctx->source_index = source_index; zip_error_init(&ctx->error); - ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1)); + ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1)); ctx->needs_seek = (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) ? true : false; - + if (st) { if (_zip_stat_merge(&ctx->stat, st, error) < 0) { free(ctx); return NULL; } } - + return zip_source_layered_create(src, window_read, ctx, error); } @@ -123,15 +133,31 @@ switch (cmd) { case ZIP_SOURCE_CLOSE: return 0; - + case ZIP_SOURCE_ERROR: return zip_error_to_data(&ctx->error, data, len); - + case ZIP_SOURCE_FREE: free(ctx); return 0; case ZIP_SOURCE_OPEN: + if (ctx->source_archive) { + zip_int64_t offset; + + if ((offset = _zip_file_get_offset(ctx->source_archive, ctx->source_index, &ctx->error)) == 0) { + return -1; + } + if (ctx->end + offset < ctx->end) { + /* zip archive data claims end of data past zip64 limits */ + zip_error_set(&ctx->error, ZIP_ER_INCONS, 0); + return -1; + } + ctx->start += offset; + ctx->end += offset; + ctx->source_archive = NULL; + } + if (!ctx->needs_seek) { for (n=0; n<ctx->start; n+=(zip_uint64_t)ret) { i = (ctx->start-n > sizeof(b) ? sizeof(b) : ctx->start-n); @@ -144,7 +170,7 @@ return -1; } } - + } ctx->offset = ctx->start; return 0; @@ -152,17 +178,17 @@ case ZIP_SOURCE_READ: if (len > ctx->end - ctx->offset) len = ctx->end - ctx->offset; - + if (len == 0) return 0; - + if (ctx->needs_seek) { if (zip_source_seek(src, (zip_int64_t)ctx->offset, SEEK_SET) < 0) { _zip_error_set_from_source(&ctx->error, src); return -1; } } - + if ((ret=zip_source_read(src, data, len)) < 0) { zip_error_set(&ctx->error, ZIP_ER_EOF, 0); return -1; @@ -177,7 +203,7 @@ } } return ret; - + case ZIP_SOURCE_SEEK: { zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset - ctx->start, ctx->end - ctx->start, data, len, &ctx->error); @@ -185,7 +211,7 @@ if (new_offset < 0) { return -1; } - + ctx->offset = (zip_uint64_t)new_offset + ctx->start; return 0; } @@ -193,21 +219,24 @@ case ZIP_SOURCE_STAT: { zip_stat_t *st; - + st = (zip_stat_t *)data; - + if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) { return -1; } return 0; } - + + case ZIP_SOURCE_GET_COMPRESSION_FLAGS: + return ctx->compression_flags; + case ZIP_SOURCE_SUPPORTS: return ctx->supports; - + case ZIP_SOURCE_TELL: return (zip_int64_t)(ctx->offset - ctx->start); - + default: zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); return -1; @@ -219,7 +248,7 @@ _zip_deregister_source(zip_t *za, zip_source_t *src) { unsigned int i; - + for (i=0; i<za->nopen_source; i++) { if (za->open_source[i] == src) { za->open_source[i] = za->open_source[za->nopen_source-1]; @@ -234,7 +263,7 @@ _zip_register_source(zip_t *za, zip_source_t *src) { zip_source_t **open_source; - + if (za->nopen_source+1 >= za->nopen_source_alloc) { unsigned int n; n = za->nopen_source_alloc + 10; @@ -246,8 +275,8 @@ za->nopen_source_alloc = n; za->open_source = open_source; } - + za->open_source[za->nopen_source++] = src; - + return 0; }
--- a/libzip/lib/zip_source_zip_new.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_source_zip_new.c Tue Oct 10 20:43:12 2017 +0200 @@ -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> @@ -40,11 +40,9 @@ zip_source_t * _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password) { - zip_compression_implementation comp_impl; - zip_encryption_implementation enc_impl; zip_source_t *src, *s2; - zip_uint64_t offset; struct zip_stat st; + bool partial_data, needs_crc, needs_decrypt, needs_decompress; if (za == NULL) return NULL; @@ -74,59 +72,59 @@ } /* overflow or past end of file */ - if ((start > 0 || len > 0) && (start+len < start || start+len > st.size)) { + if ((start > 0 || len > 0) && (start + len < start || start + len > st.size)) { zip_error_set(&za->error, ZIP_ER_INVAL, 0); return NULL; } - enc_impl = NULL; - if (((flags & ZIP_FL_ENCRYPTED) == 0) && (st.encryption_method != ZIP_EM_NONE)) { + if (len == 0) { + len = st.size - start; + } + + partial_data = len < st.size; + needs_decrypt = ((flags & ZIP_FL_ENCRYPTED) == 0) && (st.encryption_method != ZIP_EM_NONE); + needs_decompress = ((flags & ZIP_FL_COMPRESSED) == 0) && (st.comp_method != ZIP_CM_STORE); + /* when reading the whole file, check for CRC errors */ + needs_crc = ((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE) && !partial_data; + + if (needs_decrypt) { + 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) { - zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); - return NULL; - } } - 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) { - zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); - return NULL; - } - } - } - - if ((offset=_zip_file_get_offset(srcza, srcidx, &za->error)) == 0) - return NULL; - if (st.comp_size == 0) { return zip_source_buffer(za, NULL, 0, 0); } - if (start+len > 0 && enc_impl == NULL && comp_impl == NULL) { + if (partial_data && !needs_decrypt && !needs_decompress) { struct zip_stat st2; - st2.size = len ? len : st.size-start; - st2.comp_size = st2.size; + st2.size = len; + st2.comp_size = len; st2.comp_method = ZIP_CM_STORE; st2.mtime = st.mtime; st2.valid = ZIP_STAT_SIZE|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_MTIME; - if ((src = _zip_source_window_new(srcza->src, offset+start, st2.size, &st2, &za->error)) == NULL) { + if ((src = _zip_source_window_new(srcza->src, start, len, &st2, 0, srcza, srcidx, &za->error)) == NULL) { return NULL; } } else { - if ((src = _zip_source_window_new(srcza->src, offset, st.comp_size, &st, &za->error)) == NULL) { + zip_dirent_t *de; + + if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) { + return NULL; + } + if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, (de->bitflags >> 1) & 3, srcza, srcidx, &za->error)) == NULL) { return NULL; } } - + if (_zip_source_set_source_archive(src, srcza) < 0) { zip_source_free(src); return NULL; @@ -134,7 +132,14 @@ /* creating a layered source calls zip_keep() on the lower layer, so we free it */ - if (enc_impl) { + if (needs_decrypt) { + zip_encryption_implementation enc_impl; + + 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; + } + s2 = enc_impl(za, src, st.encryption_method, 0, password); zip_source_free(src); if (s2 == NULL) { @@ -142,16 +147,15 @@ } src = s2; } - if (comp_impl) { - s2 = comp_impl(za, src, st.comp_method, 0); + if (needs_decompress) { + s2 = zip_source_decompress(za, src, st.comp_method); zip_source_free(src); if (s2 == NULL) { return NULL; } src = s2; } - if (((flags & ZIP_FL_COMPRESSED) == 0 || st.comp_method == ZIP_CM_STORE) && (len == 0 || len == st.comp_size)) { - /* when reading the whole file, check for CRC errors */ + if (needs_crc) { s2 = zip_source_crc(za, src, 1); zip_source_free(src); if (s2 == NULL) { @@ -160,8 +164,8 @@ src = s2; } - if (start+len > 0 && (comp_impl || enc_impl)) { - s2 = zip_source_window(za, src, start, len ? len : st.size-start); + if (partial_data && (needs_decrypt || needs_decompress)) { + s2 = zip_source_window(za, src, start, len); zip_source_free(src); if (s2 == NULL) { return NULL;
--- a/libzip/lib/zip_stat_index.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_stat_index.c Tue Oct 10 20:43:12 2017 +0200 @@ -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 @@ 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; }
--- a/libzip/lib/zip_unchange.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_unchange.c Tue Oct 10 20:43:12 2017 +0200 @@ -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>
--- a/libzip/lib/zip_unchange_all.c Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zip_unchange_all.c Tue Oct 10 20:43:12 2017 +0200 @@ -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> @@ -43,7 +43,9 @@ int ret; zip_uint64_t i; - _zip_hash_revert(za->names); + if (!_zip_hash_revert(za->names, &za->error)) { + return -1; + } ret = 0; for (i=0; i<za->nentry; i++)
--- a/libzip/lib/zipint.h Fri Sep 22 14:07:40 2017 +0200 +++ b/libzip/lib/zipint.h Tue Oct 10 20:43:12 2017 +0200 @@ -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,20 @@ #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_CM_ACTUAL(x) ((zip_uint16_t)(ZIP_CM_IS_DEFAULT(x) ? ZIP_CM_DEFLATE : (x))) #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) @@ -92,14 +96,49 @@ #define ZIP_CODEC_DECODE 0 /* decompress/decrypt (encode flag not set) */ #define ZIP_CODEC_ENCODE 1 /* compress/encrypt */ - -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_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t method, int operation); + +enum zip_compression_status { + ZIP_COMPRESSION_OK, + ZIP_COMPRESSION_END, + ZIP_COMPRESSION_ERROR, + ZIP_COMPRESSION_NEED_DATA +}; +typedef enum zip_compression_status zip_compression_status_t; + +struct zip_compression_algorithm { + /* called once to create new context */ + void *(*allocate)(zip_uint16_t method, int compression_flags, zip_error_t *error); + /* called once to free context */ + void (*deallocate)(void *ctx); + + /* get compression specific general purpose bitflags */ + int (*compression_flags)(void *ctx); + /* start processing */ + bool (*start)(void *ctx); + /* stop processing */ + bool (*end)(void *ctx); + /* provide new input data, remains valid until next call to input or end */ + bool (*input)(void *ctx, zip_uint8_t *data, zip_uint64_t length); + + /* all input data has been provided */ + void (*end_of_input)(void *ctx); + + /* process input data, writing to data, which has room for length bytes, update length to number of bytes written */ + zip_compression_status_t (*process)(void *ctx, zip_uint8_t *data, zip_uint64_t *length); +}; +typedef struct zip_compression_algorithm zip_compression_algorithm_t; + +extern zip_compression_algorithm_t zip_algorithm_bzip2_compress; +extern zip_compression_algorithm_t zip_algorithm_bzip2_decompress; +extern zip_compression_algorithm_t zip_algorithm_deflate_compress; +extern zip_compression_algorithm_t zip_algorithm_deflate_decompress; + +bool zip_compression_method_supported(zip_int32_t method, bool compress); /* This API is not final yet, but we need it internally, so it's private for now. */ @@ -110,14 +149,17 @@ Thus we will keep it private for now. */ typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *, void *, void *, zip_uint64_t, enum zip_source_cmd); +zip_source_t *zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t cm, int compression_flags); zip_source_t *zip_source_crc(zip_t *, zip_source_t *, int); -zip_source_t *zip_source_deflate(zip_t *, zip_source_t *, zip_int32_t, int); +zip_source_t *zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t cm); zip_source_t *zip_source_layered(zip_t *, zip_source_t *, zip_source_layered_callback, void *); zip_source_t *zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error); zip_source_t *zip_source_pkware(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); 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 */ @@ -126,10 +168,10 @@ /* directory entry: general purpose bit flags */ -#define ZIP_GPBF_ENCRYPTED 0x0001 /* is encrypted */ -#define ZIP_GPBF_DATA_DESCRIPTOR 0x0008 /* crc/size after file data */ -#define ZIP_GPBF_STRONG_ENCRYPTION 0x0040 /* uses strong encryption */ -#define ZIP_GPBF_ENCODING_UTF_8 0x0800 /* file name encoding is UTF-8 */ +#define ZIP_GPBF_ENCRYPTED 0x0001u /* is encrypted */ +#define ZIP_GPBF_DATA_DESCRIPTOR 0x0008u /* crc/size after file data */ +#define ZIP_GPBF_STRONG_ENCRYPTION 0x0040u /* uses strong encryption */ +#define ZIP_GPBF_ENCODING_UTF_8 0x0800u /* file name encoding is UTF-8 */ /* extra fields */ @@ -154,11 +196,8 @@ typedef enum zip_encoding_type zip_encoding_type_t; -#ifndef ZIP_HASH_TABLE_SIZE -#define ZIP_HASH_TABLE_SIZE 8192 -#endif - struct zip_hash; +struct zip_progress; typedef struct zip_cdir zip_cdir_t; typedef struct zip_dirent zip_dirent_t; @@ -167,6 +206,7 @@ typedef struct zip_string zip_string_t; typedef struct zip_buffer zip_buffer_t; typedef struct zip_hash zip_hash_t; +typedef struct zip_progress zip_progress_t; /* zip archive, part of API */ @@ -193,8 +233,8 @@ 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_t *progress; /* progress callback for zip_close() */ }; /* file in zip archive, part of API */ @@ -208,18 +248,22 @@ /* 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 +280,10 @@ 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 compression_level; /* level of compression to use (never valid in orig) */ + zip_uint16_t encryption_method; /* encryption method, computed from other fields */ + char *password; /* file specific encryption password */ }; /* zip archive central directory */ @@ -248,6 +296,7 @@ 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 +329,7 @@ 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 +362,7 @@ struct zip_buffer { bool ok; bool free_data; - + zip_uint8_t *data; zip_uint64_t size; zip_uint64_t offset; @@ -332,6 +382,8 @@ 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 +392,17 @@ #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 +418,20 @@ 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); @@ -377,6 +443,7 @@ bool _zip_dirent_needs_zip64(const zip_dirent_t *, zip_flags_t); zip_dirent_t *_zip_dirent_new(void); zip_int64_t _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error); +void _zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64); zip_int32_t _zip_dirent_size(zip_source_t *src, zip_uint16_t, zip_error_t *); int _zip_dirent_write(zip_t *za, zip_dirent_t *dirent, zip_flags_t flags); @@ -417,11 +484,21 @@ 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_hash_t *_zip_hash_new(zip_error_t *error); +bool _zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error); +bool _zip_hash_revert(zip_hash_t *hash, zip_error_t *error); zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *); +void _zip_progress_end(zip_progress_t *progress); +void _zip_progress_free(zip_progress_t *progress); +zip_progress_t *_zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud); +void _zip_progress_start(zip_progress_t *progress); +void _zip_progress_subrange(zip_progress_t *progress, double start, double end); +void _zip_progress_update(zip_progress_t *progress, double value); + +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,11 +509,14 @@ 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); +zip_int8_t zip_source_get_compression_flags(zip_source_t *); +bool _zip_source_had_error(zip_source_t *); void _zip_source_invalidate(zip_source_t *src); 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); +zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error); zip_source_t *_zip_source_zip_new(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *); int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error);