changeset 56:056ee6b5913e

libzip: update to 1.3.0, closes #654
author David Demelier <markand@malikania.fr>
date Tue, 10 Oct 2017 20:43:12 +0200
parents a7a33cbf3e52
children 82b832e1875d
files VERSION.libzip.txt libzip/CMakeLists.txt libzip/cmake-config.h.in libzip/lib/CMakeLists.txt libzip/lib/compat.h libzip/lib/mkstemp.c libzip/lib/zip.h libzip/lib/zip_add_entry.c libzip/lib/zip_buffer.c libzip/lib/zip_close.c libzip/lib/zip_delete.c libzip/lib/zip_dirent.c libzip/lib/zip_discard.c libzip/lib/zip_err_str.c libzip/lib/zip_error.c libzip/lib/zip_error_strerror.c libzip/lib/zip_error_to_str.c libzip/lib/zip_extra_field.c libzip/lib/zip_fdopen.c libzip/lib/zip_file_get_offset.c libzip/lib/zip_filerange_crc.c libzip/lib/zip_fopen_index.c libzip/lib/zip_fopen_index_encrypted.c libzip/lib/zip_get_encryption_implementation.c libzip/lib/zip_hash.c libzip/lib/zip_io_util.c libzip/lib/zip_name_locate.c libzip/lib/zip_new.c libzip/lib/zip_open.c libzip/lib/zip_set_default_password.c libzip/lib/zip_set_file_compression.c libzip/lib/zip_set_name.c libzip/lib/zip_source_crc.c libzip/lib/zip_source_error.c libzip/lib/zip_source_file.c libzip/lib/zip_source_filep.c libzip/lib/zip_source_function.c libzip/lib/zip_source_open.c libzip/lib/zip_source_pkware.c libzip/lib/zip_source_read.c libzip/lib/zip_source_stat.c libzip/lib/zip_source_supports.c libzip/lib/zip_source_win32a.c libzip/lib/zip_source_win32handle.c libzip/lib/zip_source_win32w.c libzip/lib/zip_source_window.c libzip/lib/zip_source_zip_new.c libzip/lib/zip_stat_index.c libzip/lib/zip_unchange.c libzip/lib/zip_unchange_all.c libzip/lib/zipint.h
diffstat 51 files changed, 1469 insertions(+), 605 deletions(-) [+]
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);