From 312fd151b6feaec7a7b54d8ff6cd5439a071d5c6 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 24 Aug 2023 12:03:10 +1000 Subject: [PATCH 1/4] 3rdparty/cpuinfo: Fix build with clang-cl --- 3rdparty/cpuinfo/src/cpuinfo/utils.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/3rdparty/cpuinfo/src/cpuinfo/utils.h b/3rdparty/cpuinfo/src/cpuinfo/utils.h index 157baad9ab9a1..d2aa731ebd3cf 100644 --- a/3rdparty/cpuinfo/src/cpuinfo/utils.h +++ b/3rdparty/cpuinfo/src/cpuinfo/utils.h @@ -2,6 +2,10 @@ #include +#ifdef _MSC_VER +#include // _BitScanReverse +#endif + inline static uint32_t bit_length(uint32_t n) { const uint32_t n_minus_1 = n - 1; From a8a4f7c18f3fdc8965c18f979e8fa9916e2b807e Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 24 Aug 2023 12:30:24 +1000 Subject: [PATCH 2/4] 3rdparty: Un-submodule libzip --- .gitmodules | 3 - 3rdparty/libzip/AUTHORS | 2 + 3rdparty/libzip/CMakeLists.txt | 409 +++++- 3rdparty/libzip/LICENSE | 31 + 3rdparty/libzip/cmake-config.h.in | 72 + 3rdparty/libzip/cmake-zipconf.h.in | 47 + 3rdparty/libzip/cmake/Findzstd.cmake | 186 +++ .../cmake/GenerateZipErrorStrings.cmake | 47 + 3rdparty/libzip/lib/CMakeLists.txt | 208 +++ 3rdparty/libzip/lib/compat.h | 240 ++++ 3rdparty/libzip/lib/zip.h | 517 +++++++ 3rdparty/libzip/lib/zip_add.c | 49 + 3rdparty/libzip/lib/zip_add_dir.c | 44 + 3rdparty/libzip/lib/zip_add_entry.c | 80 ++ 3rdparty/libzip/lib/zip_algorithm_bzip2.c | 293 ++++ 3rdparty/libzip/lib/zip_algorithm_deflate.c | 276 ++++ 3rdparty/libzip/lib/zip_algorithm_xz.c | 408 ++++++ 3rdparty/libzip/lib/zip_algorithm_zstd.c | 298 ++++ 3rdparty/libzip/lib/zip_buffer.c | 337 +++++ 3rdparty/libzip/lib/zip_close.c | 745 ++++++++++ 3rdparty/libzip/lib/zip_crypto.h | 54 + 3rdparty/libzip/lib/zip_crypto_commoncrypto.c | 110 ++ 3rdparty/libzip/lib/zip_crypto_commoncrypto.h | 53 + 3rdparty/libzip/lib/zip_crypto_gnutls.c | 134 ++ 3rdparty/libzip/lib/zip_crypto_gnutls.h | 68 + 3rdparty/libzip/lib/zip_crypto_mbedtls.c | 171 +++ 3rdparty/libzip/lib/zip_crypto_mbedtls.h | 56 + 3rdparty/libzip/lib/zip_crypto_openssl.c | 229 ++++ 3rdparty/libzip/lib/zip_crypto_openssl.h | 73 + 3rdparty/libzip/lib/zip_crypto_win.c | 495 +++++++ 3rdparty/libzip/lib/zip_crypto_win.h | 53 + 3rdparty/libzip/lib/zip_delete.c | 68 + 3rdparty/libzip/lib/zip_dir_add.c | 92 ++ 3rdparty/libzip/lib/zip_dirent.c | 1207 +++++++++++++++++ 3rdparty/libzip/lib/zip_discard.c | 80 ++ 3rdparty/libzip/lib/zip_entry.c | 51 + 3rdparty/libzip/lib/zip_error.c | 156 +++ 3rdparty/libzip/lib/zip_error_clear.c | 44 + 3rdparty/libzip/lib/zip_error_get.c | 54 + 3rdparty/libzip/lib/zip_error_get_sys_type.c | 45 + 3rdparty/libzip/lib/zip_error_strerror.c | 128 ++ 3rdparty/libzip/lib/zip_error_to_str.c | 58 + 3rdparty/libzip/lib/zip_extra_field.c | 427 ++++++ 3rdparty/libzip/lib/zip_extra_field_api.c | 367 +++++ 3rdparty/libzip/lib/zip_fclose.c | 54 + 3rdparty/libzip/lib/zip_fdopen.c | 91 ++ 3rdparty/libzip/lib/zip_file_add.c | 52 + 3rdparty/libzip/lib/zip_file_error_clear.c | 44 + 3rdparty/libzip/lib/zip_file_error_get.c | 41 + 3rdparty/libzip/lib/zip_file_get_comment.c | 55 + .../lib/zip_file_get_external_attributes.c | 50 + 3rdparty/libzip/lib/zip_file_get_offset.c | 117 ++ 3rdparty/libzip/lib/zip_file_rename.c | 67 + 3rdparty/libzip/lib/zip_file_replace.c | 105 ++ 3rdparty/libzip/lib/zip_file_set_comment.c | 105 ++ 3rdparty/libzip/lib/zip_file_set_encryption.c | 120 ++ .../lib/zip_file_set_external_attributes.c | 86 ++ 3rdparty/libzip/lib/zip_file_set_mtime.c | 77 ++ 3rdparty/libzip/lib/zip_file_strerror.c | 41 + 3rdparty/libzip/lib/zip_fopen.c | 46 + 3rdparty/libzip/lib/zip_fopen_encrypted.c | 46 + 3rdparty/libzip/lib/zip_fopen_index.c | 41 + .../libzip/lib/zip_fopen_index_encrypted.c | 85 ++ 3rdparty/libzip/lib/zip_fread.c | 63 + 3rdparty/libzip/lib/zip_fseek.c | 61 + 3rdparty/libzip/lib/zip_ftell.c | 54 + 3rdparty/libzip/lib/zip_get_archive_comment.c | 58 + 3rdparty/libzip/lib/zip_get_archive_flag.c | 45 + .../lib/zip_get_encryption_implementation.c | 62 + 3rdparty/libzip/lib/zip_get_file_comment.c | 50 + 3rdparty/libzip/lib/zip_get_name.c | 58 + 3rdparty/libzip/lib/zip_get_num_entries.c | 52 + 3rdparty/libzip/lib/zip_get_num_files.c | 51 + 3rdparty/libzip/lib/zip_hash.c | 410 ++++++ 3rdparty/libzip/lib/zip_io_util.c | 146 ++ 3rdparty/libzip/lib/zip_libzip_version.c | 41 + 3rdparty/libzip/lib/zip_memdup.c | 56 + 3rdparty/libzip/lib/zip_name_locate.c | 116 ++ 3rdparty/libzip/lib/zip_new.c | 73 + 3rdparty/libzip/lib/zip_open.c | 967 +++++++++++++ 3rdparty/libzip/lib/zip_pkware.c | 112 ++ 3rdparty/libzip/lib/zip_progress.c | 293 ++++ 3rdparty/libzip/lib/zip_random_unix.c | 110 ++ 3rdparty/libzip/lib/zip_random_uwp.c | 82 ++ 3rdparty/libzip/lib/zip_random_win32.c | 82 ++ 3rdparty/libzip/lib/zip_rename.c | 42 + 3rdparty/libzip/lib/zip_replace.c | 42 + 3rdparty/libzip/lib/zip_set_archive_comment.c | 84 ++ 3rdparty/libzip/lib/zip_set_archive_flag.c | 76 ++ .../libzip/lib/zip_set_default_password.c | 58 + 3rdparty/libzip/lib/zip_set_file_comment.c | 46 + .../libzip/lib/zip_set_file_compression.c | 95 ++ 3rdparty/libzip/lib/zip_set_name.c | 157 +++ 3rdparty/libzip/lib/zip_source_accept_empty.c | 52 + 3rdparty/libzip/lib/zip_source_begin_write.c | 57 + .../lib/zip_source_begin_write_cloning.c | 57 + 3rdparty/libzip/lib/zip_source_buffer.c | 643 +++++++++ 3rdparty/libzip/lib/zip_source_call.c | 68 + 3rdparty/libzip/lib/zip_source_close.c | 57 + 3rdparty/libzip/lib/zip_source_commit_write.c | 68 + 3rdparty/libzip/lib/zip_source_compress.c | 398 ++++++ 3rdparty/libzip/lib/zip_source_crc.c | 203 +++ 3rdparty/libzip/lib/zip_source_error.c | 46 + 3rdparty/libzip/lib/zip_source_file.h | 90 ++ 3rdparty/libzip/lib/zip_source_file_common.c | 388 ++++++ 3rdparty/libzip/lib/zip_source_file_stdio.c | 178 +++ 3rdparty/libzip/lib/zip_source_file_stdio.h | 45 + .../libzip/lib/zip_source_file_stdio_named.c | 392 ++++++ 3rdparty/libzip/lib/zip_source_file_win32.c | 234 ++++ 3rdparty/libzip/lib/zip_source_file_win32.h | 84 ++ .../libzip/lib/zip_source_file_win32_ansi.c | 87 ++ .../libzip/lib/zip_source_file_win32_named.c | 274 ++++ .../libzip/lib/zip_source_file_win32_utf16.c | 113 ++ .../libzip/lib/zip_source_file_win32_utf8.c | 73 + 3rdparty/libzip/lib/zip_source_free.c | 71 + 3rdparty/libzip/lib/zip_source_function.c | 99 ++ .../lib/zip_source_get_file_attributes.c | 108 ++ 3rdparty/libzip/lib/zip_source_is_deleted.c | 41 + 3rdparty/libzip/lib/zip_source_layered.c | 75 + 3rdparty/libzip/lib/zip_source_open.c | 76 ++ .../lib/zip_source_pass_to_lower_layer.c | 78 ++ .../libzip/lib/zip_source_pkware_decode.c | 219 +++ .../libzip/lib/zip_source_pkware_encode.c | 271 ++++ 3rdparty/libzip/lib/zip_source_read.c | 96 ++ 3rdparty/libzip/lib/zip_source_remove.c | 65 + .../libzip/lib/zip_source_rollback_write.c | 50 + 3rdparty/libzip/lib/zip_source_seek.c | 95 ++ 3rdparty/libzip/lib/zip_source_seek_write.c | 56 + 3rdparty/libzip/lib/zip_source_stat.c | 66 + 3rdparty/libzip/lib/zip_source_supports.c | 74 + 3rdparty/libzip/lib/zip_source_tell.c | 57 + 3rdparty/libzip/lib/zip_source_tell_write.c | 51 + 3rdparty/libzip/lib/zip_source_window.c | 357 +++++ .../libzip/lib/zip_source_winzip_aes_decode.c | 265 ++++ .../libzip/lib/zip_source_winzip_aes_encode.c | 253 ++++ 3rdparty/libzip/lib/zip_source_write.c | 46 + 3rdparty/libzip/lib/zip_source_zip.c | 63 + 3rdparty/libzip/lib/zip_source_zip_new.c | 312 +++++ 3rdparty/libzip/lib/zip_stat.c | 46 + 3rdparty/libzip/lib/zip_stat_index.c | 111 ++ 3rdparty/libzip/lib/zip_stat_init.c | 83 ++ 3rdparty/libzip/lib/zip_strerror.c | 41 + 3rdparty/libzip/lib/zip_string.c | 178 +++ 3rdparty/libzip/lib/zip_unchange.c | 98 ++ 3rdparty/libzip/lib/zip_unchange_all.c | 54 + 3rdparty/libzip/lib/zip_unchange_archive.c | 51 + 3rdparty/libzip/lib/zip_unchange_data.c | 53 + 3rdparty/libzip/lib/zip_utf-8.c | 226 +++ 3rdparty/libzip/lib/zip_winzip_aes.c | 162 +++ 3rdparty/libzip/lib/zipint.h | 655 +++++++++ 3rdparty/libzip/libzip | 1 - 3rdparty/libzip/libzip.vcxproj | 264 ++-- 3rdparty/libzip/libzip.vcxproj.filters | 256 ++-- 3rdparty/libzip/{private => msvc}/config.h | 18 +- .../libzip/{private => msvc}/zip_err_str.c | 2 + 3rdparty/libzip/{ => msvc}/zipconf.h | 8 +- cmake/BuildParameters.cmake | 2 - cmake/SearchForStuff.cmake | 8 +- pcsx2/CMakeLists.txt | 2 +- pcsx2/pcsx2.vcxproj | 4 +- 160 files changed, 22088 insertions(+), 316 deletions(-) create mode 100644 3rdparty/libzip/AUTHORS create mode 100644 3rdparty/libzip/LICENSE create mode 100644 3rdparty/libzip/cmake-config.h.in create mode 100644 3rdparty/libzip/cmake-zipconf.h.in create mode 100644 3rdparty/libzip/cmake/Findzstd.cmake create mode 100644 3rdparty/libzip/cmake/GenerateZipErrorStrings.cmake create mode 100644 3rdparty/libzip/lib/CMakeLists.txt create mode 100644 3rdparty/libzip/lib/compat.h create mode 100644 3rdparty/libzip/lib/zip.h create mode 100644 3rdparty/libzip/lib/zip_add.c create mode 100644 3rdparty/libzip/lib/zip_add_dir.c create mode 100644 3rdparty/libzip/lib/zip_add_entry.c create mode 100644 3rdparty/libzip/lib/zip_algorithm_bzip2.c create mode 100644 3rdparty/libzip/lib/zip_algorithm_deflate.c create mode 100644 3rdparty/libzip/lib/zip_algorithm_xz.c create mode 100644 3rdparty/libzip/lib/zip_algorithm_zstd.c create mode 100644 3rdparty/libzip/lib/zip_buffer.c create mode 100644 3rdparty/libzip/lib/zip_close.c create mode 100644 3rdparty/libzip/lib/zip_crypto.h create mode 100644 3rdparty/libzip/lib/zip_crypto_commoncrypto.c create mode 100644 3rdparty/libzip/lib/zip_crypto_commoncrypto.h create mode 100644 3rdparty/libzip/lib/zip_crypto_gnutls.c create mode 100644 3rdparty/libzip/lib/zip_crypto_gnutls.h create mode 100644 3rdparty/libzip/lib/zip_crypto_mbedtls.c create mode 100644 3rdparty/libzip/lib/zip_crypto_mbedtls.h create mode 100644 3rdparty/libzip/lib/zip_crypto_openssl.c create mode 100644 3rdparty/libzip/lib/zip_crypto_openssl.h create mode 100644 3rdparty/libzip/lib/zip_crypto_win.c create mode 100644 3rdparty/libzip/lib/zip_crypto_win.h create mode 100644 3rdparty/libzip/lib/zip_delete.c create mode 100644 3rdparty/libzip/lib/zip_dir_add.c create mode 100644 3rdparty/libzip/lib/zip_dirent.c create mode 100644 3rdparty/libzip/lib/zip_discard.c create mode 100644 3rdparty/libzip/lib/zip_entry.c create mode 100644 3rdparty/libzip/lib/zip_error.c create mode 100644 3rdparty/libzip/lib/zip_error_clear.c create mode 100644 3rdparty/libzip/lib/zip_error_get.c create mode 100644 3rdparty/libzip/lib/zip_error_get_sys_type.c create mode 100644 3rdparty/libzip/lib/zip_error_strerror.c create mode 100644 3rdparty/libzip/lib/zip_error_to_str.c create mode 100644 3rdparty/libzip/lib/zip_extra_field.c create mode 100644 3rdparty/libzip/lib/zip_extra_field_api.c create mode 100644 3rdparty/libzip/lib/zip_fclose.c create mode 100644 3rdparty/libzip/lib/zip_fdopen.c create mode 100644 3rdparty/libzip/lib/zip_file_add.c create mode 100644 3rdparty/libzip/lib/zip_file_error_clear.c create mode 100644 3rdparty/libzip/lib/zip_file_error_get.c create mode 100644 3rdparty/libzip/lib/zip_file_get_comment.c create mode 100644 3rdparty/libzip/lib/zip_file_get_external_attributes.c create mode 100644 3rdparty/libzip/lib/zip_file_get_offset.c create mode 100644 3rdparty/libzip/lib/zip_file_rename.c create mode 100644 3rdparty/libzip/lib/zip_file_replace.c create mode 100644 3rdparty/libzip/lib/zip_file_set_comment.c create mode 100644 3rdparty/libzip/lib/zip_file_set_encryption.c create mode 100644 3rdparty/libzip/lib/zip_file_set_external_attributes.c create mode 100644 3rdparty/libzip/lib/zip_file_set_mtime.c create mode 100644 3rdparty/libzip/lib/zip_file_strerror.c create mode 100644 3rdparty/libzip/lib/zip_fopen.c create mode 100644 3rdparty/libzip/lib/zip_fopen_encrypted.c create mode 100644 3rdparty/libzip/lib/zip_fopen_index.c create mode 100644 3rdparty/libzip/lib/zip_fopen_index_encrypted.c create mode 100644 3rdparty/libzip/lib/zip_fread.c create mode 100644 3rdparty/libzip/lib/zip_fseek.c create mode 100644 3rdparty/libzip/lib/zip_ftell.c create mode 100644 3rdparty/libzip/lib/zip_get_archive_comment.c create mode 100644 3rdparty/libzip/lib/zip_get_archive_flag.c create mode 100644 3rdparty/libzip/lib/zip_get_encryption_implementation.c create mode 100644 3rdparty/libzip/lib/zip_get_file_comment.c create mode 100644 3rdparty/libzip/lib/zip_get_name.c create mode 100644 3rdparty/libzip/lib/zip_get_num_entries.c create mode 100644 3rdparty/libzip/lib/zip_get_num_files.c create mode 100644 3rdparty/libzip/lib/zip_hash.c create mode 100644 3rdparty/libzip/lib/zip_io_util.c create mode 100644 3rdparty/libzip/lib/zip_libzip_version.c create mode 100644 3rdparty/libzip/lib/zip_memdup.c create mode 100644 3rdparty/libzip/lib/zip_name_locate.c create mode 100644 3rdparty/libzip/lib/zip_new.c create mode 100644 3rdparty/libzip/lib/zip_open.c create mode 100644 3rdparty/libzip/lib/zip_pkware.c create mode 100644 3rdparty/libzip/lib/zip_progress.c create mode 100644 3rdparty/libzip/lib/zip_random_unix.c create mode 100644 3rdparty/libzip/lib/zip_random_uwp.c create mode 100644 3rdparty/libzip/lib/zip_random_win32.c create mode 100644 3rdparty/libzip/lib/zip_rename.c create mode 100644 3rdparty/libzip/lib/zip_replace.c create mode 100644 3rdparty/libzip/lib/zip_set_archive_comment.c create mode 100644 3rdparty/libzip/lib/zip_set_archive_flag.c create mode 100644 3rdparty/libzip/lib/zip_set_default_password.c create mode 100644 3rdparty/libzip/lib/zip_set_file_comment.c create mode 100644 3rdparty/libzip/lib/zip_set_file_compression.c create mode 100644 3rdparty/libzip/lib/zip_set_name.c create mode 100644 3rdparty/libzip/lib/zip_source_accept_empty.c create mode 100644 3rdparty/libzip/lib/zip_source_begin_write.c create mode 100644 3rdparty/libzip/lib/zip_source_begin_write_cloning.c create mode 100644 3rdparty/libzip/lib/zip_source_buffer.c create mode 100644 3rdparty/libzip/lib/zip_source_call.c create mode 100644 3rdparty/libzip/lib/zip_source_close.c create mode 100644 3rdparty/libzip/lib/zip_source_commit_write.c create mode 100644 3rdparty/libzip/lib/zip_source_compress.c create mode 100644 3rdparty/libzip/lib/zip_source_crc.c create mode 100644 3rdparty/libzip/lib/zip_source_error.c create mode 100644 3rdparty/libzip/lib/zip_source_file.h create mode 100644 3rdparty/libzip/lib/zip_source_file_common.c create mode 100644 3rdparty/libzip/lib/zip_source_file_stdio.c create mode 100644 3rdparty/libzip/lib/zip_source_file_stdio.h create mode 100644 3rdparty/libzip/lib/zip_source_file_stdio_named.c create mode 100644 3rdparty/libzip/lib/zip_source_file_win32.c create mode 100644 3rdparty/libzip/lib/zip_source_file_win32.h create mode 100644 3rdparty/libzip/lib/zip_source_file_win32_ansi.c create mode 100644 3rdparty/libzip/lib/zip_source_file_win32_named.c create mode 100644 3rdparty/libzip/lib/zip_source_file_win32_utf16.c create mode 100644 3rdparty/libzip/lib/zip_source_file_win32_utf8.c create mode 100644 3rdparty/libzip/lib/zip_source_free.c create mode 100644 3rdparty/libzip/lib/zip_source_function.c create mode 100644 3rdparty/libzip/lib/zip_source_get_file_attributes.c create mode 100644 3rdparty/libzip/lib/zip_source_is_deleted.c create mode 100644 3rdparty/libzip/lib/zip_source_layered.c create mode 100644 3rdparty/libzip/lib/zip_source_open.c create mode 100644 3rdparty/libzip/lib/zip_source_pass_to_lower_layer.c create mode 100644 3rdparty/libzip/lib/zip_source_pkware_decode.c create mode 100644 3rdparty/libzip/lib/zip_source_pkware_encode.c create mode 100644 3rdparty/libzip/lib/zip_source_read.c create mode 100644 3rdparty/libzip/lib/zip_source_remove.c create mode 100644 3rdparty/libzip/lib/zip_source_rollback_write.c create mode 100644 3rdparty/libzip/lib/zip_source_seek.c create mode 100644 3rdparty/libzip/lib/zip_source_seek_write.c create mode 100644 3rdparty/libzip/lib/zip_source_stat.c create mode 100644 3rdparty/libzip/lib/zip_source_supports.c create mode 100644 3rdparty/libzip/lib/zip_source_tell.c create mode 100644 3rdparty/libzip/lib/zip_source_tell_write.c create mode 100644 3rdparty/libzip/lib/zip_source_window.c create mode 100644 3rdparty/libzip/lib/zip_source_winzip_aes_decode.c create mode 100644 3rdparty/libzip/lib/zip_source_winzip_aes_encode.c create mode 100644 3rdparty/libzip/lib/zip_source_write.c create mode 100644 3rdparty/libzip/lib/zip_source_zip.c create mode 100644 3rdparty/libzip/lib/zip_source_zip_new.c create mode 100644 3rdparty/libzip/lib/zip_stat.c create mode 100644 3rdparty/libzip/lib/zip_stat_index.c create mode 100644 3rdparty/libzip/lib/zip_stat_init.c create mode 100644 3rdparty/libzip/lib/zip_strerror.c create mode 100644 3rdparty/libzip/lib/zip_string.c create mode 100644 3rdparty/libzip/lib/zip_unchange.c create mode 100644 3rdparty/libzip/lib/zip_unchange_all.c create mode 100644 3rdparty/libzip/lib/zip_unchange_archive.c create mode 100644 3rdparty/libzip/lib/zip_unchange_data.c create mode 100644 3rdparty/libzip/lib/zip_utf-8.c create mode 100644 3rdparty/libzip/lib/zip_winzip_aes.c create mode 100644 3rdparty/libzip/lib/zipint.h delete mode 160000 3rdparty/libzip/libzip rename 3rdparty/libzip/{private => msvc}/config.h (81%) rename 3rdparty/libzip/{private => msvc}/zip_err_str.c (97%) rename 3rdparty/libzip/{ => msvc}/zipconf.h (90%) diff --git a/.gitmodules b/.gitmodules index caf9c8738a4ef..9cdefb579d5e5 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 0000000000000..a33707b01d6df --- /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 47e08c93263a5..8c2081564bf11 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 "") - -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 "") +cmake_minimum_required(VERSION 3.5.0) -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() + +project(libzip + VERSION 1.10.1 + LANGUAGES C) + +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() -# 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") +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_subdirectory(libzip EXCLUDE_FROM_ALL) +add_library(libzip::zip ALIAS zip) diff --git a/3rdparty/libzip/LICENSE b/3rdparty/libzip/LICENSE new file mode 100644 index 0000000000000..fa706096111ba --- /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 0000000000000..630ed23f65c3e --- /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 0000000000000..b88ed267fa125 --- /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 0000000000000..b389c6b3d3877 --- /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 0000000000000..550412b6cb809 --- /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 0000000000000..1afefae000ded --- /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 0000000000000..384a611ff6a33 --- /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 0000000000000..0d31d40684caa --- /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 0000000000000..9770139d6602e --- /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 0000000000000..c31fea365a469 --- /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 0000000000000..bf12dd54176ee --- /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 0000000000000..f25be1438b232 --- /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 0000000000000..3c85e2045b70a --- /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 0000000000000..d7a7142d462dc --- /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 0000000000000..d005da9d52eb1 --- /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 0000000000000..e2103f04ce3d5 --- /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 0000000000000..ddc2c24563041 --- /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 0000000000000..0d74d1a41e819 --- /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 0000000000000..b198be563058c --- /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 0000000000000..01828cc64e432 --- /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 0000000000000..1a25aa120e7d6 --- /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 0000000000000..dc8b97a4d21db --- /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 0000000000000..84544a821de38 --- /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 0000000000000..1151fff757e2d --- /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 0000000000000..7f1da10edbe2e --- /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 0000000000000..198a907144502 --- /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 0000000000000..ee3ccc30a6af8 --- /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 0000000000000..a533fe2df3c19 --- /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 0000000000000..676c16bf2437d --- /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 0000000000000..c01081916abcc --- /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 0000000000000..45a2a6a29eb91 --- /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 0000000000000..d1dc4f8b0d14e --- /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 0000000000000..35a36e4a1613a --- /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 0000000000000..c498e086054a7 --- /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 0000000000000..94ff5062d57a1 --- /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 0000000000000..c0418f0d0c1e7 --- /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 0000000000000..a22ffb03679dc --- /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 0000000000000..fe04cbb4f4601 --- /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 0000000000000..b60b78813b92c --- /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 0000000000000..7aed12adb55d5 --- /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 0000000000000..560c71bb298a3 --- /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 0000000000000..b820d98bdcf3d --- /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 0000000000000..e72c55dcadaaa --- /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 0000000000000..c2c41e156352d --- /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 0000000000000..a10bff80c678f --- /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 0000000000000..b93117bb9bd2a --- /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 0000000000000..fa998f02ed31b --- /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 0000000000000..a79bb3ed2bdbe --- /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 0000000000000..72f4880e78b10 --- /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 0000000000000..9ac25814a9809 --- /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 0000000000000..4262d453ea067 --- /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 0000000000000..570f8e821273a --- /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 0000000000000..1cdcd4ab67c9b --- /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 0000000000000..2e0429b8ca852 --- /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 0000000000000..4126f5a166f92 --- /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 0000000000000..5b5a0092416f6 --- /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 0000000000000..e3cde9be06023 --- /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 0000000000000..d5880dcb99651 --- /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 0000000000000..a449b83a0d3ae --- /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 0000000000000..40483709ee007 --- /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 0000000000000..5b7da46aee29f --- /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 0000000000000..e68ffd367dc99 --- /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 0000000000000..bf3b03d348749 --- /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 0000000000000..ea9a00ab5ca10 --- /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 0000000000000..fc200bdc4aebd --- /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 0000000000000..72e48fe87abc8 --- /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 0000000000000..d58e22ba6db42 --- /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 0000000000000..4828d78107ea2 --- /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 0000000000000..667dc51179f10 --- /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 0000000000000..140e34f90061d --- /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 0000000000000..d3a954ec5977e --- /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 0000000000000..9fcd10b4b3972 --- /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 0000000000000..4200727fcd7bb --- /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 0000000000000..75d72c616b2ce --- /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 0000000000000..4248dc2d36e17 --- /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 0000000000000..4f69c8a2f5d9f --- /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 0000000000000..ee7e9decb8569 --- /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 0000000000000..6a8c9fcde400b --- /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 0000000000000..e080514b12dca --- /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 0000000000000..867df7900ecf0 --- /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 0000000000000..0883ce454f74d --- /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 0000000000000..789b9c2058da0 --- /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 0000000000000..c89b06c9e36f3 --- /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 0000000000000..96c083c3dce2d --- /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 0000000000000..7d06688e3a30f --- /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 0000000000000..834ef5baca091 --- /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 0000000000000..4bab513f46a33 --- /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 0000000000000..5d2b0b8a03c8a --- /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 0000000000000..a193bb77fb6d4 --- /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 0000000000000..f1bf703e44b8d --- /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 0000000000000..e772aeea967bc --- /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 0000000000000..4a9d5d5d662df --- /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 0000000000000..df195fcd40fba --- /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 0000000000000..5667293253166 --- /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 0000000000000..8c98fc2ef2d33 --- /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 0000000000000..f4f3ff2b3cc52 --- /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 0000000000000..d7f567b80ad26 --- /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 0000000000000..3cf709ffa1207 --- /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 0000000000000..435a084b70529 --- /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 0000000000000..dc7fa20cb0cad --- /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 0000000000000..cca9fd2b52475 --- /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 0000000000000..6c58320f1e0ad --- /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 0000000000000..6dcc56399f6fa --- /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 0000000000000..802e6071ff5a7 --- /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 0000000000000..1495d7dde78ca --- /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 0000000000000..624860b1cbbd6 --- /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 0000000000000..d86069ecaa6df --- /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 0000000000000..58034cc2a7871 --- /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 0000000000000..855e605a9394a --- /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 0000000000000..8f07d0210d479 --- /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 0000000000000..d154f97ae368a --- /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 0000000000000..1a800405c263c --- /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 0000000000000..1fe6396e140fe --- /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 0000000000000..4771dc16b316d --- /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 0000000000000..838aa90967985 --- /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 0000000000000..62b78e68e794c --- /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 0000000000000..b34fa2c6c0105 --- /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 0000000000000..4a98222ecd447 --- /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 0000000000000..b4c482b31238f --- /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 0000000000000..d89b9f4e882a0 --- /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 0000000000000..0938fcb0841db --- /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 0000000000000..c1d73ab928c58 --- /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 0000000000000..ea1a1510783fb --- /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 0000000000000..e3baad5ab893f --- /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 0000000000000..34ae2f5af2a87 --- /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 0000000000000..05dcb84d70470 --- /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 0000000000000..8fea2ae9191fa --- /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 0000000000000..49057ce56c0c1 --- /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 0000000000000..a5b0e53112d5b --- /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 0000000000000..524e27c837b90 --- /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 0000000000000..ee53fb419c237 --- /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 0000000000000..87e2865a03a89 --- /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 0000000000000..24dde9b2479cb --- /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 0000000000000..faabf0d29f13a --- /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 0000000000000..ecccdd68f7102 --- /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 0000000000000..51d8026dddc9e --- /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 0000000000000..da33c09eb5109 --- /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 0000000000000..9c6088a79624b --- /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 0000000000000..7d8279318dc0b --- /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 0000000000000..1c964491c9dbf --- /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 0000000000000..d69a3dfe17425 --- /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 0000000000000..34f3702e07eac --- /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 0000000000000..56a8e31f60be9 --- /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 0000000000000..6bdecd1872de1 --- /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 0000000000000..678912f6b4bee --- /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 0000000000000..ce269036cf297 --- /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 0000000000000..4887b6c5c8bc6 --- /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 bdc03ab23b703..0000000000000 --- 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 97fe04409d5ba..58e2ec58b9ec5 100644 --- a/3rdparty/libzip/libzip.vcxproj +++ b/3rdparty/libzip/libzip.vcxproj @@ -30,149 +30,145 @@ AllRules.ruleset - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + {52244028-937a-44e9-a76b-2bea18fd239a} + - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - {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 7b7ef9e826492..5efcda34ec779 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 57faa67244441..4284d435f1e78 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 c9b1504ecfb42..28af773bcae54 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 7910affd01294..41675b5becb95 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 f9f496c4e2ff9..cc967560e8572 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 0f41dff76a04d..986a68bc1a80c 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 d7ea5a60a25a1..d7eae8da06301 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 92748b70e4295..6433f2e73b5ee 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 + From 1c87558a618169773a1e3c7e08109d5739a45a90 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 24 Aug 2023 12:38:51 +1000 Subject: [PATCH 3/4] 3rdparty: Fix Debug CMake build on Windows --- 3rdparty/winpixeventruntime/CMakeLists.txt | 5 +++++ cmake/SearchForStuff.cmake | 1 + 2 files changed, 6 insertions(+) create mode 100644 3rdparty/winpixeventruntime/CMakeLists.txt diff --git a/3rdparty/winpixeventruntime/CMakeLists.txt b/3rdparty/winpixeventruntime/CMakeLists.txt new file mode 100644 index 0000000000000..785f83370c56b --- /dev/null +++ b/3rdparty/winpixeventruntime/CMakeLists.txt @@ -0,0 +1,5 @@ +add_library(WinPixEventRuntime::WinPixEventRuntime UNKNOWN IMPORTED GLOBAL) +set_target_properties(WinPixEventRuntime::WinPixEventRuntime PROPERTIES + IMPORTED_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}/lib/WinPixEventRuntime.lib" + INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/include" +) diff --git a/cmake/SearchForStuff.cmake b/cmake/SearchForStuff.cmake index 986a68bc1a80c..b9d1dee61d1fb 100644 --- a/cmake/SearchForStuff.cmake +++ b/cmake/SearchForStuff.cmake @@ -11,6 +11,7 @@ if (WIN32) add_subdirectory(3rdparty/libjpeg EXCLUDE_FROM_ALL) add_subdirectory(3rdparty/xz EXCLUDE_FROM_ALL) add_subdirectory(3rdparty/D3D12MemAlloc EXCLUDE_FROM_ALL) + add_subdirectory(3rdparty/winpixeventruntime EXCLUDE_FROM_ALL) set(FFMPEG_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/3rdparty/ffmpeg/include") find_package(Vtune) From 3eb058d83ddc6f9d720f08b40497df457a9dd85b Mon Sep 17 00:00:00 2001 From: Stenzek Date: Thu, 24 Aug 2023 13:47:37 +1000 Subject: [PATCH 4/4] Tests: Force 1MB stack size for MSVC For some reason, the stack refuses to grow with the latest MSVC updates, at least within our unit tests that bump the stack considerably within a lambda function. Just force the commit size to 1MB for now. --- tests/ctest/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/ctest/CMakeLists.txt b/tests/ctest/CMakeLists.txt index f77b7eb489c5d..1860cd1b34fd6 100644 --- a/tests/ctest/CMakeLists.txt +++ b/tests/ctest/CMakeLists.txt @@ -15,6 +15,12 @@ macro(add_pcsx2_test target) add_dependencies(unittests ${target}) add_test(NAME ${target} COMMAND ${target}) + + if(MSVC AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # For some reason, the stack refuses to grow with the latest MSVC updates. + # Just force the commit size to 1MB for now. + set_target_properties(${target} PROPERTIES LINK_FLAGS "/STACK:1048576,1048576") + endif() endmacro() add_subdirectory(gtest)