diff --git a/.gitmodules b/.gitmodules index caf9c8738a..9cdefb579d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -27,9 +27,6 @@ [submodule "3rdparty/sdl2/SDL"] path = 3rdparty/sdl2/SDL url = https://github.com/libsdl-org/SDL.git -[submodule "3rdparty/libzip/libzip"] - path = 3rdparty/libzip/libzip - url = https://github.com/nih-at/libzip.git [submodule "3rdparty/zstd/zstd"] path = 3rdparty/zstd/zstd url = https://github.com/facebook/zstd.git diff --git a/3rdparty/libzip/AUTHORS b/3rdparty/libzip/AUTHORS new file mode 100644 index 0000000000..a33707b01d --- /dev/null +++ b/3rdparty/libzip/AUTHORS @@ -0,0 +1,2 @@ +Dieter Baron +Thomas Klausner diff --git a/3rdparty/libzip/CMakeLists.txt b/3rdparty/libzip/CMakeLists.txt index 47e08c9326..8c2081564b 100644 --- a/3rdparty/libzip/CMakeLists.txt +++ b/3rdparty/libzip/CMakeLists.txt @@ -1,31 +1,386 @@ -set(BUILD_SHARED_LIBS OFF CACHE BOOL "") -set(LIBZIP_DO_INSTALL OFF CACHE BOOL "") +cmake_minimum_required(VERSION 3.5.0) -set(ENABLE_COMMONCRYPTO OFF CACHE BOOL "") -set(ENABLE_GNUTLS OFF CACHE BOOL "") -set(ENABLE_MBEDTLS OFF CACHE BOOL "") -set(ENABLE_WINDOWS_CRYPTO OFF CACHE BOOL "") -set(ENABLE_OPENSSL OFF CACHE BOOL "") -set(ENABLE_BZIP2 OFF CACHE BOOL "") -set(ENABLE_LZMA OFF CACHE BOOL "") -set(ENABLE_ZSTD ON CACHE BOOL "") - -set(BUILD_TOOLS OFF CACHE BOOL "") -set(BUILD_REGRESS OFF CACHE BOOL "") -set(BUILD_EXAMPLES OFF CACHE BOOL "") -set(BUILD_DOC OFF CACHE BOOL "") - -if(WIN32) - # Needed otherwise find_package() will look in the system. - set(ZLIB_FOUND TRUE) - set(ZLIB_LIBRARY "$") - set(ZLIB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/zlib") +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +if (${CMAKE_VERSION} VERSION_LESS "3.17.0") + list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake-compat) endif() -# Fill in the location of zstd, so find_package() doesn't try to use -# a potentially-old system version. It also picks up Zstd::Zstd. -set(Zstd_FOUND TRUE) -set(Zstd_LIBRARY "$") -set(Zstd_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../zstd/zstd/lib") +project(libzip + VERSION 1.10.1 + LANGUAGES C) -add_subdirectory(libzip EXCLUDE_FROM_ALL) +set(ENABLE_FDOPEN ON) +set(HAVE_LIBZSTD TRUE) +set(ZIP_STATIC TRUE) + +include(CheckFunctionExists) +include(CheckIncludeFiles) +include(CheckLibraryExists) +include(CheckSymbolExists) +include(CheckTypeSize) +include(CheckCSourceRuns) +include(CheckCSourceCompiles) +include(CheckStructHasMember) +include(TestBigEndian) + +# Checks + +# Request ISO C secure library functions (memcpy_s &c) +list(APPEND CMAKE_REQUIRED_DEFINITIONS -D__STDC_WANT_LIB_EXT1__=1) + +check_function_exists(_close HAVE__CLOSE) +check_function_exists(_dup HAVE__DUP) +check_function_exists(_fdopen HAVE__FDOPEN) +check_function_exists(_fileno HAVE__FILENO) +check_function_exists(_setmode HAVE__SETMODE) +check_symbol_exists(_snprintf stdio.h HAVE__SNPRINTF) +check_symbol_exists(_snprintf_s stdio.h HAVE__SNPRINTF_S) +check_symbol_exists(_snwprintf_s stdio.h HAVE__SNWPRINTF_S) +check_function_exists(_strdup HAVE__STRDUP) +check_symbol_exists(_stricmp string.h HAVE__STRICMP) +check_function_exists(_strtoi64 HAVE__STRTOI64) +check_function_exists(_strtoui64 HAVE__STRTOUI64) +check_function_exists(_unlink HAVE__UNLINK) +check_function_exists(arc4random HAVE_ARC4RANDOM) +check_function_exists(clonefile HAVE_CLONEFILE) +check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO) +check_function_exists(explicit_memset HAVE_EXPLICIT_MEMSET) +check_function_exists(fchmod HAVE_FCHMOD) +check_function_exists(fileno HAVE_FILENO) +check_function_exists(fseeko HAVE_FSEEKO) +check_function_exists(ftello HAVE_FTELLO) +check_function_exists(getprogname HAVE_GETPROGNAME) +check_symbol_exists(localtime_r time.h HAVE_LOCALTIME_R) +check_symbol_exists(localtime_s time.h HAVE_LOCALTIME_S) +check_function_exists(memcpy_s HAVE_MEMCPY_S) +check_function_exists(random HAVE_RANDOM) +check_function_exists(setmode HAVE_SETMODE) +check_symbol_exists(snprintf stdio.h HAVE_SNPRINTF) +check_symbol_exists(snprintf_s stdio.h HAVE_SNPRINTF_S) +check_symbol_exists(strcasecmp strings.h HAVE_STRCASECMP) +check_function_exists(strdup HAVE_STRDUP) +check_function_exists(strerror_s HAVE_STRERROR_S) +check_function_exists(strerrorlen_s HAVE_STRERRORLEN_S) +check_function_exists(stricmp HAVE_STRICMP) +check_function_exists(strncpy_s HAVE_STRNCPY_S) +check_function_exists(strtoll HAVE_STRTOLL) +check_function_exists(strtoull HAVE_STRTOULL) + +check_include_files("sys/types.h;sys/stat.h;fts.h" HAVE_FTS_H) +# fts functions may be in external library +if(HAVE_FTS_H) + check_function_exists(fts_open HAVE_FTS_OPEN) + if(NOT HAVE_FTS_OPEN) + check_library_exists(fts fts_open "" HAVE_LIB_FTS) + else(NOT HAVE_FTS_OPEN) + set(HAVE_LIB_FTS "" CACHE INTERNAL "") + endif(NOT HAVE_FTS_OPEN) +else(HAVE_FTS_H) + set(HAVE_LIB_FTS "" CACHE INTERNAL "") +endif(HAVE_FTS_H) + +if(HAVE_LIB_FTS) + set(FTS_LIB fts CACHE INTERNAL "") +else() + set(FTS_LIB "" CACHE INTERNAL "") +endif() + +check_include_files(stdbool.h HAVE_STDBOOL_H) +check_include_files(strings.h HAVE_STRINGS_H) +check_include_files(unistd.h HAVE_UNISTD_H) + +check_include_files(inttypes.h HAVE_INTTYPES_H_LIBZIP) +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) +check_type_size(__int16 __INT16_LIBZIP) +check_type_size(int16_t INT16_T_LIBZIP) +check_type_size(uint16_t UINT16_T_LIBZIP) +check_type_size(__int32 __INT32_LIBZIP) +check_type_size(int32_t INT32_T_LIBZIP) +check_type_size(uint32_t UINT32_T_LIBZIP) +check_type_size(__int64 __INT64_LIBZIP) +check_type_size(int64_t INT64_T_LIBZIP) +check_type_size(uint64_t UINT64_T_LIBZIP) +check_type_size("short" SHORT_LIBZIP) +check_type_size("int" INT_LIBZIP) +check_type_size("long" LONG_LIBZIP) +check_type_size("long long" LONG_LONG_LIBZIP) +check_type_size("off_t" SIZEOF_OFF_T) +check_type_size("size_t" SIZEOF_SIZE_T) + +check_c_source_compiles("#include +#include +int main(int argc, char *argv[]) { unsigned long x = FICLONERANGE; }" HAVE_FICLONERANGE) + +check_c_source_compiles(" +int foo(char * _Nullable bar); +int main(int argc, char *argv[]) { }" HAVE_NULLABLE) + +test_big_endian(WORDS_BIGENDIAN) + +if(MSVC) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + add_compile_definitions(_CRT_NONSTDC_NO_DEPRECATE) +endif(MSVC) + +# fixed size integral types + +if(HAVE_INTTYPES_H_LIBZIP) + set(LIBZIP_TYPES_INCLUDE "#if !defined(__STDC_FORMAT_MACROS) +#define __STDC_FORMAT_MACROS 1 +#endif +#include ") +elseif(HAVE_STDINT_H_LIBZIP) + set(LIBZIP_TYPES_INCLUDE "#include ") +elseif(HAVE_SYS_TYPES_H_LIBZIP) + set(LIBZIP_TYPES_INCLUDE "#include ") +endif() + +if(HAVE_INT8_T_LIBZIP) + set(ZIP_INT8_T int8_t) +elseif(HAVE___INT8_LIBZIP) + set(ZIP_INT8_T __int8) +else() + set(ZIP_INT8_T "signed char") +endif() + +if(HAVE_UINT8_T_LIBZIP) + set(ZIP_UINT8_T uint8_t) +elseif(HAVE___INT8_LIBZIP) + set(ZIP_UINT8_T "unsigned __int8") +else() + set(ZIP_UINT8_T "unsigned char") +endif() + +if(HAVE_INT16_T_LIBZIP) + set(ZIP_INT16_T int16_t) +elseif(HAVE___INT16_LIBZIP) + set(INT16_T_LIBZIP __int16) +elseif(SHORT_LIBZIP EQUAL 2) + set(INT16_T_LIBZIP short) +endif() + +if(HAVE_UINT16_T_LIBZIP) + set(ZIP_UINT16_T uint16_t) +elseif(HAVE___INT16_LIBZIP) + set(UINT16_T_LIBZIP "unsigned __int16") +elseif(SHORT_LIBZIP EQUAL 2) + set(UINT16_T_LIBZIP "unsigned short") +endif() + +if(HAVE_INT32_T_LIBZIP) + set(ZIP_INT32_T int32_t) +elseif(HAVE___INT32_LIBZIP) + set(ZIP_INT32_T __int32) +elseif(INT_LIBZIP EQUAL 4) + set(ZIP_INT32_T int) +elseif(LONG_LIBZIP EQUAL 4) + set(ZIP_INT32_T long) +endif() + +if(HAVE_UINT32_T_LIBZIP) + set(ZIP_UINT32_T uint32_t) +elseif(HAVE___INT32_LIBZIP) + set(ZIP_UINT32_T "unsigned __int32") +elseif(INT_LIBZIP EQUAL 4) + set(ZIP_UINT32_T "unsigned int") +elseif(LONG_LIBZIP EQUAL 4) + set(ZIP_UINT32_T "unsigned long") +endif() + +if(HAVE_INT64_T_LIBZIP) + set(ZIP_INT64_T int64_t) +elseif(HAVE___INT64_LIBZIP) + set(ZIP_INT64_T __int64) +elseif(LONG_LIBZIP EQUAL 8) + set(ZIP_INT64_T long) +elseif(LONG_LONG_LIBZIP EQUAL 8) + set(ZIP_INT64_T "long long") +endif() + +if(HAVE_UINT64_T_LIBZIP) + set(ZIP_UINT64_T uint64_t) +elseif(HAVE___INT64_LIBZIP) + set(ZIP_UINT64_T "unsigned __int64") +elseif(LONG_LIBZIP EQUAL 8) + set(ZIP_UINT64_T "unsigned long") +elseif(LONG_LONG_LIBZIP EQUAL 8) + set(ZIP_UINT64_T "unsigned long long") +endif() + +if(HAVE_NULLABLE) + set(ZIP_NULLABLE_DEFINES) +else() + set(ZIP_NULLABLE_DEFINES "#define _Nullable +#define _Nonnull") +endif() + +# write out config file +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake-config.h.in ${PROJECT_BINARY_DIR}/config.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake-zipconf.h.in ${PROJECT_BINARY_DIR}/zipconf.h) + +set(CMAKE_C_VISIBILITY_PRESET hidden) + +add_library(zip STATIC + lib/zip_add.c + lib/zip_add_dir.c + lib/zip_add_entry.c + lib/zip_algorithm_deflate.c + lib/zip_buffer.c + lib/zip_close.c + lib/zip_delete.c + lib/zip_dir_add.c + lib/zip_dirent.c + lib/zip_discard.c + lib/zip_entry.c + lib/zip_error.c + lib/zip_error_clear.c + lib/zip_error_get.c + lib/zip_error_get_sys_type.c + lib/zip_error_strerror.c + lib/zip_error_to_str.c + lib/zip_extra_field.c + lib/zip_extra_field_api.c + lib/zip_fclose.c + lib/zip_fdopen.c + lib/zip_file_add.c + lib/zip_file_error_clear.c + lib/zip_file_error_get.c + lib/zip_file_get_comment.c + lib/zip_file_get_external_attributes.c + lib/zip_file_get_offset.c + lib/zip_file_rename.c + lib/zip_file_replace.c + lib/zip_file_set_comment.c + lib/zip_file_set_encryption.c + lib/zip_file_set_external_attributes.c + lib/zip_file_set_mtime.c + lib/zip_file_strerror.c + lib/zip_fopen.c + lib/zip_fopen_encrypted.c + lib/zip_fopen_index.c + lib/zip_fopen_index_encrypted.c + lib/zip_fread.c + lib/zip_fseek.c + lib/zip_ftell.c + lib/zip_get_archive_comment.c + lib/zip_get_archive_flag.c + lib/zip_get_encryption_implementation.c + lib/zip_get_file_comment.c + lib/zip_get_name.c + lib/zip_get_num_entries.c + lib/zip_get_num_files.c + lib/zip_hash.c + lib/zip_io_util.c + lib/zip_libzip_version.c + lib/zip_memdup.c + lib/zip_name_locate.c + lib/zip_new.c + lib/zip_open.c + lib/zip_pkware.c + lib/zip_progress.c + lib/zip_rename.c + lib/zip_replace.c + lib/zip_set_archive_comment.c + lib/zip_set_archive_flag.c + lib/zip_set_default_password.c + lib/zip_set_file_comment.c + lib/zip_set_file_compression.c + lib/zip_set_name.c + lib/zip_source_accept_empty.c + lib/zip_source_begin_write.c + lib/zip_source_begin_write_cloning.c + lib/zip_source_buffer.c + lib/zip_source_call.c + lib/zip_source_close.c + lib/zip_source_commit_write.c + lib/zip_source_compress.c + lib/zip_source_crc.c + lib/zip_source_error.c + lib/zip_source_file_common.c + lib/zip_source_file_stdio.c + lib/zip_source_free.c + lib/zip_source_function.c + lib/zip_source_get_file_attributes.c + lib/zip_source_is_deleted.c + lib/zip_source_layered.c + lib/zip_source_open.c + lib/zip_source_pass_to_lower_layer.c + lib/zip_source_pkware_decode.c + lib/zip_source_pkware_encode.c + lib/zip_source_read.c + lib/zip_source_remove.c + lib/zip_source_rollback_write.c + lib/zip_source_seek.c + lib/zip_source_seek_write.c + lib/zip_source_stat.c + lib/zip_source_supports.c + lib/zip_source_tell.c + lib/zip_source_tell_write.c + lib/zip_source_window.c + lib/zip_source_write.c + lib/zip_source_zip.c + lib/zip_source_zip_new.c + lib/zip_stat.c + lib/zip_stat_index.c + lib/zip_stat_init.c + lib/zip_strerror.c + lib/zip_string.c + lib/zip_unchange.c + lib/zip_unchange_all.c + lib/zip_unchange_archive.c + lib/zip_unchange_data.c + lib/zip_utf-8.c + ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c + ) + +if(WIN32) + target_sources(zip PRIVATE + lib/zip_source_file_win32.c + lib/zip_source_file_win32_named.c + lib/zip_source_file_win32_utf16.c + lib/zip_source_file_win32_utf8.c + lib/zip_source_file_win32_ansi.c + lib/zip_random_win32.c + ) +else(WIN32) + target_sources(zip PRIVATE + lib/zip_source_file_stdio_named.c + lib/zip_random_unix.c + ) +endif(WIN32) + +target_sources(zip PRIVATE lib/zip_algorithm_zstd.c) +target_link_libraries(zip PRIVATE Zstd::Zstd) + +target_link_libraries(zip PRIVATE ZLIB::ZLIB) +target_include_directories(zip + PUBLIC + $ + $ + $ + ) + +# create zip_err_str.c from zip.h and zipint.h +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c + COMMAND "${CMAKE_COMMAND}" + "-DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}" + "-DCMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}" + "-P" "${PROJECT_SOURCE_DIR}/cmake/GenerateZipErrorStrings.cmake" + DEPENDS + ${PROJECT_SOURCE_DIR}/cmake/GenerateZipErrorStrings.cmake + ${PROJECT_SOURCE_DIR}/lib/zip.h + ${PROJECT_SOURCE_DIR}/lib/zipint.h + COMMENT "Generating zip_err_str.c" +) + +add_library(libzip::zip ALIAS zip) diff --git a/3rdparty/libzip/LICENSE b/3rdparty/libzip/LICENSE new file mode 100644 index 0000000000..fa70609611 --- /dev/null +++ b/3rdparty/libzip/LICENSE @@ -0,0 +1,31 @@ +Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + +The authors can be contacted at + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/3rdparty/libzip/cmake-config.h.in b/3rdparty/libzip/cmake-config.h.in new file mode 100644 index 0000000000..630ed23f65 --- /dev/null +++ b/3rdparty/libzip/cmake-config.h.in @@ -0,0 +1,72 @@ +#ifndef HAD_CONFIG_H +#define HAD_CONFIG_H +#ifndef _HAD_ZIPCONF_H +#include "zipconf.h" +#endif +/* BEGIN DEFINES */ +#cmakedefine ENABLE_FDOPEN +#cmakedefine HAVE___PROGNAME +#cmakedefine HAVE__CLOSE +#cmakedefine HAVE__DUP +#cmakedefine HAVE__FDOPEN +#cmakedefine HAVE__FILENO +#cmakedefine HAVE__SETMODE +#cmakedefine HAVE__SNPRINTF +#cmakedefine HAVE__SNPRINTF_S +#cmakedefine HAVE__SNWPRINTF_S +#cmakedefine HAVE__STRDUP +#cmakedefine HAVE__STRICMP +#cmakedefine HAVE__STRTOI64 +#cmakedefine HAVE__STRTOUI64 +#cmakedefine HAVE__UNLINK +#cmakedefine HAVE_ARC4RANDOM +#cmakedefine HAVE_CLONEFILE +#cmakedefine HAVE_COMMONCRYPTO +#cmakedefine HAVE_CRYPTO +#cmakedefine HAVE_FICLONERANGE +#cmakedefine HAVE_FILENO +#cmakedefine HAVE_FCHMOD +#cmakedefine HAVE_FSEEKO +#cmakedefine HAVE_FTELLO +#cmakedefine HAVE_GETPROGNAME +#cmakedefine HAVE_GNUTLS +#cmakedefine HAVE_LIBBZ2 +#cmakedefine HAVE_LIBLZMA +#cmakedefine HAVE_LIBZSTD +#cmakedefine HAVE_LOCALTIME_R +#cmakedefine HAVE_LOCALTIME_S +#cmakedefine HAVE_MEMCPY_S +#cmakedefine HAVE_MBEDTLS +#cmakedefine HAVE_MKSTEMP +#cmakedefine HAVE_NULLABLE +#cmakedefine HAVE_OPENSSL +#cmakedefine HAVE_SETMODE +#cmakedefine HAVE_SNPRINTF +#cmakedefine HAVE_SNPRINTF_S +#cmakedefine HAVE_STRCASECMP +#cmakedefine HAVE_STRDUP +#cmakedefine HAVE_STRERROR_S +#cmakedefine HAVE_STRERRORLEN_S +#cmakedefine HAVE_STRICMP +#cmakedefine HAVE_STRNCPY_S +#cmakedefine HAVE_STRTOLL +#cmakedefine HAVE_STRTOULL +#cmakedefine HAVE_STRUCT_TM_TM_ZONE +#cmakedefine HAVE_STDBOOL_H +#cmakedefine HAVE_STRINGS_H +#cmakedefine HAVE_UNISTD_H +#cmakedefine HAVE_WINDOWS_CRYPTO +#cmakedefine SIZEOF_OFF_T ${SIZEOF_OFF_T} +#cmakedefine SIZEOF_SIZE_T ${SIZEOF_SIZE_T} +#cmakedefine HAVE_DIRENT_H +#cmakedefine HAVE_FTS_H +#cmakedefine HAVE_NDIR_H +#cmakedefine HAVE_SYS_DIR_H +#cmakedefine HAVE_SYS_NDIR_H +#cmakedefine WORDS_BIGENDIAN +#cmakedefine HAVE_SHARED +/* END DEFINES */ +#define PACKAGE "@CMAKE_PROJECT_NAME@" +#define VERSION "@CMAKE_PROJECT_VERSION@" + +#endif /* HAD_CONFIG_H */ diff --git a/3rdparty/libzip/cmake-zipconf.h.in b/3rdparty/libzip/cmake-zipconf.h.in new file mode 100644 index 0000000000..b88ed267fa --- /dev/null +++ b/3rdparty/libzip/cmake-zipconf.h.in @@ -0,0 +1,47 @@ +#ifndef _HAD_ZIPCONF_H +#define _HAD_ZIPCONF_H + +/* + zipconf.h -- platform specific include file + + This file was generated automatically by CMake + based on ../cmake-zipconf.h.in. + */ + +#define LIBZIP_VERSION "${libzip_VERSION}" +#define LIBZIP_VERSION_MAJOR ${libzip_VERSION_MAJOR} +#define LIBZIP_VERSION_MINOR ${libzip_VERSION_MINOR} +#define LIBZIP_VERSION_MICRO ${libzip_VERSION_PATCH} + +#cmakedefine ZIP_STATIC + +${ZIP_NULLABLE_DEFINES} + +${LIBZIP_TYPES_INCLUDE} + +typedef ${ZIP_INT8_T} zip_int8_t; +typedef ${ZIP_UINT8_T} zip_uint8_t; +typedef ${ZIP_INT16_T} zip_int16_t; +typedef ${ZIP_UINT16_T} zip_uint16_t; +typedef ${ZIP_INT32_T} zip_int32_t; +typedef ${ZIP_UINT32_T} zip_uint32_t; +typedef ${ZIP_INT64_T} zip_int64_t; +typedef ${ZIP_UINT64_T} zip_uint64_t; + +#define ZIP_INT8_MIN (-ZIP_INT8_MAX-1) +#define ZIP_INT8_MAX 0x7f +#define ZIP_UINT8_MAX 0xff + +#define ZIP_INT16_MIN (-ZIP_INT16_MAX-1) +#define ZIP_INT16_MAX 0x7fff +#define ZIP_UINT16_MAX 0xffff + +#define ZIP_INT32_MIN (-ZIP_INT32_MAX-1L) +#define ZIP_INT32_MAX 0x7fffffffL +#define ZIP_UINT32_MAX 0xffffffffLU + +#define ZIP_INT64_MIN (-ZIP_INT64_MAX-1LL) +#define ZIP_INT64_MAX 0x7fffffffffffffffLL +#define ZIP_UINT64_MAX 0xffffffffffffffffULL + +#endif /* zipconf.h */ diff --git a/3rdparty/libzip/cmake/Findzstd.cmake b/3rdparty/libzip/cmake/Findzstd.cmake new file mode 100644 index 0000000000..b389c6b3d3 --- /dev/null +++ b/3rdparty/libzip/cmake/Findzstd.cmake @@ -0,0 +1,186 @@ +# Copyright (C) 2020 Dieter Baron and Thomas Klausner +# +# The authors can be contacted at +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# +# 3. The names of the authors may not be used to endorse or promote +# products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#[=======================================================================[.rst: +Findzstd +------- + +Finds the Zstandard (zstd) library. + +Imported Targets +^^^^^^^^^^^^^^^^ + +This module provides the following imported targets, if found: + +``zstd::libzstd_shared`` + The shared Zstandard library +``zstd::libzstd_static`` + The shared Zstandard library + +Result Variables +^^^^^^^^^^^^^^^^ + +This will define the following variables: + +``zstd_FOUND`` + True if the system has the Zstandard library. +``zstd_VERSION`` + The version of the Zstandard library which was found. + +Cache Variables +^^^^^^^^^^^^^^^ + +The following cache variables may also be set: + +``zstd_INCLUDE_DIR`` + The directory containing ``zstd.h``. +``zstd_STATIC_LIBRARY`` + The path to the Zstandard static library. +``zstd_SHARED_LIBRARY`` + The path to the Zstandard shared library. +``zstd_DLL`` + The path to the Zstandard DLL. + +#]=======================================================================] + +find_package(PkgConfig) +pkg_check_modules(PC_zstd QUIET libzstd) + +find_path(zstd_INCLUDE_DIR + NAMES zstd.h + HINTS ${PC_zstd_INCLUDE_DIRS} +) + +find_file(zstd_DLL + NAMES libzstd.dll zstd.dll + PATH_SUFFIXES bin + HINTS ${PC_zstd_PREFIX} +) + +# On Windows, we manually define the library names to avoid mistaking the +# implib for the static library +if(zstd_DLL) + set(_zstd_win_static_name zstd-static) + set(_zstd_win_shared_name zstd) +else() + # vcpkg removes the -static suffix in static builds + set(_zstd_win_static_name zstd zstd_static) + set(_zstd_win_shared_name) +endif() + +set(_previous_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES}) +set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".dylib" ".dll.a" ".lib") +find_library(zstd_SHARED_LIBRARY + NAMES zstd ${_zstd_win_shared_name} + HINTS ${PC_zstd_LIBDIR} +) + +set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".lib") +find_library(zstd_STATIC_LIBRARY + NAMES zstd ${_zstd_win_static_name} + HINTS ${PC_zstd_LIBDIR} +) +set(CMAKE_FIND_LIBRARY_SUFFIXES ${_previous_suffixes}) + +# Set zstd_LIBRARY to the shared library or fall back to the static library +if(zstd_SHARED_LIBRARY) + set(_zstd_LIBRARY ${zstd_SHARED_LIBRARY}) +else() + set(_zstd_LIBRARY ${zstd_STATIC_LIBRARY}) +endif() + +# Extract version information from the header file +if(zstd_INCLUDE_DIR) + file(STRINGS ${zstd_INCLUDE_DIR}/zstd.h _ver_major_line + REGEX "^#define ZSTD_VERSION_MAJOR *[0-9]+" + LIMIT_COUNT 1) + string(REGEX MATCH "[0-9]+" + zstd_MAJOR_VERSION "${_ver_major_line}") + file(STRINGS ${zstd_INCLUDE_DIR}/zstd.h _ver_minor_line + REGEX "^#define ZSTD_VERSION_MINOR *[0-9]+" + LIMIT_COUNT 1) + string(REGEX MATCH "[0-9]+" + zstd_MINOR_VERSION "${_ver_minor_line}") + file(STRINGS ${zstd_INCLUDE_DIR}/zstd.h _ver_release_line + REGEX "^#define ZSTD_VERSION_RELEASE *[0-9]+" + LIMIT_COUNT 1) + string(REGEX MATCH "[0-9]+" + zstd_RELEASE_VERSION "${_ver_release_line}") + set(Zstd_VERSION "${zstd_MAJOR_VERSION}.${zstd_MINOR_VERSION}.${zstd_RELEASE_VERSION}") + unset(_ver_major_line) + unset(_ver_minor_line) + unset(_ver_release_line) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(zstd + FOUND_VAR zstd_FOUND + REQUIRED_VARS + _zstd_LIBRARY + zstd_INCLUDE_DIR + VERSION_VAR zstd_VERSION +) + +if(zstd_FOUND AND zstd_SHARED_LIBRARY AND NOT TARGET zstd::libzstd_shared) + add_library(zstd::libzstd_shared SHARED IMPORTED) + if(WIN32) + set_target_properties(zstd::libzstd_shared PROPERTIES + IMPORTED_LOCATION "${zstd_DLL}" + IMPORTED_IMPLIB "${zstd_SHARED_LIBRARY}" + ) + else() + set_target_properties(zstd::libzstd_shared PROPERTIES + IMPORTED_LOCATION "${zstd_SHARED_LIBRARY}" + ) + endif() + + set_target_properties(zstd::libzstd_shared PROPERTIES + INTERFACE_COMPILE_OPTIONS "${PC_zstd_CFLAGS_OTHER}" + INTERFACE_INCLUDE_DIRECTORIES "${zstd_INCLUDE_DIR}" + ) +endif() + +if(zstd_FOUND AND zstd_STATIC_LIBRARY AND NOT TARGET zstd::libzstd_static) + add_library(zstd::libzstd_static STATIC IMPORTED) + set_target_properties(zstd::libzstd_static PROPERTIES + IMPORTED_LOCATION "${zstd_STATIC_LIBRARY}" + INTERFACE_COMPILE_OPTIONS "${PC_zstd_CFLAGS_OTHER}" + INTERFACE_INCLUDE_DIRECTORIES "${zstd_INCLUDE_DIR}" + ) +endif() + +mark_as_advanced( + zstd_INCLUDE_DIR + zstd_DLL + zstd_SHARED_LIBRARY + zstd_STATIC_LIBRARY +) diff --git a/3rdparty/libzip/cmake/GenerateZipErrorStrings.cmake b/3rdparty/libzip/cmake/GenerateZipErrorStrings.cmake new file mode 100644 index 0000000000..550412b6cb --- /dev/null +++ b/3rdparty/libzip/cmake/GenerateZipErrorStrings.cmake @@ -0,0 +1,47 @@ +# create zip_err_str.c from zip.h and zipint.h +file(READ ${PROJECT_SOURCE_DIR}/lib/zip.h zip_h) +string(REGEX MATCHALL "#define ZIP_ER_([A-Z0-9_]+) ([0-9]+)[ \t]+/([-*0-9a-zA-Z, ']*)/" zip_h_err ${zip_h}) +file(READ ${PROJECT_SOURCE_DIR}/lib/zipint.h zipint_h) +string(REGEX MATCHALL "#define ZIP_ER_DETAIL_([A-Z0-9_]+) ([0-9]+)[ \t]+/([-*0-9a-zA-Z, ']*)/" zipint_h_err ${zipint_h}) +set(zip_err_str [=[ +/* + This file was generated automatically by CMake + from zip.h and zipint.h\; make changes there. +*/ + +#include "zipint.h" + +#define L ZIP_ET_LIBZIP +#define N ZIP_ET_NONE +#define S ZIP_ET_SYS +#define Z ZIP_ET_ZLIB + +#define E ZIP_DETAIL_ET_ENTRY +#define G ZIP_DETAIL_ET_GLOBAL + +const struct _zip_err_info _zip_err_str[] = { +]=]) +set(zip_err_type) +foreach(errln ${zip_h_err}) + string(REGEX MATCH "#define ZIP_ER_([A-Z0-9_]+) ([0-9]+)[ \t]+/([-*0-9a-zA-Z, ']*)/" err_t_tt ${errln}) + string(REGEX MATCH "([L|N|S|Z]+) ([-0-9a-zA-Z,, ']*)" err_t_tt "${CMAKE_MATCH_3}") + string(STRIP "${CMAKE_MATCH_2}" err_t_tt) + string(APPEND zip_err_str " { ${CMAKE_MATCH_1}, \"${err_t_tt}\" },\n") +endforeach() +string(APPEND zip_err_str [=[}\; + +const int _zip_err_str_count = sizeof(_zip_err_str)/sizeof(_zip_err_str[0])\; + +const struct _zip_err_info _zip_err_details[] = { +]=]) +foreach(errln ${zipint_h_err}) + string(REGEX MATCH "#define ZIP_ER_DETAIL_([A-Z0-9_]+) ([0-9]+)[ \t]+/([-*0-9a-zA-Z, ']*)/" err_t_tt ${errln}) + string(REGEX MATCH "([E|G]+) ([-0-9a-zA-Z, ']*)" err_t_tt "${CMAKE_MATCH_3}") + string(STRIP "${CMAKE_MATCH_2}" err_t_tt) + string(APPEND zip_err_str " { ${CMAKE_MATCH_1}, \"${err_t_tt}\" },\n") +endforeach() +string(APPEND zip_err_str [=[}\; + +const int _zip_err_details_count = sizeof(_zip_err_details)/sizeof(_zip_err_details[0])\; +]=]) +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c ${zip_err_str}) diff --git a/3rdparty/libzip/lib/CMakeLists.txt b/3rdparty/libzip/lib/CMakeLists.txt new file mode 100644 index 0000000000..1afefae000 --- /dev/null +++ b/3rdparty/libzip/lib/CMakeLists.txt @@ -0,0 +1,208 @@ +include(CheckFunctionExists) + +set(CMAKE_C_VISIBILITY_PRESET hidden) + +add_library(zip + zip_add.c + zip_add_dir.c + zip_add_entry.c + zip_algorithm_deflate.c + zip_buffer.c + zip_close.c + zip_delete.c + zip_dir_add.c + zip_dirent.c + zip_discard.c + zip_entry.c + zip_error.c + zip_error_clear.c + zip_error_get.c + zip_error_get_sys_type.c + zip_error_strerror.c + zip_error_to_str.c + zip_extra_field.c + zip_extra_field_api.c + zip_fclose.c + zip_fdopen.c + zip_file_add.c + zip_file_error_clear.c + zip_file_error_get.c + zip_file_get_comment.c + zip_file_get_external_attributes.c + zip_file_get_offset.c + 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 + zip_fopen.c + zip_fopen_encrypted.c + 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_encryption_implementation.c + zip_get_file_comment.c + zip_get_name.c + zip_get_num_entries.c + zip_get_num_files.c + zip_hash.c + zip_io_util.c + zip_libzip_version.c + zip_memdup.c + zip_name_locate.c + zip_new.c + zip_open.c + zip_pkware.c + zip_progress.c + zip_rename.c + zip_replace.c + zip_set_archive_comment.c + zip_set_archive_flag.c + zip_set_default_password.c + zip_set_file_comment.c + zip_set_file_compression.c + zip_set_name.c + zip_source_accept_empty.c + zip_source_begin_write.c + zip_source_begin_write_cloning.c + zip_source_buffer.c + zip_source_call.c + zip_source_close.c + zip_source_commit_write.c + zip_source_compress.c + zip_source_crc.c + zip_source_error.c + zip_source_file_common.c + zip_source_file_stdio.c + zip_source_free.c + zip_source_function.c + zip_source_get_file_attributes.c + zip_source_is_deleted.c + zip_source_layered.c + zip_source_open.c + zip_source_pass_to_lower_layer.c + zip_source_pkware_decode.c + zip_source_pkware_encode.c + zip_source_read.c + zip_source_remove.c + zip_source_rollback_write.c + zip_source_seek.c + zip_source_seek_write.c + zip_source_stat.c + zip_source_supports.c + zip_source_tell.c + zip_source_tell_write.c + zip_source_window.c + zip_source_write.c + zip_source_zip.c + zip_source_zip_new.c + zip_stat.c + zip_stat_index.c + zip_stat_init.c + zip_strerror.c + zip_string.c + zip_unchange.c + zip_unchange_all.c + zip_unchange_archive.c + zip_unchange_data.c + zip_utf-8.c + ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c + ) +add_library(libzip::zip ALIAS zip) + +if(WIN32) + target_sources(zip PRIVATE + zip_source_file_win32.c + zip_source_file_win32_named.c + zip_source_file_win32_utf16.c + zip_source_file_win32_utf8.c + ) + if(CMAKE_SYSTEM_NAME MATCHES WindowsPhone OR CMAKE_SYSTEM_NAME MATCHES WindowsStore) + target_sources(zip PRIVATE zip_random_uwp.c) + else() + target_sources(zip PRIVATE zip_source_file_win32_ansi.c zip_random_win32.c) + target_link_libraries(zip PRIVATE advapi32) + endif() +else(WIN32) + target_sources(zip PRIVATE + zip_source_file_stdio_named.c + zip_random_unix.c + ) +endif(WIN32) + +if(HAVE_LIBBZ2) + target_sources(zip PRIVATE zip_algorithm_bzip2.c) + target_link_libraries(zip PRIVATE BZip2::BZip2) +endif() + +if(HAVE_LIBLZMA) + target_sources(zip PRIVATE zip_algorithm_xz.c) + target_link_libraries(zip PRIVATE LibLZMA::LibLZMA) +endif() + +if(HAVE_LIBZSTD) + target_sources(zip PRIVATE zip_algorithm_zstd.c) + target_link_libraries(zip PRIVATE ${zstd_TARGET}) +endif() + +if(HAVE_COMMONCRYPTO) + target_sources(zip PRIVATE zip_crypto_commoncrypto.c) +elseif(HAVE_WINDOWS_CRYPTO) + target_sources(zip PRIVATE zip_crypto_win.c) + target_link_libraries(zip PRIVATE bcrypt) +elseif(HAVE_GNUTLS) + target_sources(zip PRIVATE zip_crypto_gnutls.c) + target_link_libraries(zip PRIVATE GnuTLS::GnuTLS Nettle::Nettle) +elseif(HAVE_OPENSSL) + target_sources(zip PRIVATE zip_crypto_openssl.c) + target_link_libraries(zip PRIVATE OpenSSL::Crypto) +elseif(HAVE_MBEDTLS) + target_sources(zip PRIVATE zip_crypto_mbedtls.c) + target_link_libraries(zip PRIVATE MbedTLS::MbedTLS) +endif() + +if(HAVE_CRYPTO) + target_sources(zip PRIVATE zip_winzip_aes.c zip_source_winzip_aes_decode.c zip_source_winzip_aes_encode.c) +endif() + +if(SHARED_LIB_VERSIONNING) + set_target_properties(zip PROPERTIES VERSION 5.5 SOVERSION 5) +endif() + +target_link_libraries(zip PRIVATE ZLIB::ZLIB) +target_include_directories(zip + PUBLIC + $ + $ + $ + ) + +if(LIBZIP_DO_INSTALL) + install(TARGETS zip + EXPORT ${PROJECT_NAME}-targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(FILES zip.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) +endif() + +# create zip_err_str.c from zip.h and zipint.h +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zip_err_str.c + COMMAND "${CMAKE_COMMAND}" + "-DPROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}" + "-DCMAKE_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}" + "-P" "${PROJECT_SOURCE_DIR}/cmake/GenerateZipErrorStrings.cmake" + DEPENDS + ${PROJECT_SOURCE_DIR}/cmake/GenerateZipErrorStrings.cmake + ${PROJECT_SOURCE_DIR}/lib/zip.h + ${PROJECT_SOURCE_DIR}/lib/zipint.h + COMMENT "Generating zip_err_str.c" +) diff --git a/3rdparty/libzip/lib/compat.h b/3rdparty/libzip/lib/compat.h new file mode 100644 index 0000000000..384a611ff6 --- /dev/null +++ b/3rdparty/libzip/lib/compat.h @@ -0,0 +1,240 @@ +#ifndef _HAD_LIBZIP_COMPAT_H +#define _HAD_LIBZIP_COMPAT_H + +/* + compat.h -- compatibility defines. + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipconf.h" + +#include "config.h" + +/* to have *_MAX definitions for all types when compiling with g++ */ +#define __STDC_LIMIT_MACROS + +/* to have ISO C secure library functions */ +#define __STDC_WANT_LIB_EXT1__ 1 + +#ifdef _WIN32 +#ifndef ZIP_EXTERN +#ifndef ZIP_STATIC +#define ZIP_EXTERN __declspec(dllexport) +#endif +#endif +/* for dup(), close(), etc. */ +#include +#endif + +#ifdef HAVE_STDBOOL_H +#include +#else +typedef char bool; +#define true 1 +#define false 0 +#endif + +#include + +/* at least MinGW does not provide EOPNOTSUPP, see + * http://sourceforge.net/p/mingw/bugs/263/ + */ +#ifndef EOPNOTSUPP +#define EOPNOTSUPP EINVAL +#endif + +/* at least MinGW does not provide EOVERFLOW, see + * http://sourceforge.net/p/mingw/bugs/242/ + */ +#ifndef EOVERFLOW +#define EOVERFLOW EFBIG +#endif + +/* not supported on at least Windows */ +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +#ifdef _WIN32 +#if defined(HAVE__CLOSE) +#define close _close +#endif +#if defined(HAVE__DUP) +#define dup _dup +#endif +/* crashes reported when using fdopen instead of _fdopen on Windows/Visual Studio 10/Win64 */ +#if defined(HAVE__FDOPEN) +#define fdopen _fdopen +#endif +#if !defined(HAVE_FILENO) && defined(HAVE__FILENO) +#define fileno _fileno +#endif +#if !defined(HAVE_SNPRINTF) && defined(HAVE__SNPRINTF) +#define snprintf _snprintf +#endif +#if !defined(HAVE__SNWPRINTF_S) +#define _snwprintf_s(buf, bufsz, len, fmt, ...) (_snwprintf((buf), (len), (fmt), __VA_ARGS__)) +#endif +#if defined(HAVE__STRDUP) +#if !defined(HAVE_STRDUP) || defined(_WIN32) +#undef strdup +#define strdup _strdup +#endif +#endif +#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__UNLINK) +#define unlink _unlink +#endif +#endif + +#ifndef HAVE_FSEEKO +#define fseeko(s, o, w) (fseek((s), (long int)(o), (w))) +#endif + +#ifndef HAVE_FTELLO +#define ftello(s) ((long)ftell((s))) +#endif + +#ifdef HAVE_LOCALTIME_S +#ifdef _WIN32 +/* Windows is incompatible to the C11 standard, hurray! */ +#define zip_localtime(t, tm) (localtime_s((tm), (t)) == 0 ? tm : NULL) +#else +#define zip_localtime localtime_s +#endif +#else +#ifdef HAVE_LOCALTIME_R +#define zip_localtime localtime_r +#else +#define zip_localtime(t, tm) (localtime(t)) +#endif +#endif + +#ifndef HAVE_MEMCPY_S +#define memcpy_s(dest, destsz, src, count) (memcpy((dest), (src), (count)) == NULL) +#endif + +#ifndef HAVE_SNPRINTF_S +#ifdef HAVE__SNPRINTF_S +#define snprintf_s(buf, bufsz, fmt, ...) (_snprintf_s((buf), (bufsz), (bufsz), (fmt), __VA_ARGS__)) +#else +#define snprintf_s snprintf +#endif +#endif + +#if !defined(HAVE_STRCASECMP) +#if defined(HAVE__STRICMP) +#define strcasecmp _stricmp +#elif defined(HAVE_STRICMP) +#define strcasecmp stricmp +#endif +#endif + +#ifndef HAVE_STRNCPY_S +#define strncpy_s(dest, destsz, src, count) (strncpy((dest), (src), (count)), 0) +#endif + +#ifndef HAVE_STRERROR_S +#define strerrorlen_s(errnum) (strlen(strerror(errnum))) +#define strerror_s(buf, bufsz, errnum) ((void)strncpy_s((buf), (bufsz), strerror(errnum), (bufsz)), (buf)[(bufsz)-1] = '\0', strerrorlen_s(errnum) >= (bufsz)) +#else +#ifndef HAVE_STRERRORLEN_S +#define strerrorlen_s(errnum) 8192 +#endif +#endif + +#if SIZEOF_OFF_T == 8 +#define ZIP_OFF_MAX ZIP_INT64_MAX +#define ZIP_OFF_MIN ZIP_INT64_MIN +#elif SIZEOF_OFF_T == 4 +#define ZIP_OFF_MAX ZIP_INT32_MAX +#define ZIP_OFF_MIN ZIP_INT32_MIN +#elif SIZEOF_OFF_T == 2 +#define ZIP_OFF_MAX ZIP_INT16_MAX +#define ZIP_OFF_MIN ZIP_INT16_MIN +#else +#error unsupported size of off_t +#endif + +#if defined(HAVE_FTELLO) && defined(HAVE_FSEEKO) +#define ZIP_FSEEK_MAX ZIP_OFF_MAX +#define ZIP_FSEEK_MIN ZIP_OFF_MIN +#else +#include +#define ZIP_FSEEK_MAX LONG_MAX +#define ZIP_FSEEK_MIN LONG_MIN +#endif + +#ifndef SIZE_MAX +#if SIZEOF_SIZE_T == 8 +#define SIZE_MAX ZIP_INT64_MAX +#elif SIZEOF_SIZE_T == 4 +#define SIZE_MAX ZIP_INT32_MAX +#elif SIZEOF_SIZE_T == 2 +#define SIZE_MAX ZIP_INT16_MAX +#else +#error unsupported size of size_t +#endif +#endif + +#ifndef PRId64 +#ifdef _MSC_VER +#define PRId64 "I64d" +#else +#define PRId64 "lld" +#endif +#endif + +#ifndef PRIu64 +#ifdef _MSC_VER +#define PRIu64 "I64u" +#else +#define PRIu64 "llu" +#endif +#endif + +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR) +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG) +#endif + +#endif /* compat.h */ diff --git a/3rdparty/libzip/lib/zip.h b/3rdparty/libzip/lib/zip.h new file mode 100644 index 0000000000..0d31d40684 --- /dev/null +++ b/3rdparty/libzip/lib/zip.h @@ -0,0 +1,517 @@ +#ifndef _HAD_ZIP_H +#define _HAD_ZIP_H + +/* + zip.h -- exported declarations. + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* fix autoindent */ +#endif +#endif + +#include + +#ifndef ZIP_EXTERN +#ifndef ZIP_STATIC +#ifdef _WIN32 +#define ZIP_EXTERN __declspec(dllimport) +#elif defined(__GNUC__) && __GNUC__ >= 4 +#define ZIP_EXTERN __attribute__((visibility("default"))) +#else +#define ZIP_EXTERN +#endif +#else +#define ZIP_EXTERN +#endif +#endif + +#ifndef ZIP_DEPRECATED +#if defined(__GNUC__) || defined(__clang__) +#define ZIP_DEPRECATED(x) __attribute__((deprecated(x))) +#elif defined(_MSC_VER) +#define ZIP_DEPRECATED(x) __declspec(deprecated(x)) +#else +#define ZIP_DEPRECATED(x) +#endif +#endif + +#include +#include +#include + +/* flags for zip_open */ + +#define ZIP_CREATE 1 +#define ZIP_EXCL 2 +#define ZIP_CHECKCONS 4 +#define ZIP_TRUNCATE 8 +#define ZIP_RDONLY 16 + + +/* flags for zip_name_locate, zip_fopen, zip_stat, ... */ + +#define ZIP_FL_NOCASE 1u /* ignore case on name lookup */ +#define ZIP_FL_NODIR 2u /* ignore directory component */ +#define ZIP_FL_COMPRESSED 4u /* read compressed data */ +#define ZIP_FL_UNCHANGED 8u /* use original data, ignoring changes */ +/* 16u was ZIP_FL_RECOMPRESS, which is deprecated */ +#define ZIP_FL_ENCRYPTED 32u /* read encrypted data (implies ZIP_FL_COMPRESSED) */ +#define ZIP_FL_ENC_GUESS 0u /* guess string encoding (is default) */ +#define ZIP_FL_ENC_RAW 64u /* get unmodified string */ +#define ZIP_FL_ENC_STRICT 128u /* follow specification strictly */ +#define ZIP_FL_LOCAL 256u /* in local header */ +#define ZIP_FL_CENTRAL 512u /* in central directory */ +/* 1024u reserved for internal use */ +#define ZIP_FL_ENC_UTF_8 2048u /* string is UTF-8 encoded */ +#define ZIP_FL_ENC_CP437 4096u /* string is CP437 encoded */ +#define ZIP_FL_OVERWRITE 8192u /* zip_file_add: if file with name exists, overwrite (replace) it */ + +/* archive global flags flags */ + +#define ZIP_AFL_RDONLY 2u /* read only -- cannot be cleared */ +#define ZIP_AFL_IS_TORRENTZIP 4u /* current archive is torrentzipped */ +#define ZIP_AFL_WANT_TORRENTZIP 8u /* write archive in torrentzip format */ +#define ZIP_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE 16u /* don't remove file if archive is empty */ + + +/* create a new extra field */ + +#define ZIP_EXTRA_FIELD_ALL ZIP_UINT16_MAX +#define ZIP_EXTRA_FIELD_NEW ZIP_UINT16_MAX + +/* length parameter to various functions */ + +#define ZIP_LENGTH_TO_END 0 +#define ZIP_LENGTH_UNCHECKED (-2) /* only supported by zip_source_file and its variants */ + +/* 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 /* L 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 */ +#define ZIP_ER_CANCELLED 32 /* N Operation cancelled */ +#define ZIP_ER_DATA_LENGTH 33 /* N Unexpected length of data */ +#define ZIP_ER_NOT_ALLOWED 34 /* N Not allowed in torrentzip */ + +/* type of system error value */ + +#define ZIP_ET_NONE 0 /* sys_err unused */ +#define ZIP_ET_SYS 1 /* sys_err is errno */ +#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */ +#define ZIP_ET_LIBZIP 3 /* sys_err is libzip error code */ + +/* compression methods */ + +#define ZIP_CM_DEFAULT -1 /* better of deflate or store */ +#define ZIP_CM_STORE 0 /* stored (uncompressed) */ +#define ZIP_CM_SHRINK 1 /* shrunk */ +#define ZIP_CM_REDUCE_1 2 /* reduced with factor 1 */ +#define ZIP_CM_REDUCE_2 3 /* reduced with factor 2 */ +#define ZIP_CM_REDUCE_3 4 /* reduced with factor 3 */ +#define ZIP_CM_REDUCE_4 5 /* reduced with factor 4 */ +#define ZIP_CM_IMPLODE 6 /* imploded */ +/* 7 - Reserved for Tokenizing compression algorithm */ +#define ZIP_CM_DEFLATE 8 /* deflated */ +#define ZIP_CM_DEFLATE64 9 /* deflate64 */ +#define ZIP_CM_PKWARE_IMPLODE 10 /* PKWARE imploding */ +/* 11 - Reserved by PKWARE */ +#define ZIP_CM_BZIP2 12 /* compressed using BZIP2 algorithm */ +/* 13 - Reserved by PKWARE */ +#define ZIP_CM_LZMA 14 /* LZMA (EFS) */ +/* 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) */ +/* 20 - old value for Zstandard */ +#define ZIP_CM_LZMA2 33 +#define ZIP_CM_ZSTD 93 /* Zstandard compressed data */ +#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 */ + +/* encryption methods */ + +#define ZIP_EM_NONE 0 /* not encrypted */ +#define ZIP_EM_TRAD_PKWARE 1 /* traditional PKWARE encryption */ +#if 0 /* Strong Encryption Header not parsed yet */ +#define ZIP_EM_DES 0x6601 /* strong encryption: DES */ +#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_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 +#define ZIP_OPSYS_AMIGA 0x01u +#define ZIP_OPSYS_OPENVMS 0x02u +#define ZIP_OPSYS_UNIX 0x03u +#define ZIP_OPSYS_VM_CMS 0x04u +#define ZIP_OPSYS_ATARI_ST 0x05u +#define ZIP_OPSYS_OS_2 0x06u +#define ZIP_OPSYS_MACINTOSH 0x07u +#define ZIP_OPSYS_Z_SYSTEM 0x08u +#define ZIP_OPSYS_CPM 0x09u +#define ZIP_OPSYS_WINDOWS_NTFS 0x0au +#define ZIP_OPSYS_MVS 0x0bu +#define ZIP_OPSYS_VSE 0x0cu +#define ZIP_OPSYS_ACORN_RISC 0x0du +#define ZIP_OPSYS_VFAT 0x0eu +#define ZIP_OPSYS_ALTERNATE_MVS 0x0fu +#define ZIP_OPSYS_BEOS 0x10u +#define ZIP_OPSYS_TANDEM 0x11u +#define ZIP_OPSYS_OS_400 0x12u +#define ZIP_OPSYS_OS_X 0x13u + +#define ZIP_OPSYS_DEFAULT ZIP_OPSYS_UNIX + + +enum zip_source_cmd { + ZIP_SOURCE_OPEN, /* prepare for reading */ + ZIP_SOURCE_READ, /* read data */ + ZIP_SOURCE_CLOSE, /* reading is done */ + ZIP_SOURCE_STAT, /* get meta information */ + ZIP_SOURCE_ERROR, /* get error information */ + ZIP_SOURCE_FREE, /* cleanup and free resources */ + ZIP_SOURCE_SEEK, /* set position for reading */ + ZIP_SOURCE_TELL, /* get read position */ + ZIP_SOURCE_BEGIN_WRITE, /* prepare for writing */ + ZIP_SOURCE_COMMIT_WRITE, /* writing is done */ + ZIP_SOURCE_ROLLBACK_WRITE, /* discard written changes */ + ZIP_SOURCE_WRITE, /* write data */ + 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_RESERVED_1, /* previously used internally */ + ZIP_SOURCE_BEGIN_WRITE_CLONING, /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */ + ZIP_SOURCE_ACCEPT_EMPTY, /* whether empty files are valid archives */ + ZIP_SOURCE_GET_FILE_ATTRIBUTES, /* get additional file attributes */ + ZIP_SOURCE_SUPPORTS_REOPEN /* allow reading from changed entry */ +}; +typedef enum zip_source_cmd zip_source_cmd_t; + +#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_int64_t)1) << (cmd)) + +#define ZIP_SOURCE_CHECK_SUPPORTED(supported, cmd) (((supported) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd)) != 0) + +/* clang-format off */ + +#define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_READ) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_CLOSE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_STAT) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ERROR) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_FREE)) + +#define ZIP_SOURCE_SUPPORTS_SEEKABLE (ZIP_SOURCE_SUPPORTS_READABLE \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SUPPORTS)) + +#define ZIP_SOURCE_SUPPORTS_WRITABLE (ZIP_SOURCE_SUPPORTS_SEEKABLE \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_COMMIT_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ROLLBACK_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL_WRITE) \ + | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_REMOVE)) + +/* clang-format on */ + +/* for use by sources */ +struct zip_source_args_seek { + zip_int64_t offset; + int whence; +}; + +typedef struct zip_source_args_seek zip_source_args_seek_t; +#define ZIP_SOURCE_GET_ARGS(type, data, len, error) ((len) < sizeof(type) ? zip_error_set((error), ZIP_ER_INVAL, 0), (type *)NULL : (type *)(data)) + + +/* error information */ +/* use zip_error_*() to access */ +struct zip_error { + int zip_err; /* libzip error code (ZIP_ER_*) */ + int sys_err; /* copy of errno (E*) or zlib error code */ + char *_Nullable str; /* string representation or NULL */ +}; + +#define ZIP_STAT_NAME 0x0001u +#define ZIP_STAT_INDEX 0x0002u +#define ZIP_STAT_SIZE 0x0004u +#define ZIP_STAT_COMP_SIZE 0x0008u +#define ZIP_STAT_MTIME 0x0010u +#define ZIP_STAT_CRC 0x0020u +#define ZIP_STAT_COMP_METHOD 0x0040u +#define ZIP_STAT_ENCRYPTION_METHOD 0x0080u +#define ZIP_STAT_FLAGS 0x0100u + +struct zip_stat { + zip_uint64_t valid; /* which fields have valid values */ + const char *_Nullable name; /* name of the file */ + zip_uint64_t index; /* index within archive */ + zip_uint64_t size; /* size of file (uncompressed) */ + zip_uint64_t comp_size; /* size of file (compressed) */ + time_t mtime; /* modification time */ + zip_uint32_t crc; /* crc of file data */ + zip_uint16_t comp_method; /* compression method used */ + zip_uint16_t encryption_method; /* encryption method used */ + zip_uint32_t flags; /* reserved for future use */ +}; + +struct zip_buffer_fragment { + zip_uint8_t *_Nonnull data; + zip_uint64_t length; +}; + +struct zip_file_attributes { + zip_uint64_t valid; /* which fields have valid values */ + zip_uint8_t version; /* version of this struct, currently 1 */ + zip_uint8_t host_system; /* host system on which file was created */ + zip_uint8_t ascii; /* flag whether file is ASCII text */ + zip_uint8_t version_needed; /* minimum version needed to extract file */ + zip_uint32_t external_file_attributes; /* external file attributes (host-system specific) */ + zip_uint16_t general_purpose_bit_flags; /* general purpose big flags, only some bits are honored */ + zip_uint16_t general_purpose_bit_mask; /* which bits in general_purpose_bit_flags are valid */ +}; + +#define ZIP_FILE_ATTRIBUTES_HOST_SYSTEM 0x0001u +#define ZIP_FILE_ATTRIBUTES_ASCII 0x0002u +#define ZIP_FILE_ATTRIBUTES_VERSION_NEEDED 0x0004u +#define ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES 0x0008u +#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS 0x0010u + +struct zip; +struct zip_file; +struct zip_source; + +typedef struct zip zip_t; +typedef struct zip_error zip_error_t; +typedef struct zip_file zip_file_t; +typedef struct zip_file_attributes zip_file_attributes_t; +typedef struct zip_source zip_source_t; +typedef struct zip_stat zip_stat_t; +typedef struct zip_buffer_fragment zip_buffer_fragment_t; + +typedef zip_uint32_t zip_flags_t; + +typedef zip_int64_t (*zip_source_callback)(void *_Nullable, void *_Nullable, zip_uint64_t, zip_source_cmd_t); +typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *_Nonnull, void *_Nullable, void *_Nullable, zip_uint64_t, enum zip_source_cmd); +typedef void (*zip_progress_callback)(zip_t *_Nonnull, double, void *_Nullable); +typedef int (*zip_cancel_callback)(zip_t *_Nonnull, void *_Nullable); + +#ifndef ZIP_DISABLE_DEPRECATED +#define ZIP_FL_RECOMPRESS 16u /* force recompression of data */ + +typedef void (*zip_progress_callback_t)(double); +ZIP_DEPRECATED("use 'zip_register_progress_callback_with_state' instead") ZIP_EXTERN void zip_register_progress_callback(zip_t *_Nonnull, zip_progress_callback_t _Nullable); + +ZIP_DEPRECATED("use 'zip_file_add' instead") ZIP_EXTERN zip_int64_t zip_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull); +ZIP_DEPRECATED("use 'zip_dir_add' instead") ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *_Nonnull, const char *_Nonnull); +ZIP_DEPRECATED("use 'zip_file_get_comment' instead") ZIP_EXTERN const char *_Nullable zip_get_file_comment(zip_t *_Nonnull, zip_uint64_t, int *_Nullable, int); +ZIP_DEPRECATED("use 'zip_get_num_entries' instead") ZIP_EXTERN int zip_get_num_files(zip_t *_Nonnull); +ZIP_DEPRECATED("use 'zip_file_rename' instead") ZIP_EXTERN int zip_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull); +ZIP_DEPRECATED("use 'zip_file_replace' instead") ZIP_EXTERN int zip_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull); +ZIP_DEPRECATED("use 'zip_file_set_comment' instead") ZIP_EXTERN int zip_set_file_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, int); +ZIP_DEPRECATED("use 'zip_error_init_with_code' and 'zip_error_system_type' instead") ZIP_EXTERN int zip_error_get_sys_type(int); +ZIP_DEPRECATED("use 'zip_get_error' instead") ZIP_EXTERN void zip_error_get(zip_t *_Nonnull, int *_Nullable, int *_Nullable); +ZIP_DEPRECATED("use 'zip_error_strerror' instead") ZIP_EXTERN int zip_error_to_str(char *_Nonnull, zip_uint64_t, int, int); +ZIP_DEPRECATED("use 'zip_file_get_error' instead") ZIP_EXTERN void zip_file_error_get(zip_file_t *_Nonnull, int *_Nullable, int *_Nullable); +ZIP_DEPRECATED("use 'zip_source_zip_file' instead") ZIP_EXTERN zip_source_t *_Nullable zip_source_zip(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t); +ZIP_DEPRECATED("use 'zip_source_zip_file_create' instead") ZIP_EXTERN zip_source_t *_Nullable zip_source_zip_create(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable); +#endif + +ZIP_EXTERN int zip_close(zip_t *_Nonnull); +ZIP_EXTERN int zip_delete(zip_t *_Nonnull, zip_uint64_t); +ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t); +ZIP_EXTERN void zip_discard(zip_t *_Nonnull); + +ZIP_EXTERN zip_error_t *_Nonnull zip_get_error(zip_t *_Nonnull); +ZIP_EXTERN void zip_error_clear(zip_t *_Nonnull); +ZIP_EXTERN int zip_error_code_zip(const zip_error_t *_Nonnull); +ZIP_EXTERN int zip_error_code_system(const zip_error_t *_Nonnull); +ZIP_EXTERN void zip_error_fini(zip_error_t *_Nonnull); +ZIP_EXTERN void zip_error_init(zip_error_t *_Nonnull); +ZIP_EXTERN void zip_error_init_with_code(zip_error_t *_Nonnull, int); +ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int); +ZIP_EXTERN void zip_error_set_from_source(zip_error_t *_Nonnull, zip_source_t *_Nullable); +ZIP_EXTERN const char *_Nonnull zip_error_strerror(zip_error_t *_Nonnull); +ZIP_EXTERN int zip_error_system_type(const zip_error_t *_Nonnull); +ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *_Nonnull, void *_Nonnull, zip_uint64_t); + +ZIP_EXTERN int zip_fclose(zip_file_t *_Nonnull); +ZIP_EXTERN zip_t *_Nullable zip_fdopen(int, int, int *_Nullable); +ZIP_EXTERN zip_int64_t zip_file_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull, zip_flags_t); +ZIP_EXTERN void zip_file_attributes_init(zip_file_attributes_t *_Nonnull); +ZIP_EXTERN void zip_file_error_clear(zip_file_t *_Nonnull); +ZIP_EXTERN int zip_file_extra_field_delete(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_extra_field_set(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *_Nullable, zip_uint16_t, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(zip_t *_Nonnull, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_uint16_t *_Nullable, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_flags_t); +ZIP_EXTERN const char *_Nullable zip_file_get_comment(zip_t *_Nonnull, zip_uint64_t, zip_uint32_t *_Nullable, zip_flags_t); +ZIP_EXTERN zip_error_t *_Nonnull zip_file_get_error(zip_file_t *_Nonnull); +ZIP_EXTERN int zip_file_get_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t *_Nullable, zip_uint32_t *_Nullable); +ZIP_EXTERN int zip_file_is_seekable(zip_file_t *_Nonnull); +ZIP_EXTERN int zip_file_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull, zip_flags_t); +ZIP_EXTERN int zip_file_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull, zip_flags_t); +ZIP_EXTERN int zip_file_set_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_set_dostime(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_set_encryption(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, const char *_Nullable); +ZIP_EXTERN int zip_file_set_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t); +ZIP_EXTERN int zip_file_set_mtime(zip_t *_Nonnull, zip_uint64_t, time_t, zip_flags_t); +ZIP_EXTERN const char *_Nonnull zip_file_strerror(zip_file_t *_Nonnull); +ZIP_EXTERN zip_file_t *_Nullable zip_fopen(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t); +ZIP_EXTERN zip_file_t *_Nullable zip_fopen_encrypted(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, const char *_Nullable); +ZIP_EXTERN zip_file_t *_Nullable zip_fopen_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_file_t *_Nullable zip_fopen_index_encrypted(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, const char *_Nullable); +ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *_Nonnull, void *_Nonnull, zip_uint64_t); +ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *_Nonnull, zip_int64_t, int); +ZIP_EXTERN zip_int64_t zip_ftell(zip_file_t *_Nonnull); +ZIP_EXTERN const char *_Nullable zip_get_archive_comment(zip_t *_Nonnull, int *_Nullable, zip_flags_t); +ZIP_EXTERN int zip_get_archive_flag(zip_t *_Nonnull, zip_flags_t, zip_flags_t); +ZIP_EXTERN const char *_Nullable zip_get_name(zip_t *_Nonnull, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *_Nonnull, zip_flags_t); +ZIP_EXTERN const char *_Nonnull zip_libzip_version(void); +ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t); +ZIP_EXTERN zip_t *_Nullable zip_open(const char *_Nonnull, int, int *_Nullable); +ZIP_EXTERN zip_t *_Nullable zip_open_from_source(zip_source_t *_Nonnull, int, zip_error_t *_Nullable); +ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *_Nonnull, double, zip_progress_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable); +ZIP_EXTERN int zip_register_cancel_callback_with_state(zip_t *_Nonnull, zip_cancel_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable); +ZIP_EXTERN int zip_set_archive_comment(zip_t *_Nonnull, const char *_Nullable, zip_uint16_t); +ZIP_EXTERN int zip_set_archive_flag(zip_t *_Nonnull, zip_flags_t, int); +ZIP_EXTERN int zip_set_default_password(zip_t *_Nonnull, const char *_Nullable); +ZIP_EXTERN int zip_set_file_compression(zip_t *_Nonnull, zip_uint64_t, zip_int32_t, zip_uint32_t); +ZIP_EXTERN int zip_source_begin_write(zip_source_t *_Nonnull); +ZIP_EXTERN int zip_source_begin_write_cloning(zip_source_t *_Nonnull, zip_uint64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer(zip_t *_Nonnull, const void *_Nullable, zip_uint64_t, int); +ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_create(const void *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_fragment(zip_t *_Nonnull, const zip_buffer_fragment_t *_Nonnull, zip_uint64_t, int); +ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_fragment_create(const zip_buffer_fragment_t *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable); +ZIP_EXTERN int zip_source_close(zip_source_t *_Nonnull); +ZIP_EXTERN int zip_source_commit_write(zip_source_t *_Nonnull); +ZIP_EXTERN zip_error_t *_Nonnull zip_source_error(zip_source_t *_Nonnull); +ZIP_EXTERN zip_source_t *_Nullable zip_source_file(zip_t *_Nonnull, const char *_Nonnull, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_file_create(const char *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_filep(zip_t *_Nonnull, FILE *_Nonnull, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_filep_create(FILE *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable); +ZIP_EXTERN void zip_source_free(zip_source_t *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_function(zip_t *_Nonnull, zip_source_callback _Nonnull, void *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_function_create(zip_source_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable); +ZIP_EXTERN int zip_source_get_file_attributes(zip_source_t *_Nonnull, zip_file_attributes_t *_Nonnull); +ZIP_EXTERN int zip_source_is_deleted(zip_source_t *_Nonnull); +ZIP_EXTERN int zip_source_is_seekable(zip_source_t *_Nonnull); +ZIP_EXTERN void zip_source_keep(zip_source_t *_Nonnull); +ZIP_EXTERN zip_source_t *_Nullable zip_source_layered(zip_t *_Nullable, zip_source_t *_Nonnull, zip_source_layered_callback _Nonnull, void *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_layered_create(zip_source_t *_Nonnull, zip_source_layered_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable); +ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t, ...); +ZIP_EXTERN int zip_source_open(zip_source_t *_Nonnull); +ZIP_EXTERN zip_int64_t zip_source_pass_to_lower_layer(zip_source_t *_Nonnull, void *_Nullable, zip_uint64_t, zip_source_cmd_t); +ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *_Nonnull, void *_Nonnull, zip_uint64_t); +ZIP_EXTERN void zip_source_rollback_write(zip_source_t *_Nonnull); +ZIP_EXTERN int zip_source_seek(zip_source_t *_Nonnull, zip_int64_t, int); +ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *_Nonnull, zip_uint64_t, zip_error_t *_Nullable); +ZIP_EXTERN int zip_source_seek_write(zip_source_t *_Nonnull, zip_int64_t, int); +ZIP_EXTERN int zip_source_stat(zip_source_t *_Nonnull, zip_stat_t *_Nonnull); +ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *_Nonnull); +ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *_Nonnull); +#ifdef _WIN32 +ZIP_EXTERN zip_source_t *_Nullable zip_source_win32a(zip_t *_Nonnull, const char *_Nonnull, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_win32a_create(const char *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_win32handle(zip_t *_Nonnull, void *_Nonnull, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_win32handle_create(void *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_win32w(zip_t *_Nonnull, const wchar_t *_Nonnull, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_win32w_create(const wchar_t *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable); +#endif +ZIP_EXTERN zip_source_t *_Nullable zip_source_window_create(zip_source_t *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable); +ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *_Nonnull, const void *_Nullable, zip_uint64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_zip_file(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, const char *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_zip_file_create(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, const char *_Nullable, zip_error_t *_Nullable); +ZIP_EXTERN int zip_stat(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, zip_stat_t *_Nonnull); +ZIP_EXTERN int zip_stat_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_stat_t *_Nonnull); +ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull); +ZIP_EXTERN const char *_Nonnull zip_strerror(zip_t *_Nonnull); +ZIP_EXTERN int zip_unchange(zip_t *_Nonnull, zip_uint64_t); +ZIP_EXTERN int zip_unchange_all(zip_t *_Nonnull); +ZIP_EXTERN int zip_unchange_archive(zip_t *_Nonnull); +ZIP_EXTERN int zip_compression_method_supported(zip_int32_t method, int compress); +ZIP_EXTERN int zip_encryption_method_supported(zip_uint16_t method, int encode); + +#ifdef __cplusplus +} +#endif + +#endif /* _HAD_ZIP_H */ diff --git a/3rdparty/libzip/lib/zip_add.c b/3rdparty/libzip/lib/zip_add.c new file mode 100644 index 0000000000..9770139d66 --- /dev/null +++ b/3rdparty/libzip/lib/zip_add.c @@ -0,0 +1,49 @@ +/* + zip_add.c -- add file via callback function + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +/* + NOTE: Return type is signed so we can return -1 on error. + The index can not be larger than ZIP_INT64_MAX since the size + of the central directory cannot be larger than + ZIP_UINT64_MAX, and each entry is larger than 2 bytes. +*/ + +ZIP_EXTERN zip_int64_t +zip_add(zip_t *za, const char *name, zip_source_t *source) { + return zip_file_add(za, name, source, 0); +} diff --git a/3rdparty/libzip/lib/zip_add_dir.c b/3rdparty/libzip/lib/zip_add_dir.c new file mode 100644 index 0000000000..c31fea365a --- /dev/null +++ b/3rdparty/libzip/lib/zip_add_dir.c @@ -0,0 +1,44 @@ +/* + zip_add_dir.c -- add directory + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +ZIP_EXTERN zip_int64_t +zip_add_dir(zip_t *za, const char *name) { + return zip_dir_add(za, name, 0); +} diff --git a/3rdparty/libzip/lib/zip_add_entry.c b/3rdparty/libzip/lib/zip_add_entry.c new file mode 100644 index 0000000000..bf12dd5417 --- /dev/null +++ b/3rdparty/libzip/lib/zip_add_entry.c @@ -0,0 +1,80 @@ +/* + zip_add_entry.c -- create and init struct zip_entry + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +zip_int64_t +_zip_add_entry(zip_t *za) { + zip_uint64_t idx; + + if (za->nentry + 1 >= za->nentry_alloc) { + zip_entry_t *rentries; + zip_uint64_t nalloc = za->nentry_alloc; + zip_uint64_t additional_entries = 2 * nalloc; + zip_uint64_t realloc_size; + + if (additional_entries < 16) { + additional_entries = 16; + } + else if (additional_entries > 1024) { + additional_entries = 1024; + } + /* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */ + nalloc += additional_entries; + realloc_size = sizeof(struct zip_entry) * (size_t)nalloc; + + if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc); + if (!rentries) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + za->entry = rentries; + za->nentry_alloc = nalloc; + } + + idx = za->nentry++; + + _zip_entry_init(za->entry + idx); + + return (zip_int64_t)idx; +} diff --git a/3rdparty/libzip/lib/zip_algorithm_bzip2.c b/3rdparty/libzip/lib/zip_algorithm_bzip2.c new file mode 100644 index 0000000000..f25be1438b --- /dev/null +++ b/3rdparty/libzip/lib/zip_algorithm_bzip2.c @@ -0,0 +1,293 @@ +/* + zip_algorithm_bzip2.c -- bzip2 (de)compression routines + Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include +#include +#include + +struct ctx { + zip_error_t *error; + bool compress; + int compression_flags; + bool end_of_input; + bz_stream zstr; +}; + + +static zip_uint64_t +maximum_compressed_size(zip_uint64_t uncompressed_size) { + zip_uint64_t compressed_size = (zip_uint64_t)((double)uncompressed_size * 1.006); + + if (compressed_size < uncompressed_size) { + return ZIP_UINT64_MAX; + } + return compressed_size; +} + + +static void * +allocate(bool compress, zip_uint32_t compression_flags, zip_error_t *error) { + struct ctx *ctx; + + if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) { + return NULL; + } + + ctx->error = error; + ctx->compress = compress; + if (compression_flags >= 1 && compression_flags <= 9) { + ctx->compression_flags = (int)compression_flags; + } + else { + ctx->compression_flags = 9; + } + ctx->end_of_input = false; + + ctx->zstr.bzalloc = NULL; + ctx->zstr.bzfree = NULL; + ctx->zstr.opaque = NULL; + + return ctx; +} + + +static void * +compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) { + (void)method; + return allocate(true, compression_flags, error); +} + + +static void * +decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) { + (void)method; + return allocate(false, compression_flags, error); +} + + +static void +deallocate(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + free(ctx); +} + + +static zip_uint16_t +general_purpose_bit_flags(void *ud) { + (void)ud; + return 0; +} + + +static int +map_error(int ret) { + switch (ret) { + case BZ_FINISH_OK: + case BZ_FLUSH_OK: + case BZ_OK: + case BZ_RUN_OK: + case BZ_STREAM_END: + return ZIP_ER_OK; + + case BZ_DATA_ERROR: + case BZ_DATA_ERROR_MAGIC: + case BZ_UNEXPECTED_EOF: + return ZIP_ER_COMPRESSED_DATA; + + case BZ_MEM_ERROR: + return ZIP_ER_MEMORY; + + case BZ_PARAM_ERROR: + return ZIP_ER_INVAL; + + case BZ_CONFIG_ERROR: /* actually, bzip2 miscompiled */ + case BZ_IO_ERROR: + case BZ_OUTBUFF_FULL: + case BZ_SEQUENCE_ERROR: + default: + return ZIP_ER_INTERNAL; + } +} + +static bool +start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) { + struct ctx *ctx = (struct ctx *)ud; + int ret; + + (void)st; + (void)attributes; + + ctx->zstr.avail_in = 0; + ctx->zstr.next_in = NULL; + ctx->zstr.avail_out = 0; + ctx->zstr.next_out = NULL; + + if (ctx->compress) { + ret = BZ2_bzCompressInit(&ctx->zstr, ctx->compression_flags, 0, 30); + } + else { + ret = BZ2_bzDecompressInit(&ctx->zstr, 0, 0); + } + + if (ret != BZ_OK) { + zip_error_set(ctx->error, map_error(ret), 0); + return false; + } + + return true; +} + + +static bool +end(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + int err; + + if (ctx->compress) { + err = BZ2_bzCompressEnd(&ctx->zstr); + } + else { + err = BZ2_bzDecompressEnd(&ctx->zstr); + } + + if (err != BZ_OK) { + zip_error_set(ctx->error, map_error(err), 0); + return false; + } + + return true; +} + + +static bool +input(void *ud, zip_uint8_t *data, zip_uint64_t length) { + struct ctx *ctx = (struct ctx *)ud; + + if (length > UINT_MAX || ctx->zstr.avail_in > 0) { + zip_error_set(ctx->error, ZIP_ER_INVAL, 0); + return false; + } + + ctx->zstr.avail_in = (unsigned int)length; + ctx->zstr.next_in = (char *)data; + + return true; +} + + +static void +end_of_input(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + ctx->end_of_input = true; +} + + +static zip_compression_status_t +process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { + struct ctx *ctx = (struct ctx *)ud; + unsigned int avail_out; + + int ret; + + if (ctx->zstr.avail_in == 0 && !ctx->end_of_input) { + *length = 0; + return ZIP_COMPRESSION_NEED_DATA; + } + + avail_out = (unsigned int)ZIP_MIN(UINT_MAX, *length); + ctx->zstr.avail_out = avail_out; + ctx->zstr.next_out = (char *)data; + + if (ctx->compress) { + ret = BZ2_bzCompress(&ctx->zstr, ctx->end_of_input ? BZ_FINISH : BZ_RUN); + } + else { + ret = BZ2_bzDecompress(&ctx->zstr); + } + + *length = avail_out - ctx->zstr.avail_out; + + switch (ret) { + case BZ_FINISH_OK: /* compression */ + return ZIP_COMPRESSION_OK; + + case BZ_OK: /* decompression */ + case BZ_RUN_OK: /* compression */ + if (ctx->zstr.avail_in == 0) { + return ZIP_COMPRESSION_NEED_DATA; + } + return ZIP_COMPRESSION_OK; + + case BZ_STREAM_END: + return ZIP_COMPRESSION_END; + + default: + zip_error_set(ctx->error, map_error(ret), 0); + return ZIP_COMPRESSION_ERROR; + } +} + +/* clang-format off */ + +zip_compression_algorithm_t zip_algorithm_bzip2_compress = { + maximum_compressed_size, + compress_allocate, + deallocate, + general_purpose_bit_flags, + 46, + start, + end, + input, + end_of_input, + process +}; + + +zip_compression_algorithm_t zip_algorithm_bzip2_decompress = { + maximum_compressed_size, + decompress_allocate, + deallocate, + general_purpose_bit_flags, + 46, + start, + end, + input, + end_of_input, + process +}; + +/* clang-format on */ diff --git a/3rdparty/libzip/lib/zip_algorithm_deflate.c b/3rdparty/libzip/lib/zip_algorithm_deflate.c new file mode 100644 index 0000000000..3c85e2045b --- /dev/null +++ b/3rdparty/libzip/lib/zip_algorithm_deflate.c @@ -0,0 +1,276 @@ +/* + zip_algorithm_deflate.c -- deflate (de)compression routines + Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include +#include +#include + +struct ctx { + zip_error_t *error; + bool compress; + int level; + int mem_level; + bool end_of_input; + z_stream zstr; +}; + + +static zip_uint64_t +maximum_compressed_size(zip_uint64_t uncompressed_size) { + /* max deflate size increase: size + ceil(size/16k)*5+6 */ + + zip_uint64_t compressed_size = uncompressed_size + (uncompressed_size + 16383) / 16384 * 5 + 6; + + if (compressed_size < uncompressed_size) { + return ZIP_UINT64_MAX; + } + return compressed_size; +} + + +static void * +allocate(bool compress, zip_uint32_t compression_flags, zip_error_t *error) { + struct ctx *ctx; + + if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ET_SYS, errno); + return NULL; + } + + ctx->error = error; + ctx->compress = compress; + if (compression_flags >= 1 && compression_flags <= 9) { + ctx->level = (int)compression_flags; + } + else { + ctx->level = Z_BEST_COMPRESSION; + } + ctx->mem_level = compression_flags == TORRENTZIP_COMPRESSION_FLAGS ? TORRENTZIP_MEM_LEVEL : MAX_MEM_LEVEL; + ctx->end_of_input = false; + + ctx->zstr.zalloc = Z_NULL; + ctx->zstr.zfree = Z_NULL; + ctx->zstr.opaque = NULL; + + return ctx; +} + + +static void * +compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) { + (void)method; + return allocate(true, compression_flags, error); +} + + +static void * +decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) { + (void)method; + return allocate(false, compression_flags, error); +} + + +static void +deallocate(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + free(ctx); +} + + +static zip_uint16_t +general_purpose_bit_flags(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + if (!ctx->compress) { + return 0; + } + + if (ctx->level < 3) { + return 2 << 1; + } + else if (ctx->level > 7) { + return 1 << 1; + } + return 0; +} + + +static bool +start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) { + struct ctx *ctx = (struct ctx *)ud; + int ret; + + (void)st; + (void)attributes; + + ctx->zstr.avail_in = 0; + ctx->zstr.next_in = NULL; + ctx->zstr.avail_out = 0; + ctx->zstr.next_out = NULL; + + if (ctx->compress) { + /* negative value to tell zlib not to write a header */ + ret = deflateInit2(&ctx->zstr, ctx->level, Z_DEFLATED, -MAX_WBITS, ctx->mem_level, Z_DEFAULT_STRATEGY); + } + else { + ret = inflateInit2(&ctx->zstr, -MAX_WBITS); + } + + if (ret != Z_OK) { + zip_error_set(ctx->error, ZIP_ER_ZLIB, ret); + return false; + } + + + return true; +} + + +static bool +end(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + int err; + + if (ctx->compress) { + err = deflateEnd(&ctx->zstr); + } + else { + err = inflateEnd(&ctx->zstr); + } + + if (err != Z_OK) { + zip_error_set(ctx->error, ZIP_ER_ZLIB, err); + return false; + } + + return true; +} + + +static bool +input(void *ud, zip_uint8_t *data, zip_uint64_t length) { + struct ctx *ctx = (struct ctx *)ud; + + if (length > UINT_MAX || ctx->zstr.avail_in > 0) { + zip_error_set(ctx->error, ZIP_ER_INVAL, 0); + return false; + } + + ctx->zstr.avail_in = (uInt)length; + ctx->zstr.next_in = (Bytef *)data; + + return true; +} + + +static void +end_of_input(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + ctx->end_of_input = true; +} + + +static zip_compression_status_t +process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { + struct ctx *ctx = (struct ctx *)ud; + uInt avail_out; + + int ret; + + avail_out = (uInt)ZIP_MIN(UINT_MAX, *length); + ctx->zstr.avail_out = avail_out; + ctx->zstr.next_out = (Bytef *)data; + + if (ctx->compress) { + ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0); + } + else { + ret = inflate(&ctx->zstr, Z_SYNC_FLUSH); + } + + *length = avail_out - ctx->zstr.avail_out; + + switch (ret) { + case Z_OK: + return ZIP_COMPRESSION_OK; + + case Z_STREAM_END: + return ZIP_COMPRESSION_END; + + case Z_BUF_ERROR: + if (ctx->zstr.avail_in == 0) { + return ZIP_COMPRESSION_NEED_DATA; + } + + /* fallthrough */ + + default: + zip_error_set(ctx->error, ZIP_ER_ZLIB, ret); + return ZIP_COMPRESSION_ERROR; + } +} + +/* clang-format off */ + +zip_compression_algorithm_t zip_algorithm_deflate_compress = { + maximum_compressed_size, + compress_allocate, + deallocate, + general_purpose_bit_flags, + 20, + start, + end, + input, + end_of_input, + process +}; + + +zip_compression_algorithm_t zip_algorithm_deflate_decompress = { + maximum_compressed_size, + decompress_allocate, + deallocate, + general_purpose_bit_flags, + 20, + start, + end, + input, + end_of_input, + process +}; + +/* clang-format on */ diff --git a/3rdparty/libzip/lib/zip_algorithm_xz.c b/3rdparty/libzip/lib/zip_algorithm_xz.c new file mode 100644 index 0000000000..d7a7142d46 --- /dev/null +++ b/3rdparty/libzip/lib/zip_algorithm_xz.c @@ -0,0 +1,408 @@ +/* + zip_algorithm_xz.c -- LZMA/XZ (de)compression routines + Bazed on zip_algorithm_deflate.c -- deflate (de)compression routines + Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include +#include +#include +#include + +enum header_state { INCOMPLETE, OUTPUT, DONE }; + +#define HEADER_BYTES_ZIP 9 +#define HEADER_MAGIC_LENGTH 4 +#define HEADER_MAGIC1_OFFSET 0 +#define HEADER_MAGIC2_OFFSET 2 +#define HEADER_SIZE_OFFSET 9 +#define HEADER_SIZE_LENGTH 8 +#define HEADER_PARAMETERS_LENGTH 5 +#define HEADER_LZMA_ALONE_LENGTH (HEADER_PARAMETERS_LENGTH + HEADER_SIZE_LENGTH) + +struct ctx { + zip_error_t *error; + bool compress; + zip_uint32_t compression_flags; + bool end_of_input; + lzma_stream zstr; + zip_uint16_t method; + /* header member is used for converting from zip to "lzma alone" + * format + * + * "lzma alone" file format starts with: + * 5 bytes lzma parameters + * 8 bytes uncompressed size + * compressed data + * + * zip archive on-disk format starts with + * 4 bytes magic (first two bytes vary, e.g. 0x0914 or 0x1002, next bytes are 0x0500) + * 5 bytes lzma parameters + * compressed data + * + * we read the data into a header of the form + * 4 bytes magic + * 5 bytes lzma parameters + * 8 bytes uncompressed size + */ + zip_uint8_t header[HEADER_MAGIC_LENGTH + HEADER_LZMA_ALONE_LENGTH]; + zip_uint8_t header_bytes_offset; + enum header_state header_state; + zip_uint64_t uncompresssed_size; +}; + + +static zip_uint64_t +maximum_compressed_size(zip_uint64_t uncompressed_size) { + /* + According to https://sourceforge.net/p/sevenzip/discussion/45797/thread/b6bd62f8/ + + 1) you can use + outSize = 1.10 * originalSize + 64 KB. + in most cases outSize is less then 1.02 from originalSize. + 2) You can try LZMA2, where + outSize can be = 1.001 * originalSize + 1 KB. + */ + /* 13 bytes added for lzma alone header */ + zip_uint64_t compressed_size = (zip_uint64_t)((double)uncompressed_size * 1.1) + 64 * 1024 + 13; + + if (compressed_size < uncompressed_size) { + return ZIP_UINT64_MAX; + } + return compressed_size; +} + + +static void * +allocate(bool compress, zip_uint32_t compression_flags, zip_error_t *error, zip_uint16_t method) { + struct ctx *ctx; + + if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->error = error; + ctx->compress = compress; + if (compression_flags <= 9) { + ctx->compression_flags = compression_flags; + } else { + ctx->compression_flags = 6; /* default value */ + } + ctx->compression_flags |= LZMA_PRESET_EXTREME; + ctx->end_of_input = false; + memset(ctx->header, 0, sizeof(ctx->header)); + ctx->header_bytes_offset = 0; + if (method == ZIP_CM_LZMA) { + ctx->header_state = INCOMPLETE; + } + else { + ctx->header_state = DONE; + } + memset(&ctx->zstr, 0, sizeof(ctx->zstr)); + ctx->method = method; + return ctx; +} + + +static void * +compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) { + return allocate(true, compression_flags, error, method); +} + + +static void * +decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) { + return allocate(false, compression_flags, error, method); +} + + +static void +deallocate(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + free(ctx); +} + + +static zip_uint16_t +general_purpose_bit_flags(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + if (!ctx->compress) { + return 0; + } + + if (ctx->method == ZIP_CM_LZMA) { + /* liblzma always returns an EOS/EOPM marker, see + * https://sourceforge.net/p/lzmautils/discussion/708858/thread/84c5dbb9/#a5e4/3764 */ + return 1 << 1; + } + return 0; +} + +static int +map_error(lzma_ret ret) { + switch (ret) { + case LZMA_DATA_ERROR: + case LZMA_UNSUPPORTED_CHECK: + return ZIP_ER_COMPRESSED_DATA; + + case LZMA_MEM_ERROR: + return ZIP_ER_MEMORY; + + case LZMA_OPTIONS_ERROR: + return ZIP_ER_INVAL; + + default: + return ZIP_ER_INTERNAL; + } +} + + +static bool +start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) { + struct ctx *ctx = (struct ctx *)ud; + lzma_ret ret; + + lzma_options_lzma opt_lzma; + lzma_lzma_preset(&opt_lzma, ctx->compression_flags); + lzma_filter filters[] = { + {.id = (ctx->method == ZIP_CM_LZMA ? LZMA_FILTER_LZMA1 : LZMA_FILTER_LZMA2), .options = &opt_lzma}, + {.id = LZMA_VLI_UNKNOWN, .options = NULL}, + }; + + ctx->zstr.avail_in = 0; + ctx->zstr.next_in = NULL; + ctx->zstr.avail_out = 0; + ctx->zstr.next_out = NULL; + + if (ctx->compress) { + if (ctx->method == ZIP_CM_LZMA) + ret = lzma_alone_encoder(&ctx->zstr, filters[0].options); + else + ret = lzma_stream_encoder(&ctx->zstr, filters, LZMA_CHECK_CRC64); + } + else { + if (ctx->method == ZIP_CM_LZMA) + ret = lzma_alone_decoder(&ctx->zstr, UINT64_MAX); + else + ret = lzma_stream_decoder(&ctx->zstr, UINT64_MAX, LZMA_CONCATENATED); + } + + if (ret != LZMA_OK) { + zip_error_set(ctx->error, map_error(ret), 0); + return false; + } + + /* If general purpose bits 1 & 2 are both zero, write real uncompressed size in header. */ + if ((attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) && (attributes->general_purpose_bit_mask & 0x6) == 0x6 && (attributes->general_purpose_bit_flags & 0x06) == 0 && (st->valid & ZIP_STAT_SIZE)) { + ctx->uncompresssed_size = st->size; + } + else { + ctx->uncompresssed_size = ZIP_UINT64_MAX; + } + + return true; +} + + +static bool +end(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + lzma_end(&ctx->zstr); + return true; +} + + +static bool +input(void *ud, zip_uint8_t *data, zip_uint64_t length) { + struct ctx *ctx = (struct ctx *)ud; + + if (length > UINT_MAX || ctx->zstr.avail_in > 0) { + zip_error_set(ctx->error, ZIP_ER_INVAL, 0); + return false; + } + + /* For decompression of LZMA1: Have we read the full "lzma alone" header yet? */ + if (ctx->method == ZIP_CM_LZMA && !ctx->compress && ctx->header_state == INCOMPLETE) { + /* if not, get more of the data */ + zip_uint8_t got = (zip_uint8_t)ZIP_MIN(HEADER_BYTES_ZIP - ctx->header_bytes_offset, length); + (void)memcpy_s(ctx->header + ctx->header_bytes_offset, sizeof(ctx->header) - ctx->header_bytes_offset, data, got); + ctx->header_bytes_offset += got; + length -= got; + data += got; + /* Do we have a complete header now? */ + if (ctx->header_bytes_offset == HEADER_BYTES_ZIP) { + Bytef empty_buffer[1]; + zip_buffer_t *buffer; + /* check magic */ + if (ctx->header[HEADER_MAGIC2_OFFSET] != 0x05 || ctx->header[HEADER_MAGIC2_OFFSET + 1] != 0x00) { + /* magic does not match */ + zip_error_set(ctx->error, ZIP_ER_COMPRESSED_DATA, 0); + return false; + } + /* set size of uncompressed data in "lzma alone" header to "unknown" */ + if ((buffer = _zip_buffer_new(ctx->header + HEADER_SIZE_OFFSET, HEADER_SIZE_LENGTH)) == NULL) { + zip_error_set(ctx->error, ZIP_ER_MEMORY, 0); + return false; + } + _zip_buffer_put_64(buffer, ctx->uncompresssed_size); + _zip_buffer_free(buffer); + /* Feed header into "lzma alone" decoder, for + * initialization; this should not produce output. */ + ctx->zstr.next_in = (void *)(ctx->header + HEADER_MAGIC_LENGTH); + ctx->zstr.avail_in = HEADER_LZMA_ALONE_LENGTH; + ctx->zstr.total_in = 0; + ctx->zstr.next_out = empty_buffer; + ctx->zstr.avail_out = sizeof(*empty_buffer); + ctx->zstr.total_out = 0; + /* this just initializes the decoder and does not produce output, so it consumes the complete header */ + if (lzma_code(&ctx->zstr, LZMA_RUN) != LZMA_OK || ctx->zstr.total_out > 0) { + zip_error_set(ctx->error, ZIP_ER_COMPRESSED_DATA, 0); + return false; + } + ctx->header_state = DONE; + } + } + ctx->zstr.avail_in = (uInt)length; + ctx->zstr.next_in = (Bytef *)data; + + return true; +} + + +static void +end_of_input(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + ctx->end_of_input = true; +} + + +static zip_compression_status_t +process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { + struct ctx *ctx = (struct ctx *)ud; + uInt avail_out; + lzma_ret ret; + /* for compression of LZMA1 */ + if (ctx->method == ZIP_CM_LZMA && ctx->compress) { + if (ctx->header_state == INCOMPLETE) { + /* write magic to output buffer */ + ctx->header[0] = 0x09; + ctx->header[1] = 0x14; + ctx->header[2] = 0x05; + ctx->header[3] = 0x00; + /* generate lzma parameters into output buffer */ + ctx->zstr.avail_out = HEADER_LZMA_ALONE_LENGTH; + ctx->zstr.next_out = ctx->header + HEADER_MAGIC_LENGTH; + ret = lzma_code(&ctx->zstr, LZMA_RUN); + if (ret != LZMA_OK || ctx->zstr.avail_out != 0) { + /* assume that the whole header will be provided with the first call to lzma_code */ + return ZIP_COMPRESSION_ERROR; + } + ctx->header_state = OUTPUT; + } + if (ctx->header_state == OUTPUT) { + /* write header */ + zip_uint8_t write_len = (zip_uint8_t)ZIP_MIN(HEADER_BYTES_ZIP - ctx->header_bytes_offset, *length); + (void)memcpy_s(data, *length, ctx->header + ctx->header_bytes_offset, write_len); + ctx->header_bytes_offset += write_len; + *length = write_len; + if (ctx->header_bytes_offset == HEADER_BYTES_ZIP) { + ctx->header_state = DONE; + } + return ZIP_COMPRESSION_OK; + } + } + + avail_out = (uInt)ZIP_MIN(UINT_MAX, *length); + ctx->zstr.avail_out = avail_out; + ctx->zstr.next_out = (Bytef *)data; + + ret = lzma_code(&ctx->zstr, ctx->end_of_input ? LZMA_FINISH : LZMA_RUN); + *length = avail_out - ctx->zstr.avail_out; + + switch (ret) { + case LZMA_OK: + return ZIP_COMPRESSION_OK; + + case LZMA_STREAM_END: + return ZIP_COMPRESSION_END; + + case LZMA_BUF_ERROR: + if (ctx->zstr.avail_in == 0) { + return ZIP_COMPRESSION_NEED_DATA; + } + + /* fallthrough */ + default: + zip_error_set(ctx->error, map_error(ret), 0); + return ZIP_COMPRESSION_ERROR; + } +} + +/* Version Required should be set to 63 (6.3) because this compression + method was only defined in appnote.txt version 6.3.8, but Winzip + does not unpack it if the value is not 20. */ + +/* clang-format off */ + +zip_compression_algorithm_t zip_algorithm_xz_compress = { + maximum_compressed_size, + compress_allocate, + deallocate, + general_purpose_bit_flags, + 20, + start, + end, + input, + end_of_input, + process +}; + + +zip_compression_algorithm_t zip_algorithm_xz_decompress = { + maximum_compressed_size, + decompress_allocate, + deallocate, + general_purpose_bit_flags, + 20, + start, + end, + input, + end_of_input, + process +}; + +/* clang-format on */ diff --git a/3rdparty/libzip/lib/zip_algorithm_zstd.c b/3rdparty/libzip/lib/zip_algorithm_zstd.c new file mode 100644 index 0000000000..d005da9d52 --- /dev/null +++ b/3rdparty/libzip/lib/zip_algorithm_zstd.c @@ -0,0 +1,298 @@ +/* + zip_algorithm_zstd.c -- zstd (de)compression routines + Copyright (C) 2020-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include +#include +#include + +struct ctx { + zip_error_t *error; + bool compress; + int compression_flags; + bool end_of_input; + ZSTD_DStream *zdstream; + ZSTD_CStream *zcstream; + ZSTD_outBuffer out; + ZSTD_inBuffer in; +}; + +static zip_uint64_t +maximum_compressed_size(zip_uint64_t uncompressed_size) { + return ZSTD_compressBound(uncompressed_size); +} + + +static void * +allocate(bool compress, zip_uint32_t compression_flags, zip_error_t *error) { + struct ctx *ctx; + + if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) { + return NULL; + } + + ctx->compression_flags = (zip_int32_t)compression_flags; + if (ctx->compression_flags < ZSTD_minCLevel() || ctx->compression_flags > ZSTD_maxCLevel()) { + ctx->compression_flags = 0; /* let zstd choose */ + } + + ctx->error = error; + ctx->compress = compress; + ctx->end_of_input = false; + + ctx->zdstream = NULL; + ctx->zcstream = NULL; + ctx->in.src = NULL; + ctx->in.pos = 0; + ctx->in.size = 0; + ctx->out.dst = NULL; + ctx->out.pos = 0; + ctx->out.size = 0; + + return ctx; +} + + +static void * +compress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) { + (void)method; + return allocate(true, compression_flags, error); +} + + +static void * +decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) { + (void)method; + return allocate(false, compression_flags, error); +} + + +static void +deallocate(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + free(ctx); +} + + +static zip_uint16_t +general_purpose_bit_flags(void *ud) { + (void)ud; + return 0; +} + +static int +map_error(size_t ret) { + switch (ret) { + case ZSTD_error_no_error: + return ZIP_ER_OK; + + case ZSTD_error_corruption_detected: + case ZSTD_error_checksum_wrong: + case ZSTD_error_dictionary_corrupted: + case ZSTD_error_dictionary_wrong: + return ZIP_ER_COMPRESSED_DATA; + + case ZSTD_error_memory_allocation: + return ZIP_ER_MEMORY; + + case ZSTD_error_parameter_unsupported: + case ZSTD_error_parameter_outOfBound: + return ZIP_ER_INVAL; + + default: + return ZIP_ER_INTERNAL; + } +} + + +static bool +start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) { + struct ctx *ctx = (struct ctx *)ud; + + (void)st; + (void)attributes; + + ctx->in.src = NULL; + ctx->in.pos = 0; + ctx->in.size = 0; + ctx->out.dst = NULL; + ctx->out.pos = 0; + ctx->out.size = 0; + if (ctx->compress) { + size_t ret; + ctx->zcstream = ZSTD_createCStream(); + if (ctx->zcstream == NULL) { + zip_error_set(ctx->error, ZIP_ER_MEMORY, 0); + return false; + } + ret = ZSTD_initCStream(ctx->zcstream, ctx->compression_flags); + if (ZSTD_isError(ret)) { + zip_error_set(ctx->error, ZIP_ER_ZLIB, map_error(ret)); + return false; + } + } + else { + ctx->zdstream = ZSTD_createDStream(); + if (ctx->zdstream == NULL) { + zip_error_set(ctx->error, ZIP_ER_MEMORY, 0); + return false; + } + } + + return true; +} + + +static bool +end(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + size_t ret; + + if (ctx->compress) { + ret = ZSTD_freeCStream(ctx->zcstream); + ctx->zcstream = NULL; + } + else { + ret = ZSTD_freeDStream(ctx->zdstream); + ctx->zdstream = NULL; + } + + if (ZSTD_isError(ret)) { + zip_error_set(ctx->error, map_error(ret), 0); + return false; + } + + return true; +} + + +static bool +input(void *ud, zip_uint8_t *data, zip_uint64_t length) { + struct ctx *ctx = (struct ctx *)ud; + if (length > SIZE_MAX || ctx->in.pos != ctx->in.size) { + zip_error_set(ctx->error, ZIP_ER_INVAL, 0); + return false; + } + ctx->in.src = (const void *)data; + ctx->in.size = (size_t)length; + ctx->in.pos = 0; + return true; +} + + +static void +end_of_input(void *ud) { + struct ctx *ctx = (struct ctx *)ud; + + ctx->end_of_input = true; +} + + +static zip_compression_status_t +process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { + struct ctx *ctx = (struct ctx *)ud; + + size_t ret; + + if (ctx->in.pos == ctx->in.size && !ctx->end_of_input) { + *length = 0; + return ZIP_COMPRESSION_NEED_DATA; + } + + ctx->out.dst = data; + ctx->out.pos = 0; + ctx->out.size = ZIP_MIN(SIZE_MAX, *length); + + if (ctx->compress) { + if (ctx->in.pos == ctx->in.size && ctx->end_of_input) { + ret = ZSTD_endStream(ctx->zcstream, &ctx->out); + if (ret == 0) { + *length = ctx->out.pos; + return ZIP_COMPRESSION_END; + } + } + else { + ret = ZSTD_compressStream(ctx->zcstream, &ctx->out, &ctx->in); + } + } + else { + ret = ZSTD_decompressStream(ctx->zdstream, &ctx->out, &ctx->in); + } + if (ZSTD_isError(ret)) { + zip_error_set(ctx->error, map_error(ret), 0); + return ZIP_COMPRESSION_ERROR; + } + + *length = ctx->out.pos; + if (ctx->in.pos == ctx->in.size) { + return ZIP_COMPRESSION_NEED_DATA; + } + + return ZIP_COMPRESSION_OK; +} + +/* Version Required should be set to 63 (6.3) because this compression + method was only defined in appnote.txt version 6.3.7, but Winzip + does not unpack it if the value is not 20. */ + +/* clang-format off */ + +zip_compression_algorithm_t zip_algorithm_zstd_compress = { + maximum_compressed_size, + compress_allocate, + deallocate, + general_purpose_bit_flags, + 20, + start, + end, + input, + end_of_input, + process +}; + + +zip_compression_algorithm_t zip_algorithm_zstd_decompress = { + maximum_compressed_size, + decompress_allocate, + deallocate, + general_purpose_bit_flags, + 20, + start, + end, + input, + end_of_input, + process +}; + +/* clang-format on */ diff --git a/3rdparty/libzip/lib/zip_buffer.c b/3rdparty/libzip/lib/zip_buffer.c new file mode 100644 index 0000000000..e2103f04ce --- /dev/null +++ b/3rdparty/libzip/lib/zip_buffer.c @@ -0,0 +1,337 @@ +/* + zip_buffer.c -- bounds checked access to memory buffer + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "zipint.h" + +zip_uint8_t * +_zip_buffer_data(zip_buffer_t *buffer) { + return buffer->data; +} + + +void +_zip_buffer_free(zip_buffer_t *buffer) { + if (buffer == NULL) { + return; + } + + if (buffer->free_data) { + free(buffer->data); + } + + free(buffer); +} + + +bool +_zip_buffer_eof(zip_buffer_t *buffer) { + return buffer->ok && buffer->offset == buffer->size; +} + + +zip_uint8_t * +_zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) { + zip_uint8_t *data; + + data = _zip_buffer_peek(buffer, length); + + if (data != NULL) { + buffer->offset += length; + } + + return data; +} + + +zip_uint16_t +_zip_buffer_get_16(zip_buffer_t *buffer) { + zip_uint8_t *data = _zip_buffer_get(buffer, 2); + + if (data == NULL) { + return 0; + } + + return (zip_uint16_t)(data[0] + (data[1] << 8)); +} + + +zip_uint32_t +_zip_buffer_get_32(zip_buffer_t *buffer) { + zip_uint8_t *data = _zip_buffer_get(buffer, 4); + + if (data == NULL) { + return 0; + } + + return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0]; +} + + +zip_uint64_t +_zip_buffer_get_64(zip_buffer_t *buffer) { + zip_uint8_t *data = _zip_buffer_get(buffer, 8); + + if (data == NULL) { + return 0; + } + + return ((zip_uint64_t)data[7] << 56) + ((zip_uint64_t)data[6] << 48) + ((zip_uint64_t)data[5] << 40) + ((zip_uint64_t)data[4] << 32) + ((zip_uint64_t)data[3] << 24) + ((zip_uint64_t)data[2] << 16) + ((zip_uint64_t)data[1] << 8) + (zip_uint64_t)data[0]; +} + + +zip_uint8_t +_zip_buffer_get_8(zip_buffer_t *buffer) { + zip_uint8_t *data = _zip_buffer_get(buffer, 1); + + if (data == NULL) { + return 0; + } + + return data[0]; +} + + +zip_uint64_t +_zip_buffer_left(zip_buffer_t *buffer) { + return buffer->ok ? buffer->size - buffer->offset : 0; +} + + +zip_uint64_t +_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) { + zip_uint64_t copied; + + if (_zip_buffer_left(buffer) < length) { + length = _zip_buffer_left(buffer); + } + + copied = 0; + while (copied < length) { + size_t n = ZIP_MIN(length - copied, SIZE_MAX); + (void)memcpy_s(data + copied, n, _zip_buffer_get(buffer, n), n); + copied += n; + } + + return copied; +} + + +zip_buffer_t * +_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) { + bool free_data = (data == NULL); + zip_buffer_t *buffer; + +#if ZIP_UINT64_MAX > SIZE_MAX + if (size > SIZE_MAX) { + return NULL; + } +#endif + + if (data == NULL) { + if ((data = (zip_uint8_t *)malloc((size_t)size)) == NULL) { + return NULL; + } + } + + if ((buffer = (zip_buffer_t *)malloc(sizeof(*buffer))) == NULL) { + if (free_data) { + free(data); + } + return NULL; + } + + buffer->ok = true; + buffer->data = data; + buffer->size = size; + buffer->offset = 0; + buffer->free_data = free_data; + + return buffer; +} + + +zip_buffer_t * +_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error) { + zip_buffer_t *buffer; + + if ((buffer = _zip_buffer_new(buf, size)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (_zip_read(src, buffer->data, size, error) < 0) { + _zip_buffer_free(buffer); + return NULL; + } + + return buffer; +} + + +zip_uint64_t +_zip_buffer_offset(zip_buffer_t *buffer) { + return buffer->ok ? buffer->offset : 0; +} + + +bool +_zip_buffer_ok(zip_buffer_t *buffer) { + return buffer->ok; +} + + +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; + } + + (void)memcpy_s(dst, length, src, length); + return 0; +} + + +int +_zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i) { + zip_uint8_t *data = _zip_buffer_get(buffer, 2); + + if (data == NULL) { + return -1; + } + + data[0] = (zip_uint8_t)(i & 0xff); + data[1] = (zip_uint8_t)((i >> 8) & 0xff); + + return 0; +} + + +int +_zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i) { + zip_uint8_t *data = _zip_buffer_get(buffer, 4); + + if (data == NULL) { + return -1; + } + + data[0] = (zip_uint8_t)(i & 0xff); + data[1] = (zip_uint8_t)((i >> 8) & 0xff); + data[2] = (zip_uint8_t)((i >> 16) & 0xff); + data[3] = (zip_uint8_t)((i >> 24) & 0xff); + + return 0; +} + + +int +_zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) { + zip_uint8_t *data = _zip_buffer_get(buffer, 8); + + if (data == NULL) { + return -1; + } + + data[0] = (zip_uint8_t)(i & 0xff); + data[1] = (zip_uint8_t)((i >> 8) & 0xff); + data[2] = (zip_uint8_t)((i >> 16) & 0xff); + data[3] = (zip_uint8_t)((i >> 24) & 0xff); + data[4] = (zip_uint8_t)((i >> 32) & 0xff); + 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; +} + + +int +_zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) { + zip_uint8_t *data = _zip_buffer_get(buffer, 1); + + if (data == NULL) { + return -1; + } + + data[0] = i; + + return 0; +} + + +int +_zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) { + if (offset > buffer->size) { + buffer->ok = false; + return -1; + } + + buffer->ok = true; + buffer->offset = offset; + + return 0; +} + + +int +_zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) { + zip_uint64_t offset = buffer->offset + length; + + if (offset < buffer->offset) { + buffer->ok = false; + return -1; + } + return _zip_buffer_set_offset(buffer, offset); +} + +zip_uint64_t +_zip_buffer_size(zip_buffer_t *buffer) { + return buffer->size; +} diff --git a/3rdparty/libzip/lib/zip_close.c b/3rdparty/libzip/lib/zip_close.c new file mode 100644 index 0000000000..ddc2c24563 --- /dev/null +++ b/3rdparty/libzip/lib/zip_close.c @@ -0,0 +1,745 @@ +/* + zip_close.c -- close zip archive and update changes + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +#include +#include +#ifdef _WIN32 +#include +#include +#endif + + +static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t); +static int copy_data(zip_t *, zip_uint64_t); +static int copy_source(zip_t *, zip_source_t *, zip_int64_t); +static int torrentzip_compare_names(const void *a, const void *b); +static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t); +static int write_data_descriptor(zip_t *za, const zip_dirent_t *dirent, int is_zip64); + +ZIP_EXTERN int +zip_close(zip_t *za) { + zip_uint64_t i, j, survivors, unchanged_offset; + zip_int64_t off; + int error; + zip_filelist_t *filelist; + int changed; + + if (za == NULL) + return -1; + + changed = _zip_changed(za, &survivors); + + if (survivors == 0 && !(za->ch_flags & ZIP_AFL_CREATE_OR_KEEP_FILE_FOR_EMPTY_ARCHIVE)) { + /* don't create zip files with no entries */ + if ((za->open_flags & ZIP_TRUNCATE) || changed) { + if (zip_source_remove(za->src) < 0) { + if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) { + zip_error_set_from_source(&za->error, za->src); + return -1; + } + } + } + zip_discard(za); + return 0; + } + + /* Always write empty archive if we are told to keep it, otherwise it wouldn't be created if the file doesn't already exist. */ + if (!changed && survivors > 0) { + zip_discard(za); + return 0; + } + + if (survivors > za->nentry) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((filelist = (zip_filelist_t *)malloc(sizeof(filelist[0]) * (size_t)survivors)) == NULL) + return -1; + + unchanged_offset = ZIP_UINT64_MAX; + /* create list of files with index into original archive */ + for (i = j = 0; i < za->nentry; i++) { + if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) { + unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset); + } + if (za->entry[i].deleted) { + continue; + } + + if (j >= survivors) { + free(filelist); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + filelist[j].idx = i; + filelist[j].name = zip_get_name(za, i, 0); + j++; + } + if (j < survivors) { + free(filelist); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if (ZIP_WANT_TORRENTZIP(za)) { + qsort(filelist, (size_t)survivors, sizeof(filelist[0]), torrentzip_compare_names); + } + + if (ZIP_WANT_TORRENTZIP(za) || (zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) { + unchanged_offset = 0; + } + else { + if (unchanged_offset == ZIP_UINT64_MAX) { + /* we're keeping all file data, find the end of the last one */ + zip_uint64_t last_index = ZIP_UINT64_MAX; + unchanged_offset = 0; + + for (i = 0; i < za->nentry; i++) { + if (za->entry[i].orig != NULL) { + if (za->entry[i].orig->offset >= unchanged_offset) { + unchanged_offset = za->entry[i].orig->offset; + last_index = i; + } + } + } + if (last_index != ZIP_UINT64_MAX) { + if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) { + free(filelist); + return -1; + } + } + } + if (unchanged_offset > 0) { + if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) { + /* cloning not supported, need to copy everything */ + unchanged_offset = 0; + } + } + } + if (unchanged_offset == 0) { + if (zip_source_begin_write(za->src) < 0) { + zip_error_set_from_source(&za->error, za->src); + free(filelist); + return -1; + } + } + + if (_zip_progress_start(za->progress) != 0) { + zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); + zip_source_rollback_write(za->src); + free(filelist); + return -1; + } + error = 0; + for (j = 0; j < survivors; j++) { + int new_data; + zip_entry_t *entry; + zip_dirent_t *de; + + if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) { + zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); + error = 1; + break; + } + + i = filelist[j].idx; + entry = za->entry + i; + + if (entry->orig != NULL && entry->orig->offset < unchanged_offset) { + /* already implicitly copied by cloning */ + continue; + } + + new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD)) || (ZIP_WANT_TORRENTZIP(za) && !ZIP_IS_TORRENTZIP(za)); + + /* create new local directory entry */ + if (entry->changes == NULL) { + if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + error = 1; + break; + } + } + de = entry->changes; + + if (_zip_read_local_ef(za, i) < 0) { + error = 1; + break; + } + + if (ZIP_WANT_TORRENTZIP(za)) { + zip_dirent_torrentzip_normalize(entry->changes); + } + + if ((off = zip_source_tell_write(za->src)) < 0) { + zip_error_set_from_source(&za->error, za->src); + error = 1; + break; + } + de->offset = (zip_uint64_t)off; + + if (new_data) { + zip_source_t *zs; + + zs = NULL; + if (!ZIP_ENTRY_DATA_CHANGED(entry)) { + if ((zs = zip_source_zip_file_create(za, i, ZIP_FL_UNCHANGED, 0, -1, NULL, &za->error)) == NULL) { + error = 1; + break; + } + } + + /* add_data writes dirent */ + if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) { + error = 1; + if (zs) + zip_source_free(zs); + break; + } + if (zs) + zip_source_free(zs); + } + else { + zip_uint64_t offset; + + if (de->encryption_method != ZIP_EM_TRAD_PKWARE) { + /* when copying data, all sizes are known -> no data descriptor needed */ + /* except for PKWare encryption, where removing the data descriptor breaks password validation */ + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; + } + if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) { + error = 1; + break; + } + if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) { + error = 1; + break; + } + if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { + zip_error_set_from_source(&za->error, za->src); + error = 1; + break; + } + if (copy_data(za, de->comp_size) < 0) { + error = 1; + break; + } + + if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { + if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) { + error = 1; + break; + } + } + } + } + + if (!error) { + if (write_cdir(za, filelist, survivors) < 0) + error = 1; + } + + free(filelist); + + if (!error) { + if (zip_source_commit_write(za->src) != 0) { + zip_error_set_from_source(&za->error, za->src); + error = 1; + } + _zip_progress_end(za->progress); + } + + if (error) { + zip_source_rollback_write(za->src); + return -1; + } + + zip_discard(za); + + return 0; +} + + +static int +add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { + zip_int64_t offstart, offdata, offend, data_length; + zip_stat_t st; + zip_file_attributes_t attributes; + zip_source_t *src_final, *src_tmp; + int ret; + int is_zip64; + zip_flags_t flags; + bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt; + + if (zip_source_stat(src, &st) < 0) { + zip_error_set_from_source(&za->error, src); + return -1; + } + + if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) { + st.valid |= ZIP_STAT_COMP_METHOD; + st.comp_method = ZIP_CM_STORE; + } + + if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE) + de->comp_method = st.comp_method; + else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) { + st.valid |= ZIP_STAT_COMP_SIZE; + st.comp_size = st.size; + } + else { + /* we'll recompress */ + 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) { + /* TODO: not valid for torrentzip */ + 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) { + zip_uint64_t max_compressed_size; + zip_uint16_t compression_method = ZIP_CM_ACTUAL(de->comp_method); + + if (compression_method == ZIP_CM_STORE) { + max_compressed_size = st.size; + } + else { + zip_compression_algorithm_t *algorithm = _zip_get_compression_algorithm(compression_method, true); + if (algorithm == NULL) { + max_compressed_size = ZIP_UINT64_MAX; + } + else { + max_compressed_size = algorithm->maximum_compressed_size(st.size); + } + } + + if (max_compressed_size > 0xffffffffu) { + /* TODO: not valid for torrentzip */ + flags |= ZIP_FL_FORCE_ZIP64; + } + } + else { + de->comp_size = st.comp_size; + data_length = (zip_int64_t)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) { + return -1; + } + + needs_recompress = ZIP_WANT_TORRENTZIP(za) || st.comp_method != ZIP_CM_ACTUAL(de->comp_method); + needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE); + /* in these cases we can compute the CRC ourselves, so we do */ + needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress; + needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE); + + needs_reencrypt = needs_recompress || (de->changed & ZIP_DIRENT_PASSWORD) || (de->encryption_method != st.encryption_method); + needs_decrypt = needs_reencrypt && (st.encryption_method != ZIP_EM_NONE); + needs_encrypt = needs_reencrypt && (de->encryption_method != ZIP_EM_NONE); + + src_final = src; + zip_source_keep(src_final); + + if (!needs_decrypt && st.encryption_method == ZIP_EM_TRAD_PKWARE && (de->changed & ZIP_DIRENT_LAST_MOD)) { + /* PKWare encryption uses the last modification time for password verification, therefore we can't change it without re-encrypting. Ignoring the requested modification time change seems more sensible than failing to close the archive. */ + de->changed &= ~ZIP_DIRENT_LAST_MOD; + } + + if (needs_decrypt) { + zip_encryption_implementation impl; + + if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + zip_source_free(src_final); + return -1; + } + if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) { + /* error set by impl */ + zip_source_free(src_final); + return -1; + } + + 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; + } + + src_final = src_tmp; + } + + if (needs_crc) { + if ((src_tmp = zip_source_crc_create(src_final, 0, &za->error)) == NULL) { + zip_source_free(src_final); + return -1; + } + + 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; + } + + 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 (de->encryption_method == ZIP_EM_TRAD_PKWARE) { + de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR; + + /* PKWare encryption uses last_mod, make sure it gets the right value. */ + if (de->changed & ZIP_DIRENT_LAST_MOD) { + zip_stat_t st_mtime; + zip_stat_init(&st_mtime); + st_mtime.valid = ZIP_STAT_MTIME; + st_mtime.mtime = de->last_mod; + if ((src_tmp = _zip_source_window_new(src_final, 0, -1, &st_mtime, 0, NULL, NULL, 0, true, &za->error)) == NULL) { + zip_source_free(src_final); + return -1; + } + src_final = src_tmp; + } + } + + 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; + } + + 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, src_final, data_length); + + if (zip_source_stat(src_final, &st) < 0) { + zip_error_set_from_source(&za->error, src_final); + ret = -1; + } + + if (zip_source_get_file_attributes(src_final, &attributes) != 0) { + zip_error_set_from_source(&za->error, src_final); + ret = -1; + } + + 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; + } + + if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) { + zip_error_set_from_source(&za->error, za->src); + return -1; + } + + if ((st.valid & (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) { + if (st.valid & ZIP_STAT_MTIME) + de->last_mod = st.mtime; + else + time(&de->last_mod); + } + de->comp_method = st.comp_method; + de->crc = st.crc; + de->uncomp_size = st.size; + de->comp_size = (zip_uint64_t)(offend - offdata); + _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed); + + if (ZIP_WANT_TORRENTZIP(za)) { + zip_dirent_torrentzip_normalize(de); + } + + if ((ret = _zip_dirent_write(za, de, flags)) < 0) + return -1; + + if (is_zip64 != ret) { + /* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */ + 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); + return -1; + } + + if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { + if (write_data_descriptor(za, de, is_zip64) < 0) { + return -1; + } + } + + return 0; +} + + +static int +copy_data(zip_t *za, zip_uint64_t len) { + DEFINE_BYTE_ARRAY(buf, BUFSIZE); + double total = (double)len; + + if (!byte_array_init(buf, BUFSIZE)) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + while (len > 0) { + zip_uint64_t n = ZIP_MIN(len, BUFSIZE); + + if (_zip_read(za->src, buf, n, &za->error) < 0) { + byte_array_fini(buf); + return -1; + } + + if (_zip_write(za, buf, n) < 0) { + byte_array_fini(buf); + return -1; + } + + len -= n; + + if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) { + zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); + return -1; + } + } + + byte_array_fini(buf); + return 0; +} + + +static int +copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) { + DEFINE_BYTE_ARRAY(buf, BUFSIZE); + zip_int64_t n, current; + int ret; + + if (zip_source_open(src) < 0) { + zip_error_set_from_source(&za->error, src); + return -1; + } + + if (!byte_array_init(buf, BUFSIZE)) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + ret = 0; + current = 0; + while ((n = zip_source_read(src, buf, BUFSIZE)) > 0) { + if (_zip_write(za, buf, (zip_uint64_t)n) < 0) { + ret = -1; + break; + } + if (n == BUFSIZE && za->progress && data_length > 0) { + current += n; + if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) { + zip_error_set(&za->error, ZIP_ER_CANCELLED, 0); + ret = -1; + break; + } + } + } + + if (n < 0) { + zip_error_set_from_source(&za->error, src); + ret = -1; + } + + byte_array_fini(buf); + + zip_source_close(src); + + return ret; +} + +static int +write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) { + if (zip_source_tell_write(za->src) < 0) { + return -1; + } + + if (_zip_cdir_write(za, filelist, survivors) < 0) { + return -1; + } + + if (zip_source_tell_write(za->src) < 0) { + return -1; + } + + return 0; +} + + +int +_zip_changed(const zip_t *za, zip_uint64_t *survivorsp) { + int changed; + zip_uint64_t i, survivors; + + changed = 0; + survivors = 0; + + if (za->comment_changed || (ZIP_WANT_TORRENTZIP(za) && !ZIP_IS_TORRENTZIP(za))) { + changed = 1; + } + + for (i = 0; i < za->nentry; i++) { + if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) { + changed = 1; + } + if (!za->entry[i].deleted) { + survivors++; + } + } + + if (survivorsp) { + *survivorsp = survivors; + } + + return changed; +} + +static int +write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) { + zip_buffer_t *buffer = _zip_buffer_new(NULL, MAX_DATA_DESCRIPTOR_LENGTH); + int ret = 0; + + if (buffer == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + _zip_buffer_put(buffer, DATADES_MAGIC, 4); + _zip_buffer_put_32(buffer, de->crc); + if (is_zip64) { + _zip_buffer_put_64(buffer, de->comp_size); + _zip_buffer_put_64(buffer, de->uncomp_size); + } + else { + _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size); + _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size); + } + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + ret = -1; + } + else { + ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)); + } + + _zip_buffer_free(buffer); + + return ret; +} + + +static int torrentzip_compare_names(const void *a, const void *b) { + const char *aname = ((const zip_filelist_t *)a)->name; + const char *bname = ((const zip_filelist_t *)b)->name; + + if (aname == NULL) { + return (bname != NULL) * -1; + } + else if (bname == NULL) { + return 1; + } + + return strcasecmp(aname, bname); +} \ No newline at end of file diff --git a/3rdparty/libzip/lib/zip_crypto.h b/3rdparty/libzip/lib/zip_crypto.h new file mode 100644 index 0000000000..0d74d1a41e --- /dev/null +++ b/3rdparty/libzip/lib/zip_crypto.h @@ -0,0 +1,54 @@ +/* + zip_crypto.h -- crypto definitions + Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_H +#define HAD_ZIP_CRYPTO_H + +#define ZIP_CRYPTO_SHA1_LENGTH 20 +#define ZIP_CRYPTO_AES_BLOCK_LENGTH 16 + +#if defined(HAVE_WINDOWS_CRYPTO) +#include "zip_crypto_win.h" +#elif defined(HAVE_COMMONCRYPTO) +#include "zip_crypto_commoncrypto.h" +#elif defined(HAVE_GNUTLS) +#include "zip_crypto_gnutls.h" +#elif defined(HAVE_OPENSSL) +#include "zip_crypto_openssl.h" +#elif defined(HAVE_MBEDTLS) +#include "zip_crypto_mbedtls.h" +#else +#error "no crypto backend found" +#endif + +#endif /* HAD_ZIP_CRYPTO_H */ diff --git a/3rdparty/libzip/lib/zip_crypto_commoncrypto.c b/3rdparty/libzip/lib/zip_crypto_commoncrypto.c new file mode 100644 index 0000000000..b198be5630 --- /dev/null +++ b/3rdparty/libzip/lib/zip_crypto_commoncrypto.c @@ -0,0 +1,110 @@ +/* + zip_crypto_commoncrypto.c -- CommonCrypto wrapper. + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + +#include "zip_crypto.h" + +#include +#include + +void +_zip_crypto_aes_free(_zip_crypto_aes_t *aes) { + if (aes == NULL) { + return; + } + + CCCryptorRelease(aes); +} + + +bool +_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) { + size_t len; + CCCryptorUpdate(aes, in, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, ZIP_CRYPTO_AES_BLOCK_LENGTH, &len); + return true; +} + + +_zip_crypto_aes_t * +_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) { + _zip_crypto_aes_t *aes; + CCCryptorStatus ret; + + ret = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionECBMode, key, key_size / 8, NULL, &aes); + + switch (ret) { + case kCCSuccess: + return aes; + + case kCCMemoryFailure: + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + + case kCCParamError: + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + + default: + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } +} + + +void +_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { + if (hmac == NULL) { + return; + } + + _zip_crypto_clear(hmac, sizeof(*hmac)); + free(hmac); +} + + +_zip_crypto_hmac_t * +_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) { + _zip_crypto_hmac_t *hmac; + + if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + CCHmacInit(hmac, kCCHmacAlgSHA1, secret, secret_length); + + return hmac; +} diff --git a/3rdparty/libzip/lib/zip_crypto_commoncrypto.h b/3rdparty/libzip/lib/zip_crypto_commoncrypto.h new file mode 100644 index 0000000000..01828cc64e --- /dev/null +++ b/3rdparty/libzip/lib/zip_crypto_commoncrypto.h @@ -0,0 +1,53 @@ +/* + zip_crypto_commoncrypto.h -- definitions for CommonCrypto wrapper. + Copyright (C) 2018 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_COMMONCRYPTO_H +#define HAD_ZIP_CRYPTO_COMMONCRYPTO_H + +#include + +#define _zip_crypto_aes_t struct _CCCryptor +#define _zip_crypto_hmac_t CCHmacContext + +void _zip_crypto_aes_free(_zip_crypto_aes_t *aes); +bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out); +_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error); + +#define _zip_crypto_hmac(hmac, data, length) (CCHmacUpdate((hmac), (data), (length)), true) +void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac); +_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error); +#define _zip_crypto_hmac_output(hmac, data) (CCHmacFinal((hmac), (data)), true) + +#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)(key), (key_length), (salt), (salt_length), kCCPRFHmacAlgSHA1, (iterations), (output), (output_length)) == kCCSuccess) + +#endif /* HAD_ZIP_CRYPTO_COMMONCRYPTO_H */ diff --git a/3rdparty/libzip/lib/zip_crypto_gnutls.c b/3rdparty/libzip/lib/zip_crypto_gnutls.c new file mode 100644 index 0000000000..1a25aa120e --- /dev/null +++ b/3rdparty/libzip/lib/zip_crypto_gnutls.c @@ -0,0 +1,134 @@ +/* + zip_crypto_gnutls.c -- GnuTLS wrapper. + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + +#include "zip_crypto.h" + +_zip_crypto_aes_t * +_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) { + _zip_crypto_aes_t *aes; + + if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + aes->key_size = key_size; + + switch (aes->key_size) { + case 128: + nettle_aes128_set_encrypt_key(&aes->ctx.ctx_128, key); + break; + case 192: + nettle_aes192_set_encrypt_key(&aes->ctx.ctx_192, key); + break; + case 256: + nettle_aes256_set_encrypt_key(&aes->ctx.ctx_256, key); + break; + default: + zip_error_set(error, ZIP_ER_INVAL, 0); + free(aes); + return NULL; + } + + return aes; +} + +bool +_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) { + switch (aes->key_size) { + case 128: + nettle_aes128_encrypt(&aes->ctx.ctx_128, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in); + break; + case 192: + nettle_aes192_encrypt(&aes->ctx.ctx_192, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in); + break; + case 256: + nettle_aes256_encrypt(&aes->ctx.ctx_256, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in); + break; + } + + return true; +} + +void +_zip_crypto_aes_free(_zip_crypto_aes_t *aes) { + if (aes == NULL) { + return; + } + + _zip_crypto_clear(aes, sizeof(*aes)); + free(aes); +} + + +_zip_crypto_hmac_t * +_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) { + _zip_crypto_hmac_t *hmac; + + if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (gnutls_hmac_init(hmac, GNUTLS_MAC_SHA1, secret, secret_length) < 0) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + free(hmac); + return NULL; + } + + return hmac; +} + + +void +_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { + zip_uint8_t buf[ZIP_CRYPTO_SHA1_LENGTH]; + + if (hmac == NULL) { + return; + } + + gnutls_hmac_deinit(*hmac, buf); + _zip_crypto_clear(hmac, sizeof(*hmac)); + free(hmac); +} + + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + return gnutls_rnd(GNUTLS_RND_KEY, buffer, length) == 0; +} diff --git a/3rdparty/libzip/lib/zip_crypto_gnutls.h b/3rdparty/libzip/lib/zip_crypto_gnutls.h new file mode 100644 index 0000000000..dc8b97a4d2 --- /dev/null +++ b/3rdparty/libzip/lib/zip_crypto_gnutls.h @@ -0,0 +1,68 @@ +/* + zip_crypto_gnutls.h -- definitions for GnuTLS wrapper. + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_GNUTLS_H +#define HAD_ZIP_CRYPTO_GNUTLS_H + +#define HAVE_SECURE_RANDOM + +#include +#include + +#include + +#include + +typedef struct { + union { + struct aes128_ctx ctx_128; + struct aes192_ctx ctx_192; + struct aes256_ctx ctx_256; + } ctx; + zip_uint16_t key_size; +} _zip_crypto_aes_t; + +#define _zip_crypto_hmac_t gnutls_hmac_hd_t + +void _zip_crypto_aes_free(_zip_crypto_aes_t *aes); +bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out); +_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error); + +#define _zip_crypto_hmac(hmac, data, length) (gnutls_hmac(*(hmac), (data), (length)) == 0) +void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac); +_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error); +#define _zip_crypto_hmac_output(hmac, data) (gnutls_hmac_output(*(hmac), (data)), true) + +#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (pbkdf2_hmac_sha1((key_length), (key), (iterations), (salt_length), (salt), (output_length), (output)), true) + +#endif /* HAD_ZIP_CRYPTO_GNUTLS_H */ diff --git a/3rdparty/libzip/lib/zip_crypto_mbedtls.c b/3rdparty/libzip/lib/zip_crypto_mbedtls.c new file mode 100644 index 0000000000..84544a821d --- /dev/null +++ b/3rdparty/libzip/lib/zip_crypto_mbedtls.c @@ -0,0 +1,171 @@ +/* + zip_crypto_mbedtls.c -- mbed TLS wrapper + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + +#include "zip_crypto.h" + +#include +#include +#include + +#include + +_zip_crypto_aes_t * +_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) { + _zip_crypto_aes_t *aes; + + if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + mbedtls_aes_init(aes); + mbedtls_aes_setkey_enc(aes, (const unsigned char *)key, (unsigned int)key_size); + + return aes; +} + +void +_zip_crypto_aes_free(_zip_crypto_aes_t *aes) { + if (aes == NULL) { + return; + } + + mbedtls_aes_free(aes); + free(aes); +} + + +_zip_crypto_hmac_t * +_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) { + _zip_crypto_hmac_t *hmac; + + if (secret_length > INT_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + mbedtls_md_init(hmac); + + if (mbedtls_md_setup(hmac, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + free(hmac); + return NULL; + } + + if (mbedtls_md_hmac_starts(hmac, (const unsigned char *)secret, (size_t)secret_length) != 0) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + free(hmac); + return NULL; + } + + return hmac; +} + + +void +_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { + if (hmac == NULL) { + return; + } + + mbedtls_md_free(hmac); + free(hmac); +} + + +bool +_zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, int iterations, zip_uint8_t *output, zip_uint64_t output_length) { + mbedtls_md_context_t sha1_ctx; + bool ok = true; + +#if MBEDTLS_VERSION_NUMBER < 0x03030000 + + mbedtls_md_init(&sha1_ctx); + + if (mbedtls_md_setup(&sha1_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) { + ok = false; + } + + if (ok && mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, (const unsigned char *)key, (size_t)key_length, (const unsigned char *)salt, (size_t)salt_length, (unsigned int)iterations, (uint32_t)output_length, (unsigned char *)output) != 0) { + ok = false; + } + + mbedtls_md_free(&sha1_ctx); + +#else + + ok = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, (const unsigned char *)key, (size_t)key_length, (const unsigned char *)salt, (size_t)salt_length, (unsigned int)iterations, (uint32_t)output_length, (unsigned char *)output) == 0; + +#endif // !defined(MBEDTLS_DEPRECATED_REMOVED) || MBEDTLS_VERSION_NUMBER < 0x03030000 + + return ok; +} + + +typedef struct { + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; +} zip_random_context_t; + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + static zip_random_context_t *ctx = NULL; + const unsigned char *pers = "zip_crypto_mbedtls"; + + if (!ctx) { + ctx = (zip_random_context_t *)malloc(sizeof(zip_random_context_t)); + if (!ctx) { + return false; + } + mbedtls_entropy_init(&ctx->entropy); + mbedtls_ctr_drbg_init(&ctx->ctr_drbg); + if (mbedtls_ctr_drbg_seed(&ctx->ctr_drbg, mbedtls_entropy_func, &ctx->entropy, pers, strlen(pers)) != 0) { + mbedtls_ctr_drbg_free(&ctx->ctr_drbg); + mbedtls_entropy_free(&ctx->entropy); + free(ctx); + ctx = NULL; + return false; + } + } + + return mbedtls_ctr_drbg_random(&ctx->ctr_drbg, (unsigned char *)buffer, (size_t)length) == 0; +} diff --git a/3rdparty/libzip/lib/zip_crypto_mbedtls.h b/3rdparty/libzip/lib/zip_crypto_mbedtls.h new file mode 100644 index 0000000000..1151fff757 --- /dev/null +++ b/3rdparty/libzip/lib/zip_crypto_mbedtls.h @@ -0,0 +1,56 @@ +/* + zip_crypto_mbedtls.h -- definitions for mbedtls wrapper + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_MBEDTLS_H +#define HAD_ZIP_CRYPTO_MBEDTLS_H + +#define HAVE_SECURE_RANDOM + +#include +#include + +#define _zip_crypto_aes_t mbedtls_aes_context +#define _zip_crypto_hmac_t mbedtls_md_context_t + +_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error); +#define _zip_crypto_aes_encrypt_block(aes, in, out) (mbedtls_aes_crypt_ecb((aes), MBEDTLS_AES_ENCRYPT, (in), (out)) == 0) +void _zip_crypto_aes_free(_zip_crypto_aes_t *aes); + +_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error); +#define _zip_crypto_hmac(hmac, data, length) (mbedtls_md_hmac_update((hmac), (data), (length)) == 0) +#define _zip_crypto_hmac_output(hmac, data) (mbedtls_md_hmac_finish((hmac), (data)) == 0) +void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac); + +bool _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, int iterations, zip_uint8_t *output, zip_uint64_t output_length); + +#endif /* HAD_ZIP_CRYPTO_MBEDTLS_H */ diff --git a/3rdparty/libzip/lib/zip_crypto_openssl.c b/3rdparty/libzip/lib/zip_crypto_openssl.c new file mode 100644 index 0000000000..7f1da10edb --- /dev/null +++ b/3rdparty/libzip/lib/zip_crypto_openssl.c @@ -0,0 +1,229 @@ +/* + zip_crypto_openssl.c -- OpenSSL wrapper. + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + +#include "zip_crypto.h" + +#include +#include + +#ifdef USE_OPENSSL_3_API +static _zip_crypto_hmac_t* hmac_new() { + _zip_crypto_hmac_t *hmac = (_zip_crypto_hmac_t*)malloc(sizeof(*hmac)); + if (hmac != NULL) { + hmac->mac = NULL; + hmac->ctx = NULL; + } + return hmac; +} +static void hmac_free(_zip_crypto_hmac_t* hmac) { + if (hmac != NULL) { + if (hmac->ctx != NULL) { + EVP_MAC_CTX_free(hmac->ctx); + } + if (hmac->mac != NULL) { + EVP_MAC_free(hmac->mac); + } + free(hmac); + } +} +#endif + +_zip_crypto_aes_t * +_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) { + _zip_crypto_aes_t *aes; + const EVP_CIPHER* cipher_type; + + switch (key_size) { + case 128: + cipher_type = EVP_aes_128_ecb(); + break; + case 192: + cipher_type = EVP_aes_192_ecb(); + break; + case 256: + cipher_type = EVP_aes_256_ecb(); + break; + default: + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + +#ifdef USE_OPENSSL_1_0_API + if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + memset(aes, 0, sizeof(*aes)); +#else + if ((aes = EVP_CIPHER_CTX_new()) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } +#endif + + if (EVP_EncryptInit_ex(aes, cipher_type, NULL, key, NULL) != 1) { +#ifdef USE_OPENSSL_1_0_API + free(aes); +#else + EVP_CIPHER_CTX_free(aes); +#endif + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + + return aes; +} + +void +_zip_crypto_aes_free(_zip_crypto_aes_t *aes) { + if (aes == NULL) { + return; + } + +#ifdef USE_OPENSSL_1_0_API + EVP_CIPHER_CTX_cleanup(aes); + _zip_crypto_clear(aes, sizeof(*aes)); + free(aes); +#else + EVP_CIPHER_CTX_free(aes); +#endif +} + + +bool +_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) { + int len; + if (EVP_EncryptUpdate(aes, out, &len, in, ZIP_CRYPTO_AES_BLOCK_LENGTH) != 1) { + return false; + } + return true; +} + + +_zip_crypto_hmac_t * +_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) { + _zip_crypto_hmac_t *hmac; + + if (secret_length > INT_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + +#ifdef USE_OPENSSL_3_API + if ((hmac = hmac_new()) == NULL + || (hmac->mac = EVP_MAC_fetch(NULL, "HMAC", "provider=default")) == NULL + || (hmac->ctx = EVP_MAC_CTX_new(hmac->mac)) == NULL) { + hmac_free(hmac); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + { + OSSL_PARAM params[2]; + params[0] = OSSL_PARAM_construct_utf8_string("digest", "SHA1", 0); + params[1] = OSSL_PARAM_construct_end(); + + if (!EVP_MAC_init(hmac->ctx, (const unsigned char *)secret, secret_length, params)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + hmac_free(hmac); + return NULL; + } + } +#else +#ifdef USE_OPENSSL_1_0_API + if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + HMAC_CTX_init(hmac); +#else + if ((hmac = HMAC_CTX_new()) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } +#endif + + if (HMAC_Init_ex(hmac, secret, (int)secret_length, EVP_sha1(), NULL) != 1) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); +#ifdef USE_OPENSSL_1_0_API + free(hmac); +#else + HMAC_CTX_free(hmac); +#endif + return NULL; + } +#endif + + return hmac; +} + + +void +_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { + if (hmac == NULL) { + return; + } + +#if defined(USE_OPENSSL_3_API) + hmac_free(hmac); +#elif defined(USE_OPENSSL_1_0_API) + HMAC_CTX_cleanup(hmac); + _zip_crypto_clear(hmac, sizeof(*hmac)); + free(hmac); +#else + HMAC_CTX_free(hmac); +#endif +} + + +bool +_zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) { +#ifdef USE_OPENSSL_3_API + size_t length; + return EVP_MAC_final(hmac->ctx, data, &length, ZIP_CRYPTO_SHA1_LENGTH) == 1 && length == ZIP_CRYPTO_SHA1_LENGTH; +#else + unsigned int length; + return HMAC_Final(hmac, data, &length) == 1; +#endif +} + + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + return RAND_bytes(buffer, length) == 1; +} diff --git a/3rdparty/libzip/lib/zip_crypto_openssl.h b/3rdparty/libzip/lib/zip_crypto_openssl.h new file mode 100644 index 0000000000..198a907144 --- /dev/null +++ b/3rdparty/libzip/lib/zip_crypto_openssl.h @@ -0,0 +1,73 @@ +/* + zip_crypto_openssl.h -- definitions for OpenSSL wrapper. + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_OPENSSL_H +#define HAD_ZIP_CRYPTO_OPENSSL_H + +#define HAVE_SECURE_RANDOM + +#include +#include + +#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) +#define USE_OPENSSL_1_0_API +#elif OPENSSL_VERSION_NUMBER < 0x3000000fL +#define USE_OPENSSL_1_1_API +#else +#define USE_OPENSSL_3_API +#endif + +#define _zip_crypto_aes_t EVP_CIPHER_CTX +#ifdef USE_OPENSSL_3_API +struct _zip_crypto_hmac_t { + EVP_MAC *mac; + EVP_MAC_CTX *ctx; +}; +typedef struct _zip_crypto_hmac_t _zip_crypto_hmac_t; +#define _zip_crypto_hmac(hmac, data, length) (EVP_MAC_update((hmac->ctx), (data), (length)) == 1) +#else +#define _zip_crypto_hmac_t HMAC_CTX +#define _zip_crypto_hmac(hmac, data, length) (HMAC_Update((hmac), (data), (length)) == 1) +#endif + +void _zip_crypto_aes_free(_zip_crypto_aes_t *aes); +bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out); +_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error); + +void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac); +_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error); +bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data); + +#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (PKCS5_PBKDF2_HMAC_SHA1((const char *)(key), (key_length), (salt), (salt_length), (iterations), (output_length), (output))) + +#endif /* HAD_ZIP_CRYPTO_OPENSSL_H */ diff --git a/3rdparty/libzip/lib/zip_crypto_win.c b/3rdparty/libzip/lib/zip_crypto_win.c new file mode 100644 index 0000000000..ee3ccc30a6 --- /dev/null +++ b/3rdparty/libzip/lib/zip_crypto_win.c @@ -0,0 +1,495 @@ +/* + zip_crypto_win.c -- Windows Crypto API wrapper. + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include + +#include "zipint.h" + +#include "zip_crypto.h" + +#define WIN32_LEAN_AND_MEAN +#define NOCRYPT + +#include + +#include + +#pragma comment(lib, "bcrypt.lib") + +/* + +This code is using the Cryptography API: Next Generation (CNG) +https://docs.microsoft.com/en-us/windows/desktop/seccng/cng-portal + +This API is supported on + - Windows Vista or later (client OS) + - Windows Server 2008 (server OS) + - Windows Embedded Compact 2013 (don't know about Windows Embedded Compact 7) + +The code was developed for Windows Embedded Compact 2013 (WEC2013), +but should be working for all of the above mentioned OSes. + +There are 2 restrictions for WEC2013, Windows Vista and Windows Server 2008: + +1.) The function "BCryptDeriveKeyPBKDF2" is not available + +I found some code which is implementing this function using the deprecated Crypto API here: +https://www.idrix.fr/Root/content/view/37/54/ + +I took this code and converted it to the newer CNG API. The original code was more +flexible, but this is not needed here so i refactored it a bit and just kept what is needed. + +The define "HAS_BCRYPTDERIVEKEYPBKDF2" controls whether "BCryptDeriveKeyPBKDF2" +of the CNG API is used or not. This define must not be set if you are compiling for WEC2013 or Windows Vista. + + +2.) "BCryptCreateHash" can't manage the memory needed for the hash object internally + +On Windows 7 or later it is possible to pass NULL for the hash object buffer. +This is not supported on WEC2013, so we have to handle the memory allocation/deallocation ourselves. +There is no #ifdef to control that, because this is working for all supported OSes. + +*/ + +#if !defined(WINCE) && !defined(__MINGW32__) +#define HAS_BCRYPTDERIVEKEYPBKDF2 +#endif + +#ifdef HAS_BCRYPTDERIVEKEYPBKDF2 + +bool +_zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length) { + BCRYPT_ALG_HANDLE hAlgorithm = NULL; + bool result; + + if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG))) { + return false; + } + + result = BCRYPT_SUCCESS(BCryptDeriveKeyPBKDF2(hAlgorithm, (PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length, 0)); + + BCryptCloseAlgorithmProvider(hAlgorithm, 0); + + return result; +} + +#else + +#include + +#define DIGEST_SIZE 20 +#define BLOCK_SIZE 64 + +typedef struct { + BCRYPT_ALG_HANDLE hAlgorithm; + BCRYPT_HASH_HANDLE hInnerHash; + BCRYPT_HASH_HANDLE hOuterHash; + ULONG cbHashObject; + PUCHAR pbInnerHash; + PUCHAR pbOuterHash; +} PRF_CTX; + +static void +hmacFree(PRF_CTX *pContext) { + if (pContext->hOuterHash) + BCryptDestroyHash(pContext->hOuterHash); + if (pContext->hInnerHash) + BCryptDestroyHash(pContext->hInnerHash); + free(pContext->pbOuterHash); + free(pContext->pbInnerHash); + if (pContext->hAlgorithm) + BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0); +} + +static BOOL +hmacPrecomputeDigest(BCRYPT_HASH_HANDLE hHash, PUCHAR pbPassword, DWORD cbPassword, BYTE mask) { + BYTE buffer[BLOCK_SIZE]; + DWORD i; + + if (cbPassword > BLOCK_SIZE) { + return FALSE; + } + + memset(buffer, mask, sizeof(buffer)); + + for (i = 0; i < cbPassword; ++i) { + buffer[i] = (char)(pbPassword[i] ^ mask); + } + + return BCRYPT_SUCCESS(BCryptHashData(hHash, buffer, sizeof(buffer), 0)); +} + +static BOOL +hmacInit(PRF_CTX *pContext, PUCHAR pbPassword, DWORD cbPassword) { + BOOL bStatus = FALSE; + ULONG cbResult; + BYTE key[DIGEST_SIZE]; + + if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&pContext->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, 0)) || !BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&pContext->cbHashObject, sizeof(pContext->cbHashObject), &cbResult, 0)) || ((pContext->pbInnerHash = malloc(pContext->cbHashObject)) == NULL) || ((pContext->pbOuterHash = malloc(pContext->cbHashObject)) == NULL) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hInnerHash, pContext->pbInnerHash, pContext->cbHashObject, NULL, 0, 0)) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hOuterHash, pContext->pbOuterHash, pContext->cbHashObject, NULL, 0, 0))) { + goto hmacInit_end; + } + + if (cbPassword > BLOCK_SIZE) { + BCRYPT_HASH_HANDLE hHash = NULL; + PUCHAR pbHashObject = malloc(pContext->cbHashObject); + if (pbHashObject == NULL) { + goto hmacInit_end; + } + + bStatus = BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &hHash, pbHashObject, pContext->cbHashObject, NULL, 0, 0)) && BCRYPT_SUCCESS(BCryptHashData(hHash, pbPassword, cbPassword, 0)) && BCRYPT_SUCCESS(BCryptGetProperty(hHash, BCRYPT_HASH_LENGTH, (PUCHAR)&cbPassword, sizeof(cbPassword), &cbResult, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, key, cbPassword, 0)); + + if (hHash) + BCryptDestroyHash(hHash); + free(pbHashObject); + + if (!bStatus) { + goto hmacInit_end; + } + + pbPassword = key; + } + + bStatus = hmacPrecomputeDigest(pContext->hInnerHash, pbPassword, cbPassword, 0x36) && hmacPrecomputeDigest(pContext->hOuterHash, pbPassword, cbPassword, 0x5C); + +hmacInit_end: + + if (bStatus == FALSE) + hmacFree(pContext); + + return bStatus; +} + +static BOOL +hmacCalculateInternal(BCRYPT_HASH_HANDLE hHashTemplate, PUCHAR pbData, DWORD cbData, PUCHAR pbOutput, DWORD cbOutput, DWORD cbHashObject) { + BOOL success = FALSE; + BCRYPT_HASH_HANDLE hHash = NULL; + PUCHAR pbHashObject = malloc(cbHashObject); + + if (pbHashObject == NULL) { + return FALSE; + } + + if (BCRYPT_SUCCESS(BCryptDuplicateHash(hHashTemplate, &hHash, pbHashObject, cbHashObject, 0))) { + success = BCRYPT_SUCCESS(BCryptHashData(hHash, pbData, cbData, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, pbOutput, cbOutput, 0)); + + BCryptDestroyHash(hHash); + } + + free(pbHashObject); + + return success; +} + +static BOOL +hmacCalculate(PRF_CTX *pContext, PUCHAR pbData, DWORD cbData, PUCHAR pbDigest) { + DWORD cbResult; + DWORD cbHashObject; + + return BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&cbHashObject, sizeof(cbHashObject), &cbResult, 0)) && hmacCalculateInternal(pContext->hInnerHash, pbData, cbData, pbDigest, DIGEST_SIZE, cbHashObject) && hmacCalculateInternal(pContext->hOuterHash, pbDigest, DIGEST_SIZE, pbDigest, DIGEST_SIZE, cbHashObject); +} + +static void +myxor(LPBYTE ptr1, LPBYTE ptr2, DWORD dwLen) { + while (dwLen--) + *ptr1++ ^= *ptr2++; +} + +BOOL +pbkdf2(PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, DWORD cIterations, PUCHAR pbDerivedKey, ULONG cbDerivedKey) { + BOOL bStatus = FALSE; + DWORD l, r, dwULen, i, j; + BYTE Ti[DIGEST_SIZE]; + BYTE V[DIGEST_SIZE]; + LPBYTE U = malloc(max((cbSalt + 4), DIGEST_SIZE)); + PRF_CTX prfCtx = {0}; + + if (U == NULL) { + return FALSE; + } + + if (pbPassword == NULL || cbPassword == 0 || pbSalt == NULL || cbSalt == 0 || cIterations == 0 || pbDerivedKey == NULL || cbDerivedKey == 0) { + free(U); + return FALSE; + } + + if (!hmacInit(&prfCtx, pbPassword, cbPassword)) { + goto PBKDF2_end; + } + + l = (DWORD)ceil((double)cbDerivedKey / (double)DIGEST_SIZE); + r = cbDerivedKey - (l - 1) * DIGEST_SIZE; + + for (i = 1; i <= l; i++) { + ZeroMemory(Ti, DIGEST_SIZE); + for (j = 0; j < cIterations; j++) { + if (j == 0) { + /* construct first input for PRF */ + (void)memcpy_s(U, cbSalt, pbSalt, cbSalt); + U[cbSalt] = (BYTE)((i & 0xFF000000) >> 24); + U[cbSalt + 1] = (BYTE)((i & 0x00FF0000) >> 16); + U[cbSalt + 2] = (BYTE)((i & 0x0000FF00) >> 8); + U[cbSalt + 3] = (BYTE)((i & 0x000000FF)); + dwULen = cbSalt + 4; + } + else { + (void)memcpy_s(U, DIGEST_SIZE, V, DIGEST_SIZE); + dwULen = DIGEST_SIZE; + } + + if (!hmacCalculate(&prfCtx, U, dwULen, V)) { + goto PBKDF2_end; + } + + myxor(Ti, V, DIGEST_SIZE); + } + + if (i != l) { + (void)memcpy_s(&pbDerivedKey[(i - 1) * DIGEST_SIZE], cbDerivedKey - (i - 1) * DIGEST_SIZE, Ti, DIGEST_SIZE); + } + else { + /* Take only the first r bytes */ + (void)memcpy_s(&pbDerivedKey[(i - 1) * DIGEST_SIZE], cbDerivedKey - (i - 1) * DIGEST_SIZE, Ti, r); + } + } + + bStatus = TRUE; + +PBKDF2_end: + + hmacFree(&prfCtx); + free(U); + return bStatus; +} + +bool +_zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length) { + return (key_length <= ZIP_UINT32_MAX) && pbkdf2((PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length); +} + +#endif + + +struct _zip_crypto_aes_s { + BCRYPT_ALG_HANDLE hAlgorithm; + BCRYPT_KEY_HANDLE hKey; + ULONG cbKeyObject; + PUCHAR pbKeyObject; +}; + +_zip_crypto_aes_t * +_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) { + _zip_crypto_aes_t *aes = (_zip_crypto_aes_t *)calloc(1, sizeof(*aes)); + + ULONG cbResult; + ULONG key_length = key_size / 8; + + if (aes == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&aes->hAlgorithm, BCRYPT_AES_ALGORITHM, NULL, 0))) { + _zip_crypto_aes_free(aes); + return NULL; + } + + if (!BCRYPT_SUCCESS(BCryptSetProperty(aes->hAlgorithm, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0))) { + _zip_crypto_aes_free(aes); + return NULL; + } + + if (!BCRYPT_SUCCESS(BCryptGetProperty(aes->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&aes->cbKeyObject, sizeof(aes->cbKeyObject), &cbResult, 0))) { + _zip_crypto_aes_free(aes); + return NULL; + } + + aes->pbKeyObject = malloc(aes->cbKeyObject); + if (aes->pbKeyObject == NULL) { + _zip_crypto_aes_free(aes); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (!BCRYPT_SUCCESS(BCryptGenerateSymmetricKey(aes->hAlgorithm, &aes->hKey, aes->pbKeyObject, aes->cbKeyObject, (PUCHAR)key, key_length, 0))) { + _zip_crypto_aes_free(aes); + return NULL; + } + + return aes; +} + +void +_zip_crypto_aes_free(_zip_crypto_aes_t *aes) { + if (aes == NULL) { + return; + } + + if (aes->hKey != NULL) { + BCryptDestroyKey(aes->hKey); + } + + if (aes->pbKeyObject != NULL) { + free(aes->pbKeyObject); + } + + if (aes->hAlgorithm != NULL) { + BCryptCloseAlgorithmProvider(aes->hAlgorithm, 0); + } + + free(aes); +} + +bool +_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) { + ULONG cbResult; + NTSTATUS status = BCryptEncrypt(aes->hKey, (PUCHAR)in, ZIP_CRYPTO_AES_BLOCK_LENGTH, NULL, NULL, 0, (PUCHAR)out, ZIP_CRYPTO_AES_BLOCK_LENGTH, &cbResult, 0); + return BCRYPT_SUCCESS(status); +} + +struct _zip_crypto_hmac_s { + BCRYPT_ALG_HANDLE hAlgorithm; + BCRYPT_HASH_HANDLE hHash; + DWORD cbHashObject; + PUCHAR pbHashObject; + DWORD cbHash; + PUCHAR pbHash; +}; + +/* https://code.msdn.microsoft.com/windowsdesktop/Hmac-Computation-Sample-11fe8ec1/sourcecode?fileId=42820&pathId=283874677 */ + +_zip_crypto_hmac_t * +_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) { + NTSTATUS status; + ULONG cbResult; + _zip_crypto_hmac_t *hmac; + + if (secret_length > INT_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + hmac = (_zip_crypto_hmac_t *)calloc(1, sizeof(*hmac)); + + if (hmac == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + status = BCryptOpenAlgorithmProvider(&hmac->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG); + if (!BCRYPT_SUCCESS(status)) { + _zip_crypto_hmac_free(hmac); + return NULL; + } + + status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hmac->cbHashObject, sizeof(hmac->cbHashObject), &cbResult, 0); + if (!BCRYPT_SUCCESS(status)) { + _zip_crypto_hmac_free(hmac); + return NULL; + } + + hmac->pbHashObject = malloc(hmac->cbHashObject); + if (hmac->pbHashObject == NULL) { + _zip_crypto_hmac_free(hmac); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_HASH_LENGTH, (PUCHAR)&hmac->cbHash, sizeof(hmac->cbHash), &cbResult, 0); + if (!BCRYPT_SUCCESS(status)) { + _zip_crypto_hmac_free(hmac); + return NULL; + } + + hmac->pbHash = malloc(hmac->cbHash); + if (hmac->pbHash == NULL) { + _zip_crypto_hmac_free(hmac); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + status = BCryptCreateHash(hmac->hAlgorithm, &hmac->hHash, hmac->pbHashObject, hmac->cbHashObject, (PUCHAR)secret, (ULONG)secret_length, 0); + if (!BCRYPT_SUCCESS(status)) { + _zip_crypto_hmac_free(hmac); + return NULL; + } + + return hmac; +} + +void +_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) { + if (hmac == NULL) { + return; + } + + if (hmac->hHash != NULL) { + BCryptDestroyHash(hmac->hHash); + } + + if (hmac->pbHash != NULL) { + free(hmac->pbHash); + } + + if (hmac->pbHashObject != NULL) { + free(hmac->pbHashObject); + } + + if (hmac->hAlgorithm) { + BCryptCloseAlgorithmProvider(hmac->hAlgorithm, 0); + } + + free(hmac); +} + +bool +_zip_crypto_hmac(_zip_crypto_hmac_t *hmac, zip_uint8_t *data, zip_uint64_t length) { + if (hmac == NULL || length > ULONG_MAX) { + return false; + } + + return BCRYPT_SUCCESS(BCryptHashData(hmac->hHash, data, (ULONG)length, 0)); +} + +bool +_zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) { + if (hmac == NULL) { + return false; + } + + return BCRYPT_SUCCESS(BCryptFinishHash(hmac->hHash, data, hmac->cbHash, 0)); +} + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + return BCRYPT_SUCCESS(BCryptGenRandom(NULL, buffer, length, BCRYPT_USE_SYSTEM_PREFERRED_RNG)); +} diff --git a/3rdparty/libzip/lib/zip_crypto_win.h b/3rdparty/libzip/lib/zip_crypto_win.h new file mode 100644 index 0000000000..a533fe2df3 --- /dev/null +++ b/3rdparty/libzip/lib/zip_crypto_win.h @@ -0,0 +1,53 @@ +/* + zip_crypto_win.h -- Windows Crypto API wrapper. + Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HAD_ZIP_CRYPTO_WIN_H +#define HAD_ZIP_CRYPTO_WIN_H + +#define HAVE_SECURE_RANDOM + +typedef struct _zip_crypto_aes_s _zip_crypto_aes_t; +typedef struct _zip_crypto_hmac_s _zip_crypto_hmac_t; + +void _zip_crypto_aes_free(_zip_crypto_aes_t *aes); +_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error); +bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out); + +bool _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length); + +_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error); +void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac); +bool _zip_crypto_hmac(_zip_crypto_hmac_t *hmac, zip_uint8_t *data, zip_uint64_t length); +bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data); + +#endif /* HAD_ZIP_CRYPTO_WIN_H */ diff --git a/3rdparty/libzip/lib/zip_delete.c b/3rdparty/libzip/lib/zip_delete.c new file mode 100644 index 0000000000..676c16bf24 --- /dev/null +++ b/3rdparty/libzip/lib/zip_delete.c @@ -0,0 +1,68 @@ +/* + zip_delete.c -- delete file from zip archive + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_delete(zip_t *za, zip_uint64_t idx) { + const char *name; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if ((name = _zip_get_name(za, idx, 0, &za->error)) == NULL) { + return -1; + } + + if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) { + return -1; + } + + /* allow duplicate file names, because the file will + * be removed directly afterwards */ + if (_zip_unchange(za, idx, 1) != 0) + return -1; + + za->entry[idx].deleted = 1; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_dir_add.c b/3rdparty/libzip/lib/zip_dir_add.c new file mode 100644 index 0000000000..c01081916a --- /dev/null +++ b/3rdparty/libzip/lib/zip_dir_add.c @@ -0,0 +1,92 @@ +/* + zip_dir_add.c -- add directory + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +ZIP_EXTERN zip_int64_t +zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) { + size_t len; + zip_int64_t idx; + char *s; + zip_source_t *source; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (name == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + s = NULL; + len = strlen(name); + + if (name[len - 1] != '/') { + if (len > SIZE_MAX - 2 || (s = (char *)malloc(len + 2)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + (void)strncpy_s(s, len + 2, name, len); + s[len] = '/'; + s[len + 1] = '\0'; + } + + if ((source = zip_source_buffer(za, NULL, 0, 0)) == NULL) { + free(s); + return -1; + } + + idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags); + + free(s); + + if (idx < 0) + zip_source_free(source); + else { + if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) { + zip_delete(za, (zip_uint64_t)idx); + return -1; + } + } + + return idx; +} diff --git a/3rdparty/libzip/lib/zip_dirent.c b/3rdparty/libzip/lib/zip_dirent.c new file mode 100644 index 0000000000..45a2a6a29e --- /dev/null +++ b/3rdparty/libzip/lib/zip_dirent.c @@ -0,0 +1,1207 @@ +/* + zip_dirent.c -- read directory entry (local or central), clean dirent + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include +#include +#include +#include + +#include "zipint.h" + +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 +_zip_cdir_free(zip_cdir_t *cd) { + zip_uint64_t i; + + if (!cd) + return; + + for (i = 0; i < cd->nentry; i++) + _zip_entry_finalize(cd->entry + i); + free(cd->entry); + _zip_string_free(cd->comment); + free(cd); +} + + +zip_cdir_t * +_zip_cdir_new(zip_uint64_t nentry, zip_error_t *error) { + zip_cdir_t *cd; + + if ((cd = (zip_cdir_t *)malloc(sizeof(*cd))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + 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; + } + + return cd; +} + + +bool +_zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error) { + zip_uint64_t i, new_alloc; + zip_entry_t *new_entry; + + if (additional_entries == 0) { + return true; + } + + new_alloc = cd->nentry_alloc + additional_entries; + + if (new_alloc < additional_entries || new_alloc > SIZE_MAX / sizeof(*(cd->entry))) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + if ((new_entry = (zip_entry_t *)realloc(cd->entry, sizeof(*(cd->entry)) * (size_t)new_alloc)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + cd->entry = new_entry; + + for (i = cd->nentry; i < new_alloc; i++) { + _zip_entry_init(cd->entry + i); + } + + cd->nentry = cd->nentry_alloc = new_alloc; + + return true; +} + + +zip_int64_t +_zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) { + zip_uint64_t offset, size; + zip_string_t *comment; + zip_uint8_t buf[EOCDLEN + EOCD64LEN + EOCD64LOCLEN]; + zip_buffer_t *buffer; + zip_int64_t off; + zip_uint64_t i; + bool is_zip64; + int ret; + zip_uint32_t cdir_crc; + + if ((off = zip_source_tell_write(za->src)) < 0) { + zip_error_set_from_source(&za->error, za->src); + return -1; + } + offset = (zip_uint64_t)off; + + is_zip64 = false; + + if (ZIP_WANT_TORRENTZIP(za)) { + cdir_crc = (zip_uint32_t)crc32(0, NULL, 0); + za->write_crc = &cdir_crc; + } + + for (i = 0; i < survivors; i++) { + zip_entry_t *entry = za->entry + filelist[i].idx; + + if ((ret = _zip_dirent_write(za, entry->changes ? entry->changes : entry->orig, ZIP_FL_CENTRAL)) < 0) + return -1; + if (ret) + is_zip64 = true; + } + + za->write_crc = NULL; + + if ((off = zip_source_tell_write(za->src)) < 0) { + zip_error_set_from_source(&za->error, za->src); + return -1; + } + size = (zip_uint64_t)off - offset; + + if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX) { + is_zip64 = true; + } + + if ((buffer = _zip_buffer_new(buf, sizeof(buf))) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + if (is_zip64) { + _zip_buffer_put(buffer, EOCD64_MAGIC, 4); + _zip_buffer_put_64(buffer, EOCD64LEN - 12); + _zip_buffer_put_16(buffer, 45); + _zip_buffer_put_16(buffer, 45); + _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_64(buffer, survivors); + _zip_buffer_put_64(buffer, survivors); + _zip_buffer_put_64(buffer, size); + _zip_buffer_put_64(buffer, offset); + _zip_buffer_put(buffer, EOCD64LOC_MAGIC, 4); + _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_64(buffer, offset + size); + _zip_buffer_put_32(buffer, 1); + } + + _zip_buffer_put(buffer, EOCD_MAGIC, 4); + _zip_buffer_put_32(buffer, 0); + _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors)); + _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors)); + _zip_buffer_put_32(buffer, size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)size); + _zip_buffer_put_32(buffer, offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : (zip_uint32_t)offset); + + comment = za->comment_changed ? za->comment_changes : za->comment_orig; + + if (ZIP_WANT_TORRENTZIP(za)) { + _zip_buffer_put_16(buffer, TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH); + } + else { + _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0)); + } + + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return -1; + } + + if (_zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)) < 0) { + _zip_buffer_free(buffer); + return -1; + } + + _zip_buffer_free(buffer); + + if (ZIP_WANT_TORRENTZIP(za)) { + char torrentzip_comment[TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH + 1]; + snprintf(torrentzip_comment, sizeof(torrentzip_comment), TORRENTZIP_SIGNATURE "%08X", cdir_crc); + + if (_zip_write(za, torrentzip_comment, strlen(torrentzip_comment)) < 0) { + return -1; + } + } + else if (comment != NULL) { + if (_zip_write(za, comment->raw, comment->length) < 0) { + return -1; + } + } + + return (zip_int64_t)size; +} + + +zip_dirent_t * +_zip_dirent_clone(const zip_dirent_t *sde) { + zip_dirent_t *tde; + + if ((tde = (zip_dirent_t *)malloc(sizeof(*tde))) == NULL) + return NULL; + + if (sde) + (void)memcpy_s(tde, sizeof(*tde), sde, sizeof(*sde)); + else + _zip_dirent_init(tde); + + tde->changed = 0; + tde->cloned = 1; + + return tde; +} + + +void +_zip_dirent_finalize(zip_dirent_t *zde) { + if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) { + _zip_string_free(zde->filename); + zde->filename = NULL; + } + if (!zde->cloned || zde->changed & ZIP_DIRENT_EXTRA_FIELD) { + _zip_ef_free(zde->extra_fields); + zde->extra_fields = NULL; + } + if (!zde->cloned || zde->changed & ZIP_DIRENT_COMMENT) { + _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; + } +} + + +void +_zip_dirent_free(zip_dirent_t *zde) { + if (zde == NULL) + return; + + _zip_dirent_finalize(zde); + free(zde); +} + + +void +_zip_dirent_init(zip_dirent_t *de) { + de->changed = 0; + de->local_extra_fields_read = 0; + de->cloned = 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; + de->crc = 0; + de->comp_size = 0; + de->uncomp_size = 0; + de->filename = NULL; + de->extra_fields = NULL; + de->comment = NULL; + de->disk_number = 0; + 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; +} + + +bool +_zip_dirent_needs_zip64(const zip_dirent_t *de, zip_flags_t flags) { + if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX || ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX)) + return true; + + return false; +} + + +zip_dirent_t * +_zip_dirent_new(void) { + zip_dirent_t *de; + + if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL) + return NULL; + + _zip_dirent_init(de); + return de; +} + + +/* _zip_dirent_read(zde, fp, bufp, left, localp, error): + Fills the zip directory entry zde. + + If buffer is non-NULL, data is taken from there; otherwise data is read from fp as needed. + + If local is true, it reads a local header instead of a central directory entry. + + Returns size of dirent read if successful. On error, error is filled in and -1 is returned. +*/ + +zip_int64_t +_zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, bool local, zip_error_t *error) { + zip_uint8_t buf[CDENTRYSIZE]; + zip_uint16_t dostime, dosdate; + zip_uint32_t size, variable_size; + zip_uint16_t filename_len, comment_len, ef_len; + + bool from_buffer = (buffer != NULL); + + size = local ? LENTRYSIZE : CDENTRYSIZE; + + if (buffer) { + if (_zip_buffer_left(buffer) < size) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + return -1; + } + } + else { + if ((buffer = _zip_buffer_new_from_source(src, size, buf, error)) == NULL) { + return -1; + } + } + + if (memcmp(_zip_buffer_get(buffer, 4), (local ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + + /* convert buffercontents to zip_dirent */ + + _zip_dirent_init(zde); + if (!local) + zde->version_madeby = _zip_buffer_get_16(buffer); + else + zde->version_madeby = 0; + zde->version_needed = _zip_buffer_get_16(buffer); + zde->bitflags = _zip_buffer_get_16(buffer); + zde->comp_method = _zip_buffer_get_16(buffer); + + /* convert to time_t */ + dostime = _zip_buffer_get_16(buffer); + dosdate = _zip_buffer_get_16(buffer); + zde->last_mod = _zip_d2u_time(dostime, dosdate); + + zde->crc = _zip_buffer_get_32(buffer); + zde->comp_size = _zip_buffer_get_32(buffer); + zde->uncomp_size = _zip_buffer_get_32(buffer); + + filename_len = _zip_buffer_get_16(buffer); + ef_len = _zip_buffer_get_16(buffer); + + if (local) { + comment_len = 0; + zde->disk_number = 0; + zde->int_attrib = 0; + zde->ext_attrib = 0; + zde->offset = 0; + } + else { + comment_len = _zip_buffer_get_16(buffer); + zde->disk_number = _zip_buffer_get_16(buffer); + zde->int_attrib = _zip_buffer_get_16(buffer); + zde->ext_attrib = _zip_buffer_get_32(buffer); + zde->offset = _zip_buffer_get_32(buffer); + } + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + 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; + + variable_size = (zip_uint32_t)filename_len + (zip_uint32_t)ef_len + (zip_uint32_t)comment_len; + + if (from_buffer) { + if (_zip_buffer_left(buffer) < variable_size) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW); + return -1; + } + } + else { + _zip_buffer_free(buffer); + + if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) { + return -1; + } + } + + if (filename_len) { + zde->filename = _zip_read_string(buffer, src, filename_len, 1, error); + if (!zde->filename) { + if (zip_error_code_zip(error) == ZIP_ER_EOF) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW); + } + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + + if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { + if (_zip_guess_encoding(zde->filename, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + } + } + + if (ef_len) { + zip_uint8_t *ef = _zip_read_data(buffer, src, ef_len, 0, error); + + if (ef == NULL) { + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) { + free(ef); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + free(ef); + if (local) + zde->local_extra_fields_read = 1; + } + + if (comment_len) { + zde->comment = _zip_read_string(buffer, src, comment_len, 0, error); + if (!zde->comment) { + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + if (zde->bitflags & ZIP_GPBF_ENCODING_UTF_8) { + if (_zip_guess_encoding(zde->comment, ZIP_ENCODING_UTF8_KNOWN) == ZIP_ENCODING_ERROR) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_UTF8_IN_COMMENT); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + } + } + + zde->filename = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_NAME, zde->filename); + zde->comment = _zip_dirent_process_ef_utf_8(zde, ZIP_EF_UTF_8_COMMENT, zde->comment); + + /* Zip64 */ + + if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) { + zip_uint16_t got_len; + const zip_uint8_t *ef = _zip_ef_get_by_id(zde->extra_fields, &got_len, ZIP_EF_ZIP64, 0, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error); + if (ef != NULL) { + if (!zip_dirent_process_ef_zip64(zde, ef, got_len, local, error)) { + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + } + } + + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; + } + if (!from_buffer) { + _zip_buffer_free(buffer); + } + + /* zip_source_seek / zip_source_tell don't support values > ZIP_INT64_MAX */ + if (zde->offset > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + 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 + (zip_int64_t)variable_size; +} + +bool zip_dirent_process_ef_zip64(zip_dirent_t* zde, const zip_uint8_t* ef, zip_uint64_t got_len, bool local, zip_error_t* error) { + zip_buffer_t *ef_buffer; + + if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + if (zde->uncomp_size == ZIP_UINT32_MAX) { + zde->uncomp_size = _zip_buffer_get_64(ef_buffer); + } + else if (local) { + /* From appnote.txt: This entry in the Local header MUST + include BOTH original and compressed file size fields. */ + (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */ + } + if (zde->comp_size == ZIP_UINT32_MAX) { + zde->comp_size = _zip_buffer_get_64(ef_buffer); + } + if (!local) { + if (zde->offset == ZIP_UINT32_MAX) { + zde->offset = _zip_buffer_get_64(ef_buffer); + } + if (zde->disk_number == ZIP_UINT16_MAX) { + zde->disk_number = _zip_buffer_get_32(ef_buffer); + } + } + + if (!_zip_buffer_eof(ef_buffer)) { + /* accept additional fields if values match */ + bool ok = true; + switch (got_len) { + case 28: + _zip_buffer_set_offset(ef_buffer, 24); + if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) { + ok = false; + } + /* fallthrough */ + case 24: + _zip_buffer_set_offset(ef_buffer, 0); + if ((zde->uncomp_size != _zip_buffer_get_64(ef_buffer)) || (zde->comp_size != _zip_buffer_get_64(ef_buffer)) || (zde->offset != _zip_buffer_get_64(ef_buffer))) { + ok = false; + } + break; + + default: + ok = false; + } + if (!ok) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_ZIP64_EF); + _zip_buffer_free(ef_buffer); + return false; + } + } + _zip_buffer_free(ef_buffer); + + return true; +} + + +static zip_string_t * +_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str) { + zip_uint16_t ef_len; + zip_uint32_t ef_crc; + zip_buffer_t *buffer; + + const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL); + + if (ef == NULL || ef_len < 5 || ef[0] != 1) { + return str; + } + + if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) { + return str; + } + + _zip_buffer_get_8(buffer); + ef_crc = _zip_buffer_get_32(buffer); + + if (_zip_string_crc32(str) == ef_crc) { + zip_uint16_t len = (zip_uint16_t)_zip_buffer_left(buffer); + zip_string_t *ef_str = _zip_string_new(_zip_buffer_get(buffer, len), len, ZIP_FL_ENC_UTF_8, NULL); + + if (ef_str != NULL) { + _zip_string_free(str); + str = ef_str; + } + } + + _zip_buffer_free(buffer); + + return str; +} + + +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, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF); + 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: + crc_valid = false; + /* TODO: When checking consistency, check that crc is 0. */ + 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, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF); + _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) { + zip_int32_t size; + bool local = (flags & ZIP_EF_LOCAL) != 0; + int i; + zip_uint8_t b[6]; + zip_buffer_t *buffer; + + size = local ? LENTRYSIZE : CDENTRYSIZE; + + if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) { + zip_error_set_from_source(error, src); + return -1; + } + + if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) { + return -1; + } + + for (i = 0; i < (local ? 2 : 3); i++) { + size += _zip_buffer_get_16(buffer); + } + + if (!_zip_buffer_eof(buffer)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return -1; + } + + _zip_buffer_free(buffer); + return size; +} + + +/* _zip_dirent_write + Writes zip directory entry. + + If flags & ZIP_EF_LOCAL, it writes a local header instead of a central + directory entry. If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed. + + Returns 0 if successful, 1 if successful and wrote ZIP64 extra field. On error, error is filled in and -1 is + returned. +*/ + +int +_zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) { + zip_uint16_t dostime, dosdate; + zip_encoding_type_t com_enc, name_enc; + zip_extra_field_t *ef; + zip_extra_field_t *ef64; + zip_uint32_t ef_total_size; + bool is_zip64; + bool is_really_zip64; + bool is_winzip_aes; + zip_uint8_t buf[CDENTRYSIZE]; + zip_buffer_t *buffer; + + ef = NULL; + + name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN); + com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN); + + if ((name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_ASCII) || (name_enc == ZIP_ENCODING_ASCII && com_enc == ZIP_ENCODING_UTF8_KNOWN) || (name_enc == ZIP_ENCODING_UTF8_KNOWN && com_enc == ZIP_ENCODING_UTF8_KNOWN)) + de->bitflags |= ZIP_GPBF_ENCODING_UTF_8; + else { + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCODING_UTF_8; + if (name_enc == ZIP_ENCODING_UTF8_KNOWN) { + ef = _zip_ef_utf8(ZIP_EF_UTF_8_NAME, de->filename, &za->error); + if (ef == NULL) + return -1; + } + if ((flags & ZIP_FL_LOCAL) == 0 && com_enc == ZIP_ENCODING_UTF8_KNOWN) { + zip_extra_field_t *ef2 = _zip_ef_utf8(ZIP_EF_UTF_8_COMMENT, de->comment, &za->error); + if (ef2 == NULL) { + _zip_ef_free(ef); + return -1; + } + ef2->next = ef; + ef = ef2; + } + } + + 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]; + zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64)); + if (ef_buffer == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_ef_free(ef); + return -1; + } + + if (flags & ZIP_FL_LOCAL) { + if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->uncomp_size); + _zip_buffer_put_64(ef_buffer, de->comp_size); + } + } + else { + if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX || de->offset > ZIP_UINT32_MAX) { + if (de->uncomp_size >= ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->uncomp_size); + } + if (de->comp_size >= ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->comp_size); + } + if (de->offset >= ZIP_UINT32_MAX) { + _zip_buffer_put_64(ef_buffer, de->offset); + } + } + } + + 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; + } + + ef64 = _zip_ef_new(ZIP_EF_ZIP64, (zip_uint16_t)(_zip_buffer_offset(ef_buffer)), ef_zip64, ZIP_EF_BOTH); + _zip_buffer_free(ef_buffer); + ef64->next = ef; + 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); + return -1; + } + + _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4); + + if ((flags & ZIP_FL_LOCAL) == 0) { + _zip_buffer_put_16(buffer, de->version_madeby); + } + _zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed)); + _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); + } + + if (ZIP_WANT_TORRENTZIP(za)) { + dostime = 0xbc00; + dosdate = 0x2198; + } + else { + _zip_u2d_time(de->last_mod, &dostime, &dosdate); + } + _zip_buffer_put_16(buffer, dostime); + _zip_buffer_put_16(buffer, dosdate); + + 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 + * both compressed and uncompressed sizes (even if one of the + * two is smaller than 0xFFFFFFFF); on the other hand, those + * may only appear when the corresponding standard entry is + * 0xFFFFFFFF. (appnote.txt 4.5.3) */ + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + } + else { + if (de->comp_size < ZIP_UINT32_MAX) { + _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size); + } + else { + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + } + if (de->uncomp_size < ZIP_UINT32_MAX) { + _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size); + } + else { + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + } + } + + _zip_buffer_put_16(buffer, _zip_string_length(de->filename)); + ef_total_size = (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH); + if (!ZIP_WANT_TORRENTZIP(za)) { + /* TODO: check for overflow */ + ef_total_size += (zip_uint32_t)_zip_ef_size(de->extra_fields, flags); + } + _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size); + + if ((flags & ZIP_FL_LOCAL) == 0) { + _zip_buffer_put_16(buffer, ZIP_WANT_TORRENTZIP(za) ? 0 : _zip_string_length(de->comment)); + _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number); + _zip_buffer_put_16(buffer, de->int_attrib); + _zip_buffer_put_32(buffer, de->ext_attrib); + if (de->offset < ZIP_UINT32_MAX) + _zip_buffer_put_32(buffer, (zip_uint32_t)de->offset); + else + _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); + } + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + _zip_ef_free(ef); + return -1; + } + + if (_zip_write(za, buf, _zip_buffer_offset(buffer)) < 0) { + _zip_buffer_free(buffer); + _zip_ef_free(ef); + return -1; + } + + _zip_buffer_free(buffer); + + if (de->filename) { + if (_zip_string_write(za, de->filename) < 0) { + _zip_ef_free(ef); + return -1; + } + } + + if (ef) { + if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) { + _zip_ef_free(ef); + return -1; + } + } + _zip_ef_free(ef); + if (de->extra_fields && !ZIP_WANT_TORRENTZIP(za)) { + if (_zip_ef_write(za, de->extra_fields, flags) < 0) { + return -1; + } + } + + if ((flags & ZIP_FL_LOCAL) == 0 && !ZIP_WANT_TORRENTZIP(za)) { + if (de->comment) { + if (_zip_string_write(za, de->comment) < 0) { + return -1; + } + } + } + + + return is_zip64; +} + + +time_t +_zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate) { + struct tm tm; + + memset(&tm, 0, sizeof(tm)); + + /* let mktime decide if DST is in effect */ + tm.tm_isdst = -1; + + tm.tm_year = ((ddate >> 9) & 127) + 1980 - 1900; + tm.tm_mon = ((ddate >> 5) & 15) - 1; + tm.tm_mday = ddate & 31; + + tm.tm_hour = (dtime >> 11) & 31; + tm.tm_min = (dtime >> 5) & 63; + tm.tm_sec = (dtime << 1) & 62; + + return mktime(&tm); +} + + +static zip_extra_field_t * +_zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) { + const zip_uint8_t *raw; + zip_uint32_t len; + zip_buffer_t *buffer; + zip_extra_field_t *ef; + + if ((raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) { + /* error already set */ + return NULL; + } + + if (len + 5 > ZIP_UINT16_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */ + return NULL; + } + + if ((buffer = _zip_buffer_new(NULL, len + 5)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + _zip_buffer_put_8(buffer, 1); + _zip_buffer_put_32(buffer, _zip_string_crc32(str)); + _zip_buffer_put(buffer, raw, len); + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return NULL; + } + + ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH); + _zip_buffer_free(buffer); + + return ef; +} + + +zip_dirent_t * +_zip_get_dirent(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) { + if (error == NULL) + error = &za->error; + + if (idx >= za->nentry) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((flags & ZIP_FL_UNCHANGED) || za->entry[idx].changes == NULL) { + if (za->entry[idx].orig == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + if (za->entry[idx].deleted && (flags & ZIP_FL_UNCHANGED) == 0) { + zip_error_set(error, ZIP_ER_DELETED, 0); + return NULL; + } + return za->entry[idx].orig; + } + else + return za->entry[idx].changes; +} + + +void +_zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) { + struct tm *tpm; + struct tm tm; + tpm = zip_localtime(&intime, &tm); + if (tpm == NULL) { + /* if localtime fails, return an arbitrary date (1980-01-01 00:00:00) */ + *ddate = (1 << 5) + 1; + *dtime = 0; + return; + } + if (tpm->tm_year < 80) { + tpm->tm_year = 80; + } + + *ddate = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday); + *dtime = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1)); +} + + +void +_zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64, zip_uint32_t changed) { + zip_uint16_t length; + + if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) { + zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK; + de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask); + } + if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) { + de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0); + } + /* manually set attributes are preferred over attributes provided by source */ + if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) { + de->ext_attrib = attributes->external_file_attributes; + } + + if (de->comp_method == ZIP_CM_LZMA) { + de->version_needed = 63; + } + else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) { + de->version_needed = 51; + } + else if (de->comp_method == ZIP_CM_BZIP2) { + de->version_needed = 46; + } + else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) { + de->version_needed = 45; + } + else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) { + de->version_needed = 20; + } + else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') { + de->version_needed = 20; + } + else { + de->version_needed = 10; + } + + if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) { + de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed); + } + + de->version_madeby = 63 | (de->version_madeby & 0xff00); + if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) { + de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8); + } +} + + +/* _zip_dirent_torrent_normalize(de); + Set values suitable for torrentzip. +*/ + +void zip_dirent_torrentzip_normalize(zip_dirent_t *de) { + de->version_madeby = 0; + de->version_needed = 20; /* 2.0 */ + de->bitflags = 2; /* maximum compression */ + de->comp_method = ZIP_CM_DEFLATE; + de->compression_level = TORRENTZIP_COMPRESSION_FLAGS; + de->disk_number = 0; + de->int_attrib = 0; + de->ext_attrib = 0; + + /* last_mod, extra_fields, and comment are normalized in zip_dirent_write() directly */ + +} diff --git a/3rdparty/libzip/lib/zip_discard.c b/3rdparty/libzip/lib/zip_discard.c new file mode 100644 index 0000000000..d1dc4f8b0d --- /dev/null +++ b/3rdparty/libzip/lib/zip_discard.c @@ -0,0 +1,80 @@ +/* + zip_discard.c -- discard and free struct zip + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +/* zip_discard: + frees the space allocated to a zipfile struct, and closes the + corresponding file. */ + +void +zip_discard(zip_t *za) { + zip_uint64_t i; + + if (za == NULL) + return; + + if (za->src) { + zip_source_close(za->src); + zip_source_free(za->src); + } + + free(za->default_password); + _zip_string_free(za->comment_orig); + _zip_string_free(za->comment_changes); + + _zip_hash_free(za->names); + + if (za->entry) { + for (i = 0; i < za->nentry; i++) + _zip_entry_finalize(za->entry + i); + free(za->entry); + } + + for (i = 0; i < za->nopen_source; i++) { + _zip_source_invalidate(za->open_source[i]); + } + free(za->open_source); + + _zip_progress_free(za->progress); + + zip_error_fini(&za->error); + + free(za); + + return; +} diff --git a/3rdparty/libzip/lib/zip_entry.c b/3rdparty/libzip/lib/zip_entry.c new file mode 100644 index 0000000000..35a36e4a16 --- /dev/null +++ b/3rdparty/libzip/lib/zip_entry.c @@ -0,0 +1,51 @@ +/* + zip_entry.c -- struct zip_entry helper functions + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +void +_zip_entry_finalize(zip_entry_t *e) { + _zip_unchange_data(e); + _zip_dirent_free(e->orig); + _zip_dirent_free(e->changes); +} + + +void +_zip_entry_init(zip_entry_t *e) { + e->orig = NULL; + e->changes = NULL; + e->source = NULL; + e->deleted = 0; +} diff --git a/3rdparty/libzip/lib/zip_error.c b/3rdparty/libzip/lib/zip_error.c new file mode 100644 index 0000000000..c498e08605 --- /dev/null +++ b/3rdparty/libzip/lib/zip_error.c @@ -0,0 +1,156 @@ +/* + zip_error.c -- zip_error_t helper functions + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_error_code_system(const zip_error_t *error) { + return error->sys_err; +} + + +ZIP_EXTERN int +zip_error_code_zip(const zip_error_t *error) { + return error->zip_err; +} + + +ZIP_EXTERN void +zip_error_fini(zip_error_t *err) { + free(err->str); + err->str = NULL; +} + + +ZIP_EXTERN void +zip_error_init(zip_error_t *err) { + err->zip_err = ZIP_ER_OK; + err->sys_err = 0; + err->str = NULL; +} + +ZIP_EXTERN void +zip_error_init_with_code(zip_error_t *error, int ze) { + zip_error_init(error); + error->zip_err = ze; + switch (zip_error_system_type(error)) { + case ZIP_ET_SYS: + case ZIP_ET_LIBZIP: + error->sys_err = errno; + break; + + default: + error->sys_err = 0; + break; + } +} + + +ZIP_EXTERN int +zip_error_system_type(const zip_error_t *error) { + if (error->zip_err < 0 || error->zip_err >= _zip_err_str_count) + return ZIP_ET_NONE; + + return _zip_err_str[error->zip_err].type; +} + + +void +_zip_error_clear(zip_error_t *err) { + if (err == NULL) + return; + + err->zip_err = ZIP_ER_OK; + err->sys_err = 0; +} + + +void +_zip_error_copy(zip_error_t *dst, const zip_error_t *src) { + if (dst == NULL) { + return; + } + + dst->zip_err = src->zip_err; + dst->sys_err = src->sys_err; +} + + +void +_zip_error_get(const zip_error_t *err, int *zep, int *sep) { + if (zep) + *zep = err->zip_err; + if (sep) { + if (zip_error_system_type(err) != ZIP_ET_NONE) + *sep = err->sys_err; + else + *sep = 0; + } +} + + +void +zip_error_set(zip_error_t *err, int ze, int se) { + if (err) { + err->zip_err = ze; + err->sys_err = se; + } +} + + +void +zip_error_set_from_source(zip_error_t *err, zip_source_t *src) { + if (src == NULL) { + zip_error_set(err, ZIP_ER_INVAL, 0); + return; + } + + _zip_error_copy(err, zip_source_error(src)); +} + + +zip_int64_t +zip_error_to_data(const zip_error_t *error, void *data, zip_uint64_t length) { + int *e = (int *)data; + + if (length < sizeof(int) * 2) { + return -1; + } + + e[0] = zip_error_code_zip(error); + e[1] = zip_error_code_system(error); + return sizeof(int) * 2; +} diff --git a/3rdparty/libzip/lib/zip_error_clear.c b/3rdparty/libzip/lib/zip_error_clear.c new file mode 100644 index 0000000000..94ff5062d5 --- /dev/null +++ b/3rdparty/libzip/lib/zip_error_clear.c @@ -0,0 +1,44 @@ +/* + zip_error_clear.c -- clear zip error + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN void +zip_error_clear(zip_t *za) { + if (za == NULL) + return; + + _zip_error_clear(&za->error); +} diff --git a/3rdparty/libzip/lib/zip_error_get.c b/3rdparty/libzip/lib/zip_error_get.c new file mode 100644 index 0000000000..c0418f0d0c --- /dev/null +++ b/3rdparty/libzip/lib/zip_error_get.c @@ -0,0 +1,54 @@ +/* + zip_error_get.c -- get zip error + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN void +zip_error_get(zip_t *za, int *zep, int *sep) { + _zip_error_get(&za->error, zep, sep); +} + + +ZIP_EXTERN zip_error_t * +zip_get_error(zip_t *za) { + return &za->error; +} + + +ZIP_EXTERN zip_error_t * +zip_file_get_error(zip_file_t *f) { + return &f->error; +} diff --git a/3rdparty/libzip/lib/zip_error_get_sys_type.c b/3rdparty/libzip/lib/zip_error_get_sys_type.c new file mode 100644 index 0000000000..a22ffb0367 --- /dev/null +++ b/3rdparty/libzip/lib/zip_error_get_sys_type.c @@ -0,0 +1,45 @@ +/* + zip_error_get_sys_type.c -- return type of system error code + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN int +zip_error_get_sys_type(int ze) { + if (ze < 0 || ze >= _zip_err_str_count) { + return 0; + } + + return _zip_err_str[ze].type; +} diff --git a/3rdparty/libzip/lib/zip_error_strerror.c b/3rdparty/libzip/lib/zip_error_strerror.c new file mode 100644 index 0000000000..fe04cbb4f4 --- /dev/null +++ b/3rdparty/libzip/lib/zip_error_strerror.c @@ -0,0 +1,128 @@ +/* + zip_error_sterror.c -- get string representation of struct zip_error + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include +#include + +#include "zipint.h" + +ZIP_EXTERN const char * +zip_error_strerror(zip_error_t *err) { + const char *zip_error_string, *system_error_string; + char *s; + char *system_error_buffer = NULL; + + zip_error_fini(err); + + if (err->zip_err < 0 || err->zip_err >= _zip_err_str_count) { + system_error_buffer = (char *)malloc(128); + snprintf_s(system_error_buffer, 128, "Unknown error %d", err->zip_err); + system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */ + zip_error_string = NULL; + system_error_string = system_error_buffer; + } + else { + zip_error_string = _zip_err_str[err->zip_err].description; + + switch (_zip_err_str[err->zip_err].type) { + case ZIP_ET_SYS: { + size_t len = strerrorlen_s(err->sys_err) + 1; + system_error_buffer = malloc(len); + strerror_s(system_error_buffer, len, err->sys_err); + system_error_string = system_error_buffer; + break; + } + + case ZIP_ET_ZLIB: + system_error_string = zError(err->sys_err); + break; + + case ZIP_ET_LIBZIP: { + zip_uint8_t error = GET_ERROR_FROM_DETAIL(err->sys_err); + int index = GET_INDEX_FROM_DETAIL(err->sys_err); + + if (error == 0) { + system_error_string = NULL; + } + else if (error >= _zip_err_details_count) { + system_error_buffer = (char *)malloc(128); + snprintf_s(system_error_buffer, 128, "invalid detail error %u", error); + system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */ + system_error_string = system_error_buffer; + } + else if (_zip_err_details[error].type == ZIP_DETAIL_ET_ENTRY && index < MAX_DETAIL_INDEX) { + system_error_buffer = (char *)malloc(128); + snprintf_s(system_error_buffer, 128, "entry %d: %s", index, _zip_err_details[error].description); + system_error_buffer[128 - 1] = '\0'; /* make sure string is NUL-terminated */ + system_error_string = system_error_buffer; + } + else { + system_error_string = _zip_err_details[error].description; + } + break; + } + + default: + system_error_string = NULL; + } + } + + if (system_error_string == NULL) { + free(system_error_buffer); + return zip_error_string; + } + else { + size_t length = strlen(system_error_string); + if (zip_error_string) { + size_t length_error = strlen(zip_error_string); + if (length + length_error + 2 < length) { + free(system_error_buffer); + return _zip_err_str[ZIP_ER_MEMORY].description; + } + length += length_error + 2; + } + if (length == SIZE_MAX || (s = (char *)malloc(length + 1)) == NULL) { + free(system_error_buffer); + return _zip_err_str[ZIP_ER_MEMORY].description; + } + + snprintf_s(s, length + 1, "%s%s%s", (zip_error_string ? zip_error_string : ""), (zip_error_string ? ": " : ""), system_error_string); + err->str = s; + + free(system_error_buffer); + return s; + } +} diff --git a/3rdparty/libzip/lib/zip_error_to_str.c b/3rdparty/libzip/lib/zip_error_to_str.c new file mode 100644 index 0000000000..b60b78813b --- /dev/null +++ b/3rdparty/libzip/lib/zip_error_to_str.c @@ -0,0 +1,58 @@ +/* + zip_error_to_str.c -- get string representation of zip error code + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN int +zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) { + zip_error_t error; + const char *error_string; + int ret; + + zip_error_init(&error); + zip_error_set(&error, ze, se); + + error_string = zip_error_strerror(&error); + + ret = snprintf_s(buf, ZIP_MIN(len, SIZE_MAX), error_string, strlen(error_string)); + + zip_error_fini(&error); + + return ret; +} diff --git a/3rdparty/libzip/lib/zip_extra_field.c b/3rdparty/libzip/lib/zip_extra_field.c new file mode 100644 index 0000000000..7aed12adb5 --- /dev/null +++ b/3rdparty/libzip/lib/zip_extra_field.c @@ -0,0 +1,427 @@ +/* + zip_extra_field.c -- manipulate extra fields + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#include "zipint.h" + + +zip_extra_field_t * +_zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) { + zip_extra_field_t *head, *prev, *def; + + head = prev = NULL; + + while (ef) { + if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + _zip_ef_free(head); + return NULL; + } + + if (head == NULL) + head = def; + if (prev) + prev->next = def; + prev = def; + + ef = ef->next; + } + + return head; +} + + +zip_extra_field_t * +_zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags) { + zip_extra_field_t *head, *prev; + int i; + + i = 0; + head = ef; + prev = NULL; + for (; ef; ef = (prev ? prev->next : head)) { + if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) { + if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) { + ef->flags &= ~(flags & ZIP_EF_BOTH); + if ((ef->flags & ZIP_EF_BOTH) == 0) { + if (prev) + prev->next = ef->next; + else + head = ef->next; + ef->next = NULL; + _zip_ef_free(ef); + + if (id_idx == ZIP_EXTRA_FIELD_ALL) + continue; + } + } + + i++; + if (i > id_idx) + break; + } + prev = ef; + } + + return head; +} + + +void +_zip_ef_free(zip_extra_field_t *ef) { + zip_extra_field_t *ef2; + + while (ef) { + ef2 = ef->next; + free(ef->data); + free(ef); + ef = ef2; + } +} + + +const zip_uint8_t * +_zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, zip_error_t *error) { + static const zip_uint8_t empty[1] = {'\0'}; + + int i; + + i = 0; + for (; ef; ef = ef->next) { + if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) { + if (i < id_idx) { + i++; + continue; + } + + if (lenp) + *lenp = ef->size; + if (ef->size > 0) + return ef->data; + else + return empty; + } + } + + zip_error_set(error, ZIP_ER_NOENT, 0); + return NULL; +} + + +zip_extra_field_t * +_zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) { + zip_extra_field_t *ef2, *tt, *tail; + int duplicate; + + if (to == NULL) + return from; + + for (tail = to; tail->next; tail = tail->next) + ; + + for (; from; from = ef2) { + ef2 = from->next; + + duplicate = 0; + for (tt = to; tt; tt = tt->next) { + if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) { + tt->flags |= (from->flags & ZIP_EF_BOTH); + duplicate = 1; + break; + } + } + + from->next = NULL; + if (duplicate) + _zip_ef_free(from); + else + tail = tail->next = from; + } + + return to; +} + + +zip_extra_field_t * +_zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags) { + zip_extra_field_t *ef; + + if ((ef = (zip_extra_field_t *)malloc(sizeof(*ef))) == NULL) + return NULL; + + ef->next = NULL; + ef->flags = flags; + ef->id = id; + ef->size = size; + if (size > 0) { + if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) { + free(ef); + return NULL; + } + } + else + ef->data = NULL; + + return ef; +} + + +bool +_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_extra_field_t **ef_head_p, zip_error_t *error) { + zip_buffer_t *buffer; + zip_extra_field_t *ef, *ef2, *ef_head; + + if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + ef_head = ef = NULL; + + while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) { + zip_uint16_t fid, flen; + zip_uint8_t *ef_data; + + fid = _zip_buffer_get_16(buffer); + flen = _zip_buffer_get_16(buffer); + ef_data = _zip_buffer_get(buffer, flen); + + if (ef_data == NULL) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_EF_LENGTH); + _zip_buffer_free(buffer); + _zip_ef_free(ef_head); + return false; + } + + if ((ef2 = _zip_ef_new(fid, flen, ef_data, flags)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + _zip_buffer_free(buffer); + _zip_ef_free(ef_head); + return false; + } + + if (ef_head) { + ef->next = ef2; + ef = ef2; + } + else + ef_head = ef = ef2; + } + + if (!_zip_buffer_eof(buffer)) { + /* Android APK files align stored file data with padding in extra fields; ignore. */ + /* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */ + /* buffer is at most 64k long, so this can't overflow. */ + size_t glen = _zip_buffer_left(buffer); + zip_uint8_t *garbage; + garbage = _zip_buffer_get(buffer, glen); + if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", (size_t)glen) != 0) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EF_TRAILING_GARBAGE); + _zip_buffer_free(buffer); + _zip_ef_free(ef_head); + return false; + } + } + + _zip_buffer_free(buffer); + + if (ef_head_p) { + *ef_head_p = ef_head; + } + else { + _zip_ef_free(ef_head); + } + + return true; +} + + +zip_extra_field_t * +_zip_ef_remove_internal(zip_extra_field_t *ef) { + zip_extra_field_t *ef_head; + zip_extra_field_t *prev, *next; + + ef_head = ef; + prev = NULL; + + while (ef) { + if (ZIP_EF_IS_INTERNAL(ef->id)) { + next = ef->next; + if (ef_head == ef) + ef_head = next; + ef->next = NULL; + _zip_ef_free(ef); + if (prev) + prev->next = next; + ef = next; + } + else { + prev = ef; + ef = ef->next; + } + } + + return ef_head; +} + + +zip_uint16_t +_zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) { + zip_uint16_t size; + + size = 0; + for (; ef; ef = ef->next) { + if (ef->flags & flags & ZIP_EF_BOTH) + size = (zip_uint16_t)(size + 4 + ef->size); + } + + return size; +} + + +int +_zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) { + zip_uint8_t b[4]; + zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b)); + + if (buffer == NULL) { + return -1; + } + + for (; ef; ef = ef->next) { + if (ef->flags & flags & ZIP_EF_BOTH) { + _zip_buffer_set_offset(buffer, 0); + _zip_buffer_put_16(buffer, ef->id); + _zip_buffer_put_16(buffer, ef->size); + if (!_zip_buffer_ok(buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(buffer); + return -1; + } + if (_zip_write(za, b, 4) < 0) { + _zip_buffer_free(buffer); + return -1; + } + if (ef->size > 0) { + if (_zip_write(za, ef->data, ef->size) < 0) { + _zip_buffer_free(buffer); + return -1; + } + } + } + } + + _zip_buffer_free(buffer); + return 0; +} + + +int +_zip_read_local_ef(zip_t *za, zip_uint64_t idx) { + zip_entry_t *e; + unsigned char b[4]; + zip_buffer_t *buffer; + zip_uint16_t fname_len, ef_len; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + e = za->entry + idx; + + if (e->orig == NULL || e->orig->local_extra_fields_read) + return 0; + + if (e->orig->offset + 26 > ZIP_INT64_MAX) { + zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG); + return -1; + } + + if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) { + zip_error_set_from_source(&za->error, za->src); + return -1; + } + + if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) { + return -1; + } + + fname_len = _zip_buffer_get_16(buffer); + ef_len = _zip_buffer_get_16(buffer); + + if (!_zip_buffer_eof(buffer)) { + _zip_buffer_free(buffer); + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + _zip_buffer_free(buffer); + + if (ef_len > 0) { + zip_extra_field_t *ef; + zip_uint8_t *ef_raw; + + if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) { + zip_error_set(&za->error, ZIP_ER_SEEK, errno); + return -1; + } + + ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error); + + if (ef_raw == NULL) + return -1; + + if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) { + free(ef_raw); + return -1; + } + free(ef_raw); + + if (ef) { + ef = _zip_ef_remove_internal(ef); + e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); + } + } + + e->orig->local_extra_fields_read = 1; + + if (e->changes && e->changes->local_extra_fields_read == 0) { + e->changes->extra_fields = e->orig->extra_fields; + e->changes->local_extra_fields_read = 1; + } + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_extra_field_api.c b/3rdparty/libzip/lib/zip_extra_field_api.c new file mode 100644 index 0000000000..560c71bb29 --- /dev/null +++ b/3rdparty/libzip/lib/zip_extra_field_api.c @@ -0,0 +1,367 @@ +/* + zip_extra_field_api.c -- public extra fields API functions + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_flags_t flags) { + zip_dirent_t *de; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + if (ZIP_WANT_TORRENTZIP(za)) { + zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0); + return -1; + } + + if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) + return -1; + + de = za->entry[idx].changes; + + de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ZIP_EXTRA_FIELD_ALL, ef_idx, flags); + return 0; +} + + +ZIP_EXTERN int +zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_flags_t flags) { + zip_dirent_t *de; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + if (ZIP_WANT_TORRENTZIP(za)) { + zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0); + return -1; + } + + if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) + return -1; + + de = za->entry[idx].changes; + + de->extra_fields = _zip_ef_delete_by_id(de->extra_fields, ef_id, ef_idx, flags); + return 0; +} + + +ZIP_EXTERN const zip_uint8_t * +zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_uint16_t *idp, zip_uint16_t *lenp, zip_flags_t flags) { + static const zip_uint8_t empty[1] = {'\0'}; + + zip_dirent_t *de; + zip_extra_field_t *ef; + int i; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return NULL; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return NULL; + + i = 0; + for (ef = de->extra_fields; ef; ef = ef->next) { + if (ef->flags & flags & ZIP_EF_BOTH) { + if (i < ef_idx) { + i++; + continue; + } + + if (idp) + *idp = ef->id; + if (lenp) + *lenp = ef->size; + if (ef->size > 0) + return ef->data; + else + return empty; + } + } + + zip_error_set(&za->error, ZIP_ER_NOENT, 0); + return NULL; +} + + +ZIP_EXTERN const zip_uint8_t * +zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, zip_uint16_t *lenp, zip_flags_t flags) { + zip_dirent_t *de; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return NULL; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return NULL; + + return _zip_ef_get_by_id(de->extra_fields, lenp, ef_id, ef_idx, flags, &za->error); +} + + +ZIP_EXTERN zip_int16_t +zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags) { + zip_dirent_t *de; + zip_extra_field_t *ef; + zip_uint16_t n; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return -1; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return -1; + + n = 0; + for (ef = de->extra_fields; ef; ef = ef->next) + if (ef->flags & flags & ZIP_EF_BOTH) + n++; + + return (zip_int16_t)n; +} + + +ZIP_EXTERN zip_int16_t +zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_flags_t flags) { + zip_dirent_t *de; + zip_extra_field_t *ef; + zip_uint16_t n; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL) + return -1; + + if (flags & ZIP_FL_LOCAL) + if (_zip_read_local_ef(za, idx) < 0) + return -1; + + n = 0; + for (ef = de->extra_fields; ef; ef = ef->next) + if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) + n++; + + return (zip_int16_t)n; +} + + +ZIP_EXTERN int +zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags) { + zip_dirent_t *de; + zip_uint16_t ls, cs; + zip_extra_field_t *ef, *ef_prev, *ef_new; + int i, found, new_len; + + if ((flags & ZIP_EF_BOTH) == 0) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + if (ZIP_WANT_TORRENTZIP(za)) { + zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0); + return -1; + } + + if (ZIP_EF_IS_INTERNAL(ef_id)) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_file_extra_field_prepare_for_change(za, idx) < 0) + return -1; + + de = za->entry[idx].changes; + + ef = de->extra_fields; + ef_prev = NULL; + i = 0; + found = 0; + + for (; ef; ef = ef->next) { + if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) { + if (i == ef_idx) { + found = 1; + break; + } + i++; + } + ef_prev = ef; + } + + if (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (flags & ZIP_EF_LOCAL) + ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL); + else + ls = 0; + if (flags & ZIP_EF_CENTRAL) + cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL); + else + cs = 0; + + new_len = ls > cs ? ls : cs; + if (found) + new_len -= ef->size + 4; + new_len += len + 4; + + if (new_len > ZIP_UINT16_MAX) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((ef_new = _zip_ef_new(ef_id, len, data, flags)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + if (found) { + if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) { + ef_new->next = ef->next; + ef->next = NULL; + _zip_ef_free(ef); + if (ef_prev) + ef_prev->next = ef_new; + else + de->extra_fields = ef_new; + } + else { + ef->flags &= ~(flags & ZIP_EF_BOTH); + ef_new->next = ef->next; + ef->next = ef_new; + } + } + else if (ef_prev) { + ef_new->next = ef_prev->next; + ef_prev->next = ef_new; + } + else + de->extra_fields = ef_new; + + return 0; +} + + +int +_zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx) { + zip_entry_t *e; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + e = za->entry + idx; + + if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD)) + return 0; + + if (e->orig) { + if (_zip_read_local_ef(za, idx) < 0) + return -1; + } + + if (e->changes == NULL) { + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + if (e->orig && e->orig->extra_fields) { + if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL) + return -1; + } + e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_fclose.c b/3rdparty/libzip/lib/zip_fclose.c new file mode 100644 index 0000000000..b820d98bdc --- /dev/null +++ b/3rdparty/libzip/lib/zip_fclose.c @@ -0,0 +1,54 @@ +/* + zip_fclose.c -- close file in zip archive + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_fclose(zip_file_t *zf) { + int ret; + + if (zf->src) + zip_source_free(zf->src); + + ret = 0; + if (zf->error.zip_err) + ret = zf->error.zip_err; + + zip_error_fini(&zf->error); + free(zf); + return ret; +} diff --git a/3rdparty/libzip/lib/zip_fdopen.c b/3rdparty/libzip/lib/zip_fdopen.c new file mode 100644 index 0000000000..e72c55dcad --- /dev/null +++ b/3rdparty/libzip/lib/zip_fdopen.c @@ -0,0 +1,91 @@ +/* + zip_fdopen.c -- open read-only archive from file descriptor + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" +#ifdef HAVE_UNISTD_H +#include +#endif + + +ZIP_EXTERN zip_t * +zip_fdopen(int fd_orig, int _flags, int *zep) { + int fd; + FILE *fp; + zip_t *za; + zip_source_t *src; + struct zip_error error; + + if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS | ZIP_RDONLY))) { + _zip_set_open_error(zep, NULL, ZIP_ER_INVAL); + return NULL; + } + +#ifndef ENABLE_FDOPEN + _zip_set_open_error(zep, NULL, ZIP_ER_OPNOTSUPP); + return NULL; +#else + /* We dup() here to avoid messing with the passed in fd. + We could not restore it to the original state in case of error. */ + + if ((fd = dup(fd_orig)) < 0) { + _zip_set_open_error(zep, NULL, ZIP_ER_OPEN); + return NULL; + } + + if ((fp = fdopen(fd, "rb")) == NULL) { + close(fd); + _zip_set_open_error(zep, NULL, ZIP_ER_OPEN); + return NULL; + } + + zip_error_init(&error); + if ((src = zip_source_filep_create(fp, 0, -1, &error)) == NULL) { + fclose(fp); + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + if ((za = zip_open_from_source(src, _flags, &error)) == NULL) { + zip_source_free(src); + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + zip_error_fini(&error); + close(fd_orig); + return za; +#endif +} diff --git a/3rdparty/libzip/lib/zip_file_add.c b/3rdparty/libzip/lib/zip_file_add.c new file mode 100644 index 0000000000..c2c41e1563 --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_add.c @@ -0,0 +1,52 @@ +/* + zip_file_add.c -- add file via callback function + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +/* + NOTE: Return type is signed so we can return -1 on error. + The index can not be larger than ZIP_INT64_MAX since the size + of the central directory cannot be larger than + ZIP_UINT64_MAX, and each entry is larger than 2 bytes. +*/ + +ZIP_EXTERN zip_int64_t +zip_file_add(zip_t *za, const char *name, zip_source_t *source, zip_flags_t flags) { + if (name == NULL || source == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags); +} diff --git a/3rdparty/libzip/lib/zip_file_error_clear.c b/3rdparty/libzip/lib/zip_file_error_clear.c new file mode 100644 index 0000000000..a10bff80c6 --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_error_clear.c @@ -0,0 +1,44 @@ +/* + zip_file_error_clear.c -- clear zip file error + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN void +zip_file_error_clear(zip_file_t *zf) { + if (zf == NULL) + return; + + _zip_error_clear(&zf->error); +} diff --git a/3rdparty/libzip/lib/zip_file_error_get.c b/3rdparty/libzip/lib/zip_file_error_get.c new file mode 100644 index 0000000000..b93117bb9b --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_error_get.c @@ -0,0 +1,41 @@ +/* + zip_file_error_get.c -- get zip file error + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN void +zip_file_error_get(zip_file_t *zf, int *zep, int *sep) { + _zip_error_get(&zf->error, zep, sep); +} diff --git a/3rdparty/libzip/lib/zip_file_get_comment.c b/3rdparty/libzip/lib/zip_file_get_comment.c new file mode 100644 index 0000000000..fa998f02ed --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_get_comment.c @@ -0,0 +1,55 @@ +/* + zip_file_get_comment.c -- get file comment + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +/* lenp is 32 bit because converted comment can be longer than ZIP_UINT16_MAX */ + +ZIP_EXTERN const char * +zip_file_get_comment(zip_t *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_t flags) { + zip_dirent_t *de; + zip_uint32_t len; + const zip_uint8_t *str; + + if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL) + return NULL; + + if ((str = _zip_string_get(de->comment, &len, flags, &za->error)) == NULL) + return NULL; + + if (lenp) + *lenp = len; + + return (const char *)str; +} diff --git a/3rdparty/libzip/lib/zip_file_get_external_attributes.c b/3rdparty/libzip/lib/zip_file_get_external_attributes.c new file mode 100644 index 0000000000..a79bb3ed2b --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_get_external_attributes.c @@ -0,0 +1,50 @@ +/* + zip_file_get_external_attributes.c -- get opsys/external attributes + Copyright (C) 2013-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +int +zip_file_get_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t *opsys, zip_uint32_t *attributes) { + zip_dirent_t *de; + + if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL) + return -1; + + if (opsys) + *opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff); + + if (attributes) + *attributes = de->ext_attrib; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_file_get_offset.c b/3rdparty/libzip/lib/zip_file_get_offset.c new file mode 100644 index 0000000000..72f4880e78 --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_get_offset.c @@ -0,0 +1,117 @@ +/* + zip_file_get_offset.c -- get offset of file data in archive. + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + + +/* _zip_file_get_offset(za, ze): + Returns the offset of the file data for entry ze. + + On error, fills in za->error and returns 0. +*/ + +zip_uint64_t +_zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error) { + zip_uint64_t offset; + zip_int32_t size; + + if (za->entry[idx].orig == NULL) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return 0; + } + + offset = za->entry[idx].orig->offset; + + if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { + zip_error_set_from_source(error, za->src); + return 0; + } + + /* TODO: cache? */ + if ((size = _zip_dirent_size(za->src, ZIP_EF_LOCAL, error)) < 0) + return 0; + + if (offset + (zip_uint32_t)size > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return 0; + } + + return offset + (zip_uint32_t)size; +} + +zip_uint64_t +_zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error) { + zip_uint64_t offset; + zip_dirent_t *entry; + + if ((offset = _zip_file_get_offset(za, index, error)) == 0) { + return 0; + } + + entry = za->entry[index].orig; + + if (offset + entry->comp_size < offset || offset + entry->comp_size > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return 0; + } + offset += entry->comp_size; + + if (entry->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { + zip_uint8_t buf[4]; + if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { + zip_error_set_from_source(error, za->src); + return 0; + } + if (zip_source_read(za->src, buf, 4) != 4) { + zip_error_set_from_source(error, za->src); + return 0; + } + if (memcmp(buf, DATADES_MAGIC, 4) == 0) { + offset += 4; + } + offset += 12; + if (_zip_dirent_needs_zip64(entry, 0)) { + offset += 8; + } + if (offset > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return 0; + } + } + + return offset; +} diff --git a/3rdparty/libzip/lib/zip_file_rename.c b/3rdparty/libzip/lib/zip_file_rename.c new file mode 100644 index 0000000000..9ac25814a9 --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_rename.c @@ -0,0 +1,67 @@ +/* + zip_file_rename.c -- rename file in zip archive + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_file_rename(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) { + const char *old_name; + int old_is_dir, new_is_dir; + + if (idx >= za->nentry || (name != NULL && strlen(name) > ZIP_UINT16_MAX)) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if ((old_name = zip_get_name(za, idx, 0)) == NULL) + return -1; + + new_is_dir = (name != NULL && name[strlen(name) - 1] == '/'); + old_is_dir = (old_name[strlen(old_name) - 1] == '/'); + + if (new_is_dir != old_is_dir) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_set_name(za, idx, name, flags); +} diff --git a/3rdparty/libzip/lib/zip_file_replace.c b/3rdparty/libzip/lib/zip_file_replace.c new file mode 100644 index 0000000000..4262d453ea --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_replace.c @@ -0,0 +1,105 @@ +/* + zip_file_replace.c -- replace file via callback function + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_file_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source, zip_flags_t flags) { + if (idx >= za->nentry || source == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_file_replace(za, idx, NULL, source, flags) == -1) + return -1; + + return 0; +} + + +/* NOTE: Signed due to -1 on error. See zip_add.c for more details. */ + +zip_int64_t +_zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *source, zip_flags_t flags) { + zip_uint64_t za_nentry_prev; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + za_nentry_prev = za->nentry; + if (idx == ZIP_UINT64_MAX) { + zip_int64_t i = -1; + + if (flags & ZIP_FL_OVERWRITE) + i = _zip_name_locate(za, name, flags, NULL); + + if (i == -1) { + /* create and use new entry, used by zip_add */ + if ((i = _zip_add_entry(za)) < 0) + return -1; + } + idx = (zip_uint64_t)i; + } + + if (name && _zip_set_name(za, idx, name, flags) != 0) { + if (za->nentry != za_nentry_prev) { + _zip_entry_finalize(za->entry + idx); + za->nentry = za_nentry_prev; + } + return -1; + } + + /* does not change any name related data, so we can do it here; + * needed for a double add of the same file name */ + _zip_unchange_data(za->entry + idx); + + if (za->entry[idx].orig != NULL && (za->entry[idx].changes == NULL || (za->entry[idx].changes->changed & ZIP_DIRENT_COMP_METHOD) == 0)) { + if (za->entry[idx].changes == NULL) { + if ((za->entry[idx].changes = _zip_dirent_clone(za->entry[idx].orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT; + za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD; + } + + za->entry[idx].source = source; + + return (zip_int64_t)idx; +} diff --git a/3rdparty/libzip/lib/zip_file_set_comment.c b/3rdparty/libzip/lib/zip_file_set_comment.c new file mode 100644 index 0000000000..570f8e8212 --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_set_comment.c @@ -0,0 +1,105 @@ +/* + zip_file_set_comment.c -- set comment for file in archive + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_file_set_comment(zip_t *za, zip_uint64_t idx, const char *comment, zip_uint16_t len, zip_flags_t flags) { + zip_entry_t *e; + zip_string_t *cstr; + int changed; + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + if (ZIP_WANT_TORRENTZIP(za)) { + zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0); + return -1; + } + + if (len > 0 && comment == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (len > 0) { + if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL) + return -1; + if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) + cstr->encoding = ZIP_ENCODING_UTF8_KNOWN; + } + else + cstr = NULL; + + e = za->entry + idx; + + if (e->changes) { + _zip_string_free(e->changes->comment); + e->changes->comment = NULL; + e->changes->changed &= ~ZIP_DIRENT_COMMENT; + } + + if (e->orig && e->orig->comment) + changed = !_zip_string_equal(e->orig->comment, cstr); + else + changed = (cstr != NULL); + + if (changed) { + if (e->changes == NULL) { + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_string_free(cstr); + return -1; + } + } + e->changes->comment = cstr; + e->changes->changed |= ZIP_DIRENT_COMMENT; + } + else { + _zip_string_free(cstr); + if (e->changes && e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_file_set_encryption.c b/3rdparty/libzip/lib/zip_file_set_encryption.c new file mode 100644 index 0000000000..1cdcd4ab67 --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_set_encryption.c @@ -0,0 +1,120 @@ +/* + zip_file_set_encryption.c -- set encryption for file in archive + Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +#include +#include + +ZIP_EXTERN int +zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const char *password) { + zip_entry_t *e; + zip_uint16_t old_method; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + if (ZIP_WANT_TORRENTZIP(za)) { + zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0); + return -1; + } + + if (method != ZIP_EM_NONE && _zip_get_encryption_implementation(method, ZIP_CODEC_ENCODE) == NULL) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return -1; + } + + e = za->entry + idx; + + old_method = (e->orig == NULL ? ZIP_EM_NONE : e->orig->encryption_method); + + if (method == old_method && password == NULL) { + if (e->changes) { + if (e->changes->changed & ZIP_DIRENT_PASSWORD) { + _zip_crypto_clear(e->changes->password, strlen(e->changes->password)); + free(e->changes->password); + e->changes->password = (e->orig == NULL ? NULL : e->orig->password); + } + e->changes->changed &= ~(ZIP_DIRENT_ENCRYPTION_METHOD | ZIP_DIRENT_PASSWORD); + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + } + } + else { + char *our_password = NULL; + + if (password) { + if ((our_password = strdup(password)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + if (e->changes == NULL) { + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + if (our_password) { + _zip_crypto_clear(our_password, strlen(our_password)); + } + free(our_password); + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + e->changes->encryption_method = method; + e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD; + if (password) { + e->changes->password = our_password; + e->changes->changed |= ZIP_DIRENT_PASSWORD; + } + else { + if (e->changes->changed & ZIP_DIRENT_PASSWORD) { + _zip_crypto_clear(e->changes->password, strlen(e->changes->password)); + free(e->changes->password); + e->changes->password = e->orig ? e->orig->password : NULL; + e->changes->changed &= ~ZIP_DIRENT_PASSWORD; + } + } + } + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_file_set_external_attributes.c b/3rdparty/libzip/lib/zip_file_set_external_attributes.c new file mode 100644 index 0000000000..2e0429b8ca --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_set_external_attributes.c @@ -0,0 +1,86 @@ +/* + zip_file_set_external_attributes.c -- set external attributes for entry + Copyright (C) 2013-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +ZIP_EXTERN int +zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_uint8_t opsys, zip_uint32_t attributes) { + zip_entry_t *e; + int changed; + zip_uint8_t unchanged_opsys; + zip_uint32_t unchanged_attributes; + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + if (ZIP_WANT_TORRENTZIP(za)) { + zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0); + return -1; + } + + e = za->entry + idx; + + unchanged_opsys = (e->orig ? (zip_uint8_t)(e->orig->version_madeby >> 8) : (zip_uint8_t)ZIP_OPSYS_DEFAULT); + unchanged_attributes = e->orig ? e->orig->ext_attrib : ZIP_EXT_ATTRIB_DEFAULT; + + changed = (opsys != unchanged_opsys || attributes != unchanged_attributes); + + if (changed) { + if (e->changes == NULL) { + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + e->changes->version_madeby = (zip_uint16_t)((opsys << 8) | (e->changes->version_madeby & 0xff)); + e->changes->ext_attrib = attributes; + e->changes->changed |= ZIP_DIRENT_ATTRIBUTES; + } + else if (e->changes) { + e->changes->changed &= ~ZIP_DIRENT_ATTRIBUTES; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + else { + e->changes->version_madeby = (zip_uint16_t)((unchanged_opsys << 8) | (e->changes->version_madeby & 0xff)); + e->changes->ext_attrib = unchanged_attributes; + } + } + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_file_set_mtime.c b/3rdparty/libzip/lib/zip_file_set_mtime.c new file mode 100644 index 0000000000..4126f5a166 --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_set_mtime.c @@ -0,0 +1,77 @@ +/* + zip_file_set_mtime.c -- set modification time of entry. + Copyright (C) 2014-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "zipint.h" + +ZIP_EXTERN int +zip_file_set_dostime(zip_t *za, zip_uint64_t idx, zip_uint16_t dtime, zip_uint16_t ddate, zip_flags_t flags) { + time_t mtime; + mtime = _zip_d2u_time(dtime, ddate); + return zip_file_set_mtime(za, idx, mtime, flags); +} + +ZIP_EXTERN int +zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags) { + zip_entry_t *e; + + if (_zip_get_dirent(za, idx, 0, NULL) == NULL) + return -1; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + if (ZIP_WANT_TORRENTZIP(za)) { + zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0); + return -1; + } + + e = za->entry + idx; + + if (e->orig != NULL && e->orig->encryption_method == ZIP_EM_TRAD_PKWARE && !ZIP_ENTRY_CHANGED(e, ZIP_DIRENT_ENCRYPTION_METHOD) && !ZIP_ENTRY_DATA_CHANGED(e)) { + zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + if (e->changes == NULL) { + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + e->changes->last_mod = mtime; + e->changes->changed |= ZIP_DIRENT_LAST_MOD; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_file_strerror.c b/3rdparty/libzip/lib/zip_file_strerror.c new file mode 100644 index 0000000000..5b5a009241 --- /dev/null +++ b/3rdparty/libzip/lib/zip_file_strerror.c @@ -0,0 +1,41 @@ +/* + zip_file_sterror.c -- get string representation of zip file error + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_file_strerror(zip_file_t *zf) { + return zip_error_strerror(&zf->error); +} diff --git a/3rdparty/libzip/lib/zip_fopen.c b/3rdparty/libzip/lib/zip_fopen.c new file mode 100644 index 0000000000..e3cde9be06 --- /dev/null +++ b/3rdparty/libzip/lib/zip_fopen.c @@ -0,0 +1,46 @@ +/* + zip_fopen.c -- open file in zip archive for reading + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_file_t * +zip_fopen(zip_t *za, const char *fname, zip_flags_t flags) { + zip_int64_t idx; + + if ((idx = zip_name_locate(za, fname, flags)) < 0) + return NULL; + + return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password); +} diff --git a/3rdparty/libzip/lib/zip_fopen_encrypted.c b/3rdparty/libzip/lib/zip_fopen_encrypted.c new file mode 100644 index 0000000000..d5880dcb99 --- /dev/null +++ b/3rdparty/libzip/lib/zip_fopen_encrypted.c @@ -0,0 +1,46 @@ +/* + zip_fopen_encrypted.c -- open file for reading with password + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_file_t * +zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char *password) { + zip_int64_t idx; + + if ((idx = zip_name_locate(za, fname, flags)) < 0) + return NULL; + + return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password); +} diff --git a/3rdparty/libzip/lib/zip_fopen_index.c b/3rdparty/libzip/lib/zip_fopen_index.c new file mode 100644 index 0000000000..a449b83a0d --- /dev/null +++ b/3rdparty/libzip/lib/zip_fopen_index.c @@ -0,0 +1,41 @@ +/* + zip_fopen_index.c -- open file in zip archive for reading by index + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_file_t * +zip_fopen_index(zip_t *za, zip_uint64_t index, zip_flags_t flags) { + return zip_fopen_index_encrypted(za, index, flags, za->default_password); +} diff --git a/3rdparty/libzip/lib/zip_fopen_index_encrypted.c b/3rdparty/libzip/lib/zip_fopen_index_encrypted.c new file mode 100644 index 0000000000..40483709ee --- /dev/null +++ b/3rdparty/libzip/lib/zip_fopen_index_encrypted.c @@ -0,0 +1,85 @@ +/* + zip_fopen_index_encrypted.c -- open file for reading by index w/ password + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + +static zip_file_t *_zip_file_new(zip_t *za); + + +ZIP_EXTERN zip_file_t * +zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags, const char *password) { + zip_file_t *zf; + zip_source_t *src; + + if (password != NULL && password[0] == '\0') { + password = NULL; + } + + if ((src = zip_source_zip_file_create(za, index, flags, 0, -1, password, &za->error)) == NULL) + return NULL; + + if (zip_source_open(src) < 0) { + zip_error_set_from_source(&za->error, src); + zip_source_free(src); + return NULL; + } + + if ((zf = _zip_file_new(za)) == NULL) { + zip_source_free(src); + return NULL; + } + + zf->src = src; + + return zf; +} + + +static zip_file_t * +_zip_file_new(zip_t *za) { + zip_file_t *zf; + + if ((zf = (zip_file_t *)malloc(sizeof(struct zip_file))) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + zip_error_init(&zf->error); + zf->src = NULL; + + return zf; +} diff --git a/3rdparty/libzip/lib/zip_fread.c b/3rdparty/libzip/lib/zip_fread.c new file mode 100644 index 0000000000..5b7da46aee --- /dev/null +++ b/3rdparty/libzip/lib/zip_fread.c @@ -0,0 +1,63 @@ +/* + zip_fread.c -- read from file + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread) { + zip_int64_t n; + + if (!zf) + return -1; + + if (zf->error.zip_err != 0) + return -1; + + if (toread > ZIP_INT64_MAX) { + zip_error_set(&zf->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (toread == 0) { + return 0; + } + + if ((n = zip_source_read(zf->src, outbuf, toread)) < 0) { + zip_error_set_from_source(&zf->error, zf->src); + return -1; + } + + return n; +} diff --git a/3rdparty/libzip/lib/zip_fseek.c b/3rdparty/libzip/lib/zip_fseek.c new file mode 100644 index 0000000000..e68ffd367d --- /dev/null +++ b/3rdparty/libzip/lib/zip_fseek.c @@ -0,0 +1,61 @@ +/* + zip_fseek.c -- seek in file + Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +ZIP_EXTERN zip_int8_t +zip_fseek(zip_file_t *zf, zip_int64_t offset, int whence) { + if (!zf) + return -1; + + if (zf->error.zip_err != 0) + return -1; + + if (zip_source_seek(zf->src, offset, whence) < 0) { + zip_error_set_from_source(&zf->error, zf->src); + return -1; + } + + return 0; +} + + +ZIP_EXTERN int +zip_file_is_seekable(zip_file_t *zfile) { + if (!zfile) { + return -1; + } + + return zip_source_is_seekable(zfile->src); +} diff --git a/3rdparty/libzip/lib/zip_ftell.c b/3rdparty/libzip/lib/zip_ftell.c new file mode 100644 index 0000000000..bf3b03d348 --- /dev/null +++ b/3rdparty/libzip/lib/zip_ftell.c @@ -0,0 +1,54 @@ +/* + zip_ftell.c -- tell position in file + Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +ZIP_EXTERN zip_int64_t +zip_ftell(zip_file_t *zf) { + zip_int64_t res; + + if (!zf) + return -1; + + if (zf->error.zip_err != 0) + return -1; + + res = zip_source_tell(zf->src); + if (res < 0) { + zip_error_set_from_source(&zf->error, zf->src); + return -1; + } + + return res; +} diff --git a/3rdparty/libzip/lib/zip_get_archive_comment.c b/3rdparty/libzip/lib/zip_get_archive_comment.c new file mode 100644 index 0000000000..ea9a00ab5c --- /dev/null +++ b/3rdparty/libzip/lib/zip_get_archive_comment.c @@ -0,0 +1,58 @@ +/* + zip_get_archive_comment.c -- get archive comment + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags) { + zip_string_t *comment; + zip_uint32_t len; + const zip_uint8_t *str; + + if ((flags & ZIP_FL_UNCHANGED) || (za->comment_changes == NULL)) + comment = za->comment_orig; + else + comment = za->comment_changes; + + if ((str = _zip_string_get(comment, &len, flags, &za->error)) == NULL) + return NULL; + + if (lenp) + *lenp = (int)len; + + return (const char *)str; +} diff --git a/3rdparty/libzip/lib/zip_get_archive_flag.c b/3rdparty/libzip/lib/zip_get_archive_flag.c new file mode 100644 index 0000000000..fc200bdc4a --- /dev/null +++ b/3rdparty/libzip/lib/zip_get_archive_flag.c @@ -0,0 +1,45 @@ +/* + zip_get_archive_flag.c -- get archive global flag + Copyright (C) 2008-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_get_archive_flag(zip_t *za, zip_flags_t flag, zip_flags_t flags) { + unsigned int fl; + + fl = (flags & ZIP_FL_UNCHANGED) ? za->flags : za->ch_flags; + + return (fl & flag) ? 1 : 0; +} diff --git a/3rdparty/libzip/lib/zip_get_encryption_implementation.c b/3rdparty/libzip/lib/zip_get_encryption_implementation.c new file mode 100644 index 0000000000..72e48fe87a --- /dev/null +++ b/3rdparty/libzip/lib/zip_get_encryption_implementation.c @@ -0,0 +1,62 @@ +/* + zip_get_encryption_implementation.c -- get encryption implementation + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +zip_encryption_implementation +_zip_get_encryption_implementation(zip_uint16_t em, int operation) { + switch (em) { + case ZIP_EM_TRAD_PKWARE: + return operation == ZIP_CODEC_DECODE ? zip_source_pkware_decode : zip_source_pkware_encode; + +#if defined(HAVE_CRYPTO) + 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; +#endif + + default: + return NULL; + } +} + +ZIP_EXTERN int +zip_encryption_method_supported(zip_uint16_t method, int encode) { + if (method == ZIP_EM_NONE) { + return 1; + } + return _zip_get_encryption_implementation(method, encode ? ZIP_CODEC_ENCODE : ZIP_CODEC_DECODE) != NULL; +} diff --git a/3rdparty/libzip/lib/zip_get_file_comment.c b/3rdparty/libzip/lib/zip_get_file_comment.c new file mode 100644 index 0000000000..d58e22ba6d --- /dev/null +++ b/3rdparty/libzip/lib/zip_get_file_comment.c @@ -0,0 +1,50 @@ +/* + zip_get_file_comment.c -- get file comment + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_get_file_comment(zip_t *za, zip_uint64_t idx, int *lenp, int flags) { + zip_uint32_t len; + const char *s; + + if ((s = zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) { + if (lenp) + *lenp = (int)len; + } + + return s; +} diff --git a/3rdparty/libzip/lib/zip_get_name.c b/3rdparty/libzip/lib/zip_get_name.c new file mode 100644 index 0000000000..4828d78107 --- /dev/null +++ b/3rdparty/libzip/lib/zip_get_name.c @@ -0,0 +1,58 @@ +/* + zip_get_name.c -- get filename for a file in zip file + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags) { + return _zip_get_name(za, idx, flags, &za->error); +} + + +const char * +_zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error) { + zip_dirent_t *de; + const zip_uint8_t *str; + + if ((de = _zip_get_dirent(za, idx, flags, error)) == NULL) + return NULL; + + if ((str = _zip_string_get(de->filename, NULL, flags, error)) == NULL) + return NULL; + + return (const char *)str; +} diff --git a/3rdparty/libzip/lib/zip_get_num_entries.c b/3rdparty/libzip/lib/zip_get_num_entries.c new file mode 100644 index 0000000000..667dc51179 --- /dev/null +++ b/3rdparty/libzip/lib/zip_get_num_entries.c @@ -0,0 +1,52 @@ +/* + zip_get_num_entries.c -- get number of entries in archive + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_get_num_entries(zip_t *za, zip_flags_t flags) { + zip_uint64_t n; + + if (za == NULL) + return -1; + + if (flags & ZIP_FL_UNCHANGED) { + n = za->nentry; + while (n > 0 && za->entry[n - 1].orig == NULL) + --n; + return (zip_int64_t)n; + } + return (zip_int64_t)za->nentry; +} diff --git a/3rdparty/libzip/lib/zip_get_num_files.c b/3rdparty/libzip/lib/zip_get_num_files.c new file mode 100644 index 0000000000..140e34f900 --- /dev/null +++ b/3rdparty/libzip/lib/zip_get_num_files.c @@ -0,0 +1,51 @@ +/* + zip_get_num_files.c -- get number of files in archive + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" +#include + + +ZIP_EXTERN int +zip_get_num_files(zip_t *za) { + if (za == NULL) + return -1; + + if (za->nentry > INT_MAX) { + zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + return (int)za->nentry; +} diff --git a/3rdparty/libzip/lib/zip_hash.c b/3rdparty/libzip/lib/zip_hash.c new file mode 100644 index 0000000000..d3a954ec59 --- /dev/null +++ b/3rdparty/libzip/lib/zip_hash.c @@ -0,0 +1,410 @@ +/* + zip_hash.c -- hash table string -> uint64 + Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" +#include +#include + +/* 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_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 + (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_error_t *error) { + zip_hash_t *hash; + + if ((hash = (zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + hash->table_size = 0; + hash->nentries = 0; + hash->table = NULL; + + return hash; +} + + +void +_zip_hash_free(zip_hash_t *hash) { + zip_uint32_t i; + + if (hash == NULL) { + return; + } + + 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); +} + + +/* 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_uint32_t hash_value, table_index; + zip_hash_entry_t *entry; + + if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return false; + } + + 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; + } + } + } + + if (flags & ZIP_FL_UNCHANGED) { + entry->orig_index = (zip_int64_t)index; + } + entry->current_index = (zip_int64_t)index; + + return true; +} + + +/* remove entry from hash, error if not found */ +bool +_zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error) { + zip_uint32_t hash_value, index; + zip_hash_entry_t *entry, *previous; + + if (hash == NULL || name == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return false; + } + + 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 { + entry->current_index = -1; + } + return true; + } + previous = entry; + entry = entry->next; + } + } + + zip_error_set(error, ZIP_ER_NOENT, 0); + return false; +} + + +/* find value for entry in hash, -1 if not found */ +zip_int64_t +_zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error) { + zip_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; + } + + 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; + } + } + } + + zip_error_set(error, ZIP_ER_NOENT, 0); + return -1; +} + + +bool +_zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t *error) { + 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); + 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; +} diff --git a/3rdparty/libzip/lib/zip_io_util.c b/3rdparty/libzip/lib/zip_io_util.c new file mode 100644 index 0000000000..9fcd10b4b3 --- /dev/null +++ b/3rdparty/libzip/lib/zip_io_util.c @@ -0,0 +1,146 @@ +/* + zip_io_util.c -- I/O helper functions + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "zipint.h" + +int +_zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *error) { + zip_int64_t n; + + if (length > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((n = zip_source_read(src, b, length)) < 0) { + zip_error_set_from_source(error, src); + return -1; + } + + if (n < (zip_int64_t)length) { + zip_error_set(error, ZIP_ER_EOF, 0); + return -1; + } + + return 0; +} + + +zip_uint8_t * +_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error) { + zip_uint8_t *r; + + if (length == 0 && !nulp) { + return NULL; + } + + r = (zip_uint8_t *)malloc(length + (nulp ? 1 : 0)); + if (!r) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if (buffer) { + zip_uint8_t *data = _zip_buffer_get(buffer, length); + + if (data == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(r); + return NULL; + } + (void)memcpy_s(r, length, data, length); + } + else { + if (_zip_read(src, r, length, error) < 0) { + free(r); + return NULL; + } + } + + if (nulp) { + zip_uint8_t *o; + /* replace any in-string NUL characters with spaces */ + r[length] = 0; + for (o = r; o < r + length; o++) + if (*o == '\0') + *o = ' '; + } + + return r; +} + + +zip_string_t * +_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool nulp, zip_error_t *error) { + zip_uint8_t *raw; + zip_string_t *s; + + if ((raw = _zip_read_data(buffer, src, len, nulp, error)) == NULL) + return NULL; + + s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error); + free(raw); + return s; +} + + +int +_zip_write(zip_t *za, const void *data, zip_uint64_t length) { + zip_int64_t n; + + if ((n = zip_source_write(za->src, data, length)) < 0) { + zip_error_set_from_source(&za->error, za->src); + return -1; + } + if ((zip_uint64_t)n != length) { + zip_error_set(&za->error, ZIP_ER_WRITE, EINTR); + return -1; + } + + if (za->write_crc != NULL) { + zip_uint64_t position = 0; + while (position < length) { + zip_uint64_t nn = ZIP_MIN(UINT_MAX, length - position); + + *za->write_crc = (zip_uint32_t)crc32(*za->write_crc, (const Bytef *)data + position, (uInt)nn); + position += nn; + } + } + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_libzip_version.c b/3rdparty/libzip/lib/zip_libzip_version.c new file mode 100644 index 0000000000..4200727fcd --- /dev/null +++ b/3rdparty/libzip/lib/zip_libzip_version.c @@ -0,0 +1,41 @@ +/* + zip_libzip_version.c -- return run-time version of library + Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_libzip_version(void) { + return LIBZIP_VERSION; +} diff --git a/3rdparty/libzip/lib/zip_memdup.c b/3rdparty/libzip/lib/zip_memdup.c new file mode 100644 index 0000000000..75d72c616b --- /dev/null +++ b/3rdparty/libzip/lib/zip_memdup.c @@ -0,0 +1,56 @@ +/* + zip_memdup.c -- internal zip function, "strdup" with len + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#include "zipint.h" + + +void * +_zip_memdup(const void *mem, size_t len, zip_error_t *error) { + void *ret; + + if (len == 0) + return NULL; + + ret = malloc(len); + if (!ret) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + (void)memcpy_s(ret, len, mem, len); + + return ret; +} diff --git a/3rdparty/libzip/lib/zip_name_locate.c b/3rdparty/libzip/lib/zip_name_locate.c new file mode 100644 index 0000000000..4248dc2d36 --- /dev/null +++ b/3rdparty/libzip/lib/zip_name_locate.c @@ -0,0 +1,116 @@ +/* + zip_name_locate.c -- get index by name + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#ifdef HAVE_STRINGS_H +#include +#endif + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags) { + return _zip_name_locate(za, fname, flags, &za->error); +} + + +zip_int64_t +_zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *error) { + int (*cmp)(const char *, const char *); + size_t fname_length; + zip_string_t *str = NULL; + const char *fn, *p; + zip_uint64_t i; + + if (za == NULL) { + return -1; + } + + if (fname == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + fname_length = strlen(fname); + + if (fname_length > ZIP_UINT16_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((flags & (ZIP_FL_ENC_UTF_8 | ZIP_FL_ENC_RAW)) == 0 && fname[0] != '\0') { + if ((str = _zip_string_new((const zip_uint8_t *)fname, (zip_uint16_t)strlen(fname), flags, error)) == NULL) { + return -1; + } + if ((fname = (const char *)_zip_string_get(str, NULL, 0, error)) == NULL) { + _zip_string_free(str); + return -1; + } + } + + if (flags & (ZIP_FL_NOCASE | ZIP_FL_NODIR | ZIP_FL_ENC_RAW | ZIP_FL_ENC_STRICT)) { + /* can't use hash table */ + cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp; + + for (i = 0; i < za->nentry; i++) { + fn = _zip_get_name(za, i, flags, error); + + /* newly added (partially filled) entry or error */ + if (fn == NULL) + continue; + + if (flags & ZIP_FL_NODIR) { + p = strrchr(fn, '/'); + if (p) + fn = p + 1; + } + + if (cmp(fname, fn) == 0) { + _zip_error_clear(error); + _zip_string_free(str); + return (zip_int64_t)i; + } + } + + zip_error_set(error, ZIP_ER_NOENT, 0); + _zip_string_free(str); + return -1; + } + else { + zip_int64_t ret = _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error); + _zip_string_free(str); + return ret; + } +} diff --git a/3rdparty/libzip/lib/zip_new.c b/3rdparty/libzip/lib/zip_new.c new file mode 100644 index 0000000000..4f69c8a2f5 --- /dev/null +++ b/3rdparty/libzip/lib/zip_new.c @@ -0,0 +1,73 @@ +/* + zip_new.c -- create and init struct zip + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +/* _zip_new: + creates a new zipfile struct, and sets the contents to zero; returns + the new struct. */ + +zip_t * +_zip_new(zip_error_t *error) { + zip_t *za; + + za = (zip_t *)malloc(sizeof(struct zip)); + if (!za) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((za->names = _zip_hash_new(error)) == NULL) { + free(za); + return NULL; + } + + za->src = NULL; + za->open_flags = 0; + zip_error_init(&za->error); + za->flags = za->ch_flags = 0; + za->default_password = NULL; + za->comment_orig = za->comment_changes = NULL; + za->comment_changed = 0; + za->nentry = za->nentry_alloc = 0; + za->entry = NULL; + za->nopen_source = za->nopen_source_alloc = 0; + za->open_source = NULL; + za->progress = NULL; + + return za; +} diff --git a/3rdparty/libzip/lib/zip_open.c b/3rdparty/libzip/lib/zip_open.c new file mode 100644 index 0000000000..ee7e9decb8 --- /dev/null +++ b/3rdparty/libzip/lib/zip_open.c @@ -0,0 +1,967 @@ +/* + zip_open.c -- open zip archive by name + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include +#include + +#include "zipint.h" + +typedef enum { EXISTS_ERROR = -1, EXISTS_NOT = 0, EXISTS_OK } exists_t; +static zip_t *_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error); +static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cdir, zip_error_t *error); +static void zip_check_torrentzip(zip_t *za, const zip_cdir_t *cdir); +static zip_cdir_t *_zip_find_central_dir(zip_t *za, zip_uint64_t len); +static exists_t _zip_file_exists(zip_source_t *src, zip_error_t *error); +static int _zip_headercomp(const zip_dirent_t *, const zip_dirent_t *); +static const unsigned char *_zip_memmem(const unsigned char *, size_t, const unsigned char *, size_t); +static zip_cdir_t *_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error); +static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error); +static zip_cdir_t *_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error); + + +ZIP_EXTERN zip_t * +zip_open(const char *fn, int _flags, int *zep) { + zip_t *za; + zip_source_t *src; + struct zip_error error; + + zip_error_init(&error); + if ((src = zip_source_file_create(fn, 0, -1, &error)) == NULL) { + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + if ((za = zip_open_from_source(src, _flags, &error)) == NULL) { + zip_source_free(src); + _zip_set_open_error(zep, &error, 0); + zip_error_fini(&error); + return NULL; + } + + zip_error_fini(&error); + return za; +} + + +ZIP_EXTERN zip_t * +zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) { + 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 ((supported & ZIP_SOURCE_SUPPORTS_SEEKABLE) != ZIP_SOURCE_SUPPORTS_SEEKABLE) { + zip_error_set(error, ZIP_ER_OPNOTSUPP, 0); + return NULL; + } + if ((supported & ZIP_SOURCE_SUPPORTS_WRITABLE) != ZIP_SOURCE_SUPPORTS_WRITABLE) { + flags |= ZIP_RDONLY; + } + + if ((flags & (ZIP_RDONLY | ZIP_TRUNCATE)) == (ZIP_RDONLY | ZIP_TRUNCATE)) { + zip_error_set(error, ZIP_ER_RDONLY, 0); + return NULL; + } + + exists = _zip_file_exists(src, error); + switch (exists) { + case EXISTS_ERROR: + return NULL; + + case EXISTS_NOT: + if ((flags & ZIP_CREATE) == 0) { + zip_error_set(error, ZIP_ER_NOENT, 0); + return NULL; + } + return _zip_allocate_new(src, flags, error); + + default: { + zip_t *za; + if (flags & ZIP_EXCL) { + zip_error_set(error, ZIP_ER_EXISTS, 0); + return NULL; + } + if (zip_source_open(src) < 0) { + zip_error_set_from_source(error, src); + return NULL; + } + + if (flags & ZIP_TRUNCATE) { + za = _zip_allocate_new(src, flags, error); + } + else { + /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */ + za = _zip_open(src, flags, error); + } + + if (za == NULL) { + zip_source_close(src); + return NULL; + } + return za; + } + } +} + + +zip_t * +_zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) { + zip_t *za; + zip_cdir_t *cdir; + struct zip_stat st; + zip_uint64_t len, idx; + + zip_stat_init(&st); + if (zip_source_stat(src, &st) < 0) { + zip_error_set_from_source(error, src); + return NULL; + } + if ((st.valid & ZIP_STAT_SIZE) == 0) { + zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP); + return NULL; + } + len = st.size; + + + if ((za = _zip_allocate_new(src, flags, error)) == NULL) { + return NULL; + } + + /* treat empty files as empty archives */ + if (len == 0 && zip_source_accept_empty(src)) { + return za; + } + + 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 */ + zip_source_keep(src); + zip_discard(za); + return NULL; + } + + za->entry = cdir->entry; + za->nentry = cdir->nentry; + za->nentry_alloc = cdir->nentry_alloc; + + zip_check_torrentzip(za, cdir); + + if (ZIP_IS_TORRENTZIP(za)) { + /* Torrentzip uses the archive comment to detect changes by tools that are not torrentzip aware. */ + _zip_string_free(cdir->comment); + } + else { + za->comment_orig = cdir->comment; + } + + 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) { + /* keep src so discard does not get rid of it */ + zip_source_keep(src); + zip_discard(za); + return NULL; + } + + if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) { + if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) { + _zip_error_copy(error, &za->error); + /* keep src so discard does not get rid of it */ + zip_source_keep(src); + zip_discard(za); + return NULL; + } + } + } + + za->ch_flags = za->flags; + + return za; +} + + +void +_zip_set_open_error(int *zep, const zip_error_t *err, int ze) { + if (err) { + ze = zip_error_code_zip(err); + switch (zip_error_system_type(err)) { + case ZIP_ET_SYS: + case ZIP_ET_LIBZIP: + errno = zip_error_code_system(err); + break; + + default: + break; + } + } + + if (zep) + *zep = ze; +} + + +/* _zip_readcdir: + tries to find a valid end-of-central-directory at the beginning of + buf, and then the corresponding central directory entries. + Returns a struct zip_cdir which contains the central directory + entries, or NULL if unsuccessful. */ + +static zip_cdir_t * +_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error) { + zip_cdir_t *cd; + zip_uint16_t comment_len; + zip_uint64_t i, left; + zip_uint64_t eocd_offset = _zip_buffer_offset(buffer); + zip_buffer_t *cd_buffer; + + if (_zip_buffer_left(buffer) < EOCDLEN) { + /* not enough bytes left for comment */ + 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); + return NULL; + } + + if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) { + _zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN); + cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error); + } + else { + _zip_buffer_set_offset(buffer, eocd_offset); + cd = _zip_read_eocd(buffer, buf_offset, za->flags, error); + } + + if (cd == NULL) + return NULL; + + _zip_buffer_set_offset(buffer, eocd_offset + 20); + comment_len = _zip_buffer_get_16(buffer); + + if (cd->offset + cd->size > buf_offset + eocd_offset) { + /* cdir spans past EOCD record */ + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD); + _zip_cdir_free(cd); + return NULL; + } + + 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, ZIP_ER_DETAIL_COMMENT_LENGTH_INVALID); + _zip_cdir_free(cd); + return NULL; + } + + if (comment_len) { + if ((cd->comment = _zip_string_new(_zip_buffer_get(buffer, comment_len), comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) { + _zip_cdir_free(cd); + return NULL; + } + } + } + + if (cd->offset >= buf_offset) { + 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, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID); + _zip_cdir_free(cd); + return NULL; + } + if ((cd_buffer = _zip_buffer_new(data, cd->size)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + _zip_cdir_free(cd); + return NULL; + } + } + 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); + return NULL; + } + + /* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */ + if (zip_source_tell(za->src) != (zip_int64_t)cd->offset) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + _zip_cdir_free(cd); + return NULL; + } + } + + left = (zip_uint64_t)cd->size; + i = 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 (zip_error_code_zip(error) == ZIP_ER_INCONS) { + zip_error_set(error, ZIP_ER_INCONS, ADD_INDEX_TO_DETAIL(zip_error_code_system(error), i)); + } + else if (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) { + zip_error_set(error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_CDIR_ENTRY_INVALID, i)); + } + _zip_cdir_free(cd); + _zip_buffer_free(cd_buffer); + return NULL; + } + i++; + left -= (zip_uint64_t)entry_size; + } + + if (i != cd->nentry || left > 0) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_WRONG_ENTRIES_COUNT); + _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_cdir_free(cd); + return NULL; + } + ok = ((zip_uint64_t)offset == cd->offset + cd->size); + } + + if (!ok) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID); + _zip_buffer_free(cd_buffer); + _zip_cdir_free(cd); + return NULL; + } + } + + _zip_buffer_free(cd_buffer); + return cd; +} + + +/* _zip_checkcons: + Checks the consistency of the central directory by comparing central + directory entries with local headers and checking for plausible + file and header offsets. Returns -1 if not plausible, else the + difference between the lowest and the highest fileposition reached */ + +static zip_int64_t +_zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) { + zip_uint64_t i; + zip_uint64_t min, max, j; + struct zip_dirent temp; + + _zip_dirent_init(&temp); + if (cd->nentry) { + max = cd->entry[0].orig->offset; + min = cd->entry[0].orig->offset; + } + else + min = max = 0; + + for (i = 0; i < cd->nentry; i++) { + if (cd->entry[i].orig->offset < min) + min = cd->entry[i].orig->offset; + if (min > (zip_uint64_t)cd->offset) { + 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) + max = j; + if (max > (zip_uint64_t)cd->offset) { + 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) { + if (zip_error_code_zip(error) == ZIP_ER_INCONS) { + zip_error_set(error, ZIP_ER_INCONS, ADD_INDEX_TO_DETAIL(zip_error_code_system(error), i)); + } + _zip_dirent_finalize(&temp); + return -1; + } + + if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) { + zip_error_set(error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_ENTRY_HEADER_MISMATCH, i)); + _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); + } + + return (max - min) < ZIP_INT64_MAX ? (zip_int64_t)(max - min) : ZIP_INT64_MAX; +} + + +/* _zip_headercomp: + compares a central directory entry and a local file header + Return 0 if they are consistent, -1 if not. */ + +static int +_zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) { + if ((central->version_needed < local->version_needed) +#if 0 + /* some zip-files have different values in local + and global headers for the bitflags */ + || (central->bitflags != local->bitflags) +#endif + || (central->comp_method != local->comp_method) || (central->last_mod != local->last_mod) || !_zip_string_equal(central->filename, local->filename)) + return -1; + + if ((central->crc != local->crc) || (central->comp_size != local->comp_size) || (central->uncomp_size != local->uncomp_size)) { + /* InfoZip stores valid values in local header even when data descriptor is used. + This is in violation of the appnote. + macOS Archive sets the compressed size even when data descriptor is used ( but not the others), + also in violation of the appnote. + */ + /* if data descriptor is not used, the values must match */ + if ((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0) { + return -1; + } + /* when using a data descriptor, the local header value must be zero or match */ + if ((local->crc != 0 && central->crc != local->crc) || + (local->comp_size != 0 && central->comp_size != local->comp_size) || + (local->uncomp_size != 0 && central->uncomp_size != local->uncomp_size)) { + return -1; + } + } + + return 0; +} + + +static zip_t * +_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error) { + zip_t *za; + + if ((za = _zip_new(error)) == NULL) { + return NULL; + } + + za->src = src; + za->open_flags = flags; + za->flags = 0; + za->ch_flags = 0; + za->write_crc = NULL; + + if (flags & ZIP_RDONLY) { + za->flags |= ZIP_AFL_RDONLY; + za->ch_flags |= ZIP_AFL_RDONLY; + } + + return za; +} + + +/* + * tests for file existence + */ +static exists_t +_zip_file_exists(zip_source_t *src, zip_error_t *error) { + struct zip_stat st; + + zip_stat_init(&st); + if (zip_source_stat(src, &st) != 0) { + zip_error_t *src_error = zip_source_error(src); + if (zip_error_code_zip(src_error) == ZIP_ER_READ && zip_error_code_system(src_error) == ENOENT) { + return EXISTS_NOT; + } + _zip_error_copy(error, src_error); + return EXISTS_ERROR; + } + + return EXISTS_OK; +} + + +static zip_cdir_t * +_zip_find_central_dir(zip_t *za, zip_uint64_t len) { + zip_cdir_t *cdir, *cdirnew; + const zip_uint8_t *match; + zip_int64_t buf_offset; + zip_uint64_t buflen; + zip_int64_t a; + zip_int64_t best; + zip_error_t error; + zip_buffer_t *buffer; + + if (len < EOCDLEN) { + zip_error_set(&za->error, ZIP_ER_NOZIP, 0); + return NULL; + } + + buflen = (len < CDBUFSIZE ? len : CDBUFSIZE); + if (zip_source_seek(za->src, -(zip_int64_t)buflen, SEEK_END) < 0) { + zip_error_t *src_error = zip_source_error(za->src); + if (zip_error_code_zip(src_error) != ZIP_ER_SEEK || zip_error_code_system(src_error) != EFBIG) { + /* seek before start of file on my machine */ + _zip_error_copy(&za->error, src_error); + return NULL; + } + } + if ((buf_offset = zip_source_tell(za->src)) < 0) { + 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; + } + + best = -1; + cdir = NULL; + if (buflen >= CDBUFSIZE) { + /* EOCD64 locator is before EOCD, so leave place for it */ + _zip_buffer_set_offset(buffer, EOCD64LOCLEN); + } + zip_error_set(&error, ZIP_ER_NOZIP, 0); + + match = _zip_buffer_get(buffer, 0); + /* The size of buffer never greater than CDBUFSIZE. */ + while (_zip_buffer_left(buffer) >= EOCDLEN && (match = _zip_memmem(match, (size_t)_zip_buffer_left(buffer) - (EOCDLEN - 4), (const unsigned char *)EOCD_MAGIC, 4)) != NULL) { + _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer))); + if ((cdirnew = _zip_read_cdir(za, buffer, (zip_uint64_t)buf_offset, &error)) != NULL) { + if (cdir) { + if (best <= 0) { + best = _zip_checkcons(za, cdir, &error); + } + + a = _zip_checkcons(za, cdirnew, &error); + if (best < a) { + _zip_cdir_free(cdir); + cdir = cdirnew; + best = a; + } + else { + _zip_cdir_free(cdirnew); + } + } + else { + cdir = cdirnew; + if (za->open_flags & ZIP_CHECKCONS) + best = _zip_checkcons(za, cdir, &error); + else { + best = 0; + } + } + 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); + return NULL; + } + + return cdir; +} + + +static const unsigned char *_zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen) { + const unsigned char *p; + + if (littlelen == 0) { + return big; + } + + if (biglen < littlelen) { + return NULL; + } + + p = big; + while (true) { + p = (const unsigned char *)memchr(p, little[0], biglen - (littlelen - 1) - (size_t)(p - big)); + if (p == NULL) { + return NULL; + } + if (memcmp(p + 1, little + 1, littlelen - 1) == 0) { + return p; + } + p += 1; + } +} + + +static zip_cdir_t * +_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) { + zip_cdir_t *cd; + zip_uint64_t i, nentry, size, offset, eocd_offset; + + if (_zip_buffer_left(buffer) < EOCDLEN) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD_LENGTH_INVALID); + return NULL; + } + + eocd_offset = _zip_buffer_offset(buffer); + + _zip_buffer_get(buffer, 4); /* magic already verified */ + + if (_zip_buffer_get_32(buffer) != 0) { + zip_error_set(error, ZIP_ER_MULTIDISK, 0); + return NULL; + } + + /* number of cdir-entries on this disk */ + i = _zip_buffer_get_16(buffer); + /* number of cdir-entries */ + nentry = _zip_buffer_get_16(buffer); + + if (nentry != i) { + zip_error_set(error, ZIP_ER_NOZIP, 0); + return NULL; + } + + size = _zip_buffer_get_32(buffer); + offset = _zip_buffer_get_32(buffer); + + if (offset + size < offset) { + 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, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD); + return NULL; + } + + if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_LENGTH_INVALID); + return NULL; + } + + if ((cd = _zip_cdir_new(nentry, error)) == NULL) + return NULL; + + cd->is_zip64 = false; + cd->size = size; + cd->offset = offset; + + return cd; +} + + +static zip_cdir_t * +_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) { + zip_cdir_t *cd; + zip_uint64_t offset; + zip_uint8_t eocd[EOCD64LEN]; + zip_uint64_t eocd_offset; + zip_uint64_t size, nentry, i, eocdloc_offset; + bool free_buffer; + zip_uint32_t num_disks, num_disks64, eocd_disk, eocd_disk64; + + eocdloc_offset = _zip_buffer_offset(buffer); + + _zip_buffer_get(buffer, 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); + + /* valid seek value for start of EOCD */ + if (eocd_offset > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_SEEK, EFBIG); + return NULL; + } + + /* does EOCD fit before EOCD locator? */ + if (eocd_offset + EOCD64LEN > eocdloc_offset + buf_offset) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD); + return NULL; + } + + /* make sure current position of buffer is beginning of EOCD */ + if (eocd_offset >= buf_offset && eocd_offset + EOCD64LEN <= buf_offset + _zip_buffer_size(buffer)) { + _zip_buffer_set_offset(buffer, eocd_offset - buf_offset); + free_buffer = false; + } + else { + if (zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) { + zip_error_set_from_source(error, src); + return NULL; + } + if ((buffer = _zip_buffer_new_from_source(src, EOCD64LEN, eocd, error)) == NULL) { + return NULL; + } + free_buffer = true; + } + + if (memcmp(_zip_buffer_get(buffer, 4), EOCD64_MAGIC, 4) != 0) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_WRONG_MAGIC); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; + } + + /* size of EOCD */ + size = _zip_buffer_get_64(buffer); + + /* is there a hole between EOCD and EOCD locator, or do they overlap? */ + if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; + } + + _zip_buffer_get(buffer, 4); /* skip version made by/needed */ + + num_disks64 = _zip_buffer_get_32(buffer); + eocd_disk64 = _zip_buffer_get_32(buffer); + + /* if eocd values are 0xffff, we have to use eocd64 values. + otherwise, if the values are not the same, it's inconsistent; + in any case, if the value is not 0, we don't support it */ + if (num_disks == 0xffff) { + num_disks = num_disks64; + } + if (eocd_disk == 0xffff) { + eocd_disk = eocd_disk64; + } + if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD64_MISMATCH); + 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; + } + + nentry = _zip_buffer_get_64(buffer); + i = _zip_buffer_get_64(buffer); + + if (nentry != i) { + zip_error_set(error, ZIP_ER_MULTIDISK, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; + } + + size = _zip_buffer_get_64(buffer); + offset = _zip_buffer_get_64(buffer); + + /* did we read past the end of the buffer? */ + if (!_zip_buffer_ok(buffer)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + if (free_buffer) { + _zip_buffer_free(buffer); + } + return NULL; + } + + if (free_buffer) { + _zip_buffer_free(buffer); + } + + if (offset > ZIP_INT64_MAX || offset + size < offset) { + 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, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD); + return NULL; + } + if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD); + return NULL; + } + + if (nentry > size / CDENTRYSIZE) { + zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_CDIR_INVALID); + return NULL; + } + + if ((cd = _zip_cdir_new(nentry, error)) == NULL) + return NULL; + + cd->is_zip64 = true; + cd->size = size; + cd->offset = offset; + + return cd; +} + + +static int decode_hex(char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } + else if (c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } + else { + return -1; + } +} + +/* _zip_check_torrentzip: + check whether ZA has a valid TORRENTZIP comment, i.e. is torrentzipped */ + +static void zip_check_torrentzip(zip_t *za, const zip_cdir_t *cdir) { + zip_uint32_t crc_should; + char buf[8+1]; + size_t i; + + if (cdir == NULL) { + return; + } + + if (_zip_string_length(cdir->comment) != TORRENTZIP_SIGNATURE_LENGTH + TORRENTZIP_CRC_LENGTH + || strncmp((const char *)cdir->comment->raw, TORRENTZIP_SIGNATURE, TORRENTZIP_SIGNATURE_LENGTH) != 0) + return; + + memcpy(buf, cdir->comment->raw + TORRENTZIP_SIGNATURE_LENGTH, TORRENTZIP_CRC_LENGTH); + buf[TORRENTZIP_CRC_LENGTH] = '\0'; + crc_should = 0; + for (i = 0; i < TORRENTZIP_CRC_LENGTH; i += 2) { + int low, high; + high = decode_hex((buf[i])); + low = decode_hex(buf[i + 1]); + if (high < 0 || low < 0) { + return; + } + crc_should = (crc_should << 8) + (high << 4) + low; + } + + { + zip_stat_t st; + zip_source_t* src_window; + zip_source_t* src_crc; + zip_uint8_t buffer[512]; + zip_int64_t ret; + + zip_stat_init(&st); + st.valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC; + st.size = cdir->size; + st.crc = crc_should; + if ((src_window = _zip_source_window_new(za->src, cdir->offset, cdir->size, &st, 0, NULL, NULL, 0, false, NULL)) == NULL) { + return; + } + if ((src_crc = zip_source_crc_create(src_window, 1, NULL)) == NULL) { + zip_source_free(src_window); + return; + } + if (zip_source_open(src_crc) != 0) { + zip_source_free(src_crc); + return; + } + while ((ret = zip_source_read(src_crc, buffer, sizeof(buffer))) > 0) { + } + zip_source_free(src_crc); + if (ret < 0) { + return; + } + } + + /* TODO: if check consistency, check cdir entries for valid values */ + za->flags |= ZIP_AFL_IS_TORRENTZIP; +} diff --git a/3rdparty/libzip/lib/zip_pkware.c b/3rdparty/libzip/lib/zip_pkware.c new file mode 100644 index 0000000000..6a8c9fcde4 --- /dev/null +++ b/3rdparty/libzip/lib/zip_pkware.c @@ -0,0 +1,112 @@ +/* + zip_pkware.c -- Traditional PKWARE de/encryption backend routines + Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + +#define PKWARE_KEY0 305419896 +#define PKWARE_KEY1 591751049 +#define PKWARE_KEY2 878082192 + + +static void +update_keys(zip_pkware_keys_t *keys, zip_uint8_t b) { + keys->key[0] = (zip_uint32_t)crc32(keys->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; + keys->key[1] = (keys->key[1] + (keys->key[0] & 0xff)) * 134775813 + 1; + b = (zip_uint8_t)(keys->key[1] >> 24); + keys->key[2] = (zip_uint32_t)crc32(keys->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; +} + + +static zip_uint8_t +crypt_byte(zip_pkware_keys_t *keys) { + zip_uint16_t tmp; + tmp = (zip_uint16_t)(keys->key[2] | 2); + tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8); + return (zip_uint8_t)tmp; +} + + +void +_zip_pkware_keys_reset(zip_pkware_keys_t *keys) { + keys->key[0] = PKWARE_KEY0; + keys->key[1] = PKWARE_KEY1; + keys->key[2] = PKWARE_KEY2; +} + + +void +_zip_pkware_encrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len) { + zip_uint64_t i; + zip_uint8_t b; + zip_uint8_t tmp; + + for (i = 0; i < len; i++) { + b = in[i]; + + if (out != NULL) { + tmp = crypt_byte(keys); + update_keys(keys, b); + b ^= tmp; + out[i] = b; + } + else { + /* during initialization, we're only interested in key updates */ + update_keys(keys, b); + } + } +} + + +void +_zip_pkware_decrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len) { + zip_uint64_t i; + zip_uint8_t b; + zip_uint8_t tmp; + + for (i = 0; i < len; i++) { + b = in[i]; + + /* during initialization, we're only interested in key updates */ + if (out != NULL) { + tmp = crypt_byte(keys); + b ^= tmp; + out[i] = b; + } + + update_keys(keys, b); + } +} diff --git a/3rdparty/libzip/lib/zip_progress.c b/3rdparty/libzip/lib/zip_progress.c new file mode 100644 index 0000000000..e080514b12 --- /dev/null +++ b/3rdparty/libzip/lib/zip_progress.c @@ -0,0 +1,293 @@ +/* + zip_progress.c -- progress reporting + Copyright (C) 2017-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + +struct zip_progress { + zip_t *za; + + zip_progress_callback callback_progress; + void (*ud_progress_free)(void *); + void *ud_progress; + + zip_cancel_callback callback_cancel; + void (*ud_cancel_free)(void *); + void *ud_cancel; + + double precision; + + /* state */ + double last_update; /* last value callback function was called with */ + + double start; /* start of sub-progress section */ + double end; /* end of sub-progress section */ +}; + +static void _zip_progress_free_cancel_callback(zip_progress_t *progress); +static void _zip_progress_free_progress_callback(zip_progress_t *progress); +static zip_progress_t *_zip_progress_new(zip_t *za); +static void _zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback callback, void (*ud_free)(void *), void *ud); +static void _zip_progress_set_progress_callback(zip_progress_t *progress, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud); + +void +_zip_progress_end(zip_progress_t *progress) { + _zip_progress_update(progress, 1.0); +} + + +void +_zip_progress_free(zip_progress_t *progress) { + if (progress == NULL) { + return; + } + + _zip_progress_free_progress_callback(progress); + _zip_progress_free_cancel_callback(progress); + + free(progress); +} + + +static zip_progress_t * +_zip_progress_new(zip_t *za) { + zip_progress_t *progress = (zip_progress_t *)malloc(sizeof(*progress)); + + if (progress == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + progress->za = za; + + progress->callback_progress = NULL; + progress->ud_progress_free = NULL; + progress->ud_progress = NULL; + progress->precision = 0.0; + + progress->callback_cancel = NULL; + progress->ud_cancel_free = NULL; + progress->ud_cancel = NULL; + + return progress; +} + +static void +_zip_progress_free_progress_callback(zip_progress_t *progress) { + if (progress->ud_progress_free) { + progress->ud_progress_free(progress->ud_progress); + } + + progress->callback_progress = NULL; + progress->ud_progress = NULL; + progress->ud_progress_free = NULL; +} + +static void +_zip_progress_free_cancel_callback(zip_progress_t *progress) { + if (progress->ud_cancel_free) { + progress->ud_cancel_free(progress->ud_cancel); + } + + progress->callback_cancel = NULL; + progress->ud_cancel = NULL; + progress->ud_cancel_free = NULL; +} + +static void +_zip_progress_set_progress_callback(zip_progress_t *progress, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) { + _zip_progress_free_progress_callback(progress); + + progress->callback_progress = callback; + progress->ud_progress_free = ud_free; + progress->ud_progress = ud; + progress->precision = precision; +} + +void +_zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) { + _zip_progress_free_cancel_callback(progress); + + progress->callback_cancel = callback; + progress->ud_cancel_free = ud_free; + progress->ud_cancel = ud; +} + +int +_zip_progress_start(zip_progress_t *progress) { + if (progress == NULL) { + return 0; + } + + if (progress->callback_progress != NULL) { + progress->last_update = 0.0; + progress->callback_progress(progress->za, 0.0, progress->ud_progress); + } + + if (progress->callback_cancel != NULL) { + if (progress->callback_cancel(progress->za, progress->ud_cancel)) { + return -1; + } + } + + return 0; +} + + +int +_zip_progress_subrange(zip_progress_t *progress, double start, double end) { + if (progress == NULL) { + return 0; + } + + progress->start = start; + progress->end = end; + + return _zip_progress_update(progress, 0.0); +} + +int +_zip_progress_update(zip_progress_t *progress, double sub_current) { + double current; + + if (progress == NULL) { + return 0; + } + + if (progress->callback_progress != NULL) { + current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start; + + if (current - progress->last_update > progress->precision) { + progress->callback_progress(progress->za, current, progress->ud_progress); + progress->last_update = current; + } + } + + if (progress->callback_cancel != NULL) { + if (progress->callback_cancel(progress->za, progress->ud_cancel)) { + return -1; + } + } + + return 0; +} + + +ZIP_EXTERN int +zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) { + if (callback != NULL) { + if (za->progress == NULL) { + if ((za->progress = _zip_progress_new(za)) == NULL) { + return -1; + } + } + + _zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud); + } + else { + if (za->progress != NULL) { + if (za->progress->callback_cancel == NULL) { + _zip_progress_free(za->progress); + za->progress = NULL; + } + else { + _zip_progress_free_progress_callback(za->progress); + } + } + } + + return 0; +} + + +ZIP_EXTERN int +zip_register_cancel_callback_with_state(zip_t *za, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) { + if (callback != NULL) { + if (za->progress == NULL) { + if ((za->progress = _zip_progress_new(za)) == NULL) { + return -1; + } + } + + _zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud); + } + else { + if (za->progress != NULL) { + if (za->progress->callback_progress == NULL) { + _zip_progress_free(za->progress); + za->progress = NULL; + } + else { + _zip_progress_free_cancel_callback(za->progress); + } + } + } + + return 0; +} + + +struct legacy_ud { + zip_progress_callback_t callback; +}; + + +static void +_zip_legacy_progress_callback(zip_t *za, double progress, void *vud) { + struct legacy_ud *ud = (struct legacy_ud *)vud; + + ud->callback(progress); +} + +ZIP_EXTERN void +zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callback) { + struct legacy_ud *ud; + + if (progress_callback == NULL) { + zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL); + } + + if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) { + return; + } + + ud->callback = progress_callback; + + if (zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) { + free(ud); + } +} diff --git a/3rdparty/libzip/lib/zip_random_unix.c b/3rdparty/libzip/lib/zip_random_unix.c new file mode 100644 index 0000000000..867df7900e --- /dev/null +++ b/3rdparty/libzip/lib/zip_random_unix.c @@ -0,0 +1,110 @@ +/* + zip_random_unix.c -- fill the user's buffer with random stuff (Unix version) + Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#ifdef HAVE_CRYPTO +#include "zip_crypto.h" +#endif + +#ifdef HAVE_ARC4RANDOM + +#include + +#ifndef HAVE_SECURE_RANDOM +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + arc4random_buf(buffer, length); + return true; +} +#endif + +#ifndef HAVE_RANDOM_UINT32 +zip_uint32_t +zip_random_uint32(void) { + return arc4random(); +} +#endif + +#else /* HAVE_ARC4RANDOM */ + +#ifndef HAVE_SECURE_RANDOM +#include +#include + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + int fd; + + if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { + return false; + } + + if (read(fd, buffer, length) != length) { + close(fd); + return false; + } + + close(fd); + return true; +} +#endif + +#ifndef HAVE_RANDOM_UINT32 +#include + +#ifndef HAVE_RANDOM +#define srandom srand +#define random rand +#endif + +zip_uint32_t +zip_random_uint32(void) { + static bool seeded = false; + + zip_uint32_t value; + + if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) { + return value; + } + + if (!seeded) { + srandom((unsigned int)time(NULL)); + seeded = true; + } + + return (zip_uint32_t)random(); +} +#endif + +#endif /* HAVE_ARC4RANDOM */ diff --git a/3rdparty/libzip/lib/zip_random_uwp.c b/3rdparty/libzip/lib/zip_random_uwp.c new file mode 100644 index 0000000000..0883ce454f --- /dev/null +++ b/3rdparty/libzip/lib/zip_random_uwp.c @@ -0,0 +1,82 @@ +/* + zip_random_uwp.c -- fill the user's buffer with random stuff (UWP version) + Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#ifdef HAVE_CRYPTO +#include "zip_crypto.h" +#endif + +#ifndef HAVE_SECURE_RANDOM + +#include +#include + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + BCRYPT_ALG_HANDLE hAlg = NULL; + NTSTATUS hr = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); + if (!BCRYPT_SUCCESS(hr) || hAlg == NULL) { + return false; + } + hr = BCryptGenRandom(&hAlg, buffer, length, 0); + BCryptCloseAlgorithmProvider(&hAlg, 0); + if (!BCRYPT_SUCCESS(hr)) { + return false; + } + return true; +} + +#endif + +#ifndef HAVE_RANDOM_UINT32 +#include + +zip_uint32_t +zip_random_uint32(void) { + static bool seeded = false; + + zip_uint32_t value; + + if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) { + return value; + } + + if (!seeded) { + srand((unsigned int)time(NULL)); + seeded = true; + } + + return (zip_uint32_t)rand(); +} +#endif diff --git a/3rdparty/libzip/lib/zip_random_win32.c b/3rdparty/libzip/lib/zip_random_win32.c new file mode 100644 index 0000000000..789b9c2058 --- /dev/null +++ b/3rdparty/libzip/lib/zip_random_win32.c @@ -0,0 +1,82 @@ +/* + zip_random_win32.c -- fill the user's buffer with random stuff (Windows version) + Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#ifdef HAVE_CRYPTO +#include "zip_crypto.h" +#endif + +#include + +#ifndef HAVE_SECURE_RANDOM + +#include + +ZIP_EXTERN bool +zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) { + HCRYPTPROV hprov; + if (!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { + return false; + } + if (!CryptGenRandom(hprov, length, buffer)) { + return false; + } + if (!CryptReleaseContext(hprov, 0)) { + return false; + } + return true; +} +#endif + +#ifndef HAVE_RANDOM_UINT32 +#include + +zip_uint32_t +zip_random_uint32(void) { + static bool seeded = false; + + zip_uint32_t value; + + if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) { + return value; + } + + if (!seeded) { + srand((unsigned int)time(NULL)); + seeded = true; + } + + return (zip_uint32_t)rand(); +} +#endif diff --git a/3rdparty/libzip/lib/zip_rename.c b/3rdparty/libzip/lib/zip_rename.c new file mode 100644 index 0000000000..c89b06c9e3 --- /dev/null +++ b/3rdparty/libzip/lib/zip_rename.c @@ -0,0 +1,42 @@ +/* + zip_rename.c -- rename file in zip archive + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN int +zip_rename(zip_t *za, zip_uint64_t idx, const char *name) { + return zip_file_rename(za, idx, name, 0); +} diff --git a/3rdparty/libzip/lib/zip_replace.c b/3rdparty/libzip/lib/zip_replace.c new file mode 100644 index 0000000000..96c083c3dc --- /dev/null +++ b/3rdparty/libzip/lib/zip_replace.c @@ -0,0 +1,42 @@ +/* + zip_replace.c -- replace file via callback function + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN int +zip_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source) { + return zip_file_replace(za, idx, source, 0); +} diff --git a/3rdparty/libzip/lib/zip_set_archive_comment.c b/3rdparty/libzip/lib/zip_set_archive_comment.c new file mode 100644 index 0000000000..7d06688e3a --- /dev/null +++ b/3rdparty/libzip/lib/zip_set_archive_comment.c @@ -0,0 +1,84 @@ +/* + zip_set_archive_comment.c -- set archive comment + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len) { + zip_string_t *cstr; + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + if (ZIP_WANT_TORRENTZIP(za)) { + zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0); + return -1; + } + + if (len > 0 && comment == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (len > 0) { + if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL) + return -1; + + if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) { + _zip_string_free(cstr); + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + } + else + cstr = NULL; + + _zip_string_free(za->comment_changes); + za->comment_changes = NULL; + + if (((za->comment_orig && _zip_string_equal(za->comment_orig, cstr)) || (za->comment_orig == NULL && cstr == NULL))) { + _zip_string_free(cstr); + za->comment_changed = 0; + } + else { + za->comment_changes = cstr; + za->comment_changed = 1; + } + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_set_archive_flag.c b/3rdparty/libzip/lib/zip_set_archive_flag.c new file mode 100644 index 0000000000..834ef5baca --- /dev/null +++ b/3rdparty/libzip/lib/zip_set_archive_flag.c @@ -0,0 +1,76 @@ +/* + zip_get_archive_flag.c -- set archive global flag + Copyright (C) 2008-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value) { + unsigned int new_flags; + + if (flag == ZIP_AFL_IS_TORRENTZIP) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + /* TODO: when setting ZIP_AFL_WANT_TORRENTZIP, we should error out if any changes have been made that are not allowed for torrentzip. */ + + if (value) { + new_flags = za->ch_flags | flag; + } + else { + new_flags = za->ch_flags & ~flag; + } + + if (new_flags == za->ch_flags) { + return 0; + } + + /* Allow removing ZIP_AFL_RDONLY if manually set, not if archive was opened read-only. */ + if (za->flags & ZIP_AFL_RDONLY) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if ((flag & ZIP_AFL_RDONLY) && value && (za->ch_flags & ZIP_AFL_RDONLY) == 0) { + if (_zip_changed(za, NULL)) { + zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return -1; + } + } + + za->ch_flags = new_flags; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_set_default_password.c b/3rdparty/libzip/lib/zip_set_default_password.c new file mode 100644 index 0000000000..4bab513f46 --- /dev/null +++ b/3rdparty/libzip/lib/zip_set_default_password.c @@ -0,0 +1,58 @@ +/* + zip_set_default_password.c -- set default password for decryption + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_set_default_password(zip_t *za, const char *passwd) { + if (za == NULL) + return -1; + + free(za->default_password); + + if (passwd && passwd[0] != '\0') { + if ((za->default_password = strdup(passwd)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + else + za->default_password = NULL; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_set_file_comment.c b/3rdparty/libzip/lib/zip_set_file_comment.c new file mode 100644 index 0000000000..5d2b0b8a03 --- /dev/null +++ b/3rdparty/libzip/lib/zip_set_file_comment.c @@ -0,0 +1,46 @@ +/* + zip_set_file_comment.c -- set comment for file in archive + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + + +ZIP_EXTERN int +zip_set_file_comment(zip_t *za, zip_uint64_t idx, const char *comment, int len) { + if (len < 0 || len > ZIP_UINT16_MAX) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0); +} diff --git a/3rdparty/libzip/lib/zip_set_file_compression.c b/3rdparty/libzip/lib/zip_set_file_compression.c new file mode 100644 index 0000000000..a193bb77fb --- /dev/null +++ b/3rdparty/libzip/lib/zip_set_file_compression.c @@ -0,0 +1,95 @@ +/* + zip_set_file_compression.c -- set compression for file in archive + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_uint32_t flags) { + zip_entry_t *e; + zip_int32_t old_method; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + if (ZIP_WANT_TORRENTZIP(za)) { + zip_error_set(&za->error, ZIP_ER_NOT_ALLOWED, 0); + return -1; + } + + if (!zip_compression_method_supported(method, true)) { + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + return -1; + } + + e = za->entry + idx; + + old_method = (e->orig == NULL ? ZIP_CM_DEFAULT : e->orig->comp_method); + + /* 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; + } + } + } + else { + if (e->changes == NULL) { + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + e->changes->comp_method = method; + e->changes->compression_level = (zip_uint16_t)flags; + e->changes->changed |= ZIP_DIRENT_COMP_METHOD; + } + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_set_name.c b/3rdparty/libzip/lib/zip_set_name.c new file mode 100644 index 0000000000..f1bf703e44 --- /dev/null +++ b/3rdparty/libzip/lib/zip_set_name.c @@ -0,0 +1,157 @@ +/* + zip_set_name.c -- rename helper function + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + + +int +_zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) { + zip_entry_t *e; + zip_string_t *str; + bool same_as_orig; + zip_int64_t i; + const zip_uint8_t *old_name, *new_name; + zip_string_t *old_str; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (ZIP_IS_RDONLY(za)) { + zip_error_set(&za->error, ZIP_ER_RDONLY, 0); + return -1; + } + + if (name && name[0] != '\0') { + /* TODO: check for string too long */ + if ((str = _zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL) + return -1; + if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED) + str->encoding = ZIP_ENCODING_UTF8_KNOWN; + } + else + str = NULL; + + /* TODO: encoding flags needed for CP437? */ + if ((i = _zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) { + _zip_string_free(str); + zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; + } + + /* no effective name change */ + if (i >= 0 && (zip_uint64_t)i == idx) { + _zip_string_free(str); + return 0; + } + + e = za->entry + idx; + + if (e->orig) + same_as_orig = _zip_string_equal(e->orig->filename, str); + else + same_as_orig = false; + + if (!same_as_orig && e->changes == NULL) { + if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_string_free(str); + return -1; + } + } + + if ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) { + _zip_string_free(str); + return -1; + } + + if (e->changes) { + old_str = e->changes->filename; + } + else if (e->orig) { + old_str = e->orig->filename; + } + else { + old_str = NULL; + } + + if (old_str) { + if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) { + _zip_string_free(str); + return -1; + } + } + else { + old_name = NULL; + } + + if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) { + _zip_string_free(str); + return -1; + } + if (old_name) { + _zip_hash_delete(za->names, old_name, NULL); + } + + if (same_as_orig) { + if (e->changes) { + if (e->changes->changed & ZIP_DIRENT_FILENAME) { + _zip_string_free(e->changes->filename); + e->changes->changed &= ~ZIP_DIRENT_FILENAME; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + else { + /* TODO: what if not cloned? can that happen? */ + e->changes->filename = e->orig->filename; + } + } + } + _zip_string_free(str); + } + else { + if (e->changes->changed & ZIP_DIRENT_FILENAME) { + _zip_string_free(e->changes->filename); + } + e->changes->changed |= ZIP_DIRENT_FILENAME; + e->changes->filename = str; + } + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_source_accept_empty.c b/3rdparty/libzip/lib/zip_source_accept_empty.c new file mode 100644 index 0000000000..e772aeea96 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_accept_empty.c @@ -0,0 +1,52 @@ +/* + zip_source_accept_empty.c -- if empty source is a valid archive + Copyright (C) 2019-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +bool +zip_source_accept_empty(zip_source_t *src) { + zip_int64_t ret; + + if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY)) == 0) { + if (ZIP_SOURCE_IS_LAYERED(src)) { + return zip_source_accept_empty(src->src); + } + return true; + } + + ret = _zip_source_call(src, NULL, 0, ZIP_SOURCE_ACCEPT_EMPTY); + + return ret != 0; +} diff --git a/3rdparty/libzip/lib/zip_source_begin_write.c b/3rdparty/libzip/lib/zip_source_begin_write.c new file mode 100644 index 0000000000..4a9d5d5d66 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_begin_write.c @@ -0,0 +1,57 @@ +/* + zip_source_begin_write.c -- start a new file for writing + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_begin_write(zip_source_t *src) { + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_BEGIN_WRITE) < 0) { + return -1; + } + + src->write_state = ZIP_SOURCE_WRITE_OPEN; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_source_begin_write_cloning.c b/3rdparty/libzip/lib/zip_source_begin_write_cloning.c new file mode 100644 index 0000000000..df195fcd40 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_begin_write_cloning.c @@ -0,0 +1,57 @@ +/* + zip_source_begin_write_cloning.c -- clone part of file for writing + Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_begin_write_cloning(zip_source_t *src, zip_uint64_t offset) { + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (_zip_source_call(src, NULL, offset, ZIP_SOURCE_BEGIN_WRITE_CLONING) < 0) { + return -1; + } + + src->write_state = ZIP_SOURCE_WRITE_OPEN; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_source_buffer.c b/3rdparty/libzip/lib/zip_source_buffer.c new file mode 100644 index 0000000000..5667293253 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_buffer.c @@ -0,0 +1,643 @@ +/* + zip_source_buffer.c -- create zip data source from buffer + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#include "zipint.h" + +#ifndef WRITE_FRAGMENT_SIZE +#define WRITE_FRAGMENT_SIZE (64 * 1024) +#endif + +struct buffer { + zip_buffer_fragment_t *fragments; /* fragments */ + zip_uint64_t *fragment_offsets; /* offset of each fragment from start of buffer, nfragments+1 entries */ + zip_uint64_t nfragments; /* number of allocated fragments */ + zip_uint64_t fragments_capacity; /* size of fragments (number of pointers) */ + + zip_uint64_t first_owned_fragment; /* first fragment to free data from */ + + zip_uint64_t shared_fragments; /* number of shared fragments */ + struct buffer *shared_buffer; /* buffer fragments are shared with */ + + zip_uint64_t size; /* size of buffer */ + zip_uint64_t offset; /* current offset in buffer */ + zip_uint64_t current_fragment; /* fragment current offset is in */ +}; + +typedef struct buffer buffer_t; + +struct read_data { + zip_error_t error; + time_t mtime; + zip_file_attributes_t attributes; + buffer_t *in; + buffer_t *out; +}; + +#define buffer_capacity(buffer) ((buffer)->fragment_offsets[(buffer)->nfragments]) +#define buffer_size(buffer) ((buffer)->size) + +static buffer_t *buffer_clone(buffer_t *buffer, zip_uint64_t length, zip_error_t *error); +static zip_uint64_t buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset); +static void buffer_free(buffer_t *buffer); +static bool buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error); +static buffer_t *buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error); +static zip_int64_t buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length); +static int buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error); +static zip_int64_t buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *); + +static zip_int64_t read_data(void *, void *, zip_uint64_t, zip_source_cmd_t); + +zip_source_t *zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error); +zip_source_t *zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error); + + +ZIP_EXTERN zip_source_t * +zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) { + if (za == NULL) + return NULL; + + return zip_source_buffer_with_attributes_create(data, len, freep, NULL, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) { + return zip_source_buffer_with_attributes_create(data, len, freep, NULL, error); +} + + +zip_source_t * +zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error) { + zip_buffer_fragment_t fragment; + + if (data == NULL) { + if (len > 0) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + return zip_source_buffer_fragment_with_attributes_create(NULL, 0, freep, attributes, error); + } + + fragment.data = (zip_uint8_t *)data; + fragment.length = len; + + return zip_source_buffer_fragment_with_attributes_create(&fragment, 1, freep, attributes, error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_buffer_fragment(zip_t *za, const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep) { + if (za == NULL) { + return NULL; + } + + return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_error_t *error) { + return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, error); +} + +zip_source_t * +zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error) { + struct read_data *ctx; + zip_source_t *zs; + buffer_t *buffer; + + if (fragments == NULL && nfragments > 0) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((buffer = buffer_new(fragments, nfragments, freep, error)) == NULL) { + return NULL; + } + + if ((ctx = (struct read_data *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + buffer_free(buffer); + return NULL; + } + + ctx->in = buffer; + ctx->out = NULL; + ctx->mtime = time(NULL); + if (attributes) { + (void)memcpy_s(&ctx->attributes, sizeof(ctx->attributes), attributes, sizeof(ctx->attributes)); + } + else { + zip_file_attributes_init(&ctx->attributes); + } + zip_error_init(&ctx->error); + + if ((zs = zip_source_function_create(read_data, ctx, error)) == NULL) { + buffer_free(ctx->in); + free(ctx); + return NULL; + } + + return zs; +} + + +zip_source_t * +zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes) { + return zip_source_buffer_with_attributes_create(data, len, freep, attributes, &za->error); +} + +static zip_int64_t +read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { + struct read_data *ctx = (struct read_data *)state; + + switch (cmd) { + case ZIP_SOURCE_BEGIN_WRITE: + if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) { + return -1; + } + ctx->out->offset = 0; + ctx->out->current_fragment = 0; + return 0; + + case ZIP_SOURCE_BEGIN_WRITE_CLONING: + if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) { + return -1; + } + ctx->out->offset = len; + ctx->out->current_fragment = ctx->out->nfragments; + return 0; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_COMMIT_WRITE: + buffer_free(ctx->in); + ctx->in = ctx->out; + ctx->out = NULL; + return 0; + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + buffer_free(ctx->in); + buffer_free(ctx->out); + free(ctx); + return 0; + + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: { + if (len < sizeof(ctx->attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + (void)memcpy_s(data, sizeof(ctx->attributes), &ctx->attributes, sizeof(ctx->attributes)); + + return sizeof(ctx->attributes); + } + + case ZIP_SOURCE_OPEN: + ctx->in->offset = 0; + ctx->in->current_fragment = 0; + return 0; + + case ZIP_SOURCE_READ: + if (len > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + return buffer_read(ctx->in, data, len); + + case ZIP_SOURCE_REMOVE: { + buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error); + if (empty == NULL) { + return -1; + } + + buffer_free(ctx->in); + ctx->in = empty; + return 0; + } + + case ZIP_SOURCE_ROLLBACK_WRITE: + buffer_free(ctx->out); + ctx->out = NULL; + return 0; + + case ZIP_SOURCE_SEEK: + return buffer_seek(ctx->in, data, len, &ctx->error); + + case ZIP_SOURCE_SEEK_WRITE: + return buffer_seek(ctx->out, data, len, &ctx->error); + + case ZIP_SOURCE_STAT: { + zip_stat_t *st; + + if (len < sizeof(*st)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + st = (zip_stat_t *)data; + + zip_stat_init(st); + st->mtime = ctx->mtime; + st->size = ctx->in->size; + st->comp_size = st->size; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; + st->valid = ZIP_STAT_MTIME | ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD; + + return sizeof(*st); + } + + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_BEGIN_WRITE_CLONING, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, ZIP_SOURCE_SUPPORTS_REOPEN, -1); + + case ZIP_SOURCE_TELL: + if (ctx->in->offset > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW); + return -1; + } + return (zip_int64_t)ctx->in->offset; + + + case ZIP_SOURCE_TELL_WRITE: + if (ctx->out->offset > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW); + return -1; + } + return (zip_int64_t)ctx->out->offset; + + case ZIP_SOURCE_WRITE: + if (len > ZIP_INT64_MAX) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + return buffer_write(ctx->out, data, len, &ctx->error); + + default: + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } +} + + +static buffer_t * +buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) { + zip_uint64_t fragment, fragment_offset, waste; + buffer_t *clone; + + if (offset == 0) { + return buffer_new(NULL, 0, 1, error); + } + + if (offset > buffer->size) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + if (buffer->shared_buffer != NULL) { + zip_error_set(error, ZIP_ER_INUSE, 0); + return NULL; + } + + fragment = buffer_find_fragment(buffer, offset); + fragment_offset = offset - buffer->fragment_offsets[fragment]; + + if (fragment_offset == 0) { + fragment--; + fragment_offset = buffer->fragments[fragment].length; + } + + /* TODO: This should also consider the length of the fully shared fragments */ + waste = buffer->fragments[fragment].length - fragment_offset; + if (waste > offset) { + zip_error_set(error, ZIP_ER_OPNOTSUPP, 0); + return NULL; + } + + if ((clone = buffer_new(buffer->fragments, fragment + 1, 0, error)) == NULL) { + return NULL; + } + +#ifndef __clang_analyzer__ + /* clone->fragments can't be null, since it was created with at least one fragment */ + clone->fragments[fragment].length = fragment_offset; +#endif + clone->fragment_offsets[clone->nfragments] = offset; + clone->size = offset; + + clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments); + + buffer->shared_buffer = clone; + clone->shared_buffer = buffer; + buffer->shared_fragments = fragment + 1; + clone->shared_fragments = fragment + 1; + + return clone; +} + + +static zip_uint64_t +buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset) { + zip_uint64_t low, high, mid; + + if (buffer->nfragments == 0) { + return 0; + } + + low = 0; + high = buffer->nfragments - 1; + + while (low < high) { + mid = (high - low) / 2 + low; + if (buffer->fragment_offsets[mid] > offset) { + high = mid - 1; + } + else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) { + return mid; + } + else { + low = mid + 1; + } + } + + return low; +} + + +static void +buffer_free(buffer_t *buffer) { + zip_uint64_t i; + + if (buffer == NULL) { + return; + } + + if (buffer->shared_buffer != NULL) { + buffer->shared_buffer->shared_buffer = NULL; + buffer->shared_buffer->shared_fragments = 0; + + buffer->first_owned_fragment = ZIP_MAX(buffer->first_owned_fragment, buffer->shared_fragments); + } + + for (i = buffer->first_owned_fragment; i < buffer->nfragments; i++) { + free(buffer->fragments[i].data); + } + free(buffer->fragments); + free(buffer->fragment_offsets); + free(buffer); +} + + +static bool +buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *error) { + zip_buffer_fragment_t *fragments; + zip_uint64_t *offsets; + + if (capacity < buffer->fragments_capacity) { + return true; + } + + zip_uint64_t fragments_size = sizeof(buffer->fragments[0]) * capacity; + zip_uint64_t offsets_size = sizeof(buffer->fragment_offsets[0]) * (capacity + 1); + + if (capacity == ZIP_UINT64_MAX || fragments_size < capacity || fragments_size > SIZE_MAX|| offsets_size < capacity || offsets_size > SIZE_MAX) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + + if ((fragments = realloc(buffer->fragments, (size_t)fragments_size)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + buffer->fragments = fragments; + if ((offsets = realloc(buffer->fragment_offsets, (size_t)offsets_size)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + buffer->fragment_offsets = offsets; + buffer->fragments_capacity = capacity; + + return true; +} + + +static buffer_t * +buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int free_data, zip_error_t *error) { + buffer_t *buffer; + + if ((buffer = malloc(sizeof(*buffer))) == NULL) { + return NULL; + } + + buffer->offset = 0; + buffer->first_owned_fragment = 0; + buffer->size = 0; + buffer->fragments = NULL; + buffer->fragment_offsets = NULL; + buffer->nfragments = 0; + buffer->fragments_capacity = 0; + buffer->shared_buffer = NULL; + buffer->shared_fragments = 0; + + if (nfragments == 0) { + if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) { + free(buffer); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + buffer->fragment_offsets[0] = 0; + } + else { + zip_uint64_t i, j, offset; + + if (!buffer_grow_fragments(buffer, nfragments, NULL)) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + buffer_free(buffer); + return NULL; + } + + offset = 0; + for (i = 0, j = 0; i < nfragments; i++) { + if (fragments[i].length == 0) { + continue; + } + if (fragments[i].data == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + buffer_free(buffer); + return NULL; + } + buffer->fragments[j].data = fragments[i].data; + buffer->fragments[j].length = fragments[i].length; + buffer->fragment_offsets[i] = offset; + /* TODO: overflow */ + offset += fragments[i].length; + j++; + } + buffer->nfragments = j; + buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments; + buffer->fragment_offsets[buffer->nfragments] = offset; + buffer->size = offset; + } + + return buffer; +} + +static zip_int64_t +buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) { + zip_uint64_t n, i, fragment_offset; + + length = ZIP_MIN(length, buffer->size - buffer->offset); + + if (length == 0) { + return 0; + } + if (length > ZIP_INT64_MAX) { + return -1; + } + + i = buffer->current_fragment; + fragment_offset = buffer->offset - buffer->fragment_offsets[i]; + n = 0; + while (n < length) { + zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset); +#if ZIP_UINT64_MAX > SIZE_MAX + left = ZIP_MIN(left, SIZE_MAX); +#endif + + (void)memcpy_s(data + n, (size_t)left, buffer->fragments[i].data + fragment_offset, (size_t)left); + + if (left == buffer->fragments[i].length - fragment_offset) { + i++; + } + n += left; + fragment_offset = 0; + } + + buffer->offset += n; + buffer->current_fragment = i; + return (zip_int64_t)n; +} + + +static int +buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error) { + zip_int64_t new_offset = zip_source_seek_compute_offset(buffer->offset, buffer->size, data, len, error); + + if (new_offset < 0) { + return -1; + } + + buffer->offset = (zip_uint64_t)new_offset; + buffer->current_fragment = buffer_find_fragment(buffer, buffer->offset); + return 0; +} + + +static zip_int64_t +buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *error) { + zip_uint64_t copied, i, fragment_offset, capacity; + + if (buffer->offset + length + WRITE_FRAGMENT_SIZE - 1 < length) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + /* grow buffer if needed */ + capacity = buffer_capacity(buffer); + if (buffer->offset + length > capacity) { + zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE; + + if (needed_fragments > buffer->fragments_capacity) { + zip_uint64_t new_capacity = buffer->fragments_capacity; + + if (new_capacity == 0) { + new_capacity = 16; + } + while (new_capacity < needed_fragments) { + new_capacity *= 2; + } + + if (!buffer_grow_fragments(buffer, new_capacity, error)) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return -1; + } + } + + while (buffer->nfragments < needed_fragments) { + if ((buffer->fragments[buffer->nfragments].data = malloc(WRITE_FRAGMENT_SIZE)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return -1; + } + buffer->fragments[buffer->nfragments].length = WRITE_FRAGMENT_SIZE; + buffer->nfragments++; + capacity += WRITE_FRAGMENT_SIZE; + buffer->fragment_offsets[buffer->nfragments] = capacity; + } + } + + i = buffer->current_fragment; + fragment_offset = buffer->offset - buffer->fragment_offsets[i]; + copied = 0; + while (copied < length) { + zip_uint64_t n = ZIP_MIN(ZIP_MIN(length - copied, buffer->fragments[i].length - fragment_offset), SIZE_MAX); +#if ZIP_UINT64_MAX > SIZE_MAX + n = ZIP_MIN(n, SIZE_MAX); +#endif + + (void)memcpy_s(buffer->fragments[i].data + fragment_offset, (size_t)n, data + copied, (size_t)n); + + if (n == buffer->fragments[i].length - fragment_offset) { + i++; + fragment_offset = 0; + } + else { + fragment_offset += n; + } + copied += n; + } + + buffer->offset += copied; + buffer->current_fragment = i; + if (buffer->offset > buffer->size) { + buffer->size = buffer->offset; + } + + return (zip_int64_t)copied; +} diff --git a/3rdparty/libzip/lib/zip_source_call.c b/3rdparty/libzip/lib/zip_source_call.c new file mode 100644 index 0000000000..8c98fc2ef2 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_call.c @@ -0,0 +1,68 @@ +/* + zip_source_call.c -- invoke callback command on zip_source + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "zipint.h" + + +zip_int64_t +_zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command) { + zip_int64_t ret; + + if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(command)) == 0) { + zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + if (src->src == NULL) { + ret = src->cb.f(src->ud, data, length, command); + } + else { + ret = src->cb.l(src->src, src->ud, data, length, command); + } + + if (ret < 0) { + if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) { + int e[2]; + + if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) { + zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); + } + else { + zip_error_set(&src->error, e[0], e[1]); + } + } + } + + return ret; +} diff --git a/3rdparty/libzip/lib/zip_source_close.c b/3rdparty/libzip/lib/zip_source_close.c new file mode 100644 index 0000000000..f4f3ff2b3c --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_close.c @@ -0,0 +1,57 @@ +/* + zip_source_close.c -- close zip_source (stop reading) + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +int +zip_source_close(zip_source_t *src) { + if (!ZIP_SOURCE_IS_OPEN_READING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + src->open_count--; + if (src->open_count == 0) { + _zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE); + + if (ZIP_SOURCE_IS_LAYERED(src)) { + if (zip_source_close(src->src) < 0) { + zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); + } + } + } + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_source_commit_write.c b/3rdparty/libzip/lib/zip_source_commit_write.c new file mode 100644 index 0000000000..d7f567b80a --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_commit_write.c @@ -0,0 +1,68 @@ +/* + zip_source_commit_write.c -- commit changes to file + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_commit_write(zip_source_t *src) { + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (src->open_count > 1) { + zip_error_set(&src->error, ZIP_ER_INUSE, 0); + return -1; + } + else if (ZIP_SOURCE_IS_OPEN_READING(src)) { + if (zip_source_close(src) < 0) { + return -1; + } + } + + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_COMMIT_WRITE) < 0) { + src->write_state = ZIP_SOURCE_WRITE_FAILED; + return -1; + } + + src->write_state = ZIP_SOURCE_WRITE_CLOSED; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_source_compress.c b/3rdparty/libzip/lib/zip_source_compress.c new file mode 100644 index 0000000000..3cf709ffa1 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_compress.c @@ -0,0 +1,398 @@ +/* + zip_source_compress.c -- (de)compression routines + Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +#include "zipint.h" + +struct context { + zip_error_t error; + + bool end_of_input; + bool end_of_stream; + bool can_store; + bool is_stored; /* only valid if end_of_stream is true */ + bool compress; + zip_int32_t method; + + zip_uint64_t size; + zip_int64_t first_read; + zip_uint8_t buffer[BUFSIZE]; + + zip_compression_algorithm_t *algorithm; + void *ud; +}; + + +struct implementation { + zip_uint16_t method; + zip_compression_algorithm_t *compress; + zip_compression_algorithm_t *decompress; +}; + +static struct implementation implementations[] = { + {ZIP_CM_DEFLATE, &zip_algorithm_deflate_compress, &zip_algorithm_deflate_decompress}, +#if defined(HAVE_LIBBZ2) + {ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress}, +#endif +#if defined(HAVE_LIBLZMA) + {ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, + /* Disabled - because 7z isn't able to unpack ZIP+LZMA2 + archives made this way - and vice versa. + + {ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, + */ + {ZIP_CM_XZ, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, +#endif +#if defined(HAVE_LIBZSTD) + {ZIP_CM_ZSTD, &zip_algorithm_zstd_compress, &zip_algorithm_zstd_decompress}, +#endif + +}; + +static size_t implementations_size = sizeof(implementations) / sizeof(implementations[0]); + +static zip_source_t *compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, zip_uint32_t compression_flags); +static zip_int64_t compress_callback(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); +static void context_free(struct context *ctx); +static struct context *context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, zip_compression_algorithm_t *algorithm); +static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t); + +zip_compression_algorithm_t * +_zip_get_compression_algorithm(zip_int32_t method, bool compress) { + size_t i; + zip_uint16_t real_method = ZIP_CM_ACTUAL(method); + + for (i = 0; i < implementations_size; i++) { + if (implementations[i].method == real_method) { + if (compress) { + return implementations[i].compress; + } + else { + return implementations[i].decompress; + } + } + } + + return NULL; +} + +ZIP_EXTERN int +zip_compression_method_supported(zip_int32_t method, int compress) { + if (method == ZIP_CM_STORE) { + return 1; + } + return _zip_get_compression_algorithm(method, compress) != NULL; +} + +zip_source_t * +zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t method, zip_uint32_t compression_flags) { + return compression_source_new(za, src, method, true, compression_flags); +} + +zip_source_t * +zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t method) { + return compression_source_new(za, src, method, false, 0); +} + + +static zip_source_t * +compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, zip_uint32_t compression_flags) { + struct context *ctx; + zip_source_t *s2; + zip_compression_algorithm_t *algorithm = NULL; + + if (src == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((algorithm = _zip_get_compression_algorithm(method, compress)) == NULL) { + zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0); + return NULL; + } + + if ((ctx = context_new(method, compress, compression_flags, algorithm)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((s2 = zip_source_layered(za, src, compress_callback, ctx)) == NULL) { + context_free(ctx); + return NULL; + } + + return s2; +} + + +static struct context * +context_new(zip_int32_t method, bool compress, zip_uint32_t compression_flags, zip_compression_algorithm_t *algorithm) { + struct context *ctx; + + if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) { + return NULL; + } + zip_error_init(&ctx->error); + ctx->can_store = compress ? ZIP_CM_IS_DEFAULT(method) : false; + ctx->algorithm = algorithm; + ctx->method = method; + ctx->compress = compress; + ctx->end_of_input = false; + ctx->end_of_stream = false; + ctx->is_stored = false; + + if ((ctx->ud = ctx->algorithm->allocate(ZIP_CM_ACTUAL(method), compression_flags, &ctx->error)) == NULL) { + zip_error_fini(&ctx->error); + free(ctx); + return NULL; + } + + return ctx; +} + + +static void +context_free(struct context *ctx) { + if (ctx == NULL) { + return; + } + + ctx->algorithm->deallocate(ctx->ud); + zip_error_fini(&ctx->error); + + free(ctx); +} + + +static zip_int64_t +compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t len) { + zip_compression_status_t ret; + bool end; + zip_int64_t n; + zip_uint64_t out_offset; + zip_uint64_t out_len; + + if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) { + return -1; + } + + if (len == 0 || ctx->end_of_stream) { + return 0; + } + + out_offset = 0; + + end = false; + while (!end && out_offset < len) { + out_len = len - out_offset; + ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len); + + if (ret != ZIP_COMPRESSION_ERROR) { + out_offset += out_len; + } + + switch (ret) { + case ZIP_COMPRESSION_END: + ctx->end_of_stream = true; + + if (!ctx->end_of_input) { + /* TODO: garbage after stream, or compression ended before all data read */ + } + + if (ctx->first_read < 0) { + /* we got end of processed stream before reading any input data */ + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + end = true; + break; + } + if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) { + ctx->is_stored = true; + ctx->size = (zip_uint64_t)ctx->first_read; + (void)memcpy_s(data, ctx->size, ctx->buffer, ctx->size); + return (zip_int64_t)ctx->size; + } + end = true; + break; + + case ZIP_COMPRESSION_OK: + break; + + case ZIP_COMPRESSION_NEED_DATA: + if (ctx->end_of_input) { + /* TODO: error: stream not ended, but no more input */ + end = true; + break; + } + + if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { + zip_error_set_from_source(&ctx->error, src); + end = true; + break; + } + else if (n == 0) { + ctx->end_of_input = true; + ctx->algorithm->end_of_input(ctx->ud); + if (ctx->first_read < 0) { + ctx->first_read = 0; + } + } + else { + if (ctx->first_read >= 0) { + /* we overwrote a previously filled ctx->buffer */ + ctx->can_store = false; + } + else { + ctx->first_read = n; + } + + ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n); + } + break; + + case ZIP_COMPRESSION_ERROR: + /* error set by algorithm */ + if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + } + end = true; + break; + } + } + + if (out_offset > 0) { + ctx->can_store = false; + ctx->size += out_offset; + return (zip_int64_t)out_offset; + } + + return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1; +} + + +static zip_int64_t +compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { + struct context *ctx; + + ctx = (struct context *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: { + zip_stat_t st; + zip_file_attributes_t attributes; + + ctx->size = 0; + ctx->end_of_input = false; + ctx->end_of_stream = false; + ctx->is_stored = false; + ctx->first_read = -1; + + if (zip_source_stat(src, &st) < 0 || zip_source_get_file_attributes(src, &attributes) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if (!ctx->algorithm->start(ctx->ud, &st, &attributes)) { + return -1; + } + + return 0; + } + + case ZIP_SOURCE_READ: + return compress_read(src, ctx, data, len); + + case ZIP_SOURCE_CLOSE: + if (!ctx->algorithm->end(ctx->ud)) { + return -1; + } + return 0; + + case ZIP_SOURCE_STAT: { + zip_stat_t *st; + + st = (zip_stat_t *)data; + + if (ctx->compress) { + if (ctx->end_of_stream) { + st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method); + st->comp_size = ctx->size; + st->valid |= ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD; + } + else { + st->valid &= ~(ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD); + } + } + else { + st->comp_method = ZIP_CM_STORE; + st->valid |= ZIP_STAT_COMP_METHOD; + st->valid &= ~ZIP_STAT_COMP_SIZE; + if (ctx->end_of_stream) { + st->size = ctx->size; + st->valid |= ZIP_STAT_SIZE; + } + } + } + return 0; + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + context_free(ctx); + return 0; + + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: { + zip_file_attributes_t *attributes = (zip_file_attributes_t *)data; + + if (len < sizeof(*attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS; + attributes->version_needed = ctx->algorithm->version_needed; + attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK; + attributes->general_purpose_bit_flags = (ctx->is_stored ? 0 : ctx->algorithm->general_purpose_bit_flags(ctx->ud)); + + return sizeof(*attributes); + } + + case ZIP_SOURCE_SUPPORTS: + return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_SUPPORTS_REOPEN, -1); + + default: + return zip_source_pass_to_lower_layer(src, data, len, cmd); + } +} diff --git a/3rdparty/libzip/lib/zip_source_crc.c b/3rdparty/libzip/lib/zip_source_crc.c new file mode 100644 index 0000000000..435a084b70 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_crc.c @@ -0,0 +1,203 @@ +/* + zip_source_crc.c -- pass-through source that calculates CRC32 and size + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include + +#include "zipint.h" + +struct crc_context { + int validate; /* whether to check CRC on EOF and return error on mismatch */ + int crc_complete; /* whether CRC was computed for complete file */ + zip_error_t error; + zip_uint64_t size; + zip_uint64_t position; /* current reading position */ + zip_uint64_t crc_position; /* how far we've computed the CRC */ + zip_uint32_t crc; +}; + +static zip_int64_t crc_read(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); + + +zip_source_t * +zip_source_crc_create(zip_source_t *src, int validate, zip_error_t *error) { + struct crc_context *ctx; + + if (src == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((ctx = (struct crc_context *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + zip_error_init(&ctx->error); + ctx->validate = validate; + ctx->crc_complete = 0; + ctx->crc_position = 0; + ctx->crc = (zip_uint32_t)crc32(0, NULL, 0); + ctx->size = 0; + + return zip_source_layered_create(src, crc_read, ctx, error); +} + + +static zip_int64_t +crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { + struct crc_context *ctx; + zip_int64_t n; + + ctx = (struct crc_context *)_ctx; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + ctx->position = 0; + return 0; + + case ZIP_SOURCE_READ: + if ((n = zip_source_read(src, data, len)) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if (n == 0) { + if (ctx->crc_position == ctx->position) { + ctx->crc_complete = 1; + ctx->size = ctx->position; + + if (ctx->validate) { + struct zip_stat st; + + if (zip_source_stat(src, &st) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) { + zip_error_set(&ctx->error, ZIP_ER_CRC, 0); + return -1; + } + if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) { + /* We don't have the index here, but the caller should know which file they are reading from. */ + zip_error_set(&ctx->error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_INVALID_FILE_LENGTH, MAX_DETAIL_INDEX)); + return -1; + } + } + } + } + else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) { + zip_uint64_t i, nn; + + for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) { + nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n - i); + + ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data + i, (uInt)nn); + ctx->crc_position += nn; + } + } + ctx->position += (zip_uint64_t)n; + return n; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: { + zip_stat_t *st; + + st = (zip_stat_t *)data; + + if (ctx->crc_complete) { + if ((st->valid & ZIP_STAT_SIZE) && st->size != ctx->size) { + zip_error_set(&ctx->error, ZIP_ER_DATA_LENGTH, 0); + return -1; + } + /* TODO: Set comp_size, comp_method, encryption_method? + After all, this only works for uncompressed data. */ + st->size = ctx->size; + st->crc = ctx->crc; + st->comp_size = ctx->size; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; + st->valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD; + } + 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_SUPPORTS: { + zip_int64_t mask = zip_source_supports(src); + + if (mask < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + 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_FILE_ATTRIBUTES, -1); + mask |= zip_source_make_command_bitmap(ZIP_SOURCE_FREE, -1); + return mask; + } + + case ZIP_SOURCE_SEEK: { + zip_int64_t new_position; + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); + + if (args == NULL) { + return -1; + } + if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + ctx->position = (zip_uint64_t)new_position; + + return 0; + } + + case ZIP_SOURCE_TELL: + return (zip_int64_t)ctx->position; + + default: + return zip_source_pass_to_lower_layer(src, data, len, cmd); + } +} diff --git a/3rdparty/libzip/lib/zip_source_error.c b/3rdparty/libzip/lib/zip_source_error.c new file mode 100644 index 0000000000..dc7fa20cb0 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_error.c @@ -0,0 +1,46 @@ +/* + zip_source_error.c -- get last error from zip_source + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +zip_error_t * +zip_source_error(zip_source_t *src) { + return &src->error; +} + +bool +_zip_source_had_error(zip_source_t *src) { + return zip_source_error(src)->zip_err != ZIP_ER_OK; +} diff --git a/3rdparty/libzip/lib/zip_source_file.h b/3rdparty/libzip/lib/zip_source_file.h new file mode 100644 index 0000000000..cca9fd2b52 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_file.h @@ -0,0 +1,90 @@ +/* + zip_source_file.h -- header for common file operations + Copyright (C) 2020-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +struct zip_source_file_stat { + zip_uint64_t size; /* must be valid for regular files */ + time_t mtime; /* must always be valid, is initialized to current time */ + bool exists; /* must always be valid */ + bool regular_file; /* must always be valid */ +}; + +typedef struct zip_source_file_context zip_source_file_context_t; +typedef struct zip_source_file_operations zip_source_file_operations_t; +typedef struct zip_source_file_stat zip_source_file_stat_t; + +struct zip_source_file_context { + zip_error_t error; /* last error information */ + zip_int64_t supports; + + /* reading */ + char *fname; /* name of file to read from */ + void *f; /* file to read from */ + zip_stat_t st; /* stat information passed in */ + zip_file_attributes_t attributes; /* additional file attributes */ + zip_error_t stat_error; /* error returned for stat */ + zip_uint64_t start; /* start offset of data to read */ + zip_uint64_t len; /* length of the file, 0 for up to EOF */ + zip_uint64_t offset; /* current offset relative to start (0 is beginning of part we read) */ + + /* writing */ + char *tmpname; + void *fout; + + zip_source_file_operations_t *ops; + void *ops_userdata; +}; + + +/* The following methods must be implemented to support each feature: + - close, read, seek, and stat must always be implemented. + - To support specifying the file by name, open, and strdup must be implemented. + - For write support, the file must be specified by name and close, commit_write, create_temp_output, remove, rollback_write, and tell must be implemented. + - create_temp_output_cloning is always optional. */ + +struct zip_source_file_operations { + void (*close)(zip_source_file_context_t *ctx); + zip_int64_t (*commit_write)(zip_source_file_context_t *ctx); + zip_int64_t (*create_temp_output)(zip_source_file_context_t *ctx); + zip_int64_t (*create_temp_output_cloning)(zip_source_file_context_t *ctx, zip_uint64_t len); + bool (*open)(zip_source_file_context_t *ctx); + zip_int64_t (*read)(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len); + zip_int64_t (*remove)(zip_source_file_context_t *ctx); + void (*rollback_write)(zip_source_file_context_t *ctx); + bool (*seek)(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence); + bool (*stat)(zip_source_file_context_t *ctx, zip_source_file_stat_t *st); + char *(*string_duplicate)(zip_source_file_context_t *ctx, const char *); + zip_int64_t (*tell)(zip_source_file_context_t *ctx, void *f); + zip_int64_t (*write)(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len); +}; + +zip_source_t *zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_source_file_operations_t *ops, void *ops_userdata, zip_error_t *error); diff --git a/3rdparty/libzip/lib/zip_source_file_common.c b/3rdparty/libzip/lib/zip_source_file_common.c new file mode 100644 index 0000000000..6c58320f1e --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_file_common.c @@ -0,0 +1,388 @@ +/* + zip_source_file_common.c -- create data source from file + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include + +#include "zipint.h" + +#include "zip_source_file.h" + +static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd); + +static void +zip_source_file_stat_init(zip_source_file_stat_t *st) { + st->size = 0; + st->mtime = time(NULL); + st->exists = false; + st->regular_file = false; +} + +zip_source_t * +zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_source_file_operations_t *ops, void *ops_userdata, zip_error_t *error) { + zip_source_file_context_t *ctx; + zip_source_t *zs; + zip_source_file_stat_t sb; + zip_uint64_t length; + + if (ops == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (ops->close == NULL || ops->read == NULL || ops->seek == NULL || ops->stat == NULL) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + + if (ops->write != NULL && (ops->commit_write == NULL || ops->create_temp_output == NULL || ops->remove == NULL || ops->rollback_write == NULL || ops->tell == NULL)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + + if (fname != NULL) { + if (ops->open == NULL || ops->string_duplicate == NULL) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + } + else if (file == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (len < 0) { + if (len == -1) { + len = ZIP_LENGTH_TO_END; + } + // TODO: return ZIP_ER_INVAL if len != ZIP_LENGTH_UNCHECKED? + length = 0; + } + else { + length = (zip_uint64_t)len; + } + + if (start > ZIP_INT64_MAX || start + length < start) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((ctx = (zip_source_file_context_t *)malloc(sizeof(zip_source_file_context_t))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->ops = ops; + ctx->ops_userdata = ops_userdata; + ctx->fname = NULL; + if (fname) { + if ((ctx->fname = ops->string_duplicate(ctx, fname)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; + } + } + ctx->f = file; + ctx->start = start; + ctx->len = length; + if (st) { + (void)memcpy_s(&ctx->st, sizeof(ctx->st), st, sizeof(*st)); + ctx->st.name = NULL; + ctx->st.valid &= ~ZIP_STAT_NAME; + } + else { + zip_stat_init(&ctx->st); + } + + if (ctx->len > 0) { + ctx->st.size = ctx->len; + ctx->st.valid |= ZIP_STAT_SIZE; + } + + zip_error_init(&ctx->stat_error); + + ctx->tmpname = NULL; + ctx->fout = NULL; + + zip_error_init(&ctx->error); + zip_file_attributes_init(&ctx->attributes); + + ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, ZIP_SOURCE_SUPPORTS_REOPEN, -1); + + zip_source_file_stat_init(&sb); + if (!ops->stat(ctx, &sb)) { + _zip_error_copy(error, &ctx->error); + free(ctx->fname); + free(ctx); + return NULL; + } + + if (!sb.exists) { + if (ctx->fname && ctx->start == 0 && ctx->len == 0 && ops->write != NULL) { + ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + /* zip_open_from_source checks for this to detect non-existing files */ + zip_error_set(&ctx->stat_error, ZIP_ER_READ, ENOENT); + } + else { + zip_error_set(&ctx->stat_error, ZIP_ER_READ, ENOENT); + free(ctx->fname); + free(ctx); + return NULL; + } + } + else { + if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) { + ctx->st.mtime = sb.mtime; + ctx->st.valid |= ZIP_STAT_MTIME; + } + if (sb.regular_file) { + ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE; + + if (ctx->start + ctx->len > sb.size) { + zip_error_set(error, ZIP_ER_INVAL, 0); + free(ctx->fname); + free(ctx); + return NULL; + } + + if (ctx->len == 0) { + if (len != ZIP_LENGTH_UNCHECKED) { + ctx->len = sb.size - ctx->start; + ctx->st.size = ctx->len; + ctx->st.valid |= ZIP_STAT_SIZE; + } + + /* when using a partial file, don't allow writing */ + if (ctx->fname && start == 0 && ops->write != NULL) { + ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + } + } + } + + ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES); + } + + ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY); + if (ops->create_temp_output_cloning != NULL) { + if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) { + ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING); + } + } + + if ((zs = zip_source_function_create(read_file, ctx, error)) == NULL) { + free(ctx->fname); + free(ctx); + return NULL; + } + + return zs; +} + + +static zip_int64_t +read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { + zip_source_file_context_t *ctx; + char *buf; + + ctx = (zip_source_file_context_t *)state; + buf = (char *)data; + + switch (cmd) { + case ZIP_SOURCE_ACCEPT_EMPTY: + return 0; + + case ZIP_SOURCE_BEGIN_WRITE: + /* write support should not be set if fname is NULL */ + if (ctx->fname == NULL) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; + } + return ctx->ops->create_temp_output(ctx); + + case ZIP_SOURCE_BEGIN_WRITE_CLONING: + /* write support should not be set if fname is NULL */ + if (ctx->fname == NULL) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; + } + return ctx->ops->create_temp_output_cloning(ctx, len); + + case ZIP_SOURCE_CLOSE: + if (ctx->fname) { + ctx->ops->close(ctx); + ctx->f = NULL; + } + return 0; + + case ZIP_SOURCE_COMMIT_WRITE: { + zip_int64_t ret = ctx->ops->commit_write(ctx); + ctx->fout = NULL; + if (ret == 0) { + free(ctx->tmpname); + ctx->tmpname = NULL; + } + return ret; + } + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + free(ctx->fname); + free(ctx->tmpname); + if (ctx->f) { + ctx->ops->close(ctx); + } + free(ctx); + return 0; + + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: + if (len < sizeof(ctx->attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + (void)memcpy_s(data, sizeof(ctx->attributes), &ctx->attributes, sizeof(ctx->attributes)); + return sizeof(ctx->attributes); + + case ZIP_SOURCE_OPEN: + if (ctx->fname) { + if (ctx->ops->open(ctx) == false) { + return -1; + } + } + + if (ctx->start > 0) { /* TODO: rewind on re-open */ + if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)ctx->start, SEEK_SET) == false) { + /* TODO: skip by reading */ + return -1; + } + } + ctx->offset = 0; + return 0; + + case ZIP_SOURCE_READ: { + zip_int64_t i; + zip_uint64_t n; + + if (ctx->len > 0) { + n = ZIP_MIN(ctx->len - ctx->offset, len); + } + else { + n = len; + } + + if ((i = ctx->ops->read(ctx, buf, n)) < 0) { + zip_error_set(&ctx->error, ZIP_ER_READ, errno); + return -1; + } + ctx->offset += (zip_uint64_t)i; + + return i; + } + + case ZIP_SOURCE_REMOVE: + return ctx->ops->remove(ctx); + + case ZIP_SOURCE_ROLLBACK_WRITE: + ctx->ops->rollback_write(ctx); + ctx->fout = NULL; + free(ctx->tmpname); + ctx->tmpname = NULL; + return 0; + + case ZIP_SOURCE_SEEK: { + zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error); + + if (new_offset < 0) { + return -1; + } + + /* The actual offset inside the file must be representable as zip_int64_t. */ + if (new_offset > ZIP_INT64_MAX - (zip_int64_t)ctx->start) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW); + return -1; + } + + ctx->offset = (zip_uint64_t)new_offset; + + if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)(ctx->offset + ctx->start), SEEK_SET) == false) { + 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 (ctx->ops->seek(ctx, ctx->fout, args->offset, args->whence) == false) { + return -1; + } + return 0; + } + + case ZIP_SOURCE_STAT: { + if (len < sizeof(ctx->st)) + return -1; + + 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; + } + + (void)memcpy_s(data, sizeof(ctx->st), &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->offset; + + case ZIP_SOURCE_TELL_WRITE: + return ctx->ops->tell(ctx, ctx->fout); + + case ZIP_SOURCE_WRITE: + return ctx->ops->write(ctx, data, len); + + default: + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } +} diff --git a/3rdparty/libzip/lib/zip_source_file_stdio.c b/3rdparty/libzip/lib/zip_source_file_stdio.c new file mode 100644 index 0000000000..6dcc56399f --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_file_stdio.c @@ -0,0 +1,178 @@ +/* + zip_source_file_stdio.c -- read-only stdio file source implementation + Copyright (C) 2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include "zip_source_file.h" +#include "zip_source_file_stdio.h" + +#include +#include +#include +#include + +#ifdef _WIN32 +#ifndef S_IWUSR +#define S_IWUSR _S_IWRITE +#endif +#endif + +/* clang-format off */ +static zip_source_file_operations_t ops_stdio_read = { + _zip_stdio_op_close, + NULL, + NULL, + NULL, + NULL, + _zip_stdio_op_read, + NULL, + NULL, + _zip_stdio_op_seek, + _zip_stdio_op_stat, + NULL, + _zip_stdio_op_tell, + NULL +}; +/* clang-format on */ + + +ZIP_EXTERN zip_source_t * +zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) { + if (za == NULL) { + return NULL; + } + + return zip_source_filep_create(file, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { + if (file == NULL || length < ZIP_LENGTH_UNCHECKED) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + return zip_source_file_common_new(NULL, file, start, length, NULL, &ops_stdio_read, NULL, error); +} + + +void +_zip_stdio_op_close(zip_source_file_context_t *ctx) { + fclose((FILE *)ctx->f); +} + + +zip_int64_t +_zip_stdio_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len) { + size_t i; + if (len > SIZE_MAX) { + len = SIZE_MAX; + } + + if ((i = fread(buf, 1, (size_t)len, ctx->f)) == 0) { + if (ferror((FILE *)ctx->f)) { + zip_error_set(&ctx->error, ZIP_ER_READ, errno); + return -1; + } + } + + return (zip_int64_t)i; +} + + +bool +_zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence) { +#if ZIP_FSEEK_MAX > ZIP_INT64_MAX + if (offset > ZIP_FSEEK_MAX || offset < ZIP_FSEEK_MIN) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW); + return false; + } +#endif + + if (fseeko((FILE *)f, (off_t)offset, whence) < 0) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + return false; + } + return true; +} + + +bool +_zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) { + struct stat sb; + + int ret; + + if (ctx->fname) { + ret = stat(ctx->fname, &sb); + } + else { + ret = fstat(fileno((FILE *)ctx->f), &sb); + } + + if (ret < 0) { + if (errno == ENOENT) { + st->exists = false; + return true; + } + zip_error_set(&ctx->error, ZIP_ER_READ, errno); + return false; + } + + st->size = (zip_uint64_t)sb.st_size; + st->mtime = sb.st_mtime; + + st->regular_file = S_ISREG(sb.st_mode); + st->exists = true; + + /* We're using UNIX file API, even on Windows; thus, we supply external file attributes with Unix values. */ + /* TODO: This could be improved on Windows by providing Windows-specific file attributes */ + ctx->attributes.valid = ZIP_FILE_ATTRIBUTES_HOST_SYSTEM | ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES; + ctx->attributes.host_system = ZIP_OPSYS_UNIX; + ctx->attributes.external_file_attributes = (((zip_uint32_t)sb.st_mode) << 16) | ((sb.st_mode & S_IWUSR) ? 0 : 1); + + return true; +} + + +zip_int64_t +_zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f) { + off_t offset = ftello((FILE *)f); + + if (offset < 0) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + } + + return offset; +} diff --git a/3rdparty/libzip/lib/zip_source_file_stdio.h b/3rdparty/libzip/lib/zip_source_file_stdio.h new file mode 100644 index 0000000000..802e6071ff --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_file_stdio.h @@ -0,0 +1,45 @@ +#ifndef _HAD_ZIP_SOURCE_FILE_STDIO_H +#define _HAD_ZIP_SOURCE_FILE_STDIO_H + +/* + zip_source_file_stdio.h -- common header for stdio file implementation + Copyright (C) 2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +void _zip_stdio_op_close(zip_source_file_context_t *ctx); +zip_int64_t _zip_stdio_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len); +bool _zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence); +bool _zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st); +zip_int64_t _zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f); + +#endif /* _HAD_ZIP_SOURCE_FILE_STDIO_H */ diff --git a/3rdparty/libzip/lib/zip_source_file_stdio_named.c b/3rdparty/libzip/lib/zip_source_file_stdio_named.c new file mode 100644 index 0000000000..1495d7dde7 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_file_stdio_named.c @@ -0,0 +1,392 @@ +/* + zip_source_file_stdio_named.c -- source for stdio file opened by name + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include "zip_source_file.h" +#include "zip_source_file_stdio.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_CLONEFILE +#include +#include +#define CAN_CLONE +#endif +#ifdef HAVE_FICLONERANGE +#include +#include +#define CAN_CLONE +#endif + +static int create_temp_file(zip_source_file_context_t *ctx, bool create_file); + +static zip_int64_t _zip_stdio_op_commit_write(zip_source_file_context_t *ctx); +static zip_int64_t _zip_stdio_op_create_temp_output(zip_source_file_context_t *ctx); +#ifdef CAN_CLONE +static zip_int64_t _zip_stdio_op_create_temp_output_cloning(zip_source_file_context_t *ctx, zip_uint64_t offset); +#endif +static bool _zip_stdio_op_open(zip_source_file_context_t *ctx); +static zip_int64_t _zip_stdio_op_remove(zip_source_file_context_t *ctx); +static void _zip_stdio_op_rollback_write(zip_source_file_context_t *ctx); +static char *_zip_stdio_op_strdup(zip_source_file_context_t *ctx, const char *string); +static zip_int64_t _zip_stdio_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len); +static FILE *_zip_fopen_close_on_exec(const char *name, bool writeable); + +/* clang-format off */ +static zip_source_file_operations_t ops_stdio_named = { + _zip_stdio_op_close, + _zip_stdio_op_commit_write, + _zip_stdio_op_create_temp_output, +#ifdef CAN_CLONE + _zip_stdio_op_create_temp_output_cloning, +#else + NULL, +#endif + _zip_stdio_op_open, + _zip_stdio_op_read, + _zip_stdio_op_remove, + _zip_stdio_op_rollback_write, + _zip_stdio_op_seek, + _zip_stdio_op_stat, + _zip_stdio_op_strdup, + _zip_stdio_op_tell, + _zip_stdio_op_write +}; +/* clang-format on */ + +ZIP_EXTERN zip_source_t * +zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) { + if (za == NULL) + return NULL; + + return zip_source_file_create(fname, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { + if (fname == NULL || length < ZIP_LENGTH_UNCHECKED) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + return zip_source_file_common_new(fname, NULL, start, length, NULL, &ops_stdio_named, NULL, error); +} + + +static zip_int64_t +_zip_stdio_op_commit_write(zip_source_file_context_t *ctx) { + if (fclose(ctx->fout) < 0) { + zip_error_set(&ctx->error, ZIP_ER_WRITE, errno); + return -1; + } + if (rename(ctx->tmpname, ctx->fname) < 0) { + zip_error_set(&ctx->error, ZIP_ER_RENAME, errno); + return -1; + } + + return 0; +} + + +static zip_int64_t +_zip_stdio_op_create_temp_output(zip_source_file_context_t *ctx) { + int fd = create_temp_file(ctx, true); + + if (fd < 0) { + return -1; + } + + if ((ctx->fout = fdopen(fd, "r+b")) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + close(fd); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + + return 0; +} + +#ifdef CAN_CLONE +static zip_int64_t +_zip_stdio_op_create_temp_output_cloning(zip_source_file_context_t *ctx, zip_uint64_t offset) { + FILE *tfp; + + if (offset > ZIP_OFF_MAX) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, E2BIG); + return -1; + } + +#ifdef HAVE_CLONEFILE + /* clonefile insists on creating the file, so just create a name */ + if (create_temp_file(ctx, false) < 0) { + return -1; + } + + if (clonefile(ctx->fname, ctx->tmpname, 0) < 0) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + if ((tfp = _zip_fopen_close_on_exec(ctx->tmpname, true)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } +#else + { + int fd; + struct file_clone_range range; + struct stat st; + + if (fstat(fileno(ctx->f), &st) < 0) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + return -1; + } + + if ((fd = create_temp_file(ctx, true)) < 0) { + return -1; + } + + range.src_fd = fileno(ctx->f); + range.src_offset = 0; + range.src_length = ((offset + st.st_blksize - 1) / st.st_blksize) * st.st_blksize; + if (range.src_length > st.st_size) { + range.src_length = 0; + } + range.dest_offset = 0; + if (ioctl(fd, FICLONERANGE, &range) < 0) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + (void)close(fd); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + + if ((tfp = fdopen(fd, "r+b")) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + (void)close(fd); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + } +#endif + + if (ftruncate(fileno(tfp), (off_t)offset) < 0) { + (void)fclose(tfp); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + if (fseeko(tfp, (off_t)offset, SEEK_SET) < 0) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + (void)fclose(tfp); + (void)remove(ctx->tmpname); + free(ctx->tmpname); + ctx->tmpname = NULL; + return -1; + } + + ctx->fout = tfp; + + return 0; +} +#endif + +static bool +_zip_stdio_op_open(zip_source_file_context_t *ctx) { + if ((ctx->f = _zip_fopen_close_on_exec(ctx->fname, false)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_OPEN, errno); + return false; + } + return true; +} + + +static zip_int64_t +_zip_stdio_op_remove(zip_source_file_context_t *ctx) { + if (remove(ctx->fname) < 0) { + zip_error_set(&ctx->error, ZIP_ER_REMOVE, errno); + return -1; + } + return 0; +} + + +static void +_zip_stdio_op_rollback_write(zip_source_file_context_t *ctx) { + if (ctx->fout) { + fclose(ctx->fout); + } + (void)remove(ctx->tmpname); +} + +static char * +_zip_stdio_op_strdup(zip_source_file_context_t *ctx, const char *string) { + return strdup(string); +} + + +static zip_int64_t +_zip_stdio_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len) { + size_t ret; + + clearerr((FILE *)ctx->fout); + ret = fwrite(data, 1, len, (FILE *)ctx->fout); + if (ret != len || ferror((FILE *)ctx->fout)) { + zip_error_set(&ctx->error, ZIP_ER_WRITE, errno); + return -1; + } + + return (zip_int64_t)ret; +} + + +static int create_temp_file(zip_source_file_context_t *ctx, bool create_file) { + char *temp; + int mode; + struct stat st; + int fd = 0; + char *start, *end; + + if (stat(ctx->fname, &st) == 0) { + mode = st.st_mode; + } + else { + mode = -1; + } + + size_t temp_size = strlen(ctx->fname) + 13; + if ((temp = (char *)malloc(temp_size)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + snprintf_s(temp, temp_size, "%s.XXXXXX.part", ctx->fname); + end = temp + strlen(temp) - 5; + start = end - 6; + + for (;;) { + zip_uint32_t value = zip_random_uint32(); + char *xs = start; + + while (xs < end) { + char digit = value % 36; + if (digit < 10) { + *(xs++) = digit + '0'; + } + else { + *(xs++) = digit - 10 + 'a'; + } + value /= 36; + } + + if (create_file) { + if ((fd = open(temp, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, mode == -1 ? 0666 : (mode_t)mode)) >= 0) { + if (mode != -1) { + /* open() honors umask(), which we don't want in this case */ +#ifdef HAVE_FCHMOD + (void)fchmod(fd, (mode_t)mode); +#else + (void)chmod(temp, (mode_t)mode); +#endif + } + break; + } + if (errno != EEXIST) { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + free(temp); + return -1; + } + } + else { + if (stat(temp, &st) < 0) { + if (errno == ENOENT) { + break; + } + else { + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); + free(temp); + return -1; + } + } + } + } + + ctx->tmpname = temp; + + return fd; /* initialized to 0 if !create_file */ +} + + +/* + * fopen replacement that sets the close-on-exec flag + * some implementations support an fopen 'e' flag for that, + * but e.g. macOS doesn't. + */ +static FILE *_zip_fopen_close_on_exec(const char *name, bool writeable) { + int fd; + int flags; + FILE *fp; + + flags = O_CLOEXEC; + if (writeable) { + flags |= O_RDWR; + } + else { + flags |= O_RDONLY; + } + + /* mode argument needed on Windows */ + if ((fd = open(name, flags, 0666)) < 0) { + return NULL; + } + if ((fp = fdopen(fd, writeable ? "r+b" : "rb")) == NULL) { + return NULL; + } + return fp; +} diff --git a/3rdparty/libzip/lib/zip_source_file_win32.c b/3rdparty/libzip/lib/zip_source_file_win32.c new file mode 100644 index 0000000000..624860b1cb --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_file_win32.c @@ -0,0 +1,234 @@ +/* + zip_source_file_win32.c -- read-only Windows file source implementation + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zip_source_file_win32.h" + +static bool _zip_win32_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st); + +static bool _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HANDLE h); + +/* clang-format off */ + +static zip_source_file_operations_t ops_win32_read = { + _zip_win32_op_close, + NULL, + NULL, + NULL, + NULL, + _zip_win32_op_read, + NULL, + NULL, + _zip_win32_op_seek, + _zip_win32_op_stat, + NULL, + _zip_win32_op_tell, + NULL +}; + +/* clang-format on */ + +ZIP_EXTERN zip_source_t * +zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len) { + if (za == NULL) { + return NULL; + } + + return zip_source_win32handle_create(h, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_win32handle_create(HANDLE h, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { + if (h == INVALID_HANDLE_VALUE || length < ZIP_LENGTH_UNCHECKED) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + return zip_source_file_common_new(NULL, h, start, length, NULL, &ops_win32_read, NULL, error); +} + + +void +_zip_win32_op_close(zip_source_file_context_t *ctx) { + CloseHandle((HANDLE)ctx->f); +} + + +zip_int64_t +_zip_win32_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len) { + DWORD i; + + /* TODO: cap len to "DWORD_MAX" */ + if (!ReadFile((HANDLE)ctx->f, buf, (DWORD)len, &i, NULL)) { + zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + return (zip_int64_t)i; +} + + +bool +_zip_win32_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence) { + LARGE_INTEGER li; + DWORD method; + + switch (whence) { + case SEEK_SET: + method = FILE_BEGIN; + break; + case SEEK_END: + method = FILE_END; + break; + case SEEK_CUR: + method = FILE_CURRENT; + break; + default: + zip_error_set(&ctx->error, ZIP_ER_SEEK, EINVAL); + return false; + } + + li.QuadPart = (LONGLONG)offset; + if (!SetFilePointerEx((HANDLE)f, li, NULL, method)) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError())); + return false; + } + + return true; +} + + +static bool +_zip_win32_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) { + return _zip_stat_win32(ctx, st, (HANDLE)ctx->f); +} + + +zip_int64_t +_zip_win32_op_tell(zip_source_file_context_t *ctx, void *f) { + LARGE_INTEGER zero; + LARGE_INTEGER new_offset; + + zero.QuadPart = 0; + if (!SetFilePointerEx((HANDLE)f, zero, &new_offset, FILE_CURRENT)) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + return (zip_int64_t)new_offset.QuadPart; +} + + +int +_zip_win32_error_to_errno(DWORD win32err) { + /* Note: This list isn't exhaustive, but should cover common cases. */ + switch (win32err) { + case ERROR_INVALID_PARAMETER: + return EINVAL; + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + return ENOENT; + case ERROR_INVALID_HANDLE: + return EBADF; + case ERROR_ACCESS_DENIED: + return EACCES; + case ERROR_FILE_EXISTS: + return EEXIST; + case ERROR_TOO_MANY_OPEN_FILES: + return EMFILE; + case ERROR_DISK_FULL: + return ENOSPC; + default: + return 10000 + win32err; + } +} + + +static bool +_zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HANDLE h) { + FILETIME mtimeft; + time_t mtime; + LARGE_INTEGER size; + + if (!GetFileTime(h, NULL, NULL, &mtimeft)) { + zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); + return false; + } + if (!_zip_filetime_to_time_t(mtimeft, &mtime)) { + zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE); + return false; + } + + st->exists = true; + st->mtime = mtime; + + if (GetFileType(h) == FILE_TYPE_DISK) { + st->regular_file = 1; + + if (!GetFileSizeEx(h, &size)) { + zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); + return false; + } + + st->size = (zip_uint64_t)size.QuadPart; + } + + /* TODO: fill in ctx->attributes */ + + return true; +} + + +bool +_zip_filetime_to_time_t(FILETIME ft, time_t *t) { + /* + Inspired by http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux + */ + const zip_int64_t WINDOWS_TICK = 10000000LL; + const zip_int64_t SEC_TO_UNIX_EPOCH = 11644473600LL; + ULARGE_INTEGER li; + zip_int64_t secs; + time_t temp; + + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + secs = (li.QuadPart / WINDOWS_TICK - SEC_TO_UNIX_EPOCH); + + temp = (time_t)secs; + if (secs != (zip_int64_t)temp) { + return false; + } + + *t = temp; + return true; +} diff --git a/3rdparty/libzip/lib/zip_source_file_win32.h b/3rdparty/libzip/lib/zip_source_file_win32.h new file mode 100644 index 0000000000..d86069ecaa --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_file_win32.h @@ -0,0 +1,84 @@ +#ifndef _HAD_ZIP_SOURCE_FILE_WIN32_H +#define _HAD_ZIP_SOURCE_FILE_WIN32_H + +/* + zip_source_file_win32.h -- common header for Windows file implementation + Copyright (C) 2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* 0x0501 => Windows XP; needs to be at least this value because of GetFileSizeEx */ +#if !defined(MS_UWP) && !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0501 +#endif + +#include + +#include + +#include + +#include "zipint.h" + +#include "zip_source_file.h" + +struct zip_win32_file_operations { + char *(*allocate_tempname)(const char *name, size_t extra_chars, size_t *lengthp); + HANDLE(__stdcall *create_file)(const void *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file); + BOOL(__stdcall *delete_file)(const void *name); + DWORD(__stdcall *get_file_attributes)(const void *name); + BOOL(__stdcall *get_file_attributes_ex)(const void *name, GET_FILEEX_INFO_LEVELS info_level, void *information); + void (*make_tempname)(char *buf, size_t len, const char *name, zip_uint32_t i); + BOOL(__stdcall *move_file)(const void *from, const void *to, DWORD flags); + BOOL(__stdcall *set_file_attributes)(const void *name, DWORD attributes); + char *(*string_duplicate)(const char *string); +}; + +typedef struct zip_win32_file_operations zip_win32_file_operations_t; + +extern zip_source_file_operations_t _zip_source_file_win32_named_ops; + +void _zip_win32_op_close(zip_source_file_context_t *ctx); +zip_int64_t _zip_win32_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len); +bool _zip_win32_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence); +zip_int64_t _zip_win32_op_tell(zip_source_file_context_t *ctx, void *f); + +bool _zip_filetime_to_time_t(FILETIME ft, time_t *t); +int _zip_win32_error_to_errno(DWORD win32err); + +#ifdef __clang__ +#define DONT_WARN_INCOMPATIBLE_FN_PTR_BEGIN _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wincompatible-function-pointer-types\"") +#define DONT_WARN_INCOMPATIBLE_FN_PTR_END _Pragma("GCC diagnostic pop") +#else +#define DONT_WARN_INCOMPATIBLE_FN_PTR_BEGIN +#define DONT_WARN_INCOMPATIBLE_FN_PTR_END +#endif + +#endif /* _HAD_ZIP_SOURCE_FILE_WIN32_H */ diff --git a/3rdparty/libzip/lib/zip_source_file_win32_ansi.c b/3rdparty/libzip/lib/zip_source_file_win32_ansi.c new file mode 100644 index 0000000000..58034cc2a7 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_file_win32_ansi.c @@ -0,0 +1,87 @@ +/* + zip_source_file_win32_ansi.c -- source for Windows file opened by ANSI name + Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zip_source_file_win32.h" + +static char *ansi_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp); +static void ansi_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i); + +/* clang-format off */ +DONT_WARN_INCOMPATIBLE_FN_PTR_BEGIN + +zip_win32_file_operations_t ops_ansi = { + ansi_allocate_tempname, + CreateFileA, + DeleteFileA, + GetFileAttributesA, + GetFileAttributesExA, + ansi_make_tempname, + MoveFileExA, + SetFileAttributesA, + strdup +}; + +DONT_WARN_INCOMPATIBLE_FN_PTR_END +/* clang-format on */ + +ZIP_EXTERN zip_source_t * +zip_source_win32a(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) { + if (za == NULL) + return NULL; + + return zip_source_win32a_create(fname, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_win32a_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { + if (fname == NULL || length < ZIP_LENGTH_UNCHECKED) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + return zip_source_file_common_new(fname, NULL, start, length, NULL, &_zip_source_file_win32_named_ops, &ops_ansi, error); +} + + +static char * +ansi_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp) { + *lengthp = strlen(name) + extra_chars; + return (char *)malloc(*lengthp); +} + + +static void +ansi_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i) { + snprintf_s(buf, len, "%s.%08x", name, i); +} diff --git a/3rdparty/libzip/lib/zip_source_file_win32_named.c b/3rdparty/libzip/lib/zip_source_file_win32_named.c new file mode 100644 index 0000000000..855e605a93 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_file_win32_named.c @@ -0,0 +1,274 @@ +/* + zip_source_file_win32_named.c -- source for Windows file opened by name + Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zip_source_file_win32.h" + +static zip_int64_t _zip_win32_named_op_commit_write(zip_source_file_context_t *ctx); +static zip_int64_t _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx); +static bool _zip_win32_named_op_open(zip_source_file_context_t *ctx); +static zip_int64_t _zip_win32_named_op_remove(zip_source_file_context_t *ctx); +static void _zip_win32_named_op_rollback_write(zip_source_file_context_t *ctx); +static bool _zip_win32_named_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st); +static char *_zip_win32_named_op_string_duplicate(zip_source_file_context_t *ctx, const char *string); +static zip_int64_t _zip_win32_named_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len); + +static HANDLE win32_named_open(zip_source_file_context_t *ctx, const char *name, bool temporary, PSECURITY_ATTRIBUTES security_attributes); + +/* clang-format off */ +zip_source_file_operations_t _zip_source_file_win32_named_ops = { + _zip_win32_op_close, + _zip_win32_named_op_commit_write, + _zip_win32_named_op_create_temp_output, + NULL, + _zip_win32_named_op_open, + _zip_win32_op_read, + _zip_win32_named_op_remove, + _zip_win32_named_op_rollback_write, + _zip_win32_op_seek, + _zip_win32_named_op_stat, + _zip_win32_named_op_string_duplicate, + _zip_win32_op_tell, + _zip_win32_named_op_write +}; +/* clang-format on */ + +static zip_int64_t +_zip_win32_named_op_commit_write(zip_source_file_context_t *ctx) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + DWORD attributes; + + if (!CloseHandle((HANDLE)ctx->fout)) { + zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + attributes = file_ops->get_file_attributes(ctx->tmpname); + if (attributes == INVALID_FILE_ATTRIBUTES) { + zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + if (attributes & FILE_ATTRIBUTE_TEMPORARY) { + if (!file_ops->set_file_attributes(ctx->tmpname, attributes & ~FILE_ATTRIBUTE_TEMPORARY)) { + zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + } + + if (!file_ops->move_file(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING)) { + zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + return 0; +} + +static zip_int64_t +_zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + zip_uint32_t value, i; + HANDLE th = INVALID_HANDLE_VALUE; + PSECURITY_DESCRIPTOR psd = NULL; + PSECURITY_ATTRIBUTES psa = NULL; + SECURITY_ATTRIBUTES sa; + SECURITY_INFORMATION si; + DWORD success; + PACL dacl = NULL; + char *tempname = NULL; + size_t tempname_size = 0; + + if ((HANDLE)ctx->f != INVALID_HANDLE_VALUE && GetFileType((HANDLE)ctx->f) == FILE_TYPE_DISK) { + si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION; + success = GetSecurityInfo((HANDLE)ctx->f, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd); + if (success == ERROR_SUCCESS) { + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = FALSE; + sa.lpSecurityDescriptor = psd; + psa = &sa; + } + } + +#ifndef MS_UWP + value = GetTickCount(); +#else + value = (zip_uint32_t)(GetTickCount64() & 0xffffffff); +#endif + + if ((tempname = file_ops->allocate_tempname(ctx->fname, 10, &tempname_size)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + + for (i = 0; i < 1024 && th == INVALID_HANDLE_VALUE; i++) { + file_ops->make_tempname(tempname, tempname_size, ctx->fname, value + i); + + th = win32_named_open(ctx, tempname, true, psa); + if (th == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_EXISTS) + break; + } + + if (th == INVALID_HANDLE_VALUE) { + free(tempname); + LocalFree(psd); + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + LocalFree(psd); + ctx->fout = th; + ctx->tmpname = tempname; + + return 0; +} + + +static bool +_zip_win32_named_op_open(zip_source_file_context_t *ctx) { + HANDLE h = win32_named_open(ctx, ctx->fname, false, NULL); + + if (h == INVALID_HANDLE_VALUE) { + return false; + } + + ctx->f = h; + return true; +} + + +static zip_int64_t +_zip_win32_named_op_remove(zip_source_file_context_t *ctx) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + if (!file_ops->delete_file(ctx->fname)) { + zip_error_set(&ctx->error, ZIP_ER_REMOVE, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + return 0; +} + + +static void +_zip_win32_named_op_rollback_write(zip_source_file_context_t *ctx) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + if (ctx->fout) { + CloseHandle((HANDLE)ctx->fout); + } + file_ops->delete_file(ctx->tmpname); +} + + +static bool +_zip_win32_named_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + WIN32_FILE_ATTRIBUTE_DATA file_attributes; + + if (!file_ops->get_file_attributes_ex(ctx->fname, GetFileExInfoStandard, &file_attributes)) { + DWORD error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND) { + st->exists = false; + return true; + } + zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(error)); + return false; + } + + st->exists = true; + st->regular_file = false; + + if (file_attributes.dwFileAttributes != INVALID_FILE_ATTRIBUTES) { + if ((file_attributes.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_REPARSE_POINT)) == 0) { + st->regular_file = true; + } + } + + if (!_zip_filetime_to_time_t(file_attributes.ftLastWriteTime, &st->mtime)) { + zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE); + return false; + } + st->size = ((zip_uint64_t)file_attributes.nFileSizeHigh << 32) | file_attributes.nFileSizeLow; + + /* TODO: fill in ctx->attributes */ + + return true; +} + + +static char * +_zip_win32_named_op_string_duplicate(zip_source_file_context_t *ctx, const char *string) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + return file_ops->string_duplicate(string); +} + + +static zip_int64_t +_zip_win32_named_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len) { + DWORD ret; + if (!WriteFile((HANDLE)ctx->fout, data, (DWORD)len, &ret, NULL) || ret != len) { + zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + return (zip_int64_t)ret; +} + + +static HANDLE +win32_named_open(zip_source_file_context_t *ctx, const char *name, bool temporary, PSECURITY_ATTRIBUTES security_attributes) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + DWORD access = GENERIC_READ; + DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE; + DWORD creation_disposition = OPEN_EXISTING; + DWORD file_attributes = FILE_ATTRIBUTE_NORMAL; + HANDLE h; + + if (temporary) { + access = GENERIC_READ | GENERIC_WRITE; + share_mode = FILE_SHARE_READ; + creation_disposition = CREATE_NEW; + file_attributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY; + } + + h = file_ops->create_file(name, access, share_mode, security_attributes, creation_disposition, file_attributes, NULL); + + if (h == INVALID_HANDLE_VALUE) { + zip_error_set(&ctx->error, ZIP_ER_OPEN, _zip_win32_error_to_errno(GetLastError())); + } + + return h; +} diff --git a/3rdparty/libzip/lib/zip_source_file_win32_utf16.c b/3rdparty/libzip/lib/zip_source_file_win32_utf16.c new file mode 100644 index 0000000000..8f07d0210d --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_file_win32_utf16.c @@ -0,0 +1,113 @@ +/* + zip_source_file_win32_utf16.c -- source for Windows file opened by UTF-16 name + Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zip_source_file_win32.h" + +static char *utf16_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp); +static HANDLE __stdcall utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file); +static void utf16_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i); +static char *utf16_strdup(const char *string); + +/* clang-format off */ +DONT_WARN_INCOMPATIBLE_FN_PTR_BEGIN + +zip_win32_file_operations_t ops_utf16 = { + utf16_allocate_tempname, + utf16_create_file, + DeleteFileW, + GetFileAttributesW, + GetFileAttributesExW, + utf16_make_tempname, + MoveFileExW, + SetFileAttributesW, + utf16_strdup +}; + +DONT_WARN_INCOMPATIBLE_FN_PTR_END +/* clang-format on */ + +ZIP_EXTERN zip_source_t * +zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64_t len) { + if (za == NULL) + return NULL; + + return zip_source_win32w_create(fname, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_win32w_create(const wchar_t *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { + if (fname == NULL || length < ZIP_LENGTH_UNCHECKED) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + + return zip_source_file_common_new((const char *)fname, NULL, start, length, NULL, &_zip_source_file_win32_named_ops, &ops_utf16, error); +} + + +static char * +utf16_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp) { + *lengthp = wcslen((const wchar_t *)name) + extra_chars; + return (char *)malloc(*lengthp * sizeof(wchar_t)); +} + + +static HANDLE __stdcall utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file) { +#ifdef MS_UWP + CREATEFILE2_EXTENDED_PARAMETERS extParams = {0}; + extParams.dwFileAttributes = file_attributes; + extParams.dwFileFlags = FILE_FLAG_RANDOM_ACCESS; + extParams.dwSecurityQosFlags = SECURITY_ANONYMOUS; + extParams.dwSize = sizeof(extParams); + extParams.hTemplateFile = template_file; + extParams.lpSecurityAttributes = security_attributes; + + return CreateFile2((const wchar_t *)name, access, share_mode, creation_disposition, &extParams); +#else + return CreateFileW((const wchar_t *)name, access, share_mode, security_attributes, creation_disposition, file_attributes, template_file); +#endif +} + + +static void +utf16_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i) { + _snwprintf_s((wchar_t *)buf, len, len, L"%s.%08x", (const wchar_t *)name, i); +} + + +static char * +utf16_strdup(const char *string) { + return (char *)_wcsdup((const wchar_t *)string); +} diff --git a/3rdparty/libzip/lib/zip_source_file_win32_utf8.c b/3rdparty/libzip/lib/zip_source_file_win32_utf8.c new file mode 100644 index 0000000000..d154f97ae3 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_file_win32_utf8.c @@ -0,0 +1,73 @@ +/* + zip_source_file_win32_ansi.c -- source for Windows file opened by UTF-8 name + Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zip_source_file_win32.h" + +ZIP_EXTERN zip_source_t * +zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) { + if (za == NULL) { + return NULL; + } + + return zip_source_file_create(fname, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { + int size; + wchar_t *wfname; + zip_source_t *source; + + if (fname == NULL || length < ZIP_LENGTH_UNCHECKED) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + /* Convert fname from UTF-8 to Windows-friendly UTF-16. */ + size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, NULL, 0); + if (size == 0) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + if ((wfname = (wchar_t *)malloc(sizeof(wchar_t) * size)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, wfname, size); + + source = zip_source_win32w_create(wfname, start, length, error); + + free(wfname); + return source; +} diff --git a/3rdparty/libzip/lib/zip_source_free.c b/3rdparty/libzip/lib/zip_source_free.c new file mode 100644 index 0000000000..1a800405c2 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_free.c @@ -0,0 +1,71 @@ +/* + zip_source_free.c -- free zip data source + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN void +zip_source_free(zip_source_t *src) { + if (src == NULL) + return; + + if (src->refcount > 0) { + src->refcount--; + } + if (src->refcount > 0) { + return; + } + + if (ZIP_SOURCE_IS_OPEN_READING(src)) { + src->open_count = 1; /* force close */ + zip_source_close(src); + } + if (ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_source_rollback_write(src); + } + + if (src->source_archive && !src->source_closed) { + _zip_deregister_source(src->source_archive, src); + } + + (void)_zip_source_call(src, NULL, 0, ZIP_SOURCE_FREE); + + if (src->src) { + zip_source_free(src->src); + } + + free(src); +} diff --git a/3rdparty/libzip/lib/zip_source_function.c b/3rdparty/libzip/lib/zip_source_function.c new file mode 100644 index 0000000000..1fe6396e14 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_function.c @@ -0,0 +1,99 @@ +/* + zip_source_function.c -- create zip data source from callback function + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN zip_source_t * +zip_source_function(zip_t *za, zip_source_callback zcb, void *ud) { + if (za == NULL) { + return NULL; + } + + return zip_source_function_create(zcb, ud, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_function_create(zip_source_callback zcb, void *ud, zip_error_t *error) { + zip_source_t *zs; + + if ((zs = _zip_source_new(error)) == NULL) + return NULL; + + zs->cb.f = zcb; + zs->ud = ud; + + zs->supports = zcb(ud, NULL, 0, ZIP_SOURCE_SUPPORTS); + if (zs->supports < 0) { + zs->supports = ZIP_SOURCE_SUPPORTS_READABLE; + } + zs->supports |= zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, -1); + + return zs; +} + + +ZIP_EXTERN void +zip_source_keep(zip_source_t *src) { + src->refcount++; +} + + +zip_source_t * +_zip_source_new(zip_error_t *error) { + zip_source_t *src; + + if ((src = (zip_source_t *)malloc(sizeof(*src))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + src->src = NULL; + src->cb.f = NULL; + src->ud = NULL; + src->open_count = 0; + src->write_state = ZIP_SOURCE_WRITE_CLOSED; + src->source_closed = false; + src->source_archive = NULL; + src->refcount = 1; + zip_error_init(&src->error); + src->eof = false; + src->had_read_error = false; + src->bytes_read = 0; + + return src; +} diff --git a/3rdparty/libzip/lib/zip_source_get_file_attributes.c b/3rdparty/libzip/lib/zip_source_get_file_attributes.c new file mode 100644 index 0000000000..4771dc16b3 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_get_file_attributes.c @@ -0,0 +1,108 @@ +/* + zip_source_get_file_attributes.c -- get attributes for file from source + Copyright (C) 2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +ZIP_EXTERN void +zip_file_attributes_init(zip_file_attributes_t *attributes) { + attributes->valid = 0; + attributes->version = 1; +} + +int +zip_source_get_file_attributes(zip_source_t *src, zip_file_attributes_t *attributes) { + if (src->source_closed) { + return -1; + } + if (attributes == NULL) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + zip_file_attributes_init(attributes); + + if (src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES)) { + if (_zip_source_call(src, attributes, sizeof(*attributes), ZIP_SOURCE_GET_FILE_ATTRIBUTES) < 0) { + return -1; + } + } + + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_file_attributes_t lower_attributes; + + zip_file_attributes_init(&lower_attributes); + + if (zip_source_get_file_attributes(src->src, &lower_attributes) < 0) { + zip_error_set_from_source(&src->error, src->src); + return -1; + } + + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) == 0) { + attributes->host_system = lower_attributes.host_system; + attributes->valid |= ZIP_FILE_ATTRIBUTES_HOST_SYSTEM; + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_ASCII) && (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) == 0) { + attributes->ascii = lower_attributes.ascii; + attributes->valid |= ZIP_FILE_ATTRIBUTES_ASCII; + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED)) { + if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) { + attributes->version_needed = ZIP_MAX(lower_attributes.version_needed, attributes->version_needed); + } + else { + attributes->version_needed = lower_attributes.version_needed; + attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED; + } + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) == 0) { + attributes->external_file_attributes = lower_attributes.external_file_attributes; + attributes->valid |= ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES; + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS)) { + if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) { + /* only take from lower level what is not defined at current level */ + lower_attributes.general_purpose_bit_mask &= ~attributes->general_purpose_bit_mask; + + attributes->general_purpose_bit_flags |= lower_attributes.general_purpose_bit_flags & lower_attributes.general_purpose_bit_mask; + attributes->general_purpose_bit_mask |= lower_attributes.general_purpose_bit_mask; + } + else { + attributes->valid |= ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS; + attributes->general_purpose_bit_flags = lower_attributes.general_purpose_bit_flags; + attributes->general_purpose_bit_mask = lower_attributes.general_purpose_bit_mask; + } + } + } + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_source_is_deleted.c b/3rdparty/libzip/lib/zip_source_is_deleted.c new file mode 100644 index 0000000000..838aa90967 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_is_deleted.c @@ -0,0 +1,41 @@ +/* + zip_source_is_deleted.c -- was archive was removed? + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_is_deleted(zip_source_t *src) { + return src->write_state == ZIP_SOURCE_WRITE_REMOVED; +} diff --git a/3rdparty/libzip/lib/zip_source_layered.c b/3rdparty/libzip/lib/zip_source_layered.c new file mode 100644 index 0000000000..62b78e68e7 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_layered.c @@ -0,0 +1,75 @@ +/* + zip_source_layered.c -- create layered source + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +zip_source_t * +zip_source_layered(zip_t *za, zip_source_t *src, zip_source_layered_callback cb, void *ud) { + if (za == NULL) + return NULL; + + return zip_source_layered_create(src, cb, ud, &za->error); +} + + +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 *zs; + zip_int64_t lower_supports, supports; + + lower_supports = zip_source_supports(src); + supports = cb(src, ud, &lower_supports, sizeof(lower_supports), ZIP_SOURCE_SUPPORTS); + if (supports < 0) { + zip_error_set(error,ZIP_ER_INVAL, 0); /* Initialize in case cb doesn't return valid error. */ + cb(src, ud, error, sizeof(*error), ZIP_SOURCE_ERROR); + return NULL; + } + + if ((zs = _zip_source_new(error)) == NULL) { + return NULL; + } + + zs->src = src; + zs->cb.l = cb; + zs->ud = ud; + zs->supports = supports; + + /* Layered sources can't support writing, since we currently have no use case. If we want to revisit this, we have to define how the two sources interact. */ + zs->supports &= ~(ZIP_SOURCE_SUPPORTS_WRITABLE & ~ZIP_SOURCE_SUPPORTS_SEEKABLE); + + return zs; +} diff --git a/3rdparty/libzip/lib/zip_source_open.c b/3rdparty/libzip/lib/zip_source_open.c new file mode 100644 index 0000000000..b34fa2c6c0 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_open.c @@ -0,0 +1,76 @@ +/* + zip_source_open.c -- open zip_source (prepare for reading) + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +ZIP_EXTERN int +zip_source_open(zip_source_t *src) { + if (src->source_closed) { + return -1; + } + if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) { + zip_error_set(&src->error, ZIP_ER_DELETED, 0); + return -1; + } + + if (ZIP_SOURCE_IS_OPEN_READING(src)) { + if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) == 0) { + zip_error_set(&src->error, ZIP_ER_INUSE, 0); + return -1; + } + } + else { + if (ZIP_SOURCE_IS_LAYERED(src)) { + if (zip_source_open(src->src) < 0) { + zip_error_set_from_source(&src->error, src->src); + return -1; + } + } + + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_OPEN) < 0) { + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_source_close(src->src); + } + return -1; + } + } + + src->eof = false; + src->had_read_error = false; + _zip_error_clear(&src->error); + src->bytes_read = 0; + src->open_count++; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_source_pass_to_lower_layer.c b/3rdparty/libzip/lib/zip_source_pass_to_lower_layer.c new file mode 100644 index 0000000000..4a98222ecd --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_pass_to_lower_layer.c @@ -0,0 +1,78 @@ +/* + zip_source_pass_to_lower_layer.c -- pass command to lower layer + Copyright (C) 2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +zip_int64_t zip_source_pass_to_lower_layer(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command) { + switch (command) { + case ZIP_SOURCE_OPEN: + case ZIP_SOURCE_CLOSE: + case ZIP_SOURCE_FREE: + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: + case ZIP_SOURCE_SUPPORTS_REOPEN: + return 0; + + case ZIP_SOURCE_STAT: + return sizeof(zip_stat_t); + + case ZIP_SOURCE_ACCEPT_EMPTY: + case ZIP_SOURCE_ERROR: + case ZIP_SOURCE_READ: + case ZIP_SOURCE_SEEK: + case ZIP_SOURCE_TELL: + return _zip_source_call(src, data, length, command); + + + case ZIP_SOURCE_BEGIN_WRITE: + case ZIP_SOURCE_BEGIN_WRITE_CLONING: + case ZIP_SOURCE_COMMIT_WRITE: + case ZIP_SOURCE_REMOVE: + case ZIP_SOURCE_ROLLBACK_WRITE: + case ZIP_SOURCE_SEEK_WRITE: + case ZIP_SOURCE_TELL_WRITE: + case ZIP_SOURCE_WRITE: + zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + + case ZIP_SOURCE_SUPPORTS: + if (length < sizeof(zip_int64_t)) { + zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); + return -1; + } + return *(zip_int64_t *)data; + + default: + zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } +} \ No newline at end of file diff --git a/3rdparty/libzip/lib/zip_source_pkware_decode.c b/3rdparty/libzip/lib/zip_source_pkware_decode.c new file mode 100644 index 0000000000..b4c482b312 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_pkware_decode.c @@ -0,0 +1,219 @@ +/* + zip_source_pkware_decode.c -- Traditional PKWARE decryption routines + Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + +struct trad_pkware { + char *password; + zip_pkware_keys_t keys; + zip_error_t error; +}; + + +static int decrypt_header(zip_source_t *, struct trad_pkware *); +static zip_int64_t pkware_decrypt(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); +static struct trad_pkware *trad_pkware_new(const char *password, zip_error_t *error); +static void trad_pkware_free(struct trad_pkware *); + + +zip_source_t * +zip_source_pkware_decode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, const char *password) { + struct trad_pkware *ctx; + zip_source_t *s2; + + if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + if (flags & ZIP_CODEC_ENCODE) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } + + if ((ctx = trad_pkware_new(password, &za->error)) == NULL) { + return NULL; + } + + if ((s2 = zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) { + trad_pkware_free(ctx); + return NULL; + } + + return s2; +} + + +static int +decrypt_header(zip_source_t *src, struct trad_pkware *ctx) { + zip_uint8_t header[ZIP_CRYPTO_PKWARE_HEADERLEN]; + struct zip_stat st; + zip_int64_t n; + bool ok = false; + + if ((n = zip_source_read(src, header, ZIP_CRYPTO_PKWARE_HEADERLEN)) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if (n != ZIP_CRYPTO_PKWARE_HEADERLEN) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; + } + + _zip_pkware_decrypt(&ctx->keys, header, header, ZIP_CRYPTO_PKWARE_HEADERLEN); + + if (zip_source_stat(src, &st)) { + /* stat failed, skip password validation */ + return 0; + } + + /* password verification - two ways: + * mtime - InfoZIP way, to avoid computing complete CRC before encrypting data + * CRC - old PKWare way + */ + + if (st.valid & ZIP_STAT_MTIME) { + unsigned short dostime, dosdate; + _zip_u2d_time(st.mtime, &dostime, &dosdate); + if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == dostime >> 8) { + ok = true; + } + } + + if (st.valid & ZIP_STAT_CRC) { + if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == st.crc >> 24) { + ok = true; + } + } + + if (!ok && ((st.valid & (ZIP_STAT_MTIME | ZIP_STAT_CRC)) != 0)) { + zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0); + return -1; + } + + return 0; +} + + +static zip_int64_t +pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { + struct trad_pkware *ctx; + zip_int64_t n; + + ctx = (struct trad_pkware *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + _zip_pkware_keys_reset(&ctx->keys); + _zip_pkware_decrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password)); + if (decrypt_header(src, ctx) < 0) { + return -1; + } + return 0; + + case ZIP_SOURCE_READ: + if ((n = zip_source_read(src, data, len)) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + _zip_pkware_decrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n); + return n; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: { + zip_stat_t *st; + + st = (zip_stat_t *)data; + + st->encryption_method = ZIP_EM_NONE; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size -= ZIP_CRYPTO_PKWARE_HEADERLEN; + } + + return 0; + } + + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SUPPORTS_REOPEN, -1); + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + trad_pkware_free(ctx); + return 0; + + default: + return zip_source_pass_to_lower_layer(src, data, len, cmd); + } +} + + +static struct trad_pkware * +trad_pkware_new(const char *password, zip_error_t *error) { + struct trad_pkware *ctx; + + if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((ctx->password = strdup(password)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; + } + + zip_error_init(&ctx->error); + + return ctx; +} + + +static void +trad_pkware_free(struct trad_pkware *ctx) { + if (ctx == NULL) { + return; + } + + free(ctx->password); + free(ctx); +} diff --git a/3rdparty/libzip/lib/zip_source_pkware_encode.c b/3rdparty/libzip/lib/zip_source_pkware_encode.c new file mode 100644 index 0000000000..d89b9f4e88 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_pkware_encode.c @@ -0,0 +1,271 @@ +/* + zip_source_pkware_encode.c -- Traditional PKWARE encryption routines + Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + +struct trad_pkware { + char *password; + zip_pkware_keys_t keys; + zip_buffer_t *buffer; + bool eof; + bool mtime_set; + time_t mtime; + zip_error_t error; +}; + + +static int encrypt_header(zip_source_t *, struct trad_pkware *); +static zip_int64_t pkware_encrypt(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); +static void trad_pkware_free(struct trad_pkware *); +static struct trad_pkware *trad_pkware_new(const char *password, zip_error_t *error); +static void set_mtime(struct trad_pkware* ctx, zip_stat_t* st); + +zip_source_t * +zip_source_pkware_encode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, const char *password) { + struct trad_pkware *ctx; + zip_source_t *s2; + + if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + if (!(flags & ZIP_CODEC_ENCODE)) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } + + if ((ctx = trad_pkware_new(password, &za->error)) == NULL) { + return NULL; + } + + if ((s2 = zip_source_layered(za, src, pkware_encrypt, ctx)) == NULL) { + trad_pkware_free(ctx); + return NULL; + } + + return s2; +} + + +static int +encrypt_header(zip_source_t *src, struct trad_pkware *ctx) { + unsigned short dostime, dosdate; + zip_uint8_t *header; + + if (!ctx->mtime_set) { + struct zip_stat st; + if (zip_source_stat(src, &st) != 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + set_mtime(ctx, &st); + } + + _zip_u2d_time(ctx->mtime, &dostime, &dosdate); + + if ((ctx->buffer = _zip_buffer_new(NULL, ZIP_CRYPTO_PKWARE_HEADERLEN)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + + header = _zip_buffer_data(ctx->buffer); + + /* generate header from random bytes and mtime + see appnote.iz, XIII. Decryption, Step 2, last paragraph */ + if (!zip_secure_random(header, ZIP_CRYPTO_PKWARE_HEADERLEN - 1)) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + return -1; + } + header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] = (zip_uint8_t)((dostime >> 8) & 0xff); + + _zip_pkware_encrypt(&ctx->keys, header, header, ZIP_CRYPTO_PKWARE_HEADERLEN); + + return 0; +} + + +static zip_int64_t +pkware_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip_source_cmd_t cmd) { + struct trad_pkware *ctx; + zip_int64_t n; + zip_uint64_t buffer_n; + + ctx = (struct trad_pkware *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + ctx->eof = false; + + /* initialize keys */ + _zip_pkware_keys_reset(&ctx->keys); + _zip_pkware_encrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password)); + + if (encrypt_header(src, ctx) < 0) { + return -1; + } + return 0; + + case ZIP_SOURCE_READ: + buffer_n = 0; + + if (ctx->buffer) { + /* write header values to data */ + buffer_n = _zip_buffer_read(ctx->buffer, data, length); + data = (zip_uint8_t *)data + buffer_n; + length -= buffer_n; + + if (_zip_buffer_eof(ctx->buffer)) { + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + } + } + + if (ctx->eof) { + return (zip_int64_t)buffer_n; + } + + if ((n = zip_source_read(src, data, length)) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + _zip_pkware_encrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n); + + if ((zip_uint64_t)n < length) { + ctx->eof = true; + } + + return (zip_int64_t)buffer_n + n; + + case ZIP_SOURCE_CLOSE: + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + return 0; + + case ZIP_SOURCE_STAT: { + zip_stat_t *st; + + st = (zip_stat_t *)data; + st->encryption_method = ZIP_EM_TRAD_PKWARE; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size += ZIP_CRYPTO_PKWARE_HEADERLEN; + } + set_mtime(ctx, st); + st->mtime = ctx->mtime; + st->valid |= ZIP_STAT_MTIME; + + return 0; + } + + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: { + zip_file_attributes_t *attributes = (zip_file_attributes_t *)data; + if (length < sizeof(*attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED; + attributes->version_needed = 20; + + return 0; + } + + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, length); + + case ZIP_SOURCE_FREE: + trad_pkware_free(ctx); + return 0; + + default: + return zip_source_pass_to_lower_layer(src, data, length, cmd); + } +} + + +static struct trad_pkware * +trad_pkware_new(const char *password, zip_error_t *error) { + struct trad_pkware *ctx; + + if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((ctx->password = strdup(password)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; + } + ctx->buffer = NULL; + ctx->mtime_set = false; + ctx->mtime = 0; + zip_error_init(&ctx->error); + + return ctx; +} + + +static void +trad_pkware_free(struct trad_pkware *ctx) { + if (ctx == NULL) { + return; + } + + free(ctx->password); + _zip_buffer_free(ctx->buffer); + zip_error_fini(&ctx->error); + free(ctx); +} + + +static void set_mtime(struct trad_pkware* ctx, zip_stat_t* st) { + if (!ctx->mtime_set) { + if (st->valid & ZIP_STAT_MTIME) { + ctx->mtime = st->mtime; + } + else { + time(&ctx->mtime); + } + ctx->mtime_set = true; + } +} diff --git a/3rdparty/libzip/lib/zip_source_read.c b/3rdparty/libzip/lib/zip_source_read.c new file mode 100644 index 0000000000..0938fcb084 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_read.c @@ -0,0 +1,96 @@ +/* + zip_source_read.c -- read data from zip_source + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +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; + } + if (!ZIP_SOURCE_IS_OPEN_READING(src) || len > ZIP_INT64_MAX || (len > 0 && data == NULL)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (src->had_read_error) { + return -1; + } + + if (_zip_source_eof(src)) { + return 0; + } + + if (len == 0) { + 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) { + src->had_read_error = true; + 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; + } + + if (src->bytes_read + bytes_read < src->bytes_read) { + src->bytes_read = ZIP_UINT64_MAX; + } + else { + src->bytes_read += bytes_read; + } + return (zip_int64_t)bytes_read; +} + + +bool +_zip_source_eof(zip_source_t *src) { + return src->eof; +} diff --git a/3rdparty/libzip/lib/zip_source_remove.c b/3rdparty/libzip/lib/zip_source_remove.c new file mode 100644 index 0000000000..c1d73ab928 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_remove.c @@ -0,0 +1,65 @@ +/* + zip_source_remove.c -- remove empty archive + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "zipint.h" + + +int +zip_source_remove(zip_source_t *src) { + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) { + return 0; + } + + if (ZIP_SOURCE_IS_OPEN_READING(src)) { + if (zip_source_close(src) < 0) { + return -1; + } + } + if (src->write_state != ZIP_SOURCE_WRITE_CLOSED) { + zip_source_rollback_write(src); + } + + if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_REMOVE) < 0) { + return -1; + } + + src->write_state = ZIP_SOURCE_WRITE_REMOVED; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_source_rollback_write.c b/3rdparty/libzip/lib/zip_source_rollback_write.c new file mode 100644 index 0000000000..ea1a151078 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_rollback_write.c @@ -0,0 +1,50 @@ +/* + zip_source_rollback_write.c -- discard changes + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN void +zip_source_rollback_write(zip_source_t *src) { + if (ZIP_SOURCE_IS_LAYERED(src)) { + return; + } + + if (src->write_state != ZIP_SOURCE_WRITE_OPEN && src->write_state != ZIP_SOURCE_WRITE_FAILED) { + return; + } + + _zip_source_call(src, NULL, 0, ZIP_SOURCE_ROLLBACK_WRITE); + src->write_state = ZIP_SOURCE_WRITE_CLOSED; +} diff --git a/3rdparty/libzip/lib/zip_source_seek.c b/3rdparty/libzip/lib/zip_source_seek.c new file mode 100644 index 0000000000..e3baad5ab8 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_seek.c @@ -0,0 +1,95 @@ +/* + zip_source_seek.c -- seek to offset + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_seek(zip_source_t *src, zip_int64_t offset, int whence) { + zip_source_args_seek_t args; + + if (src->source_closed) { + return -1; + } + if (!ZIP_SOURCE_IS_OPEN_READING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + args.offset = offset; + args.whence = whence; + + if (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK) < 0) { + return -1; + } + + src->eof = 0; + return 0; +} + + +zip_int64_t +zip_source_seek_compute_offset(zip_uint64_t offset, zip_uint64_t length, void *data, zip_uint64_t data_length, zip_error_t *error) { + zip_int64_t new_offset; + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, data_length, error); + + if (args == NULL) { + return -1; + } + + switch (args->whence) { + case SEEK_CUR: + new_offset = (zip_int64_t)offset + args->offset; + break; + + case SEEK_END: + new_offset = (zip_int64_t)length + args->offset; + break; + + case SEEK_SET: + new_offset = args->offset; + break; + + default: + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + if (new_offset < 0 || (zip_uint64_t)new_offset > length) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + return new_offset; +} diff --git a/3rdparty/libzip/lib/zip_source_seek_write.c b/3rdparty/libzip/lib/zip_source_seek_write.c new file mode 100644 index 0000000000..34ae2f5af2 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_seek_write.c @@ -0,0 +1,56 @@ +/* + zip_source_seek_write.c -- seek to offset for writing + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_seek_write(zip_source_t *src, zip_int64_t offset, int whence) { + zip_source_args_seek_t args; + + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + args.offset = offset; + args.whence = whence; + + return (_zip_source_call(src, &args, sizeof(args), ZIP_SOURCE_SEEK_WRITE) < 0 ? -1 : 0); +} diff --git a/3rdparty/libzip/lib/zip_source_stat.c b/3rdparty/libzip/lib/zip_source_stat.c new file mode 100644 index 0000000000..05dcb84d70 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_stat.c @@ -0,0 +1,66 @@ +/* + zip_source_stat.c -- get meta information from zip_source + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_source_stat(zip_source_t *src, zip_stat_t *st) { + if (src->source_closed) { + return -1; + } + if (st == NULL) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) { + zip_error_set(&src->error, ZIP_ER_READ, ENOENT); + } + + zip_stat_init(st); + + if (ZIP_SOURCE_IS_LAYERED(src)) { + if (zip_source_stat(src->src, st) < 0) { + zip_error_set_from_source(&src->error, src->src); + return -1; + } + } + + if (_zip_source_call(src, st, sizeof(*st), ZIP_SOURCE_STAT) < 0) { + return -1; + } + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_source_supports.c b/3rdparty/libzip/lib/zip_source_supports.c new file mode 100644 index 0000000000..8fea2ae919 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_supports.c @@ -0,0 +1,74 @@ +/* + zip_source_supports.c -- check for supported functions + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +zip_int64_t +zip_source_supports(zip_source_t *src) { + return src->supports; +} + +bool +zip_source_supports_reopen(zip_source_t *src) { + return (zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SUPPORTS_REOPEN)) != 0; +} + +ZIP_EXTERN zip_int64_t +zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...) { + zip_int64_t bitmap; + va_list ap; + + bitmap = ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd0); + + + va_start(ap, cmd0); + for (;;) { + int cmd = va_arg(ap, int); + if (cmd < 0) { + break; + } + bitmap |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd); + } + va_end(ap); + + return bitmap; +} + + +ZIP_EXTERN int zip_source_is_seekable(zip_source_t *src) { + return ZIP_SOURCE_CHECK_SUPPORTED(zip_source_supports(src->src), ZIP_SOURCE_SEEK); +} diff --git a/3rdparty/libzip/lib/zip_source_tell.c b/3rdparty/libzip/lib/zip_source_tell.c new file mode 100644 index 0000000000..49057ce56c --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_tell.c @@ -0,0 +1,57 @@ +/* + zip_source_tell.c -- report current offset + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_source_tell(zip_source_t *src) { + if (src->source_closed) { + return -1; + } + if (!ZIP_SOURCE_IS_OPEN_READING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + if ((src->supports & (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL) | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK))) == 0) { + if (src->bytes_read > ZIP_INT64_MAX) { + zip_error_set(&src->error, ZIP_ER_TELL, EOVERFLOW); + return -1; + } + return (zip_int64_t)src->bytes_read; + } + + return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL); +} diff --git a/3rdparty/libzip/lib/zip_source_tell_write.c b/3rdparty/libzip/lib/zip_source_tell_write.c new file mode 100644 index 0000000000..a5b0e53112 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_tell_write.c @@ -0,0 +1,51 @@ +/* + zip_source_tell_write.c -- report current offset for writing + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_source_tell_write(zip_source_t *src) { + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } + + if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_source_call(src, NULL, 0, ZIP_SOURCE_TELL_WRITE); +} diff --git a/3rdparty/libzip/lib/zip_source_window.c b/3rdparty/libzip/lib/zip_source_window.c new file mode 100644 index 0000000000..524e27c837 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_window.c @@ -0,0 +1,357 @@ +/* + zip_source_window.c -- return part of lower source + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" + +struct window { + zip_uint64_t start; /* where in file we start reading */ + zip_uint64_t end; /* where in file we stop reading */ + bool end_valid; /* whether end is set, otherwise read until EOF */ + + /* 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_uint64_t stat_invalid; + zip_file_attributes_t attributes; + zip_error_t error; + zip_int64_t supports; + bool needs_seek; +}; + +static zip_int64_t window_read(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); + + +ZIP_EXTERN zip_source_t * +zip_source_window_create(zip_source_t *src, zip_uint64_t start, zip_int64_t len, zip_error_t *error) { + return _zip_source_window_new(src, start, len, NULL, 0, NULL, NULL, 0, false, error); +} + + +zip_source_t * +_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_int64_t length, zip_stat_t *st, zip_uint64_t st_invalid, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, bool take_ownership, zip_error_t *error) { + zip_source_t* window_source; + struct window *ctx; + + if (src == NULL || length < -1 || (source_archive == NULL && source_index != 0)) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (length >= 0) { + if (start + (zip_uint64_t)length < start) { + 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; + if (length == -1) { + ctx->end_valid = false; + } + else { + ctx->end = start + (zip_uint64_t)length; + ctx->end_valid = true; + } + zip_stat_init(&ctx->stat); + ctx->stat_invalid = st_invalid; + if (attributes != NULL) { + (void)memcpy_s(&ctx->attributes, sizeof(ctx->attributes), attributes, sizeof(ctx->attributes)); + } + else { + zip_file_attributes_init(&ctx->attributes); + } + 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_SUPPORTS_REOPEN)) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, ZIP_SOURCE_FREE, -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; + } + } + + window_source = zip_source_layered_create(src, window_read, ctx, error); + if (window_source != NULL && !take_ownership) { + zip_source_keep(src); + } + return window_source; +} + + +int +_zip_source_set_source_archive(zip_source_t *src, zip_t *za) { + src->source_archive = za; + return _zip_register_source(za, src); +} + + +/* called by zip_discard to avoid operating on file from closed archive */ +void +_zip_source_invalidate(zip_source_t *src) { + src->source_closed = 1; + + if (zip_error_code_zip(&src->error) == ZIP_ER_OK) { + zip_error_set(&src->error, ZIP_ER_ZIPCLOSED, 0); + } +} + + +static zip_int64_t +window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { + struct window *ctx; + zip_int64_t ret; + zip_uint64_t n, i; + + ctx = (struct window *)_ctx; + + 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_uint64_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, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_CDIR_ENTRY_INVALID, ctx->source_index)); + return -1; + } + ctx->start += offset; + ctx->end += offset; + ctx->source_archive = NULL; + } + + if (!ctx->needs_seek) { + DEFINE_BYTE_ARRAY(b, BUFSIZE); + + if (!byte_array_init(b, BUFSIZE)) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + + for (n = 0; n < ctx->start; n += (zip_uint64_t)ret) { + i = (ctx->start - n > BUFSIZE ? BUFSIZE : ctx->start - n); + if ((ret = zip_source_read(src, b, i)) < 0) { + zip_error_set_from_source(&ctx->error, src); + byte_array_fini(b); + return -1; + } + if (ret == 0) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + byte_array_fini(b); + return -1; + } + } + + byte_array_fini(b); + } + + ctx->offset = ctx->start; + return 0; + + case ZIP_SOURCE_READ: + if (ctx->end_valid && 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; + } + + ctx->offset += (zip_uint64_t)ret; + + if (ret == 0) { + if (ctx->end_valid && ctx->offset < ctx->end) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; + } + } + return ret; + + case ZIP_SOURCE_SEEK: { + zip_int64_t new_offset; + + if (!ctx->end_valid) { + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); + + if (args == NULL) { + return -1; + } + if (args->whence == SEEK_END) { + if (zip_source_seek(src, args->offset, args->whence) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + new_offset = zip_source_tell(src); + if (new_offset < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + if ((zip_uint64_t)new_offset < ctx->start) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + (void)zip_source_seek(src, (zip_int64_t)ctx->offset, SEEK_SET); + return -1; + } + ctx->offset = (zip_uint64_t)new_offset; + return 0; + } + } + + new_offset = zip_source_seek_compute_offset(ctx->offset - ctx->start, ctx->end - ctx->start, data, len, &ctx->error); + + if (new_offset < 0) { + return -1; + } + + ctx->offset = (zip_uint64_t)new_offset + ctx->start; + return 0; + } + + 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; + } + + if (!(ctx->stat.valid & ZIP_STAT_SIZE)) { + if (ctx->end_valid) { + st->valid |= ZIP_STAT_SIZE; + st->size = ctx->end - ctx->start; + } + else if (st->valid & ZIP_STAT_SIZE) { + st->size -= ctx->start; + } + } + + st->valid &= ~ctx->stat_invalid; + + return 0; + } + + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: + if (len < sizeof(ctx->attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + (void)memcpy_s(data, sizeof(ctx->attributes), &ctx->attributes, sizeof(ctx->attributes)); + return sizeof(ctx->attributes); + + case ZIP_SOURCE_SUPPORTS: + return ctx->supports; + + case ZIP_SOURCE_TELL: + return (zip_int64_t)(ctx->offset - ctx->start); + + default: + return zip_source_pass_to_lower_layer(src, data, len, cmd); + } +} + + +void +_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]; + za->nopen_source--; + break; + } + } +} + + +int +_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; + open_source = (zip_source_t **)realloc(za->open_source, n * sizeof(zip_source_t *)); + if (open_source == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + za->nopen_source_alloc = n; + za->open_source = open_source; + } + + za->open_source[za->nopen_source++] = src; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_source_winzip_aes_decode.c b/3rdparty/libzip/lib/zip_source_winzip_aes_decode.c new file mode 100644 index 0000000000..ee53fb419c --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_winzip_aes_decode.c @@ -0,0 +1,265 @@ +/* + zip_source_winzip_aes_decode.c -- Winzip AES decryption routines + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" +#include "zip_crypto.h" + +struct winzip_aes { + char *password; + zip_uint16_t encryption_method; + + zip_uint64_t data_length; + zip_uint64_t current_position; + + zip_winzip_aes_t *aes_ctx; + zip_error_t error; +}; + + +static int decrypt_header(zip_source_t *src, struct winzip_aes *ctx); +static void winzip_aes_free(struct winzip_aes *); +static zip_int64_t winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd); +static struct winzip_aes *winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t *error); + + +zip_source_t * +zip_source_winzip_aes_decode(zip_t *za, zip_source_t *src, zip_uint16_t encryption_method, int flags, const char *password) { + zip_source_t *s2; + zip_stat_t st; + zip_uint64_t aux_length; + struct winzip_aes *ctx; + + if ((encryption_method != ZIP_EM_AES_128 && encryption_method != ZIP_EM_AES_192 && encryption_method != ZIP_EM_AES_256) || password == NULL || src == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + if (flags & ZIP_CODEC_ENCODE) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } + + if (zip_source_stat(src, &st) != 0) { + zip_error_set_from_source(&za->error, src); + return NULL; + } + + aux_length = WINZIP_AES_PASSWORD_VERIFY_LENGTH + SALT_LENGTH(encryption_method) + HMAC_LENGTH; + + if ((st.valid & ZIP_STAT_COMP_SIZE) == 0 || st.comp_size < aux_length) { + zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0); + return NULL; + } + + if ((ctx = winzip_aes_new(encryption_method, password, &za->error)) == NULL) { + return NULL; + } + + ctx->data_length = st.comp_size - aux_length; + + if ((s2 = zip_source_layered(za, src, winzip_aes_decrypt, ctx)) == NULL) { + winzip_aes_free(ctx); + return NULL; + } + + return s2; +} + + +static int +decrypt_header(zip_source_t *src, struct winzip_aes *ctx) { + zip_uint8_t header[WINZIP_AES_MAX_HEADER_LENGTH]; + zip_uint8_t password_verification[WINZIP_AES_PASSWORD_VERIFY_LENGTH]; + unsigned int headerlen; + zip_int64_t n; + + headerlen = WINZIP_AES_PASSWORD_VERIFY_LENGTH + SALT_LENGTH(ctx->encryption_method); + if ((n = zip_source_read(src, header, headerlen)) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if (n != headerlen) { + zip_error_set(&ctx->error, ZIP_ER_EOF, 0); + return -1; + } + + if ((ctx->aes_ctx = _zip_winzip_aes_new((zip_uint8_t *)ctx->password, strlen(ctx->password), header, ctx->encryption_method, password_verification, &ctx->error)) == NULL) { + return -1; + } + if (memcmp(password_verification, header + SALT_LENGTH(ctx->encryption_method), WINZIP_AES_PASSWORD_VERIFY_LENGTH) != 0) { + _zip_winzip_aes_free(ctx->aes_ctx); + ctx->aes_ctx = NULL; + zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0); + return -1; + } + return 0; +} + + +static bool +verify_hmac(zip_source_t *src, struct winzip_aes *ctx) { + unsigned char computed[ZIP_CRYPTO_SHA1_LENGTH], from_file[HMAC_LENGTH]; + if (zip_source_read(src, from_file, HMAC_LENGTH) < HMAC_LENGTH) { + zip_error_set_from_source(&ctx->error, src); + return false; + } + + if (!_zip_winzip_aes_finish(ctx->aes_ctx, computed)) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return false; + } + _zip_winzip_aes_free(ctx->aes_ctx); + ctx->aes_ctx = NULL; + + if (memcmp(from_file, computed, HMAC_LENGTH) != 0) { + zip_error_set(&ctx->error, ZIP_ER_CRC, 0); + return false; + } + + return true; +} + + +static zip_int64_t +winzip_aes_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { + struct winzip_aes *ctx; + zip_int64_t n; + + ctx = (struct winzip_aes *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + if (decrypt_header(src, ctx) < 0) { + return -1; + } + ctx->current_position = 0; + return 0; + + case ZIP_SOURCE_READ: + if (len > ctx->data_length - ctx->current_position) { + len = ctx->data_length - ctx->current_position; + } + + if (len == 0) { + if (!verify_hmac(src, ctx)) { + return -1; + } + return 0; + } + + if ((n = zip_source_read(src, data, len)) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + ctx->current_position += (zip_uint64_t)n; + + if (!_zip_winzip_aes_decrypt(ctx->aes_ctx, (zip_uint8_t *)data, (zip_uint64_t)n)) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + return n; + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: { + zip_stat_t *st; + + st = (zip_stat_t *)data; + + st->encryption_method = ZIP_EM_NONE; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size -= 12 + SALT_LENGTH(ctx->encryption_method); + } + + return 0; + } + + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SUPPORTS_REOPEN, -1); + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + winzip_aes_free(ctx); + return 0; + + default: + return zip_source_pass_to_lower_layer(src, data, len, cmd); + } +} + + +static void +winzip_aes_free(struct winzip_aes *ctx) { + if (ctx == NULL) { + return; + } + + _zip_crypto_clear(ctx->password, strlen(ctx->password)); + free(ctx->password); + zip_error_fini(&ctx->error); + _zip_winzip_aes_free(ctx->aes_ctx); + free(ctx); +} + + +static struct winzip_aes * +winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t *error) { + struct winzip_aes *ctx; + + if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((ctx->password = strdup(password)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; + } + + ctx->encryption_method = encryption_method; + ctx->aes_ctx = NULL; + + zip_error_init(&ctx->error); + + return ctx; +} diff --git a/3rdparty/libzip/lib/zip_source_winzip_aes_encode.c b/3rdparty/libzip/lib/zip_source_winzip_aes_encode.c new file mode 100644 index 0000000000..87e2865a03 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_winzip_aes_encode.c @@ -0,0 +1,253 @@ +/* + zip_source_winzip_aes_encode.c -- Winzip AES encryption routines + Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include + +#include "zipint.h" +#include "zip_crypto.h" + +struct winzip_aes { + char *password; + zip_uint16_t encryption_method; + + zip_uint8_t data[ZIP_MAX(WINZIP_AES_MAX_HEADER_LENGTH, ZIP_CRYPTO_SHA1_LENGTH)]; + zip_buffer_t *buffer; + + zip_winzip_aes_t *aes_ctx; + bool eof; + zip_error_t error; +}; + + +static int encrypt_header(zip_source_t *src, struct winzip_aes *ctx); +static void winzip_aes_free(struct winzip_aes *); +static zip_int64_t winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd); +static struct winzip_aes *winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t *error); + + +zip_source_t * +zip_source_winzip_aes_encode(zip_t *za, zip_source_t *src, zip_uint16_t encryption_method, int flags, const char *password) { + zip_source_t *s2; + struct winzip_aes *ctx; + + if ((encryption_method != ZIP_EM_AES_128 && encryption_method != ZIP_EM_AES_192 && encryption_method != ZIP_EM_AES_256) || password == NULL || src == NULL) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((ctx = winzip_aes_new(encryption_method, password, &za->error)) == NULL) { + return NULL; + } + + if ((s2 = zip_source_layered(za, src, winzip_aes_encrypt, ctx)) == NULL) { + winzip_aes_free(ctx); + return NULL; + } + + return s2; +} + + +static int +encrypt_header(zip_source_t *src, struct winzip_aes *ctx) { + zip_uint16_t salt_length = SALT_LENGTH(ctx->encryption_method); + if (!zip_secure_random(ctx->data, salt_length)) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; + } + + if ((ctx->aes_ctx = _zip_winzip_aes_new((zip_uint8_t *)ctx->password, strlen(ctx->password), ctx->data, ctx->encryption_method, ctx->data + salt_length, &ctx->error)) == NULL) { + return -1; + } + + if ((ctx->buffer = _zip_buffer_new(ctx->data, salt_length + WINZIP_AES_PASSWORD_VERIFY_LENGTH)) == NULL) { + _zip_winzip_aes_free(ctx->aes_ctx); + ctx->aes_ctx = NULL; + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + + return 0; +} + + +static zip_int64_t +winzip_aes_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip_source_cmd_t cmd) { + struct winzip_aes *ctx; + zip_int64_t ret; + zip_uint64_t buffer_n; + + ctx = (struct winzip_aes *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + ctx->eof = false; + if (encrypt_header(src, ctx) < 0) { + return -1; + } + return 0; + + case ZIP_SOURCE_READ: + buffer_n = 0; + + if (ctx->buffer) { + buffer_n = _zip_buffer_read(ctx->buffer, data, length); + + data = (zip_uint8_t *)data + buffer_n; + length -= buffer_n; + + if (_zip_buffer_eof(ctx->buffer)) { + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + } + } + + if (ctx->eof) { + return (zip_int64_t)buffer_n; + } + + if ((ret = zip_source_read(src, data, length)) < 0) { + zip_error_set_from_source(&ctx->error, src); + return -1; + } + + if (!_zip_winzip_aes_encrypt(ctx->aes_ctx, data, (zip_uint64_t)ret)) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + /* TODO: return partial read? */ + return -1; + } + + if ((zip_uint64_t)ret < length) { + ctx->eof = true; + if (!_zip_winzip_aes_finish(ctx->aes_ctx, ctx->data)) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + /* TODO: return partial read? */ + return -1; + } + _zip_winzip_aes_free(ctx->aes_ctx); + ctx->aes_ctx = NULL; + if ((ctx->buffer = _zip_buffer_new(ctx->data, HMAC_LENGTH)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + /* TODO: return partial read? */ + return -1; + } + buffer_n += _zip_buffer_read(ctx->buffer, (zip_uint8_t *)data + ret, length - (zip_uint64_t)ret); + } + + return (zip_int64_t)(buffer_n + (zip_uint64_t)ret); + + case ZIP_SOURCE_CLOSE: + return 0; + + case ZIP_SOURCE_STAT: { + zip_stat_t *st; + + st = (zip_stat_t *)data; + st->encryption_method = ctx->encryption_method; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size += 12 + SALT_LENGTH(ctx->encryption_method); + } + + return 0; + } + + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: { + zip_file_attributes_t *attributes = (zip_file_attributes_t *)data; + if (length < sizeof(*attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED; + attributes->version_needed = 51; + + return 0; + } + + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, length); + + case ZIP_SOURCE_FREE: + winzip_aes_free(ctx); + return 0; + + default: + return zip_source_pass_to_lower_layer(src, data, length, cmd); + } +} + + +static void +winzip_aes_free(struct winzip_aes *ctx) { + if (ctx == NULL) { + return; + } + + _zip_crypto_clear(ctx->password, strlen(ctx->password)); + free(ctx->password); + zip_error_fini(&ctx->error); + _zip_buffer_free(ctx->buffer); + _zip_winzip_aes_free(ctx->aes_ctx); + free(ctx); +} + + +static struct winzip_aes * +winzip_aes_new(zip_uint16_t encryption_method, const char *password, zip_error_t *error) { + struct winzip_aes *ctx; + + if ((ctx = (struct winzip_aes *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((ctx->password = strdup(password)) == NULL) { + free(ctx); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->encryption_method = encryption_method; + ctx->buffer = NULL; + ctx->aes_ctx = NULL; + + zip_error_init(&ctx->error); + + ctx->eof = false; + return ctx; +} diff --git a/3rdparty/libzip/lib/zip_source_write.c b/3rdparty/libzip/lib/zip_source_write.c new file mode 100644 index 0000000000..24dde9b247 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_write.c @@ -0,0 +1,46 @@ +/* + zip_source_write.c -- start a new file for writing + Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN zip_int64_t +zip_source_write(zip_source_t *src, const void *data, zip_uint64_t length) { + if (!ZIP_SOURCE_IS_OPEN_WRITING(src) || length > ZIP_INT64_MAX) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + return _zip_source_call(src, (void *)data, length, ZIP_SOURCE_WRITE); +} diff --git a/3rdparty/libzip/lib/zip_source_zip.c b/3rdparty/libzip/lib/zip_source_zip.c new file mode 100644 index 0000000000..faabf0d29f --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_zip.c @@ -0,0 +1,63 @@ +/* + zip_source_zip.c -- create data source from zip file + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#define _ZIP_COMPILING_DEPRECATED +#include "zipint.h" + +ZIP_EXTERN zip_source_t *zip_source_zip_create(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len, zip_error_t *error) { + if (len < -1) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (len == 0) { + len = -1; + } + + if (start == 0 && len == -1) { + flags |= ZIP_FL_COMPRESSED; + } + else { + flags &= ~ZIP_FL_COMPRESSED; + } + + return zip_source_zip_file_create(srcza, srcidx, flags, start, len, NULL, error); +} + + +ZIP_EXTERN zip_source_t *zip_source_zip(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len) { + return zip_source_zip_create(srcza, srcidx, flags, start, len, &za->error); +} diff --git a/3rdparty/libzip/lib/zip_source_zip_new.c b/3rdparty/libzip/lib/zip_source_zip_new.c new file mode 100644 index 0000000000..ecccdd68f7 --- /dev/null +++ b/3rdparty/libzip/lib/zip_source_zip_new.c @@ -0,0 +1,312 @@ +/* + zip_source_zip_new.c -- prepare data structures for zip_fopen/zip_source_zip + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + +static void _zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de); + +ZIP_EXTERN zip_source_t *zip_source_zip_file(zip_t* za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len, const char *password) { + return zip_source_zip_file_create(srcza, srcidx, flags, start, len, password, &za->error); +} + + +ZIP_EXTERN zip_source_t *zip_source_zip_file_create(zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_int64_t len, const char *password, zip_error_t *error) { + /* TODO: We need to make sure that the returned source is invalidated when srcza is closed. */ + zip_source_t *src, *s2; + zip_stat_t st; + zip_file_attributes_t attributes; + zip_dirent_t *de; + bool partial_data, needs_crc, encrypted, needs_decrypt, compressed, needs_decompress, changed_data, have_size, have_comp_size; + zip_flags_t stat_flags; + zip_int64_t data_len; + bool take_ownership = false; + bool empty_data = false; + + if (srcza == NULL || srcidx >= srcza->nentry || len < -1) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (flags & ZIP_FL_ENCRYPTED) { + flags |= ZIP_FL_COMPRESSED; + } + + changed_data = false; + if ((flags & ZIP_FL_UNCHANGED) == 0) { + zip_entry_t *entry = srcza->entry + srcidx; + if (ZIP_ENTRY_DATA_CHANGED(entry)) { + if ((flags & ZIP_FL_COMPRESSED) || !zip_source_supports_reopen(entry->source)) { + zip_error_set(error, ZIP_ER_CHANGED, 0); + return NULL; + } + + changed_data = true; + } + else if (entry->deleted) { + zip_error_set(error, ZIP_ER_CHANGED, 0); + return NULL; + } + } + + stat_flags = flags; + if (!changed_data) { + stat_flags |= ZIP_FL_UNCHANGED; + } + + if (zip_stat_index(srcza, srcidx, stat_flags, &st) < 0) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + + if ((start > 0 || len >= 0) && (flags & ZIP_FL_COMPRESSED)) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + have_size = (st.valid & ZIP_STAT_SIZE) != 0; + /* overflow or past end of file */ + if (len >= 0 && ((start > 0 && start + len < start) || (have_size && start + len > st.size))) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (len == -1) { + if (have_size) { + if (st.size - start > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + data_len = (zip_int64_t)(st.size - start); + } + else { + data_len = -1; + } + } + else { + data_len = len; + } + + if (have_size) { + partial_data = (zip_uint64_t)(data_len) < st.size; + } + else { + partial_data = true; + } + encrypted = (st.valid & ZIP_STAT_ENCRYPTION_METHOD) && (st.encryption_method != ZIP_EM_NONE); + needs_decrypt = ((flags & ZIP_FL_ENCRYPTED) == 0) && encrypted; + compressed = (st.valid & ZIP_STAT_COMP_METHOD) && (st.comp_method != ZIP_CM_STORE); + needs_decompress = ((flags & ZIP_FL_COMPRESSED) == 0) && compressed; + /* when reading the whole file, check for CRC errors */ + needs_crc = ((flags & ZIP_FL_COMPRESSED) == 0 || !compressed) && !partial_data && (st.valid & ZIP_STAT_CRC) != 0; + + if (needs_decrypt) { + if (password == NULL) { + password = srcza->default_password; + } + if (password == NULL) { + zip_error_set(error, ZIP_ER_NOPASSWD, 0); + return NULL; + } + } + + if ((de = _zip_get_dirent(srcza, srcidx, flags, error)) == NULL) { + return NULL; + } + _zip_file_attributes_from_dirent(&attributes, de); + + have_comp_size = (st.valid & ZIP_STAT_COMP_SIZE) != 0; + if (needs_decrypt || needs_decompress) { + empty_data = (have_comp_size && st.comp_size == 0); + } + else { + empty_data = (have_size && st.size == 0); + } + if (empty_data) { + src = zip_source_buffer_with_attributes_create(NULL, 0, 0, &attributes, error); + } + else { + src = NULL; + } + + + /* If we created source buffer above, we want the window source to take ownership of it. */ + take_ownership = src != NULL; + /* if we created a buffer source above, then treat it as if + reading the changed data - that way we don't need add another + special case to the code below that wraps it in the window + source */ + changed_data = changed_data || (src != NULL); + + if (partial_data && !needs_decrypt && !needs_decompress) { + struct zip_stat st2; + zip_t *source_archive; + zip_uint64_t source_index; + + if (changed_data) { + if (src == NULL) { + src = srcza->entry[srcidx].source; + } + source_archive = NULL; + source_index = 0; + } + else { + src = srcza->src; + source_archive = srcza; + source_index = srcidx; + } + + st2.comp_method = ZIP_CM_STORE; + st2.valid = ZIP_STAT_COMP_METHOD; + if (data_len >= 0) { + st2.size = (zip_uint64_t)data_len; + st2.comp_size = (zip_uint64_t)data_len; + st2.valid |= ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE; + } + if (st.valid & ZIP_STAT_MTIME) { + st2.mtime = st.mtime; + st2.valid |= ZIP_STAT_MTIME; + } + + if ((src = _zip_source_window_new(src, start, data_len, &st2, ZIP_STAT_NAME, &attributes, source_archive, source_index, take_ownership, error)) == NULL) { + return NULL; + } + } + /* here we restrict src to file data, so no point in doing it for + source that already represents only the file data */ + else if (!changed_data) { + /* this branch is executed only for archive sources; we know + that stat data come from the archive too, so it's safe to + assume that st has a comp_size specified */ + if (st.comp_size > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + /* despite the fact that we want the whole data file, we still + wrap the source into a window source to add st and + attributes and to have a source that positions the read + offset properly before each read for multiple zip_file_t + referring to the same underlying source */ + if ((src = _zip_source_window_new(srcza->src, 0, (zip_int64_t)st.comp_size, &st, ZIP_STAT_NAME, &attributes, srcza, srcidx, take_ownership, error)) == NULL) { + return NULL; + } + } + else { + /* this branch gets executed when reading the whole changed + data file or when "reading" from a zero-sized source buffer + that we created above */ + if (src == NULL) { + src = srcza->entry[srcidx].source; + } + /* despite the fact that we want the whole data file, we still + wrap the source into a window source to add st and + attributes and to have a source that positions the read + offset properly before each read for multiple zip_file_t + referring to the same underlying source */ + if ((src = _zip_source_window_new(src, 0, data_len, &st, ZIP_STAT_NAME, &attributes, NULL, 0, take_ownership, error)) == NULL) { + return NULL; + } + } + + /* In all cases, src is a window source and therefore is owned by this function. */ + + if (_zip_source_set_source_archive(src, srcza) < 0) { + zip_source_free(src); + return NULL; + } + + /* creating a layered source calls zip_keep() on the lower layer, so we free it */ + + 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(error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } + + s2 = enc_impl(srcza, src, st.encryption_method, 0, password); + if (s2 == NULL) { + zip_source_free(src); + return NULL; + } + + src = s2; + } + if (needs_decompress) { + s2 = zip_source_decompress(srcza, src, st.comp_method); + if (s2 == NULL) { + zip_source_free(src); + return NULL; + } + src = s2; + } + if (needs_crc) { + s2 = zip_source_crc_create(src, 1, error); + if (s2 == NULL) { + zip_source_free(src); + return NULL; + } + src = s2; + } + + if (partial_data && (needs_decrypt || needs_decompress)) { + zip_stat_t st2; + zip_stat_init(&st2); + if (data_len >= 0) { + st2.valid = ZIP_STAT_SIZE; + st2.size = (zip_uint64_t)data_len; + } + s2 = _zip_source_window_new(src, start, data_len, &st2, ZIP_STAT_NAME, NULL, NULL, 0, true, error); + if (s2 == NULL) { + zip_source_free(src); + return NULL; + } + src = s2; + } + + return src; +} + +static void +_zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de) { + zip_file_attributes_init(attributes); + attributes->valid = ZIP_FILE_ATTRIBUTES_ASCII | ZIP_FILE_ATTRIBUTES_HOST_SYSTEM | ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS; + attributes->ascii = de->int_attrib & 1; + attributes->host_system = de->version_madeby >> 8; + attributes->external_file_attributes = de->ext_attrib; + attributes->general_purpose_bit_flags = de->bitflags; + attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK; +} diff --git a/3rdparty/libzip/lib/zip_stat.c b/3rdparty/libzip/lib/zip_stat.c new file mode 100644 index 0000000000..51d8026ddd --- /dev/null +++ b/3rdparty/libzip/lib/zip_stat.c @@ -0,0 +1,46 @@ +/* + zip_stat.c -- get information about file by name + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_stat(zip_t *za, const char *fname, zip_flags_t flags, zip_stat_t *st) { + zip_int64_t idx; + + if ((idx = zip_name_locate(za, fname, flags)) < 0) + return -1; + + return zip_stat_index(za, (zip_uint64_t)idx, flags, st); +} diff --git a/3rdparty/libzip/lib/zip_stat_index.c b/3rdparty/libzip/lib/zip_stat_index.c new file mode 100644 index 0000000000..da33c09eb5 --- /dev/null +++ b/3rdparty/libzip/lib/zip_stat_index.c @@ -0,0 +1,111 @@ +/* + zip_stat_index.c -- get information about file by index + Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_stat_index(zip_t *za, zip_uint64_t index, zip_flags_t flags, zip_stat_t *st) { + const char *name; + zip_dirent_t *de; + zip_entry_t *entry; + + if ((de = _zip_get_dirent(za, index, flags, NULL)) == NULL) { + return -1; + } + + if ((name = zip_get_name(za, index, flags)) == NULL) { + return -1; + } + + entry = za->entry + index; + + if ((flags & ZIP_FL_UNCHANGED) == 0 && ZIP_ENTRY_DATA_CHANGED(za->entry + index)) { + + if (zip_source_stat(entry->source, st) < 0) { + zip_error_set(&za->error, ZIP_ER_CHANGED, 0); + return -1; + } + + if (ZIP_CM_IS_DEFAULT(de->comp_method)) { + if (!(st->valid & ZIP_STAT_COMP_METHOD) || st->comp_method == ZIP_CM_STORE) { + st->valid &= ~(ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD); + } + } + else { + if ((st->valid & ZIP_STAT_COMP_METHOD) && st->comp_method != de->comp_method) { + st->valid &= ~ZIP_STAT_COMP_SIZE; + } + st->valid |= ZIP_STAT_COMP_METHOD; + st->comp_method = de->comp_method; + } + + if (((st->valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_SIZE)) == (ZIP_STAT_COMP_METHOD|ZIP_STAT_SIZE)) && st->comp_method == ZIP_CM_STORE) { + st->valid |= ZIP_STAT_COMP_SIZE; + st->comp_size = st->size; + } + + if (entry->changes != NULL && entry->changes->changed & ZIP_DIRENT_LAST_MOD) { + st->mtime = de->last_mod; + st->valid |= ZIP_STAT_MTIME; + } + } + else { + zip_stat_init(st); + + st->crc = de->crc; + st->size = de->uncomp_size; + st->mtime = de->last_mod; + st->comp_size = de->comp_size; + st->comp_method = (zip_uint16_t)de->comp_method; + 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; + if (entry->changes != NULL && entry->changes->changed & ZIP_DIRENT_COMP_METHOD) { + st->valid &= ~ZIP_STAT_COMP_SIZE; + } + } + + if ((za->ch_flags & ZIP_AFL_WANT_TORRENTZIP) && (flags & ZIP_FL_UNCHANGED) == 0) { + st->comp_method = ZIP_CM_DEFLATE; + st->mtime = _zip_d2u_time(0xbc00, 0x2198); + st->valid |= ZIP_STAT_MTIME | ZIP_STAT_COMP_METHOD; + st->valid &= ~ZIP_STAT_COMP_SIZE; + } + + st->index = index; + st->name = name; + st->valid |= ZIP_STAT_INDEX | ZIP_STAT_NAME; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_stat_init.c b/3rdparty/libzip/lib/zip_stat_init.c new file mode 100644 index 0000000000..9c6088a796 --- /dev/null +++ b/3rdparty/libzip/lib/zip_stat_init.c @@ -0,0 +1,83 @@ +/* + zip_stat_init.c -- initialize struct zip_stat. + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "zipint.h" + + +ZIP_EXTERN void +zip_stat_init(zip_stat_t *st) { + st->valid = 0; + st->name = NULL; + st->index = ZIP_UINT64_MAX; + st->crc = 0; + st->mtime = (time_t)-1; + st->size = 0; + st->comp_size = 0; + st->comp_method = ZIP_CM_STORE; + st->encryption_method = ZIP_EM_NONE; +} + + +int +_zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error) { + /* name is not merged, since zip_stat_t doesn't own it, and src may not be valid as long as dst */ + if (src->valid & ZIP_STAT_INDEX) { + dst->index = src->index; + } + if (src->valid & ZIP_STAT_SIZE) { + dst->size = src->size; + } + if (src->valid & ZIP_STAT_COMP_SIZE) { + dst->comp_size = src->comp_size; + } + if (src->valid & ZIP_STAT_MTIME) { + dst->mtime = src->mtime; + } + if (src->valid & ZIP_STAT_CRC) { + dst->crc = src->crc; + } + if (src->valid & ZIP_STAT_COMP_METHOD) { + dst->comp_method = src->comp_method; + } + if (src->valid & ZIP_STAT_ENCRYPTION_METHOD) { + dst->encryption_method = src->encryption_method; + } + if (src->valid & ZIP_STAT_FLAGS) { + dst->flags = src->flags; + } + dst->valid |= src->valid; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_strerror.c b/3rdparty/libzip/lib/zip_strerror.c new file mode 100644 index 0000000000..7d8279318d --- /dev/null +++ b/3rdparty/libzip/lib/zip_strerror.c @@ -0,0 +1,41 @@ +/* + zip_sterror.c -- get string representation of zip error + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN const char * +zip_strerror(zip_t *za) { + return zip_error_strerror(&za->error); +} diff --git a/3rdparty/libzip/lib/zip_string.c b/3rdparty/libzip/lib/zip_string.c new file mode 100644 index 0000000000..1c964491c9 --- /dev/null +++ b/3rdparty/libzip/lib/zip_string.c @@ -0,0 +1,178 @@ +/* + zip_string.c -- string handling (with encoding) + Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include +#include +#include + +#include "zipint.h" + +zip_uint32_t +_zip_string_crc32(const zip_string_t *s) { + zip_uint32_t crc; + + crc = (zip_uint32_t)crc32(0L, Z_NULL, 0); + + if (s != NULL) + crc = (zip_uint32_t)crc32(crc, s->raw, s->length); + + return crc; +} + + +int +_zip_string_equal(const zip_string_t *a, const zip_string_t *b) { + if (a == NULL || b == NULL) + return a == b; + + if (a->length != b->length) + return 0; + + /* TODO: encoding */ + + return (memcmp(a->raw, b->raw, a->length) == 0); +} + + +void +_zip_string_free(zip_string_t *s) { + if (s == NULL) + return; + + free(s->raw); + free(s->converted); + free(s); +} + + +const zip_uint8_t * +_zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip_error_t *error) { + static const zip_uint8_t empty[1] = ""; + + if (string == NULL) { + if (lenp) + *lenp = 0; + return empty; + } + + if ((flags & ZIP_FL_ENC_RAW) == 0) { + /* start guessing */ + if (string->encoding == ZIP_ENCODING_UNKNOWN) + _zip_guess_encoding(string, ZIP_ENCODING_UNKNOWN); + + if (((flags & ZIP_FL_ENC_STRICT) && string->encoding != ZIP_ENCODING_ASCII && string->encoding != ZIP_ENCODING_UTF8_KNOWN) || (string->encoding == ZIP_ENCODING_CP437)) { + if (string->converted == NULL) { + if ((string->converted = _zip_cp437_to_utf8(string->raw, string->length, &string->converted_length, error)) == NULL) + return NULL; + } + if (lenp) + *lenp = string->converted_length; + return string->converted; + } + } + + if (lenp) + *lenp = string->length; + return string->raw; +} + + +zip_uint16_t +_zip_string_length(const zip_string_t *s) { + if (s == NULL) + return 0; + + return s->length; +} + + +zip_string_t * +_zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, zip_error_t *error) { + zip_string_t *s; + zip_encoding_type_t expected_encoding; + + if (length == 0) + return NULL; + + switch (flags & ZIP_FL_ENCODING_ALL) { + case ZIP_FL_ENC_GUESS: + expected_encoding = ZIP_ENCODING_UNKNOWN; + break; + case ZIP_FL_ENC_UTF_8: + expected_encoding = ZIP_ENCODING_UTF8_KNOWN; + break; + case ZIP_FL_ENC_CP437: + expected_encoding = ZIP_ENCODING_CP437; + break; + default: + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((s = (zip_string_t *)malloc(sizeof(*s))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((s->raw = (zip_uint8_t *)malloc((size_t)length + 1)) == NULL) { + free(s); + return NULL; + } + + (void)memcpy_s(s->raw, length + 1, raw, length); + s->raw[length] = '\0'; + s->length = length; + s->encoding = ZIP_ENCODING_UNKNOWN; + s->converted = NULL; + s->converted_length = 0; + + if (expected_encoding != ZIP_ENCODING_UNKNOWN) { + if (_zip_guess_encoding(s, expected_encoding) == ZIP_ENCODING_ERROR) { + _zip_string_free(s); + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + } + + return s; +} + + +int +_zip_string_write(zip_t *za, const zip_string_t *s) { + if (s == NULL) + return 0; + + return _zip_write(za, s->raw, s->length); +} diff --git a/3rdparty/libzip/lib/zip_unchange.c b/3rdparty/libzip/lib/zip_unchange.c new file mode 100644 index 0000000000..d69a3dfe17 --- /dev/null +++ b/3rdparty/libzip/lib/zip_unchange.c @@ -0,0 +1,98 @@ +/* + zip_unchange.c -- undo changes to file in zip archive + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_unchange(zip_t *za, zip_uint64_t idx) { + return _zip_unchange(za, idx, 0); +} + + +int +_zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates) { + zip_int64_t i; + bool renamed; + + if (idx >= za->nentry) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return -1; + } + + renamed = za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME); + if (!allow_duplicates && (renamed || za->entry[idx].deleted)) { + const char *orig_name = NULL; + const char *changed_name = NULL; + + if (za->entry[idx].orig != NULL) { + if ((orig_name = _zip_get_name(za, idx, ZIP_FL_UNCHANGED, &za->error)) == NULL) { + return -1; + } + + i = _zip_name_locate(za, orig_name, 0, NULL); + if (i >= 0 && (zip_uint64_t)i != idx) { + zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; + } + } + + if (renamed) { + if ((changed_name = _zip_get_name(za, idx, 0, &za->error)) == NULL) { + return -1; + } + } + + if (orig_name) { + if (_zip_hash_add(za->names, (const zip_uint8_t *)orig_name, idx, 0, &za->error) == false) { + return -1; + } + } + if (changed_name) { + if (_zip_hash_delete(za->names, (const zip_uint8_t *)changed_name, &za->error) == false) { + _zip_hash_delete(za->names, (const zip_uint8_t *)orig_name, NULL); + return -1; + } + } + } + + _zip_dirent_free(za->entry[idx].changes); + za->entry[idx].changes = NULL; + + _zip_unchange_data(za->entry + idx); + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_unchange_all.c b/3rdparty/libzip/lib/zip_unchange_all.c new file mode 100644 index 0000000000..34f3702e07 --- /dev/null +++ b/3rdparty/libzip/lib/zip_unchange_all.c @@ -0,0 +1,54 @@ +/* + zip_unchange.c -- undo changes to all files in zip archive + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + + +ZIP_EXTERN int +zip_unchange_all(zip_t *za) { + int ret; + zip_uint64_t i; + + if (!_zip_hash_revert(za->names, &za->error)) { + return -1; + } + + ret = 0; + for (i = 0; i < za->nentry; i++) + ret |= _zip_unchange(za, i, 1); + + ret |= zip_unchange_archive(za); + + return ret; +} diff --git a/3rdparty/libzip/lib/zip_unchange_archive.c b/3rdparty/libzip/lib/zip_unchange_archive.c new file mode 100644 index 0000000000..56a8e31f60 --- /dev/null +++ b/3rdparty/libzip/lib/zip_unchange_archive.c @@ -0,0 +1,51 @@ +/* + zip_unchange_archive.c -- undo global changes to ZIP archive + Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include + +#include "zipint.h" + + +ZIP_EXTERN int +zip_unchange_archive(zip_t *za) { + if (za->comment_changed) { + _zip_string_free(za->comment_changes); + za->comment_changes = NULL; + za->comment_changed = 0; + } + + za->ch_flags = za->flags; + + return 0; +} diff --git a/3rdparty/libzip/lib/zip_unchange_data.c b/3rdparty/libzip/lib/zip_unchange_data.c new file mode 100644 index 0000000000..6bdecd1872 --- /dev/null +++ b/3rdparty/libzip/lib/zip_unchange_data.c @@ -0,0 +1,53 @@ +/* + zip_unchange_data.c -- undo helper function + Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +void +_zip_unchange_data(zip_entry_t *ze) { + if (ze->source) { + zip_source_free(ze->source); + ze->source = NULL; + } + + if (ze->changes != NULL && (ze->changes->changed & ZIP_DIRENT_COMP_METHOD) && ze->changes->comp_method == ZIP_CM_REPLACED_DEFAULT) { + ze->changes->changed &= ~ZIP_DIRENT_COMP_METHOD; + if (ze->changes->changed == 0) { + _zip_dirent_free(ze->changes); + ze->changes = NULL; + } + } + + ze->deleted = 0; +} diff --git a/3rdparty/libzip/lib/zip_utf-8.c b/3rdparty/libzip/lib/zip_utf-8.c new file mode 100644 index 0000000000..678912f6b4 --- /dev/null +++ b/3rdparty/libzip/lib/zip_utf-8.c @@ -0,0 +1,226 @@ +/* + zip_utf-8.c -- UTF-8 support functions for libzip + Copyright (C) 2011-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "zipint.h" + +#include + + +static const zip_uint16_t _cp437_to_unicode[256] = { + /* 0x00 - 0x0F */ + 0x0000, 0x263A, 0x263B, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 0x25D8, 0x25CB, 0x25D9, 0x2642, 0x2640, 0x266A, 0x266B, 0x263C, + + /* 0x10 - 0x1F */ + 0x25BA, 0x25C4, 0x2195, 0x203C, 0x00B6, 0x00A7, 0x25AC, 0x21A8, 0x2191, 0x2193, 0x2192, 0x2190, 0x221F, 0x2194, 0x25B2, 0x25BC, + + /* 0x20 - 0x2F */ + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + + /* 0x30 - 0x3F */ + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + + /* 0x40 - 0x4F */ + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + + /* 0x50 - 0x5F */ + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + + /* 0x60 - 0x6F */ + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + + /* 0x70 - 0x7F */ + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x2302, + + /* 0x80 - 0x8F */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + + /* 0x90 - 0x9F */ + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + + /* 0xA0 - 0xAF */ + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + + /* 0xB0 - 0xBF */ + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + + /* 0xC0 - 0xCF */ + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + + /* 0xD0 - 0xDF */ + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + + /* 0xE0 - 0xEF */ + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + + /* 0xF0 - 0xFF */ + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0}; + +#define UTF_8_LEN_2_MASK 0xe0 +#define UTF_8_LEN_2_MATCH 0xc0 +#define UTF_8_LEN_3_MASK 0xf0 +#define UTF_8_LEN_3_MATCH 0xe0 +#define UTF_8_LEN_4_MASK 0xf8 +#define UTF_8_LEN_4_MATCH 0xf0 +#define UTF_8_CONTINUE_MASK 0xc0 +#define UTF_8_CONTINUE_MATCH 0x80 + + +zip_encoding_type_t +_zip_guess_encoding(zip_string_t *str, zip_encoding_type_t expected_encoding) { + zip_encoding_type_t enc; + const zip_uint8_t *name; + zip_uint32_t i, j, ulen; + + if (str == NULL) + return ZIP_ENCODING_ASCII; + + name = str->raw; + + if (str->encoding != ZIP_ENCODING_UNKNOWN) + enc = str->encoding; + else { + enc = ZIP_ENCODING_ASCII; + for (i = 0; i < str->length; i++) { + if ((name[i] > 31 && name[i] < 128) || name[i] == '\r' || name[i] == '\n' || name[i] == '\t') + continue; + + enc = ZIP_ENCODING_UTF8_GUESSED; + if ((name[i] & UTF_8_LEN_2_MASK) == UTF_8_LEN_2_MATCH) + ulen = 1; + else if ((name[i] & UTF_8_LEN_3_MASK) == UTF_8_LEN_3_MATCH) + ulen = 2; + else if ((name[i] & UTF_8_LEN_4_MASK) == UTF_8_LEN_4_MATCH) + ulen = 3; + else { + enc = ZIP_ENCODING_CP437; + break; + } + + if (i + ulen >= str->length) { + enc = ZIP_ENCODING_CP437; + break; + } + + for (j = 1; j <= ulen; j++) { + if ((name[i + j] & UTF_8_CONTINUE_MASK) != UTF_8_CONTINUE_MATCH) { + enc = ZIP_ENCODING_CP437; + goto done; + } + } + i += ulen; + } + } + +done: + str->encoding = enc; + + if (expected_encoding != ZIP_ENCODING_UNKNOWN) { + if (expected_encoding == ZIP_ENCODING_UTF8_KNOWN && enc == ZIP_ENCODING_UTF8_GUESSED) + str->encoding = enc = ZIP_ENCODING_UTF8_KNOWN; + + if (expected_encoding != enc && enc != ZIP_ENCODING_ASCII) + return ZIP_ENCODING_ERROR; + } + + return enc; +} + + +static zip_uint32_t +_zip_unicode_to_utf8_len(zip_uint32_t codepoint) { + if (codepoint < 0x0080) + return 1; + if (codepoint < 0x0800) + return 2; + if (codepoint < 0x10000) + return 3; + return 4; +} + + +static zip_uint32_t +_zip_unicode_to_utf8(zip_uint32_t codepoint, zip_uint8_t *buf) { + if (codepoint < 0x0080) { + buf[0] = codepoint & 0xff; + return 1; + } + if (codepoint < 0x0800) { + buf[0] = (zip_uint8_t)(UTF_8_LEN_2_MATCH | ((codepoint >> 6) & 0x1f)); + buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f)); + return 2; + } + if (codepoint < 0x10000) { + buf[0] = (zip_uint8_t)(UTF_8_LEN_3_MATCH | ((codepoint >> 12) & 0x0f)); + buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f)); + buf[2] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f)); + return 3; + } + buf[0] = (zip_uint8_t)(UTF_8_LEN_4_MATCH | ((codepoint >> 18) & 0x07)); + buf[1] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 12) & 0x3f)); + buf[2] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | ((codepoint >> 6) & 0x3f)); + buf[3] = (zip_uint8_t)(UTF_8_CONTINUE_MATCH | (codepoint & 0x3f)); + return 4; +} + + +zip_uint8_t * +_zip_cp437_to_utf8(const zip_uint8_t *const _cp437buf, zip_uint32_t len, zip_uint32_t *utf8_lenp, zip_error_t *error) { + zip_uint8_t *cp437buf = (zip_uint8_t *)_cp437buf; + zip_uint8_t *utf8buf; + zip_uint32_t buflen, i, offset; + + if (len == 0) { + if (utf8_lenp) + *utf8_lenp = 0; + return NULL; + } + + buflen = 1; + for (i = 0; i < len; i++) + buflen += _zip_unicode_to_utf8_len(_cp437_to_unicode[cp437buf[i]]); + + if ((utf8buf = (zip_uint8_t *)malloc(buflen)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + offset = 0; + for (i = 0; i < len; i++) + offset += _zip_unicode_to_utf8(_cp437_to_unicode[cp437buf[i]], utf8buf + offset); + + utf8buf[buflen - 1] = 0; + if (utf8_lenp) + *utf8_lenp = buflen - 1; + return utf8buf; +} diff --git a/3rdparty/libzip/lib/zip_winzip_aes.c b/3rdparty/libzip/lib/zip_winzip_aes.c new file mode 100644 index 0000000000..ce269036cf --- /dev/null +++ b/3rdparty/libzip/lib/zip_winzip_aes.c @@ -0,0 +1,162 @@ +/* + zip_winzip_aes.c -- Winzip AES de/encryption backend routines + Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include "zip_crypto.h" + +#include +#include + + +#define MAX_KEY_LENGTH 256 +#define PBKDF2_ITERATIONS 1000 + +struct _zip_winzip_aes { + _zip_crypto_aes_t *aes; + _zip_crypto_hmac_t *hmac; + zip_uint8_t counter[ZIP_CRYPTO_AES_BLOCK_LENGTH]; + zip_uint8_t pad[ZIP_CRYPTO_AES_BLOCK_LENGTH]; + int pad_offset; +}; + +static bool +aes_crypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length) { + zip_uint64_t i, j; + + for (i = 0; i < length; i++) { + if (ctx->pad_offset == AES_BLOCK_SIZE) { + for (j = 0; j < 8; j++) { + ctx->counter[j]++; + if (ctx->counter[j] != 0) { + break; + } + } + if (!_zip_crypto_aes_encrypt_block(ctx->aes, ctx->counter, ctx->pad)) { + return false; + } + ctx->pad_offset = 0; + } + data[i] ^= ctx->pad[ctx->pad_offset++]; + } + + return true; +} + + +zip_winzip_aes_t * +_zip_winzip_aes_new(const zip_uint8_t *password, zip_uint64_t password_length, const zip_uint8_t *salt, zip_uint16_t encryption_method, zip_uint8_t *password_verify, zip_error_t *error) { + zip_winzip_aes_t *ctx; + zip_uint8_t buffer[2 * (MAX_KEY_LENGTH / 8) + WINZIP_AES_PASSWORD_VERIFY_LENGTH]; + zip_uint16_t key_size = 0; /* in bits */ + zip_uint16_t key_length; /* in bytes */ + + switch (encryption_method) { + case ZIP_EM_AES_128: + key_size = 128; + break; + case ZIP_EM_AES_192: + key_size = 192; + break; + case ZIP_EM_AES_256: + key_size = 256; + break; + } + + if (key_size == 0 || salt == NULL || password == NULL || password_length == 0) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + key_length = key_size / 8; + + if ((ctx = (zip_winzip_aes_t *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + memset(ctx->counter, 0, sizeof(ctx->counter)); + ctx->pad_offset = ZIP_CRYPTO_AES_BLOCK_LENGTH; + + if (!_zip_crypto_pbkdf2(password, password_length, salt, key_length / 2, PBKDF2_ITERATIONS, buffer, 2 * key_length + WINZIP_AES_PASSWORD_VERIFY_LENGTH)) { + free(ctx); + return NULL; + } + + if ((ctx->aes = _zip_crypto_aes_new(buffer, key_size, error)) == NULL) { + _zip_crypto_clear(ctx, sizeof(*ctx)); + free(ctx); + return NULL; + } + if ((ctx->hmac = _zip_crypto_hmac_new(buffer + key_length, key_length, error)) == NULL) { + _zip_crypto_aes_free(ctx->aes); + free(ctx); + return NULL; + } + + if (password_verify) { + (void)memcpy_s(password_verify, WINZIP_AES_PASSWORD_VERIFY_LENGTH, buffer + (2 * key_size / 8), WINZIP_AES_PASSWORD_VERIFY_LENGTH); + } + + return ctx; +} + + +bool +_zip_winzip_aes_encrypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length) { + return aes_crypt(ctx, data, length) && _zip_crypto_hmac(ctx->hmac, data, length); +} + + +bool +_zip_winzip_aes_decrypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length) { + return _zip_crypto_hmac(ctx->hmac, data, length) && aes_crypt(ctx, data, length); +} + + +bool +_zip_winzip_aes_finish(zip_winzip_aes_t *ctx, zip_uint8_t *hmac) { + return _zip_crypto_hmac_output(ctx->hmac, hmac); +} + + +void +_zip_winzip_aes_free(zip_winzip_aes_t *ctx) { + if (ctx == NULL) { + return; + } + + _zip_crypto_aes_free(ctx->aes); + _zip_crypto_hmac_free(ctx->hmac); + free(ctx); +} diff --git a/3rdparty/libzip/lib/zipint.h b/3rdparty/libzip/lib/zipint.h new file mode 100644 index 0000000000..4887b6c5c8 --- /dev/null +++ b/3rdparty/libzip/lib/zipint.h @@ -0,0 +1,655 @@ +#ifndef _HAD_ZIPINT_H +#define _HAD_ZIPINT_H + +/* + zipint.h -- internal declarations. + Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "config.h" + +#include "compat.h" + +#ifdef ZIP_ALLOCATE_BUFFER +#include +#endif + +#ifdef _ZIP_COMPILING_DEPRECATED +#define ZIP_DEPRECATED(x) +#else +#define ZIP_DISABLE_DEPRECATED +#endif + +#include "zip.h" + +#define CENTRAL_MAGIC "PK\1\2" +#define LOCAL_MAGIC "PK\3\4" +#define EOCD_MAGIC "PK\5\6" +#define DATADES_MAGIC "PK\7\10" +#define EOCD64LOC_MAGIC "PK\6\7" +#define EOCD64_MAGIC "PK\6\6" +#define CDENTRYSIZE 46u +#define LENTRYSIZE 30 +#define MAXCOMLEN 65536 +#define MAXEXTLEN 65536 +#define EOCDLEN 22 +#define EOCD64LOCLEN 20 +#define EOCD64LEN 56 +#define CDBUFSIZE (MAXCOMLEN + EOCDLEN + EOCD64LOCLEN) +#define BUFSIZE 8192 +#define EFZIP64SIZE 28 +#define EF_WINZIP_AES_SIZE 7 +#define MAX_DATA_DESCRIPTOR_LENGTH 24 + +#define TORRENTZIP_SIGNATURE "TORRENTZIPPED-" +#define TORRENTZIP_SIGNATURE_LENGTH 14 +#define TORRENTZIP_CRC_LENGTH 8 +#define TORRENTZIP_MEM_LEVEL 8 +#define TORRENTZIP_COMPRESSION_FLAGS ZIP_UINT16_MAX + +#define ZIP_CRYPTO_PKWARE_HEADERLEN 12 + +#define ZIP_CM_REPLACED_DEFAULT (-2) +#define ZIP_CM_WINZIP_AES 99 /* Winzip AES encrypted */ + +#define WINZIP_AES_PASSWORD_VERIFY_LENGTH 2 +#define WINZIP_AES_MAX_HEADER_LENGTH (16 + WINZIP_AES_PASSWORD_VERIFY_LENGTH) +#define AES_BLOCK_SIZE 16 +#define HMAC_LENGTH 10 +#define SALT_LENGTH(method) ((method) == ZIP_EM_AES_128 ? 8 : ((method) == ZIP_EM_AES_192 ? 12 : 16)) + +#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_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) +/* according to unzip-6.0's zipinfo.c, this corresponds to a directory with rwx permissions for everyone */ +#define ZIP_EXT_ATTRIB_DEFAULT_DIR (0040777u << 16) + +#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK 0x0836 + +#define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b)) +#define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b)) + +/* This section contains API that won't materialize like this. It's + placed in the internal section, pending cleanup. */ + +/* flags for compression and encryption sources */ + +#define ZIP_CODEC_DECODE 0 /* decompress/decrypt (encode flag not set) */ +#define ZIP_CODEC_ENCODE 1 /* compress/encrypt */ + +typedef zip_source_t *(*zip_encryption_implementation)(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); + +zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t method, int operation); + +/* clang-format off */ +enum zip_compression_status { + ZIP_COMPRESSION_OK, + ZIP_COMPRESSION_END, + ZIP_COMPRESSION_ERROR, + ZIP_COMPRESSION_NEED_DATA +}; +/* clang-format on */ +typedef enum zip_compression_status zip_compression_status_t; + +struct zip_compression_algorithm { + /* Return maximum compressed size for uncompressed data of given size. */ + zip_uint64_t (*maximum_compressed_size)(zip_uint64_t uncompressed_size); + + /* called once to create new context */ + void *(*allocate)(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error); + /* called once to free context */ + void (*deallocate)(void *ctx); + + /* get compression specific general purpose bitflags */ + zip_uint16_t (*general_purpose_bit_flags)(void *ctx); + /* minimum version needed when using this algorithm */ + zip_uint8_t version_needed; + + /* start processing */ + bool (*start)(void *ctx, zip_stat_t *st, zip_file_attributes_t *attributes); + /* 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; +extern zip_compression_algorithm_t zip_algorithm_xz_compress; +extern zip_compression_algorithm_t zip_algorithm_xz_decompress; +extern zip_compression_algorithm_t zip_algorithm_zstd_compress; +extern zip_compression_algorithm_t zip_algorithm_zstd_decompress; + +zip_compression_algorithm_t *_zip_get_compression_algorithm(zip_int32_t method, bool compress); + +/* This API is not final yet, but we need it internally, so it's private for now. */ + +const zip_uint8_t *zip_get_extra_field_by_id(zip_t *, int, int, zip_uint16_t, int, zip_uint16_t *); + +/* This section contains API that is of limited use until support for + user-supplied compression/encryption implementation is finished. + Thus we will keep it private for now. */ + +zip_source_t *zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t cm, zip_uint32_t compression_flags); +zip_source_t *zip_source_crc_create(zip_source_t *, int, zip_error_t *error); +zip_source_t *zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t cm); +zip_source_t *zip_source_pkware_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); +zip_source_t *zip_source_pkware_encode(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); +bool zip_source_supports_reopen(zip_source_t *src); +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 *); +zip_source_t *zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes); +zip_source_t *zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error); + +/* error source for layered sources */ + +enum zip_les { ZIP_LES_NONE, ZIP_LES_UPPER, ZIP_LES_LOWER, ZIP_LES_INVAL }; + +#define ZIP_DETAIL_ET_GLOBAL 0 +#define ZIP_DETAIL_ET_ENTRY 1 + +struct _zip_err_info { + int type; + const char *description; +}; + +extern const struct _zip_err_info _zip_err_str[]; +extern const int _zip_err_str_count; +extern const struct _zip_err_info _zip_err_details[]; +extern const int _zip_err_details_count; + +/* macros for libzip-internal errors */ +#define MAX_DETAIL_INDEX 0x7fffff +#define MAKE_DETAIL_WITH_INDEX(error, index) ((((index) > MAX_DETAIL_INDEX) ? MAX_DETAIL_INDEX : (int)(index)) << 8 | (error)) +#define GET_INDEX_FROM_DETAIL(error) (((error) >> 8) & MAX_DETAIL_INDEX) +#define GET_ERROR_FROM_DETAIL(error) ((error) & 0xff) +#define ADD_INDEX_TO_DETAIL(error, index) MAKE_DETAIL_WITH_INDEX(GET_ERROR_FROM_DETAIL(error), (index)) + +/* error code for libzip-internal errors */ +#define ZIP_ER_DETAIL_NO_DETAIL 0 /* G no detail */ +#define ZIP_ER_DETAIL_CDIR_OVERLAPS_EOCD 1 /* G central directory overlaps EOCD, or there is space between them */ +#define ZIP_ER_DETAIL_COMMENT_LENGTH_INVALID 2 /* G archive comment length incorrect */ +#define ZIP_ER_DETAIL_CDIR_LENGTH_INVALID 3 /* G central directory length invalid */ +#define ZIP_ER_DETAIL_CDIR_ENTRY_INVALID 4 /* E central header invalid */ +#define ZIP_ER_DETAIL_CDIR_WRONG_ENTRIES_COUNT 5 /* G central directory count of entries is incorrect */ +#define ZIP_ER_DETAIL_ENTRY_HEADER_MISMATCH 6 /* E local and central headers do not match */ +#define ZIP_ER_DETAIL_EOCD_LENGTH_INVALID 7 /* G wrong EOCD length */ +#define ZIP_ER_DETAIL_EOCD64_OVERLAPS_EOCD 8 /* G EOCD64 overlaps EOCD, or there is space between them */ +#define ZIP_ER_DETAIL_EOCD64_WRONG_MAGIC 9 /* G EOCD64 magic incorrect */ +#define ZIP_ER_DETAIL_EOCD64_MISMATCH 10 /* G EOCD64 and EOCD do not match */ +#define ZIP_ER_DETAIL_CDIR_INVALID 11 /* G invalid value in central directory */ +#define ZIP_ER_DETAIL_VARIABLE_SIZE_OVERFLOW 12 /* E variable size fields overflow header */ +#define ZIP_ER_DETAIL_INVALID_UTF8_IN_FILENAME 13 /* E invalid UTF-8 in filename */ +#define ZIP_ER_DETAIL_INVALID_UTF8_IN_COMMENT 13 /* E invalid UTF-8 in comment */ +#define ZIP_ER_DETAIL_INVALID_ZIP64_EF 14 /* E invalid Zip64 extra field */ +#define ZIP_ER_DETAIL_INVALID_WINZIPAES_EF 14 /* E invalid WinZip AES extra field */ +#define ZIP_ER_DETAIL_EF_TRAILING_GARBAGE 15 /* E garbage at end of extra fields */ +#define ZIP_ER_DETAIL_INVALID_EF_LENGTH 16 /* E extra field length is invalid */ +#define ZIP_ER_DETAIL_INVALID_FILE_LENGTH 17 /* E file length in header doesn't match actual file length */ + +/* directory entry: general purpose bit flags */ + +#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 */ +#define ZIP_EF_LOCAL ZIP_FL_LOCAL /* include in local header */ +#define ZIP_EF_CENTRAL ZIP_FL_CENTRAL /* include in central directory */ +#define ZIP_EF_BOTH (ZIP_EF_LOCAL | ZIP_EF_CENTRAL) /* include in both */ + +#define ZIP_FL_FORCE_ZIP64 1024 /* force zip64 extra field (_zip_dirent_write) */ + +#define ZIP_FL_ENCODING_ALL (ZIP_FL_ENC_GUESS | ZIP_FL_ENC_CP437 | ZIP_FL_ENC_UTF_8) + + +/* encoding type */ +enum zip_encoding_type { + ZIP_ENCODING_UNKNOWN, /* not yet analyzed */ + ZIP_ENCODING_ASCII, /* plain ASCII */ + ZIP_ENCODING_UTF8_KNOWN, /* is UTF-8 */ + ZIP_ENCODING_UTF8_GUESSED, /* possibly UTF-8 */ + ZIP_ENCODING_CP437, /* Code Page 437 */ + ZIP_ENCODING_ERROR /* should be UTF-8 but isn't */ +}; + +typedef enum zip_encoding_type zip_encoding_type_t; + +struct zip_hash; +struct zip_progress; + +typedef struct zip_cdir zip_cdir_t; +typedef struct zip_dirent zip_dirent_t; +typedef struct zip_entry zip_entry_t; +typedef struct zip_extra_field zip_extra_field_t; +typedef struct zip_string zip_string_t; +typedef struct zip_buffer zip_buffer_t; +typedef struct zip_hash zip_hash_t; +typedef struct zip_progress zip_progress_t; + +/* zip archive, part of API */ + +struct zip { + zip_source_t *src; /* data source for archive */ + unsigned int open_flags; /* flags passed to zip_open */ + zip_error_t error; /* error information */ + + unsigned int flags; /* archive global flags */ + unsigned int ch_flags; /* changed archive global flags */ + + char *default_password; /* password used when no other supplied */ + + zip_string_t *comment_orig; /* archive comment */ + zip_string_t *comment_changes; /* changed archive comment */ + bool comment_changed; /* whether archive comment was changed */ + + zip_uint64_t nentry; /* number of entries */ + zip_uint64_t nentry_alloc; /* number of entries allocated */ + zip_entry_t *entry; /* entries */ + + unsigned int nopen_source; /* number of open sources using archive */ + unsigned int nopen_source_alloc; /* number of sources allocated */ + zip_source_t **open_source; /* open sources using archive */ + + zip_hash_t *names; /* hash table for name lookup */ + + zip_progress_t *progress; /* progress callback for zip_close() */ + + zip_uint32_t* write_crc; /* have _zip_write() compute CRC */ +}; + +/* file in zip archive, part of API */ + +struct zip_file { + zip_error_t error; /* error information */ + zip_source_t *src; /* data source */ +}; + +/* 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_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 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 */ + zip_uint16_t bitflags; /* (cl) general purpose bit flag */ + zip_int32_t comp_method; /* (cl) compression method used (uint16 and ZIP_CM_DEFAULT (-1)) */ + time_t last_mod; /* (cl) time of last modification */ + zip_uint32_t crc; /* (cl) CRC-32 of uncompressed data */ + zip_uint64_t comp_size; /* (cl) size of compressed data */ + zip_uint64_t uncomp_size; /* (cl) size of uncompressed data */ + zip_string_t *filename; /* (cl) file name (NUL-terminated) */ + zip_extra_field_t *extra_fields; /* (cl) extra fields, parsed */ + zip_string_t *comment; /* (c) file comment */ + zip_uint32_t disk_number; /* (c) disk number start */ + 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_uint32_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 */ + +struct zip_cdir { + zip_entry_t *entry; /* directory entries */ + zip_uint64_t nentry; /* number of entries */ + zip_uint64_t nentry_alloc; /* number of entries allocated */ + + 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 { + zip_extra_field_t *next; + zip_flags_t flags; /* in local/central header */ + zip_uint16_t id; /* header id */ + zip_uint16_t size; /* data size */ + zip_uint8_t *data; +}; + +enum zip_source_write_state { + ZIP_SOURCE_WRITE_CLOSED, /* write is not in progress */ + ZIP_SOURCE_WRITE_OPEN, /* write is in progress */ + ZIP_SOURCE_WRITE_FAILED, /* commit failed, only rollback allowed */ + ZIP_SOURCE_WRITE_REMOVED /* file was removed */ +}; +typedef enum zip_source_write_state zip_source_write_state_t; + +struct zip_source { + zip_source_t *src; + union { + zip_source_callback f; + zip_source_layered_callback l; + } cb; + void *ud; + zip_error_t error; + zip_int64_t supports; /* supported commands */ + unsigned int open_count; /* number of times source was opened (directly or as lower layer) */ + zip_source_write_state_t write_state; /* whether source is open for writing */ + 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 */ + bool had_read_error; /* a previous ZIP_SOURCE_READ reported an error */ + zip_uint64_t bytes_read; /* for sources that don't support ZIP_SOURCE_TELL. */ +}; + +#define ZIP_SOURCE_IS_OPEN_READING(src) ((src)->open_count > 0) +#define ZIP_SOURCE_IS_OPEN_WRITING(src) ((src)->write_state == ZIP_SOURCE_WRITE_OPEN) +#define ZIP_SOURCE_IS_LAYERED(src) ((src)->src != NULL) + +/* entry in zip archive directory */ + +struct zip_entry { + zip_dirent_t *orig; + zip_dirent_t *changes; + zip_source_t *source; + bool deleted; +}; + + +/* file or archive comment, or filename */ + +struct zip_string { + zip_uint8_t *raw; /* raw string */ + zip_uint16_t length; /* length of raw string */ + enum zip_encoding_type encoding; /* autorecognized encoding */ + zip_uint8_t *converted; /* autoconverted string */ + zip_uint32_t converted_length; /* length of converted */ +}; + + +/* byte array */ + +/* For performance, we usually keep 8k byte arrays on the stack. + However, there are (embedded) systems with a stack size of 12k; + for those, use malloc()/free() */ + +#ifdef ZIP_ALLOCATE_BUFFER +#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t *buf +#define byte_array_init(buf, size) (((buf) = (zip_uint8_t *)malloc(size)) != NULL) +#define byte_array_fini(buf) (free(buf)) +#else +#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t buf[size] +#define byte_array_init(buf, size) (1) +#define byte_array_fini(buf) ((void)0) +#endif + + +/* bounds checked access to memory buffer */ + +struct zip_buffer { + bool ok; + bool free_data; + + zip_uint8_t *data; + zip_uint64_t size; + zip_uint64_t offset; +}; + +/* which files to write in which order */ + +struct zip_filelist { + zip_uint64_t idx; + const char *name; +}; + +typedef struct zip_filelist zip_filelist_t; + +struct _zip_winzip_aes; +typedef struct _zip_winzip_aes zip_winzip_aes_t; + +struct _zip_pkware_keys { + zip_uint32_t key[3]; +}; +typedef struct _zip_pkware_keys zip_pkware_keys_t; + +#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))) +#define ZIP_ENTRY_DATA_CHANGED(x) ((x)->source != NULL) +#define ZIP_ENTRY_HAS_CHANGES(e) (ZIP_ENTRY_DATA_CHANGED(e) || (e)->deleted || ZIP_ENTRY_CHANGED((e), ZIP_DIRENT_ALL)) + +#define ZIP_IS_RDONLY(za) ((za)->ch_flags & ZIP_AFL_RDONLY) +#define ZIP_IS_TORRENTZIP(za) ((za)->flags & ZIP_AFL_IS_TORRENTZIP) +#define ZIP_WANT_TORRENTZIP(za) ((za)->ch_flags & ZIP_AFL_WANT_TORRENTZIP) + + +#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 +#include +#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); +bool _zip_buffer_eof(zip_buffer_t *buffer); +void _zip_buffer_free(zip_buffer_t *buffer); +zip_uint8_t *_zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length); +zip_uint16_t _zip_buffer_get_16(zip_buffer_t *buffer); +zip_uint32_t _zip_buffer_get_32(zip_buffer_t *buffer); +zip_uint64_t _zip_buffer_get_64(zip_buffer_t *buffer); +zip_uint8_t _zip_buffer_get_8(zip_buffer_t *buffer); +zip_uint64_t _zip_buffer_left(zip_buffer_t *buffer); +zip_buffer_t *_zip_buffer_new(zip_uint8_t *data, zip_uint64_t size); +zip_buffer_t *_zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *buf, zip_error_t *error); +zip_uint64_t _zip_buffer_offset(zip_buffer_t *buffer); +bool _zip_buffer_ok(zip_buffer_t *buffer); +zip_uint8_t *_zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length); +int _zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length); +int _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i); +int _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i); +int _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i); +int _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i); +zip_uint64_t _zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length); +int _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length); +int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset); +zip_uint64_t _zip_buffer_size(zip_buffer_t *buffer); + +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); +time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t); +void _zip_deregister_source(zip_t *za, zip_source_t *src); + +void _zip_dirent_apply_attributes(zip_dirent_t *, zip_file_attributes_t *, bool, zip_uint32_t); +zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *); +void _zip_dirent_free(zip_dirent_t *); +void _zip_dirent_finalize(zip_dirent_t *); +void _zip_dirent_init(zip_dirent_t *); +bool _zip_dirent_needs_zip64(const zip_dirent_t *, zip_flags_t); +zip_dirent_t *_zip_dirent_new(void); +bool zip_dirent_process_ef_zip64(zip_dirent_t * zde, const zip_uint8_t * ef, zip_uint64_t got_len, bool local, zip_error_t * error); +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); +void zip_dirent_torrentzip_normalize(zip_dirent_t *de); + +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); + +zip_extra_field_t *_zip_ef_clone(const zip_extra_field_t *, zip_error_t *); +zip_extra_field_t *_zip_ef_delete_by_id(zip_extra_field_t *, zip_uint16_t, zip_uint16_t, zip_flags_t); +void _zip_ef_free(zip_extra_field_t *); +const zip_uint8_t *_zip_ef_get_by_id(const zip_extra_field_t *, zip_uint16_t *, zip_uint16_t, zip_uint16_t, zip_flags_t, zip_error_t *); +zip_extra_field_t *_zip_ef_merge(zip_extra_field_t *, zip_extra_field_t *); +zip_extra_field_t *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_flags_t); +bool _zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_extra_field_t **, zip_error_t *); +zip_extra_field_t *_zip_ef_remove_internal(zip_extra_field_t *); +zip_uint16_t _zip_ef_size(const zip_extra_field_t *, zip_flags_t); +int _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags); + +void _zip_entry_finalize(zip_entry_t *); +void _zip_entry_init(zip_entry_t *); + +void _zip_error_clear(zip_error_t *); +void _zip_error_get(const zip_error_t *, int *, int *); + +void _zip_error_copy(zip_error_t *dst, const zip_error_t *src); + +const zip_uint8_t *_zip_extract_extra_field_by_id(zip_error_t *, zip_uint16_t, int, const zip_uint8_t *, zip_uint16_t, zip_uint16_t *); + +int _zip_file_extra_field_prepare_for_change(zip_t *, zip_uint64_t); +int _zip_file_fillbuf(void *, size_t, zip_file_t *); +zip_uint64_t _zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error); +zip_uint64_t _zip_file_get_offset(const zip_t *, zip_uint64_t, zip_error_t *); + +zip_dirent_t *_zip_get_dirent(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *); + +enum zip_encoding_type _zip_guess_encoding(zip_string_t *, enum zip_encoding_type); +zip_uint8_t *_zip_cp437_to_utf8(const zip_uint8_t *const, zip_uint32_t, zip_uint32_t *, zip_error_t *); + +bool _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error); +bool _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *key, zip_error_t *error); +void _zip_hash_free(zip_hash_t *hash); +zip_int64_t _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error); +zip_hash_t *_zip_hash_new(zip_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); + +int _zip_mkstempm(char *path, int mode, bool create_file); + +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); +int _zip_progress_start(zip_progress_t *progress); +int _zip_progress_subrange(zip_progress_t *progress, double start, double end); +int _zip_progress_update(zip_progress_t *progress, double value); + +/* this symbol is extern so it can be overridden for regression testing */ +ZIP_EXTERN bool zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length); +zip_uint32_t zip_random_uint32(void); + +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); +int _zip_read_local_ef(zip_t *, zip_uint64_t); +zip_string_t *_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t length, bool nulp, zip_error_t *error); +int _zip_register_source(zip_t *za, zip_source_t *src); + +void _zip_set_open_error(int *zep, const zip_error_t *err, int ze); + +bool zip_source_accept_empty(zip_source_t *src); +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); +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_int64_t length, zip_stat_t *st, zip_uint64_t st_invalid, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, bool take_ownership, zip_error_t *error); + +int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error); +int _zip_string_equal(const zip_string_t *a, const zip_string_t *b); +void _zip_string_free(zip_string_t *string); +zip_uint32_t _zip_string_crc32(const zip_string_t *string); +const zip_uint8_t *_zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip_error_t *error); +zip_uint16_t _zip_string_length(const zip_string_t *string); +zip_string_t *_zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, zip_error_t *error); +int _zip_string_write(zip_t *za, const zip_string_t *string); +bool _zip_winzip_aes_decrypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length); +bool _zip_winzip_aes_encrypt(zip_winzip_aes_t *ctx, zip_uint8_t *data, zip_uint64_t length); +bool _zip_winzip_aes_finish(zip_winzip_aes_t *ctx, zip_uint8_t *hmac); +void _zip_winzip_aes_free(zip_winzip_aes_t *ctx); +zip_winzip_aes_t *_zip_winzip_aes_new(const zip_uint8_t *password, zip_uint64_t password_length, const zip_uint8_t *salt, zip_uint16_t key_size, zip_uint8_t *password_verify, zip_error_t *error); + +void _zip_pkware_encrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len); +void _zip_pkware_decrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len); +zip_pkware_keys_t *_zip_pkware_keys_new(zip_error_t *error); +void _zip_pkware_keys_free(zip_pkware_keys_t *keys); +void _zip_pkware_keys_reset(zip_pkware_keys_t *keys); + +int _zip_changed(const zip_t *, zip_uint64_t *); +const char *_zip_get_name(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *); +int _zip_local_header_read(zip_t *, int); +void *_zip_memdup(const void *, size_t, zip_error_t *); +zip_int64_t _zip_name_locate(zip_t *, const char *, zip_flags_t, zip_error_t *); +zip_t *_zip_new(zip_error_t *); + +zip_int64_t _zip_file_replace(zip_t *, zip_uint64_t, const char *, zip_source_t *, zip_flags_t); +int _zip_set_name(zip_t *, zip_uint64_t, const char *, zip_flags_t); +void _zip_u2d_time(time_t, zip_uint16_t *, zip_uint16_t *); +int _zip_unchange(zip_t *, zip_uint64_t, int); +void _zip_unchange_data(zip_entry_t *); +int _zip_write(zip_t *za, const void *data, zip_uint64_t length); + +#endif /* zipint.h */ diff --git a/3rdparty/libzip/libzip b/3rdparty/libzip/libzip deleted file mode 160000 index bdc03ab23b..0000000000 --- a/3rdparty/libzip/libzip +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bdc03ab23b703fcc516436d6ebcbfb6ac4484033 diff --git a/3rdparty/libzip/libzip.vcxproj b/3rdparty/libzip/libzip.vcxproj index 97fe04409d..58e2ec58b9 100644 --- a/3rdparty/libzip/libzip.vcxproj +++ b/3rdparty/libzip/libzip.vcxproj @@ -29,150 +29,146 @@ AllRules.ruleset - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {52244028-937a-44e9-a76b-2bea18fd239a} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ZIP_STATIC;%(PreprocessorDefinitions) TurnOffAllWarnings - $(SolutionDir)3rdparty\zstd\zstd\lib;$(SolutionDir)3rdparty\zlib;$(ProjectDir)private;$(ProjectDir)libzip\lib;$(ProjectDir);%(AdditionalIncludeDirectories) + $(SolutionDir)3rdparty\zstd\zstd\lib;$(SolutionDir)3rdparty\zlib;$(ProjectDir)msvc;$(ProjectDir)lib;%(AdditionalIncludeDirectories) diff --git a/3rdparty/libzip/libzip.vcxproj.filters b/3rdparty/libzip/libzip.vcxproj.filters index 7b7ef9e826..5efcda34ec 100644 --- a/3rdparty/libzip/libzip.vcxproj.filters +++ b/3rdparty/libzip/libzip.vcxproj.filters @@ -1,137 +1,133 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/3rdparty/libzip/private/config.h b/3rdparty/libzip/msvc/config.h similarity index 81% rename from 3rdparty/libzip/private/config.h rename to 3rdparty/libzip/msvc/config.h index 57faa67244..4284d435f1 100644 --- a/3rdparty/libzip/private/config.h +++ b/3rdparty/libzip/msvc/config.h @@ -4,6 +4,7 @@ #include "zipconf.h" #endif /* BEGIN DEFINES */ +#define ENABLE_FDOPEN /* #undef HAVE___PROGNAME */ #define HAVE__CLOSE #define HAVE__DUP @@ -11,16 +12,17 @@ #define HAVE__FILENO #define HAVE__SETMODE #define HAVE__SNPRINTF +#define HAVE__SNPRINTF_S +#define HAVE__SNWPRINTF_S #define HAVE__STRDUP #define HAVE__STRICMP #define HAVE__STRTOI64 #define HAVE__STRTOUI64 -/* #undef HAVE__UMASK */ #define HAVE__UNLINK /* #undef HAVE_ARC4RANDOM */ /* #undef HAVE_CLONEFILE */ /* #undef HAVE_COMMONCRYPTO */ -#define HAVE_CRYPTO +/* #undef HAVE_CRYPTO */ /* #undef HAVE_FICLONERANGE */ #define HAVE_FILENO /* #undef HAVE_FCHMOD */ @@ -32,22 +34,28 @@ /* #undef HAVE_LIBLZMA */ #define HAVE_LIBZSTD /* #undef HAVE_LOCALTIME_R */ +#define HAVE_LOCALTIME_S +#define HAVE_MEMCPY_S /* #undef HAVE_MBEDTLS */ /* #undef HAVE_MKSTEMP */ /* #undef HAVE_NULLABLE */ /* #undef HAVE_OPENSSL */ #define HAVE_SETMODE #define HAVE_SNPRINTF +/* #undef HAVE_SNPRINTF_S */ /* #undef HAVE_STRCASECMP */ #define HAVE_STRDUP +#define HAVE_STRERROR_S +/* #undef HAVE_STRERRORLEN_S */ #define HAVE_STRICMP +#define HAVE_STRNCPY_S #define HAVE_STRTOLL #define HAVE_STRTOULL /* #undef HAVE_STRUCT_TM_TM_ZONE */ #define HAVE_STDBOOL_H /* #undef HAVE_STRINGS_H */ /* #undef HAVE_UNISTD_H */ -#define HAVE_WINDOWS_CRYPTO +/* #undef HAVE_WINDOWS_CRYPTO */ #define SIZEOF_OFF_T 4 #define SIZEOF_SIZE_T 8 /* #undef HAVE_DIRENT_H */ @@ -56,9 +64,7 @@ /* #undef HAVE_SYS_DIR_H */ /* #undef HAVE_SYS_NDIR_H */ /* #undef WORDS_BIGENDIAN */ -#define HAVE_SHARED +/* #undef HAVE_SHARED */ /* END DEFINES */ -#define PACKAGE "libzip" -#define VERSION "1.8.0" #endif /* HAD_CONFIG_H */ diff --git a/3rdparty/libzip/private/zip_err_str.c b/3rdparty/libzip/msvc/zip_err_str.c similarity index 97% rename from 3rdparty/libzip/private/zip_err_str.c rename to 3rdparty/libzip/msvc/zip_err_str.c index c9b1504ecf..28af773bca 100644 --- a/3rdparty/libzip/private/zip_err_str.c +++ b/3rdparty/libzip/msvc/zip_err_str.c @@ -47,6 +47,8 @@ const struct _zip_err_info _zip_err_str[] = { { S, "Tell error" }, { N, "Compressed data invalid" }, { N, "Operation cancelled" }, + { N, "Unexpected length of data" }, + { N, "Not allowed in torrentzip" }, }; const int _zip_err_str_count = sizeof(_zip_err_str)/sizeof(_zip_err_str[0]); diff --git a/3rdparty/libzip/zipconf.h b/3rdparty/libzip/msvc/zipconf.h similarity index 90% rename from 3rdparty/libzip/zipconf.h rename to 3rdparty/libzip/msvc/zipconf.h index 7910affd01..41675b5bec 100644 --- a/3rdparty/libzip/zipconf.h +++ b/3rdparty/libzip/msvc/zipconf.h @@ -8,12 +8,12 @@ based on ../cmake-zipconf.h.in. */ -#define LIBZIP_VERSION "1.8.0" +#define LIBZIP_VERSION "1.10.1" #define LIBZIP_VERSION_MAJOR 1 -#define LIBZIP_VERSION_MINOR 8 -#define LIBZIP_VERSION_MICRO 0 +#define LIBZIP_VERSION_MINOR 10 +#define LIBZIP_VERSION_MICRO 1 -/* #undef ZIP_STATIC */ +#define ZIP_STATIC #define _Nullable #define _Nonnull diff --git a/cmake/BuildParameters.cmake b/cmake/BuildParameters.cmake index f9f496c4e2..cc967560e8 100644 --- a/cmake/BuildParameters.cmake +++ b/cmake/BuildParameters.cmake @@ -10,8 +10,6 @@ set(USE_SYSTEM_LIBS "AUTO" CACHE STRING "Use system libraries instead of bundled set(DEFAULT_USE_SYSTEM_RYML OFF) # System rapidyaml causes a lot of problems optional_system_library(fmt) optional_system_library(ryml) -optional_system_library(zstd) -optional_system_library(libzip) optional_system_library(SDL2) option(LTO_PCSX2_CORE "Enable LTO/IPO/LTCG on the subset of pcsx2 that benefits most from it but not anything else") option(USE_VTUNE "Plug VTUNE to profile GS JIT.") diff --git a/cmake/SearchForStuff.cmake b/cmake/SearchForStuff.cmake index 0f41dff76a..986a68bc1a 100644 --- a/cmake/SearchForStuff.cmake +++ b/cmake/SearchForStuff.cmake @@ -117,12 +117,6 @@ endif() find_optional_system_library(fmt 3rdparty/fmt/fmt 7.1.3) find_optional_system_library(ryml 3rdparty/rapidyaml/rapidyaml 0.4.0) -find_optional_system_library(zstd 3rdparty/zstd 1.4.5) -if (${zstd_TYPE} STREQUAL System) - alias_library(Zstd::Zstd zstd::libzstd_shared) - alias_library(pcsx2-zstd zstd::libzstd_shared) -endif() -find_optional_system_library(libzip 3rdparty/libzip 1.8.0) if(QT_BUILD) # Default to bundled Qt6 for Windows. @@ -183,6 +177,8 @@ add_subdirectory(3rdparty/simpleini EXCLUDE_FROM_ALL) add_subdirectory(3rdparty/imgui EXCLUDE_FROM_ALL) add_subdirectory(3rdparty/cpuinfo EXCLUDE_FROM_ALL) add_subdirectory(3rdparty/zydis EXCLUDE_FROM_ALL) +add_subdirectory(3rdparty/zstd EXCLUDE_FROM_ALL) +add_subdirectory(3rdparty/libzip EXCLUDE_FROM_ALL) if(USE_OPENGL) add_subdirectory(3rdparty/glad EXCLUDE_FROM_ALL) diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index d7ea5a60a2..d7eae8da06 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -629,7 +629,7 @@ if(USE_OPENGL) if(WIN32) list(APPEND pcsx2GSSources GS/Renderers/OpenGL/GLContextWGL.cpp) list(APPEND pcsx2GSHeaders GS/Renderers/OpenGL/GLContextWGL.h) - target_link_libraries(PCSX2_FLAGS INTERFACE opengl32.lib) + target_link_libraries(PCSX2_FLAGS INTERFACE opengl32.lib WinPixEventRuntime::WinPixEventRuntime) elseif(APPLE) list(APPEND pcsx2GSSources GS/Renderers/OpenGL/GLContextAGL.mm) list(APPEND pcsx2GSHeaders GS/Renderers/OpenGL/GLContextAGL.h) diff --git a/pcsx2/pcsx2.vcxproj b/pcsx2/pcsx2.vcxproj index 92748b70e4..6433f2e73b 100644 --- a/pcsx2/pcsx2.vcxproj +++ b/pcsx2/pcsx2.vcxproj @@ -45,7 +45,7 @@ %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\imgui\include %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\simpleini\include %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\sdl2\include;$(SolutionDir)3rdparty\sdl2\SDL\include - %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\libzip;$(SolutionDir)3rdparty\libzip\libzip\lib + %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\libzip\msvc;$(SolutionDir)3rdparty\libzip\lib %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\zstd\zstd\lib %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\cpuinfo\include %(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\rapidyaml\rapidyaml\src @@ -883,4 +883,4 @@ - \ No newline at end of file +