VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/libzip
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/libzip')
-rw-r--r--src/Common/libzip/LICENSE4
-rw-r--r--src/Common/libzip/NEWS.md217
-rw-r--r--src/Common/libzip/compat.h87
-rw-r--r--src/Common/libzip/config.h78
-rw-r--r--src/Common/libzip/mkstemp.c153
-rw-r--r--src/Common/libzip/zip.h373
-rw-r--r--src/Common/libzip/zip_add.c10
-rw-r--r--src/Common/libzip/zip_add_dir.c4
-rw-r--r--src/Common/libzip/zip_add_entry.c52
-rw-r--r--src/Common/libzip/zip_algorithm_bzip2.c293
-rw-r--r--src/Common/libzip/zip_algorithm_deflate.c119
-rw-r--r--src/Common/libzip/zip_algorithm_xz.c408
-rw-r--r--src/Common/libzip/zip_algorithm_zstd.c298
-rw-r--r--src/Common/libzip/zip_buffer.c83
-rw-r--r--src/Common/libzip/zip_close.c804
-rw-r--r--src/Common/libzip/zip_crypto.h54
-rw-r--r--src/Common/libzip/zip_crypto_commoncrypto.c110
-rw-r--r--src/Common/libzip/zip_crypto_commoncrypto.h53
-rw-r--r--src/Common/libzip/zip_crypto_gnutls.c134
-rw-r--r--src/Common/libzip/zip_crypto_gnutls.h68
-rw-r--r--src/Common/libzip/zip_crypto_mbedtls.c171
-rw-r--r--src/Common/libzip/zip_crypto_mbedtls.h56
-rw-r--r--src/Common/libzip/zip_crypto_openssl.c229
-rw-r--r--src/Common/libzip/zip_crypto_openssl.h73
-rw-r--r--src/Common/libzip/zip_crypto_win.c495
-rw-r--r--src/Common/libzip/zip_crypto_win.h53
-rw-r--r--src/Common/libzip/zip_delete.c18
-rw-r--r--src/Common/libzip/zip_dir_add.c40
-rw-r--r--src/Common/libzip/zip_dirent.c1037
-rw-r--r--src/Common/libzip/zip_discard.c18
-rw-r--r--src/Common/libzip/zip_entry.c4
-rw-r--r--src/Common/libzip/zip_err_str.c81
-rw-r--r--src/Common/libzip/zip_error.c52
-rw-r--r--src/Common/libzip/zip_error_clear.c6
-rw-r--r--src/Common/libzip/zip_error_get.c4
-rw-r--r--src/Common/libzip/zip_error_get_sys_type.c11
-rw-r--r--src/Common/libzip/zip_error_strerror.c110
-rw-r--r--src/Common/libzip/zip_error_to_str.c30
-rw-r--r--src/Common/libzip/zip_extra_field.c375
-rw-r--r--src/Common/libzip/zip_extra_field_api.c236
-rw-r--r--src/Common/libzip/zip_fclose.c8
-rw-r--r--src/Common/libzip/zip_fdopen.c39
-rw-r--r--src/Common/libzip/zip_file_add.c14
-rw-r--r--src/Common/libzip/zip_file_error_clear.c6
-rw-r--r--src/Common/libzip/zip_file_error_get.c4
-rw-r--r--src/Common/libzip/zip_file_get_comment.c10
-rw-r--r--src/Common/libzip/zip_file_get_external_attributes.c10
-rw-r--r--src/Common/libzip/zip_file_get_offset.c67
-rw-r--r--src/Common/libzip/zip_file_rename.c18
-rw-r--r--src/Common/libzip/zip_file_replace.c60
-rw-r--r--src/Common/libzip/zip_file_set_comment.c66
-rw-r--r--src/Common/libzip/zip_file_set_encryption.c120
-rw-r--r--src/Common/libzip/zip_file_set_external_attributes.c50
-rw-r--r--src/Common/libzip/zip_file_set_mtime.c53
-rw-r--r--src/Common/libzip/zip_file_strerror.c4
-rw-r--r--src/Common/libzip/zip_fopen.c6
-rw-r--r--src/Common/libzip/zip_fopen_encrypted.c6
-rw-r--r--src/Common/libzip/zip_fopen_index.c7
-rw-r--r--src/Common/libzip/zip_fopen_index_encrypted.c28
-rw-r--r--src/Common/libzip/zip_fread.c21
-rw-r--r--src/Common/libzip/zip_fseek.c (renamed from src/Common/libzip/zip_source_get_compression_flags.c)44
-rw-r--r--src/Common/libzip/zip_ftell.c (renamed from src/Common/libzip/zip_source_file.c)37
-rw-r--r--src/Common/libzip/zip_get_archive_comment.c12
-rw-r--r--src/Common/libzip/zip_get_archive_flag.c4
-rw-r--r--src/Common/libzip/zip_get_encryption_implementation.c21
-rw-r--r--src/Common/libzip/zip_get_file_comment.c8
-rw-r--r--src/Common/libzip/zip_get_name.c8
-rw-r--r--src/Common/libzip/zip_get_num_entries.c14
-rw-r--r--src/Common/libzip/zip_get_num_files.c10
-rw-r--r--src/Common/libzip/zip_hash.c294
-rw-r--r--src/Common/libzip/zip_io_util.c80
-rw-r--r--src/Common/libzip/zip_libzip_version.c41
-rw-r--r--src/Common/libzip/zip_memdup.c12
-rw-r--r--src/Common/libzip/zip_name_locate.c82
-rw-r--r--src/Common/libzip/zip_new.c12
-rw-r--r--src/Common/libzip/zip_open.c895
-rw-r--r--src/Common/libzip/zip_pkware.c112
-rw-r--r--src/Common/libzip/zip_progress.c188
-rw-r--r--src/Common/libzip/zip_random_unix.c110
-rw-r--r--src/Common/libzip/zip_random_uwp.c (renamed from src/Common/libzip/zip_filerange_crc.c)76
-rw-r--r--src/Common/libzip/zip_random_win32.c82
-rw-r--r--src/Common/libzip/zip_rename.c6
-rw-r--r--src/Common/libzip/zip_replace.c4
-rw-r--r--src/Common/libzip/zip_set_archive_comment.c40
-rw-r--r--src/Common/libzip/zip_set_archive_flag.c41
-rw-r--r--src/Common/libzip/zip_set_default_password.c18
-rw-r--r--src/Common/libzip/zip_set_file_comment.c10
-rw-r--r--src/Common/libzip/zip_set_file_compression.c58
-rw-r--r--src/Common/libzip/zip_set_name.c114
-rw-r--r--src/Common/libzip/zip_source_accept_empty.c52
-rw-r--r--src/Common/libzip/zip_source_begin_write.c15
-rw-r--r--src/Common/libzip/zip_source_begin_write_cloning.c15
-rw-r--r--src/Common/libzip/zip_source_buffer.c502
-rw-r--r--src/Common/libzip/zip_source_call.c30
-rw-r--r--src/Common/libzip/zip_source_close.c20
-rw-r--r--src/Common/libzip/zip_source_commit_write.c27
-rw-r--r--src/Common/libzip/zip_source_compress.c363
-rw-r--r--src/Common/libzip/zip_source_crc.c188
-rw-r--r--src/Common/libzip/zip_source_deflate.c415
-rw-r--r--src/Common/libzip/zip_source_error.c4
-rw-r--r--src/Common/libzip/zip_source_file.h90
-rw-r--r--src/Common/libzip/zip_source_file_common.c388
-rw-r--r--src/Common/libzip/zip_source_file_stdio.c178
-rw-r--r--src/Common/libzip/zip_source_file_stdio.h45
-rw-r--r--src/Common/libzip/zip_source_file_stdio_named.c392
-rw-r--r--src/Common/libzip/zip_source_file_win32.c234
-rw-r--r--src/Common/libzip/zip_source_file_win32.h84
-rw-r--r--src/Common/libzip/zip_source_file_win32_ansi.c87
-rw-r--r--src/Common/libzip/zip_source_file_win32_named.c274
-rw-r--r--src/Common/libzip/zip_source_file_win32_utf16.c113
-rw-r--r--src/Common/libzip/zip_source_file_win32_utf8.c (renamed from src/Common/libzip/zip_source_win32utf8.c)37
-rw-r--r--src/Common/libzip/zip_source_filep.c658
-rw-r--r--src/Common/libzip/zip_source_free.c20
-rw-r--r--src/Common/libzip/zip_source_function.c16
-rw-r--r--src/Common/libzip/zip_source_get_file_attributes.c108
-rw-r--r--src/Common/libzip/zip_source_is_deleted.c4
-rw-r--r--src/Common/libzip/zip_source_layered.c28
-rw-r--r--src/Common/libzip/zip_source_open.c43
-rw-r--r--src/Common/libzip/zip_source_pass_to_lower_layer.c78
-rw-r--r--src/Common/libzip/zip_source_pkware.c215
-rw-r--r--src/Common/libzip/zip_source_pkware_decode.c219
-rw-r--r--src/Common/libzip/zip_source_pkware_encode.c271
-rw-r--r--src/Common/libzip/zip_source_read.c54
-rw-r--r--src/Common/libzip/zip_source_remove.c21
-rw-r--r--src/Common/libzip/zip_source_rollback_write.c10
-rw-r--r--src/Common/libzip/zip_source_seek.c34
-rw-r--r--src/Common/libzip/zip_source_seek_write.c13
-rw-r--r--src/Common/libzip/zip_source_stat.c24
-rw-r--r--src/Common/libzip/zip_source_supports.c23
-rw-r--r--src/Common/libzip/zip_source_tell.c18
-rw-r--r--src/Common/libzip/zip_source_tell_write.c13
-rw-r--r--src/Common/libzip/zip_source_win32a.c125
-rw-r--r--src/Common/libzip/zip_source_win32handle.c597
-rw-r--r--src/Common/libzip/zip_source_win32w.c149
-rw-r--r--src/Common/libzip/zip_source_window.c334
-rw-r--r--src/Common/libzip/zip_source_winzip_aes_decode.c265
-rw-r--r--src/Common/libzip/zip_source_winzip_aes_encode.c253
-rw-r--r--src/Common/libzip/zip_source_write.c8
-rw-r--r--src/Common/libzip/zip_source_zip.c36
-rw-r--r--src/Common/libzip/zip_source_zip_new.c313
-rw-r--r--src/Common/libzip/zip_stat.c6
-rw-r--r--src/Common/libzip/zip_stat_index.c76
-rw-r--r--src/Common/libzip/zip_stat_init.c20
-rw-r--r--src/Common/libzip/zip_strerror.c4
-rw-r--r--src/Common/libzip/zip_string.c92
-rw-r--r--src/Common/libzip/zip_unchange.c73
-rw-r--r--src/Common/libzip/zip_unchange_all.c10
-rw-r--r--src/Common/libzip/zip_unchange_archive.c10
-rw-r--r--src/Common/libzip/zip_unchange_data.c18
-rw-r--r--src/Common/libzip/zip_utf-8.c116
-rw-r--r--src/Common/libzip/zip_winzip_aes.c162
-rw-r--r--src/Common/libzip/zipconf.h65
-rw-r--r--src/Common/libzip/zipint.h186
-rw-r--r--src/Common/libzip/zipwin32.h85
154 files changed, 11585 insertions, 6372 deletions
diff --git a/src/Common/libzip/LICENSE b/src/Common/libzip/LICENSE
index e93454e8..fa706096 100644
--- a/src/Common/libzip/LICENSE
+++ b/src/Common/libzip/LICENSE
@@ -1,6 +1,6 @@
-Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
+Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
-The authors can be contacted at <libzip@nih.at>
+The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/Common/libzip/NEWS.md b/src/Common/libzip/NEWS.md
index 9d8d2a33..e117422d 100644
--- a/src/Common/libzip/NEWS.md
+++ b/src/Common/libzip/NEWS.md
@@ -1,13 +1,115 @@
-1.5.2 [2019-03-12]
-==================
+# 1.10.1 [2023-08-23]
+
+* Add `ZIP_LENGTH_TO_END` and `ZIP_LENGTH_UNCHECKED`. Unless `ZIP_LENGTH_UNCHECKED` is used as `length`, it is an error for a file to shrink between the time when the source is created and when its data is read.
+* Fix test on Windows.
+
+# 1.10.0 [2023-06-23]
+
+* Make support for layered sources public.
+* Add `zip_source_zip_file` and `zip_source_zip_file_create`, deprecate `zip_source_zip` and `zip_source_zip_create`.
+* Allow reading changed file data.
+* Fix handling of files of size 4294967295.
+* `zipmerge`: copy extra fields.
+* `zipmerge`: add option to keep files uncompressed.
+* Switch test framework to use nihtest instead of Perl.
+* Fix reading/writing compressed data with buffers > 4GiB.
+* Restore support for torrentzip.
+* Add warnings when using deprecated functions.
+* Allow keeping files for empty archives.
+* Support mbedTLS>=3.3.0.
+* Support OpenSSL 3.
+* Use ISO C secure library functions, if available.
+
+
+# 1.9.2 [2022-06-28]
+
+* Fix version number in header file.
+
+
+# 1.9.1 [2022-06-28]
+
+* Fix `zip_file_is_seekable()`.
+
+
+# 1.9.0 [2022-06-13]
+
+* Add `zip_file_is_seekable()`.
+* Improve compatibility with WinAES.
+* Fix encoding handling in `zip_name_locate()`.
+* Add option to `zipcmp` to output summary of changes.
+* Various bug fixes and documentation improvements.
+
+
+# 1.8.0 [2021-06-18]
+
+* Add support for zstd (Zstandard) compression.
+* Add support for lzma (ID 14) compression.
+* Add `zip_source_window_create()`.
+* Add `zip_source_zip_create()` variant to `zip_source_zip()`.
+* Allow method specific `comp_flags` in `zip_set_file_compression()`.
+* Allow `zip_source_tell()` on sources that don't support seeking and `zip_ftell()` on compressed data.
+* Provide more details for consistency check errors.
+* Improve output of `zipcmp`.
+* In `zipcmp`, don’t ignore empty directories when comparing directory listing.
+* Treat empty string as no password given in `zip_file_set_encryption()`, `zip_fopen_encrypted()`, and `zip_set_default_password()`.
+
+
+# 1.7.3 [2020-07-15]
+
+* Support cmake < 3.17 again.
+* Fix pkgconfig file (regression in 1.7.2).
+
+
+# 1.7.2 [2020-07-11]
+
+* Fixes for the CMake `find_project()` files.
+* libzip moved to the CMake `libzip::` `NAMESPACE`.
+* CMake usage best practice cleanups.
+
+
+# 1.7.1 [2020-06-13]
+
+* Restore `LIBZIP_VERSION_{MAJOR,MINOR,MICRO}` symbols.
+* Fixes warnings reported by PVS-Studio.
+* Add `LIBZIP_DO_INSTALL` build setting to make it easier to use
+ libzip as subproject.
+
+
+# 1.7.0 [2020-06-05]
+
+* Add support for encrypting using traditional PKWare encryption.
+* Add `zip_compression_method_supported()`.
+* Add `zip_encryption_method_supported()`.
+* Add the `ZIP_SOURCE_GET_FILE_ATTRIBUTES` source command.
+* Refactor stdio file backend.
+* Add CMake find_project() support.
+
+
+# 1.6.1 [2020-02-03]
+
+* Bugfix for double-free in `zipcmp(1)` during cleanup.
+
+
+# 1.6.0 [2020-01-24]
+
+* Avoid using `umask()` since it's not thread-safe.
+* Set close-on-exec flag when opening files.
+* Do not accept empty files as valid zip archives any longer.
+* Add support for XZ compressed files (using liblzma).
+* Add support for cancelling while closing zip archives.
+* Add support for setting the time in the on-disk format.
+
+
+# 1.5.2 [2019-03-12]
+
* Fix bug in AES encryption affecting certain file sizes
* Keep file permissions when modifying zip archives
* Support systems with small stack size.
* Support mbed TLS as crypto backend.
* Add nullability annotations.
-1.5.1 [2018-04-11]
-==================
+
+# 1.5.1 [2018-04-11]
* Choose format of installed documentation based on available tools.
* Fix visibility of symbols.
@@ -17,16 +119,16 @@
* Fix build with LibreSSL.
* Various bugfixes.
-1.5.0 [2018-03-11]
-==================
+
+# 1.5.0 [2018-03-11]
* Use standard cryptographic library instead of custom AES implementation.
This also simplifies the license.
* Use `clang-format` to format the source code.
* More Windows improvements.
-1.4.0 [2017-12-29]
-==================
+
+# 1.4.0 [2017-12-29]
* Improve build with cmake
* Retire autoconf/automake build system
@@ -35,19 +137,20 @@
Supported for buffer sources and on Apple File System.
* Add support for Microsoft Universal Windows Platform.
-1.3.2 [2017-11-20]
-==================
+
+# 1.3.2 [2017-11-20]
+
* Fix bug introduced in last: zip_t was erroneously freed if zip_close() failed.
-1.3.1 [2017-11-19]
-==================
+
+# 1.3.1 [2017-11-19]
* Install zipconf.h into ${PREFIX}/include
* Add zip_libzip_version()
* Fix AES tests on Linux
-1.3.0 [2017-09-02]
-==================
+
+# 1.3.0 [2017-09-02]
* Support bzip2 compressed zip archives
* Improve file progress callback code
@@ -55,8 +158,8 @@
* CVE-2017-12858: Fix double free()
* CVE-2017-14107: Improve EOCD64 parsing
-1.2.0 [2017-02-19]
-==================
+
+# 1.2.0 [2017-02-19]
* Support for AES encryption (Winzip version), both encryption
and decryption
@@ -66,24 +169,24 @@
* Add zip_ftell() for telling position in uncompressed data
* Add zip_register_progress_callback() for UI updates during zip_close()
-1.1.3 [2016-05-28]
-==================
+
+# 1.1.3 [2016-05-28]
* Fix build on Windows when using autoconf
-1.1.2 [2016-02-19]
-==================
+
+# 1.1.2 [2016-02-19]
* Improve support for 3MF files
-1.1.1 [2016-02-07]
-==================
+
+# 1.1.1 [2016-02-07]
* Build fixes for Linux
* Fix some warnings reported by PVS-Studio
-1.1 [2016-01-26]
-================
+
+# 1.1 [2016-01-26]
* ziptool(1): command line tool to modify zip archives
* Speedups for archives with many entries
@@ -94,13 +197,13 @@
* Portability fixes
* Documentation improvements
-1.0.1 [2015-05-04]
-==================
+
+# 1.0.1 [2015-05-04]
* Build fixes for Windows
-1.0 [2015-05-03]
-================
+
+# 1.0 [2015-05-03]
* Implemented an I/O abstraction layer
* Added support for native Windows API for files
@@ -111,22 +214,22 @@
* CVE-2015-2331 was fixed
* Addressed all Coverity CIDs
-0.11.2 [2013-12-19]
-===================
+
+# 0.11.2 [2013-12-19]
* Support querying/setting operating system and external attributes
* For newly added files, set operating system to UNIX, permissions
to 0666 (0777 for directories)
* Fix bug when writing zip archives containing files bigger than 4GB
-0.11.1 [2013-04-27]
-===================
+
+# 0.11.1 [2013-04-27]
* Fix bugs in zip_set_file_compression()
* Include Xcode build infrastructure
-0.11 [2013-03-23]
-=================
+
+# 0.11 [2013-03-23]
* Added Zip64 support (large file support)
* Added UTF-8 support for file names, file comments, and archive comments
@@ -140,14 +243,14 @@
* More changes for Windows support
* Additional test cases
-0.10.1 [2012-03-20]
-===================
+
+# 0.10.1 [2012-03-20]
* Fixed CVE-2012-1162
* Fixed CVE-2012-1163
-0.10 [2010-03-18]
-=================
+
+# 0.10 [2010-03-18]
* Added zip_get_num_entries(), deprecated zip_get_num_files()
* Better windows support
@@ -159,37 +262,37 @@
* Fixed CVE-2011-0421 (no security implications though)
* More documentation
-0.9.3 [2010-02-01]
-==================
+
+# 0.9.3 [2010-02-01]
* Include m4/ directory in distribution; some packagers need it
-0.9.2 [2010-01-31]
-==================
+
+# 0.9.2 [2010-01-31]
* Avoid passing uninitialized data to deflate()
* Fix memory leak when closing zip archives
-0.9.1 [2010-01-24]
-==================
+
+# 0.9.1 [2010-01-24]
* Fix infinite loop on reading some broken files
* Optimization in time conversion (don't call localtime())
* Clear data descriptor flag in central directory, fixing Open Office files
* Allow more than 64k entries
-0.9 [2008-07-25]
-==================
-* on Windows, explictly set dllimport/dllexport
+# 0.9 [2008-07-25]
+
+* on Windows, explicitly set dllimport/dllexport
* remove erroneous references to GPL
* add support for torrentzip
* new functions: zip_get_archive_flag, zip_set_archive_flag
* zip_source_zip: add flag to force recompression
* zip_sorce_file: only keep file open while reading from it
-0.8 [2007-06-06]
-==================
+
+# 0.8 [2007-06-06]
* fix for zip archives larger than 2GiB
* fix zip_error_strerror to include libzip error string
@@ -197,13 +300,13 @@
* new functions: zip_add_dir, zip_error_clear, zip_file_error_clear
* add basic support for building with CMake (incomplete)
-0.7.1 [2006-05-18]
-==================
+
+# 0.7.1 [2006-05-18]
* bugfix for zip_close
-0.7 [2006-05-06]
-================
+
+# 0.7 [2006-05-06]
* struct zip_stat increased for future encryption support
* zip_add return value changed (now returns new index of added file)
@@ -212,13 +315,13 @@
New functions: zip_get_archive_comment, zip_get_file_comment,
zip_set_archive_comment, zip_set_file_comment, zip_unchange_archive
-0.6.1 [2005-07-14]
-==================
+
+# 0.6.1 [2005-07-14]
* various bug fixes
-0.6 [2005-06-09]
-================
+
+# 0.6 [2005-06-09]
* first standalone release
* changed license to three-clause BSD
diff --git a/src/Common/libzip/compat.h b/src/Common/libzip/compat.h
index f2e4c6c5..296ee59e 100644
--- a/src/Common/libzip/compat.h
+++ b/src/Common/libzip/compat.h
@@ -3,10 +3,10 @@
/*
compat.h -- compatibility defines.
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -36,34 +36,34 @@
#include "zipconf.h"
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
/* to have *_MAX definitions for all types when compiling with g++ */
#define __STDC_LIMIT_MACROS
-#ifdef _WIN32
-#ifndef ZIP_EXTERN
-#ifndef ZIP_STATIC
+/* to have ISO C secure library functions */
+#define __STDC_WANT_LIB_EXT1__ 1
+
+#if defined(_WIN32) && defined(ZIP_DLL) && !defined(ZIP_STATIC)
+#ifdef BUILDING_LIBZIP
#define ZIP_EXTERN __declspec(dllexport)
#else
-#define ZIP_EXTERN
+#define ZIP_EXTERN __declspec(dllimport)
#endif
#endif
+
+#ifdef _WIN32
/* for dup(), close(), etc. */
#include <io.h>
#endif
#ifdef HAVE_STDBOOL_H
#include <stdbool.h>
-#else
-#ifndef __cplusplus
+#elif !defined(__BOOL_DEFINED)
typedef char bool;
#define true 1
#define false 0
#endif
-#endif
#include <errno.h>
@@ -81,10 +81,12 @@ typedef char bool;
#define EOVERFLOW EFBIG
#endif
-#ifdef _WIN32
-#if defined(HAVE__CHMOD)
-#define chmod _chmod
+/* not supported on at least Windows */
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
#endif
+
+#ifdef _WIN32
#if defined(HAVE__CLOSE)
#define close _close
#endif
@@ -98,13 +100,12 @@ typedef char bool;
#if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
#define fileno _fileno
#endif
-/* Windows' open() doesn't understand Unix permissions */
-#if defined(HAVE__OPEN)
-#define open(a, b, c) _open((a), (b))
-#endif
-#if defined(HAVE__SNPRINTF)
+#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
@@ -120,9 +121,6 @@ typedef char bool;
#if !defined(HAVE_STRTOULL) && defined(HAVE__STRTOUI64)
#define strtoull _strtoui64
#endif
-#if defined(HAVE__UMASK)
-#define umask _umask
-#endif
#if defined(HAVE__UNLINK)
#define unlink _unlink
#endif
@@ -136,9 +134,31 @@ typedef char bool;
#define ftello(s) ((long)ftell((s)))
#endif
-#ifndef HAVE_MKSTEMP
-int _zip_mkstemp(char *);
-#define mkstemp _zip_mkstemp
+#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)
@@ -149,6 +169,19 @@ int _zip_mkstemp(char *);
#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
@@ -203,4 +236,8 @@ int _zip_mkstemp(char *);
#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/src/Common/libzip/config.h b/src/Common/libzip/config.h
index 4de10dff..2976249c 100644
--- a/src/Common/libzip/config.h
+++ b/src/Common/libzip/config.h
@@ -4,69 +4,81 @@
#include "zipconf.h"
#endif
/* BEGIN DEFINES */
+#define ENABLE_FDOPEN
/* #undef HAVE___PROGNAME */
-#define HAVE__CHMOD
#define HAVE__CLOSE
#define HAVE__DUP
#define HAVE__FDOPEN
#define HAVE__FILENO
-#define HAVE__OPEN
#define HAVE__SETMODE
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#define HAVE__SNPRINTF
+#else
/* #undef HAVE__SNPRINTF */
+#endif
+#define HAVE__SNPRINTF_S
+#define HAVE__SNWPRINTF_S
#define HAVE__STRDUP
#define HAVE__STRICMP
#define HAVE__STRTOI64
#define HAVE__STRTOUI64
-#define HAVE__UMASK
#define HAVE__UNLINK
+/* #undef HAVE_ARC4RANDOM */
/* #undef HAVE_CLONEFILE */
/* #undef HAVE_COMMONCRYPTO */
-/* #undef HAVE_CRYPTO */
+#define HAVE_CRYPTO
/* #undef HAVE_FICLONERANGE */
#define HAVE_FILENO
+/* #undef HAVE_FCHMOD */
/* #undef HAVE_FSEEKO */
/* #undef HAVE_FTELLO */
/* #undef HAVE_GETPROGNAME */
/* #undef HAVE_GNUTLS */
/* #undef HAVE_LIBBZ2 */
-#define HAVE_OPEN
-/* #undef HAVE_OPENSSL */
+/* #undef HAVE_LIBLZMA */
+/* #undef 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
+#if defined(_MSC_VER) && _MSC_VER < 1900
/* #undef HAVE_SNPRINTF */
-/* #undef HAVE_SSIZE_T_LIBZIP */
+#else
+#define HAVE_SNPRINTF
+#endif
+/* #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
+#if defined(_MSC_VER) && _MSC_VER < 1800
/* #undef HAVE_STRTOLL */
/* #undef HAVE_STRTOULL */
+#else
+#define HAVE_STRTOLL
+#define HAVE_STRTOULL
+#endif
/* #undef HAVE_STRUCT_TM_TM_ZONE */
+#if defined(_MSC_VER) && _MSC_VER < 1800
/* #undef HAVE_STDBOOL_H */
+#else
+#define HAVE_STDBOOL_H
+#endif
/* #undef HAVE_STRINGS_H */
/* #undef HAVE_UNISTD_H */
-#define __INT8_LIBZIP 1
-#define INT8_T_LIBZIP 1
-#define UINT8_T_LIBZIP 1
-#define __INT16_LIBZIP 2
-#define INT16_T_LIBZIP 2
-#define UINT16_T_LIBZIP 2
-#define __INT32_LIBZIP 4
-#define INT32_T_LIBZIP 4
-#define UINT32_T_LIBZIP 4
-#define __INT64_LIBZIP 8
-#define INT64_T_LIBZIP 8
-#define UINT64_T_LIBZIP 8
-#define SHORT_LIBZIP 2
-#define INT_LIBZIP 4
-#define LONG_LIBZIP 4
-#define LONG_LONG_LIBZIP 8
+#define HAVE_WINDOWS_CRYPTO
#define SIZEOF_OFF_T 4
#ifdef _WIN64
-#define SIZE_T_LIBZIP 8
+#define SIZEOF_SIZE_T 8
#else
-#define SIZE_T_LIBZIP 4
+#define SIZEOF_SIZE_T 4
#endif
-/* #undef SSIZE_T_LIBZIP */
/* #undef HAVE_DIRENT_H */
/* #undef HAVE_FTS_H */
/* #undef HAVE_NDIR_H */
@@ -76,18 +88,6 @@
#define HAVE_SHARED
/* END DEFINES */
#define PACKAGE "libzip"
-#define VERSION "1.5.2"
-
-#ifndef HAVE_SSIZE_T_LIBZIP
-# if SIZE_T_LIBZIP == INT_LIBZIP
-typedef int ssize_t;
-# elif SIZE_T_LIBZIP == LONG_LIBZIP
-typedef long ssize_t;
-# elif SIZE_T_LIBZIP == LONG_LONG_LIBZIP
-typedef long long ssize_t;
-# else
-#error no suitable type for ssize_t found
-# endif
-#endif
+#define VERSION "1.10.1"
#endif /* HAD_CONFIG_H */
diff --git a/src/Common/libzip/mkstemp.c b/src/Common/libzip/mkstemp.c
deleted file mode 100644
index 01a531fc..00000000
--- a/src/Common/libzip/mkstemp.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/* Adapted from NetBSB libc by Dieter Baron */
-
-/* NetBSD: gettemp.c,v 1.13 2003/12/05 00:57:36 uebayasi Exp */
-
-/*
- * Copyright (c) 1987, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (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 <sys/stat.h>
-#include <sys/types.h>
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#ifdef _WIN32
-#include <io.h>
-#include <process.h>
-#else
-#include <unistd.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-
-int
-_zip_mkstemp(char *path) {
-#ifdef _WIN32
- int ret;
- ret = _creat(_mktemp(path), _S_IREAD | _S_IWRITE);
- if (ret == -1) {
- return 0;
- }
- else {
- return ret;
- }
-#else
- int fd;
- char *start, *trv;
- struct stat sbuf;
- pid_t pid;
-
- /* To guarantee multiple calls generate unique names even if
- the file is not created. 676 different possibilities with 7
- or more X's, 26 with 6 or less. */
- static char xtra[2] = "aa";
- int xcnt = 0;
-
- pid = getpid();
-
- /* Move to end of path and count trailing X's. */
- for (trv = path; *trv; ++trv)
- if (*trv == 'X')
- xcnt++;
- else
- xcnt = 0;
-
- /* Use at least one from xtra. Use 2 if more than 6 X's. */
- if (*(trv - 1) == 'X')
- *--trv = xtra[0];
- if (xcnt > 6 && *(trv - 1) == 'X')
- *--trv = xtra[1];
-
- /* Set remaining X's to pid digits with 0's to the left. */
- while (*--trv == 'X') {
- *trv = (pid % 10) + '0';
- pid /= 10;
- }
-
- /* update xtra for next call. */
- if (xtra[0] != 'z')
- xtra[0]++;
- else {
- xtra[0] = 'a';
- if (xtra[1] != 'z')
- xtra[1]++;
- else
- xtra[1] = 'a';
- }
-
- /*
- * check the target directory; if you have six X's and it
- * doesn't exist this runs for a *very* long time.
- */
- for (start = trv + 1;; --trv) {
- if (trv <= path)
- break;
- if (*trv == '/') {
- *trv = '\0';
- if (stat(path, &sbuf))
- return (0);
- if (!S_ISDIR(sbuf.st_mode)) {
- errno = ENOTDIR;
- return (0);
- }
- *trv = '/';
- break;
- }
- }
-
- for (;;) {
- if ((fd = open(path, O_CREAT | O_EXCL | O_RDWR | O_BINARY, 0600)) >= 0)
- return (fd);
- if (errno != EEXIST)
- return (0);
-
- /* tricky little algorithm for backward compatibility */
- for (trv = start;;) {
- if (!*trv)
- return (0);
- if (*trv == 'z')
- *trv++ = 'a';
- else {
- if (isdigit((unsigned char)*trv))
- *trv = 'a';
- else
- ++*trv;
- break;
- }
- }
- }
- /*NOTREACHED*/
-#endif
-}
diff --git a/src/Common/libzip/zip.h b/src/Common/libzip/zip.h
index b7cd60c5..dc3751c8 100644
--- a/src/Common/libzip/zip.h
+++ b/src/Common/libzip/zip.h
@@ -3,10 +3,10 @@
/*
zip.h -- exported declarations.
- Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -45,9 +45,13 @@ extern "C" {
#include <zipconf.h>
#ifndef ZIP_EXTERN
-#ifndef ZIP_STATIC
+#if defined(ZIP_DLL) && !defined(ZIP_STATIC)
#ifdef _WIN32
+#ifdef BUILDING_LIBZIP
+#define ZIP_EXTERN __declspec(dllexport)
+#else
#define ZIP_EXTERN __declspec(dllimport)
+#endif
#elif defined(__GNUC__) && __GNUC__ >= 4
#define ZIP_EXTERN __attribute__((visibility("default")))
#else
@@ -58,6 +62,16 @@ extern "C" {
#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 <stdio.h>
#include <sys/types.h>
#include <time.h>
@@ -77,7 +91,7 @@ extern "C" {
#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 */
-#define ZIP_FL_RECOMPRESS 16u /* force recompression of data */
+/* 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 */
@@ -91,7 +105,10 @@ extern "C" {
/* archive global flags flags */
-#define ZIP_AFL_RDONLY 2u /* read only -- cannot be cleared */
+#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 */
@@ -99,6 +116,10 @@ extern "C" {
#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 */
@@ -123,7 +144,7 @@ extern "C" {
#define ZIP_ER_INVAL 18 /* N Invalid argument */
#define ZIP_ER_NOZIP 19 /* N Not a zip archive */
#define ZIP_ER_INTERNAL 20 /* N Internal error */
-#define ZIP_ER_INCONS 21 /* N Zip archive inconsistent */
+#define ZIP_ER_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 */
@@ -134,12 +155,16 @@ extern "C" {
#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_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 */
@@ -160,8 +185,11 @@ extern "C" {
/* 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) */
+#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 */
@@ -212,30 +240,35 @@ extern "C" {
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_GET_COMPRESSION_FLAGS, /* get compression flags, internal only */
- ZIP_SOURCE_BEGIN_WRITE_CLONING /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */
+ 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))
-// clang-format off
+#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) \
@@ -258,7 +291,7 @@ typedef enum zip_source_cmd zip_source_cmd_t;
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL_WRITE) \
| ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_REMOVE))
-// clang-format on
+/* clang-format on */
/* for use by sources */
struct zip_source_args_seek {
@@ -273,9 +306,9 @@ typedef struct zip_source_args_seek zip_source_args_seek_t;
/* 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 *str; /* string representation or NULL */
+ 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
@@ -290,7 +323,7 @@ struct zip_error {
struct zip_stat {
zip_uint64_t valid; /* which fields have valid values */
- const char * name; /* name of the file */
+ 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) */
@@ -302,10 +335,27 @@ struct zip_stat {
};
struct zip_buffer_fragment {
- zip_uint8_t * data;
+ 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;
@@ -313,135 +363,156 @@ 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 *, void *, zip_uint64_t, zip_source_cmd_t);
-typedef void (*zip_progress_callback)(zip_t *, double, void *);
+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_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t); /* use zip_register_progress_callback_with_state */
-
-ZIP_EXTERN zip_int64_t zip_add(zip_t *, const char *, zip_source_t *); /* use zip_file_add */
-ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *, const char *); /* use zip_dir_add */
-ZIP_EXTERN const char * zip_get_file_comment(zip_t *, zip_uint64_t, int *, int); /* use zip_file_get_comment */
-ZIP_EXTERN int zip_get_num_files(zip_t *); /* use zip_get_num_entries instead */
-ZIP_EXTERN int zip_rename(zip_t *, zip_uint64_t, const char *); /* use zip_file_rename */
-ZIP_EXTERN int zip_replace(zip_t *, zip_uint64_t, zip_source_t *); /* use zip_file_replace */
-ZIP_EXTERN int zip_set_file_comment(zip_t *, zip_uint64_t, const char *, int); /* use zip_file_set_comment */
-ZIP_EXTERN int zip_error_get_sys_type(int); /* use zip_error_system_type */
-ZIP_EXTERN void zip_error_get(zip_t *, int *, int *); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */
-ZIP_EXTERN int zip_error_to_str(char *, zip_uint64_t, int, int); /* use zip_error_init_with_code / zip_error_strerror */
-ZIP_EXTERN void zip_file_error_get(zip_file_t *, int *, int *); /* use zip_file_get_error, zip_error_code_zip / zip_error_code_system */
+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 *);
-ZIP_EXTERN int zip_delete(zip_t *, zip_uint64_t);
-ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *, const char *, zip_flags_t);
-ZIP_EXTERN void zip_discard(zip_t *);
-
-ZIP_EXTERN zip_error_t * zip_get_error(zip_t *);
-ZIP_EXTERN void zip_error_clear(zip_t *);
-ZIP_EXTERN int zip_error_code_zip(const zip_error_t *);
-ZIP_EXTERN int zip_error_code_system(const zip_error_t *);
-ZIP_EXTERN void zip_error_fini(zip_error_t *);
-ZIP_EXTERN void zip_error_init(zip_error_t *);
-ZIP_EXTERN void zip_error_init_with_code(zip_error_t *, int);
-ZIP_EXTERN void zip_error_set(zip_error_t *, int, int);
-ZIP_EXTERN const char * zip_error_strerror(zip_error_t *);
-ZIP_EXTERN int zip_error_system_type(const zip_error_t *);
-ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *, void *, zip_uint64_t);
-
-ZIP_EXTERN int zip_fclose(zip_file_t *);
-ZIP_EXTERN zip_t * zip_fdopen(int, int, int *);
-ZIP_EXTERN zip_int64_t zip_file_add(zip_t *, const char *, zip_source_t *, zip_flags_t);
-ZIP_EXTERN void zip_file_error_clear(zip_file_t *);
-ZIP_EXTERN int zip_file_extra_field_delete(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t);
-ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t);
-ZIP_EXTERN int zip_file_extra_field_set(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t);
-ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(zip_t *, zip_uint64_t, zip_flags_t);
-ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t);
-ZIP_EXTERN const zip_uint8_t * zip_file_extra_field_get(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t);
-ZIP_EXTERN const zip_uint8_t * zip_file_extra_field_get_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t);
-ZIP_EXTERN const char * zip_file_get_comment(zip_t *, zip_uint64_t, zip_uint32_t *, zip_flags_t);
-ZIP_EXTERN zip_error_t * zip_file_get_error(zip_file_t *);
-ZIP_EXTERN int zip_file_get_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t *, zip_uint32_t *);
-ZIP_EXTERN int zip_file_rename(zip_t *, zip_uint64_t, const char *, zip_flags_t);
-ZIP_EXTERN int zip_file_replace(zip_t *, zip_uint64_t, zip_source_t *, zip_flags_t);
-ZIP_EXTERN int zip_file_set_comment(zip_t *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t);
-ZIP_EXTERN int zip_file_set_encryption(zip_t *, zip_uint64_t, zip_uint16_t, const char *);
-ZIP_EXTERN int zip_file_set_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t);
-ZIP_EXTERN int zip_file_set_mtime(zip_t *, zip_uint64_t, time_t, zip_flags_t);
-ZIP_EXTERN const char * zip_file_strerror(zip_file_t *);
-ZIP_EXTERN zip_file_t * zip_fopen(zip_t *, const char *, zip_flags_t);
-ZIP_EXTERN zip_file_t * zip_fopen_encrypted(zip_t *, const char *, zip_flags_t, const char *);
-ZIP_EXTERN zip_file_t * zip_fopen_index(zip_t *, zip_uint64_t, zip_flags_t);
-ZIP_EXTERN zip_file_t * zip_fopen_index_encrypted(zip_t *, zip_uint64_t, zip_flags_t, const char *);
-ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *, void *, zip_uint64_t);
-ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *, zip_int64_t, int);
-ZIP_EXTERN zip_int64_t zip_ftell(zip_file_t *);
-ZIP_EXTERN const char * zip_get_archive_comment(zip_t *, int *, zip_flags_t);
-ZIP_EXTERN int zip_get_archive_flag(zip_t *, zip_flags_t, zip_flags_t);
-ZIP_EXTERN const char * zip_get_name(zip_t *, zip_uint64_t, zip_flags_t);
-ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *, zip_flags_t);
-ZIP_EXTERN const char * zip_libzip_version(void);
-ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *, const char *, zip_flags_t);
-ZIP_EXTERN zip_t * zip_open(const char *, int, int *);
-ZIP_EXTERN zip_t * zip_open_from_source(zip_source_t *, int, zip_error_t *);
-ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *, double, zip_progress_callback, void (*)(void *), void *);
-ZIP_EXTERN int zip_set_archive_comment(zip_t *, const char *, zip_uint16_t);
-ZIP_EXTERN int zip_set_archive_flag(zip_t *, zip_flags_t, int);
-ZIP_EXTERN int zip_set_default_password(zip_t *, const char *);
-ZIP_EXTERN int zip_set_file_compression(zip_t *, zip_uint64_t, zip_int32_t, zip_uint32_t);
-ZIP_EXTERN int zip_source_begin_write(zip_source_t *);
-ZIP_EXTERN int zip_source_begin_write_cloning(zip_source_t *, zip_uint64_t);
-ZIP_EXTERN zip_source_t * zip_source_buffer(zip_t *, const void *, zip_uint64_t, int);
-ZIP_EXTERN zip_source_t * zip_source_buffer_create(const void *, zip_uint64_t, int, zip_error_t *);
-ZIP_EXTERN zip_source_t * zip_source_buffer_fragment(zip_t *, const zip_buffer_fragment_t *, zip_uint64_t, int);
-ZIP_EXTERN zip_source_t * zip_source_buffer_fragment_create(const zip_buffer_fragment_t *, zip_uint64_t, int, zip_error_t *);
-ZIP_EXTERN int zip_source_close(zip_source_t *);
-ZIP_EXTERN int zip_source_commit_write(zip_source_t *);
-ZIP_EXTERN zip_error_t * zip_source_error(zip_source_t *);
-ZIP_EXTERN zip_source_t * zip_source_file(zip_t *, const char *, zip_uint64_t, zip_int64_t);
-ZIP_EXTERN zip_source_t * zip_source_file_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *);
-ZIP_EXTERN zip_source_t * zip_source_filep(zip_t *, FILE *, zip_uint64_t, zip_int64_t);
-ZIP_EXTERN zip_source_t * zip_source_filep_create(FILE *, zip_uint64_t, zip_int64_t, zip_error_t *);
-ZIP_EXTERN void zip_source_free(zip_source_t *);
-ZIP_EXTERN zip_source_t * zip_source_function(zip_t *, zip_source_callback , void *);
-ZIP_EXTERN zip_source_t * zip_source_function_create(zip_source_callback , void *, zip_error_t *);
-ZIP_EXTERN int zip_source_is_deleted(zip_source_t *);
-ZIP_EXTERN void zip_source_keep(zip_source_t *);
+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 *);
-ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *, void *, zip_uint64_t);
-ZIP_EXTERN void zip_source_rollback_write(zip_source_t *);
-ZIP_EXTERN int zip_source_seek(zip_source_t *, zip_int64_t, int);
-ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *, zip_uint64_t, zip_error_t *);
-ZIP_EXTERN int zip_source_seek_write(zip_source_t *, zip_int64_t, int);
-ZIP_EXTERN int zip_source_stat(zip_source_t *, zip_stat_t *);
-ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *);
-ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_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 *zip_source_win32a(zip_t *, const char *, zip_uint64_t, zip_int64_t);
-ZIP_EXTERN zip_source_t *zip_source_win32a_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *);
-ZIP_EXTERN zip_source_t *zip_source_win32handle(zip_t *, void *, zip_uint64_t, zip_int64_t);
-ZIP_EXTERN zip_source_t *zip_source_win32handle_create(void *, zip_uint64_t, zip_int64_t, zip_error_t *);
-ZIP_EXTERN zip_source_t *zip_source_win32w(zip_t *, const wchar_t *, zip_uint64_t, zip_int64_t);
-ZIP_EXTERN zip_source_t *zip_source_win32w_create(const wchar_t *, zip_uint64_t, zip_int64_t, zip_error_t *);
+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_int64_t zip_source_write(zip_source_t *, const void *, zip_uint64_t);
-ZIP_EXTERN zip_source_t * zip_source_zip(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
-ZIP_EXTERN int zip_stat(zip_t *, const char *, zip_flags_t, zip_stat_t *);
-ZIP_EXTERN int zip_stat_index(zip_t *, zip_uint64_t, zip_flags_t, zip_stat_t *);
-ZIP_EXTERN void zip_stat_init( zip_stat_t *);
-ZIP_EXTERN const char * zip_strerror(zip_t *);
-ZIP_EXTERN int zip_unchange(zip_t *, zip_uint64_t);
-ZIP_EXTERN int zip_unchange_all(zip_t *);
-ZIP_EXTERN int zip_unchange_archive(zip_t *);
+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
}
diff --git a/src/Common/libzip/zip_add.c b/src/Common/libzip/zip_add.c
index f09c9ffe..9770139d 100644
--- a/src/Common/libzip/zip_add.c
+++ b/src/Common/libzip/zip_add.c
@@ -1,9 +1,9 @@
/*
zip_add.c -- add file via callback function
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -38,9 +38,9 @@
/*
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.
+ 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
diff --git a/src/Common/libzip/zip_add_dir.c b/src/Common/libzip/zip_add_dir.c
index 6beb929b..c31fea36 100644
--- a/src/Common/libzip/zip_add_dir.c
+++ b/src/Common/libzip/zip_add_dir.c
@@ -1,9 +1,9 @@
/*
zip_add_dir.c -- add directory
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/Common/libzip/zip_add_entry.c b/src/Common/libzip/zip_add_entry.c
index 45def7a1..bf12dd54 100644
--- a/src/Common/libzip/zip_add_entry.c
+++ b/src/Common/libzip/zip_add_entry.c
@@ -1,9 +1,9 @@
/*
zip_add_entry.c -- create and init struct zip_entry
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -44,32 +44,32 @@ _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;
+ 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 (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;
+ 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++;
diff --git a/src/Common/libzip/zip_algorithm_bzip2.c b/src/Common/libzip/zip_algorithm_bzip2.c
new file mode 100644
index 00000000..f25be143
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <bzlib.h>
+#include <limits.h>
+#include <stdlib.h>
+
+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/src/Common/libzip/zip_algorithm_deflate.c b/src/Common/libzip/zip_algorithm_deflate.c
index ba5ad439..3c85e204 100644
--- a/src/Common/libzip/zip_algorithm_deflate.c
+++ b/src/Common/libzip/zip_algorithm_deflate.c
@@ -1,9 +1,9 @@
/*
zip_algorithm_deflate.c -- deflate (de)compression routines
- Copyright (C) 2017-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,26 +40,44 @@
struct ctx {
zip_error_t *error;
bool compress;
- int compression_flags;
+ 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, int compression_flags, zip_error_t *error) {
+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;
+ zip_error_set(error, ZIP_ET_SYS, errno);
+ return NULL;
}
ctx->error = error;
ctx->compress = compress;
- ctx->compression_flags = compression_flags;
- if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
- ctx->compression_flags = Z_BEST_COMPRESSION;
+ 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;
@@ -71,13 +89,15 @@ allocate(bool compress, int compression_flags, zip_error_t *error) {
static void *
-compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
+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, int compression_flags, zip_error_t *error) {
+decompress_allocate(zip_uint16_t method, zip_uint32_t compression_flags, zip_error_t *error) {
+ (void)method;
return allocate(false, compression_flags, error);
}
@@ -90,45 +110,48 @@ deallocate(void *ud) {
}
-static int
-compression_flags(void *ud) {
+static zip_uint16_t
+general_purpose_bit_flags(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
if (!ctx->compress) {
- return 0;
+ return 0;
}
- if (ctx->compression_flags < 3) {
- return 2;
+ if (ctx->level < 3) {
+ return 2 << 1;
}
- else if (ctx->compression_flags > 7) {
- return 1;
+ else if (ctx->level > 7) {
+ return 1 << 1;
}
return 0;
}
static bool
-start(void *ud) {
+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->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
+ /* 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);
+ ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
}
if (ret != Z_OK) {
- zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
- return false;
+ zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
+ return false;
}
@@ -142,15 +165,15 @@ end(void *ud) {
int err;
if (ctx->compress) {
- err = deflateEnd(&ctx->zstr);
+ err = deflateEnd(&ctx->zstr);
}
else {
- err = inflateEnd(&ctx->zstr);
+ err = inflateEnd(&ctx->zstr);
}
if (err != Z_OK) {
- zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
- return false;
+ zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
+ return false;
}
return true;
@@ -162,8 +185,8 @@ 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;
+ zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
+ return false;
}
ctx->zstr.avail_in = (uInt)length;
@@ -184,47 +207,51 @@ end_of_input(void *ud) {
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;
- ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
+ 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);
+ ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);
}
else {
- ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
+ ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
}
- *length = *length - ctx->zstr.avail_out;
+ *length = avail_out - ctx->zstr.avail_out;
switch (ret) {
case Z_OK:
- return ZIP_COMPRESSION_OK;
+ return ZIP_COMPRESSION_OK;
case Z_STREAM_END:
- return ZIP_COMPRESSION_END;
+ return ZIP_COMPRESSION_END;
case Z_BUF_ERROR:
- if (ctx->zstr.avail_in == 0) {
- return ZIP_COMPRESSION_NEED_DATA;
- }
+ if (ctx->zstr.avail_in == 0) {
+ return ZIP_COMPRESSION_NEED_DATA;
+ }
- /* fallthrough */
+ /* fallthrough */
default:
- zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
- return ZIP_COMPRESSION_ERROR;
+ zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
+ return ZIP_COMPRESSION_ERROR;
}
}
-// clang-format off
+/* clang-format off */
zip_compression_algorithm_t zip_algorithm_deflate_compress = {
+ maximum_compressed_size,
compress_allocate,
deallocate,
- compression_flags,
+ general_purpose_bit_flags,
+ 20,
start,
end,
input,
@@ -234,9 +261,11 @@ zip_compression_algorithm_t zip_algorithm_deflate_compress = {
zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
+ maximum_compressed_size,
decompress_allocate,
deallocate,
- compression_flags,
+ general_purpose_bit_flags,
+ 20,
start,
end,
input,
@@ -244,4 +273,4 @@ zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
process
};
-// clang-format on
+/* clang-format on */
diff --git a/src/Common/libzip/zip_algorithm_xz.c b/src/Common/libzip/zip_algorithm_xz.c
new file mode 100644
index 00000000..d7a7142d
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <limits.h>
+#include <lzma.h>
+#include <stdlib.h>
+#include <zlib.h>
+
+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/src/Common/libzip/zip_algorithm_zstd.c b/src/Common/libzip/zip_algorithm_zstd.c
new file mode 100644
index 00000000..d005da9d
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+#include <zstd.h>
+#include <zstd_errors.h>
+
+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/src/Common/libzip/zip_buffer.c b/src/Common/libzip/zip_buffer.c
index 37977f09..e2103f04 100644
--- a/src/Common/libzip/zip_buffer.c
+++ b/src/Common/libzip/zip_buffer.c
@@ -1,9 +1,9 @@
/*
zip_buffer.c -- bounds checked access to memory buffer
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -45,11 +45,11 @@ _zip_buffer_data(zip_buffer_t *buffer) {
void
_zip_buffer_free(zip_buffer_t *buffer) {
if (buffer == NULL) {
- return;
+ return;
}
if (buffer->free_data) {
- free(buffer->data);
+ free(buffer->data);
}
free(buffer);
@@ -69,7 +69,7 @@ _zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) {
data = _zip_buffer_peek(buffer, length);
if (data != NULL) {
- buffer->offset += length;
+ buffer->offset += length;
}
return data;
@@ -81,7 +81,7 @@ _zip_buffer_get_16(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 2);
if (data == NULL) {
- return 0;
+ return 0;
}
return (zip_uint16_t)(data[0] + (data[1] << 8));
@@ -93,7 +93,7 @@ _zip_buffer_get_32(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 4);
if (data == NULL) {
- return 0;
+ return 0;
}
return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0];
@@ -105,7 +105,7 @@ _zip_buffer_get_64(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 8);
if (data == NULL) {
- return 0;
+ 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];
@@ -117,7 +117,7 @@ _zip_buffer_get_8(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 1);
if (data == NULL) {
- return 0;
+ return 0;
}
return data[0];
@@ -132,13 +132,20 @@ _zip_buffer_left(zip_buffer_t *buffer) {
zip_uint64_t
_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
+ zip_uint64_t copied;
+
if (_zip_buffer_left(buffer) < length) {
- length = _zip_buffer_left(buffer);
+ length = _zip_buffer_left(buffer);
}
- memcpy(data, _zip_buffer_get(buffer, length), length);
+ 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 length;
+ return copied;
}
@@ -147,17 +154,23 @@ _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)) == NULL) {
- return 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;
+ if (free_data) {
+ free(data);
+ }
+ return NULL;
}
buffer->ok = true;
@@ -175,13 +188,13 @@ _zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *b
zip_buffer_t *buffer;
if ((buffer = _zip_buffer_new(buf, size)) == NULL) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- return 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;
+ _zip_buffer_free(buffer);
+ return NULL;
}
return buffer;
@@ -205,8 +218,8 @@ _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;
+ buffer->ok = false;
+ return NULL;
}
data = buffer->data + buffer->offset;
@@ -218,10 +231,10 @@ _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;
+ return -1;
}
- memcpy(dst, src, length);
+ (void)memcpy_s(dst, length, src, length);
return 0;
}
@@ -231,7 +244,7 @@ _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;
+ return -1;
}
data[0] = (zip_uint8_t)(i & 0xff);
@@ -246,7 +259,7 @@ _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;
+ return -1;
}
data[0] = (zip_uint8_t)(i & 0xff);
@@ -263,7 +276,7 @@ _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;
+ return -1;
}
data[0] = (zip_uint8_t)(i & 0xff);
@@ -284,7 +297,7 @@ _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;
+ return -1;
}
data[0] = i;
@@ -296,8 +309,8 @@ _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) {
int
_zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) {
if (offset > buffer->size) {
- buffer->ok = false;
- return -1;
+ buffer->ok = false;
+ return -1;
}
buffer->ok = true;
@@ -312,8 +325,8 @@ _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;
+ buffer->ok = false;
+ return -1;
}
return _zip_buffer_set_offset(buffer, offset);
}
diff --git a/src/Common/libzip/zip_close.c b/src/Common/libzip/zip_close.c
index 26572261..ddc2c245 100644
--- a/src/Common/libzip/zip_close.c
+++ b/src/Common/libzip/zip_close.c
@@ -1,9 +1,9 @@
/*
zip_close.c -- close zip archive and update changes
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -36,25 +36,18 @@
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <sys/stat.h>
-#include <sys/types.h>
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#endif
-static int add_data(zip_t *, zip_source_t *, zip_dirent_t *);
+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) {
@@ -65,204 +58,235 @@ zip_close(zip_t *za) {
int changed;
if (za == NULL)
- return -1;
+ return -1;
changed = _zip_changed(za, &survivors);
- /* don't create zip files with no entries */
- if (survivors == 0) {
- if ((za->open_flags & ZIP_TRUNCATE) || changed) {
- if (zip_source_remove(za->src) < 0) {
- _zip_error_set_from_source(&za->error, za->src);
- return -1;
- }
- }
- zip_discard(za);
- return 0;
+ 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;
}
- if (!changed) {
- 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;
+ 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;
+ 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;
- j++;
+ 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;
+ 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_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) {
- unchanged_offset = 0;
+ 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 == 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_source_begin_write(za->src) < 0) {
+ zip_error_set_from_source(&za->error, za->src);
+ free(filelist);
+ return -1;
+ }
}
- _zip_progress_start(za->progress);
+ 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;
-
- _zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors);
-
- 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));
-
- /* 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 ((off = zip_source_tell_write(za->src)) < 0) {
- 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_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
- error = 1;
- break;
- }
- }
-
- /* add_data writes dirent */
- if (add_data(za, zs ? zs : entry->source, de) < 0) {
- error = 1;
- if (zs)
- zip_source_free(zs);
- break;
- }
- if (zs)
- zip_source_free(zs);
- }
- else {
- zip_uint64_t offset;
-
- /* when copying data, all sizes are known -> no data descriptor needed */
- 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;
- }
- }
+ 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;
+ 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;
- }
+ if (zip_source_commit_write(za->src) != 0) {
+ zip_error_set_from_source(&za->error, za->src);
+ error = 1;
+ }
+ _zip_progress_end(za->progress);
}
- _zip_progress_end(za->progress);
-
if (error) {
- zip_source_rollback_write(za->src);
- return -1;
+ zip_source_rollback_write(za->src);
+ return -1;
}
zip_discard(za);
@@ -272,97 +296,96 @@ zip_close(zip_t *za) {
static int
-add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
+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;
- struct zip_stat st;
+ 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;
- zip_int8_t compression_flags;
bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
if (zip_source_stat(src, &st) < 0) {
- _zip_error_set_from_source(&za->error, src);
- return -1;
+ 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;
+ 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;
+ 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;
+ st.valid |= ZIP_STAT_COMP_SIZE;
+ st.comp_size = st.size;
}
else {
- /* we'll recompress */
- st.valid &= ~ZIP_STAT_COMP_SIZE;
+ /* 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;
+ st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
+ st.encryption_method = ZIP_EM_NONE;
}
flags = ZIP_EF_LOCAL;
if ((st.valid & ZIP_STAT_SIZE) == 0) {
- flags |= ZIP_FL_FORCE_ZIP64;
- data_length = -1;
+ /* 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_size;
-
- switch (ZIP_CM_ACTUAL(de->comp_method)) {
- case ZIP_CM_BZIP2:
- /* computed by looking at increase of 10 random files of size 1MB when
- * compressed with bzip2, rounded up: 1.006 */
- max_size = 4269351188u;
- break;
-
- case ZIP_CM_DEFLATE:
- /* max deflate size increase: size + ceil(size/16k)*5+6 */
- max_size = 4293656963u;
- break;
-
- case ZIP_CM_STORE:
- max_size = 0xffffffffu;
- break;
-
- default:
- max_size = 0;
- }
-
- if (st.size > max_size) {
- flags |= ZIP_FL_FORCE_ZIP64;
- }
- }
- else
- de->comp_size = st.comp_size;
+ 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;
+ 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;
+ return -1;
}
- needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method);
+ 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);
@@ -373,145 +396,172 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
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;
+ zip_encryption_implementation impl;
- if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
- zip_source_free(src_final);
- return -1;
- }
- if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
- /* error set by impl */
- zip_source_free(src_final);
- return -1;
- }
+ if ((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;
+ }
- zip_source_free(src_final);
- src_final = src_tmp;
+ 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;
- }
+ if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
+ zip_source_free(src_final);
+ return -1;
+ }
- zip_source_free(src_final);
- src_final = src_tmp;
+ src_final = src_tmp;
}
if (needs_crc) {
- if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) {
- zip_source_free(src_final);
- return -1;
- }
+ if ((src_tmp = zip_source_crc_create(src_final, 0, &za->error)) == NULL) {
+ zip_source_free(src_final);
+ return -1;
+ }
- zip_source_free(src_final);
- src_final = src_tmp;
+ 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;
- }
+ if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
+ zip_source_free(src_final);
+ return -1;
+ }
- zip_source_free(src_final);
- src_final = src_tmp;
+ src_final = src_tmp;
}
if (needs_encrypt) {
- zip_encryption_implementation impl;
- const char *password = NULL;
-
- if (de->password) {
- password = de->password;
- }
- else if (za->default_password) {
- password = za->default_password;
- }
-
- if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
- zip_source_free(src_final);
- return -1;
- }
- if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
- /* error set by impl */
- zip_source_free(src_final);
- return -1;
- }
-
- zip_source_free(src_final);
- src_final = src_tmp;
+ 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;
+ 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;
+ zip_error_set_from_source(&za->error, src_final);
+ ret = -1;
}
- if ((compression_flags = zip_source_get_compression_flags(src_final)) < 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;
+ return -1;
}
if ((offend = zip_source_tell_write(za->src)) < 0) {
- _zip_error_set_from_source(&za->error, za->src);
- return -1;
+ 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;
+ 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;
+ 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);
+ 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);
- de->bitflags = (zip_uint16_t)((de->bitflags & (zip_uint16_t)~6) | ((zip_uint8_t)compression_flags << 1));
- _zip_dirent_set_version_needed(de, (flags & ZIP_FL_FORCE_ZIP64) != 0);
+ _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;
+ 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;
+ /* 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;
+ 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;
@@ -521,29 +571,32 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) {
static int
copy_data(zip_t *za, zip_uint64_t len) {
DEFINE_BYTE_ARRAY(buf, BUFSIZE);
- size_t n;
double total = (double)len;
if (!byte_array_init(buf, BUFSIZE)) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
- return -1;
+ zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+ return -1;
}
while (len > 0) {
- n = len > BUFSIZE ? BUFSIZE : len;
- if (_zip_read(za->src, buf, n, &za->error) < 0) {
- byte_array_fini(buf);
- return -1;
- }
+ zip_uint64_t n = ZIP_MIN(len, BUFSIZE);
- if (_zip_write(za, buf, n) < 0) {
- byte_array_fini(buf);
- return -1;
- }
+ if (_zip_read(za->src, buf, n, &za->error) < 0) {
+ byte_array_fini(buf);
+ return -1;
+ }
- len -= n;
+ if (_zip_write(za, buf, n) < 0) {
+ byte_array_fini(buf);
+ return -1;
+ }
- _zip_progress_update(za->progress, (total - (double)len) / total);
+ 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);
@@ -558,31 +611,35 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
int ret;
if (zip_source_open(src) < 0) {
- _zip_error_set_from_source(&za->error, src);
- return -1;
+ 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;
+ 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;
- _zip_progress_update(za->progress, (double)current / (double)data_length);
- }
+ 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;
+ zip_error_set_from_source(&za->error, src);
+ ret = -1;
}
byte_array_fini(buf);
@@ -594,18 +651,16 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
static int
write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
- zip_int64_t cd_start, end, size;
-
- if ((cd_start = zip_source_tell_write(za->src)) < 0) {
- return -1;
+ if (zip_source_tell_write(za->src) < 0) {
+ return -1;
}
- if ((size = _zip_cdir_write(za, filelist, survivors)) < 0) {
- return -1;
+ if (_zip_cdir_write(za, filelist, survivors) < 0) {
+ return -1;
}
- if ((end = zip_source_tell_write(za->src)) < 0) {
- return -1;
+ if (zip_source_tell_write(za->src) < 0) {
+ return -1;
}
return 0;
@@ -620,22 +675,71 @@ _zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
changed = 0;
survivors = 0;
- if (za->comment_changed || za->ch_flags != za->flags) {
- changed = 1;
+ 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 (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
+ changed = 1;
+ }
+ if (!za->entry[i].deleted) {
+ survivors++;
+ }
}
if (survivorsp) {
- *survivorsp = survivors;
+ *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/src/Common/libzip/zip_crypto.h b/src/Common/libzip/zip_crypto.h
new file mode 100644
index 00000000..0d74d1a4
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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/src/Common/libzip/zip_crypto_commoncrypto.c b/src/Common/libzip/zip_crypto_commoncrypto.c
new file mode 100644
index 00000000..b198be56
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+
+#include "zipint.h"
+
+#include "zip_crypto.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+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/src/Common/libzip/zip_crypto_commoncrypto.h b/src/Common/libzip/zip_crypto_commoncrypto.h
new file mode 100644
index 00000000..01828cc6
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <CommonCrypto/CommonCrypto.h>
+
+#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/src/Common/libzip/zip_crypto_gnutls.c b/src/Common/libzip/zip_crypto_gnutls.c
new file mode 100644
index 00000000..1a25aa12
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+
+#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/src/Common/libzip/zip_crypto_gnutls.h b/src/Common/libzip/zip_crypto_gnutls.h
new file mode 100644
index 00000000..dc8b97a4
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <nettle/aes.h>
+#include <nettle/pbkdf2.h>
+
+#include <gnutls/gnutls.h>
+
+#include <gnutls/crypto.h>
+
+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/src/Common/libzip/zip_crypto_mbedtls.c b/src/Common/libzip/zip_crypto_mbedtls.c
new file mode 100644
index 00000000..84544a82
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+
+#include "zipint.h"
+
+#include "zip_crypto.h"
+
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/entropy.h>
+#include <mbedtls/pkcs5.h>
+
+#include <limits.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;
+ }
+
+ 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/src/Common/libzip/zip_crypto_mbedtls.h b/src/Common/libzip/zip_crypto_mbedtls.h
new file mode 100644
index 00000000..1151fff7
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <mbedtls/aes.h>
+#include <mbedtls/md.h>
+
+#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/src/Common/libzip/zip_crypto_openssl.c b/src/Common/libzip/zip_crypto_openssl.c
new file mode 100644
index 00000000..7f1da10e
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+
+#include "zipint.h"
+
+#include "zip_crypto.h"
+
+#include <limits.h>
+#include <openssl/rand.h>
+
+#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/src/Common/libzip/zip_crypto_openssl.h b/src/Common/libzip/zip_crypto_openssl.h
new file mode 100644
index 00000000..198a9071
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <openssl/evp.h>
+#include <openssl/hmac.h>
+
+#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/src/Common/libzip/zip_crypto_win.c b/src/Common/libzip/zip_crypto_win.c
new file mode 100644
index 00000000..ee3ccc30
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+#include <limits.h>
+
+#include "zipint.h"
+
+#include "zip_crypto.h"
+
+#define WIN32_LEAN_AND_MEAN
+#define NOCRYPT
+
+#include <windows.h>
+
+#include <bcrypt.h>
+
+#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 <math.h>
+
+#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/src/Common/libzip/zip_crypto_win.h b/src/Common/libzip/zip_crypto_win.h
new file mode 100644
index 00000000..a533fe2d
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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/src/Common/libzip/zip_delete.c b/src/Common/libzip/zip_delete.c
index 458a1b84..676c16bf 100644
--- a/src/Common/libzip/zip_delete.c
+++ b/src/Common/libzip/zip_delete.c
@@ -1,9 +1,9 @@
/*
zip_delete.c -- delete file from zip archive
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,27 +40,27 @@ 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;
+ 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;
+ zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+ return -1;
}
if ((name = _zip_get_name(za, idx, 0, &za->error)) == NULL) {
- return -1;
+ return -1;
}
if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) {
- return -1;
+ return -1;
}
/* allow duplicate file names, because the file will
* be removed directly afterwards */
if (_zip_unchange(za, idx, 1) != 0)
- return -1;
+ return -1;
za->entry[idx].deleted = 1;
diff --git a/src/Common/libzip/zip_dir_add.c b/src/Common/libzip/zip_dir_add.c
index 46c76cf7..c0108191 100644
--- a/src/Common/libzip/zip_dir_add.c
+++ b/src/Common/libzip/zip_dir_add.c
@@ -1,9 +1,9 @@
/*
zip_dir_add.c -- add directory
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -48,31 +48,31 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
zip_source_t *source;
if (ZIP_IS_RDONLY(za)) {
- zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
- return -1;
+ 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;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return -1;
}
s = NULL;
len = strlen(name);
if (name[len - 1] != '/') {
- if ((s = (char *)malloc(len + 2)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
- return -1;
- }
- strcpy(s, name);
- s[len] = '/';
- s[len + 1] = '\0';
+ 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;
+ free(s);
+ return -1;
}
idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags);
@@ -80,12 +80,12 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
free(s);
if (idx < 0)
- zip_source_free(source);
+ 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;
- }
+ 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/src/Common/libzip/zip_dirent.c b/src/Common/libzip/zip_dirent.c
index 4dcb3391..45a2a6a2 100644
--- a/src/Common/libzip/zip_dirent.c
+++ b/src/Common/libzip/zip_dirent.c
@@ -1,9 +1,9 @@
/*
zip_dirent.c -- read directory entry (local or central), clean dirent
- Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -35,13 +35,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
+#include <zlib.h>
#include "zipint.h"
-static time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t);
static zip_string_t *_zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string_t *str);
static zip_extra_field_t *_zip_ef_utf8(zip_uint16_t, zip_string_t *, zip_error_t *);
static bool _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error);
@@ -52,10 +51,10 @@ _zip_cdir_free(zip_cdir_t *cd) {
zip_uint64_t i;
if (!cd)
- return;
+ return;
for (i = 0; i < cd->nentry; i++)
- _zip_entry_finalize(cd->entry + i);
+ _zip_entry_finalize(cd->entry + i);
free(cd->entry);
_zip_string_free(cd->comment);
free(cd);
@@ -67,8 +66,8 @@ _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;
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
}
cd->entry = NULL;
@@ -78,8 +77,8 @@ _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error) {
cd->is_zip64 = false;
if (!_zip_cdir_grow(cd, nentry, error)) {
- _zip_cdir_free(cd);
- return NULL;
+ _zip_cdir_free(cd);
+ return NULL;
}
return cd;
@@ -92,25 +91,25 @@ _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *err
zip_entry_t *new_entry;
if (additional_entries == 0) {
- return true;
+ 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;
+ 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;
+ 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);
+ _zip_entry_init(cd->entry + i);
}
cd->nentry = cd->nentry_alloc = new_alloc;
@@ -129,54 +128,62 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
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;
+ 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;
+ 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;
+ 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;
+ 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 (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;
+ 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, 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);
@@ -188,25 +195,39 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
comment = za->comment_changed ? za->comment_changes : za->comment_orig;
- _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
+ 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;
+ 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);
+ return -1;
}
_zip_buffer_free(buffer);
- if (comment) {
- if (_zip_write(za, comment->raw, comment->length) < 0) {
- return -1;
- }
+ 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;
@@ -218,12 +239,12 @@ _zip_dirent_clone(const zip_dirent_t *sde) {
zip_dirent_t *tde;
if ((tde = (zip_dirent_t *)malloc(sizeof(*tde))) == NULL)
- return NULL;
+ return NULL;
if (sde)
- memcpy(tde, sde, sizeof(*sde));
+ (void)memcpy_s(tde, sizeof(*tde), sde, sizeof(*sde));
else
- _zip_dirent_init(tde);
+ _zip_dirent_init(tde);
tde->changed = 0;
tde->cloned = 1;
@@ -235,23 +256,23 @@ _zip_dirent_clone(const zip_dirent_t *sde) {
void
_zip_dirent_finalize(zip_dirent_t *zde) {
if (!zde->cloned || zde->changed & ZIP_DIRENT_FILENAME) {
- _zip_string_free(zde->filename);
- zde->filename = NULL;
+ _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;
+ _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;
+ _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;
+ if (zde->password) {
+ _zip_crypto_clear(zde->password, strlen(zde->password));
+ }
+ free(zde->password);
+ zde->password = NULL;
}
}
@@ -259,7 +280,7 @@ _zip_dirent_finalize(zip_dirent_t *zde) {
void
_zip_dirent_free(zip_dirent_t *zde) {
if (zde == NULL)
- return;
+ return;
_zip_dirent_finalize(zde);
free(zde);
@@ -297,7 +318,7 @@ _zip_dirent_init(zip_dirent_t *de) {
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 true;
return false;
}
@@ -308,7 +329,7 @@ _zip_dirent_new(void) {
zip_dirent_t *de;
if ((de = (zip_dirent_t *)malloc(sizeof(*de))) == NULL)
- return NULL;
+ return NULL;
_zip_dirent_init(de);
return de;
@@ -337,32 +358,32 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
size = local ? LENTRYSIZE : CDENTRYSIZE;
if (buffer) {
- if (_zip_buffer_left(buffer) < size) {
- zip_error_set(error, ZIP_ER_NOZIP, 0);
- return -1;
- }
+ 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 ((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;
+ 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);
+ zde->version_madeby = _zip_buffer_get_16(buffer);
else
- zde->version_madeby = 0;
+ 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);
@@ -380,39 +401,39 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
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;
+ 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);
+ 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;
+ 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;
- }
+ 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->encryption_method = ZIP_EM_NONE;
}
zde->filename = NULL;
@@ -422,80 +443,80 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
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, 0);
- return -1;
- }
+ 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);
+ _zip_buffer_free(buffer);
- if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
- return -1;
- }
+ 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, 0);
- }
- 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, 0);
- if (!from_buffer) {
- _zip_buffer_free(buffer);
- }
- return -1;
- }
- }
+ 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;
+ 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, 0);
- if (!from_buffer) {
- _zip_buffer_free(buffer);
- }
- return -1;
- }
- }
+ 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);
@@ -504,76 +525,102 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
/* Zip64 */
if (zde->uncomp_size == ZIP_UINT32_MAX || zde->comp_size == ZIP_UINT32_MAX || zde->offset == ZIP_UINT32_MAX) {
- zip_uint16_t got_len;
- zip_buffer_t *ef_buffer;
- 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);
- /* TODO: if got_len == 0 && !ZIP64_EOCD: no error, 0xffffffff is valid value */
- if (ef == NULL) {
- if (!from_buffer) {
- _zip_buffer_free(buffer);
- }
- return -1;
- }
-
- if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- if (!from_buffer) {
- _zip_buffer_free(buffer);
- }
- return -1;
- }
-
- 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)) {
- zip_error_set(error, ZIP_ER_INCONS, 0);
- _zip_buffer_free(ef_buffer);
- if (!from_buffer) {
- _zip_buffer_free(buffer);
- }
- return -1;
- }
- _zip_buffer_free(ef_buffer);
+ 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;
+ 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_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;
+ zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+ return -1;
}
if (!_zip_dirent_process_winzip_aes(zde, error)) {
- return -1;
+ return -1;
}
zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
- return (zip_int64_t)(size + variable_size);
+ 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;
}
@@ -586,24 +633,24 @@ _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string
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;
+ return str;
}
if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
- return str;
+ 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);
+ 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;
- }
+ if (ef_str != NULL) {
+ _zip_string_free(str);
+ str = ef_str;
+ }
}
_zip_buffer_free(buffer);
@@ -622,68 +669,67 @@ _zip_dirent_process_winzip_aes(zip_dirent_t *de, zip_error_t *error) {
if (de->comp_method != ZIP_CM_WINZIP_AES) {
- return true;
+ return true;
}
ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, ZIP_EF_WINZIP_AES, 0, ZIP_EF_BOTH, NULL);
if (ef == NULL || ef_len < 7) {
- zip_error_set(error, ZIP_ER_INCONS, 0);
- return false;
+ 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;
+ zip_error_set(error, ZIP_ER_INTERNAL, 0);
+ return false;
}
/* version */
crc_valid = true;
switch (_zip_buffer_get_16(buffer)) {
- case 1:
- break;
-
- case 2:
- if (de->uncomp_size < 20 /* TODO: constant */) {
- crc_valid = false;
- }
- break;
+ case 1:
+ break;
- default:
- zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
- _zip_buffer_free(buffer);
- return false;
+ 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;
+ 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;
+ enc_method = ZIP_EM_AES_128;
+ break;
case 2:
- enc_method = ZIP_EM_AES_192;
- break;
+ enc_method = ZIP_EM_AES_192;
+ break;
case 3:
- enc_method = ZIP_EM_AES_256;
- break;
+ enc_method = ZIP_EM_AES_256;
+ break;
default:
- zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
- _zip_buffer_free(buffer);
- return false;
+ zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
+ _zip_buffer_free(buffer);
+ return false;
}
if (ef_len != 7) {
- zip_error_set(error, ZIP_ER_INCONS, 0);
- _zip_buffer_free(buffer);
- return false;
+ zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_WINZIPAES_EF);
+ _zip_buffer_free(buffer);
+ return false;
}
de->crc_valid = crc_valid;
@@ -706,22 +752,22 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) {
size = local ? LENTRYSIZE : CDENTRYSIZE;
if (zip_source_seek(src, local ? 26 : 28, SEEK_CUR) < 0) {
- _zip_error_set_from_source(error, src);
- return -1;
+ 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;
+ return -1;
}
for (i = 0; i < (local ? 2 : 3); i++) {
- size += _zip_buffer_get_16(buffer);
+ 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_error_set(error, ZIP_ER_INTERNAL, 0);
+ _zip_buffer_free(buffer);
+ return -1;
}
_zip_buffer_free(buffer);
@@ -758,30 +804,30 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
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;
+ 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;
- }
+ 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;
+ de->bitflags &= (zip_uint16_t)~ZIP_GPBF_ENCRYPTED;
}
else {
- de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
+ de->bitflags |= (zip_uint16_t)ZIP_GPBF_ENCRYPTED;
}
is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
@@ -789,188 +835,197 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
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;
+ 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;
+ 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_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, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby));
+ _zip_buffer_put_16(buffer, de->version_madeby);
}
- _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_needed));
+ _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);
+ _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES);
}
else {
- _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method);
+ _zip_buffer_put_16(buffer, (zip_uint16_t)de->comp_method);
}
- _zip_u2d_time(de->last_mod, &dostime, &dosdate);
+ 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);
+ _zip_buffer_put_32(buffer, 0);
}
else {
- _zip_buffer_put_32(buffer, de->crc);
+ _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);
+ /* 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);
- }
+ 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));
- /* TODO: check for overflow */
- ef_total_size = (zip_uint32_t)_zip_ef_size(de->extra_fields, flags) + (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
+ 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_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);
+ _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;
+ 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);
+ _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 (_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;
- }
+ if (_zip_ef_write(za, ef, ZIP_EF_BOTH) < 0) {
+ _zip_ef_free(ef);
+ return -1;
+ }
}
_zip_ef_free(ef);
- if (de->extra_fields) {
- if (_zip_ef_write(za, de->extra_fields, flags) < 0) {
- return -1;
- }
+ 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) {
- if (de->comment) {
- if (_zip_string_write(za, de->comment) < 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;
+ }
+ }
}
@@ -978,7 +1033,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) {
}
-static time_t
+time_t
_zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate) {
struct tm tm;
@@ -1007,18 +1062,18 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
zip_extra_field_t *ef;
if ((raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
- /* error already set */
- return 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;
+ 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_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
}
_zip_buffer_put_8(buffer, 1);
@@ -1026,9 +1081,9 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
_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;
+ 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);
@@ -1041,82 +1096,112 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) {
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;
+ error = &za->error;
if (idx >= za->nentry) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
+ 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;
+ 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;
+ return za->entry[idx].changes;
}
void
_zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) {
- struct tm *tm;
-
- tm = localtime(&intime);
- if (tm == NULL) {
- /* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */
- *ddate = (1 << 5) + 1;
- *dtime = 0;
- return;
+ 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 (tm->tm_year < 80) {
- tm->tm_year = 80;
+ if (tpm->tm_year < 80) {
+ tpm->tm_year = 80;
}
- *ddate = (zip_uint16_t)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
- *dtime = (zip_uint16_t)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
-
- return;
+ *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_set_version_needed(zip_dirent_t *de, bool force_zip64) {
+_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 (de->comp_method == ZIP_CM_LZMA) {
- de->version_needed = 63;
- return;
+ 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 (de->comp_method == ZIP_CM_BZIP2) {
- de->version_needed = 46;
- return;
+ 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 (force_zip64 || _zip_dirent_needs_zip64(de, 0)) {
- de->version_needed = 45;
- return;
+ 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 (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) {
- de->version_needed = 20;
- return;
+ if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) {
+ de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed);
}
- /* directory */
- if ((length = _zip_string_length(de->filename)) > 0) {
- if (de->filename->raw[length - 1] == '/') {
- de->version_needed = 20;
- return;
- }
+ 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 */
- de->version_needed = 10;
}
diff --git a/src/Common/libzip/zip_discard.c b/src/Common/libzip/zip_discard.c
index 94972cfb..d1dc4f8b 100644
--- a/src/Common/libzip/zip_discard.c
+++ b/src/Common/libzip/zip_discard.c
@@ -1,9 +1,9 @@
/*
zip_discard.c -- discard and free struct zip
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -46,11 +46,11 @@ zip_discard(zip_t *za) {
zip_uint64_t i;
if (za == NULL)
- return;
+ return;
if (za->src) {
- zip_source_close(za->src);
- zip_source_free(za->src);
+ zip_source_close(za->src);
+ zip_source_free(za->src);
}
free(za->default_password);
@@ -60,13 +60,13 @@ zip_discard(zip_t *za) {
_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->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]);
+ _zip_source_invalidate(za->open_source[i]);
}
free(za->open_source);
diff --git a/src/Common/libzip/zip_entry.c b/src/Common/libzip/zip_entry.c
index 55f64581..35a36e4a 100644
--- a/src/Common/libzip/zip_entry.c
+++ b/src/Common/libzip/zip_entry.c
@@ -1,9 +1,9 @@
/*
zip_entry.c -- struct zip_entry helper functions
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/Common/libzip/zip_err_str.c b/src/Common/libzip/zip_err_str.c
index 3d9ee54e..28af773b 100644
--- a/src/Common/libzip/zip_err_str.c
+++ b/src/Common/libzip/zip_err_str.c
@@ -1,20 +1,79 @@
/*
- This file was generated automatically by ./make_zip_err_str.sh
- from ./zip.h; make changes there.
- */
+ This file was generated automatically by CMake
+ from zip.h and zipint.h; make changes there.
+*/
#include "zipint.h"
-const char *const _zip_err_str[] = {
- "No error", "Multi-disk zip archives not supported", "Renaming temporary file failed", "Closing zip archive failed", "Seek error", "Read error", "Write error", "CRC error", "Containing zip archive was closed", "No such file", "File already exists", "Can't open file", "Failure to create temporary file", "Zlib error", "Malloc failure", "Entry has been changed", "Compression method not supported", "Premature end of file", "Invalid argument", "Not a zip archive", "Internal error", "Zip archive inconsistent", "Can't remove file", "Entry has been deleted", "Encryption method not supported", "Read-only archive", "No password provided", "Wrong password provided", "Operation not supported", "Resource still in use", "Tell error", "Compressed data invalid",
-};
-
-const int _zip_nerr_str = sizeof(_zip_err_str) / sizeof(_zip_err_str[0]);
-
+#define L ZIP_ET_LIBZIP
#define N ZIP_ET_NONE
#define S ZIP_ET_SYS
#define Z ZIP_ET_ZLIB
-const int _zip_err_type[] = {
- N, N, S, S, S, S, S, N, N, N, N, S, S, Z, N, N, N, N, N, N, N, N, S, N, N, N, N, N, N, N, S, N,
+#define E ZIP_DETAIL_ET_ENTRY
+#define G ZIP_DETAIL_ET_GLOBAL
+
+const struct _zip_err_info _zip_err_str[] = {
+ { N, "No error" },
+ { N, "Multi-disk zip archives not supported" },
+ { S, "Renaming temporary file failed" },
+ { S, "Closing zip archive failed" },
+ { S, "Seek error" },
+ { S, "Read error" },
+ { S, "Write error" },
+ { N, "CRC error" },
+ { N, "Containing zip archive was closed" },
+ { N, "No such file" },
+ { N, "File already exists" },
+ { S, "Can't open file" },
+ { S, "Failure to create temporary file" },
+ { Z, "Zlib error" },
+ { N, "Malloc failure" },
+ { N, "Entry has been changed" },
+ { N, "Compression method not supported" },
+ { N, "Premature end of file" },
+ { N, "Invalid argument" },
+ { N, "Not a zip archive" },
+ { N, "Internal error" },
+ { L, "Zip archive inconsistent" },
+ { S, "Can't remove file" },
+ { N, "Entry has been deleted" },
+ { N, "Encryption method not supported" },
+ { N, "Read-only archive" },
+ { N, "No password provided" },
+ { N, "Wrong password provided" },
+ { N, "Operation not supported" },
+ { N, "Resource still in use" },
+ { 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]);
+
+const struct _zip_err_info _zip_err_details[] = {
+ { G, "no detail" },
+ { G, "central directory overlaps EOCD, or there is space between them" },
+ { G, "archive comment length incorrect" },
+ { G, "central directory length invalid" },
+ { E, "central header invalid" },
+ { G, "central directory count of entries is incorrect" },
+ { E, "local and central headers do not match" },
+ { G, "wrong EOCD length" },
+ { G, "EOCD64 overlaps EOCD, or there is space between them" },
+ { G, "EOCD64 magic incorrect" },
+ { G, "EOCD64 and EOCD do not match" },
+ { G, "invalid value in central directory" },
+ { E, "variable size fields overflow header" },
+ { E, "invalid UTF-8 in filename" },
+ { E, "invalid UTF-8 in comment" },
+ { E, "invalid Zip64 extra field" },
+ { E, "invalid WinZip AES extra field" },
+ { E, "garbage at end of extra fields" },
+ { E, "extra field length is invalid" },
+ { E, "file length in header doesn't match actual file length" },
+};
+
+const int _zip_err_details_count = sizeof(_zip_err_details)/sizeof(_zip_err_details[0]);
diff --git a/src/Common/libzip/zip_error.c b/src/Common/libzip/zip_error.c
index e05ae500..c498e086 100644
--- a/src/Common/libzip/zip_error.c
+++ b/src/Common/libzip/zip_error.c
@@ -1,9 +1,9 @@
/*
zip_error.c -- zip_error_t helper functions
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -67,30 +67,31 @@ 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:
- error->sys_err = errno;
- break;
-
- default:
- error->sys_err = 0;
- break;
+ 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_nerr_str)
- return ZIP_ET_NONE;
+ if (error->zip_err < 0 || error->zip_err >= _zip_err_str_count)
+ return ZIP_ET_NONE;
- return _zip_err_type[error->zip_err];
+ return _zip_err_str[error->zip_err].type;
}
void
_zip_error_clear(zip_error_t *err) {
if (err == NULL)
- return;
+ return;
err->zip_err = ZIP_ER_OK;
err->sys_err = 0;
@@ -100,7 +101,7 @@ _zip_error_clear(zip_error_t *err) {
void
_zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
if (dst == NULL) {
- return;
+ return;
}
dst->zip_err = src->zip_err;
@@ -111,12 +112,12 @@ _zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
void
_zip_error_get(const zip_error_t *err, int *zep, int *sep) {
if (zep)
- *zep = err->zip_err;
+ *zep = err->zip_err;
if (sep) {
- if (zip_error_system_type(err) != ZIP_ET_NONE)
- *sep = err->sys_err;
- else
- *sep = 0;
+ if (zip_error_system_type(err) != ZIP_ET_NONE)
+ *sep = err->sys_err;
+ else
+ *sep = 0;
}
}
@@ -124,14 +125,19 @@ _zip_error_get(const zip_error_t *err, int *zep, int *sep) {
void
zip_error_set(zip_error_t *err, int ze, int se) {
if (err) {
- err->zip_err = ze;
- err->sys_err = se;
+ err->zip_err = ze;
+ err->sys_err = se;
}
}
void
-_zip_error_set_from_source(zip_error_t *err, zip_source_t *src) {
+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));
}
@@ -141,7 +147,7 @@ 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;
+ return -1;
}
e[0] = zip_error_code_zip(error);
diff --git a/src/Common/libzip/zip_error_clear.c b/src/Common/libzip/zip_error_clear.c
index 6b3a8da0..94ff5062 100644
--- a/src/Common/libzip/zip_error_clear.c
+++ b/src/Common/libzip/zip_error_clear.c
@@ -1,9 +1,9 @@
/*
zip_error_clear.c -- clear zip error
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -38,7 +38,7 @@
ZIP_EXTERN void
zip_error_clear(zip_t *za) {
if (za == NULL)
- return;
+ return;
_zip_error_clear(&za->error);
}
diff --git a/src/Common/libzip/zip_error_get.c b/src/Common/libzip/zip_error_get.c
index 12341d1c..c0418f0d 100644
--- a/src/Common/libzip/zip_error_get.c
+++ b/src/Common/libzip/zip_error_get.c
@@ -1,9 +1,9 @@
/*
zip_error_get.c -- get zip error
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/Common/libzip/zip_error_get_sys_type.c b/src/Common/libzip/zip_error_get_sys_type.c
index 80bfc0ca..a22ffb03 100644
--- a/src/Common/libzip/zip_error_get_sys_type.c
+++ b/src/Common/libzip/zip_error_get_sys_type.c
@@ -1,9 +1,9 @@
/*
zip_error_get_sys_type.c -- return type of system error code
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -37,8 +37,9 @@
ZIP_EXTERN int
zip_error_get_sys_type(int ze) {
- if (ze < 0 || ze >= _zip_nerr_str)
- return 0;
+ if (ze < 0 || ze >= _zip_err_str_count) {
+ return 0;
+ }
- return _zip_err_type[ze];
+ return _zip_err_str[ze].type;
}
diff --git a/src/Common/libzip/zip_error_strerror.c b/src/Common/libzip/zip_error_strerror.c
index 0f650b5f..fe04cbb4 100644
--- a/src/Common/libzip/zip_error_strerror.c
+++ b/src/Common/libzip/zip_error_strerror.c
@@ -1,9 +1,9 @@
/*
zip_error_sterror.c -- get string representation of struct zip_error
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -35,48 +35,94 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <zlib.h>
#include "zipint.h"
-
ZIP_EXTERN const char *
zip_error_strerror(zip_error_t *err) {
- const char *zs, *ss;
- char buf[128], *s;
+ 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_nerr_str) {
- sprintf(buf, "Unknown error %d", err->zip_err);
- zs = NULL;
- ss = buf;
+ 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 {
- zs = _zip_err_str[err->zip_err];
-
- switch (_zip_err_type[err->zip_err]) {
- case ZIP_ET_SYS:
- ss = strerror(err->sys_err);
- break;
-
- case ZIP_ET_ZLIB:
- ss = zError(err->sys_err);
- break;
-
- default:
- ss = NULL;
- }
+ 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 (ss == NULL)
- return zs;
+ if (system_error_string == NULL) {
+ free(system_error_buffer);
+ return zip_error_string;
+ }
else {
- if ((s = (char *)malloc(strlen(ss) + (zs ? strlen(zs) + 2 : 0) + 1)) == NULL)
- return _zip_err_str[ZIP_ER_MEMORY];
-
- sprintf(s, "%s%s%s", (zs ? zs : ""), (zs ? ": " : ""), ss);
- err->str = s;
-
- return s;
+ 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/src/Common/libzip/zip_error_to_str.c b/src/Common/libzip/zip_error_to_str.c
index bf515698..b60b7881 100644
--- a/src/Common/libzip/zip_error_to_str.c
+++ b/src/Common/libzip/zip_error_to_str.c
@@ -1,9 +1,9 @@
/*
zip_error_to_str.c -- get string representation of zip error code
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -33,7 +33,6 @@
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#define _ZIP_COMPILING_DEPRECATED
@@ -42,25 +41,18 @@
ZIP_EXTERN int
zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) {
- const char *zs, *ss;
+ zip_error_t error;
+ const char *error_string;
+ int ret;
- if (ze < 0 || ze >= _zip_nerr_str)
- return snprintf(buf, len, "Unknown error %d", ze);
+ zip_error_init(&error);
+ zip_error_set(&error, ze, se);
- zs = _zip_err_str[ze];
+ error_string = zip_error_strerror(&error);
- switch (_zip_err_type[ze]) {
- case ZIP_ET_SYS:
- ss = strerror(se);
- break;
+ ret = snprintf_s(buf, ZIP_MIN(len, SIZE_MAX), error_string, strlen(error_string));
- case ZIP_ET_ZLIB:
- ss = zError(se);
- break;
+ zip_error_fini(&error);
- default:
- ss = NULL;
- }
-
- return snprintf(buf, len, "%s%s%s", zs, (ss ? ": " : ""), (ss ? ss : ""));
+ return ret;
}
diff --git a/src/Common/libzip/zip_extra_field.c b/src/Common/libzip/zip_extra_field.c
index a17e4916..7aed12ad 100644
--- a/src/Common/libzip/zip_extra_field.c
+++ b/src/Common/libzip/zip_extra_field.c
@@ -1,9 +1,9 @@
/*
zip_extra_field.c -- manipulate extra fields
- Copyright (C) 2012-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -44,19 +44,19 @@ _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) {
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;
+ 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;
@@ -72,27 +72,27 @@ _zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx
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;
+ 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;
@@ -104,10 +104,10 @@ _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;
+ ef2 = ef->next;
+ free(ef->data);
+ free(ef);
+ ef = ef2;
}
}
@@ -120,19 +120,19 @@ _zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t
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;
- }
+ 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);
@@ -146,28 +146,28 @@ _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) {
int duplicate;
if (to == NULL)
- return from;
+ 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;
+ 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;
@@ -179,20 +179,20 @@ _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_fla
zip_extra_field_t *ef;
if ((ef = (zip_extra_field_t *)malloc(sizeof(*ef))) == NULL)
- return 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;
- }
+ if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
+ free(ef);
+ return NULL;
+ }
}
else
- ef->data = NULL;
+ ef->data = NULL;
return ef;
}
@@ -204,63 +204,64 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_
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;
+ 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, 0);
- _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;
+ 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 */
- 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", glen) != 0) {
- zip_error_set(error, ZIP_ER_INCONS, 0);
- _zip_buffer_free(buffer);
- _zip_ef_free(ef_head);
- return false;
- }
+ /* 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;
+ *ef_head_p = ef_head;
}
else {
- _zip_ef_free(ef_head);
+ _zip_ef_free(ef_head);
}
return true;
@@ -276,20 +277,20 @@ _zip_ef_remove_internal(zip_extra_field_t *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;
- }
+ 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;
@@ -302,8 +303,8 @@ _zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) {
size = 0;
for (; ef; ef = ef->next) {
- if (ef->flags & flags & ZIP_EF_BOTH)
- size = (zip_uint16_t)(size + 4 + ef->size);
+ if (ef->flags & flags & ZIP_EF_BOTH)
+ size = (zip_uint16_t)(size + 4 + ef->size);
}
return size;
@@ -316,30 +317,30 @@ _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) {
zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b));
if (buffer == NULL) {
- return -1;
+ 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;
- }
- }
- }
+ 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);
@@ -355,71 +356,71 @@ _zip_read_local_ef(zip_t *za, zip_uint64_t idx) {
zip_uint16_t fname_len, ef_len;
if (idx >= za->nentry) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return -1;
+ 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;
+ return 0;
if (e->orig->offset + 26 > ZIP_INT64_MAX) {
- zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG);
- return -1;
+ 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;
+ 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;
+ 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);
+ 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;
+ 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;
- }
+ 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);
+ ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error);
- if (ef_raw == NULL)
- return -1;
+ 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 (!_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);
- }
+ 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;
+ e->changes->extra_fields = e->orig->extra_fields;
+ e->changes->local_extra_fields_read = 1;
}
return 0;
diff --git a/src/Common/libzip/zip_extra_field_api.c b/src/Common/libzip/zip_extra_field_api.c
index 31808ded..560c71bb 100644
--- a/src/Common/libzip/zip_extra_field_api.c
+++ b/src/Common/libzip/zip_extra_field_api.c
@@ -1,9 +1,9 @@
/*
zip_extra_field_api.c -- public extra fields API functions
- Copyright (C) 2012-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,25 +40,29 @@ zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zi
zip_dirent_t *de;
if ((flags & ZIP_EF_BOTH) == 0) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return -1;
+ 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;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return -1;
}
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
- return -1;
+ return -1;
if (ZIP_IS_RDONLY(za)) {
- zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
- return -1;
+ 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;
+ return -1;
de = za->entry[idx].changes;
@@ -72,25 +76,29 @@ zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
zip_dirent_t *de;
if ((flags & ZIP_EF_BOTH) == 0) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return -1;
+ 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;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return -1;
}
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
- return -1;
+ return -1;
if (ZIP_IS_RDONLY(za)) {
- zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
- return -1;
+ 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;
+ return -1;
de = za->entry[idx].changes;
@@ -108,34 +116,34 @@ zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_u
int i;
if ((flags & ZIP_EF_BOTH) == 0) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return NULL;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return NULL;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
- return NULL;
+ return NULL;
if (flags & ZIP_FL_LOCAL)
- if (_zip_read_local_ef(za, idx) < 0)
- return NULL;
+ 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;
- }
+ 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);
@@ -148,16 +156,16 @@ zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id,
zip_dirent_t *de;
if ((flags & ZIP_EF_BOTH) == 0) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return NULL;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return NULL;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
- return NULL;
+ return NULL;
if (flags & ZIP_FL_LOCAL)
- if (_zip_read_local_ef(za, idx) < 0)
- return NULL;
+ 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);
}
@@ -170,21 +178,21 @@ zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags) {
zip_uint16_t n;
if ((flags & ZIP_EF_BOTH) == 0) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return -1;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return -1;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
- return -1;
+ return -1;
if (flags & ZIP_FL_LOCAL)
- if (_zip_read_local_ef(za, idx) < 0)
- return -1;
+ 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++;
+ if (ef->flags & flags & ZIP_EF_BOTH)
+ n++;
return (zip_int16_t)n;
}
@@ -197,21 +205,21 @@ zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
zip_uint16_t n;
if ((flags & ZIP_EF_BOTH) == 0) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return -1;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return -1;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
- return -1;
+ return -1;
if (flags & ZIP_FL_LOCAL)
- if (_zip_read_local_ef(za, idx) < 0)
- return -1;
+ 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++;
+ if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH))
+ n++;
return (zip_int16_t)n;
}
@@ -225,25 +233,29 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
int i, found, new_len;
if ((flags & ZIP_EF_BOTH) == 0) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return -1;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return -1;
}
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
- return -1;
+ return -1;
if (ZIP_IS_RDONLY(za)) {
- zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
- return -1;
+ 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;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return -1;
}
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
- return -1;
+ return -1;
de = za->entry[idx].changes;
@@ -253,67 +265,67 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
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 (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;
+ 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);
+ ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL);
else
- ls = 0;
+ ls = 0;
if (flags & ZIP_EF_CENTRAL)
- cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
+ cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
else
- cs = 0;
+ cs = 0;
new_len = ls > cs ? ls : cs;
if (found)
- new_len -= ef->size + 4;
+ 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;
+ 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;
+ 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;
- }
+ 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;
+ ef_new->next = ef_prev->next;
+ ef_prev->next = ef_new;
}
else
- de->extra_fields = ef_new;
+ de->extra_fields = ef_new;
return 0;
}
@@ -324,30 +336,30 @@ _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;
+ 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;
+ return 0;
if (e->orig) {
- if (_zip_read_local_ef(za, idx) < 0)
- return -1;
+ 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->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;
+ if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
+ return -1;
}
e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD;
diff --git a/src/Common/libzip/zip_fclose.c b/src/Common/libzip/zip_fclose.c
index 1c69a966..b820d98b 100644
--- a/src/Common/libzip/zip_fclose.c
+++ b/src/Common/libzip/zip_fclose.c
@@ -1,9 +1,9 @@
/*
zip_fclose.c -- close file in zip archive
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -42,11 +42,11 @@ zip_fclose(zip_file_t *zf) {
int ret;
if (zf->src)
- zip_source_free(zf->src);
+ zip_source_free(zf->src);
ret = 0;
if (zf->error.zip_err)
- ret = zf->error.zip_err;
+ ret = zf->error.zip_err;
zip_error_fini(&zf->error);
free(zf);
diff --git a/src/Common/libzip/zip_fdopen.c b/src/Common/libzip/zip_fdopen.c
index 32709355..e72c55dc 100644
--- a/src/Common/libzip/zip_fdopen.c
+++ b/src/Common/libzip/zip_fdopen.c
@@ -1,9 +1,9 @@
/*
zip_fdopen.c -- open read-only archive from file descriptor
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -47,40 +47,45 @@ zip_fdopen(int fd_orig, int _flags, int *zep) {
struct zip_error error;
if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS | ZIP_RDONLY))) {
- _zip_set_open_error(zep, NULL, ZIP_ER_INVAL);
- return NULL;
+ _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;
+ _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;
+ 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;
+ 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_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/src/Common/libzip/zip_file_add.c b/src/Common/libzip/zip_file_add.c
index c2c13d66..c2c41e15 100644
--- a/src/Common/libzip/zip_file_add.c
+++ b/src/Common/libzip/zip_file_add.c
@@ -1,9 +1,9 @@
/*
zip_file_add.c -- add file via callback function
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -36,16 +36,16 @@
/*
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.
+ 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;
+ 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/src/Common/libzip/zip_file_error_clear.c b/src/Common/libzip/zip_file_error_clear.c
index 2e7dcea8..a10bff80 100644
--- a/src/Common/libzip/zip_file_error_clear.c
+++ b/src/Common/libzip/zip_file_error_clear.c
@@ -1,9 +1,9 @@
/*
zip_file_error_clear.c -- clear zip file error
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -38,7 +38,7 @@
ZIP_EXTERN void
zip_file_error_clear(zip_file_t *zf) {
if (zf == NULL)
- return;
+ return;
_zip_error_clear(&zf->error);
}
diff --git a/src/Common/libzip/zip_file_error_get.c b/src/Common/libzip/zip_file_error_get.c
index 1d13807f..b93117bb 100644
--- a/src/Common/libzip/zip_file_error_get.c
+++ b/src/Common/libzip/zip_file_error_get.c
@@ -1,9 +1,9 @@
/*
zip_file_error_get.c -- get zip file error
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/Common/libzip/zip_file_get_comment.c b/src/Common/libzip/zip_file_get_comment.c
index ad944aaf..fa998f02 100644
--- a/src/Common/libzip/zip_file_get_comment.c
+++ b/src/Common/libzip/zip_file_get_comment.c
@@ -1,9 +1,9 @@
/*
zip_file_get_comment.c -- get file comment
- Copyright (C) 2006-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -43,13 +43,13 @@ zip_file_get_comment(zip_t *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_
const zip_uint8_t *str;
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
- return NULL;
+ return NULL;
if ((str = _zip_string_get(de->comment, &len, flags, &za->error)) == NULL)
- return NULL;
+ return NULL;
if (lenp)
- *lenp = len;
+ *lenp = len;
return (const char *)str;
}
diff --git a/src/Common/libzip/zip_file_get_external_attributes.c b/src/Common/libzip/zip_file_get_external_attributes.c
index e2e55357..a79bb3ed 100644
--- a/src/Common/libzip/zip_file_get_external_attributes.c
+++ b/src/Common/libzip/zip_file_get_external_attributes.c
@@ -1,9 +1,9 @@
/*
zip_file_get_external_attributes.c -- get opsys/external attributes
- Copyright (C) 2013-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -38,13 +38,13 @@ zip_file_get_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
zip_dirent_t *de;
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
- return -1;
+ return -1;
if (opsys)
- *opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff);
+ *opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff);
if (attributes)
- *attributes = de->ext_attrib;
+ *attributes = de->ext_attrib;
return 0;
}
diff --git a/src/Common/libzip/zip_file_get_offset.c b/src/Common/libzip/zip_file_get_offset.c
index 858a78a4..72f4880e 100644
--- a/src/Common/libzip/zip_file_get_offset.c
+++ b/src/Common/libzip/zip_file_get_offset.c
@@ -1,9 +1,9 @@
/*
zip_file_get_offset.c -- get offset of file data in archive.
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -33,10 +33,7 @@
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
#include "zipint.h"
@@ -53,24 +50,24 @@ _zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error) {
zip_int32_t size;
if (za->entry[idx].orig == NULL) {
- zip_error_set(error, ZIP_ER_INTERNAL, 0);
- return 0;
+ 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;
+ 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;
+ return 0;
if (offset + (zip_uint32_t)size > ZIP_INT64_MAX) {
- zip_error_set(error, ZIP_ER_SEEK, EFBIG);
- return 0;
+ zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+ return 0;
}
return offset + (zip_uint32_t)size;
@@ -82,38 +79,38 @@ _zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error) {
zip_dirent_t *entry;
if ((offset = _zip_file_get_offset(za, index, error)) == 0) {
- return 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;
+ 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;
- }
+ 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/src/Common/libzip/zip_file_rename.c b/src/Common/libzip/zip_file_rename.c
index cc42dfcc..9ac25814 100644
--- a/src/Common/libzip/zip_file_rename.c
+++ b/src/Common/libzip/zip_file_rename.c
@@ -1,9 +1,9 @@
/*
zip_file_rename.c -- rename file in zip archive
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -43,24 +43,24 @@ zip_file_rename(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags
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;
+ 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;
+ zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+ return -1;
}
if ((old_name = zip_get_name(za, idx, 0)) == NULL)
- return -1;
+ 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;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return -1;
}
return _zip_set_name(za, idx, name, flags);
diff --git a/src/Common/libzip/zip_file_replace.c b/src/Common/libzip/zip_file_replace.c
index 70b379aa..4262d453 100644
--- a/src/Common/libzip/zip_file_replace.c
+++ b/src/Common/libzip/zip_file_replace.c
@@ -1,9 +1,9 @@
/*
zip_file_replace.c -- replace file via callback function
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -38,12 +38,12 @@
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;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return -1;
}
if (_zip_file_replace(za, idx, NULL, source, flags) == -1)
- return -1;
+ return -1;
return 0;
}
@@ -56,31 +56,31 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s
zip_uint64_t za_nentry_prev;
if (ZIP_IS_RDONLY(za)) {
- zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
- return -1;
+ 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;
+ zip_int64_t i = -1;
- if (flags & ZIP_FL_OVERWRITE)
- i = _zip_name_locate(za, name, flags, NULL);
+ 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 (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;
+ 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;
@@ -88,15 +88,15 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s
_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;
+ 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;
diff --git a/src/Common/libzip/zip_file_set_comment.c b/src/Common/libzip/zip_file_set_comment.c
index ae6b6021..570f8e82 100644
--- a/src/Common/libzip/zip_file_set_comment.c
+++ b/src/Common/libzip/zip_file_set_comment.c
@@ -1,9 +1,9 @@
/*
zip_file_set_comment.c -- set comment for file in archive
- Copyright (C) 2006-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -44,57 +44,61 @@ zip_file_set_comment(zip_t *za, zip_uint64_t idx, const char *comment, zip_uint1
int changed;
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
- return -1;
+ return -1;
if (ZIP_IS_RDONLY(za)) {
- zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
- return -1;
+ 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;
+ 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;
+ 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;
+ 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;
+ _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);
+ changed = !_zip_string_equal(e->orig->comment, cstr);
else
- changed = (cstr != NULL);
+ 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;
+ 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;
- }
+ _zip_string_free(cstr);
+ if (e->changes && e->changes->changed == 0) {
+ _zip_dirent_free(e->changes);
+ e->changes = NULL;
+ }
}
return 0;
diff --git a/src/Common/libzip/zip_file_set_encryption.c b/src/Common/libzip/zip_file_set_encryption.c
new file mode 100644
index 00000000..1cdcd4ab
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+#include <string.h>
+
+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/src/Common/libzip/zip_file_set_external_attributes.c b/src/Common/libzip/zip_file_set_external_attributes.c
index c412f272..2e0429b8 100644
--- a/src/Common/libzip/zip_file_set_external_attributes.c
+++ b/src/Common/libzip/zip_file_set_external_attributes.c
@@ -1,9 +1,9 @@
/*
zip_file_set_external_attributes.c -- set external attributes for entry
- Copyright (C) 2013-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -41,11 +41,15 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
zip_uint32_t unchanged_attributes;
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
- return -1;
+ return -1;
if (ZIP_IS_RDONLY(za)) {
- zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
- return -1;
+ 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;
@@ -56,26 +60,26 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
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;
+ 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;
- }
+ 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/src/Common/libzip/zip_file_set_mtime.c b/src/Common/libzip/zip_file_set_mtime.c
index f8d6c208..4126f5a1 100644
--- a/src/Common/libzip/zip_file_set_mtime.c
+++ b/src/Common/libzip/zip_file_set_mtime.c
@@ -1,9 +1,9 @@
/*
zip_file_set_mtime.c -- set modification time of entry.
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -34,41 +34,44 @@
#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;
- int changed;
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
- return -1;
+ return -1;
if (ZIP_IS_RDONLY(za)) {
- zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
- return -1;
+ 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;
- changed = e->orig == NULL || mtime != e->orig->last_mod;
-
- 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->last_mod = mtime;
- e->changes->changed |= ZIP_DIRENT_LAST_MOD;
+ 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;
}
- else {
- if (e->changes) {
- e->changes->changed &= ~ZIP_DIRENT_LAST_MOD;
- if (e->changes->changed == 0) {
- _zip_dirent_free(e->changes);
- e->changes = NULL;
- }
- }
+
+ 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/src/Common/libzip/zip_file_strerror.c b/src/Common/libzip/zip_file_strerror.c
index 189c556c..5b5a0092 100644
--- a/src/Common/libzip/zip_file_strerror.c
+++ b/src/Common/libzip/zip_file_strerror.c
@@ -1,9 +1,9 @@
/*
zip_file_sterror.c -- get string representation of zip file error
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/Common/libzip/zip_fopen.c b/src/Common/libzip/zip_fopen.c
index 4ef76bad..e3cde9be 100644
--- a/src/Common/libzip/zip_fopen.c
+++ b/src/Common/libzip/zip_fopen.c
@@ -1,9 +1,9 @@
/*
zip_fopen.c -- open file in zip archive for reading
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,7 +40,7 @@ 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 NULL;
return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password);
}
diff --git a/src/Common/libzip/zip_fopen_encrypted.c b/src/Common/libzip/zip_fopen_encrypted.c
index 47cd3776..d5880dcb 100644
--- a/src/Common/libzip/zip_fopen_encrypted.c
+++ b/src/Common/libzip/zip_fopen_encrypted.c
@@ -1,9 +1,9 @@
/*
zip_fopen_encrypted.c -- open file for reading with password
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,7 +40,7 @@ zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char
zip_int64_t idx;
if ((idx = zip_name_locate(za, fname, flags)) < 0)
- return NULL;
+ return NULL;
return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password);
}
diff --git a/src/Common/libzip/zip_fopen_index.c b/src/Common/libzip/zip_fopen_index.c
index 5f0dc2a7..a449b83a 100644
--- a/src/Common/libzip/zip_fopen_index.c
+++ b/src/Common/libzip/zip_fopen_index.c
@@ -1,9 +1,9 @@
/*
zip_fopen_index.c -- open file in zip archive for reading by index
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -32,9 +32,6 @@
*/
-#include <stdio.h>
-#include <stdlib.h>
-
#include "zipint.h"
diff --git a/src/Common/libzip/zip_fopen_index_encrypted.c b/src/Common/libzip/zip_fopen_index_encrypted.c
index 4d4aee39..40483709 100644
--- a/src/Common/libzip/zip_fopen_index_encrypted.c
+++ b/src/Common/libzip/zip_fopen_index_encrypted.c
@@ -1,9 +1,9 @@
/*
zip_fopen_index_encrypted.c -- open file for reading by index w/ password
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -45,18 +45,22 @@ zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags, cons
zip_file_t *zf;
zip_source_t *src;
- if ((src = _zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL)
- return NULL;
+ 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;
+ 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;
+ zip_source_free(src);
+ return NULL;
}
zf->src = src;
@@ -70,13 +74,11 @@ _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_set(&za->error, ZIP_ER_MEMORY, 0);
+ return NULL;
}
- zf->za = za;
zip_error_init(&zf->error);
- zf->eof = 0;
zf->src = NULL;
return zf;
diff --git a/src/Common/libzip/zip_fread.c b/src/Common/libzip/zip_fread.c
index 3020a16e..5b7da46a 100644
--- a/src/Common/libzip/zip_fread.c
+++ b/src/Common/libzip/zip_fread.c
@@ -1,9 +1,9 @@
/*
zip_fread.c -- read from file
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,22 +40,23 @@ zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread) {
zip_int64_t n;
if (!zf)
- return -1;
+ return -1;
if (zf->error.zip_err != 0)
- return -1;
+ return -1;
if (toread > ZIP_INT64_MAX) {
- zip_error_set(&zf->error, ZIP_ER_INVAL, 0);
- return -1;
+ zip_error_set(&zf->error, ZIP_ER_INVAL, 0);
+ return -1;
}
- if ((zf->eof) || (toread == 0))
- return 0;
+ 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;
+ zip_error_set_from_source(&zf->error, zf->src);
+ return -1;
}
return n;
diff --git a/src/Common/libzip/zip_source_get_compression_flags.c b/src/Common/libzip/zip_fseek.c
index a9442aa5..e68ffd36 100644
--- a/src/Common/libzip/zip_source_get_compression_flags.c
+++ b/src/Common/libzip/zip_fseek.c
@@ -1,9 +1,9 @@
/*
- zip_source_get_compression_flags.c -- get compression flags for entry
- Copyright (C) 2017-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -34,24 +34,28 @@
#include "zipint.h"
-#define ZIP_COMPRESSION_BITFLAG_MAX 3
-
-zip_int8_t
-zip_source_get_compression_flags(zip_source_t *src) {
- while (src) {
- if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_COMPRESSION_FLAGS))) {
- zip_int64_t ret = _zip_source_call(src, NULL, 0, ZIP_SOURCE_GET_COMPRESSION_FLAGS);
- if (ret < 0) {
- return -1;
- }
- if (ret > ZIP_COMPRESSION_BITFLAG_MAX) {
- zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
- return -1;
- }
- return (zip_int8_t)ret;
- }
- src = src->src;
+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/src/Common/libzip/zip_source_file.c b/src/Common/libzip/zip_ftell.c
index 87147852..bf3b03d3 100644
--- a/src/Common/libzip/zip_source_file.c
+++ b/src/Common/libzip/zip_ftell.c
@@ -1,9 +1,9 @@
/*
- zip_source_file.c -- create data source from file
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -32,30 +32,23 @@
*/
-#include <stdio.h>
-
#include "zipint.h"
-#ifdef _WIN32
-#error This file is incompatible with Windows, use zip_source_win32utf8.c instead.
-#error Something probably went wrong with configure/cmake.
-#endif
-
-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;
+ZIP_EXTERN zip_int64_t
+zip_ftell(zip_file_t *zf) {
+ zip_int64_t res;
- return zip_source_file_create(fname, start, len, &za->error);
-}
+ if (!zf)
+ return -1;
+ if (zf->error.zip_err != 0)
+ return -1;
-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 < -1) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
+ res = zip_source_tell(zf->src);
+ if (res < 0) {
+ zip_error_set_from_source(&zf->error, zf->src);
+ return -1;
}
- return _zip_source_file_or_p(fname, NULL, start, length, NULL, error);
+ return res;
}
diff --git a/src/Common/libzip/zip_get_archive_comment.c b/src/Common/libzip/zip_get_archive_comment.c
index c51148db..ea9a00ab 100644
--- a/src/Common/libzip/zip_get_archive_comment.c
+++ b/src/Common/libzip/zip_get_archive_comment.c
@@ -1,9 +1,9 @@
/*
zip_get_archive_comment.c -- get archive comment
- Copyright (C) 2006-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -44,15 +44,15 @@ zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags) {
const zip_uint8_t *str;
if ((flags & ZIP_FL_UNCHANGED) || (za->comment_changes == NULL))
- comment = za->comment_orig;
+ comment = za->comment_orig;
else
- comment = za->comment_changes;
+ comment = za->comment_changes;
if ((str = _zip_string_get(comment, &len, flags, &za->error)) == NULL)
- return NULL;
+ return NULL;
if (lenp)
- *lenp = (int)len;
+ *lenp = (int)len;
return (const char *)str;
}
diff --git a/src/Common/libzip/zip_get_archive_flag.c b/src/Common/libzip/zip_get_archive_flag.c
index 1aaca729..fc200bdc 100644
--- a/src/Common/libzip/zip_get_archive_flag.c
+++ b/src/Common/libzip/zip_get_archive_flag.c
@@ -1,9 +1,9 @@
/*
zip_get_archive_flag.c -- get archive global flag
- Copyright (C) 2008-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/Common/libzip/zip_get_encryption_implementation.c b/src/Common/libzip/zip_get_encryption_implementation.c
index 07e43169..72e48fe8 100644
--- a/src/Common/libzip/zip_get_encryption_implementation.c
+++ b/src/Common/libzip/zip_get_encryption_implementation.c
@@ -1,9 +1,9 @@
/*
zip_get_encryption_implementation.c -- get encryption implementation
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -39,19 +39,24 @@ zip_encryption_implementation
_zip_get_encryption_implementation(zip_uint16_t em, int operation) {
switch (em) {
case ZIP_EM_TRAD_PKWARE:
- if (operation == ZIP_CODEC_ENCODE) {
- return NULL;
- }
- return zip_source_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;
+ return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode;
#endif
default:
- return NULL;
+ 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/src/Common/libzip/zip_get_file_comment.c b/src/Common/libzip/zip_get_file_comment.c
index 6e85a58e..d58e22ba 100644
--- a/src/Common/libzip/zip_get_file_comment.c
+++ b/src/Common/libzip/zip_get_file_comment.c
@@ -1,9 +1,9 @@
/*
zip_get_file_comment.c -- get file comment
- Copyright (C) 2006-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -42,8 +42,8 @@ zip_get_file_comment(zip_t *za, zip_uint64_t idx, int *lenp, int flags) {
const char *s;
if ((s = zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) {
- if (lenp)
- *lenp = (int)len;
+ if (lenp)
+ *lenp = (int)len;
}
return s;
diff --git a/src/Common/libzip/zip_get_name.c b/src/Common/libzip/zip_get_name.c
index 2ac005a8..4828d781 100644
--- a/src/Common/libzip/zip_get_name.c
+++ b/src/Common/libzip/zip_get_name.c
@@ -1,9 +1,9 @@
/*
zip_get_name.c -- get filename for a file in zip file
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -49,10 +49,10 @@ _zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error
const zip_uint8_t *str;
if ((de = _zip_get_dirent(za, idx, flags, error)) == NULL)
- return NULL;
+ return NULL;
if ((str = _zip_string_get(de->filename, NULL, flags, error)) == NULL)
- return NULL;
+ return NULL;
return (const char *)str;
}
diff --git a/src/Common/libzip/zip_get_num_entries.c b/src/Common/libzip/zip_get_num_entries.c
index 99dfc7a6..667dc511 100644
--- a/src/Common/libzip/zip_get_num_entries.c
+++ b/src/Common/libzip/zip_get_num_entries.c
@@ -1,9 +1,9 @@
/*
zip_get_num_entries.c -- get number of entries in archive
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,13 +40,13 @@ zip_get_num_entries(zip_t *za, zip_flags_t flags) {
zip_uint64_t n;
if (za == NULL)
- return -1;
+ 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;
+ 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/src/Common/libzip/zip_get_num_files.c b/src/Common/libzip/zip_get_num_files.c
index b6e910e4..140e34f9 100644
--- a/src/Common/libzip/zip_get_num_files.c
+++ b/src/Common/libzip/zip_get_num_files.c
@@ -1,9 +1,9 @@
/*
zip_get_num_files.c -- get number of files in archive
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,11 +40,11 @@
ZIP_EXTERN int
zip_get_num_files(zip_t *za) {
if (za == NULL)
- return -1;
+ return -1;
if (za->nentry > INT_MAX) {
- zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
- return -1;
+ zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
+ return -1;
}
return (int)za->nentry;
diff --git a/src/Common/libzip/zip_hash.c b/src/Common/libzip/zip_hash.c
index 72884533..d3a954ec 100644
--- a/src/Common/libzip/zip_hash.c
+++ b/src/Common/libzip/zip_hash.c
@@ -1,9 +1,9 @@
/*
zip_hash.c -- hash table string -> uint64
- Copyright (C) 2015-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -67,9 +67,9 @@ struct zip_hash {
static void
free_list(zip_hash_entry_t *entry) {
while (entry != NULL) {
- zip_hash_entry_t *next = entry->next;
- free(entry);
- entry = next;
+ zip_hash_entry_t *next = entry->next;
+ free(entry);
+ entry = next;
}
}
@@ -80,12 +80,12 @@ hash_string(const zip_uint8_t *name) {
zip_uint64_t value = HASH_START;
if (name == NULL) {
- return 0;
+ return 0;
}
while (*name != 0) {
- value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
- name++;
+ value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
+ name++;
}
return (zip_uint32_t)value;
@@ -98,30 +98,30 @@ 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;
+ 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;
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return false;
}
if (hash->nentries > 0) {
- zip_uint32_t i;
+ 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;
+ 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;
+ zip_uint32_t new_index = entry->hash_value % new_size;
- entry->next = new_table[new_index];
- new_table[new_index] = entry;
+ entry->next = new_table[new_index];
+ new_table[new_index] = entry;
- entry = next;
- }
- }
+ entry = next;
+ }
+ }
}
free(hash->table);
@@ -138,14 +138,14 @@ size_for_capacity(zip_uint64_t capacity) {
zip_uint32_t v;
if (needed_size > ZIP_UINT32_MAX) {
- v = ZIP_UINT32_MAX;
+ v = ZIP_UINT32_MAX;
}
else {
- v = (zip_uint32_t)needed_size;
+ v = (zip_uint32_t)needed_size;
}
if (v > HASH_MAX_SIZE) {
- return HASH_MAX_SIZE;
+ return HASH_MAX_SIZE;
}
/* From Bit Twiddling Hacks by Sean Eron Anderson <seander@cs.stanford.edu>
@@ -168,8 +168,8 @@ _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;
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
}
hash->table_size = 0;
@@ -185,16 +185,16 @@ _zip_hash_free(zip_hash_t *hash) {
zip_uint32_t i;
if (hash == NULL) {
- return;
+ 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);
+ for (i = 0; i < hash->table_size; i++) {
+ if (hash->table[i] != NULL) {
+ free_list(hash->table[i]);
+ }
+ }
+ free(hash->table);
}
free(hash);
}
@@ -207,51 +207,51 @@ _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip
zip_hash_entry_t *entry;
if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return false;
+ 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;
- }
+ 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->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 ((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->orig_index = (zip_int64_t)index;
}
entry->current_index = (zip_int64_t)index;
@@ -266,40 +266,40 @@ _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
zip_hash_entry_t *entry, *previous;
if (hash == NULL || name == NULL) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return false;
+ 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;
- }
+ 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);
@@ -314,28 +314,28 @@ _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, z
zip_hash_entry_t *entry;
if (hash == NULL || name == NULL) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return -1;
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return -1;
}
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;
- }
- }
+ 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);
@@ -348,17 +348,17 @@ _zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t
zip_uint32_t new_size;
if (capacity == 0) {
- return true;
+ return true;
}
new_size = size_for_capacity(capacity);
if (new_size <= hash->table_size) {
- return true;
+ return true;
}
if (!hash_resize(hash, new_size, error)) {
- return false;
+ return false;
}
return true;
@@ -371,39 +371,39 @@ _zip_hash_revert(zip_hash_t *hash, zip_error_t *error) {
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;
- }
- }
+ 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;
- }
+ 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/src/Common/libzip/zip_io_util.c b/src/Common/libzip/zip_io_util.c
index 53f44377..9fcd10b4 100644
--- a/src/Common/libzip/zip_io_util.c
+++ b/src/Common/libzip/zip_io_util.c
@@ -1,9 +1,9 @@
/*
zip_io_util.c -- I/O helper functions
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -31,8 +31,10 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <zlib.h>
#include "zipint.h"
@@ -41,18 +43,18 @@ _zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *e
zip_int64_t n;
if (length > ZIP_INT64_MAX) {
- zip_error_set(error, ZIP_ER_INTERNAL, 0);
- return -1;
+ 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;
+ 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;
+ zip_error_set(error, ZIP_ER_EOF, 0);
+ return -1;
}
return 0;
@@ -64,39 +66,39 @@ _zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp
zip_uint8_t *r;
if (length == 0 && !nulp) {
- return NULL;
+ return NULL;
}
r = (zip_uint8_t *)malloc(length + (nulp ? 1 : 0));
if (!r) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- return NULL;
+ 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;
- }
- memcpy(r, data, length);
+ 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 (_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 = ' ';
+ 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;
@@ -109,7 +111,7 @@ _zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool
zip_string_t *s;
if ((raw = _zip_read_data(buffer, src, len, nulp, error)) == NULL)
- return NULL;
+ return NULL;
s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error);
free(raw);
@@ -122,12 +124,22 @@ _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;
+ 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;
+ 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/src/Common/libzip/zip_libzip_version.c b/src/Common/libzip/zip_libzip_version.c
new file mode 100644
index 00000000..4200727f
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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/src/Common/libzip/zip_memdup.c b/src/Common/libzip/zip_memdup.c
index d6044081..75d72c61 100644
--- a/src/Common/libzip/zip_memdup.c
+++ b/src/Common/libzip/zip_memdup.c
@@ -1,9 +1,9 @@
/*
zip_memdup.c -- internal zip function, "strdup" with len
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -42,15 +42,15 @@ _zip_memdup(const void *mem, size_t len, zip_error_t *error) {
void *ret;
if (len == 0)
- return NULL;
+ return NULL;
ret = malloc(len);
if (!ret) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- return NULL;
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
}
- memcpy(ret, mem, len);
+ (void)memcpy_s(ret, len, mem, len);
return ret;
}
diff --git a/src/Common/libzip/zip_name_locate.c b/src/Common/libzip/zip_name_locate.c
index 37b1ffeb..4248dc2d 100644
--- a/src/Common/libzip/zip_name_locate.c
+++ b/src/Common/libzip/zip_name_locate.c
@@ -1,9 +1,9 @@
/*
zip_name_locate.c -- get index by name
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -49,44 +49,68 @@ zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags) {
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 (za == NULL) {
+ return -1;
+ }
if (fname == NULL) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return -1;
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return -1;
}
- if (flags & (ZIP_FL_NOCASE | ZIP_FL_NODIR | ZIP_FL_ENC_CP437)) {
- /* 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;
+ fname_length = strlen(fname);
- if (flags & ZIP_FL_NODIR) {
- p = strrchr(fn, '/');
- if (p)
- fn = p + 1;
- }
+ if (fname_length > ZIP_UINT16_MAX) {
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return -1;
+ }
- if (cmp(fname, fn) == 0) {
- _zip_error_clear(error);
- return (zip_int64_t)i;
- }
- }
+ 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;
+ }
+ }
- zip_error_set(error, ZIP_ER_NOENT, 0);
- 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 {
- return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
+ 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/src/Common/libzip/zip_new.c b/src/Common/libzip/zip_new.c
index 1cd614df..4f69c8a2 100644
--- a/src/Common/libzip/zip_new.c
+++ b/src/Common/libzip/zip_new.c
@@ -1,9 +1,9 @@
/*
zip_new.c -- create and init struct zip
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -47,13 +47,13 @@ _zip_new(zip_error_t *error) {
za = (zip_t *)malloc(sizeof(struct zip));
if (!za) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- return NULL;
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
}
if ((za->names = _zip_hash_new(error)) == NULL) {
- free(za);
- return NULL;
+ free(za);
+ return NULL;
}
za->src = NULL;
diff --git a/src/Common/libzip/zip_open.c b/src/Common/libzip/zip_open.c
index 593bfde5..ee7e9dec 100644
--- a/src/Common/libzip/zip_open.c
+++ b/src/Common/libzip/zip_open.c
@@ -1,9 +1,9 @@
/*
zip_open.c -- open zip archive by name
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -36,22 +36,17 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/stat.h>
#include "zipint.h"
-typedef enum {
- EXISTS_ERROR = -1,
- EXISTS_NOT = 0,
- EXISTS_EMPTY,
- EXISTS_NONEMPTY,
-} exists_t;
+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 unsigned char *_zip_memmem(const unsigned char *, size_t, const unsigned char *, size_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);
@@ -65,16 +60,16 @@ zip_open(const char *fn, int _flags, int *zep) {
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;
+ _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_source_free(src);
+ _zip_set_open_error(zep, &error, 0);
+ zip_error_fini(&error);
+ return NULL;
}
zip_error_fini(&error);
@@ -84,73 +79,66 @@ zip_open(const char *fn, int _flags, int *zep) {
ZIP_EXTERN zip_t *
zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) {
- static zip_int64_t needed_support_read = -1;
- static zip_int64_t needed_support_write = -1;
-
unsigned int flags;
zip_int64_t supported;
exists_t exists;
if (_flags < 0 || src == NULL) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return NULL;
}
flags = (unsigned int)_flags;
supported = zip_source_supports(src);
- if (needed_support_read == -1) {
- needed_support_read = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_STAT, -1);
- needed_support_write = zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1);
- }
- if ((supported & needed_support_read) != needed_support_read) {
- zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
- return NULL;
+ if ((supported & ZIP_SOURCE_SUPPORTS_SEEKABLE) != ZIP_SOURCE_SUPPORTS_SEEKABLE) {
+ zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
+ return NULL;
}
- if ((supported & needed_support_write) != needed_support_write) {
- flags |= ZIP_RDONLY;
+ 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;
+ zip_error_set(error, ZIP_ER_RDONLY, 0);
+ return NULL;
}
exists = _zip_file_exists(src, error);
switch (exists) {
case EXISTS_ERROR:
- return NULL;
+ 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);
+ 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 *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;
}
}
}
@@ -165,63 +153,69 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
zip_stat_init(&st);
if (zip_source_stat(src, &st) < 0) {
- _zip_error_set_from_source(error, src);
- return NULL;
+ 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;
+ zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP);
+ return NULL;
}
len = st.size;
- /* treat empty files as empty archives */
- if (len == 0) {
- if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
- return NULL;
- }
- return za;
+ if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
+ return NULL;
}
- 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;
+ _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;
- za->comment_orig = cdir->comment;
+
+ 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;
- }
- }
+ 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;
@@ -233,14 +227,20 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
void
_zip_set_open_error(int *zep, const zip_error_t *err, int ze) {
if (err) {
- ze = zip_error_code_zip(err);
- if (zip_error_system_type(err) == ZIP_ET_SYS) {
- errno = zip_error_code_system(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;
+ *zep = ze;
}
@@ -259,156 +259,159 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
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;
+ /* 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;
+ 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);
+ _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);
+ _zip_buffer_set_offset(buffer, eocd_offset);
+ cd = _zip_read_eocd(buffer, buf_offset, za->flags, error);
}
if (cd == NULL)
- return 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, 0);
- _zip_cdir_free(cd);
- return NULL;
+ /* 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_uint64_t tail_len;
- _zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN);
- tail_len = _zip_buffer_left(buffer);
+ _zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN);
+ tail_len = _zip_buffer_left(buffer);
- if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) {
- zip_error_set(error, ZIP_ER_INCONS, 0);
- _zip_cdir_free(cd);
- return NULL;
- }
+ 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 (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, 0);
- _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;
- }
+ 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;
+ 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;
- }
+ 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;
- }
+ /* 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 (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) {
- zip_error_set(error, ZIP_ER_INCONS, 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));
}
- _zip_cdir_free(cd);
- _zip_buffer_free(cd_buffer);
- return NULL;
- }
- i++;
- left -= (zip_uint64_t)entry_size;
+ 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, 0);
- _zip_buffer_free(cd_buffer);
- _zip_cdir_free(cd);
- return NULL;
+ 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, 0);
- _zip_buffer_free(cd_buffer);
- _zip_cdir_free(cd);
- return NULL;
- }
+ 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);
@@ -430,49 +433,52 @@ _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) {
_zip_dirent_init(&temp);
if (cd->nentry) {
- max = cd->entry[0].orig->offset;
- min = cd->entry[0].orig->offset;
+ max = cd->entry[0].orig->offset;
+ min = cd->entry[0].orig->offset;
}
else
- min = max = 0;
+ 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) {
- _zip_dirent_finalize(&temp);
- return -1;
- }
+ 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, 0);
- _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;
+ 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);
+ _zip_dirent_finalize(&temp);
}
return (max - min) < ZIP_INT64_MAX ? (zip_int64_t)(max - min) : ZIP_INT64_MAX;
@@ -491,14 +497,25 @@ _zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *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;
+ || (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. */
- if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0))
+ /* 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;
@@ -510,15 +527,20 @@ _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;
+ 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;
+ za->flags |= ZIP_AFL_RDONLY;
+ za->ch_flags |= ZIP_AFL_RDONLY;
}
+
return za;
}
@@ -532,22 +554,22 @@ _zip_file_exists(zip_source_t *src, zip_error_t *error) {
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;
+ 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 (st.valid & ZIP_STAT_SIZE) && st.size == 0 ? EXISTS_EMPTY : EXISTS_NONEMPTY;
+ return EXISTS_OK;
}
static zip_cdir_t *
_zip_find_central_dir(zip_t *za, zip_uint64_t len) {
zip_cdir_t *cdir, *cdirnew;
- zip_uint8_t *match;
+ const zip_uint8_t *match;
zip_int64_t buf_offset;
zip_uint64_t buflen;
zip_int64_t a;
@@ -556,95 +578,105 @@ _zip_find_central_dir(zip_t *za, zip_uint64_t len) {
zip_buffer_t *buffer;
if (len < EOCDLEN) {
- zip_error_set(&za->error, ZIP_ER_NOZIP, 0);
- return NULL;
+ 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;
- }
+ 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;
+ 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;
+ 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);
+ /* 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);
- while ((match = _zip_memmem(match, _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)));
+ /* 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;
+ _zip_error_copy(&za->error, &error);
+ _zip_cdir_free(cdir);
+ return NULL;
}
return cdir;
}
-static unsigned char *
-_zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen) {
+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 ((biglen < littlelen) || (littlelen == 0))
- return NULL;
- p = big - 1;
- while ((p = (const unsigned char *)memchr(p + 1, little[0], (size_t)(big - (p + 1)) + (size_t)(biglen - littlelen) + 1)) != NULL) {
- if (memcmp(p + 1, little + 1, littlelen - 1) == 0)
- return (unsigned char *)p;
+ if (littlelen == 0) {
+ return big;
+ }
+
+ if (biglen < littlelen) {
+ return NULL;
}
- 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;
+ }
}
@@ -654,8 +686,8 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags
zip_uint64_t i, nentry, size, offset, eocd_offset;
if (_zip_buffer_left(buffer) < EOCDLEN) {
- zip_error_set(error, ZIP_ER_INCONS, 0);
- return NULL;
+ zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EOCD_LENGTH_INVALID);
+ return NULL;
}
eocd_offset = _zip_buffer_offset(buffer);
@@ -663,8 +695,8 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags
_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;
+ zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+ return NULL;
}
/* number of cdir-entries on this disk */
@@ -673,31 +705,31 @@ _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags
nentry = _zip_buffer_get_16(buffer);
if (nentry != i) {
- zip_error_set(error, ZIP_ER_NOZIP, 0);
- return NULL;
+ 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;
+ zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+ return NULL;
}
if (offset + size > buf_offset + eocd_offset) {
- /* cdir spans past EOCD record */
- zip_error_set(error, ZIP_ER_INCONS, 0);
- return NULL;
+ /* 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, 0);
- return NULL;
+ 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;
+ return NULL;
cd->is_zip64 = false;
cd->size = size;
@@ -725,47 +757,52 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
eocd_disk = _zip_buffer_get_16(buffer);
eocd_offset = _zip_buffer_get_64(buffer);
- if (eocd_offset > ZIP_INT64_MAX || eocd_offset + EOCD64LEN < eocd_offset) {
- zip_error_set(error, ZIP_ER_SEEK, EFBIG);
- return NULL;
+ /* 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, 0);
- return NULL;
+ 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;
+ _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 (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, 0);
- if (free_buffer) {
- _zip_buffer_free(buffer);
- }
- return NULL;
+ 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, 0);
- if (free_buffer) {
- _zip_buffer_free(buffer);
- }
- return NULL;
+ 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 */
@@ -777,68 +814,74 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
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;
+ num_disks = num_disks64;
}
if (eocd_disk == 0xffff) {
- eocd_disk = eocd_disk64;
+ eocd_disk = eocd_disk64;
}
if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) {
- zip_error_set(error, ZIP_ER_INCONS, 0);
- if (free_buffer) {
- _zip_buffer_free(buffer);
- }
- return NULL;
+ 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;
+ 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;
+ 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;
+ zip_error_set(error, ZIP_ER_INTERNAL, 0);
+ if (free_buffer) {
+ _zip_buffer_free(buffer);
+ }
+ return NULL;
}
if (free_buffer) {
- _zip_buffer_free(buffer);
+ _zip_buffer_free(buffer);
}
if (offset > ZIP_INT64_MAX || offset + size < offset) {
- zip_error_set(error, ZIP_ER_SEEK, EFBIG);
- return NULL;
+ zip_error_set(error, ZIP_ER_SEEK, EFBIG);
+ return NULL;
}
if (offset + size > buf_offset + eocd_offset) {
- /* cdir spans past EOCD record */
- zip_error_set(error, ZIP_ER_INCONS, 0);
- return NULL;
+ /* 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, 0);
- return NULL;
+ 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;
+ return NULL;
cd->is_zip64 = true;
cd->size = size;
@@ -846,3 +889,79 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
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/src/Common/libzip/zip_pkware.c b/src/Common/libzip/zip_pkware.c
new file mode 100644
index 00000000..6a8c9fcd
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+#include <zlib.h>
+
+#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/src/Common/libzip/zip_progress.c b/src/Common/libzip/zip_progress.c
index 9b116942..e080514b 100644
--- a/src/Common/libzip/zip_progress.c
+++ b/src/Common/libzip/zip_progress.c
@@ -1,9 +1,9 @@
/*
zip_progress.c -- progress reporting
- Copyright (C) 2017-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,10 +40,14 @@
struct zip_progress {
zip_t *za;
- zip_progress_callback callback;
- void (*ud_free)(void *);
- void *ud;
+ 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;
@@ -54,6 +58,11 @@ struct zip_progress {
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) {
@@ -64,88 +73,189 @@ _zip_progress_end(zip_progress_t *progress) {
void
_zip_progress_free(zip_progress_t *progress) {
if (progress == NULL) {
- return;
+ return;
}
- if (progress->ud_free) {
- progress->ud_free(progress->ud);
- }
+ _zip_progress_free_progress_callback(progress);
+ _zip_progress_free_cancel_callback(progress);
free(progress);
}
-zip_progress_t *
-_zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) {
+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;
+ zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+ return NULL;
}
progress->za = za;
- progress->callback = callback;
- progress->ud_free = ud_free;
- progress->ud = ud;
- progress->precision = precision;
+
+ 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;
+ return 0;
}
- progress->last_update = 0.0;
- progress->callback(progress->za, 0.0, progress->ud);
+ 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;
}
-void
+int
_zip_progress_subrange(zip_progress_t *progress, double start, double end) {
if (progress == NULL) {
- return;
+ return 0;
}
progress->start = start;
progress->end = end;
- _zip_progress_update(progress, 0.0);
+ return _zip_progress_update(progress, 0.0);
}
-void
+int
_zip_progress_update(zip_progress_t *progress, double sub_current) {
double current;
if (progress == NULL) {
- return;
+ return 0;
}
- current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
+ 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->za, current, progress->ud);
- progress->last_update = current;
+ 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) {
- zip_progress_t *progress = NULL;
-
if (callback != NULL) {
- if ((progress = _zip_progress_new(za, precision, callback, ud_free, ud)) == NULL) {
- return -1;
- }
+ 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);
+ }
+ }
}
- _zip_progress_free(za->progress);
- za->progress = 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;
}
@@ -168,16 +278,16 @@ zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callb
struct legacy_ud *ud;
if (progress_callback == NULL) {
- zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
+ zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
}
if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) {
- return;
+ return;
}
ud->callback = progress_callback;
if (zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) {
- free(ud);
+ free(ud);
}
}
diff --git a/src/Common/libzip/zip_random_unix.c b/src/Common/libzip/zip_random_unix.c
new file mode 100644
index 00000000..867df790
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+
+#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 <fcntl.h>
+#include <unistd.h>
+
+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 <stdlib.h>
+
+#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/src/Common/libzip/zip_filerange_crc.c b/src/Common/libzip/zip_random_uwp.c
index 33bf5d85..0883ce45 100644
--- a/src/Common/libzip/zip_filerange_crc.c
+++ b/src/Common/libzip/zip_random_uwp.c
@@ -1,9 +1,9 @@
/*
- zip_filerange_crc.c -- compute CRC32 for a range of a file
- Copyright (C) 2008-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -31,54 +31,52 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
-#include <stdio.h>
-
#include "zipint.h"
+#ifdef HAVE_CRYPTO
+#include "zip_crypto.h"
+#endif
-int
-_zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLong *crcp, zip_error_t *error) {
- DEFINE_BYTE_ARRAY(buf, BUFSIZE);
+#ifndef HAVE_SECURE_RANDOM
- zip_int64_t n;
+#include <windows.h>
+#include <bcrypt.h>
- *crcp = crc32(0L, Z_NULL, 0);
-
- if (start > ZIP_INT64_MAX) {
- zip_error_set(error, ZIP_ER_SEEK, EFBIG);
- return -1;
+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;
}
-
- if (zip_source_seek(src, (zip_int64_t)start, SEEK_SET) != 0) {
- _zip_error_set_from_source(error, src);
- return -1;
+ hr = BCryptGenRandom(&hAlg, buffer, length, 0);
+ BCryptCloseAlgorithmProvider(&hAlg, 0);
+ if (!BCRYPT_SUCCESS(hr)) {
+ return false;
}
+ return true;
+}
- if (!byte_array_init(buf, BUFSIZE)) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- return -1;
- }
+#endif
- while (len > 0) {
- n = (zip_int64_t)(len > BUFSIZE ? BUFSIZE : len);
- if ((n = zip_source_read(src, buf, (zip_uint64_t)n)) < 0) {
- _zip_error_set_from_source(error, src);
- byte_array_fini(buf);
- return -1;
- }
- if (n == 0) {
- zip_error_set(error, ZIP_ER_EOF, 0);
- byte_array_fini(buf);
- return -1;
- }
+#ifndef HAVE_RANDOM_UINT32
+#include <stdlib.h>
- *crcp = crc32(*crcp, buf, (uInt)n);
+zip_uint32_t
+zip_random_uint32(void) {
+ static bool seeded = false;
- len -= (zip_uint64_t)n;
+ zip_uint32_t value;
+
+ if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
+ return value;
}
- byte_array_fini(buf);
+ if (!seeded) {
+ srand((unsigned int)time(NULL));
+ seeded = true;
+ }
- return 0;
+ return (zip_uint32_t)rand();
}
+#endif
diff --git a/src/Common/libzip/zip_random_win32.c b/src/Common/libzip/zip_random_win32.c
new file mode 100644
index 00000000..789b9c20
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <windows.h>
+
+#ifndef HAVE_SECURE_RANDOM
+
+#include <wincrypt.h>
+
+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 <stdlib.h>
+
+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/src/Common/libzip/zip_rename.c b/src/Common/libzip/zip_rename.c
index 4fdf6361..c89b06c9 100644
--- a/src/Common/libzip/zip_rename.c
+++ b/src/Common/libzip/zip_rename.c
@@ -1,9 +1,9 @@
/*
zip_rename.c -- rename file in zip archive
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -32,8 +32,6 @@
*/
-#include <string.h>
-
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
diff --git a/src/Common/libzip/zip_replace.c b/src/Common/libzip/zip_replace.c
index 2e982aff..96c083c3 100644
--- a/src/Common/libzip/zip_replace.c
+++ b/src/Common/libzip/zip_replace.c
@@ -1,9 +1,9 @@
/*
zip_replace.c -- replace file via callback function
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/Common/libzip/zip_set_archive_comment.c b/src/Common/libzip/zip_set_archive_comment.c
index 166a2c0b..7d06688e 100644
--- a/src/Common/libzip/zip_set_archive_comment.c
+++ b/src/Common/libzip/zip_set_archive_comment.c
@@ -1,9 +1,9 @@
/*
zip_set_archive_comment.c -- set archive comment
- Copyright (C) 2006-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -42,38 +42,42 @@ 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;
+ 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;
+ 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 ((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;
- }
+ 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;
+ 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;
+ _zip_string_free(cstr);
+ za->comment_changed = 0;
}
else {
- za->comment_changes = cstr;
- za->comment_changed = 1;
+ za->comment_changes = cstr;
+ za->comment_changed = 1;
}
return 0;
diff --git a/src/Common/libzip/zip_set_archive_flag.c b/src/Common/libzip/zip_set_archive_flag.c
index facf6146..834ef5ba 100644
--- a/src/Common/libzip/zip_set_archive_flag.c
+++ b/src/Common/libzip/zip_set_archive_flag.c
@@ -1,9 +1,9 @@
/*
zip_get_archive_flag.c -- set archive global flag
- Copyright (C) 2008-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -39,24 +39,35 @@ ZIP_EXTERN int
zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value) {
unsigned int new_flags;
- if (value)
- new_flags = za->ch_flags | flag;
- else
- new_flags = za->ch_flags & ~flag;
+ 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;
+ if (new_flags == za->ch_flags) {
+ return 0;
+ }
- if (ZIP_IS_RDONLY(za)) {
- zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
- return -1;
+ /* 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;
- }
+ if (_zip_changed(za, NULL)) {
+ zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
+ return -1;
+ }
}
za->ch_flags = new_flags;
diff --git a/src/Common/libzip/zip_set_default_password.c b/src/Common/libzip/zip_set_default_password.c
index 8081657c..4bab513f 100644
--- a/src/Common/libzip/zip_set_default_password.c
+++ b/src/Common/libzip/zip_set_default_password.c
@@ -1,9 +1,9 @@
/*
zip_set_default_password.c -- set default password for decryption
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -41,18 +41,18 @@
ZIP_EXTERN int
zip_set_default_password(zip_t *za, const char *passwd) {
if (za == NULL)
- return -1;
+ return -1;
free(za->default_password);
- if (passwd) {
- if ((za->default_password = strdup(passwd)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
- return -1;
- }
+ 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;
+ za->default_password = NULL;
return 0;
}
diff --git a/src/Common/libzip/zip_set_file_comment.c b/src/Common/libzip/zip_set_file_comment.c
index e4e0331e..5d2b0b8a 100644
--- a/src/Common/libzip/zip_set_file_comment.c
+++ b/src/Common/libzip/zip_set_file_comment.c
@@ -1,9 +1,9 @@
/*
zip_set_file_comment.c -- set comment for file in archive
- Copyright (C) 2006-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -32,8 +32,6 @@
*/
-#include <stdlib.h>
-
#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
@@ -41,8 +39,8 @@
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;
+ 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/src/Common/libzip/zip_set_file_compression.c b/src/Common/libzip/zip_set_file_compression.c
index 054dd1fd..a193bb77 100644
--- a/src/Common/libzip/zip_set_file_compression.c
+++ b/src/Common/libzip/zip_set_file_compression.c
@@ -1,9 +1,9 @@
/*
zip_set_file_compression.c -- set compression for file in archive
- Copyright (C) 2012-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,19 +40,23 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
zip_entry_t *e;
zip_int32_t old_method;
- if (idx >= za->nentry || flags > 9) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return -1;
+ 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;
+ 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;
+ zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
+ return -1;
}
e = za->entry + idx;
@@ -65,26 +69,26 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
* 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;
- }
- }
+ 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;
+ 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/src/Common/libzip/zip_set_name.c b/src/Common/libzip/zip_set_name.c
index aa1dd8ea..f1bf703e 100644
--- a/src/Common/libzip/zip_set_name.c
+++ b/src/Common/libzip/zip_set_name.c
@@ -1,9 +1,9 @@
/*
zip_set_name.c -- rename helper function
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -48,109 +48,109 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
zip_string_t *old_str;
if (idx >= za->nentry) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return -1;
+ 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;
+ 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;
+ /* 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;
+ 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;
+ _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;
+ _zip_string_free(str);
+ return 0;
}
e = za->entry + idx;
if (e->orig)
- same_as_orig = _zip_string_equal(e->orig->filename, str);
+ same_as_orig = _zip_string_equal(e->orig->filename, str);
else
- same_as_orig = false;
+ 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 ((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;
+ _zip_string_free(str);
+ return -1;
}
if (e->changes) {
- old_str = e->changes->filename;
+ old_str = e->changes->filename;
}
else if (e->orig) {
- old_str = e->orig->filename;
+ old_str = e->orig->filename;
}
else {
- old_str = NULL;
+ 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;
- }
+ if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) {
+ _zip_string_free(str);
+ return -1;
+ }
}
else {
- old_name = NULL;
+ old_name = NULL;
}
if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) {
- _zip_string_free(str);
- return -1;
+ _zip_string_free(str);
+ return -1;
}
if (old_name) {
- _zip_hash_delete(za->names, old_name, NULL);
+ _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);
+ 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;
+ 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/src/Common/libzip/zip_source_accept_empty.c b/src/Common/libzip/zip_source_accept_empty.c
new file mode 100644
index 00000000..e772aeea
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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/src/Common/libzip/zip_source_begin_write.c b/src/Common/libzip/zip_source_begin_write.c
index a8b90b5f..4a9d5d5d 100644
--- a/src/Common/libzip/zip_source_begin_write.c
+++ b/src/Common/libzip/zip_source_begin_write.c
@@ -1,9 +1,9 @@
/*
zip_source_begin_write.c -- start a new file for writing
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -37,13 +37,18 @@
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;
+ 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;
+ return -1;
}
src->write_state = ZIP_SOURCE_WRITE_OPEN;
diff --git a/src/Common/libzip/zip_source_begin_write_cloning.c b/src/Common/libzip/zip_source_begin_write_cloning.c
index b38de04d..df195fcd 100644
--- a/src/Common/libzip/zip_source_begin_write_cloning.c
+++ b/src/Common/libzip/zip_source_begin_write_cloning.c
@@ -1,9 +1,9 @@
/*
zip_source_begin_write_cloning.c -- clone part of file for writing
- Copyright (C) 2017-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -37,13 +37,18 @@
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;
+ 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;
+ return -1;
}
src->write_state = ZIP_SOURCE_WRITE_OPEN;
diff --git a/src/Common/libzip/zip_source_buffer.c b/src/Common/libzip/zip_source_buffer.c
index 119bc02c..44159536 100644
--- a/src/Common/libzip/zip_source_buffer.c
+++ b/src/Common/libzip/zip_source_buffer.c
@@ -1,9 +1,9 @@
/*
zip_source_buffer.c -- create zip data source from buffer
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -50,8 +50,8 @@ struct buffer {
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 size; /* size of buffer */
zip_uint64_t offset; /* current offset in buffer */
zip_uint64_t current_fragment; /* fragment current offset is in */
};
@@ -61,6 +61,7 @@ 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;
};
@@ -79,200 +80,240 @@ static zip_int64_t buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_u
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 NULL;
- return zip_source_buffer_create(data, len, freep, &za->error);
+ 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 && len > 0) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
+ 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_create(&fragment, 1, freep, error);
+ 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 NULL;
}
- return zip_source_buffer_fragment_create(fragments, nfragments, freep, &za->error);
+ 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;
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return NULL;
}
if ((buffer = buffer_new(fragments, nfragments, freep, error)) == NULL) {
- return 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;
+ 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;
+ 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;
+ 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;
+ 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;
+ return 0;
case ZIP_SOURCE_COMMIT_WRITE:
- buffer_free(ctx->in);
- ctx->in = ctx->out;
- ctx->out = NULL;
- return 0;
+ 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);
+ 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;
+ 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;
+ 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);
+ 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_t *empty = buffer_new(NULL, 0, 0, &ctx->error);
+ if (empty == NULL) {
+ return -1;
+ }
- buffer_free(ctx->in);
- ctx->in = empty;
- return 0;
+ buffer_free(ctx->in);
+ ctx->in = empty;
+ return 0;
}
case ZIP_SOURCE_ROLLBACK_WRITE:
- buffer_free(ctx->out);
- ctx->out = NULL;
- return 0;
+ buffer_free(ctx->out);
+ ctx->out = NULL;
+ return 0;
case ZIP_SOURCE_SEEK:
- return buffer_seek(ctx->in, data, len, &ctx->error);
+ return buffer_seek(ctx->in, data, len, &ctx->error);
case ZIP_SOURCE_SEEK_WRITE:
- return buffer_seek(ctx->out, data, len, &ctx->error);
+ return buffer_seek(ctx->out, data, len, &ctx->error);
case ZIP_SOURCE_STAT: {
- zip_stat_t *st;
+ zip_stat_t *st;
- if (len < sizeof(*st)) {
- zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
- return -1;
- }
+ if (len < sizeof(*st)) {
+ zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
+ return -1;
+ }
- st = (zip_stat_t *)data;
+ 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;
+ 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);
+ return sizeof(*st);
}
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_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, -1);
+ 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;
+ 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;
+ 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);
+ 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;
+ zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
+ return -1;
}
}
@@ -283,50 +324,51 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
buffer_t *clone;
if (offset == 0) {
- return buffer_new(NULL, 0, 1, error);
+ return buffer_new(NULL, 0, 1, error);
}
if (offset > buffer->size) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
+ 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;
+ 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;
+ 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;
+ zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
+ return NULL;
}
if ((clone = buffer_new(buffer->fragments, fragment + 1, 0, error)) == NULL) {
- return NULL;
+ return NULL;
}
#ifndef __clang_analyzer__
/* clone->fragments can't be null, since it was created with at least one fragment */
- clone->fragments[clone->nfragments - 1].length = fragment_offset;
+ 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 - 1);
+ clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments);
buffer->shared_buffer = clone;
clone->shared_buffer = buffer;
- buffer->shared_fragments = clone->nfragments;
+ buffer->shared_fragments = fragment + 1;
clone->shared_fragments = fragment + 1;
-
+
return clone;
}
@@ -335,20 +377,24 @@ 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;
- }
+ 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;
@@ -360,18 +406,18 @@ buffer_free(buffer_t *buffer) {
zip_uint64_t i;
if (buffer == NULL) {
- return;
+ return;
}
if (buffer->shared_buffer != NULL) {
- buffer->shared_buffer->shared_buffer = NULL;
- buffer->shared_buffer->shared_fragments = 0;
+ 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);
+ 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[i].data);
}
free(buffer->fragments);
free(buffer->fragment_offsets);
@@ -383,19 +429,29 @@ 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;
+ zip_uint64_t fragments_size;
+ zip_uint64_t offsets_size;
if (capacity < buffer->fragments_capacity) {
- return true;
+ return true;
}
- if ((fragments = realloc(buffer->fragments, sizeof(buffer->fragments[0]) * capacity)) == NULL) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- return false;
+ fragments_size = sizeof(buffer->fragments[0]) * capacity;
+ 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, sizeof(buffer->fragment_offsets[0]) * (capacity + 1))) == NULL) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- return false;
+ 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;
@@ -409,7 +465,7 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int
buffer_t *buffer;
if ((buffer = malloc(sizeof(*buffer))) == NULL) {
- return NULL;
+ return NULL;
}
buffer->offset = 0;
@@ -423,42 +479,43 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int
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;
+ 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;
- offset += fragments[i].length;
- j++;
- }
- buffer->nfragments = j;
- buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments;
- buffer->fragment_offsets[nfragments] = offset;
- buffer->size = offset;
+ 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;
@@ -471,25 +528,28 @@ buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
length = ZIP_MIN(length, buffer->size - buffer->offset);
if (length == 0) {
- return 0;
+ return 0;
}
if (length > ZIP_INT64_MAX) {
- return -1;
+ 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);
+ 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
- memcpy(data + n, buffer->fragments[i].data + fragment_offset, left);
+ (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;
+ if (left == buffer->fragments[i].length - fragment_offset) {
+ i++;
+ }
+ n += left;
+ fragment_offset = 0;
}
buffer->offset += n;
@@ -503,7 +563,7 @@ 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;
+ return -1;
}
buffer->offset = (zip_uint64_t)new_offset;
@@ -514,66 +574,72 @@ 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 *error) {
- zip_uint64_t n, i, fragment_offset, capacity;
+ 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;
+ 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;
- }
+ 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];
- n = 0;
- while (n < length) {
- zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
+ 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
- memcpy(buffer->fragments[i].data + fragment_offset, data + n, left);
+ (void)memcpy_s(buffer->fragments[i].data + fragment_offset, (size_t)n, data + copied, (size_t)n);
- if (left == buffer->fragments[i].length - fragment_offset) {
- i++;
- }
- n += left;
- fragment_offset = 0;
+ if (n == buffer->fragments[i].length - fragment_offset) {
+ i++;
+ fragment_offset = 0;
+ }
+ else {
+ fragment_offset += n;
+ }
+ copied += n;
}
- buffer->offset += n;
+ buffer->offset += copied;
buffer->current_fragment = i;
if (buffer->offset > buffer->size) {
- buffer->size = buffer->offset;
+ buffer->size = buffer->offset;
}
- return (zip_int64_t)n;
+ return (zip_int64_t)copied;
}
diff --git a/src/Common/libzip/zip_source_call.c b/src/Common/libzip/zip_source_call.c
index 3f374fc5..8c98fc2e 100644
--- a/src/Common/libzip/zip_source_call.c
+++ b/src/Common/libzip/zip_source_call.c
@@ -1,9 +1,9 @@
/*
zip_source_call.c -- invoke callback command on zip_source
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,28 +40,28 @@ _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_
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;
+ zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
+ return -1;
}
if (src->src == NULL) {
- ret = src->cb.f(src->ud, data, length, command);
+ ret = src->cb.f(src->ud, data, length, command);
}
else {
- ret = src->cb.l(src->src, src->ud, data, length, command);
+ 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 (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]);
- }
- }
+ 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/src/Common/libzip/zip_source_close.c b/src/Common/libzip/zip_source_close.c
index 79165500..f4f3ff2b 100644
--- a/src/Common/libzip/zip_source_close.c
+++ b/src/Common/libzip/zip_source_close.c
@@ -1,9 +1,9 @@
/*
zip_source_close.c -- close zip_source (stop reading)
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -38,19 +38,19 @@
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;
+ 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);
+ _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);
- }
- }
+ 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/src/Common/libzip/zip_source_commit_write.c b/src/Common/libzip/zip_source_commit_write.c
index 67881f05..d7f567b8 100644
--- a/src/Common/libzip/zip_source_commit_write.c
+++ b/src/Common/libzip/zip_source_commit_write.c
@@ -1,9 +1,9 @@
/*
zip_source_commit_write.c -- commit changes to file
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -37,24 +37,29 @@
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;
+ 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;
+ 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_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_FAILED;
+ return -1;
}
src->write_state = ZIP_SOURCE_WRITE_CLOSED;
diff --git a/src/Common/libzip/zip_source_compress.c b/src/Common/libzip/zip_source_compress.c
index d2ae220c..3cf709ff 100644
--- a/src/Common/libzip/zip_source_compress.c
+++ b/src/Common/libzip/zip_source_compress.c
@@ -1,9 +1,9 @@
/*
zip_source_compress.c -- (de)compression routines
- Copyright (C) 2017-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -31,7 +31,6 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -67,45 +66,58 @@ static struct implementation implementations[] = {
#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, int compression_flags);
+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, int compression_flags, zip_compression_algorithm_t *algorithm);
+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);
-static zip_compression_algorithm_t *
-get_algorithm(zip_int32_t method, bool compress) {
+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;
- }
- }
+ if (implementations[i].method == real_method) {
+ if (compress) {
+ return implementations[i].compress;
+ }
+ else {
+ return implementations[i].decompress;
+ }
+ }
}
return NULL;
}
-bool
-zip_compression_method_supported(zip_int32_t method, bool compress) {
+ZIP_EXTERN int
+zip_compression_method_supported(zip_int32_t method, int compress) {
if (method == ZIP_CM_STORE) {
- return true;
+ return 1;
}
- return get_algorithm(method, compress) != NULL;
+ 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, int compression_flags) {
+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);
}
@@ -116,29 +128,29 @@ zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t method) {
static zip_source_t *
-compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool compress, int compression_flags) {
+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;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return NULL;
}
- if ((algorithm = get_algorithm(method, compress)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 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;
+ 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;
+ context_free(ctx);
+ return NULL;
}
return s2;
@@ -146,11 +158,11 @@ compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool co
static struct context *
-context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm) {
+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;
+ return NULL;
}
zip_error_init(&ctx->error);
ctx->can_store = compress ? ZIP_CM_IS_DEFAULT(method) : false;
@@ -162,9 +174,9 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre
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;
+ zip_error_fini(&ctx->error);
+ free(ctx);
+ return NULL;
}
return ctx;
@@ -174,7 +186,7 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre
static void
context_free(struct context *ctx) {
if (ctx == NULL) {
- return;
+ return;
}
ctx->algorithm->deallocate(ctx->ud);
@@ -193,96 +205,96 @@ compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t l
zip_uint64_t out_len;
if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) {
- return -1;
+ return -1;
}
if (len == 0 || ctx->end_of_stream) {
- return 0;
+ 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;
- memcpy(data, 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;
- }
+ 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;
+ 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;
@@ -296,72 +308,91 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip
ctx = (struct context *)ud;
switch (cmd) {
- case ZIP_SOURCE_OPEN:
- ctx->size = 0;
- ctx->end_of_input = false;
- ctx->end_of_stream = false;
- ctx->is_stored = false;
- ctx->first_read = -1;
-
- if (!ctx->algorithm->start(ctx->ud)) {
- return -1;
- }
-
- return 0;
+ 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);
+ return compress_read(src, ctx, data, len);
case ZIP_SOURCE_CLOSE:
- if (!ctx->algorithm->end(ctx->ud)) {
- return -1;
- }
- return 0;
+ 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;
- if (ctx->end_of_stream) {
- st->size = ctx->size;
- st->valid |= ZIP_STAT_SIZE;
- }
- else {
- st->valid &= ~ZIP_STAT_SIZE;
- }
- }
+ 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_GET_COMPRESSION_FLAGS:
- return ctx->is_stored ? 0 : ctx->algorithm->compression_flags(ctx->ud);
+ return 0;
case ZIP_SOURCE_ERROR:
- return zip_error_to_data(&ctx->error, data, len);
+ return zip_error_to_data(&ctx->error, data, len);
case ZIP_SOURCE_FREE:
- context_free(ctx);
- return 0;
+ 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_COMPRESSION_FLAGS, -1);
+ return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_SUPPORTS_REOPEN, -1);
default:
- zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
- return -1;
+ return zip_source_pass_to_lower_layer(src, data, len, cmd);
}
}
diff --git a/src/Common/libzip/zip_source_crc.c b/src/Common/libzip/zip_source_crc.c
index e16f9298..435a084b 100644
--- a/src/Common/libzip/zip_source_crc.c
+++ b/src/Common/libzip/zip_source_crc.c
@@ -1,9 +1,9 @@
/*
zip_source_crc.c -- pass-through source that calculates CRC32 and size
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -34,7 +34,7 @@
#include <limits.h>
#include <stdlib.h>
-#include <string.h>
+#include <zlib.h>
#include "zipint.h"
@@ -52,17 +52,17 @@ static zip_int64_t crc_read(zip_source_t *, void *, void *, zip_uint64_t, zip_so
zip_source_t *
-zip_source_crc(zip_t *za, zip_source_t *src, int validate) {
+zip_source_crc_create(zip_source_t *src, int validate, zip_error_t *error) {
struct crc_context *ctx;
if (src == NULL) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return NULL;
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return NULL;
}
if ((ctx = (struct crc_context *)malloc(sizeof(*ctx))) == NULL) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
- return NULL;
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
}
zip_error_init(&ctx->error);
@@ -72,7 +72,7 @@ zip_source_crc(zip_t *za, zip_source_t *src, int validate) {
ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
ctx->size = 0;
- return zip_source_layered(za, src, crc_read, ctx);
+ return zip_source_layered_create(src, crc_read, ctx, error);
}
@@ -85,113 +85,119 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
switch (cmd) {
case ZIP_SOURCE_OPEN:
- ctx->position = 0;
- return 0;
+ 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) {
- zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
- 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;
+ 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;
+ return 0;
case ZIP_SOURCE_STAT: {
- zip_stat_t *st;
-
- st = (zip_stat_t *)data;
-
- if (ctx->crc_complete) {
- /* 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;
+ 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);
+ return zip_error_to_data(&ctx->error, data, len);
case ZIP_SOURCE_FREE:
- free(ctx);
- return 0;
+ free(ctx);
+ return 0;
case ZIP_SOURCE_SUPPORTS: {
- zip_int64_t mask = zip_source_supports(src);
+ zip_int64_t mask = zip_source_supports(src);
- if (mask < 0) {
- _zip_error_set_from_source(&ctx->error, src);
- return -1;
- }
+ if (mask < 0) {
+ zip_error_set_from_source(&ctx->error, src);
+ return -1;
+ }
- return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_COMPRESSION_FLAGS, -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);
+ 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;
- }
+ 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;
+ ctx->position = (zip_uint64_t)new_position;
- return 0;
+ return 0;
}
case ZIP_SOURCE_TELL:
- return (zip_int64_t)ctx->position;
+ return (zip_int64_t)ctx->position;
default:
- zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
- return -1;
+ return zip_source_pass_to_lower_layer(src, data, len, cmd);
}
}
diff --git a/src/Common/libzip/zip_source_deflate.c b/src/Common/libzip/zip_source_deflate.c
deleted file mode 100644
index 2574ad01..00000000
--- a/src/Common/libzip/zip_source_deflate.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- zip_source_deflate.c -- deflate (de)compressoin routines
- Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner
-
- This file is part of libzip, a library to manipulate ZIP archives.
- The authors can be contacted at <libzip@nih.at>
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- 3. The names of the authors may not be used to endorse or promote
- products derived from this software without specific prior
- written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include "zipint.h"
-
-struct deflate {
- zip_error_t error;
-
- bool eof;
- bool can_store;
- bool is_stored;
- int mem_level;
- zip_uint64_t size;
- zip_uint8_t buffer[BUFSIZE];
- z_stream zstr;
-};
-
-static zip_int64_t compress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t);
-static zip_int64_t decompress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t);
-static zip_int64_t deflate_compress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
-static zip_int64_t deflate_decompress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
-static void deflate_free(struct deflate *);
-
-
-zip_source_t *
-zip_source_deflate(zip_t *za, zip_source_t *src, zip_int32_t cm, int flags)
-{
- struct deflate *ctx;
- zip_source_t *s2;
-
- if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return NULL;
- }
-
- if ((ctx=(struct deflate *)malloc(sizeof(*ctx))) == NULL) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
- return NULL;
- }
-
- zip_error_init(&ctx->error);
- ctx->eof = false;
- ctx->is_stored = false;
- ctx->can_store = ZIP_CM_IS_DEFAULT(cm);
- if (flags & ZIP_CODEC_ENCODE) {
- ctx->mem_level = MAX_MEM_LEVEL;
- }
-
- if ((s2=zip_source_layered(za, src,
- ((flags & ZIP_CODEC_ENCODE)
- ? deflate_compress : deflate_decompress),
- ctx)) == NULL) {
- deflate_free(ctx);
- return NULL;
- }
-
- return s2;
-}
-
-
-static zip_int64_t
-compress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
-{
- int end, ret;
- zip_int64_t n;
- zip_uint64_t out_offset;
- uInt out_len;
-
- if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK)
- return -1;
-
- if (len == 0 || ctx->is_stored) {
- return 0;
- }
-
- out_offset = 0;
- out_len = (uInt)ZIP_MIN(UINT_MAX, len);
- ctx->zstr.next_out = (Bytef *)data;
- ctx->zstr.avail_out = out_len;
-
- end = 0;
- while (!end) {
- ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0);
-
- switch (ret) {
- case Z_STREAM_END:
- if (ctx->can_store && ctx->zstr.total_in <= ctx->zstr.total_out) {
- ctx->is_stored = true;
- ctx->size = ctx->zstr.total_in;
- memcpy(data, ctx->buffer, ctx->size);
- return (zip_int64_t)ctx->size;
- }
- /* fallthrough */
- case Z_OK:
- /* all ok */
-
- if (ctx->zstr.avail_out == 0) {
- out_offset += out_len;
- if (out_offset < len) {
- out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset);
- ctx->zstr.next_out = (Bytef *)data+out_offset;
- ctx->zstr.avail_out = out_len;
- }
- else {
- ctx->can_store = false;
- end = 1;
- }
- }
- else if (ctx->eof && ctx->zstr.avail_in == 0)
- end = 1;
- break;
-
- case Z_BUF_ERROR:
- if (ctx->zstr.avail_in == 0) {
- if (ctx->eof) {
- end = 1;
- break;
- }
-
- if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
- _zip_error_set_from_source(&ctx->error, src);
- end = 1;
- break;
- }
- else if (n == 0) {
- ctx->eof = true;
- /* TODO: check against stat of src? */
- ctx->size = ctx->zstr.total_in;
- }
- else {
- if (ctx->zstr.total_in > 0) {
- /* we overwrote a previously filled ctx->buffer */
- ctx->can_store = false;
- }
- ctx->zstr.next_in = (Bytef *)ctx->buffer;
- ctx->zstr.avail_in = (uInt)n;
- }
- continue;
- }
- /* fallthrough */
- case Z_NEED_DICT:
- case Z_DATA_ERROR:
- case Z_STREAM_ERROR:
- case Z_MEM_ERROR:
- zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
-
- end = 1;
- break;
- }
- }
-
- if (ctx->zstr.avail_out < len) {
- ctx->can_store = false;
- return (zip_int64_t)(len - ctx->zstr.avail_out);
- }
-
- return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
-}
-
-
-static zip_int64_t
-decompress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len)
-{
- int end, ret;
- zip_int64_t n;
- zip_uint64_t out_offset;
- uInt out_len;
-
- if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK)
- return -1;
-
- if (len == 0)
- return 0;
-
- out_offset = 0;
- out_len = (uInt)ZIP_MIN(UINT_MAX, len);
- ctx->zstr.next_out = (Bytef *)data;
- ctx->zstr.avail_out = out_len;
-
- end = 0;
- while (!end) {
- ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
-
- switch (ret) {
- case Z_OK:
- if (ctx->zstr.avail_out == 0) {
- out_offset += out_len;
- if (out_offset < len) {
- out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset);
- ctx->zstr.next_out = (Bytef *)data+out_offset;
- ctx->zstr.avail_out = out_len;
- }
- else {
- end = 1;
- }
- }
- break;
-
- case Z_STREAM_END:
- ctx->eof = 1;
- end = 1;
- break;
-
- case Z_BUF_ERROR:
- if (ctx->zstr.avail_in == 0) {
- if (ctx->eof) {
- end = 1;
- break;
- }
-
- if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
- _zip_error_set_from_source(&ctx->error, src);
- end = 1;
- break;
- }
- else if (n == 0) {
- ctx->eof = 1;
- }
- else {
- ctx->zstr.next_in = (Bytef *)ctx->buffer;
- ctx->zstr.avail_in = (uInt)n;
- }
- continue;
- }
- /* fallthrough */
- case Z_NEED_DICT:
- case Z_DATA_ERROR:
- case Z_STREAM_ERROR:
- case Z_MEM_ERROR:
- zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
- end = 1;
- break;
- }
- }
-
- if (ctx->zstr.avail_out < len)
- return (zip_int64_t)(len - ctx->zstr.avail_out);
-
- return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
-}
-
-
-static zip_int64_t
-deflate_compress(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
-{
- struct deflate *ctx;
- int ret;
-
- ctx = (struct deflate *)ud;
-
- switch (cmd) {
- case ZIP_SOURCE_OPEN:
- ctx->zstr.zalloc = Z_NULL;
- ctx->zstr.zfree = Z_NULL;
- ctx->zstr.opaque = NULL;
- ctx->zstr.avail_in = 0;
- ctx->zstr.next_in = NULL;
- ctx->zstr.avail_out = 0;
- ctx->zstr.next_out = NULL;
-
- /* negative value to tell zlib not to write a header */
- if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, ctx->mem_level, Z_DEFAULT_STRATEGY)) != Z_OK) {
- zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
- return -1;
- }
-
- return 0;
-
- case ZIP_SOURCE_READ:
- return compress_read(src, ctx, data, len);
-
- case ZIP_SOURCE_CLOSE:
- deflateEnd(&ctx->zstr);
- return 0;
-
- case ZIP_SOURCE_STAT:
- {
- zip_stat_t *st;
-
- st = (zip_stat_t *)data;
-
- st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_DEFLATE;
- st->valid |= ZIP_STAT_COMP_METHOD;
- if (ctx->eof) {
- st->comp_size = ctx->size;
- st->valid |= ZIP_STAT_COMP_SIZE;
- }
- else
- st->valid &= ~ZIP_STAT_COMP_SIZE;
- }
- return 0;
-
- case ZIP_SOURCE_ERROR:
- return zip_error_to_data(&ctx->error, data, len);
-
- case ZIP_SOURCE_FREE:
- deflate_free(ctx);
- return 0;
-
- case ZIP_SOURCE_SUPPORTS:
- return ZIP_SOURCE_SUPPORTS_READABLE;
-
- default:
- zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
- return -1;
- }
-}
-
-
-static zip_int64_t
-deflate_decompress(zip_source_t *src, void *ud, void *data,
- zip_uint64_t len, zip_source_cmd_t cmd)
-{
- struct deflate *ctx;
- zip_int64_t n;
- int ret;
-
- ctx = (struct deflate *)ud;
-
- switch (cmd) {
- case ZIP_SOURCE_OPEN:
- if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
- _zip_error_set_from_source(&ctx->error, src);
- return -1;
- }
-
- ctx->zstr.zalloc = Z_NULL;
- ctx->zstr.zfree = Z_NULL;
- ctx->zstr.opaque = NULL;
- ctx->zstr.next_in = (Bytef *)ctx->buffer;
- ctx->zstr.avail_in = (uInt)n;
-
- /* negative value to tell zlib that there is no header */
- if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) {
- zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret);
- return -1;
- }
- return 0;
-
- case ZIP_SOURCE_READ:
- return decompress_read(src, ctx, data, len);
-
- case ZIP_SOURCE_CLOSE:
- inflateEnd(&ctx->zstr);
- return 0;
-
- case ZIP_SOURCE_STAT:
- {
- zip_stat_t *st;
-
- st = (zip_stat_t *)data;
-
- st->comp_method = ZIP_CM_STORE;
- if (st->comp_size > 0 && st->size > 0)
- st->comp_size = st->size;
-
- 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:
- return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
-
- default:
- zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
- return -1;
- }
-}
-
-
-static void
-deflate_free(struct deflate *ctx)
-{
- free(ctx);
-}
diff --git a/src/Common/libzip/zip_source_error.c b/src/Common/libzip/zip_source_error.c
index 1e0e0d46..dc7fa20c 100644
--- a/src/Common/libzip/zip_source_error.c
+++ b/src/Common/libzip/zip_source_error.c
@@ -1,9 +1,9 @@
/*
zip_source_error.c -- get last error from zip_source
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/Common/libzip/zip_source_file.h b/src/Common/libzip/zip_source_file.h
new file mode 100644
index 00000000..cca9fd2b
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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/src/Common/libzip/zip_source_file_common.c b/src/Common/libzip/zip_source_file_common.c
new file mode 100644
index 00000000..6c58320f
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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/src/Common/libzip/zip_source_file_stdio.c b/src/Common/libzip/zip_source_file_stdio.c
new file mode 100644
index 00000000..6dcc5639
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#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/src/Common/libzip/zip_source_file_stdio.h b/src/Common/libzip/zip_source_file_stdio.h
new file mode 100644
index 00000000..802e6071
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdio.h>
+
+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/src/Common/libzip/zip_source_file_stdio_named.c b/src/Common/libzip/zip_source_file_stdio_named.c
new file mode 100644
index 00000000..1495d7dd
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_CLONEFILE
+#include <sys/attr.h>
+#include <sys/clonefile.h>
+#define CAN_CLONE
+#endif
+#ifdef HAVE_FICLONERANGE
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#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/src/Common/libzip/zip_source_file_win32.c b/src/Common/libzip/zip_source_file_win32.c
new file mode 100644
index 00000000..624860b1
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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/src/Common/libzip/zip_source_file_win32.h b/src/Common/libzip/zip_source_file_win32.h
new file mode 100644
index 00000000..d86069ec
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <windows.h>
+
+#include <aclapi.h>
+
+#include <stdlib.h>
+
+#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/src/Common/libzip/zip_source_file_win32_ansi.c b/src/Common/libzip/zip_source_file_win32_ansi.c
new file mode 100644
index 00000000..58034cc2
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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/src/Common/libzip/zip_source_file_win32_named.c b/src/Common/libzip/zip_source_file_win32_named.c
new file mode 100644
index 00000000..855e605a
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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/src/Common/libzip/zip_source_file_win32_utf16.c b/src/Common/libzip/zip_source_file_win32_utf16.c
new file mode 100644
index 00000000..8f07d021
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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/src/Common/libzip/zip_source_win32utf8.c b/src/Common/libzip/zip_source_file_win32_utf8.c
index 103b498c..d154f97a 100644
--- a/src/Common/libzip/zip_source_win32utf8.c
+++ b/src/Common/libzip/zip_source_file_win32_utf8.c
@@ -1,9 +1,9 @@
/*
- zip_source_win32utf8.c -- create data source from Windows file (UTF-8)
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -31,22 +31,13 @@
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 <windows.h>
-
-#include <stdlib.h>
-
-#include "zipint.h"
-#include "zipwin32.h"
-
+#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;
+ if (za == NULL) {
+ return NULL;
+ }
return zip_source_file_create(fname, start, len, &za->error);
}
@@ -58,20 +49,20 @@ zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length
wchar_t *wfname;
zip_source_t *source;
- if (fname == NULL || length < -1) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
+ 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;
+ 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;
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
}
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, wfname, size);
diff --git a/src/Common/libzip/zip_source_filep.c b/src/Common/libzip/zip_source_filep.c
deleted file mode 100644
index cb3d1511..00000000
--- a/src/Common/libzip/zip_source_filep.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- zip_source_filep.c -- create data source from FILE *
- Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
-
- This file is part of libzip, a library to manipulate ZIP archives.
- The authors can be contacted at <libzip@nih.at>
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- 3. The names of the authors may not be used to endorse or promote
- products derived from this software without specific prior
- written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "zipint.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_CLONEFILE
-#include <sys/attr.h>
-#include <sys/clonefile.h>
-#define CAN_CLONE
-#endif
-#ifdef HAVE_FICLONERANGE
-#include <linux/fs.h>
-#include <sys/ioctl.h>
-#define CAN_CLONE
-#endif
-
-#ifdef _WIN32
-/* WIN32 needs <fcntl.h> for _O_BINARY */
-#include <fcntl.h>
-#endif
-
-/* Windows sys/types.h does not provide these */
-#ifndef S_ISREG
-#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
-#endif
-#if defined(S_IXUSR) && defined(S_IRWXG) && defined(S_IRWXO)
-#define _SAFE_MASK (S_IXUSR | S_IRWXG | S_IRWXO)
-#elif defined(_S_IWRITE)
-#define _SAFE_MASK (_S_IWRITE)
-#else
-#error do not know safe values for umask, please report this
-#endif
-
-#ifdef _MSC_VER
-/* MSVC doesn't have mode_t */
-typedef int mode_t;
-#endif
-
-struct read_file {
- zip_error_t error; /* last error information */
- zip_int64_t supports;
-
- /* reading */
- char *fname; /* name of file to read from */
- FILE *f; /* file to read from */
- struct zip_stat st; /* stat information passed in */
- zip_error_t stat_error; /* error returned for stat */
- zip_uint64_t start; /* start offset of data to read */
- zip_uint64_t end; /* end offset of data to read relative to start, 0 for up to EOF */
- zip_uint64_t current; /* current offset relative to start (0 is beginning of part we read) */
-
- /* writing */
- char *tmpname;
- FILE *fout;
-};
-
-static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd);
-static int create_temp_output(struct read_file *ctx);
-#ifdef CAN_CLONE
-static zip_int64_t create_temp_output_cloning(struct read_file *ctx, zip_uint64_t offset);
-#endif
-static int _zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error);
-static int _zip_fseek(FILE *f, zip_int64_t offset, int whence, zip_error_t *error);
-
-
-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 < -1) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
- }
-
- return _zip_source_file_or_p(NULL, file, start, length, NULL, error);
-}
-
-
-zip_source_t *
-_zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_error_t *error) {
- struct read_file *ctx;
- zip_source_t *zs;
- struct stat sb;
- bool stat_valid;
-
- if (file == NULL && fname == NULL) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
- }
-
- if (len < 0) {
- len = 0;
- }
-
- if (start > ZIP_INT64_MAX || start + (zip_uint64_t)len < start) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
- }
-
- if ((ctx = (struct read_file *)malloc(sizeof(struct read_file))) == NULL) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- return NULL;
- }
-
- ctx->fname = NULL;
- if (fname) {
- if ((ctx->fname = strdup(fname)) == NULL) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- free(ctx);
- return NULL;
- }
- }
- ctx->f = file;
- ctx->start = start;
- ctx->end = (zip_uint64_t)len;
- if (st) {
- memcpy(&ctx->st, st, sizeof(ctx->st));
- ctx->st.name = NULL;
- ctx->st.valid &= ~ZIP_STAT_NAME;
- }
- else {
- zip_stat_init(&ctx->st);
- }
-
- if (ctx->end > 0) {
- ctx->st.size = ctx->end;
- ctx->st.valid |= ZIP_STAT_SIZE;
- }
-
- zip_error_init(&ctx->stat_error);
-
- ctx->tmpname = NULL;
- ctx->fout = NULL;
-
- zip_error_init(&ctx->error);
-
- ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1);
-
- if (ctx->fname) {
- stat_valid = stat(ctx->fname, &sb) >= 0;
-
- if (!stat_valid) {
- if (ctx->start == 0 && ctx->end == 0) {
- ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
- }
- }
- }
- else {
- stat_valid = fstat(fileno(ctx->f), &sb) >= 0;
- }
-
- if (!stat_valid) {
- zip_error_set(&ctx->stat_error, ZIP_ER_READ, errno);
- }
- else {
- if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) {
- ctx->st.mtime = sb.st_mtime;
- ctx->st.valid |= ZIP_STAT_MTIME;
- }
- if (S_ISREG(sb.st_mode)) {
- ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
-
- if (ctx->start + ctx->end > (zip_uint64_t)sb.st_size) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- free(ctx->fname);
- free(ctx);
- return NULL;
- }
-
- if (ctx->end == 0) {
- ctx->st.size = (zip_uint64_t)sb.st_size - ctx->start;
- ctx->st.valid |= ZIP_STAT_SIZE;
-
- if (ctx->fname && start == 0) {
- ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
- }
- }
- }
- }
-
-#ifdef CAN_CLONE
- if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) {
- ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING);
- }
-#endif
-
- if ((zs = zip_source_function_create(read_file, ctx, error)) == NULL) {
- free(ctx->fname);
- free(ctx);
- return NULL;
- }
-
- return zs;
-}
-
-
-static int
-create_temp_output(struct read_file *ctx) {
- char *temp;
- int tfd;
- mode_t mask;
- FILE *tfp;
-
- if ((temp = (char *)malloc(strlen(ctx->fname) + 8)) == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
- return -1;
- }
- sprintf(temp, "%s.XXXXXX", ctx->fname);
-
- mask = umask(_SAFE_MASK);
- if ((tfd = mkstemp(temp)) == -1) {
- zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
- umask(mask);
- free(temp);
- return -1;
- }
- umask(mask);
-
- if ((tfp = fdopen(tfd, "r+b")) == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
- close(tfd);
- (void)remove(temp);
- free(temp);
- return -1;
- }
-
-#ifdef _WIN32
- /*
- According to Pierre Joye, Windows in some environments per
- default creates text files, so force binary mode.
- */
- _setmode(_fileno(tfp), _O_BINARY);
-#endif
-
- ctx->fout = tfp;
- ctx->tmpname = temp;
-
- return 0;
-}
-
-#ifdef CAN_CLONE
-zip_int64_t static create_temp_output_cloning(struct read_file *ctx, zip_uint64_t offset) {
- char *temp;
- FILE *tfp;
-
- if (offset > ZIP_OFF_MAX) {
- zip_error_set(&ctx->error, ZIP_ER_SEEK, E2BIG);
- return -1;
- }
-
- if ((temp = (char *)malloc(strlen(ctx->fname) + 8)) == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
- return -1;
- }
- sprintf(temp, "%s.XXXXXX", ctx->fname);
-
-#ifdef HAVE_CLONEFILE
-#ifndef __clang_analyzer__
- /* we can't use mkstemp, since clonefile insists on creating the file */
- if (mktemp(temp) == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
- free(temp);
- return -1;
- }
-#endif
-
- if (clonefile(ctx->fname, temp, 0) < 0) {
- zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
- free(temp);
- return -1;
- }
- if ((tfp = fopen(temp, "r+b")) == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
- (void)remove(temp);
- free(temp);
- 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 = mkstemp(temp)) < 0) {
- zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
- free(temp);
- 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(temp);
- free(temp);
- return -1;
- }
-
- if ((tfp = fdopen(fd, "r+b")) == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
- (void)close(fd);
- (void)remove(temp);
- free(temp);
- return -1;
- }
- }
-#endif
-
- if (ftruncate(fileno(tfp), (off_t)offset) < 0) {
- (void)fclose(tfp);
- (void)remove(temp);
- free(temp);
- return -1;
- }
- if (fseeko(tfp, (off_t)offset, SEEK_SET) < 0) {
- (void)fclose(tfp);
- (void)remove(temp);
- free(temp);
- zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
- }
-
- ctx->fout = tfp;
- ctx->tmpname = temp;
-
- return 0;
-}
-#endif
-
-
-static zip_int64_t
-read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
- struct read_file *ctx;
- char *buf;
- zip_uint64_t n;
- size_t i;
-
- ctx = (struct read_file *)state;
- buf = (char *)data;
-
- switch (cmd) {
- case ZIP_SOURCE_BEGIN_WRITE:
- if (ctx->fname == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
- return -1;
- }
- return create_temp_output(ctx);
-
-#ifdef CAN_CLONE
- case ZIP_SOURCE_BEGIN_WRITE_CLONING:
- if (ctx->fname == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
- return -1;
- }
- return create_temp_output_cloning(ctx, len);
-#endif
-
- case ZIP_SOURCE_COMMIT_WRITE: {
- mode_t mode;
- struct stat st;
-
- if (fclose(ctx->fout) < 0) {
- ctx->fout = NULL;
- zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
- }
- ctx->fout = NULL;
- if (stat(ctx->fname, &st) == 0) {
- mode = st.st_mode;
- } else {
- mode_t mask = umask(022);
- umask(mask);
- mode = 0666 & ~mask;
- }
- if (rename(ctx->tmpname, ctx->fname) < 0) {
- zip_error_set(&ctx->error, ZIP_ER_RENAME, errno);
- return -1;
- }
- /* not much we can do if chmod fails except make the whole commit fail */
- (void)chmod(ctx->fname, mode);
- free(ctx->tmpname);
- ctx->tmpname = NULL;
- return 0;
- }
-
- case ZIP_SOURCE_CLOSE:
- if (ctx->fname) {
- fclose(ctx->f);
- ctx->f = NULL;
- }
- return 0;
-
- case ZIP_SOURCE_ERROR:
- return zip_error_to_data(&ctx->error, data, len);
-
- case ZIP_SOURCE_FREE:
- free(ctx->fname);
- free(ctx->tmpname);
- if (ctx->f)
- fclose(ctx->f);
- free(ctx);
- return 0;
-
- case ZIP_SOURCE_OPEN:
- if (ctx->fname) {
- if ((ctx->f = fopen(ctx->fname, "rb")) == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_OPEN, errno);
- return -1;
- }
- }
-
- if (ctx->start > 0) {
- if (_zip_fseek_u(ctx->f, ctx->start, SEEK_SET, &ctx->error) < 0) {
- /* TODO: skip by reading */
- return -1;
- }
- }
- ctx->current = 0;
- return 0;
-
- case ZIP_SOURCE_READ:
- if (ctx->end > 0) {
- n = ctx->end - ctx->current;
- if (n > len) {
- n = len;
- }
- }
- else {
- n = len;
- }
-
- if (n > SIZE_MAX)
- n = SIZE_MAX;
-
- if ((i = fread(buf, 1, (size_t)n, ctx->f)) == 0) {
- if (ferror(ctx->f)) {
- zip_error_set(&ctx->error, ZIP_ER_READ, errno);
- return -1;
- }
- }
- ctx->current += i;
-
- return (zip_int64_t)i;
-
- case ZIP_SOURCE_REMOVE:
- if (remove(ctx->fname) < 0) {
- zip_error_set(&ctx->error, ZIP_ER_REMOVE, errno);
- return -1;
- }
- return 0;
-
- case ZIP_SOURCE_ROLLBACK_WRITE:
- if (ctx->fout) {
- fclose(ctx->fout);
- ctx->fout = NULL;
- }
- (void)remove(ctx->tmpname);
- free(ctx->tmpname);
- ctx->tmpname = NULL;
- return 0;
-
- case ZIP_SOURCE_SEEK: {
- zip_int64_t new_current;
- int need_seek;
- zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
-
- if (args == NULL)
- return -1;
-
- need_seek = 1;
-
- switch (args->whence) {
- case SEEK_SET:
- new_current = args->offset;
- break;
-
- case SEEK_END:
- if (ctx->end == 0) {
- if (_zip_fseek(ctx->f, args->offset, SEEK_END, &ctx->error) < 0) {
- return -1;
- }
- if ((new_current = ftello(ctx->f)) < 0) {
- zip_error_set(&ctx->error, ZIP_ER_SEEK, errno);
- return -1;
- }
- new_current -= (zip_int64_t)ctx->start;
- need_seek = 0;
- }
- else {
- new_current = (zip_int64_t)ctx->end + args->offset;
- }
- break;
-
- case SEEK_CUR:
- new_current = (zip_int64_t)ctx->current + args->offset;
- break;
-
- default:
- zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
- return -1;
- }
-
- if (new_current < 0 || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end) || (zip_uint64_t)new_current + ctx->start < ctx->start) {
- zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
- return -1;
- }
-
- ctx->current = (zip_uint64_t)new_current;
-
- if (need_seek) {
- if (_zip_fseek_u(ctx->f, ctx->current + ctx->start, SEEK_SET, &ctx->error) < 0) {
- return -1;
- }
- }
- return 0;
- }
-
- case ZIP_SOURCE_SEEK_WRITE: {
- zip_source_args_seek_t *args;
-
- args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
- if (args == NULL) {
- return -1;
- }
-
- if (_zip_fseek(ctx->fout, args->offset, args->whence, &ctx->error) < 0) {
- return -1;
- }
- 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;
- }
-
- memcpy(data, &ctx->st, sizeof(ctx->st));
- return sizeof(ctx->st);
- }
-
- case ZIP_SOURCE_SUPPORTS:
- return ctx->supports;
-
- case ZIP_SOURCE_TELL:
- return (zip_int64_t)ctx->current;
-
- case ZIP_SOURCE_TELL_WRITE: {
- off_t ret = ftello(ctx->fout);
-
- if (ret < 0) {
- zip_error_set(&ctx->error, ZIP_ER_TELL, errno);
- return -1;
- }
- return ret;
- }
-
- case ZIP_SOURCE_WRITE: {
- size_t ret;
-
- clearerr(ctx->fout);
- ret = fwrite(data, 1, len, ctx->fout);
- if (ret != len || ferror(ctx->fout)) {
- zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
- return -1;
- }
-
- return (zip_int64_t)ret;
- }
-
- default:
- zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
- return -1;
- }
-}
-
-
-static int
-_zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error) {
- if (offset > ZIP_INT64_MAX) {
- zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW);
- return -1;
- }
- return _zip_fseek(f, (zip_int64_t)offset, whence, error);
-}
-
-
-static int
-_zip_fseek(FILE *f, zip_int64_t offset, int whence, zip_error_t *error) {
- if (offset > ZIP_FSEEK_MAX || offset < ZIP_FSEEK_MIN) {
- zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW);
- return -1;
- }
- if (fseeko(f, (off_t)offset, whence) < 0) {
- zip_error_set(error, ZIP_ER_SEEK, errno);
- return -1;
- }
- return 0;
-}
diff --git a/src/Common/libzip/zip_source_free.c b/src/Common/libzip/zip_source_free.c
index dd3c6df9..1a800405 100644
--- a/src/Common/libzip/zip_source_free.c
+++ b/src/Common/libzip/zip_source_free.c
@@ -1,9 +1,9 @@
/*
zip_source_free.c -- free zip data source
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,31 +40,31 @@
ZIP_EXTERN void
zip_source_free(zip_source_t *src) {
if (src == NULL)
- return;
+ return;
if (src->refcount > 0) {
- src->refcount--;
+ src->refcount--;
}
if (src->refcount > 0) {
- return;
+ return;
}
if (ZIP_SOURCE_IS_OPEN_READING(src)) {
- src->open_count = 1; /* force close */
- zip_source_close(src);
+ src->open_count = 1; /* force close */
+ zip_source_close(src);
}
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
- zip_source_rollback_write(src);
+ zip_source_rollback_write(src);
}
if (src->source_archive && !src->source_closed) {
- _zip_deregister_source(src->source_archive, src);
+ _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);
+ zip_source_free(src->src);
}
free(src);
diff --git a/src/Common/libzip/zip_source_function.c b/src/Common/libzip/zip_source_function.c
index c9730c95..1fe6396e 100644
--- a/src/Common/libzip/zip_source_function.c
+++ b/src/Common/libzip/zip_source_function.c
@@ -1,9 +1,9 @@
/*
zip_source_function.c -- create zip data source from callback function
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,7 +40,7 @@
ZIP_EXTERN zip_source_t *
zip_source_function(zip_t *za, zip_source_callback zcb, void *ud) {
if (za == NULL) {
- return NULL;
+ return NULL;
}
return zip_source_function_create(zcb, ud, &za->error);
@@ -52,15 +52,16 @@ 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;
+ 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_SUPPORTS_READABLE;
}
+ zs->supports |= zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, -1);
return zs;
}
@@ -77,8 +78,8 @@ _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;
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
}
src->src = NULL;
@@ -92,6 +93,7 @@ _zip_source_new(zip_error_t *error) {
zip_error_init(&src->error);
src->eof = false;
src->had_read_error = false;
+ src->bytes_read = 0;
return src;
}
diff --git a/src/Common/libzip/zip_source_get_file_attributes.c b/src/Common/libzip/zip_source_get_file_attributes.c
new file mode 100644
index 00000000..4771dc16
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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/src/Common/libzip/zip_source_is_deleted.c b/src/Common/libzip/zip_source_is_deleted.c
index 090a67b4..838aa909 100644
--- a/src/Common/libzip/zip_source_is_deleted.c
+++ b/src/Common/libzip/zip_source_is_deleted.c
@@ -1,9 +1,9 @@
/*
zip_source_is_deleted.c -- was archive was removed?
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/Common/libzip/zip_source_layered.c b/src/Common/libzip/zip_source_layered.c
index 580bff0e..62b78e68 100644
--- a/src/Common/libzip/zip_source_layered.c
+++ b/src/Common/libzip/zip_source_layered.c
@@ -1,9 +1,9 @@
/*
zip_source_layered.c -- create layered source
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,7 +40,7 @@
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 NULL;
return zip_source_layered_create(src, cb, ud, &za->error);
}
@@ -49,19 +49,27 @@ zip_source_layered(zip_t *za, zip_source_t *src, zip_source_layered_callback cb,
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;
- if ((zs = _zip_source_new(error)) == NULL)
- return NULL;
+ 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;
+ }
- zip_source_keep(src);
zs->src = src;
zs->cb.l = cb;
zs->ud = ud;
+ zs->supports = supports;
- zs->supports = cb(src, ud, NULL, 0, ZIP_SOURCE_SUPPORTS);
- if (zs->supports < 0) {
- zs->supports = ZIP_SOURCE_SUPPORTS_READABLE;
- }
+ /* 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/src/Common/libzip/zip_source_open.c b/src/Common/libzip/zip_source_open.c
index d10a3c55..b34fa2c6 100644
--- a/src/Common/libzip/zip_source_open.c
+++ b/src/Common/libzip/zip_source_open.c
@@ -1,9 +1,9 @@
/*
zip_source_open.c -- open zip_source (prepare for reading)
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -37,38 +37,39 @@
ZIP_EXTERN int
zip_source_open(zip_source_t *src) {
if (src->source_closed) {
- return -1;
+ return -1;
}
if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) {
- zip_error_set(&src->error, ZIP_ER_DELETED, 0);
- return -1;
+ 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;
- }
+ 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_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;
- }
+ 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/src/Common/libzip/zip_source_pass_to_lower_layer.c b/src/Common/libzip/zip_source_pass_to_lower_layer.c
new file mode 100644
index 00000000..4a98222e
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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/src/Common/libzip/zip_source_pkware.c b/src/Common/libzip/zip_source_pkware.c
deleted file mode 100644
index cc510ea5..00000000
--- a/src/Common/libzip/zip_source_pkware.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- zip_source_pkware.c -- Traditional PKWARE de/encryption routines
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
-
- This file is part of libzip, a library to manipulate ZIP archives.
- The authors can be contacted at <libzip@nih.at>
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- 3. The names of the authors may not be used to endorse or promote
- products derived from this software without specific prior
- written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
-#include <string.h>
-
-#include "zipint.h"
-
-struct trad_pkware {
- zip_error_t error;
- zip_uint32_t key[3];
-};
-
-#define HEADERLEN 12
-#define KEY0 305419896
-#define KEY1 591751049
-#define KEY2 878082192
-
-
-static void decrypt(struct trad_pkware *, zip_uint8_t *, const zip_uint8_t *, zip_uint64_t, int);
-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 void pkware_free(struct trad_pkware *);
-
-
-zip_source_t *
-zip_source_pkware(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 = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
- return NULL;
- }
-
- zip_error_init(&ctx->error);
-
- ctx->key[0] = KEY0;
- ctx->key[1] = KEY1;
- ctx->key[2] = KEY2;
- decrypt(ctx, NULL, (const zip_uint8_t *)password, strlen(password), 1);
-
- if ((s2 = zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) {
- pkware_free(ctx);
- return NULL;
- }
-
- return s2;
-}
-
-
-static void
-decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len, int update_only) {
- zip_uint16_t tmp;
- zip_uint64_t i;
- Bytef b;
-
- for (i = 0; i < len; i++) {
- b = in[i];
-
- if (!update_only) {
- /* decrypt next byte */
- tmp = (zip_uint16_t)(ctx->key[2] | 2);
- tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8);
- b ^= (Bytef)tmp;
- }
-
- /* store cleartext */
- if (out)
- out[i] = b;
-
- /* update keys */
- ctx->key[0] = (zip_uint32_t)crc32(ctx->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
- ctx->key[1] = (ctx->key[1] + (ctx->key[0] & 0xff)) * 134775813 + 1;
- b = (Bytef)(ctx->key[1] >> 24);
- ctx->key[2] = (zip_uint32_t)crc32(ctx->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL;
- }
-}
-
-
-static int
-decrypt_header(zip_source_t *src, struct trad_pkware *ctx) {
- zip_uint8_t header[HEADERLEN];
- struct zip_stat st;
- zip_int64_t n;
- unsigned short dostime, dosdate;
-
- 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;
- }
-
- decrypt(ctx, header, header, HEADERLEN, 0);
-
- if (zip_source_stat(src, &st) < 0) {
- /* stat failed, skip password validation */
- return 0;
- }
-
- _zip_u2d_time(st.mtime, &dostime, &dosdate);
-
- if (header[HEADERLEN - 1] != st.crc >> 24 && header[HEADERLEN - 1] != dostime >> 8) {
- 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:
- 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;
- }
-
- decrypt((struct trad_pkware *)ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n, 0);
- 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;
- /* TODO: deduce HEADERLEN from size for uncompressed */
- if (st->valid & ZIP_STAT_COMP_SIZE)
- st->comp_size -= 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, -1);
-
- case ZIP_SOURCE_ERROR:
- return zip_error_to_data(&ctx->error, data, len);
-
- case ZIP_SOURCE_FREE:
- pkware_free(ctx);
- return 0;
-
- default:
- zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
- return -1;
- }
-}
-
-
-static void
-pkware_free(struct trad_pkware *ctx) {
- free(ctx);
-}
diff --git a/src/Common/libzip/zip_source_pkware_decode.c b/src/Common/libzip/zip_source_pkware_decode.c
new file mode 100644
index 00000000..b4c482b3
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+#include <string.h>
+
+#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/src/Common/libzip/zip_source_pkware_encode.c b/src/Common/libzip/zip_source_pkware_encode.c
new file mode 100644
index 00000000..d89b9f4e
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+#include <string.h>
+
+#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/src/Common/libzip/zip_source_read.c b/src/Common/libzip/zip_source_read.c
index 816fb3d2..0938fcb0 100644
--- a/src/Common/libzip/zip_source_read.c
+++ b/src/Common/libzip/zip_source_read.c
@@ -1,9 +1,9 @@
/*
zip_source_read.c -- read data from zip_source
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -41,45 +41,51 @@ zip_source_read(zip_source_t *src, void *data, zip_uint64_t len) {
zip_int64_t n;
if (src->source_closed) {
- return -1;
+ 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;
+ zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+ return -1;
}
if (src->had_read_error) {
- return -1;
+ return -1;
}
if (_zip_source_eof(src)) {
- return 0;
+ return 0;
}
if (len == 0) {
- return 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 ((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;
}
diff --git a/src/Common/libzip/zip_source_remove.c b/src/Common/libzip/zip_source_remove.c
index 6841b747..c1d73ab9 100644
--- a/src/Common/libzip/zip_source_remove.c
+++ b/src/Common/libzip/zip_source_remove.c
@@ -1,9 +1,9 @@
/*
zip_source_remove.c -- remove empty archive
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -37,21 +37,26 @@
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;
+ return 0;
}
if (ZIP_SOURCE_IS_OPEN_READING(src)) {
- if (zip_source_close(src) < 0) {
- return -1;
- }
+ if (zip_source_close(src) < 0) {
+ return -1;
+ }
}
if (src->write_state != ZIP_SOURCE_WRITE_CLOSED) {
- zip_source_rollback_write(src);
+ zip_source_rollback_write(src);
}
if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_REMOVE) < 0) {
- return -1;
+ return -1;
}
src->write_state = ZIP_SOURCE_WRITE_REMOVED;
diff --git a/src/Common/libzip/zip_source_rollback_write.c b/src/Common/libzip/zip_source_rollback_write.c
index 04aa9389..ea1a1510 100644
--- a/src/Common/libzip/zip_source_rollback_write.c
+++ b/src/Common/libzip/zip_source_rollback_write.c
@@ -1,9 +1,9 @@
/*
zip_source_rollback_write.c -- discard changes
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -37,8 +37,12 @@
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;
+ return;
}
_zip_source_call(src, NULL, 0, ZIP_SOURCE_ROLLBACK_WRITE);
diff --git a/src/Common/libzip/zip_source_seek.c b/src/Common/libzip/zip_source_seek.c
index c7bd8e6e..e3baad5a 100644
--- a/src/Common/libzip/zip_source_seek.c
+++ b/src/Common/libzip/zip_source_seek.c
@@ -1,9 +1,9 @@
/*
zip_source_seek.c -- seek to offset
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,18 +40,18 @@ 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;
+ 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;
+ 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;
+ return -1;
}
src->eof = 0;
@@ -65,30 +65,30 @@ zip_source_seek_compute_offset(zip_uint64_t offset, zip_uint64_t length, void *d
zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, data_length, error);
if (args == NULL) {
- return -1;
+ return -1;
}
switch (args->whence) {
case SEEK_CUR:
- new_offset = (zip_int64_t)offset + args->offset;
- break;
+ new_offset = (zip_int64_t)offset + args->offset;
+ break;
case SEEK_END:
- new_offset = (zip_int64_t)length + args->offset;
- break;
+ new_offset = (zip_int64_t)length + args->offset;
+ break;
case SEEK_SET:
- new_offset = args->offset;
- break;
+ new_offset = args->offset;
+ break;
default:
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return -1;
+ 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;
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return -1;
}
return new_offset;
diff --git a/src/Common/libzip/zip_source_seek_write.c b/src/Common/libzip/zip_source_seek_write.c
index a20dc82e..34ae2f5a 100644
--- a/src/Common/libzip/zip_source_seek_write.c
+++ b/src/Common/libzip/zip_source_seek_write.c
@@ -1,9 +1,9 @@
/*
zip_source_seek_write.c -- seek to offset for writing
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -39,9 +39,14 @@ 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;
+ zip_error_set(&src->error, ZIP_ER_INVAL, 0);
+ return -1;
}
args.offset = offset;
diff --git a/src/Common/libzip/zip_source_stat.c b/src/Common/libzip/zip_source_stat.c
index f3af3be9..05dcb84d 100644
--- a/src/Common/libzip/zip_source_stat.c
+++ b/src/Common/libzip/zip_source_stat.c
@@ -1,9 +1,9 @@
/*
zip_source_stat.c -- get meta information from zip_source
- Copyright (C) 2009-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -38,24 +38,28 @@
ZIP_EXTERN int
zip_source_stat(zip_source_t *src, zip_stat_t *st) {
if (src->source_closed) {
- return -1;
+ return -1;
}
if (st == NULL) {
- zip_error_set(&src->error, ZIP_ER_INVAL, 0);
- return -1;
+ 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_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 -1;
}
return 0;
diff --git a/src/Common/libzip/zip_source_supports.c b/src/Common/libzip/zip_source_supports.c
index 394f06ec..8fea2ae9 100644
--- a/src/Common/libzip/zip_source_supports.c
+++ b/src/Common/libzip/zip_source_supports.c
@@ -1,9 +1,9 @@
/*
zip_source_supports.c -- check for supported functions
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -42,6 +42,10 @@ 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, ...) {
@@ -53,13 +57,18 @@ zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...) {
va_start(ap, cmd0);
for (;;) {
- int cmd = va_arg(ap, int);
- if (cmd < 0) {
- break;
- }
- bitmap |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd);
+ 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/src/Common/libzip/zip_source_tell.c b/src/Common/libzip/zip_source_tell.c
index da13cf51..49057ce5 100644
--- a/src/Common/libzip/zip_source_tell.c
+++ b/src/Common/libzip/zip_source_tell.c
@@ -1,9 +1,9 @@
/*
zip_source_tell.c -- report current offset
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -38,11 +38,19 @@
ZIP_EXTERN zip_int64_t
zip_source_tell(zip_source_t *src) {
if (src->source_closed) {
- return -1;
+ return -1;
}
if (!ZIP_SOURCE_IS_OPEN_READING(src)) {
- zip_error_set(&src->error, ZIP_ER_INVAL, 0);
- return -1;
+ 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/src/Common/libzip/zip_source_tell_write.c b/src/Common/libzip/zip_source_tell_write.c
index d20139fe..a5b0e531 100644
--- a/src/Common/libzip/zip_source_tell_write.c
+++ b/src/Common/libzip/zip_source_tell_write.c
@@ -1,9 +1,9 @@
/*
zip_source_tell_write.c -- report current offset for writing
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -37,9 +37,14 @@
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;
+ 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/src/Common/libzip/zip_source_win32a.c b/src/Common/libzip/zip_source_win32a.c
deleted file mode 100644
index b4b060a8..00000000
--- a/src/Common/libzip/zip_source_win32a.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- zip_source_win32a.c -- create data source from Windows file (ANSI)
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
-
- This file is part of libzip, a library to manipulate ZIP archives.
- The authors can be contacted at <libzip@nih.at>
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- 3. The names of the authors may not be used to endorse or promote
- products derived from this software without specific prior
- written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- IN CONTRACT, STRICT LIABILITY, OR TORT (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 <windows.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "zipint.h"
-#include "zipwin32.h"
-
-static void *_win32_strdup_a(const void *str);
-static HANDLE _win32_open_a(_zip_source_win32_read_file_t *ctx);
-static HANDLE _win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa);
-static int _win32_rename_temp_a(_zip_source_win32_read_file_t *ctx);
-static int _win32_remove_a(const void *fname);
-
-// clang-format off
-static _zip_source_win32_file_ops_t win32_ops_a = {
- _win32_strdup_a,
- _win32_open_a,
- _win32_create_temp_a,
- _win32_rename_temp_a,
- _win32_remove_a
-};
-// 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 < -1) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
- }
-
- return _zip_source_win32_handle_or_name(fname, INVALID_HANDLE_VALUE, start, length, 1, NULL, &win32_ops_a, error);
-}
-
-
-static void *
-_win32_strdup_a(const void *str) {
- return strdup((const char *)str);
-}
-
-
-static HANDLE
-_win32_open_a(_zip_source_win32_read_file_t *ctx) {
- return CreateFileA(ctx->fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-}
-
-
-static HANDLE
-_win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa) {
- size_t len;
-
- len = strlen((const char *)ctx->fname) + 10;
- if (*temp == NULL) {
- if ((*temp = malloc(sizeof(char) * len)) == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
- return INVALID_HANDLE_VALUE;
- }
- }
- if (sprintf((char *)*temp, "%s.%08x", (const char *)ctx->fname, value) != len - 1) {
- return INVALID_HANDLE_VALUE;
- }
-
- return CreateFileA((const char *)*temp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY, NULL);
-}
-
-
-static int
-_win32_rename_temp_a(_zip_source_win32_read_file_t *ctx) {
- if (!MoveFileExA(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING))
- return -1;
- return 0;
-}
-
-
-static int
-_win32_remove_a(const void *fname) {
- DeleteFileA((const char *)fname);
- return 0;
-}
diff --git a/src/Common/libzip/zip_source_win32handle.c b/src/Common/libzip/zip_source_win32handle.c
deleted file mode 100644
index 3a2f52e1..00000000
--- a/src/Common/libzip/zip_source_win32handle.c
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- zip_source_win32file.c -- create data source from HANDLE (Win32)
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
-
- This file is part of libzip, a library to manipulate ZIP archives.
- The authors can be contacted at <libzip@nih.at>
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- 3. The names of the authors may not be used to endorse or promote
- products derived from this software without specific prior
- written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- IN CONTRACT, STRICT LIABILITY, OR TORT (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 <aclapi.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wchar.h>
-
-#include "zipint.h"
-#include "zipwin32.h"
-
-static zip_int64_t _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd);
-static int _win32_create_temp_file(_zip_source_win32_read_file_t *ctx);
-static int _zip_filetime_to_time_t(FILETIME ft, time_t *t);
-static int _zip_seek_win32_u(void *h, zip_uint64_t offset, int whence, zip_error_t *error);
-static int _zip_seek_win32(void *h, zip_int64_t offset, int whence, zip_error_t *error);
-static int _zip_win32_error_to_errno(unsigned long win32err);
-static int _zip_stat_win32(void *h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx);
-
-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 < -1) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
- }
-
- return _zip_source_win32_handle_or_name(NULL, h, start, length, 1, NULL, NULL, error);
-}
-
-
-zip_source_t *
-_zip_source_win32_handle_or_name(const void *fname, HANDLE h, zip_uint64_t start, zip_int64_t len, int closep, const zip_stat_t *st, _zip_source_win32_file_ops_t *ops, zip_error_t *error) {
- _zip_source_win32_read_file_t *ctx;
- zip_source_t *zs;
-
- if (h == INVALID_HANDLE_VALUE && fname == NULL) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
- }
-
- if ((ctx = (_zip_source_win32_read_file_t *)malloc(sizeof(_zip_source_win32_read_file_t))) == NULL) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- return NULL;
- }
-
- ctx->fname = NULL;
- if (fname) {
- if ((ctx->fname = ops->op_strdup(fname)) == NULL) {
- zip_error_set(error, ZIP_ER_MEMORY, 0);
- free(ctx);
- return NULL;
- }
- }
-
- ctx->ops = ops;
- ctx->h = h;
- ctx->start = start;
- ctx->end = (len < 0 ? 0 : start + (zip_uint64_t)len);
- ctx->closep = ctx->fname ? 1 : closep;
- if (st) {
- memcpy(&ctx->st, st, sizeof(ctx->st));
- ctx->st.name = NULL;
- ctx->st.valid &= ~ZIP_STAT_NAME;
- }
- else {
- zip_stat_init(&ctx->st);
- }
-
- ctx->tmpname = NULL;
- ctx->hout = INVALID_HANDLE_VALUE;
-
- zip_error_init(&ctx->error);
-
- ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1);
- if (ctx->fname) {
- HANDLE th;
-
- th = ops->op_open(ctx);
- if (th == INVALID_HANDLE_VALUE || GetFileType(th) == FILE_TYPE_DISK) {
- ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE;
- }
- if (th != INVALID_HANDLE_VALUE) {
- CloseHandle(th);
- }
- }
- else if (GetFileType(ctx->h) == FILE_TYPE_DISK) {
- ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE;
- }
-
- if ((zs = zip_source_function_create(_win32_read_file, ctx, error)) == NULL) {
- free(ctx->fname);
- free(ctx);
- return NULL;
- }
-
- return zs;
-}
-
-
-static zip_int64_t
-_win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
- _zip_source_win32_read_file_t *ctx;
- char *buf;
- zip_uint64_t n;
- DWORD i;
-
- ctx = (_zip_source_win32_read_file_t *)state;
- buf = (char *)data;
-
- switch (cmd) {
- case ZIP_SOURCE_BEGIN_WRITE:
- if (ctx->fname == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
- return -1;
- }
- return _win32_create_temp_file(ctx);
-
- case ZIP_SOURCE_COMMIT_WRITE: {
- if (!CloseHandle(ctx->hout)) {
- ctx->hout = INVALID_HANDLE_VALUE;
- zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError()));
- }
- ctx->hout = INVALID_HANDLE_VALUE;
- if (ctx->ops->op_rename_temp(ctx) < 0) {
- zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError()));
- return -1;
- }
- free(ctx->tmpname);
- ctx->tmpname = NULL;
- return 0;
- }
-
- case ZIP_SOURCE_CLOSE:
- if (ctx->fname) {
- CloseHandle(ctx->h);
- ctx->h = INVALID_HANDLE_VALUE;
- }
- return 0;
-
- case ZIP_SOURCE_ERROR:
- return zip_error_to_data(&ctx->error, data, len);
-
- case ZIP_SOURCE_FREE:
- free(ctx->fname);
- free(ctx->tmpname);
- if (ctx->closep && ctx->h != INVALID_HANDLE_VALUE)
- CloseHandle(ctx->h);
- free(ctx);
- return 0;
-
- case ZIP_SOURCE_OPEN:
- if (ctx->fname) {
- if ((ctx->h = ctx->ops->op_open(ctx)) == INVALID_HANDLE_VALUE) {
- zip_error_set(&ctx->error, ZIP_ER_OPEN, _zip_win32_error_to_errno(GetLastError()));
- return -1;
- }
- }
-
- if (ctx->closep && ctx->start > 0) {
- if (_zip_seek_win32_u(ctx->h, ctx->start, SEEK_SET, &ctx->error) < 0) {
- return -1;
- }
- }
- ctx->current = ctx->start;
- return 0;
-
- case ZIP_SOURCE_READ:
- if (ctx->end > 0) {
- n = ctx->end - ctx->current;
- if (n > len) {
- n = len;
- }
- }
- else {
- n = len;
- }
-
- if (n > SIZE_MAX)
- n = SIZE_MAX;
-
- if (!ctx->closep) {
- if (_zip_seek_win32_u(ctx->h, ctx->current, SEEK_SET, &ctx->error) < 0) {
- return -1;
- }
- }
-
- if (!ReadFile(ctx->h, buf, (DWORD)n, &i, NULL)) {
- zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
- return -1;
- }
- ctx->current += i;
-
- return (zip_int64_t)i;
-
- case ZIP_SOURCE_REMOVE:
- if (ctx->ops->op_remove(ctx->fname) < 0) {
- zip_error_set(&ctx->error, ZIP_ER_REMOVE, _zip_win32_error_to_errno(GetLastError()));
- return -1;
- }
- return 0;
-
- case ZIP_SOURCE_ROLLBACK_WRITE:
- if (ctx->hout) {
- CloseHandle(ctx->hout);
- ctx->hout = INVALID_HANDLE_VALUE;
- }
- ctx->ops->op_remove(ctx->tmpname);
- free(ctx->tmpname);
- ctx->tmpname = NULL;
- return 0;
-
- case ZIP_SOURCE_SEEK: {
- zip_int64_t new_current;
- int need_seek;
- zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
-
- if (args == NULL)
- return -1;
-
- need_seek = ctx->closep;
-
- switch (args->whence) {
- case SEEK_SET:
- new_current = args->offset;
- break;
-
- case SEEK_END:
- if (ctx->end == 0) {
- LARGE_INTEGER zero;
- LARGE_INTEGER new_offset;
-
- if (_zip_seek_win32(ctx->h, args->offset, SEEK_END, &ctx->error) < 0) {
- return -1;
- }
- zero.QuadPart = 0;
- if (!SetFilePointerEx(ctx->h, zero, &new_offset, FILE_CURRENT)) {
- zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError()));
- return -1;
- }
- new_current = new_offset.QuadPart;
- need_seek = 0;
- }
- else {
- new_current = (zip_int64_t)ctx->end + args->offset;
- }
- break;
- case SEEK_CUR:
- new_current = (zip_int64_t)ctx->current + args->offset;
- break;
-
- default:
- zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
- return -1;
- }
-
- if (new_current < 0 || (zip_uint64_t)new_current < ctx->start || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end)) {
- zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
- return -1;
- }
-
- ctx->current = (zip_uint64_t)new_current;
-
- if (need_seek) {
- if (_zip_seek_win32_u(ctx->h, ctx->current, SEEK_SET, &ctx->error) < 0) {
- return -1;
- }
- }
- return 0;
- }
-
- case ZIP_SOURCE_SEEK_WRITE: {
- zip_source_args_seek_t *args;
-
- args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
- if (args == NULL) {
- return -1;
- }
-
- if (_zip_seek_win32(ctx->hout, args->offset, args->whence, &ctx->error) < 0) {
- return -1;
- }
- return 0;
- }
-
- case ZIP_SOURCE_STAT: {
- if (len < sizeof(ctx->st))
- return -1;
-
- if (ctx->st.valid != 0)
- memcpy(data, &ctx->st, sizeof(ctx->st));
- else {
- DWORD win32err;
- zip_stat_t *st;
- HANDLE h;
- int success;
-
- st = (zip_stat_t *)data;
-
- if (ctx->h != INVALID_HANDLE_VALUE) {
- h = ctx->h;
- }
- else {
- h = ctx->ops->op_open(ctx);
- if (h == INVALID_HANDLE_VALUE) {
- win32err = GetLastError();
- if (win32err == ERROR_FILE_NOT_FOUND || win32err == ERROR_PATH_NOT_FOUND) {
- zip_error_set(&ctx->error, ZIP_ER_READ, ENOENT);
- return -1;
- }
- }
- }
-
- success = _zip_stat_win32(h, st, ctx);
- win32err = GetLastError();
-
- /* We're done with the handle, so close it if we just opened it. */
- if (h != ctx->h) {
- CloseHandle(h);
- }
-
- if (success < 0) {
- /* TODO: Is this the correct error to return in all cases? */
- zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(win32err));
- return -1;
- }
- }
- return sizeof(ctx->st);
- }
-
- case ZIP_SOURCE_SUPPORTS:
- return ctx->supports;
-
- case ZIP_SOURCE_TELL:
- return (zip_int64_t)ctx->current;
-
- case ZIP_SOURCE_TELL_WRITE: {
- LARGE_INTEGER zero;
- LARGE_INTEGER offset;
-
- zero.QuadPart = 0;
- if (!SetFilePointerEx(ctx->hout, zero, &offset, FILE_CURRENT)) {
- zip_error_set(&ctx->error, ZIP_ER_TELL, _zip_win32_error_to_errno(GetLastError()));
- return -1;
- }
-
- return offset.QuadPart;
- }
-
- case ZIP_SOURCE_WRITE: {
- DWORD ret;
- if (!WriteFile(ctx->hout, 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;
- }
-
- default:
- zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
- return -1;
- }
-}
-
-
-static int
-_win32_create_temp_file(_zip_source_win32_read_file_t *ctx) {
- zip_uint32_t value;
- /*
- Windows has GetTempFileName(), but it closes the file after
- creation, leaving it open to a horrible race condition. So
- we reinvent the wheel.
- */
- int i;
- HANDLE th = INVALID_HANDLE_VALUE;
- void *temp = NULL;
- PSECURITY_DESCRIPTOR psd = NULL;
- PSECURITY_ATTRIBUTES psa = NULL;
- SECURITY_ATTRIBUTES sa;
- SECURITY_INFORMATION si;
- DWORD success;
- PACL dacl = NULL;
-
- /*
- Read the DACL from the original file, so we can copy it to the temp file.
- If there is no original file, or if we can't read the DACL, we'll use the
- default security descriptor.
- */
- if (ctx->h != INVALID_HANDLE_VALUE && GetFileType(ctx->h) == FILE_TYPE_DISK) {
- si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION;
- success = GetSecurityInfo(ctx->h, 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();
-#endif
-
- for (i = 0; i < 1024 && th == INVALID_HANDLE_VALUE; i++) {
- th = ctx->ops->op_create_temp(ctx, &temp, value + i, psa);
- if (th == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_EXISTS)
- break;
- }
-
- if (th == INVALID_HANDLE_VALUE) {
- free(temp);
- LocalFree(psd);
- zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, _zip_win32_error_to_errno(GetLastError()));
- return -1;
- }
-
- LocalFree(psd);
- ctx->hout = th;
- ctx->tmpname = temp;
-
- return 0;
-}
-
-
-static int
-_zip_seek_win32_u(HANDLE h, zip_uint64_t offset, int whence, zip_error_t *error) {
- if (offset > ZIP_INT64_MAX) {
- zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW);
- return -1;
- }
- return _zip_seek_win32(h, (zip_int64_t)offset, whence, error);
-}
-
-
-static int
-_zip_seek_win32(HANDLE h, zip_int64_t offset, int whence, zip_error_t *error) {
- 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(error, ZIP_ER_SEEK, EINVAL);
- return -1;
- }
-
- li.QuadPart = (LONGLONG)offset;
- if (!SetFilePointerEx(h, li, NULL, method)) {
- zip_error_set(error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError()));
- return -1;
- }
-
- return 0;
-}
-
-
-static 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:
- 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 0;
- }
-}
-
-
-static int
-_zip_stat_win32(HANDLE h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx) {
- FILETIME mtimeft;
- time_t mtime;
- LARGE_INTEGER size;
- int regularp;
-
- if (!GetFileTime(h, NULL, NULL, &mtimeft)) {
- zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
- return -1;
- }
- if (_zip_filetime_to_time_t(mtimeft, &mtime) < 0) {
- zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE);
- return -1;
- }
-
- regularp = 0;
- if (GetFileType(h) == FILE_TYPE_DISK) {
- regularp = 1;
- }
-
- if (!GetFileSizeEx(h, &size)) {
- zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError()));
- return -1;
- }
-
- zip_stat_init(st);
- st->mtime = mtime;
- st->valid |= ZIP_STAT_MTIME;
- if (ctx->end != 0) {
- st->size = ctx->end - ctx->start;
- st->valid |= ZIP_STAT_SIZE;
- }
- else if (regularp) {
- st->size = (zip_uint64_t)size.QuadPart;
- st->valid |= ZIP_STAT_SIZE;
- }
-
- return 0;
-}
-
-
-static int
-_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 -1;
-
- *t = temp;
- return 0;
-}
diff --git a/src/Common/libzip/zip_source_win32w.c b/src/Common/libzip/zip_source_win32w.c
deleted file mode 100644
index 4097214d..00000000
--- a/src/Common/libzip/zip_source_win32w.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- zip_source_win32w.c -- create data source from Windows file (UTF-16)
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
-
- This file is part of libzip, a library to manipulate ZIP archives.
- The authors can be contacted at <libzip@nih.at>
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- 3. The names of the authors may not be used to endorse or promote
- products derived from this software without specific prior
- written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- IN CONTRACT, STRICT LIABILITY, OR TORT (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 <windows.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "zipint.h"
-#include "zipwin32.h"
-
-static void *_win32_strdup_w(const void *str);
-static HANDLE _win32_open_w(_zip_source_win32_read_file_t *ctx);
-static HANDLE _win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa);
-static int _win32_rename_temp_w(_zip_source_win32_read_file_t *ctx);
-static int _win32_remove_w(const void *fname);
-
-// clang-format off
-static _zip_source_win32_file_ops_t win32_ops_w = {
- _win32_strdup_w,
- _win32_open_w,
- _win32_create_temp_w,
- _win32_rename_temp_w,
- _win32_remove_w
-};
-// 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 < -1) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
- }
-
- return _zip_source_win32_handle_or_name(fname, INVALID_HANDLE_VALUE, start, length, 1, NULL, &win32_ops_w, error);
-}
-
-
-static void *
-_win32_strdup_w(const void *str) {
- return _wcsdup((const wchar_t *)str);
-}
-
-
-static HANDLE
-_win32_open_w(_zip_source_win32_read_file_t *ctx) {
-#ifdef MS_UWP
- CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
- extParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
- extParams.dwFileFlags = FILE_FLAG_RANDOM_ACCESS;
- extParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
- extParams.dwSize = sizeof(extParams);
- extParams.hTemplateFile = NULL;
- extParams.lpSecurityAttributes = NULL;
-
- return CreateFile2(ctx->fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, &extParams);
-#else
- return CreateFileW(ctx->fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-#endif
-}
-
-
-static HANDLE
-_win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa) {
- size_t len;
-
- len = wcslen((const wchar_t *)ctx->fname) + 10;
- if (*temp == NULL) {
- if ((*temp = malloc(sizeof(wchar_t) * len)) == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
- return INVALID_HANDLE_VALUE;
- }
- }
- if (_snwprintf((wchar_t *)*temp, len, L"%s.%08x", (const wchar_t *)ctx->fname, value) != len - 1) {
- return INVALID_HANDLE_VALUE;
- }
-
-#ifdef MS_UWP
- CREATEFILE2_EXTENDED_PARAMETERS extParams = {0};
- extParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY;
- extParams.dwFileFlags = FILE_FLAG_RANDOM_ACCESS;
- extParams.dwSecurityQosFlags = SECURITY_ANONYMOUS;
- extParams.dwSize = sizeof(extParams);
- extParams.hTemplateFile = NULL;
- extParams.lpSecurityAttributes = NULL;
-
- return CreateFile2((const wchar_t *)*temp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, CREATE_NEW, &extParams);
-#else
- return CreateFileW((const wchar_t *)*temp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY, NULL);
-#endif
-}
-
-
-static int
-_win32_rename_temp_w(_zip_source_win32_read_file_t *ctx) {
- if (!MoveFileExW(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING))
- return -1;
- return 0;
-}
-
-
-static int
-_win32_remove_w(const void *fname) {
- DeleteFileW((const wchar_t *)fname);
- return 0;
-}
diff --git a/src/Common/libzip/zip_source_window.c b/src/Common/libzip/zip_source_window.c
index d9e90bff..524e27c8 100644
--- a/src/Common/libzip/zip_source_window.c
+++ b/src/Common/libzip/zip_source_window.c
@@ -1,9 +1,9 @@
/*
zip_source_window.c -- return part of lower source
- Copyright (C) 2012-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,6 +40,7 @@
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;
@@ -48,7 +49,8 @@ struct window {
zip_uint64_t offset; /* offset in src for next read */
zip_stat_t stat;
- zip_int8_t compression_flags;
+ zip_uint64_t stat_invalid;
+ zip_file_attributes_t attributes;
zip_error_t error;
zip_int64_t supports;
bool needs_seek;
@@ -57,44 +59,68 @@ struct window {
static zip_int64_t window_read(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t);
-zip_source_t *
-zip_source_window(zip_t *za, zip_source_t *src, zip_uint64_t start, zip_uint64_t len) {
- return _zip_source_window_new(src, start, len, NULL, 0, NULL, 0, &za->error);
+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_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) {
+_zip_source_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 || start + length < start || (source_archive == NULL && source_index != 0)) {
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
+ 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;
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
}
ctx->start = start;
- ctx->end = start + length;
+ 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->compression_flags = compression_flags;
+ 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_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1));
+ 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;
- }
+ if (_zip_stat_merge(&ctx->stat, st, error) < 0) {
+ free(ctx);
+ return NULL;
+ }
}
-
- return zip_source_layered_create(src, window_read, ctx, error);
+
+ window_source = zip_source_layered_create(src, window_read, ctx, error);
+ if (window_source != NULL && !take_ownership) {
+ zip_source_keep(src);
+ }
+ return window_source;
}
@@ -111,7 +137,7 @@ _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);
+ zip_error_set(&src->error, ZIP_ER_ZIPCLOSED, 0);
}
}
@@ -126,123 +152,171 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou
switch (cmd) {
case ZIP_SOURCE_CLOSE:
- return 0;
+ return 0;
case ZIP_SOURCE_ERROR:
- return zip_error_to_data(&ctx->error, data, len);
+ return zip_error_to_data(&ctx->error, data, len);
case ZIP_SOURCE_FREE:
- free(ctx);
- return 0;
+ 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, 0);
- 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;
+ 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 (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->offset < ctx->end) {
- zip_error_set(&ctx->error, ZIP_ER_EOF, 0);
- return -1;
- }
- }
- return ret;
+ 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 = 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;
+ 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;
+ zip_stat_t *st;
+
+ st = (zip_stat_t *)data;
- st = (zip_stat_t *)data;
+ if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) {
+ return -1;
+ }
- if (_zip_stat_merge(st, &ctx->stat, &ctx->error) < 0) {
- return -1;
- }
- return 0;
+ 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_COMPRESSION_FLAGS:
- return ctx->compression_flags;
+ 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;
+ return ctx->supports;
case ZIP_SOURCE_TELL:
- return (zip_int64_t)(ctx->offset - ctx->start);
+ return (zip_int64_t)(ctx->offset - ctx->start);
default:
- zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
- return -1;
+ return zip_source_pass_to_lower_layer(src, data, len, cmd);
}
}
@@ -252,11 +326,11 @@ _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;
- }
+ if (za->open_source[i] == src) {
+ za->open_source[i] = za->open_source[za->nopen_source - 1];
+ za->nopen_source--;
+ break;
+ }
}
}
@@ -266,15 +340,15 @@ _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;
+ 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;
diff --git a/src/Common/libzip/zip_source_winzip_aes_decode.c b/src/Common/libzip/zip_source_winzip_aes_decode.c
new file mode 100644
index 00000000..ee53fb41
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+#include <string.h>
+
+#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/src/Common/libzip/zip_source_winzip_aes_encode.c b/src/Common/libzip/zip_source_winzip_aes_encode.c
new file mode 100644
index 00000000..87e2865a
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+#include <string.h>
+
+#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/src/Common/libzip/zip_source_write.c b/src/Common/libzip/zip_source_write.c
index 9f494e09..24dde9b2 100644
--- a/src/Common/libzip/zip_source_write.c
+++ b/src/Common/libzip/zip_source_write.c
@@ -1,9 +1,9 @@
/*
zip_source_write.c -- start a new file for writing
- Copyright (C) 2014-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -38,8 +38,8 @@
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;
+ 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/src/Common/libzip/zip_source_zip.c b/src/Common/libzip/zip_source_zip.c
index 3fd90abe..faabf0d2 100644
--- a/src/Common/libzip/zip_source_zip.c
+++ b/src/Common/libzip/zip_source_zip.c
@@ -1,9 +1,9 @@
/*
zip_source_zip.c -- create data source from zip file
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -33,25 +33,31 @@
#include <stdlib.h>
-#include <string.h>
+#define _ZIP_COMPILING_DEPRECATED
#include "zipint.h"
-
-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) {
+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(&za->error, ZIP_ER_INVAL, 0);
- return NULL;
+ 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;
}
- if (len == -1)
- len = 0;
+ return zip_source_zip_file_create(srcza, srcidx, flags, start, len, NULL, error);
+}
- if (start == 0 && len == 0)
- flags |= ZIP_FL_COMPRESSED;
- else
- flags &= ~ZIP_FL_COMPRESSED;
- return _zip_source_zip_new(za, srcza, srcidx, flags, start, (zip_uint64_t)len, NULL);
+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/src/Common/libzip/zip_source_zip_new.c b/src/Common/libzip/zip_source_zip_new.c
index ab785615..ecccdd68 100644
--- a/src/Common/libzip/zip_source_zip_new.c
+++ b/src/Common/libzip/zip_source_zip_new.c
@@ -1,9 +1,9 @@
/*
zip_source_zip_new.c -- prepare data structures for zip_fopen/zip_source_zip
- Copyright (C) 2012-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -36,140 +36,277 @@
#include "zipint.h"
+static void _zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de);
-zip_source_t *
-_zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password) {
+ZIP_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;
- struct zip_stat st;
- bool partial_data, needs_crc, needs_decrypt, needs_decompress;
+ 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 (za == NULL)
- return NULL;
+ if (srcza == NULL || srcidx >= srcza->nentry || len < -1) {
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return NULL;
+ }
- if (srcza == NULL || srcidx >= srcza->nentry) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return NULL;
+ if (flags & ZIP_FL_ENCRYPTED) {
+ flags |= ZIP_FL_COMPRESSED;
}
- if ((flags & ZIP_FL_UNCHANGED) == 0 && (ZIP_ENTRY_DATA_CHANGED(srcza->entry + srcidx) || srcza->entry[srcidx].deleted)) {
- zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
- return NULL;
+ 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;
+ }
}
- if (zip_stat_index(srcza, srcidx, flags | ZIP_FL_UNCHANGED, &st) < 0) {
- zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
- return NULL;
+ stat_flags = flags;
+ if (!changed_data) {
+ stat_flags |= ZIP_FL_UNCHANGED;
}
- if (flags & ZIP_FL_ENCRYPTED)
- flags |= ZIP_FL_COMPRESSED;
+ 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(&za->error, ZIP_ER_INVAL, 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 ((start > 0 || len > 0) && (start + len < start || start + len > st.size)) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return NULL;
+ 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 == 0) {
- len = st.size - start;
+ 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;
}
- partial_data = len < st.size;
- needs_decrypt = ((flags & ZIP_FL_ENCRYPTED) == 0) && (st.encryption_method != ZIP_EM_NONE);
- needs_decompress = ((flags & ZIP_FL_COMPRESSED) == 0) && (st.comp_method != ZIP_CM_STORE);
+ 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 || st.comp_method == ZIP_CM_STORE) && !partial_data;
+ needs_crc = ((flags & ZIP_FL_COMPRESSED) == 0 || !compressed) && !partial_data && (st.valid & ZIP_STAT_CRC) != 0;
if (needs_decrypt) {
- if (password == NULL) {
- password = za->default_password;
- }
- if (password == NULL) {
- zip_error_set(&za->error, ZIP_ER_NOPASSWD, 0);
- return NULL;
- }
+ if (password == NULL) {
+ password = srcza->default_password;
+ }
+ if (password == NULL) {
+ zip_error_set(error, ZIP_ER_NOPASSWD, 0);
+ return NULL;
+ }
}
- if (st.comp_size == 0) {
- return zip_source_buffer(za, NULL, 0, 0);
+ 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;
+ 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.size = len;
- st2.comp_size = len;
- st2.comp_method = ZIP_CM_STORE;
- st2.mtime = st.mtime;
- st2.valid = ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_MTIME;
+ 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(srcza->src, start, len, &st2, 0, srcza, srcidx, &za->error)) == NULL) {
- return NULL;
- }
+ 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 {
- zip_dirent_t *de;
-
- if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) {
- return NULL;
- }
- if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, (de->bitflags >> 1) & 3, srcza, srcidx, &za->error)) == NULL) {
- return NULL;
- }
+ /* 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;
+ 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;
+ zip_encryption_implementation enc_impl;
- if ((enc_impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
- return NULL;
- }
+ 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(za, src, st.encryption_method, 0, password);
- zip_source_free(src);
- if (s2 == NULL) {
- return NULL;
- }
- src = s2;
+ 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(za, src, st.comp_method);
- zip_source_free(src);
- if (s2 == NULL) {
- return NULL;
- }
- src = s2;
+ 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(za, src, 1);
- zip_source_free(src);
- if (s2 == NULL) {
- return NULL;
- }
- src = s2;
+ 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)) {
- s2 = zip_source_window(za, src, start, len);
- zip_source_free(src);
- if (s2 == NULL) {
- return NULL;
- }
- src = s2;
+ 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/src/Common/libzip/zip_stat.c b/src/Common/libzip/zip_stat.c
index 237d985d..51d8026d 100644
--- a/src/Common/libzip/zip_stat.c
+++ b/src/Common/libzip/zip_stat.c
@@ -1,9 +1,9 @@
/*
zip_stat.c -- get information about file by name
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,7 +40,7 @@ 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 -1;
return zip_stat_index(za, (zip_uint64_t)idx, flags, st);
}
diff --git a/src/Common/libzip/zip_stat_index.c b/src/Common/libzip/zip_stat_index.c
index d19e76a3..da33c09e 100644
--- a/src/Common/libzip/zip_stat_index.c
+++ b/src/Common/libzip/zip_stat_index.c
@@ -1,9 +1,9 @@
/*
zip_stat_index.c -- get information about file by index
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -39,30 +39,68 @@ 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 ((de = _zip_get_dirent(za, index, flags, NULL)) == NULL) {
+ return -1;
+ }
- if ((name = zip_get_name(za, index, flags)) == 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(za->entry[index].source, st) < 0) {
- zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
- return -1;
- }
+
+ 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;
+ 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;
diff --git a/src/Common/libzip/zip_stat_init.c b/src/Common/libzip/zip_stat_init.c
index 46fa404c..9c6088a7 100644
--- a/src/Common/libzip/zip_stat_init.c
+++ b/src/Common/libzip/zip_stat_init.c
@@ -1,9 +1,9 @@
/*
zip_stat_init.c -- initialize struct zip_stat.
- Copyright (C) 2006-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -54,28 +54,28 @@ 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;
+ dst->index = src->index;
}
if (src->valid & ZIP_STAT_SIZE) {
- dst->size = src->size;
+ dst->size = src->size;
}
if (src->valid & ZIP_STAT_COMP_SIZE) {
- dst->comp_size = src->comp_size;
+ dst->comp_size = src->comp_size;
}
if (src->valid & ZIP_STAT_MTIME) {
- dst->mtime = src->mtime;
+ dst->mtime = src->mtime;
}
if (src->valid & ZIP_STAT_CRC) {
- dst->crc = src->crc;
+ dst->crc = src->crc;
}
if (src->valid & ZIP_STAT_COMP_METHOD) {
- dst->comp_method = src->comp_method;
+ dst->comp_method = src->comp_method;
}
if (src->valid & ZIP_STAT_ENCRYPTION_METHOD) {
- dst->encryption_method = src->encryption_method;
+ dst->encryption_method = src->encryption_method;
}
if (src->valid & ZIP_STAT_FLAGS) {
- dst->flags = src->flags;
+ dst->flags = src->flags;
}
dst->valid |= src->valid;
diff --git a/src/Common/libzip/zip_strerror.c b/src/Common/libzip/zip_strerror.c
index eb94198d..7d827931 100644
--- a/src/Common/libzip/zip_strerror.c
+++ b/src/Common/libzip/zip_strerror.c
@@ -1,9 +1,9 @@
/*
zip_sterror.c -- get string representation of zip error
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/src/Common/libzip/zip_string.c b/src/Common/libzip/zip_string.c
index 7e16a728..1c964491 100644
--- a/src/Common/libzip/zip_string.c
+++ b/src/Common/libzip/zip_string.c
@@ -1,9 +1,9 @@
/*
zip_string.c -- string handling (with encoding)
- Copyright (C) 2012-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -34,10 +34,10 @@
#include <stdlib.h>
#include <string.h>
+#include <zlib.h>
#include "zipint.h"
-
zip_uint32_t
_zip_string_crc32(const zip_string_t *s) {
zip_uint32_t crc;
@@ -45,7 +45,7 @@ _zip_string_crc32(const zip_string_t *s) {
crc = (zip_uint32_t)crc32(0L, Z_NULL, 0);
if (s != NULL)
- crc = (zip_uint32_t)crc32(crc, s->raw, s->length);
+ crc = (zip_uint32_t)crc32(crc, s->raw, s->length);
return crc;
}
@@ -54,10 +54,10 @@ _zip_string_crc32(const zip_string_t *s) {
int
_zip_string_equal(const zip_string_t *a, const zip_string_t *b) {
if (a == NULL || b == NULL)
- return a == b;
+ return a == b;
if (a->length != b->length)
- return 0;
+ return 0;
/* TODO: encoding */
@@ -68,7 +68,7 @@ _zip_string_equal(const zip_string_t *a, const zip_string_t *b) {
void
_zip_string_free(zip_string_t *s) {
if (s == NULL)
- return;
+ return;
free(s->raw);
free(s->converted);
@@ -81,29 +81,29 @@ _zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip
static const zip_uint8_t empty[1] = "";
if (string == NULL) {
- if (lenp)
- *lenp = 0;
- return empty;
+ 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;
- }
+ /* 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;
+ *lenp = string->length;
return string->raw;
}
@@ -111,7 +111,7 @@ _zip_string_get(zip_string_t *string, zip_uint32_t *lenp, zip_flags_t flags, zip
zip_uint16_t
_zip_string_length(const zip_string_t *s) {
if (s == NULL)
- return 0;
+ return 0;
return s->length;
}
@@ -123,34 +123,34 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags,
zip_encoding_type_t expected_encoding;
if (length == 0)
- return NULL;
+ return NULL;
switch (flags & ZIP_FL_ENCODING_ALL) {
case ZIP_FL_ENC_GUESS:
- expected_encoding = ZIP_ENCODING_UNKNOWN;
- break;
+ expected_encoding = ZIP_ENCODING_UNKNOWN;
+ break;
case ZIP_FL_ENC_UTF_8:
- expected_encoding = ZIP_ENCODING_UTF8_KNOWN;
- break;
+ expected_encoding = ZIP_ENCODING_UTF8_KNOWN;
+ break;
case ZIP_FL_ENC_CP437:
- expected_encoding = ZIP_ENCODING_CP437;
- break;
+ expected_encoding = ZIP_ENCODING_CP437;
+ break;
default:
- zip_error_set(error, ZIP_ER_INVAL, 0);
- return NULL;
+ 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;
+ 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;
+ if ((s->raw = (zip_uint8_t *)malloc((size_t)length + 1)) == NULL) {
+ free(s);
+ return NULL;
}
- memcpy(s->raw, raw, length);
+ (void)memcpy_s(s->raw, length + 1, raw, length);
s->raw[length] = '\0';
s->length = length;
s->encoding = ZIP_ENCODING_UNKNOWN;
@@ -158,11 +158,11 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags,
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;
- }
+ 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;
@@ -172,7 +172,7 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags,
int
_zip_string_write(zip_t *za, const zip_string_t *s) {
if (s == NULL)
- return 0;
+ return 0;
return _zip_write(za, s->raw, s->length);
}
diff --git a/src/Common/libzip/zip_unchange.c b/src/Common/libzip/zip_unchange.c
index 8285707b..d69a3dfe 100644
--- a/src/Common/libzip/zip_unchange.c
+++ b/src/Common/libzip/zip_unchange.c
@@ -1,9 +1,9 @@
/*
zip_unchange.c -- undo changes to file in zip archive
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -46,42 +46,47 @@ zip_unchange(zip_t *za, zip_uint64_t idx) {
int
_zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates) {
zip_int64_t i;
- const char *orig_name, *changed_name;
+ bool renamed;
if (idx >= za->nentry) {
- zip_error_set(&za->error, ZIP_ER_INVAL, 0);
- return -1;
+ zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+ return -1;
}
- if (!allow_duplicates && za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME)) {
- 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;
- }
- }
- else {
- orig_name = NULL;
- }
-
- 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 (_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;
- }
+ 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);
diff --git a/src/Common/libzip/zip_unchange_all.c b/src/Common/libzip/zip_unchange_all.c
index 6a43358c..34f3702e 100644
--- a/src/Common/libzip/zip_unchange_all.c
+++ b/src/Common/libzip/zip_unchange_all.c
@@ -1,9 +1,9 @@
/*
zip_unchange.c -- undo changes to all files in zip archive
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -32,8 +32,6 @@
*/
-#include <stdlib.h>
-
#include "zipint.h"
@@ -43,12 +41,12 @@ zip_unchange_all(zip_t *za) {
zip_uint64_t i;
if (!_zip_hash_revert(za->names, &za->error)) {
- return -1;
+ return -1;
}
ret = 0;
for (i = 0; i < za->nentry; i++)
- ret |= _zip_unchange(za, i, 1);
+ ret |= _zip_unchange(za, i, 1);
ret |= zip_unchange_archive(za);
diff --git a/src/Common/libzip/zip_unchange_archive.c b/src/Common/libzip/zip_unchange_archive.c
index 404f1ed8..56a8e31f 100644
--- a/src/Common/libzip/zip_unchange_archive.c
+++ b/src/Common/libzip/zip_unchange_archive.c
@@ -1,9 +1,9 @@
/*
zip_unchange_archive.c -- undo global changes to ZIP archive
- Copyright (C) 2006-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -40,9 +40,9 @@
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;
+ _zip_string_free(za->comment_changes);
+ za->comment_changes = NULL;
+ za->comment_changed = 0;
}
za->ch_flags = za->flags;
diff --git a/src/Common/libzip/zip_unchange_data.c b/src/Common/libzip/zip_unchange_data.c
index f1df2bde..6bdecd18 100644
--- a/src/Common/libzip/zip_unchange_data.c
+++ b/src/Common/libzip/zip_unchange_data.c
@@ -1,9 +1,9 @@
/*
zip_unchange_data.c -- undo helper function
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -37,16 +37,16 @@
void
_zip_unchange_data(zip_entry_t *ze) {
if (ze->source) {
- zip_source_free(ze->source);
- ze->source = NULL;
+ 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->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/src/Common/libzip/zip_utf-8.c b/src/Common/libzip/zip_utf-8.c
index 684eba5e..678912f6 100644
--- a/src/Common/libzip/zip_utf-8.c
+++ b/src/Common/libzip/zip_utf-8.c
@@ -1,9 +1,9 @@
/*
zip_utf-8.c -- UTF-8 support functions for libzip
- Copyright (C) 2011-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -103,54 +103,54 @@ _zip_guess_encoding(zip_string_t *str, zip_encoding_type_t expected_encoding) {
zip_uint32_t i, j, ulen;
if (str == NULL)
- return ZIP_ENCODING_ASCII;
+ return ZIP_ENCODING_ASCII;
name = str->raw;
if (str->encoding != ZIP_ENCODING_UNKNOWN)
- enc = str->encoding;
+ 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;
- }
+ 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 == 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;
+ if (expected_encoding != enc && enc != ZIP_ENCODING_ASCII)
+ return ZIP_ENCODING_ERROR;
}
return enc;
@@ -160,11 +160,11 @@ done:
static zip_uint32_t
_zip_unicode_to_utf8_len(zip_uint32_t codepoint) {
if (codepoint < 0x0080)
- return 1;
+ return 1;
if (codepoint < 0x0800)
- return 2;
+ return 2;
if (codepoint < 0x10000)
- return 3;
+ return 3;
return 4;
}
@@ -172,19 +172,19 @@ _zip_unicode_to_utf8_len(zip_uint32_t codepoint) {
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;
+ 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;
+ 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_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));
@@ -201,26 +201,26 @@ _zip_cp437_to_utf8(const zip_uint8_t *const _cp437buf, zip_uint32_t len, zip_uin
zip_uint32_t buflen, i, offset;
if (len == 0) {
- if (utf8_lenp)
- *utf8_lenp = 0;
- return NULL;
+ 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]]);
+ 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;
+ 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);
+ offset += _zip_unicode_to_utf8(_cp437_to_unicode[cp437buf[i]], utf8buf + offset);
utf8buf[buflen - 1] = 0;
if (utf8_lenp)
- *utf8_lenp = buflen - 1;
+ *utf8_lenp = buflen - 1;
return utf8buf;
}
diff --git a/src/Common/libzip/zip_winzip_aes.c b/src/Common/libzip/zip_winzip_aes.c
new file mode 100644
index 00000000..ce269036
--- /dev/null
+++ b/src/Common/libzip/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 <info@libzip.org>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (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 <stdlib.h>
+#include <string.h>
+
+
+#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/src/Common/libzip/zipconf.h b/src/Common/libzip/zipconf.h
index e4224da2..472e06c1 100644
--- a/src/Common/libzip/zipconf.h
+++ b/src/Common/libzip/zipconf.h
@@ -1,40 +1,52 @@
-/*
- This file was generated automatically by C:\dev\prj\Github\VeraCrypt\src\Common\libzip\make_zip_err_str.sh
- from C:\dev\libraries\libzip\build\config.h; make changes there.
- */
-
#ifndef _HAD_ZIPCONF_H
#define _HAD_ZIPCONF_H
-extern const char * const _zip_err_str[];
-
-extern const int _zip_nerr_str;
-
-#define N ZIP_ET_NONE
-#define S ZIP_ET_SYS
-#define Z ZIP_ET_ZLIB
-
-extern const int _zip_err_type[];
-
+/*
+ zipconf.h -- platform specific include file
-typedef signed char zip_int8_t;
-typedef unsigned char zip_uint8_t;
-typedef signed short zip_int16_t;
-typedef unsigned short zip_uint16_t;
-typedef signed int zip_int32_t;
-typedef unsigned int zip_uint32_t;
-typedef signed long long zip_int64_t;
-typedef unsigned long long zip_uint64_t;
+ This file was generated automatically by CMake
+ based on ../cmake-zipconf.h.in.
+ */
-#define ZIP_INT8_MIN -0x80
+#define LIBZIP_VERSION "1.10.1"
+#define LIBZIP_VERSION_MAJOR 1
+#define LIBZIP_VERSION_MINOR 10
+#define LIBZIP_VERSION_MICRO 1
+
+/* #undef ZIP_STATIC */
+
+#define _Nullable
+#define _Nonnull
+
+#if !defined(__STDC_FORMAT_MACROS)
+#define __STDC_FORMAT_MACROS 1
+#endif
+#if defined(_MSC_VER) && _MSC_VER < 1700
+#include <stdint.h>
+#define PRIu32 "lu"
+#define PRIu64 "llu"
+#else
+#include <inttypes.h>
+#endif
+
+typedef int8_t zip_int8_t;
+typedef uint8_t zip_uint8_t;
+typedef int16_t zip_int16_t;
+typedef uint16_t zip_uint16_t;
+typedef int32_t zip_int32_t;
+typedef uint32_t zip_uint32_t;
+typedef int64_t zip_int64_t;
+typedef 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 -0x8000
+#define ZIP_INT16_MIN (-ZIP_INT16_MAX-1)
#define ZIP_INT16_MAX 0x7fff
#define ZIP_UINT16_MAX 0xffff
-#define ZIP_INT32_MIN -0x80000000L
+#define ZIP_INT32_MIN (-ZIP_INT32_MAX-1L)
#define ZIP_INT32_MAX 0x7fffffffL
#define ZIP_UINT32_MAX 0xffffffffLU
@@ -43,4 +55,3 @@ typedef unsigned long long zip_uint64_t;
#define ZIP_UINT64_MAX 0xffffffffffffffffULL
#endif /* zipconf.h */
-
diff --git a/src/Common/libzip/zipint.h b/src/Common/libzip/zipint.h
index 093a1b2d..4887b6c5 100644
--- a/src/Common/libzip/zipint.h
+++ b/src/Common/libzip/zipint.h
@@ -3,10 +3,10 @@
/*
zipint.h -- internal declarations.
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
+ 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 <libzip@nih.at>
+ The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -34,9 +34,7 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
#include "compat.h"
@@ -44,9 +42,9 @@
#include <stdlib.h>
#endif
-#include <zlib.h>
-
-#ifndef _ZIP_COMPILING_DEPRECATED
+#ifdef _ZIP_COMPILING_DEPRECATED
+#define ZIP_DEPRECATED(x)
+#else
#define ZIP_DISABLE_DEPRECATED
#endif
@@ -69,6 +67,15 @@
#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 */
@@ -77,7 +84,6 @@
#define WINZIP_AES_MAX_HEADER_LENGTH (16 + WINZIP_AES_PASSWORD_VERIFY_LENGTH)
#define AES_BLOCK_SIZE 16
#define HMAC_LENGTH 10
-#define SHA1_LENGTH 20
#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)
@@ -95,6 +101,7 @@
/* 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))
@@ -111,27 +118,32 @@ typedef zip_source_t *(*zip_encryption_implementation)(zip_t *, zip_source_t *,
zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t method, int operation);
-// clang-format off
+/* clang-format off */
enum zip_compression_status {
ZIP_COMPRESSION_OK,
ZIP_COMPRESSION_END,
ZIP_COMPRESSION_ERROR,
ZIP_COMPRESSION_NEED_DATA
};
-// clang-format on
+/* 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, int compression_flags, zip_error_t *error);
+ 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 */
- int (*compression_flags)(void *ctx);
+ 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);
+ bool (*start)(void *ctx, zip_stat_t *st, zip_file_attributes_t *attributes);
/* stop processing */
bool (*end)(void *ctx);
@@ -150,8 +162,12 @@ 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;
-bool zip_compression_method_supported(zip_int32_t method, bool compress);
+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. */
@@ -161,24 +177,65 @@ const zip_uint8_t *zip_get_extra_field_by_id(zip_t *, int, int, zip_uint16_t, in
user-supplied compression/encryption implementation is finished.
Thus we will keep it private for now. */
-typedef zip_int64_t (*zip_source_layered_callback)(zip_source_t *, void *, void *, zip_uint64_t, enum zip_source_cmd);
-zip_source_t *zip_source_compress(zip_t *za, zip_source_t *src, zip_int32_t cm, int compression_flags);
-zip_source_t *zip_source_crc(zip_t *, zip_source_t *, int);
+zip_source_t *zip_source_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_layered(zip_t *, zip_source_t *, zip_source_layered_callback, void *);
-zip_source_t *zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error);
-zip_source_t *zip_source_pkware(zip_t *, zip_source_t *, zip_uint16_t, int, const char *);
+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);
-zip_source_t *zip_source_window(zip_t *, zip_source_t *, zip_uint64_t, zip_uint64_t);
+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 */
@@ -248,14 +305,14 @@ struct zip {
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_t *za; /* zip archive containing this file */
zip_error_t error; /* error information */
- bool eof;
zip_source_t *src; /* data source */
};
@@ -294,7 +351,7 @@ struct zip_dirent {
zip_uint32_t ext_attrib; /* (c) external file attributes */
zip_uint64_t offset; /* (c) offset of local header */
- zip_uint16_t compression_level; /* level of compression to use (never valid in orig) */
+ zip_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 */
};
@@ -331,8 +388,8 @@ 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;
+ zip_source_callback f;
+ zip_source_layered_callback l;
} cb;
void *ud;
zip_error_t error;
@@ -342,8 +399,9 @@ struct zip_source {
bool source_closed; /* set if source archive is closed */
zip_t *source_archive; /* zip archive we're reading from, NULL if not from archive */
unsigned int refcount;
- bool eof; /* EOF reached */
- bool had_read_error; /* a previous ZIP_SOURCE_READ reported an error */
+ 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)
@@ -378,13 +436,13 @@ struct zip_string {
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))
+#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)
+#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
@@ -403,7 +461,7 @@ struct zip_buffer {
struct zip_filelist {
zip_uint64_t idx;
- /* TODO const char *name; */
+ const char *name;
};
typedef struct zip_filelist zip_filelist_t;
@@ -411,9 +469,10 @@ typedef struct zip_filelist zip_filelist_t;
struct _zip_winzip_aes;
typedef struct _zip_winzip_aes zip_winzip_aes_t;
-extern const char *const _zip_err_str[];
-extern const int _zip_nerr_str;
-extern const int _zip_err_type[];
+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))
@@ -423,6 +482,8 @@ extern const int _zip_err_type[];
#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
@@ -463,21 +524,25 @@ int _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length);
int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset);
zip_uint64_t _zip_buffer_size(zip_buffer_t *buffer);
-int _zip_cdir_compute_crc(zip_t *, uLong *);
void _zip_cdir_free(zip_cdir_t *);
bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error);
zip_cdir_t *_zip_cdir_new(zip_uint64_t, zip_error_t *);
zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors);
+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);
@@ -499,7 +564,6 @@ 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);
-void _zip_error_set_from_source(zip_error_t *, zip_source_t *);
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 *);
@@ -508,8 +572,6 @@ 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 *);
-int _zip_filerange_crc(zip_source_t *src, zip_uint64_t offset, zip_uint64_t length, uLong *crcp, zip_error_t *error);
-
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);
@@ -523,44 +585,46 @@ 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);
-zip_progress_t *_zip_progress_new(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud);
-void _zip_progress_start(zip_progress_t *progress);
-void _zip_progress_subrange(zip_progress_t *progress, double start, double end);
-void _zip_progress_update(zip_progress_t *progress, double value);
+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);
-ZIP_EXTERN bool zip_random(zip_uint8_t *buffer, zip_uint16_t length);
+/* 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 lenght, bool nulp, zip_error_t *error);
+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);
-zip_int8_t zip_source_get_compression_flags(zip_source_t *);
bool _zip_source_had_error(zip_source_t *);
void _zip_source_invalidate(zip_source_t *src);
zip_source_t *_zip_source_new(zip_error_t *error);
int _zip_source_set_source_archive(zip_source_t *, zip_t *);
-zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error);
-zip_source_t *_zip_source_zip_new(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *);
+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 *, const zip_string_t *);
-void _zip_string_free(zip_string_t *);
-zip_uint32_t _zip_string_crc32(const zip_string_t *);
-const zip_uint8_t *_zip_string_get(zip_string_t *, zip_uint32_t *, zip_flags_t, zip_error_t *);
-zip_uint16_t _zip_string_length(const zip_string_t *);
-zip_string_t *_zip_string_new(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_error_t *);
+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);
@@ -568,6 +632,12 @@ 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);
diff --git a/src/Common/libzip/zipwin32.h b/src/Common/libzip/zipwin32.h
deleted file mode 100644
index 7d3ac76c..00000000
--- a/src/Common/libzip/zipwin32.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef _HAD_ZIPWIN32_H
-#define _HAD_ZIPWIN32_H
-
-/*
- zipwin32.h -- internal declarations for Windows.
- Copyright (C) 1999-2018 Dieter Baron and Thomas Klausner
-
- This file is part of libzip, a library to manipulate ZIP archives.
- The authors can be contacted at <libzip@nih.at>
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
- 3. The names of the authors may not be used to endorse or promote
- products derived from this software without specific prior
- written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- IN CONTRACT, STRICT LIABILITY, OR TORT (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 <windows.h>
-
-/* context for Win32 source */
-
-struct _zip_source_win32_file_ops;
-
-struct _zip_source_win32_read_file {
- zip_error_t error; /* last error information */
- zip_int64_t supports;
-
- /* operations */
- struct _zip_source_win32_file_ops *ops;
-
- /* reading */
- void *fname; /* name of file to read from - ANSI (char *) or Unicode (wchar_t *) */
- void *h; /* HANDLE for file to read from */
- int closep; /* whether to close f on ZIP_CMD_FREE */
- struct zip_stat st; /* stat information passed in */
- zip_uint64_t start; /* start offset of data to read */
- zip_uint64_t end; /* end offset of data to read, 0 for up to EOF */
- zip_uint64_t current; /* current offset */
-
- /* writing */
- void *tmpname; /* name of temp file - ANSI (char *) or Unicode (wchar_t *) */
- void *hout; /* HANDLE for output file */
-};
-
-typedef struct _zip_source_win32_read_file _zip_source_win32_read_file_t;
-
-/* internal operations for Win32 source */
-
-struct _zip_source_win32_file_ops {
- void *(*op_strdup)(const void *);
- void *(*op_open)(_zip_source_win32_read_file_t *);
- void *(*op_create_temp)(_zip_source_win32_read_file_t *, void **, zip_uint32_t, PSECURITY_ATTRIBUTES);
- int (*op_rename_temp)(_zip_source_win32_read_file_t *);
- int (*op_remove)(const void *);
-};
-
-typedef struct _zip_source_win32_file_ops _zip_source_win32_file_ops_t;
-
-zip_source_t *_zip_source_win32_handle_or_name(const void *, void *, zip_uint64_t, zip_int64_t, int, const zip_stat_t *, _zip_source_win32_file_ops_t *, zip_error_t *);
-
-#endif /* zipwin32.h */