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.h74
-rw-r--r--src/Common/libzip/config.h78
-rw-r--r--src/Common/libzip/mkstemp.c153
-rw-r--r--src/Common/libzip/zip.h375
-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.c120
-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.c817
-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.c1027
-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.c145
-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.c27
-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.c874
-rw-r--r--src/Common/libzip/zip_pkware.c112
-rw-r--r--src/Common/libzip/zip_progress.c110
-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.c16
-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.c494
-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.c663
-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.c135
-rw-r--r--src/Common/libzip/zip_source_win32handle.c602
-rw-r--r--src/Common/libzip/zip_source_win32w.c159
-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.c79
-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.h172
-rw-r--r--src/Common/libzip/zipwin32.h85
154 files changed, 11379 insertions, 6485 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 e0a27beb..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-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
@@ -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>
@@ -87,9 +87,6 @@ typedef char bool;
#endif
#ifdef _WIN32
-#if defined(HAVE__CHMOD)
-#define chmod _chmod
-#endif
#if defined(HAVE__CLOSE)
#define close _close
#endif
@@ -103,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
@@ -138,6 +134,33 @@ typedef char bool;
#define ftello(s) ((long)ftell((s)))
#endif
+#ifdef HAVE_LOCALTIME_S
+#ifdef _WIN32
+/* Windows is incompatible to the C11 standard, hurray! */
+#define zip_localtime(t, tm) (localtime_s((tm), (t)) == 0 ? tm : NULL)
+#else
+#define zip_localtime localtime_s
+#endif
+#else
+#ifdef HAVE_LOCALTIME_R
+#define zip_localtime localtime_r
+#else
+#define zip_localtime(t, tm) (localtime(t))
+#endif
+#endif
+
+#ifndef HAVE_MEMCPY_S
+#define memcpy_s(dest, destsz, src, count) (memcpy((dest), (src), (count)) == NULL)
+#endif
+
+#ifndef HAVE_SNPRINTF_S
+#ifdef HAVE__SNPRINTF_S
+#define snprintf_s(buf, bufsz, fmt, ...) (_snprintf_s((buf), (bufsz), (bufsz), (fmt), __VA_ARGS__))
+#else
+#define snprintf_s snprintf
+#endif
+#endif
+
#if !defined(HAVE_STRCASECMP)
#if defined(HAVE__STRICMP)
#define strcasecmp _stricmp
@@ -146,6 +169,19 @@ typedef char bool;
#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
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 34b544ef..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-2020 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 */
@@ -135,12 +156,15 @@ extern "C" {
#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 */
@@ -161,9 +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 */
@@ -214,31 +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_ACCEPT_EMPTY /* whether empty files are valid archives */
+ 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) \
@@ -261,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 {
@@ -276,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
@@ -293,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) */
@@ -305,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;
@@ -316,138 +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 int (*zip_cancel_callback)(zip_t *, 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_dostime(zip_t *, zip_uint64_t, zip_uint16_t, 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_register_cancel_callback_with_state(zip_t *, zip_cancel_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 19542357..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-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
@@ -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 88fcf53a..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-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
diff --git a/src/Common/libzip/zip_add_entry.c b/src/Common/libzip/zip_add_entry.c
index f52e0b5c..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-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
@@ -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 30e072a5..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-2019 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,27 +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) {
- zip_error_set(error, ZIP_ET_SYS, errno);
- 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;
@@ -72,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);
}
@@ -91,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;
}
@@ -143,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;
@@ -163,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;
@@ -185,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,
@@ -235,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,
@@ -245,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 8c24b27e..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-2019 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 2a9fed25..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-2020 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,214 +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) {
- 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 (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;
+ }
}
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;
+ zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
+ zip_source_rollback_write(za->src);
+ free(filelist);
+ return -1;
}
error = 0;
for (j = 0; j < survivors; j++) {
- int new_data;
- zip_entry_t *entry;
- zip_dirent_t *de;
-
- if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) {
- zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
- error = 1;
- break;
- }
-
- i = filelist[j].idx;
- entry = za->entry + i;
-
- if (entry->orig != NULL && entry->orig->offset < unchanged_offset) {
- /* already implicitly copied by cloning */
- continue;
- }
-
- new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
-
- /* 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;
- }
- _zip_progress_end(za->progress);
+ if (zip_source_commit_write(za->src) != 0) {
+ zip_error_set_from_source(&za->error, za->src);
+ error = 1;
+ }
+ _zip_progress_end(za->progress);
}
if (error) {
- zip_source_rollback_write(za->src);
- return -1;
+ zip_source_rollback_write(za->src);
+ return -1;
}
zip_discard(za);
@@ -282,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);
@@ -383,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;
@@ -531,32 +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_read(za->src, buf, n, &za->error) < 0) {
+ byte_array_fini(buf);
+ return -1;
+ }
- if (_zip_write(za, buf, n) < 0) {
- byte_array_fini(buf);
- return -1;
- }
+ if (_zip_write(za, buf, n) < 0) {
+ byte_array_fini(buf);
+ return -1;
+ }
- len -= n;
+ len -= n;
- if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) {
- zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
- return -1;
- }
+ 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);
@@ -571,35 +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;
- 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 (_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);
@@ -611,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;
@@ -637,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 97701a01..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-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
@@ -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 c40b1cb9..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-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
@@ -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 2bbb63dc..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-2020 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,9 +35,9 @@
#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"
@@ -51,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);
@@ -66,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;
@@ -77,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;
@@ -91,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;
@@ -128,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);
@@ -187,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;
@@ -217,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;
@@ -234,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;
}
}
@@ -258,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);
@@ -296,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;
}
@@ -307,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;
@@ -336,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);
@@ -379,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;
@@ -421,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);
@@ -503,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;
}
@@ -585,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);
@@ -621,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 1:
+ break;
- case 2:
- if (de->uncomp_size < 20 /* TODO: constant */) {
- crc_valid = false;
- }
- break;
-
- default:
- zip_error_set(error, ZIP_ER_ENCRNOTSUPP, 0);
- _zip_buffer_free(buffer);
- return false;
+ 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;
@@ -705,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);
@@ -757,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);
@@ -788,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;
+ }
+ }
}
@@ -1006,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);
@@ -1025,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);
@@ -1040,87 +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 *tpm;
-
-#ifdef HAVE_LOCALTIME_R
struct tm tm;
- tpm = localtime_r(&intime, &tm);
-#else
- tpm = localtime(&intime);
-#endif
+ 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 localtime fails, return an arbitrary date (1980-01-01 00:00:00) */
+ *ddate = (1 << 5) + 1;
+ *dtime = 0;
+ return;
}
if (tpm->tm_year < 80) {
- tpm->tm_year = 80;
+ tpm->tm_year = 80;
}
*ddate = (zip_uint16_t)(((tpm->tm_year + 1900 - 1980) << 9) + ((tpm->tm_mon + 1) << 5) + tpm->tm_mday);
*dtime = (zip_uint16_t)(((tpm->tm_hour) << 11) + ((tpm->tm_min) << 5) + ((tpm->tm_sec) >> 1));
-
- return;
}
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 12f06367..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-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
@@ -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 52ecaef9..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-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
diff --git a/src/Common/libzip/zip_err_str.c b/src/Common/libzip/zip_err_str.c
index e0a04a94..28af773b 100644
--- a/src/Common/libzip/zip_err_str.c
+++ b/src/Common/libzip/zip_err_str.c
@@ -1,84 +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",
- "Operation cancelled",
-};
-
-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,
- 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 a0f74f02..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-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
@@ -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 eec1568f..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-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
@@ -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 9588b4c4..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-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
diff --git a/src/Common/libzip/zip_error_get_sys_type.c b/src/Common/libzip/zip_error_get_sys_type.c
index 3dfe5c26..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-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
@@ -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 63585779..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-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,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 13faf962..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-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
@@ -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 7114a251..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-2019 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 605f95d0..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-2019 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 6eb9dc91..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-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
@@ -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 5a732cd4..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-2019 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 c019d8dd..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-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
@@ -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 47e5da63..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-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
@@ -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 1ed68df1..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-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
diff --git a/src/Common/libzip/zip_file_get_comment.c b/src/Common/libzip/zip_file_get_comment.c
index 8f68141a..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-2019 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 ebc20580..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-2019 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 9ea89090..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-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
@@ -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 7ca428c4..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-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
@@ -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 87401f4a..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-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
@@ -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 c309db8b..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-2019 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 bb2ea614..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-2019 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 838548ef..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-2020 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
@@ -45,20 +45,29 @@ zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags)
zip_entry_t *e;
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
- return -1;
+ 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;
+ if (e->orig != NULL && e->orig->encryption_method == ZIP_EM_TRAD_PKWARE && !ZIP_ENTRY_CHANGED(e, ZIP_DIRENT_ENCRYPTION_METHOD) && !ZIP_ENTRY_DATA_CHANGED(e)) {
+ zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
+ return -1;
+ }
+
if (e->changes == NULL) {
- if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
- return -1;
- }
+ 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;
diff --git a/src/Common/libzip/zip_file_strerror.c b/src/Common/libzip/zip_file_strerror.c
index 1fa7fffd..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-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
diff --git a/src/Common/libzip/zip_fopen.c b/src/Common/libzip/zip_fopen.c
index 4f1a051d..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-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
@@ -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 9e9b13e5..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-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
@@ -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 ffca281d..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-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
@@ -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 6712c32a..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-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,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 646d7124..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-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
@@ -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 7e04bed6..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-2019 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 3fff4e3b..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-2019 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 953c6f42..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-2019 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 fa4dd502..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-2019 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 c9d52ad5..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-2019 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 f8006861..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-2019 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 43442093..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-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
@@ -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 410d26e1..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-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
@@ -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 4895eaab..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-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
@@ -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 3206dbf7..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-2019 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 dd07cbb9..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-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
@@ -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 05fcb7b7..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-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
@@ -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 f7318ece..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-2019 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 4f58ecc7..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-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
@@ -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 4e29c5b9..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-2019 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,21 +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_OK
-} 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);
@@ -64,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);
@@ -83,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;
}
}
}
@@ -164,60 +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;
if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
- return NULL;
+ return NULL;
}
/* treat empty files as empty archives */
if (len == 0 && zip_source_accept_empty(src)) {
- return za;
+ 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;
@@ -229,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;
}
@@ -255,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);
@@ -426,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;
@@ -487,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;
@@ -506,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;
}
@@ -528,12 +554,12 @@ _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 EXISTS_OK;
@@ -543,7 +569,7 @@ _zip_file_exists(zip_source_t *src, zip_error_t *error) {
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;
@@ -552,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;
+ }
}
@@ -650,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);
@@ -659,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 */
@@ -669,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;
@@ -723,38 +759,38 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
/* valid seek value for start of EOCD */
if (eocd_offset > ZIP_INT64_MAX) {
- zip_error_set(error, ZIP_ER_SEEK, EFBIG);
- return NULL;
+ 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 */
@@ -762,11 +798,11 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
/* 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 */
@@ -778,35 +814,35 @@ _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);
@@ -814,38 +850,38 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
/* 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, 0);
- return NULL;
+ 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;
@@ -853,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 d48ae563..e080514b 100644
--- a/src/Common/libzip/zip_progress.c
+++ b/src/Common/libzip/zip_progress.c
@@ -3,7 +3,7 @@
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
@@ -73,7 +73,7 @@ _zip_progress_end(zip_progress_t *progress) {
void
_zip_progress_free(zip_progress_t *progress) {
if (progress == NULL) {
- return;
+ return;
}
_zip_progress_free_progress_callback(progress);
@@ -88,8 +88,8 @@ _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;
@@ -109,7 +109,7 @@ _zip_progress_new(zip_t *za) {
static void
_zip_progress_free_progress_callback(zip_progress_t *progress) {
if (progress->ud_progress_free) {
- progress->ud_progress_free(progress->ud_progress);
+ progress->ud_progress_free(progress->ud_progress);
}
progress->callback_progress = NULL;
@@ -120,7 +120,7 @@ _zip_progress_free_progress_callback(zip_progress_t *progress) {
static void
_zip_progress_free_cancel_callback(zip_progress_t *progress) {
if (progress->ud_cancel_free) {
- progress->ud_cancel_free(progress->ud_cancel);
+ progress->ud_cancel_free(progress->ud_cancel);
}
progress->callback_cancel = NULL;
@@ -150,18 +150,18 @@ _zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback
int
_zip_progress_start(zip_progress_t *progress) {
if (progress == NULL) {
- return 0;
+ return 0;
}
if (progress->callback_progress != NULL) {
- progress->last_update = 0.0;
- progress->callback_progress(progress->za, 0.0, progress->ud_progress);
+ 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;
- }
+ if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
+ return -1;
+ }
}
return 0;
@@ -171,7 +171,7 @@ _zip_progress_start(zip_progress_t *progress) {
int
_zip_progress_subrange(zip_progress_t *progress, double start, double end) {
if (progress == NULL) {
- return 0;
+ return 0;
}
progress->start = start;
@@ -185,22 +185,22 @@ _zip_progress_update(zip_progress_t *progress, double sub_current) {
double current;
if (progress == NULL) {
- return 0;
+ return 0;
}
if (progress->callback_progress != NULL) {
- current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
+ current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
- if (current - progress->last_update > progress->precision) {
- progress->callback_progress(progress->za, current, progress->ud_progress);
- progress->last_update = current;
- }
+ if (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;
- }
+ if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
+ return -1;
+ }
}
return 0;
@@ -209,27 +209,25 @@ _zip_progress_update(zip_progress_t *progress, double sub_current) {
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 (za->progress == NULL) {
- if ((za->progress = _zip_progress_new(za)) == NULL) {
- return -1;
- }
- }
+ if ((za->progress = _zip_progress_new(za)) == NULL) {
+ return -1;
+ }
+ }
- _zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud);
+ _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);
- }
- }
+ if (za->progress != NULL) {
+ if (za->progress->callback_cancel == NULL) {
+ _zip_progress_free(za->progress);
+ za->progress = NULL;
+ }
+ else {
+ _zip_progress_free_progress_callback(za->progress);
+ }
+ }
}
return 0;
@@ -238,27 +236,25 @@ zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progr
ZIP_EXTERN int
zip_register_cancel_callback_with_state(zip_t *za, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) {
- zip_progress_t *progress = NULL;
-
if (callback != NULL) {
if (za->progress == NULL) {
- if ((za->progress = _zip_progress_new(za)) == NULL) {
- return -1;
- }
- }
+ if ((za->progress = _zip_progress_new(za)) == NULL) {
+ return -1;
+ }
+ }
- _zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud);
+ _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);
- }
- }
+ 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;
@@ -282,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 b8873634..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-2019 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 e5f16823..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-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
@@ -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 30a2eb1d..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-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
diff --git a/src/Common/libzip/zip_set_archive_comment.c b/src/Common/libzip/zip_set_archive_comment.c
index 3f050b3e..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-2019 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 e0d55021..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-2019 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 41c7c519..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-2019 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 1fa01ae6..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-2019 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 927fbb76..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-2019 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 43c772e4..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-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
@@ -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
index e6d51516..e772aeea 100644
--- a/src/Common/libzip/zip_source_accept_empty.c
+++ b/src/Common/libzip/zip_source_accept_empty.c
@@ -1,9 +1,9 @@
/*
zip_source_accept_empty.c -- if empty source is a valid archive
- Copyright (C) 2019 Dieter Baron and Thomas Klausner
+ 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 <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 @@
bool
zip_source_accept_empty(zip_source_t *src) {
- int ret;
+ 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;
+ if (ZIP_SOURCE_IS_LAYERED(src)) {
+ return zip_source_accept_empty(src->src);
+ }
+ return true;
}
- ret = (int)_zip_source_call(src, NULL, 0, ZIP_SOURCE_ACCEPT_EMPTY);
+ 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 432c2c15..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-2019 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 41b4c73c..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-2019 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 0685fb39..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-2019 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,18 +80,27 @@ 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) {
@@ -99,184 +109,211 @@ zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_erro
return NULL;
}
- return zip_source_buffer_fragment_create(NULL, 0, freep, error);
+ 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;
}
}
@@ -287,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;
}
@@ -339,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;
@@ -364,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);
@@ -387,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;
+ }
+
+ 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, sizeof(buffer->fragments[0]) * capacity)) == NULL) {
- 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;
@@ -413,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;
@@ -427,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[buffer->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;
@@ -475,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;
@@ -507,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;
@@ -518,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 e7c29544..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-2019 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 ab7898ce..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-2019 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 d1254bf1..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-2019 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 59b1212d..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-2019 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>
@@ -68,54 +67,57 @@ static struct implementation implementations[] = {
{ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress},
#endif
#if defined(HAVE_LIBLZMA)
-/* Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2
- archives made this way - and vice versa.
-
{ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
- {ZIP_CM_LZMA2, &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);
}
@@ -126,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;
@@ -156,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;
@@ -172,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;
@@ -184,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);
@@ -203,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;
@@ -306,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 56572c0b..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-2019 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 2257f715..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-2019 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 083f5bcb..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-2019 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 30e5991c..00000000
--- a/src/Common/libzip/zip_source_filep.c
+++ /dev/null
@@ -1,663 +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 <fcntl.h>
-#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
-
-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 FILE *_zip_fopen(const char *name, bool writeable);
-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;
- }
- }
- }
- }
-
- ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY);
-#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;
- int mode;
- FILE *tfp;
- struct stat st;
-
- if ((temp = (char *)malloc(strlen(ctx->fname) + 8)) == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0);
- return -1;
- }
-
- if (stat(ctx->fname, &st) == 0) {
- mode = st.st_mode;
- }
- else {
- mode = -1;
- }
-
- sprintf(temp, "%s.XXXXXX", ctx->fname);
-
- if ((tfd = _zip_mkstempm(temp, mode)) == -1) {
- zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
- free(temp);
- return -1;
- }
-
- 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;
- }
-
- 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 = _zip_fopen(temp, true)) == 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_ACCEPT_EMPTY:
- return 0;
-
- case ZIP_SOURCE_BEGIN_WRITE:
-#ifdef _WIN32
- return -1;
-#else
- if (ctx->fname == NULL) {
- zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
- return -1;
- }
- return create_temp_output(ctx);
-#endif
-
-#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_CLOSE:
- if (ctx->fname) {
- fclose(ctx->f);
- ctx->f = NULL;
- }
- return 0;
-
- case ZIP_SOURCE_COMMIT_WRITE: {
- if (fclose(ctx->fout) < 0) {
- ctx->fout = NULL;
- zip_error_set(&ctx->error, ZIP_ER_WRITE, errno);
- }
- ctx->fout = NULL;
- if (rename(ctx->tmpname, ctx->fname) < 0) {
- zip_error_set(&ctx->error, ZIP_ER_RENAME, errno);
- return -1;
- }
- free(ctx->tmpname);
- ctx->tmpname = 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 = _zip_fopen(ctx->fname, false)) == 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;
-}
-
-
-/*
- * 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(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_free.c b/src/Common/libzip/zip_source_free.c
index 2f10ef8f..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-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
@@ -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 d5c1b5b0..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-2019 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 edd10ca2..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-2019 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 d02bc852..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-2019 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 414c677a..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-2019 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 1b59d7a7..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-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 <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 33088cb1..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-2019 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 14eddb8f..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-2019 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 e8259bff..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-2019 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 163daf1b..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-2019 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 6b0aa78e..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-2019 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 3421d2cb..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-2019 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 84715598..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-2019 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 772e2524..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-2019 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 96ad7e26..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-2019 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 257fc6aa..00000000
--- a/src/Common/libzip/zip_source_win32a.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- zip_source_win32a.c -- create data source from Windows file (ANSI)
- 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.
-*/
-
-/* 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) {
- DWORD attributes = GetFileAttributesA(ctx->tmpname);
- if (INVALID_FILE_ATTRIBUTES == attributes)
- return -1;
-
- if (FILE_ATTRIBUTE_TEMPORARY & attributes) {
- if (!SetFileAttributesA(ctx->tmpname, attributes & ~FILE_ATTRIBUTE_TEMPORARY))
- return -1;
- }
-
- 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 8746cdd1..00000000
--- a/src/Common/libzip/zip_source_win32handle.c
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
- zip_source_win32file.c -- create data source from HANDLE (Win32)
- 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 <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;
- }
-
- ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY);
-
- 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_ACCEPT_EMPTY:
- return 0;
-
- 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 + ctx->start;
- 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 cb8d64e6..00000000
--- a/src/Common/libzip/zip_source_win32w.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- zip_source_win32w.c -- create data source from Windows file (UTF-16)
- 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.
-*/
-
-/* 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) {
- DWORD attributes = GetFileAttributesW(ctx->tmpname);
- if (INVALID_FILE_ATTRIBUTES == attributes)
- return -1;
-
- if (FILE_ATTRIBUTE_TEMPORARY & attributes) {
- if (!SetFileAttributesW(ctx->tmpname, attributes & ~FILE_ATTRIBUTE_TEMPORARY))
- return -1;
- }
-
- 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 1276485d..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-2019 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 73fc3a31..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-2019 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 1f77aaaf..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-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
@@ -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 f36609b1..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-2019 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 341c6f77..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-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
@@ -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 71f80491..da33c09e 100644
--- a/src/Common/libzip/zip_stat_index.c
+++ b/src/Common/libzip/zip_stat_index.c
@@ -3,7 +3,7 @@
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,37 +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)) {
- zip_entry_t *entry = za->entry+index;
-
- if (zip_source_stat(entry->source, st) < 0) {
- zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
- return -1;
- }
- if (entry->changes->changed & ZIP_DIRENT_LAST_MOD) {
- st->mtime = de->last_mod;
- st->valid |= ZIP_STAT_MTIME;
- }
+ 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 6d0903d6..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-2019 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 906c7f76..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-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
diff --git a/src/Common/libzip/zip_string.c b/src/Common/libzip/zip_string.c
index a6edbc5d..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-2019 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 1a78e2c3..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-2019 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 5e7df80a..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-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
@@ -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 bd223ef5..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-2019 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 74a429c9..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-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
@@ -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 099db9bf..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-2019 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 721d36e8..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-2020 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);
@@ -152,9 +164,10 @@ 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. */
@@ -164,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 */
@@ -251,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 */
};
@@ -297,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 */
};
@@ -334,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;
@@ -345,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)
@@ -381,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
@@ -406,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;
@@ -414,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))
@@ -426,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
@@ -466,7 +524,6 @@ 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 *);
@@ -474,14 +531,18 @@ zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint6
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);
@@ -503,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 *);
@@ -512,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);
@@ -527,7 +585,7 @@ 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);
+int _zip_mkstempm(char *path, int mode, bool create_file);
zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *);
@@ -545,7 +603,7 @@ int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_err
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);
@@ -554,21 +612,19 @@ 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);
@@ -576,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 870f1d5a..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-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.
-*/
-
-/* 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 */