From 361b6829cfd1480562855340111711080407ce7b Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 12:19:49 +0300 Subject: [PATCH 01/12] a --- thirdparty/next/inc/core/variant.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/thirdparty/next/inc/core/variant.h b/thirdparty/next/inc/core/variant.h index 224ae1b6a..5b68a5436 100644 --- a/thirdparty/next/inc/core/variant.h +++ b/thirdparty/next/inc/core/variant.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -114,7 +115,9 @@ class NEXT_LIBRARY_EXPORT Variant { if(m_data.type < MetaType::STRING) { if(m_data.type == type) { - return *reinterpret_cast(&m_data.ptr); + T result; + memcpy(&result, &m_data.ptr, sizeof(T)); + return result; } else if(canConvert(type)) { T result; MetaType::convert(&m_data.ptr, m_data.type, &result, type); From d3a26a0ae3a671463898b7a677e9c87d029c7275 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 12:30:03 +0300 Subject: [PATCH 02/12] a --- thirdparty/next/inc/core/variant.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/thirdparty/next/inc/core/variant.h b/thirdparty/next/inc/core/variant.h index 5b68a5436..f0028f1a8 100644 --- a/thirdparty/next/inc/core/variant.h +++ b/thirdparty/next/inc/core/variant.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include @@ -115,9 +115,13 @@ class NEXT_LIBRARY_EXPORT Variant { if(m_data.type < MetaType::STRING) { if(m_data.type == type) { - T result; - memcpy(&result, &m_data.ptr, sizeof(T)); - return result; + if constexpr (std::is_trivially_copyable_v) { + T result; + memcpy(&result, &m_data.ptr, sizeof(T)); + return result; + } else { + return *reinterpret_cast(&m_data.ptr); + } } else if(canConvert(type)) { T result; MetaType::convert(&m_data.ptr, m_data.type, &result, type); From f4f0db8f897e2d711ec0796568ff69fd5b61fe09 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 12:41:23 +0300 Subject: [PATCH 03/12] a --- thirdparty/next/inc/core/variant.h | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/thirdparty/next/inc/core/variant.h b/thirdparty/next/inc/core/variant.h index f0028f1a8..224ae1b6a 100644 --- a/thirdparty/next/inc/core/variant.h +++ b/thirdparty/next/inc/core/variant.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -115,13 +114,7 @@ class NEXT_LIBRARY_EXPORT Variant { if(m_data.type < MetaType::STRING) { if(m_data.type == type) { - if constexpr (std::is_trivially_copyable_v) { - T result; - memcpy(&result, &m_data.ptr, sizeof(T)); - return result; - } else { - return *reinterpret_cast(&m_data.ptr); - } + return *reinterpret_cast(&m_data.ptr); } else if(canConvert(type)) { T result; MetaType::convert(&m_data.ptr, m_data.type, &result, type); From 0581227d487b772ccd4c0d6416e21c0e7f6e8865 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 15:22:16 +0300 Subject: [PATCH 04/12] Minizip library updated --- thirdparty/LIBRARIES.md | 8 +- .../assimp/code/Common/ZipArchiveIOSystem.cpp | 2 +- thirdparty/minizip/CMakeLists.txt | 42 - thirdparty/minizip/MiniZip64_Changes.txt | 6 - thirdparty/minizip/MiniZip64_info.txt | 74 - thirdparty/minizip/README.md | 25 - thirdparty/minizip/compat/crypt.h | 84 + thirdparty/minizip/compat/ioapi.c | 260 ++ thirdparty/minizip/compat/ioapi.h | 97 + thirdparty/minizip/compat/unzip.c | 744 +++++ thirdparty/minizip/compat/unzip.h | 239 ++ thirdparty/minizip/compat/zip.c | 407 +++ thirdparty/minizip/compat/zip.h | 180 ++ thirdparty/minizip/ioapi.c | 235 -- thirdparty/minizip/iowin32.c | 389 --- thirdparty/minizip/make_vms.com | 25 - thirdparty/minizip/minigzip.c | 180 ++ thirdparty/minizip/miniunz.c | 648 ---- thirdparty/minizip/minizip.c | 1104 ++++--- thirdparty/minizip/minizip.qbs | 18 +- thirdparty/minizip/minizip/ioapi.h | 204 -- thirdparty/minizip/minizip/iowin32.h | 28 - thirdparty/minizip/minizip/mztools.h | 31 - thirdparty/minizip/minizip/unzip.h | 437 --- thirdparty/minizip/minizip/zip.h | 362 --- thirdparty/minizip/minizip/zipcrypt.h | 131 - thirdparty/minizip/mz.h | 277 ++ thirdparty/minizip/mz_config.h | 28 + thirdparty/minizip/mz_crypt.c | 182 ++ thirdparty/minizip/mz_crypt.h | 65 + thirdparty/minizip/mz_crypt_apple.c | 522 +++ thirdparty/minizip/mz_crypt_openssl.c | 698 ++++ thirdparty/minizip/mz_crypt_winvista.c | 662 ++++ thirdparty/minizip/mz_crypt_winxp.c | 568 ++++ thirdparty/minizip/mz_os.c | 471 +++ thirdparty/minizip/mz_os.h | 198 ++ thirdparty/minizip/mz_os_posix.c | 445 +++ thirdparty/minizip/mz_os_win32.c | 760 +++++ thirdparty/minizip/mz_strm.c | 545 ++++ thirdparty/minizip/mz_strm.h | 135 + thirdparty/minizip/mz_strm_buf.c | 381 +++ thirdparty/minizip/mz_strm_buf.h | 42 + thirdparty/minizip/mz_strm_bzip.c | 349 ++ thirdparty/minizip/mz_strm_bzip.h | 45 + thirdparty/minizip/mz_strm_libcomp.c | 334 ++ thirdparty/minizip/mz_strm_libcomp.h | 43 + thirdparty/minizip/mz_strm_lzma.c | 452 +++ thirdparty/minizip/mz_strm_lzma.h | 43 + thirdparty/minizip/mz_strm_mem.c | 265 ++ thirdparty/minizip/mz_strm_mem.h | 48 + thirdparty/minizip/mz_strm_os.h | 40 + thirdparty/minizip/mz_strm_os_posix.c | 212 ++ thirdparty/minizip/mz_strm_os_win32.c | 280 ++ thirdparty/minizip/mz_strm_pkcrypt.c | 324 ++ thirdparty/minizip/mz_strm_pkcrypt.h | 46 + thirdparty/minizip/mz_strm_ppmd.c | 490 +++ thirdparty/minizip/mz_strm_ppmd.h | 43 + thirdparty/minizip/mz_strm_split.c | 416 +++ thirdparty/minizip/mz_strm_split.h | 43 + thirdparty/minizip/mz_strm_wzaes.c | 355 +++ thirdparty/minizip/mz_strm_wzaes.h | 46 + thirdparty/minizip/mz_strm_zlib.c | 378 +++ thirdparty/minizip/mz_strm_zlib.h | 43 + thirdparty/minizip/mz_strm_zstd.c | 344 ++ thirdparty/minizip/mz_strm_zstd.h | 44 + thirdparty/minizip/mz_zip.c | 2834 +++++++++++++++++ thirdparty/minizip/mz_zip.h | 257 ++ thirdparty/minizip/mz_zip_rw.c | 2029 ++++++++++++ thirdparty/minizip/mz_zip_rw.h | 281 ++ thirdparty/minizip/mztools.c | 281 -- thirdparty/minizip/unzip.c | 2125 ------------ thirdparty/minizip/zip.c | 2004 ------------ 72 files changed, 18936 insertions(+), 7497 deletions(-) delete mode 100644 thirdparty/minizip/CMakeLists.txt delete mode 100644 thirdparty/minizip/MiniZip64_Changes.txt delete mode 100644 thirdparty/minizip/MiniZip64_info.txt delete mode 100644 thirdparty/minizip/README.md create mode 100644 thirdparty/minizip/compat/crypt.h create mode 100644 thirdparty/minizip/compat/ioapi.c create mode 100644 thirdparty/minizip/compat/ioapi.h create mode 100644 thirdparty/minizip/compat/unzip.c create mode 100644 thirdparty/minizip/compat/unzip.h create mode 100644 thirdparty/minizip/compat/zip.c create mode 100644 thirdparty/minizip/compat/zip.h delete mode 100644 thirdparty/minizip/ioapi.c delete mode 100644 thirdparty/minizip/iowin32.c delete mode 100644 thirdparty/minizip/make_vms.com create mode 100644 thirdparty/minizip/minigzip.c delete mode 100644 thirdparty/minizip/miniunz.c delete mode 100644 thirdparty/minizip/minizip/ioapi.h delete mode 100644 thirdparty/minizip/minizip/iowin32.h delete mode 100644 thirdparty/minizip/minizip/mztools.h delete mode 100644 thirdparty/minizip/minizip/unzip.h delete mode 100644 thirdparty/minizip/minizip/zip.h delete mode 100644 thirdparty/minizip/minizip/zipcrypt.h create mode 100644 thirdparty/minizip/mz.h create mode 100644 thirdparty/minizip/mz_config.h create mode 100644 thirdparty/minizip/mz_crypt.c create mode 100644 thirdparty/minizip/mz_crypt.h create mode 100644 thirdparty/minizip/mz_crypt_apple.c create mode 100644 thirdparty/minizip/mz_crypt_openssl.c create mode 100644 thirdparty/minizip/mz_crypt_winvista.c create mode 100644 thirdparty/minizip/mz_crypt_winxp.c create mode 100644 thirdparty/minizip/mz_os.c create mode 100644 thirdparty/minizip/mz_os.h create mode 100644 thirdparty/minizip/mz_os_posix.c create mode 100644 thirdparty/minizip/mz_os_win32.c create mode 100644 thirdparty/minizip/mz_strm.c create mode 100644 thirdparty/minizip/mz_strm.h create mode 100644 thirdparty/minizip/mz_strm_buf.c create mode 100644 thirdparty/minizip/mz_strm_buf.h create mode 100644 thirdparty/minizip/mz_strm_bzip.c create mode 100644 thirdparty/minizip/mz_strm_bzip.h create mode 100644 thirdparty/minizip/mz_strm_libcomp.c create mode 100644 thirdparty/minizip/mz_strm_libcomp.h create mode 100644 thirdparty/minizip/mz_strm_lzma.c create mode 100644 thirdparty/minizip/mz_strm_lzma.h create mode 100644 thirdparty/minizip/mz_strm_mem.c create mode 100644 thirdparty/minizip/mz_strm_mem.h create mode 100644 thirdparty/minizip/mz_strm_os.h create mode 100644 thirdparty/minizip/mz_strm_os_posix.c create mode 100644 thirdparty/minizip/mz_strm_os_win32.c create mode 100644 thirdparty/minizip/mz_strm_pkcrypt.c create mode 100644 thirdparty/minizip/mz_strm_pkcrypt.h create mode 100644 thirdparty/minizip/mz_strm_ppmd.c create mode 100644 thirdparty/minizip/mz_strm_ppmd.h create mode 100644 thirdparty/minizip/mz_strm_split.c create mode 100644 thirdparty/minizip/mz_strm_split.h create mode 100644 thirdparty/minizip/mz_strm_wzaes.c create mode 100644 thirdparty/minizip/mz_strm_wzaes.h create mode 100644 thirdparty/minizip/mz_strm_zlib.c create mode 100644 thirdparty/minizip/mz_strm_zlib.h create mode 100644 thirdparty/minizip/mz_strm_zstd.c create mode 100644 thirdparty/minizip/mz_strm_zstd.h create mode 100644 thirdparty/minizip/mz_zip.c create mode 100644 thirdparty/minizip/mz_zip.h create mode 100644 thirdparty/minizip/mz_zip_rw.c create mode 100644 thirdparty/minizip/mz_zip_rw.h delete mode 100644 thirdparty/minizip/mztools.c delete mode 100644 thirdparty/minizip/unzip.c delete mode 100644 thirdparty/minizip/zip.c diff --git a/thirdparty/LIBRARIES.md b/thirdparty/LIBRARIES.md index 07060daab..5b4c19fb4 100644 --- a/thirdparty/LIBRARIES.md +++ b/thirdparty/LIBRARIES.md @@ -61,11 +61,17 @@ - Version: 0.11.24 - License: Public Domain +## minzip-ng + +- Link: https://github.com/zlib-ng/minizip-ng +- Version: 4.2.1 +- License: Zlib + ## next - Link: https://github.com/eprikazchikov/platformnext - Version: 1.0 -- License: MIT +- License: Apache 2.0 ## physfs diff --git a/thirdparty/assimp/code/Common/ZipArchiveIOSystem.cpp b/thirdparty/assimp/code/Common/ZipArchiveIOSystem.cpp index 23d7db15d..2f4d6d2e9 100644 --- a/thirdparty/assimp/code/Common/ZipArchiveIOSystem.cpp +++ b/thirdparty/assimp/code/Common/ZipArchiveIOSystem.cpp @@ -52,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #ifdef ASSIMP_USE_HUNTER -# include +# include #else # include #endif diff --git a/thirdparty/minizip/CMakeLists.txt b/thirdparty/minizip/CMakeLists.txt deleted file mode 100644 index 92df3bab1..000000000 --- a/thirdparty/minizip/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -project(minizip) - - -set(${PROJECT_NAME}_incPaths - "./" - "../zlib/src" -) - -# This path is only needed on the BSDs -if(UNIX AND NOT APPLE AND NOT LINUX) - set(${PROJECT_NAME}_incPaths - ${${PROJECT_NAME}_incPaths} - "/usr/local/include" - ) -endif() - -set(${PROJECT_NAME}_srcFiles - ioapi.c - miniunz.c - mztools.c - unzip.c - zip.c -) - -if(WIN32) - set(${PROJECT_NAME}_srcFiles - ${${PROJECT_NAME}_srcFiles} - iowin32.c - ) -endif() - -# Static Library -add_library(${PROJECT_NAME} STATIC ${${PROJECT_NAME}_srcFiles}) -target_include_directories(${PROJECT_NAME} PRIVATE ${${PROJECT_NAME}_incPaths}) -set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER "thirdparty") - -# Solve build error using Clang on BSDs -if(UNIX AND NOT APPLE AND NOT LINUX) - target_compile_options(${PROJECT_NAME} PRIVATE -fPIC) -endif() \ No newline at end of file diff --git a/thirdparty/minizip/MiniZip64_Changes.txt b/thirdparty/minizip/MiniZip64_Changes.txt deleted file mode 100644 index 13a1bd91a..000000000 --- a/thirdparty/minizip/MiniZip64_Changes.txt +++ /dev/null @@ -1,6 +0,0 @@ - -MiniZip 1.1 was derrived from MiniZip at version 1.01f - -Change in 1.0 (Okt 2009) - - **TODO - Add history** - diff --git a/thirdparty/minizip/MiniZip64_info.txt b/thirdparty/minizip/MiniZip64_info.txt deleted file mode 100644 index 57d715242..000000000 --- a/thirdparty/minizip/MiniZip64_info.txt +++ /dev/null @@ -1,74 +0,0 @@ -MiniZip - Copyright (c) 1998-2010 - by Gilles Vollant - version 1.1 64 bits from Mathias Svensson - -Introduction ---------------------- -MiniZip 1.1 is built from MiniZip 1.0 by Gilles Vollant ( http://www.winimage.com/zLibDll/minizip.html ) - -When adding ZIP64 support into minizip it would result into risk of breaking compatibility with minizip 1.0. -All possible work was done for compatibility. - - -Background ---------------------- -When adding ZIP64 support Mathias Svensson found that Even Rouault have added ZIP64 -support for unzip.c into minizip for a open source project called gdal ( http://www.gdal.org/ ) - -That was used as a starting point. And after that ZIP64 support was added to zip.c -some refactoring and code cleanup was also done. - - -Changed from MiniZip 1.0 to MiniZip 1.1 ---------------------------------------- -* Added ZIP64 support for unzip ( by Even Rouault ) -* Added ZIP64 support for zip ( by Mathias Svensson ) -* Reverted some changed that Even Rouault did. -* Bunch of patches received from Gulles Vollant that he received for MiniZip from various users. -* Added unzip patch for BZIP Compression method (patch create by Daniel Borca) -* Added BZIP Compress method for zip -* Did some refactoring and code cleanup - - -Credits - - Gilles Vollant - Original MiniZip author - Even Rouault - ZIP64 unzip Support - Daniel Borca - BZip Compression method support in unzip - Mathias Svensson - ZIP64 zip support - Mathias Svensson - BZip Compression method support in zip - - Resources - - ZipLayout http://result42.com/projects/ZipFileLayout - Command line tool for Windows that shows the layout and information of the headers in a zip archive. - Used when debugging and validating the creation of zip files using MiniZip64 - - - ZIP App Note http://www.pkware.com/documents/casestudies/APPNOTE.TXT - Zip File specification - - -Notes. - * To be able to use BZip compression method in zip64.c or unzip64.c the BZIP2 lib is needed and HAVE_BZIP2 need to be defined. - -License ----------------------------------------------------------- - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - ----------------------------------------------------------- - diff --git a/thirdparty/minizip/README.md b/thirdparty/minizip/README.md deleted file mode 100644 index 38f390b93..000000000 --- a/thirdparty/minizip/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Minizip. Portable zip & unzip lib - -Based on the original work of [Gilles Vollant](http://www.winimage.com/zLibDll/minizip.html) - -### Usage in a CMake project - -add_subdirectory (minizip) -target_link_libraries(${PROJECT_NAME} minizip) -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/minizip) - -In your code you can use it like - -#include - -### Requirement: - -* Zlib. The Zlib library allows to deflate compressed files and to create gzip (.gz) files. Zlib is free software and small. - -### Usage of library - -``` -#include - -unzip(src, dst); -``` diff --git a/thirdparty/minizip/compat/crypt.h b/thirdparty/minizip/compat/crypt.h new file mode 100644 index 000000000..284c14d71 --- /dev/null +++ b/thirdparty/minizip/compat/crypt.h @@ -0,0 +1,84 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#ifndef ZLIB_VERNUM +/* No zlib */ +typedef unsigned int z_crc_t; +#elif (ZLIB_VERNUM & 0xf != 0xf) && (ZLIB_VERNUM < 0x1270) +/* Define z_crc_t in zlib 1.2.6 and less */ +typedef unsigned long z_crc_t; +#elif (ZLIB_VERNUM & 0xf == 0xf) && (ZLIB_VERNUM < 0x12df) +/* Define z_crc_t in zlib-ng 2.0.7 and less */ +typedef unsigned int z_crc_t; +#endif + +#define CRC32(c, b) ((*(pcrc_32_tab + (((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/***************************************************************************/ +/* Return the next byte in the pseudo-random sequence */ + +static int decrypt_byte(unsigned long *pkeys, const z_crc_t *pcrc_32_tab) { + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + (void)pcrc_32_tab; + temp = ((unsigned)(*(pkeys + 2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/***************************************************************************/ +/* Update the encryption keys with the next byte of plain text */ + +static int update_keys(unsigned long *pkeys, const z_crc_t *pcrc_32_tab, int c) { + (*(pkeys + 0)) = CRC32((*(pkeys + 0)), c); + (*(pkeys + 1)) += (*(pkeys + 0)) & 0xff; + (*(pkeys + 1)) = (*(pkeys + 1)) * 134775813L + 1; + { + int keyshift = (int)((*(pkeys + 1)) >> 24); + (*(pkeys + 2)) = CRC32((*(pkeys + 2)), keyshift); + } + return c; +} + +/***************************************************************************/ +/* Initialize the encryption keys and the random header according to the password. */ + +static void init_keys(const char *passwd, unsigned long *pkeys, const z_crc_t *pcrc_32_tab) { + *(pkeys + 0) = 305419896L; + *(pkeys + 1) = 591751049L; + *(pkeys + 2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys, pcrc_32_tab, (int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys, pcrc_32_tab, c) (update_keys(pkeys, pcrc_32_tab, c ^= decrypt_byte(pkeys, pcrc_32_tab))) + +#define zencode(pkeys, pcrc_32_tab, c, t) \ + (t = decrypt_byte(pkeys, pcrc_32_tab), update_keys(pkeys, pcrc_32_tab, c), (Byte)t ^ (c)) diff --git a/thirdparty/minizip/compat/ioapi.c b/thirdparty/minizip/compat/ioapi.c new file mode 100644 index 000000000..9465f6096 --- /dev/null +++ b/thirdparty/minizip/compat/ioapi.c @@ -0,0 +1,260 @@ +#include "mz.h" +#include "mz_strm.h" +#include "mz_strm_mem.h" + +#include "ioapi.h" + +typedef struct mz_stream_ioapi_s { + mz_stream stream; + void *handle; + zlib_filefunc_def filefunc; + zlib_filefunc64_def filefunc64; +} mz_stream_ioapi; + +/***************************************************************************/ + +static int32_t mz_stream_ioapi_open(void *stream, const char *path, int32_t mode); +static int32_t mz_stream_ioapi_is_open(void *stream); +static int32_t mz_stream_ioapi_read(void *stream, void *buf, int32_t size); +static int32_t mz_stream_ioapi_write(void *stream, const void *buf, int32_t size); +static int64_t mz_stream_ioapi_tell(void *stream); +static int32_t mz_stream_ioapi_seek(void *stream, int64_t offset, int32_t origin); +static int32_t mz_stream_ioapi_close(void *stream); +static int32_t mz_stream_ioapi_error(void *stream); + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_ioapi_vtbl = {mz_stream_ioapi_open, + mz_stream_ioapi_is_open, + mz_stream_ioapi_read, + mz_stream_ioapi_write, + mz_stream_ioapi_tell, + mz_stream_ioapi_seek, + mz_stream_ioapi_close, + mz_stream_ioapi_error, + mz_stream_ioapi_create, + mz_stream_ioapi_delete, + NULL, + NULL}; + +/***************************************************************************/ + +static int32_t mz_stream_ioapi_open(void *stream, const char *path, int32_t mode) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; + int32_t ioapi_mode = 0; + + if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) + ioapi_mode = ZLIB_FILEFUNC_MODE_READ; + else if (mode & MZ_OPEN_MODE_APPEND) + ioapi_mode = ZLIB_FILEFUNC_MODE_EXISTING; + else if (mode & MZ_OPEN_MODE_CREATE) + ioapi_mode = ZLIB_FILEFUNC_MODE_CREATE; + else + return MZ_OPEN_ERROR; + + if (ioapi->filefunc64.zopen64_file) + ioapi->handle = ioapi->filefunc64.zopen64_file(ioapi->filefunc64.opaque, path, ioapi_mode); + else if (ioapi->filefunc.zopen_file) + ioapi->handle = ioapi->filefunc.zopen_file(ioapi->filefunc.opaque, path, ioapi_mode); + + if (!ioapi->handle) + return MZ_PARAM_ERROR; + + return MZ_OK; +} + +static int32_t mz_stream_ioapi_is_open(void *stream) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; + if (!ioapi->handle) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +static int32_t mz_stream_ioapi_read(void *stream, void *buf, int32_t size) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; + read_file_func zread = NULL; + void *opaque = NULL; + + if (mz_stream_ioapi_is_open(stream) != MZ_OK) + return MZ_OPEN_ERROR; + + if (ioapi->filefunc64.zread_file) { + zread = ioapi->filefunc64.zread_file; + opaque = ioapi->filefunc64.opaque; + } else if (ioapi->filefunc.zread_file) { + zread = ioapi->filefunc.zread_file; + opaque = ioapi->filefunc.opaque; + } else + return MZ_PARAM_ERROR; + + return (int32_t)zread(opaque, ioapi->handle, buf, size); +} + +static int32_t mz_stream_ioapi_write(void *stream, const void *buf, int32_t size) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; + write_file_func zwrite = NULL; + int32_t written = 0; + void *opaque = NULL; + + if (mz_stream_ioapi_is_open(stream) != MZ_OK) + return MZ_OPEN_ERROR; + + if (ioapi->filefunc64.zwrite_file) { + zwrite = ioapi->filefunc64.zwrite_file; + opaque = ioapi->filefunc64.opaque; + } else if (ioapi->filefunc.zwrite_file) { + zwrite = ioapi->filefunc.zwrite_file; + opaque = ioapi->filefunc.opaque; + } else + return MZ_PARAM_ERROR; + + written = (int32_t)zwrite(opaque, ioapi->handle, buf, size); + return written; +} + +static int64_t mz_stream_ioapi_tell(void *stream) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; + + if (mz_stream_ioapi_is_open(stream) != MZ_OK) + return MZ_OPEN_ERROR; + + if (ioapi->filefunc64.ztell64_file) + return ioapi->filefunc64.ztell64_file(ioapi->filefunc64.opaque, ioapi->handle); + else if (ioapi->filefunc.ztell_file) + return ioapi->filefunc.ztell_file(ioapi->filefunc.opaque, ioapi->handle); + + return MZ_INTERNAL_ERROR; +} + +static int32_t mz_stream_ioapi_seek(void *stream, int64_t offset, int32_t origin) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; + + if (mz_stream_ioapi_is_open(stream) != MZ_OK) + return MZ_OPEN_ERROR; + + if (ioapi->filefunc64.zseek64_file) { + if (ioapi->filefunc64.zseek64_file(ioapi->filefunc64.opaque, ioapi->handle, offset, origin) != 0) + return MZ_INTERNAL_ERROR; + } else if (ioapi->filefunc.zseek_file) { + if (ioapi->filefunc.zseek_file(ioapi->filefunc.opaque, ioapi->handle, (int32_t)offset, origin) != 0) + return MZ_INTERNAL_ERROR; + } else + return MZ_PARAM_ERROR; + + return MZ_OK; +} + +static int32_t mz_stream_ioapi_close(void *stream) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; + close_file_func zclose = NULL; + void *opaque = NULL; + + if (mz_stream_ioapi_is_open(stream) != MZ_OK) + return MZ_OPEN_ERROR; + + if (ioapi->filefunc.zclose_file) { + zclose = ioapi->filefunc.zclose_file; + opaque = ioapi->filefunc.opaque; + } else if (ioapi->filefunc64.zclose_file) { + zclose = ioapi->filefunc64.zclose_file; + opaque = ioapi->filefunc64.opaque; + } else + return MZ_PARAM_ERROR; + + if (zclose(opaque, ioapi->handle) != 0) + return MZ_CLOSE_ERROR; + ioapi->handle = NULL; + return MZ_OK; +} + +static int32_t mz_stream_ioapi_error(void *stream) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; + testerror_file_func zerror = NULL; + void *opaque = NULL; + + if (mz_stream_ioapi_is_open(stream) != MZ_OK) + return MZ_OPEN_ERROR; + + if (ioapi->filefunc.zerror_file) { + zerror = ioapi->filefunc.zerror_file; + opaque = ioapi->filefunc.opaque; + } else if (ioapi->filefunc64.zerror_file) { + zerror = ioapi->filefunc64.zerror_file; + opaque = ioapi->filefunc64.opaque; + } else + return MZ_PARAM_ERROR; + + return zerror(opaque, ioapi->handle); +} + +int32_t mz_stream_ioapi_set_filefunc(void *stream, zlib_filefunc_def *filefunc) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; + memcpy(&ioapi->filefunc, filefunc, sizeof(zlib_filefunc_def)); + return MZ_OK; +} + +int32_t mz_stream_ioapi_set_filefunc64(void *stream, zlib_filefunc64_def *filefunc) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)stream; + memcpy(&ioapi->filefunc64, filefunc, sizeof(zlib_filefunc64_def)); + return MZ_OK; +} + +void *mz_stream_ioapi_create(void) { + mz_stream_ioapi *ioapi = (mz_stream_ioapi *)calloc(1, sizeof(mz_stream_ioapi)); + if (ioapi) + ioapi->stream.vtbl = &mz_stream_ioapi_vtbl; + return ioapi; +} + +void mz_stream_ioapi_delete(void **stream) { + mz_stream_ioapi *ioapi = NULL; + if (!stream) + return; + ioapi = (mz_stream_ioapi *)*stream; + free(ioapi); + *stream = NULL; +} + +/***************************************************************************/ + +void fill_fopen_filefunc(zlib_filefunc_def *pzlib_filefunc_def) { + /* For 32-bit file support only, compile with MZ_FILE32_API */ + if (pzlib_filefunc_def) + memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc_def)); +} + +void fill_fopen64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def) { + /* All mz_stream_os_* support large files if compilation supports it */ + if (pzlib_filefunc_def) + memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc64_def)); +} + +void fill_win32_filefunc(zlib_filefunc_def *pzlib_filefunc_def) { + /* Handled by mz_stream_os_win32 */ + if (pzlib_filefunc_def) + memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc_def)); +} + +void fill_win32_filefunc64(zlib_filefunc64_def *pzlib_filefunc_def) { + /* Automatically supported in mz_stream_os_win32 */ + if (pzlib_filefunc_def) + memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc64_def)); +} + +void fill_win32_filefunc64A(zlib_filefunc64_def *pzlib_filefunc_def) { + /* Automatically supported in mz_stream_os_win32 */ + if (pzlib_filefunc_def) + memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc64_def)); +} + +/* NOTE: fill_win32_filefunc64W is no longer necessary since wide-character + support is automatically handled by the underlying os stream. Do not + pass wide-characters to zipOpen or unzOpen. */ + +void fill_memory_filefunc(zlib_filefunc_def *pzlib_filefunc_def) { + /* Use opaque to indicate which stream interface to create */ + if (pzlib_filefunc_def) { + memset(pzlib_filefunc_def, 0, sizeof(zlib_filefunc_def)); + pzlib_filefunc_def->opaque = mz_stream_mem_get_interface(); + } +} diff --git a/thirdparty/minizip/compat/ioapi.h b/thirdparty/minizip/compat/ioapi.h new file mode 100644 index 000000000..3f9c654b1 --- /dev/null +++ b/thirdparty/minizip/compat/ioapi.h @@ -0,0 +1,97 @@ + +#ifndef ZLIBIOAPI64_H +#define ZLIBIOAPI64_H + +#include + +typedef uint64_t ZPOS64_T; + +#ifndef ZEXPORT +# define ZEXPORT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +#define ZLIB_FILEFUNC_SEEK_SET (0) +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + +#ifndef ZCALLBACK +# define ZCALLBACK +#endif + +/***************************************************************************/ + +typedef void *(ZCALLBACK *open_file_func)(void *opaque, const char *filename, int mode); +typedef void *(ZCALLBACK *open64_file_func)(void *opaque, const void *filename, int mode); +typedef unsigned long(ZCALLBACK *read_file_func)(void *opaque, void *stream, void *buf, unsigned long size); +typedef unsigned long(ZCALLBACK *write_file_func)(void *opaque, void *stream, const void *buf, unsigned long size); +typedef int(ZCALLBACK *close_file_func)(void *opaque, void *stream); +typedef int(ZCALLBACK *testerror_file_func)(void *opaque, void *stream); +typedef long(ZCALLBACK *tell_file_func)(void *opaque, void *stream); +typedef ZPOS64_T(ZCALLBACK *tell64_file_func)(void *opaque, void *stream); +typedef long(ZCALLBACK *seek_file_func)(void *opaque, void *stream, unsigned long offset, int origin); +typedef long(ZCALLBACK *seek64_file_func)(void *opaque, void *stream, ZPOS64_T offset, int origin); + +/***************************************************************************/ + +typedef struct zlib_filefunc_def_s { + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + void *opaque; +} zlib_filefunc_def; + +typedef struct zlib_filefunc64_def_s { + open64_file_func zopen64_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell64_file_func ztell64_file; + seek64_file_func zseek64_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + void *opaque; +} zlib_filefunc64_def; + +/***************************************************************************/ + +/* Compatibility layer with the original minizip library (ioapi.h and iowin32.h). */ +ZEXPORT void fill_fopen_filefunc(zlib_filefunc_def *pzlib_filefunc_def); +ZEXPORT void fill_fopen64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def); +ZEXPORT void fill_win32_filefunc(zlib_filefunc_def *pzlib_filefunc_def); +ZEXPORT void fill_win32_filefunc64(zlib_filefunc64_def *pzlib_filefunc_def); +ZEXPORT void fill_win32_filefunc64A(zlib_filefunc64_def *pzlib_filefunc_def); + +/* Compatibility layer with older minizip-ng (ioapi_mem.h). */ +ZEXPORT void fill_memory_filefunc(zlib_filefunc_def *pzlib_filefunc_def); + +/***************************************************************************/ + +int32_t mz_stream_ioapi_set_filefunc(void *stream, zlib_filefunc_def *filefunc); +int32_t mz_stream_ioapi_set_filefunc64(void *stream, zlib_filefunc64_def *filefunc); + +void *mz_stream_ioapi_create(void); +void mz_stream_ioapi_delete(void **stream); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/compat/unzip.c b/thirdparty/minizip/compat/unzip.c new file mode 100644 index 000000000..27bc670a0 --- /dev/null +++ b/thirdparty/minizip/compat/unzip.c @@ -0,0 +1,744 @@ +/* zip.c -- Backwards compatible unzip interface + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Copyright (C) 1998-2010 Gilles Vollant + https://www.winimage.com/zLibDll/minizip.html + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_os.h" +#include "mz_strm.h" +#include "mz_strm_os.h" +#include "mz_zip.h" + +#include /* SEEK */ + +#include "unzip.h" + +/***************************************************************************/ + +typedef struct mz_unzip_compat_s { + void *stream; + void *handle; + uint64_t entry_index; + int64_t entry_pos; + int64_t total_out; +} mz_unzip_compat; + +/***************************************************************************/ + +unzFile unzOpen(const char *path) { + return unzOpen64(path); +} + +unzFile unzOpen64(const void *path) { + return unzOpen2(path, NULL); +} + +unzFile unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc_def) { + unzFile unz = NULL; + void *stream = NULL; + + if (pzlib_filefunc_def) { + if (pzlib_filefunc_def->zopen_file) { + stream = mz_stream_ioapi_create(); + if (!stream) + return NULL; + mz_stream_ioapi_set_filefunc(stream, pzlib_filefunc_def); + } else if (pzlib_filefunc_def->opaque) { + stream = mz_stream_create((mz_stream_vtbl *)pzlib_filefunc_def->opaque); + if (!stream) + return NULL; + } + } + + if (!stream) { + stream = mz_stream_os_create(); + if (!stream) + return NULL; + } + + if (mz_stream_open(stream, path, MZ_OPEN_MODE_READ) != MZ_OK) { + mz_stream_delete(&stream); + return NULL; + } + + unz = unzOpen_MZ(stream); + if (!unz) { + mz_stream_close(stream); + mz_stream_delete(&stream); + return NULL; + } + return unz; +} + +unzFile unzOpen2_64(const void *path, zlib_filefunc64_def *pzlib_filefunc_def) { + unzFile unz = NULL; + void *stream = NULL; + + if (pzlib_filefunc_def) { + if (pzlib_filefunc_def->zopen64_file) { + stream = mz_stream_ioapi_create(); + if (!stream) + return NULL; + mz_stream_ioapi_set_filefunc64(stream, pzlib_filefunc_def); + } else if (pzlib_filefunc_def->opaque) { + stream = mz_stream_create((mz_stream_vtbl *)pzlib_filefunc_def->opaque); + if (!stream) + return NULL; + } + } + + if (!stream) { + stream = mz_stream_os_create(); + if (!stream) + return NULL; + } + + if (mz_stream_open(stream, path, MZ_OPEN_MODE_READ) != MZ_OK) { + mz_stream_delete(&stream); + return NULL; + } + + unz = unzOpen_MZ(stream); + if (!unz) { + mz_stream_close(stream); + mz_stream_delete(&stream); + return NULL; + } + return unz; +} + +void *unzGetHandle_MZ(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + if (!compat) + return NULL; + return compat->handle; +} + +void *unzGetStream_MZ(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + if (!compat) + return NULL; + return compat->stream; +} + +unzFile unzOpen_MZ(void *stream) { + mz_unzip_compat *compat = NULL; + int32_t err = MZ_OK; + void *handle = NULL; + + handle = mz_zip_create(); + if (!handle) + return NULL; + + mz_zip_set_recover(handle, 1); + + err = mz_zip_open(handle, stream, MZ_OPEN_MODE_READ); + if (err != MZ_OK) { + mz_zip_delete(&handle); + return NULL; + } + + compat = (mz_unzip_compat *)calloc(1, sizeof(mz_unzip_compat)); + if (compat) { + compat->handle = handle; + compat->stream = stream; + + mz_zip_goto_first_entry(compat->handle); + } else { + mz_zip_delete(&handle); + } + + return (unzFile)compat; +} + +int unzClose(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + int32_t err = MZ_OK; + + if (!compat) + return UNZ_PARAMERROR; + + if (compat->handle) + err = unzClose_MZ(file); + + if (compat->stream) { + mz_stream_close(compat->stream); + mz_stream_delete(&compat->stream); + } + + free(compat); + + return err; +} + +/* Only closes the zip handle, does not close the stream */ +int unzClose_MZ(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + int32_t err = MZ_OK; + + if (!compat) + return UNZ_PARAMERROR; + + err = mz_zip_close(compat->handle); + mz_zip_delete(&compat->handle); + + return err; +} + +int unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info32) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + unz_global_info64 global_info64; + int32_t err = MZ_OK; + + memset(pglobal_info32, 0, sizeof(unz_global_info)); + if (!compat) + return UNZ_PARAMERROR; + + err = unzGetGlobalInfo64(file, &global_info64); + if (err == MZ_OK) { + pglobal_info32->number_entry = (uint32_t)global_info64.number_entry; + pglobal_info32->size_comment = global_info64.size_comment; + pglobal_info32->number_disk_with_CD = global_info64.number_disk_with_CD; + } + return err; +} + +int unzGetGlobalInfo64(unzFile file, unz_global_info64 *pglobal_info) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + const char *comment_ptr = NULL; + int32_t err = MZ_OK; + + memset(pglobal_info, 0, sizeof(unz_global_info64)); + if (!compat) + return UNZ_PARAMERROR; + err = mz_zip_get_comment(compat->handle, &comment_ptr); + if (err == MZ_OK) + pglobal_info->size_comment = (uint16_t)strlen(comment_ptr); + if ((err == MZ_OK) || (err == MZ_EXIST_ERROR)) + err = mz_zip_get_number_entry(compat->handle, &pglobal_info->number_entry); + if (err == MZ_OK) + err = mz_zip_get_disk_number_with_cd(compat->handle, &pglobal_info->number_disk_with_CD); + return err; +} + +int unzGetGlobalComment(unzFile file, char *comment, unsigned long comment_size) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + const char *comment_ptr = NULL; + int32_t err = MZ_OK; + + if (!comment || !comment_size) + return UNZ_PARAMERROR; + err = mz_zip_get_comment(compat->handle, &comment_ptr); + if (err == MZ_OK) { + strncpy(comment, comment_ptr, comment_size - 1); + comment[comment_size - 1] = 0; + } + return err; +} + +int unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + mz_zip_file *file_info = NULL; + int32_t err = MZ_OK; + void *stream = NULL; + + if (!compat) + return UNZ_PARAMERROR; + if (method) + *method = 0; + if (level) + *level = 0; + + if (mz_zip_entry_is_open(compat->handle) == MZ_OK) { + /* zlib minizip does not error out here if close returns errors */ + unzCloseCurrentFile(file); + } + + compat->total_out = 0; + err = mz_zip_entry_read_open(compat->handle, (uint8_t)raw, password); + if (err == MZ_OK) + err = mz_zip_entry_get_info(compat->handle, &file_info); + if (err == MZ_OK) { + if (method) { + *method = file_info->compression_method; + } + + if (level) { + *level = 6; + switch (file_info->flag & 0x06) { + case MZ_ZIP_FLAG_DEFLATE_SUPER_FAST: + *level = 1; + break; + case MZ_ZIP_FLAG_DEFLATE_FAST: + *level = 2; + break; + case MZ_ZIP_FLAG_DEFLATE_MAX: + *level = 9; + break; + } + } + } + if (err == MZ_OK) + err = mz_zip_get_stream(compat->handle, &stream); + if (err == MZ_OK) + compat->entry_pos = mz_stream_tell(stream); + return err; +} + +int unzOpenCurrentFile(unzFile file) { + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +int unzOpenCurrentFilePassword(unzFile file, const char *password) { + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +int unzOpenCurrentFile2(unzFile file, int *method, int *level, int raw) { + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +int unzReadCurrentFile(unzFile file, void *buf, uint32_t len) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + int32_t err = MZ_OK; + if (!compat || len >= INT32_MAX) + return UNZ_PARAMERROR; + err = mz_zip_entry_read(compat->handle, buf, (int32_t)len); + if (err > 0) + compat->total_out += (uint32_t)err; + return err; +} + +int unzCloseCurrentFile(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + int32_t err = MZ_OK; + if (!compat) + return UNZ_PARAMERROR; + err = mz_zip_entry_close(compat->handle); + return err; +} + +static void unzConvertTimeToUnzTime(time_t time, tm_unz *tmu_date) { + struct tm tm_date; + memset(&tm_date, 0, sizeof(struct tm)); + mz_zip_time_t_to_tm(time, &tm_date); + memcpy(tmu_date, &tm_date, sizeof(tm_unz)); + tmu_date->tm_year += 1900; +} + +int unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *filename, unsigned long filename_size, + void *extrafield, unsigned long extrafield_size, char *comment, unsigned long comment_size) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + mz_zip_file *file_info = NULL; + uint16_t bytes_to_copy = 0; + int32_t err = MZ_OK; + + if (!compat) + return UNZ_PARAMERROR; + + err = mz_zip_entry_get_info(compat->handle, &file_info); + if (err != MZ_OK) + return err; + + if (pfile_info) { + pfile_info->version = file_info->version_madeby; + pfile_info->version_needed = file_info->version_needed; + pfile_info->flag = file_info->flag; + pfile_info->compression_method = file_info->compression_method; + pfile_info->mz_dos_date = mz_zip_time_t_to_dos_date(file_info->modified_date); + unzConvertTimeToUnzTime(file_info->modified_date, &pfile_info->tmu_date); + pfile_info->crc = file_info->crc; + + pfile_info->size_filename = file_info->filename_size; + pfile_info->size_file_extra = file_info->extrafield_size; + pfile_info->size_file_comment = file_info->comment_size; + + pfile_info->disk_num_start = (uint16_t)file_info->disk_number; + pfile_info->internal_fa = file_info->internal_fa; + pfile_info->external_fa = file_info->external_fa; + + pfile_info->compressed_size = (uint32_t)file_info->compressed_size; + pfile_info->uncompressed_size = (uint32_t)file_info->uncompressed_size; + } + if (filename_size > 0 && filename && file_info->filename) { + bytes_to_copy = (uint16_t)filename_size; + if (bytes_to_copy > file_info->filename_size) + bytes_to_copy = file_info->filename_size; + memcpy(filename, file_info->filename, bytes_to_copy); + if (bytes_to_copy < filename_size) + filename[bytes_to_copy] = 0; + } + if (extrafield_size > 0 && extrafield) { + bytes_to_copy = (uint16_t)extrafield_size; + if (bytes_to_copy > file_info->extrafield_size) + bytes_to_copy = file_info->extrafield_size; + memcpy(extrafield, file_info->extrafield, bytes_to_copy); + } + if (comment_size > 0 && comment && file_info->comment) { + bytes_to_copy = (uint16_t)comment_size; + if (bytes_to_copy > file_info->comment_size) + bytes_to_copy = file_info->comment_size; + memcpy(comment, file_info->comment, bytes_to_copy); + if (bytes_to_copy < comment_size) + comment[bytes_to_copy] = 0; + } + return err; +} + +int unzGetCurrentFileInfo64(unzFile file, unz_file_info64 *pfile_info, char *filename, unsigned long filename_size, + void *extrafield, unsigned long extrafield_size, char *comment, + unsigned long comment_size) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + mz_zip_file *file_info = NULL; + uint16_t bytes_to_copy = 0; + int32_t err = MZ_OK; + + if (!compat) + return UNZ_PARAMERROR; + + err = mz_zip_entry_get_info(compat->handle, &file_info); + if (err != MZ_OK) + return err; + + if (pfile_info) { + pfile_info->version = file_info->version_madeby; + pfile_info->version_needed = file_info->version_needed; + pfile_info->flag = file_info->flag; + pfile_info->compression_method = file_info->compression_method; + pfile_info->mz_dos_date = mz_zip_time_t_to_dos_date(file_info->modified_date); + unzConvertTimeToUnzTime(file_info->modified_date, &pfile_info->tmu_date); + pfile_info->crc = file_info->crc; + + pfile_info->size_filename = file_info->filename_size; + pfile_info->size_file_extra = file_info->extrafield_size; + pfile_info->size_file_comment = file_info->comment_size; + + pfile_info->disk_num_start = file_info->disk_number; + pfile_info->internal_fa = file_info->internal_fa; + pfile_info->external_fa = file_info->external_fa; + + pfile_info->compressed_size = (uint64_t)file_info->compressed_size; + pfile_info->uncompressed_size = (uint64_t)file_info->uncompressed_size; + } + if (filename_size > 0 && filename && file_info->filename) { + bytes_to_copy = (uint16_t)filename_size; + if (bytes_to_copy > file_info->filename_size) + bytes_to_copy = file_info->filename_size; + memcpy(filename, file_info->filename, bytes_to_copy); + if (bytes_to_copy < filename_size) + filename[bytes_to_copy] = 0; + } + if (extrafield_size > 0 && extrafield) { + bytes_to_copy = (uint16_t)extrafield_size; + if (bytes_to_copy > file_info->extrafield_size) + bytes_to_copy = file_info->extrafield_size; + memcpy(extrafield, file_info->extrafield, bytes_to_copy); + } + if (comment_size > 0 && comment && file_info->comment) { + bytes_to_copy = (uint16_t)comment_size; + if (bytes_to_copy > file_info->comment_size) + bytes_to_copy = file_info->comment_size; + memcpy(comment, file_info->comment, bytes_to_copy); + if (bytes_to_copy < comment_size) + comment[bytes_to_copy] = 0; + } + return err; +} + +int unzGoToFirstFile(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + if (!compat) + return UNZ_PARAMERROR; + compat->entry_index = 0; + return mz_zip_goto_first_entry(compat->handle); +} + +int unzGoToNextFile(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + int32_t err = MZ_OK; + if (!compat) + return UNZ_PARAMERROR; + err = mz_zip_goto_next_entry(compat->handle); + if (err != MZ_END_OF_LIST) + compat->entry_index += 1; + return err; +} + +#if !defined(MZ_COMPAT_VERSION) || MZ_COMPAT_VERSION < 110 +# ifdef WIN32 +# define UNZ_DEFAULT_IGNORE_CASE 1 +# else +# define UNZ_DEFAULT_IGNORE_CASE 0 +# endif + +int unzLocateFile(unzFile file, const char *filename, unzFileNameCase filename_case) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + mz_zip_file *file_info = NULL; + uint64_t preserve_index = 0; + int32_t err = MZ_OK; + int32_t result = 0; + uint8_t ignore_case = UNZ_DEFAULT_IGNORE_CASE; + + if (!compat) + return UNZ_PARAMERROR; + + if (filename_case == 1) { + ignore_case = 0; + } else if (filename_case > 1) { + ignore_case = 1; + } + + preserve_index = compat->entry_index; + + err = mz_zip_goto_first_entry(compat->handle); + while (err == MZ_OK) { + err = mz_zip_entry_get_info(compat->handle, &file_info); + if (err != MZ_OK) + break; + + result = mz_path_compare_wc(filename, file_info->filename, !ignore_case); + + if (result == 0) + return MZ_OK; + + err = mz_zip_goto_next_entry(compat->handle); + } + + compat->entry_index = preserve_index; + return err; +} +#else +int unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filename_compare_func) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + mz_zip_file *file_info = NULL; + uint64_t preserve_index = 0; + int32_t err = MZ_OK; + int32_t result = 0; + + if (!compat) + return UNZ_PARAMERROR; + + preserve_index = compat->entry_index; + + err = mz_zip_goto_first_entry(compat->handle); + while (err == MZ_OK) { + err = mz_zip_entry_get_info(compat->handle, &file_info); + if (err != MZ_OK) + break; + + if ((intptr_t)filename_compare_func > 2) { + result = filename_compare_func(file, filename, file_info->filename); + } else { + int32_t case_sensitive = (int32_t)(intptr_t)filename_compare_func; + result = mz_path_compare_wc(filename, file_info->filename, !case_sensitive); + } + + if (result == 0) + return MZ_OK; + + err = mz_zip_goto_next_entry(compat->handle); + } + + compat->entry_index = preserve_index; + return err; +} +#endif + +/***************************************************************************/ + +int unzGetFilePos(unzFile file, unz_file_pos *file_pos) { + unz64_file_pos file_pos64; + int32_t err = 0; + + err = unzGetFilePos64(file, &file_pos64); + if (err < 0) + return err; + + file_pos->pos_in_zip_directory = (uint32_t)file_pos64.pos_in_zip_directory; + file_pos->num_of_file = (uint32_t)file_pos64.num_of_file; + return err; +} + +int unzGoToFilePos(unzFile file, unz_file_pos *file_pos) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + unz64_file_pos file_pos64; + + if (!compat || !file_pos) + return UNZ_PARAMERROR; + + file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; + file_pos64.num_of_file = file_pos->num_of_file; + + return unzGoToFilePos64(file, &file_pos64); +} + +int unzGetFilePos64(unzFile file, unz64_file_pos *file_pos) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + int64_t offset = 0; + + if (!compat || !file_pos) + return UNZ_PARAMERROR; + + offset = unzGetOffset64(file); + if (offset < 0) + return (int)offset; + + file_pos->pos_in_zip_directory = offset; + file_pos->num_of_file = compat->entry_index; + return UNZ_OK; +} + +int unzGoToFilePos64(unzFile file, const unz64_file_pos *file_pos) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + int32_t err = MZ_OK; + + if (!compat || !file_pos) + return UNZ_PARAMERROR; + + err = mz_zip_goto_entry(compat->handle, file_pos->pos_in_zip_directory); + if (err == MZ_OK) + compat->entry_index = file_pos->num_of_file; + return err; +} + +unsigned long unzGetOffset(unzFile file) { + return (uint32_t)unzGetOffset64(file); +} + +int64_t unzGetOffset64(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + if (!compat) + return UNZ_PARAMERROR; + return mz_zip_get_entry(compat->handle); +} + +int unzSetOffset(unzFile file, unsigned long pos) { + return unzSetOffset64(file, pos); +} + +int unzSetOffset64(unzFile file, int64_t pos) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + if (!compat) + return UNZ_PARAMERROR; + return (int)mz_zip_goto_entry(compat->handle, pos); +} + +uint64_t unzGetCurrentFileZStreamPos64(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + if (!compat || mz_zip_entry_is_open(compat->handle) != MZ_OK) + return 0; + return (uint64_t)compat->entry_pos; +} + +int unzGetLocalExtrafield(unzFile file, void *buf, unsigned int len) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + mz_zip_file *file_info = NULL; + int32_t err = MZ_OK; + int32_t bytes_to_copy = 0; + + if (!compat || !buf || len >= INT32_MAX) + return UNZ_PARAMERROR; + + err = mz_zip_entry_get_local_info(compat->handle, &file_info); + if (err != MZ_OK) + return err; + + bytes_to_copy = (int32_t)len; + if (bytes_to_copy > file_info->extrafield_size) + bytes_to_copy = file_info->extrafield_size; + + memcpy(buf, file_info->extrafield, bytes_to_copy); + return MZ_OK; +} + +int32_t unzTell(unzFile file) { + return unztell(file); +} + +int32_t unztell(unzFile file) { + return (int32_t)unztell64(file); +} + +uint64_t unzTell64(unzFile file) { + return unztell64(file); +} + +uint64_t unztell64(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + if (!compat) + return UNZ_PARAMERROR; + return compat->total_out; +} + +int unzSeek(unzFile file, int32_t offset, int origin) { + return unzSeek64(file, offset, origin); +} + +int unzSeek64(unzFile file, int64_t offset, int origin) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + mz_zip_file *file_info = NULL; + int64_t position = 0; + int32_t err = MZ_OK; + void *stream = NULL; + + if (!compat) + return UNZ_PARAMERROR; + err = mz_zip_entry_get_info(compat->handle, &file_info); + if (err != MZ_OK) + return err; + if (file_info->compression_method != MZ_COMPRESS_METHOD_STORE) + return UNZ_ERRNO; + + if (origin == SEEK_SET) + position = offset; + else if (origin == SEEK_CUR) + position = compat->total_out + offset; + else if (origin == SEEK_END) + position = (int64_t)file_info->compressed_size + offset; + else + return UNZ_PARAMERROR; + + if (position > (int64_t)file_info->compressed_size) + return UNZ_PARAMERROR; + + err = mz_zip_get_stream(compat->handle, &stream); + if (err == MZ_OK) + err = mz_stream_seek(stream, compat->entry_pos + position, MZ_SEEK_SET); + if (err == MZ_OK) + compat->total_out = position; + return err; +} + +int unzEndOfFile(unzFile file) { + return unzeof(file); +} + +int unzeof(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + mz_zip_file *file_info = NULL; + int32_t err = MZ_OK; + + if (!compat) + return UNZ_PARAMERROR; + err = mz_zip_entry_get_info(compat->handle, &file_info); + if (err != MZ_OK) + return err; + if (compat->total_out == (int64_t)file_info->uncompressed_size) + return 1; + return 0; +} + +void *unzGetStream(unzFile file) { + mz_unzip_compat *compat = (mz_unzip_compat *)file; + if (!compat) + return NULL; + return (void *)compat->stream; +} + +/***************************************************************************/ diff --git a/thirdparty/minizip/compat/unzip.h b/thirdparty/minizip/compat/unzip.h new file mode 100644 index 000000000..28548ab27 --- /dev/null +++ b/thirdparty/minizip/compat/unzip.h @@ -0,0 +1,239 @@ +/* unzip.h -- Backwards compatible unzip interface + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Copyright (C) 1998-2010 Gilles Vollant + https://www.winimage.com/zLibDll/minizip.html + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef _unz64_H +#define _unz64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#if !defined(_ZLIB_H) && !defined(ZLIB_H) && !defined(ZLIB_H_) +# if __has_include() +# include +# elif __has_include() +# include +# endif +#endif + +#ifndef _ZLIBIOAPI_H +# include "ioapi.h" +#endif + +/***************************************************************************/ + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { + int unused; +} unzFile__; +typedef unzFile__ *unzFile; +#else +typedef void *unzFile; +#endif + +/***************************************************************************/ + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (-1) /* Z_ERRNO */ +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) +#define UNZ_BADPASSWORD (-106) /* minizip-ng */ + +/***************************************************************************/ +/* tm_unz contain date/time info */ +typedef struct tm_unz_s { + int tm_sec; /* seconds after the minute - [0,59] */ + int tm_min; /* minutes after the hour - [0,59] */ + int tm_hour; /* hours since midnight - [0,23] */ + int tm_mday; /* day of the month - [1,31] */ + int tm_mon; /* months since January - [0,11] */ + int tm_year; /* years - [1980..2044] */ +} tm_unz; + +/***************************************************************************/ + +#if !defined(MZ_COMPAT_VERSION) || MZ_COMPAT_VERSION <= 110 +# define mz_dos_date dosDate +#else +# define mz_dos_date dos_date +#endif + +/* Global data about the zip from end of central dir */ +typedef struct unz_global_info64_s { + uint64_t number_entry; /* total number of entries in the central dir on this disk */ + unsigned long size_comment; /* size of the global comment of the zipfile */ + /* minizip-ng fields */ + uint32_t number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP */ +} unz_global_info64; + +typedef struct unz_global_info_s { + unsigned long number_entry; /* total number of entries in the central dir on this disk */ + unsigned long size_comment; /* size of the global comment of the zipfile */ + /* minizip-ng fields */ + uint32_t number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP */ +} unz_global_info; + +/* Information about a file in the zip */ +typedef struct unz_file_info64_s { + unsigned long version; /* version made by 2 bytes */ + unsigned long version_needed; /* version needed to extract 2 bytes */ + unsigned long flag; /* general purpose bit flag 2 bytes */ + unsigned long compression_method; /* compression method 2 bytes */ + unsigned long mz_dos_date; /* last mod file date in Dos fmt 4 bytes */ + unsigned long crc; /* crc-32 4 bytes */ + ZPOS64_T compressed_size; /* compressed size 8 bytes */ + ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ + unsigned long size_filename; /* filename length 2 bytes */ + unsigned long size_file_extra; /* extra field length 2 bytes */ + unsigned long size_file_comment; /* file comment length 2 bytes */ + + unsigned long disk_num_start; /* disk number start 4 bytes */ + unsigned long internal_fa; /* internal file attributes 2 bytes */ + unsigned long external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; + + /* minizip-ng fields */ + ZPOS64_T disk_offset; + uint16_t size_file_extra_internal; +} unz_file_info64; + +typedef struct unz_file_info_s { + unsigned long version; /* version made by 2 bytes */ + unsigned long version_needed; /* version needed to extract 2 bytes */ + unsigned long flag; /* general purpose bit flag 2 bytes */ + unsigned long compression_method; /* compression method 2 bytes */ + unsigned long mz_dos_date; /* last mod file date in Dos fmt 4 bytes */ + unsigned long crc; /* crc-32 4 bytes */ + ZPOS64_T compressed_size; /* compressed size 4 bytes */ + ZPOS64_T uncompressed_size; /* uncompressed size 4 bytes */ + unsigned long size_filename; /* filename length 2 bytes */ + unsigned long size_file_extra; /* extra field length 2 bytes */ + unsigned long size_file_comment; /* file comment length 2 bytes */ + + unsigned long disk_num_start; /* disk number start 2 bytes */ + unsigned long internal_fa; /* internal file attributes 2 bytes */ + unsigned long external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; + + /* minizip-ng fields */ + ZPOS64_T disk_offset; +} unz_file_info; + +/***************************************************************************/ + +#if !defined(MZ_COMPAT_VERSION) || MZ_COMPAT_VERSION < 110 +/* Possible values: + 0 - Uses OS default, e.g. Windows ignores case. + 1 - Is case sensitive. + >= 2 - Ignore case. +*/ +typedef int unzFileNameCase; +#else +typedef int (*unzFileNameComparer)(unzFile file, const char *filename1, const char *filename2); +#endif +typedef int (*unzIteratorFunction)(unzFile file); +typedef int (*unzIteratorFunction2)(unzFile file, unz_file_info64 *pfile_info, char *filename, uint16_t filename_size, + void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size); + +/***************************************************************************/ +/* Reading a zip file */ + +/* Compatibility layer with the original minizip library (unzip.h). */ +ZEXPORT unzFile unzOpen(const char *path); +ZEXPORT unzFile unzOpen64(const void *path); +ZEXPORT unzFile unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc_def); +ZEXPORT unzFile unzOpen2_64(const void *path, zlib_filefunc64_def *pzlib_filefunc_def); +ZEXPORT int unzClose(unzFile file); + +ZEXPORT int unzGetGlobalInfo(unzFile file, unz_global_info *pglobal_info32); +ZEXPORT int unzGetGlobalInfo64(unzFile file, unz_global_info64 *pglobal_info); +ZEXPORT int unzGetGlobalComment(unzFile file, char *comment, unsigned long comment_size); +ZEXPORT int unzOpenCurrentFile(unzFile file); +ZEXPORT int unzOpenCurrentFilePassword(unzFile file, const char *password); +ZEXPORT int unzOpenCurrentFile2(unzFile file, int *method, int *level, int raw); +ZEXPORT int unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password); +ZEXPORT int unzReadCurrentFile(unzFile file, void *buf, uint32_t len); +ZEXPORT int unzCloseCurrentFile(unzFile file); +ZEXPORT int unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *filename, unsigned long filename_size, + void *extrafield, unsigned long extrafield_size, char *comment, + unsigned long comment_size); +ZEXPORT int unzGetCurrentFileInfo64(unzFile file, unz_file_info64 *pfile_info, char *filename, + unsigned long filename_size, void *extrafield, unsigned long extrafield_size, + char *comment, unsigned long comment_size); +ZEXPORT int unzGoToFirstFile(unzFile file); +ZEXPORT int unzGoToNextFile(unzFile file); +#if !defined(MZ_COMPAT_VERSION) || MZ_COMPAT_VERSION < 110 +ZEXPORT int unzLocateFile(unzFile file, const char *filename, unzFileNameCase filename_case); +#else +ZEXPORT int unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filename_compare_func); +#endif +/* unzStringFileNameCompare is too new */ +ZEXPORT int unzGetLocalExtrafield(unzFile file, void *buf, unsigned int len); + +/* Compatibility layer with older minizip-ng (mz_unzip.h). */ +unzFile unzOpen_MZ(void *stream); +ZEXPORT int unzClose_MZ(unzFile file); +ZEXPORT void *unzGetHandle_MZ(unzFile file); +ZEXPORT void *unzGetStream_MZ(unzFile file); + +/***************************************************************************/ +/* Raw access to zip file */ + +typedef struct unz_file_pos_s { + uint32_t pos_in_zip_directory; /* offset in zip file directory */ + uint32_t num_of_file; /* # of file */ +} unz_file_pos; + +typedef struct unz64_file_pos_s { + int64_t pos_in_zip_directory; /* offset in zip file directory */ + uint64_t num_of_file; /* # of file */ +} unz64_file_pos; + +/* Compatibility layer with the original minizip library (unzip.h). */ +ZEXPORT int unzGetFilePos(unzFile file, unz_file_pos *file_pos); +ZEXPORT int unzGoToFilePos(unzFile file, unz_file_pos *file_pos); +ZEXPORT int unzGetFilePos64(unzFile file, unz64_file_pos *file_pos); +ZEXPORT int unzGoToFilePos64(unzFile file, const unz64_file_pos *file_pos); +ZEXPORT int64_t unzGetOffset64(unzFile file); +ZEXPORT unsigned long unzGetOffset(unzFile file); +ZEXPORT int unzSetOffset64(unzFile file, int64_t pos); +ZEXPORT int unzSetOffset(unzFile file, unsigned long pos); +ZEXPORT uint64_t unzGetCurrentFileZStreamPos64(unzFile file); +ZEXPORT int32_t unztell(unzFile file); +ZEXPORT uint64_t unztell64(unzFile file); +ZEXPORT int unzeof(unzFile file); + +/* Compatibility layer with older minizip-ng (mz_unzip.h). */ +ZEXPORT int32_t unzTell(unzFile file); +ZEXPORT uint64_t unzTell64(unzFile file); +ZEXPORT int unzSeek(unzFile file, int32_t offset, int origin); +ZEXPORT int unzSeek64(unzFile file, int64_t offset, int origin); +ZEXPORT int unzEndOfFile(unzFile file); +ZEXPORT void *unzGetStream(unzFile file); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* _unz64_H */ diff --git a/thirdparty/minizip/compat/zip.c b/thirdparty/minizip/compat/zip.c new file mode 100644 index 000000000..762ca1f31 --- /dev/null +++ b/thirdparty/minizip/compat/zip.c @@ -0,0 +1,407 @@ +/* zip.c -- Backwards compatible zip interface + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Copyright (C) 1998-2010 Gilles Vollant + https://www.winimage.com/zLibDll/minizip.html + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_os.h" +#include "mz_strm.h" +#include "mz_strm_os.h" +#include "mz_zip.h" + +#include "zip.h" + +/***************************************************************************/ + +typedef struct mz_zip_compat_s { + void *stream; + void *handle; +} mz_zip_compat; + +/***************************************************************************/ + +static int32_t zipConvertAppendToStreamMode(int append) { + int32_t mode = MZ_OPEN_MODE_WRITE; + switch (append) { + case APPEND_STATUS_CREATE: + mode |= MZ_OPEN_MODE_CREATE; + break; + case APPEND_STATUS_CREATEAFTER: + mode |= MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_APPEND; + break; + case APPEND_STATUS_ADDINZIP: + mode |= MZ_OPEN_MODE_READ | MZ_OPEN_MODE_APPEND; + break; + } + return mode; +} + +zipFile zipOpen(const char *path, int append) { + return zipOpen2(path, append, NULL, NULL); +} + +zipFile zipOpen64(const void *path, int append) { + return zipOpen2(path, append, NULL, NULL); +} + +zipFile zipOpen2(const char *path, int append, zipcharpc *globalcomment, zlib_filefunc_def *pzlib_filefunc_def) { + zipFile zip = NULL; + int32_t mode = zipConvertAppendToStreamMode(append); + void *stream = NULL; + + if (pzlib_filefunc_def) { + if (pzlib_filefunc_def->zopen_file) { + stream = mz_stream_ioapi_create(); + if (!stream) + return NULL; + mz_stream_ioapi_set_filefunc(stream, pzlib_filefunc_def); + } else if (pzlib_filefunc_def->opaque) { + stream = mz_stream_create((mz_stream_vtbl *)pzlib_filefunc_def->opaque); + if (!stream) + return NULL; + } + } + + if (!stream) { + stream = mz_stream_os_create(); + if (!stream) + return NULL; + } + + if (mz_stream_open(stream, path, mode) != MZ_OK) { + mz_stream_delete(&stream); + return NULL; + } + + zip = zipOpen_MZ(stream, append, globalcomment); + + if (!zip) { + mz_stream_delete(&stream); + return NULL; + } + + return zip; +} + +zipFile zipOpen2_64(const void *path, int append, zipcharpc *globalcomment, zlib_filefunc64_def *pzlib_filefunc_def) { + zipFile zip = NULL; + int32_t mode = zipConvertAppendToStreamMode(append); + void *stream = NULL; + + if (pzlib_filefunc_def) { + if (pzlib_filefunc_def->zopen64_file) { + stream = mz_stream_ioapi_create(); + if (!stream) + return NULL; + mz_stream_ioapi_set_filefunc64(stream, pzlib_filefunc_def); + } else if (pzlib_filefunc_def->opaque) { + stream = mz_stream_create((mz_stream_vtbl *)pzlib_filefunc_def->opaque); + if (!stream) + return NULL; + } + } + + if (!stream) { + stream = mz_stream_os_create(); + if (!stream) + return NULL; + } + + if (mz_stream_open(stream, path, mode) != MZ_OK) { + mz_stream_delete(&stream); + return NULL; + } + + zip = zipOpen_MZ(stream, append, globalcomment); + + if (!zip) { + mz_stream_delete(&stream); + return NULL; + } + + return zip; +} + +zipFile zipOpen_MZ(void *stream, int append, zipcharpc *globalcomment) { + mz_zip_compat *compat = NULL; + int32_t err = MZ_OK; + int32_t mode = zipConvertAppendToStreamMode(append); + void *handle = NULL; + + handle = mz_zip_create(); + if (!handle) + return NULL; + + err = mz_zip_open(handle, stream, mode); + + if (err != MZ_OK) { + mz_zip_delete(&handle); + return NULL; + } + + if (globalcomment) + mz_zip_get_comment(handle, globalcomment); + + compat = (mz_zip_compat *)calloc(1, sizeof(mz_zip_compat)); + if (compat) { + compat->handle = handle; + compat->stream = stream; + } else { + mz_zip_delete(&handle); + } + + return (zipFile)compat; +} + +void *zipGetHandle_MZ(zipFile file) { + mz_zip_compat *compat = (mz_zip_compat *)file; + if (!compat) + return NULL; + return compat->handle; +} + +void *zipGetStream_MZ(zipFile file) { + mz_zip_compat *compat = (mz_zip_compat *)file; + if (!compat) + return NULL; + return (void *)compat->stream; +} + +static time_t zipConvertZipDateToTime(tm_zip tmz_date) { + struct tm tm_date; + memset(&tm_date, 0, sizeof(struct tm)); + memcpy(&tm_date, &tmz_date, sizeof(tm_zip)); + return mz_zip_dosdate_to_time_t(mz_zip_tm_to_dosdate(&tm_date)); +} + +int zipOpenNewFileInZip5(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, + uint16_t size_extrafield_local, const void *extrafield_global, uint16_t size_extrafield_global, + const char *comment, int compression_method, int level, int raw, int windowBits, int memLevel, + int strategy, const char *password, unsigned long crc_for_crypting, + unsigned long version_madeby, unsigned long flag_base, int zip64) { + mz_zip_compat *compat = (mz_zip_compat *)file; + mz_zip_file file_info; + + MZ_UNUSED(strategy); + MZ_UNUSED(memLevel); + MZ_UNUSED(windowBits); + MZ_UNUSED(size_extrafield_local); + MZ_UNUSED(extrafield_local); + MZ_UNUSED(crc_for_crypting); + + if (!compat) + return ZIP_PARAMERROR; + + /* The filename and comment length must fit in 16 bits. */ + if (filename && strlen(filename) > 0xffff) + return ZIP_PARAMERROR; + if (comment && strlen(comment) > 0xffff) + return ZIP_PARAMERROR; + + memset(&file_info, 0, sizeof(file_info)); + + if (zipfi) { + if (zipfi->mz_dos_date != 0) + file_info.modified_date = mz_zip_dosdate_to_time_t(zipfi->mz_dos_date); + else + file_info.modified_date = zipConvertZipDateToTime(zipfi->tmz_date); + + file_info.external_fa = (uint32_t)zipfi->external_fa; + file_info.internal_fa = (uint16_t)zipfi->internal_fa; + } + + if (!filename) + filename = "-"; + + file_info.compression_method = (uint16_t)compression_method; + file_info.filename = filename; + /* file_info.extrafield_local = extrafield_local; */ + /* file_info.extrafield_local_size = size_extrafield_local; */ + file_info.extrafield = extrafield_global; + file_info.extrafield_size = size_extrafield_global; + file_info.version_madeby = (uint16_t)version_madeby; + file_info.comment = comment; + if (file_info.comment) + file_info.comment_size = (uint16_t)strlen(file_info.comment); + file_info.flag = (uint16_t)flag_base; + if (zip64) + file_info.zip64 = MZ_ZIP64_FORCE; + else + file_info.zip64 = MZ_ZIP64_DISABLE; +#ifdef HAVE_WZAES + if (password || (raw && (file_info.flag & MZ_ZIP_FLAG_ENCRYPTED))) + file_info.aes_version = MZ_AES_VERSION; +#endif + + return mz_zip_entry_write_open(compat->handle, &file_info, (int16_t)level, (uint8_t)raw, password); +} + +int zipOpenNewFileInZip4_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, + uint16_t size_extrafield_local, const void *extrafield_global, + uint16_t size_extrafield_global, const char *comment, int compression_method, int level, + int raw, int windowBits, int memLevel, int strategy, const char *password, + unsigned long crc_for_crypting, unsigned long version_madeby, unsigned long flag_base, + int zip64) { + return zipOpenNewFileInZip5(file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, + size_extrafield_global, comment, compression_method, level, raw, windowBits, memLevel, + strategy, password, crc_for_crypting, version_madeby, flag_base, zip64); +} + +int zipOpenNewFileInZip4(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, + uint16_t size_extrafield_local, const void *extrafield_global, uint16_t size_extrafield_global, + const char *comment, int compression_method, int level, int raw, int windowBits, int memLevel, + int strategy, const char *password, unsigned long crc_for_crypting, + unsigned long version_madeby, unsigned long flag_base) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, + size_extrafield_global, comment, compression_method, level, raw, windowBits, + memLevel, strategy, password, crc_for_crypting, version_madeby, flag_base, 0); +} + +int zipOpenNewFileInZip3(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, + uint16_t size_extrafield_local, const void *extrafield_global, uint16_t size_extrafield_global, + const char *comment, int compression_method, int level, int raw, int windowBits, int memLevel, + int strategy, const char *password, unsigned long crc_for_crypting) { + return zipOpenNewFileInZip3_64(file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, + size_extrafield_global, comment, compression_method, level, raw, windowBits, + memLevel, strategy, password, crc_for_crypting, 0); +} + +int zipOpenNewFileInZip3_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, + uint16_t size_extrafield_local, const void *extrafield_global, + uint16_t size_extrafield_global, const char *comment, int compression_method, int level, + int raw, int windowBits, int memLevel, int strategy, const char *password, + unsigned long crc_for_crypting, int zip64) { + return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, + size_extrafield_global, comment, compression_method, level, raw, windowBits, + memLevel, strategy, password, crc_for_crypting, MZ_VERSION_MADEBY, 0, zip64); +} + +int zipOpenNewFileInZip2(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, + uint16_t size_extrafield_local, const void *extrafield_global, uint16_t size_extrafield_global, + const char *comment, int compression_method, int level, int raw) { + return zipOpenNewFileInZip3_64(file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, + size_extrafield_global, comment, compression_method, level, raw, 0, 0, 0, NULL, 0, + 0); +} + +int zipOpenNewFileInZip2_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, + uint16_t size_extrafield_local, const void *extrafield_global, + uint16_t size_extrafield_global, const char *comment, int compression_method, int level, + int raw, int zip64) { + return zipOpenNewFileInZip3_64(file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, + size_extrafield_global, comment, compression_method, level, raw, 0, 0, 0, NULL, 0, + zip64); +} + +int zipOpenNewFileInZip(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, + uint16_t size_extrafield_local, const void *extrafield_global, uint16_t size_extrafield_global, + const char *comment, int compression_method, int level) { + return zipOpenNewFileInZip_64(file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, + size_extrafield_global, comment, compression_method, level, 0); +} + +int zipOpenNewFileInZip64(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, + uint16_t size_extrafield_local, const void *extrafield_global, + uint16_t size_extrafield_global, const char *comment, int compression_method, int level, + int zip64) { + return zipOpenNewFileInZip2_64(file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, + size_extrafield_global, comment, compression_method, level, 0, zip64); +} + +int zipOpenNewFileInZip_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, const void *extrafield_local, + uint16_t size_extrafield_local, const void *extrafield_global, + uint16_t size_extrafield_global, const char *comment, int compression_method, int level, + int zip64) { + return zipOpenNewFileInZip2_64(file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, + size_extrafield_global, comment, compression_method, level, 0, zip64); +} + +int zipWriteInFileInZip(zipFile file, const void *buf, uint32_t len) { + mz_zip_compat *compat = (mz_zip_compat *)file; + int32_t written = 0; + if (!compat || len >= INT32_MAX) + return ZIP_PARAMERROR; + written = mz_zip_entry_write(compat->handle, buf, (int32_t)len); + if ((written < 0) || ((uint32_t)written != len)) + return ZIP_ERRNO; + return ZIP_OK; +} + +int zipCloseFileInZipRaw(zipFile file, unsigned long uncompressed_size, unsigned long crc32) { + return zipCloseFileInZipRaw64(file, uncompressed_size, crc32); +} + +int zipCloseFileInZipRaw64(zipFile file, uint64_t uncompressed_size, unsigned long crc32) { + mz_zip_compat *compat = (mz_zip_compat *)file; + if (!compat) + return ZIP_PARAMERROR; + return mz_zip_entry_close_raw(compat->handle, (int64_t)uncompressed_size, (uint32_t)crc32); +} + +int zipCloseFileInZip(zipFile file) { + return zipCloseFileInZip64(file); +} + +int zipCloseFileInZip64(zipFile file) { + mz_zip_compat *compat = (mz_zip_compat *)file; + if (!compat) + return ZIP_PARAMERROR; + return mz_zip_entry_close(compat->handle); +} + +int zipClose(zipFile file, const char *global_comment) { + return zipClose_64(file, global_comment); +} + +int zipClose_64(zipFile file, const char *global_comment) { + return zipClose2_64(file, global_comment, MZ_VERSION_MADEBY); +} + +int zipClose2_64(zipFile file, const char *global_comment, uint16_t version_madeby) { + mz_zip_compat *compat = (mz_zip_compat *)file; + int32_t err = MZ_OK; + + if (compat->handle) + err = zipClose2_MZ(file, global_comment, version_madeby); + + if (compat->stream) { + mz_stream_close(compat->stream); + mz_stream_delete(&compat->stream); + } + + free(compat); + + return err; +} + +/* Only closes the zip handle, does not close the stream */ +int zipClose_MZ(zipFile file, const char *global_comment) { + return zipClose2_MZ(file, global_comment, MZ_VERSION_MADEBY); +} + +/* Only closes the zip handle, does not close the stream */ +int zipClose2_MZ(zipFile file, const char *global_comment, uint16_t version_madeby) { + mz_zip_compat *compat = (mz_zip_compat *)file; + int32_t err = MZ_OK; + + if (!compat) + return ZIP_PARAMERROR; + if (!compat->handle) + return err; + + if (global_comment) + mz_zip_set_comment(compat->handle, global_comment); + + mz_zip_set_version_madeby(compat->handle, version_madeby); + err = mz_zip_close(compat->handle); + mz_zip_delete(&compat->handle); + + return err; +} diff --git a/thirdparty/minizip/compat/zip.h b/thirdparty/minizip/compat/zip.h new file mode 100644 index 000000000..d7db2c4fc --- /dev/null +++ b/thirdparty/minizip/compat/zip.h @@ -0,0 +1,180 @@ +/* zip.h -- Backwards compatible zip interface + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Copyright (C) 1998-2010 Gilles Vollant + https://www.winimage.com/zLibDll/minizip.html + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef _zip64_H +#define _zip64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#if !defined(_ZLIB_H) && !defined(ZLIB_H) && !defined(ZLIB_H_) +# if __has_include() +# include +# elif __has_include() +# include +# endif +#endif + +#ifndef _ZLIBIOAPI_H +# include "ioapi.h" +#endif + +/***************************************************************************/ + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { + int unused; +} zipFile__; +typedef zipFile__ *zipFile; +#else +typedef void *zipFile; +#endif + +/***************************************************************************/ + +#define ZIP_OK (0) +#define ZIP_EOF (0) +#define ZIP_ERRNO (-1) /* Z_ERRNO */ +#define ZIP_PARAMERROR (-102) +#define ZIP_BADZIPFILE (-103) +#define ZIP_INTERNALERROR (-104) + +/***************************************************************************/ +/* default memLevel */ +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif + +/***************************************************************************/ +/* tm_zip contain date/time info */ +typedef struct tm_zip_s { + int tm_sec; /* seconds after the minute - [0,59] */ + int tm_min; /* minutes after the hour - [0,59] */ + int tm_hour; /* hours since midnight - [0,23] */ + int tm_mday; /* day of the month - [1,31] */ + int tm_mon; /* months since January - [0,11] */ + int tm_year; /* years - [1980..2044] */ +} tm_zip; + +/***************************************************************************/ + +#if !defined(MZ_COMPAT_VERSION) || MZ_COMPAT_VERSION <= 110 +# define mz_dos_date dosDate +#else +# define mz_dos_date dos_date +#endif + +typedef struct { + tm_zip tmz_date; /* date in understandable format */ + unsigned long mz_dos_date; /* if dos_date == 0, tmz_date is used */ + unsigned long internal_fa; /* internal file attributes 2 bytes */ + unsigned long external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +typedef const char *zipcharpc; + +#define APPEND_STATUS_CREATE (0) +#define APPEND_STATUS_CREATEAFTER (1) +#define APPEND_STATUS_ADDINZIP (2) + +/***************************************************************************/ +/* Writing a zip file */ + +/* Compatibility layer with the original minizip library (zip.h). */ +ZEXPORT zipFile zipOpen(const char *path, int append); +ZEXPORT zipFile zipOpen64(const void *path, int append); + +ZEXPORT zipFile zipOpen2(const char *path, int append, zipcharpc *globalcomment, zlib_filefunc_def *pzlib_filefunc_def); +ZEXPORT zipFile zipOpen2_64(const void *path, int append, zipcharpc *globalcomment, + zlib_filefunc64_def *pzlib_filefunc_def); +/* zipOpen3 is not supported */ + +ZEXPORT int zipOpenNewFileInZip(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, + const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, + int compression_method, int level); +ZEXPORT int zipOpenNewFileInZip64(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, + const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, + int compression_method, int level, int zip64); +ZEXPORT int zipOpenNewFileInZip2(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, + const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, + int compression_method, int level, int raw); +ZEXPORT int zipOpenNewFileInZip2_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, + const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, + int compression_method, int level, int raw, int zip64); +ZEXPORT int zipOpenNewFileInZip3(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, + const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, + int compression_method, int level, int raw, int windowBits, int memLevel, int strategy, + const char *password, unsigned long crc_for_crypting); +ZEXPORT int zipOpenNewFileInZip3_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, + const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, + int compression_method, int level, int raw, int windowBits, int memLevel, + int strategy, const char *password, unsigned long crc_for_crypting, int zip64); +ZEXPORT int zipOpenNewFileInZip4(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, + const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, + int compression_method, int level, int raw, int windowBits, int memLevel, int strategy, + const char *password, unsigned long crc_for_crypting, unsigned long version_madeby, + unsigned long flag_base); +ZEXPORT int zipOpenNewFileInZip4_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, + const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, + int compression_method, int level, int raw, int windowBits, int memLevel, + int strategy, const char *password, unsigned long crc_for_crypting, + unsigned long version_madeby, unsigned long flag_base, int zip64); +ZEXPORT int zipWriteInFileInZip(zipFile file, const void *buf, uint32_t len); +ZEXPORT int zipCloseFileInZipRaw(zipFile file, unsigned long uncompressed_size, unsigned long crc32); +ZEXPORT int zipCloseFileInZipRaw64(zipFile file, uint64_t uncompressed_size, unsigned long crc32); +ZEXPORT int zipCloseFileInZip(zipFile file); +/* zipAlreadyThere is too new */ +ZEXPORT int zipClose(zipFile file, const char *global_comment); +/* zipRemoveExtraInfoBlock is not supported */ + +/* Compatibility layer with older minizip-ng (mz_zip.h). */ +ZEXPORT zipFile zipOpen_MZ(void *stream, int append, zipcharpc *globalcomment); +ZEXPORT void *zipGetHandle_MZ(zipFile); +ZEXPORT void *zipGetStream_MZ(zipFile file); +ZEXPORT int zipOpenNewFileInZip_64(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, + const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, + int compression_method, int level, int zip64); +ZEXPORT int zipOpenNewFileInZip5(zipFile file, const char *filename, const zip_fileinfo *zipfi, + const void *extrafield_local, uint16_t size_extrafield_local, + const void *extrafield_global, uint16_t size_extrafield_global, const char *comment, + int compression_method, int level, int raw, int windowBits, int memLevel, int strategy, + const char *password, unsigned long crc_for_crypting, unsigned long version_madeby, + unsigned long flag_base, int zip64); +ZEXPORT int zipCloseFileInZip64(zipFile file); +ZEXPORT int zipClose_64(zipFile file, const char *global_comment); +ZEXPORT int zipClose2_64(zipFile file, const char *global_comment, uint16_t version_madeby); +int zipClose_MZ(zipFile file, const char *global_comment); +int zipClose2_MZ(zipFile file, const char *global_comment, uint16_t version_madeby); + +#ifdef __cplusplus +} +#endif + +#endif /* _zip64_H */ diff --git a/thirdparty/minizip/ioapi.c b/thirdparty/minizip/ioapi.c deleted file mode 100644 index ac3a188c5..000000000 --- a/thirdparty/minizip/ioapi.c +++ /dev/null @@ -1,235 +0,0 @@ -/* ioapi.h -- IO base function header for compress/uncompress .zip - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - -*/ - -#if (defined(_WIN32)) - #define _CRT_SECURE_NO_WARNINGS -#endif - -#include "minizip/ioapi.h" - -voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) -{ - if (pfilefunc->zfile_func64.zopen64_file != NULL) - return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); - else - { - return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); - } -} - -long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) -{ - if (pfilefunc->zfile_func64.zseek64_file != NULL) - return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); - else - { - uLong offsetTruncated = (uLong)offset; - if (offsetTruncated != offset) - return -1; - else - return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); - } -} - -ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) -{ - if (pfilefunc->zfile_func64.zseek64_file != NULL) - return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); - else - { - uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); - if ((tell_uLong) == ((uLong)-1)) - return (ZPOS64_T)-1; - else - return tell_uLong; - } -} - -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) -{ - p_filefunc64_32->zfile_func64.zopen64_file = NULL; - p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; - p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; - p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; - p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; - p_filefunc64_32->zfile_func64.ztell64_file = NULL; - p_filefunc64_32->zfile_func64.zseek64_file = NULL; - p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; - p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; - p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; - p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; - p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; -} - - - -static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); -static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); -static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); -static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); -static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); - -static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) -{ - FILE* file = NULL; - const char* mode_fopen = NULL; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - mode_fopen = "rb"; - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - mode_fopen = "r+b"; - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - mode_fopen = "wb"; - - if ((filename!=NULL) && (mode_fopen != NULL)) - file = fopen(filename, mode_fopen); - return file; -} - -static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) -{ - FILE* file = NULL; - const char* mode_fopen = NULL; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - mode_fopen = "rb"; - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - mode_fopen = "r+b"; - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - mode_fopen = "wb"; - - if ((filename!=NULL) && (mode_fopen != NULL)) - file = fopen64((const char*)filename, mode_fopen); - return file; -} - - -static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) -{ - uLong ret; - ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - -static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) -{ - uLong ret; - ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - -static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) -{ - long ret; - ret = ftell((FILE *)stream); - return ret; -} - - -static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) -{ - ZPOS64_T ret; - ret = ftello64((FILE *)stream); - return ret; -} - -static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) -{ - int fseek_origin=0; - long ret; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - fseek_origin = SEEK_CUR; - break; - case ZLIB_FILEFUNC_SEEK_END : - fseek_origin = SEEK_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - fseek_origin = SEEK_SET; - break; - default: return -1; - } - ret = 0; - if (fseek((FILE *)stream, offset, fseek_origin) != 0) - ret = -1; - return ret; -} - -static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) -{ - int fseek_origin=0; - long ret; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - fseek_origin = SEEK_CUR; - break; - case ZLIB_FILEFUNC_SEEK_END : - fseek_origin = SEEK_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - fseek_origin = SEEK_SET; - break; - default: return -1; - } - ret = 0; - - if(fseeko64((FILE *)stream, offset, fseek_origin) != 0) - ret = -1; - - return ret; -} - - -static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) -{ - int ret; - ret = fclose((FILE *)stream); - return ret; -} - -static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) -{ - int ret; - ret = ferror((FILE *)stream); - return ret; -} - -void fill_fopen_filefunc (pzlib_filefunc_def) - zlib_filefunc_def* pzlib_filefunc_def; -{ - pzlib_filefunc_def->zopen_file = fopen_file_func; - pzlib_filefunc_def->zread_file = fread_file_func; - pzlib_filefunc_def->zwrite_file = fwrite_file_func; - pzlib_filefunc_def->ztell_file = ftell_file_func; - pzlib_filefunc_def->zseek_file = fseek_file_func; - pzlib_filefunc_def->zclose_file = fclose_file_func; - pzlib_filefunc_def->zerror_file = ferror_file_func; - pzlib_filefunc_def->opaque = NULL; -} - -void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = fopen64_file_func; - pzlib_filefunc_def->zread_file = fread_file_func; - pzlib_filefunc_def->zwrite_file = fwrite_file_func; - pzlib_filefunc_def->ztell64_file = ftell64_file_func; - pzlib_filefunc_def->zseek64_file = fseek64_file_func; - pzlib_filefunc_def->zclose_file = fclose_file_func; - pzlib_filefunc_def->zerror_file = ferror_file_func; - pzlib_filefunc_def->opaque = NULL; -} diff --git a/thirdparty/minizip/iowin32.c b/thirdparty/minizip/iowin32.c deleted file mode 100644 index f5683f1c2..000000000 --- a/thirdparty/minizip/iowin32.c +++ /dev/null @@ -1,389 +0,0 @@ -/* iowin32.c -- IO base function header for compress/uncompress .zip - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - -*/ - -#include - -#include "zlib.h" -#include "minizip/ioapi.h" -#include "minizip/iowin32.h" - -#ifndef INVALID_HANDLE_VALUE -#define INVALID_HANDLE_VALUE (0xFFFFFFFF) -#endif - -#ifndef INVALID_SET_FILE_POINTER -#define INVALID_SET_FILE_POINTER ((DWORD)-1) -#endif - -voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); -uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -uLong ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -ZPOS64_T ZCALLBACK win32_tell64_file_func OF((voidpf opaque, voidpf stream)); -long ZCALLBACK win32_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -int ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream)); -int ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream)); - -typedef struct -{ - HANDLE hf; - int error; -} WIN32FILE_IOWIN; - - -static void win32_translate_open_mode(int mode, - DWORD* lpdwDesiredAccess, - DWORD* lpdwCreationDisposition, - DWORD* lpdwShareMode, - DWORD* lpdwFlagsAndAttributes) -{ - *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0; - - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - { - *lpdwDesiredAccess = GENERIC_READ; - *lpdwCreationDisposition = OPEN_EXISTING; - *lpdwShareMode = FILE_SHARE_READ; - } - else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - { - *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; - *lpdwCreationDisposition = OPEN_EXISTING; - } - else if (mode & ZLIB_FILEFUNC_MODE_CREATE) - { - *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; - *lpdwCreationDisposition = CREATE_ALWAYS; - } -} - -static voidpf win32_build_iowin(HANDLE hFile) -{ - voidpf ret=NULL; - - if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) - { - WIN32FILE_IOWIN w32fiow; - w32fiow.hf = hFile; - w32fiow.error = 0; - ret = malloc(sizeof(WIN32FILE_IOWIN)); - - if (ret==NULL) - CloseHandle(hFile); - else - *((WIN32FILE_IOWIN*)ret) = w32fiow; - } - return ret; -} - -voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); - - return win32_build_iowin(hFile); -} - - -voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); - - return win32_build_iowin(hFile); -} - - -voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); - - return win32_build_iowin(hFile); -} - - -voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode) -{ - const char* mode_fopen = NULL; - DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; - HANDLE hFile = NULL; - - win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); - - if ((filename!=NULL) && (dwDesiredAccess != 0)) - hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); - - return win32_build_iowin(hFile); -} - - -uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) -{ - uLong ret=0; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - - if (hFile != NULL) - { - if (!ReadFile(hFile, buf, size, &ret, NULL)) - { - DWORD dwErr = GetLastError(); - if (dwErr == ERROR_HANDLE_EOF) - dwErr = 0; - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - } - } - - return ret; -} - - -uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) -{ - uLong ret=0; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - - if (hFile != NULL) - { - if (!WriteFile(hFile, buf, size, &ret, NULL)) - { - DWORD dwErr = GetLastError(); - if (dwErr == ERROR_HANDLE_EOF) - dwErr = 0; - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - } - } - - return ret; -} - -long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) -{ - long ret=-1; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - if (hFile != NULL) - { - DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); - if (dwSet == INVALID_SET_FILE_POINTER) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = -1; - } - else - ret=(long)dwSet; - } - return ret; -} - -ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) -{ - ZPOS64_T ret= (ZPOS64_T)-1; - HANDLE hFile = NULL; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream)->hf; - - if (hFile) - { - LARGE_INTEGER li; - li.QuadPart = 0; - li.u.LowPart = SetFilePointer(hFile, li.u.LowPart, &li.u.HighPart, FILE_CURRENT); - if ( (li.LowPart == 0xFFFFFFFF) && (GetLastError() != NO_ERROR)) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = (ZPOS64_T)-1; - } - else - ret=li.QuadPart; - } - return ret; -} - - -long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin) -{ - DWORD dwMoveMethod=0xFFFFFFFF; - HANDLE hFile = NULL; - - long ret=-1; - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - dwMoveMethod = FILE_CURRENT; - break; - case ZLIB_FILEFUNC_SEEK_END : - dwMoveMethod = FILE_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - dwMoveMethod = FILE_BEGIN; - break; - default: return -1; - } - - if (hFile != NULL) - { - DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod); - if (dwSet == INVALID_SET_FILE_POINTER) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = -1; - } - else - ret=0; - } - return ret; -} - -long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) -{ - DWORD dwMoveMethod=0xFFFFFFFF; - HANDLE hFile = NULL; - long ret=-1; - - if (stream!=NULL) - hFile = ((WIN32FILE_IOWIN*)stream)->hf; - - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - dwMoveMethod = FILE_CURRENT; - break; - case ZLIB_FILEFUNC_SEEK_END : - dwMoveMethod = FILE_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - dwMoveMethod = FILE_BEGIN; - break; - default: return -1; - } - - if (hFile) - { - LARGE_INTEGER* li = (LARGE_INTEGER*)&offset; - DWORD dwSet = SetFilePointer(hFile, li->u.LowPart, &li->u.HighPart, dwMoveMethod); - if (dwSet == INVALID_SET_FILE_POINTER) - { - DWORD dwErr = GetLastError(); - ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; - ret = -1; - } - else - ret=0; - } - return ret; -} - -int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) -{ - int ret=-1; - - if (stream!=NULL) - { - HANDLE hFile; - hFile = ((WIN32FILE_IOWIN*)stream) -> hf; - if (hFile != NULL) - { - CloseHandle(hFile); - ret=0; - } - free(stream); - } - return ret; -} - -int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) -{ - int ret=-1; - if (stream!=NULL) - { - ret = ((WIN32FILE_IOWIN*)stream) -> error; - } - return ret; -} - -void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen_file = win32_open_file_func; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell_file = win32_tell_file_func; - pzlib_filefunc_def->zseek_file = win32_seek_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} - -void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = win32_open64_file_func; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; - pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} - - -void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; - pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} - - -void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) -{ - pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; - pzlib_filefunc_def->zread_file = win32_read_file_func; - pzlib_filefunc_def->zwrite_file = win32_write_file_func; - pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; - pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; - pzlib_filefunc_def->zclose_file = win32_close_file_func; - pzlib_filefunc_def->zerror_file = win32_error_file_func; - pzlib_filefunc_def->opaque = NULL; -} diff --git a/thirdparty/minizip/make_vms.com b/thirdparty/minizip/make_vms.com deleted file mode 100644 index 9ac13a98f..000000000 --- a/thirdparty/minizip/make_vms.com +++ /dev/null @@ -1,25 +0,0 @@ -$ if f$search("ioapi.h_orig") .eqs. "" then copy ioapi.h ioapi.h_orig -$ open/write zdef vmsdefs.h -$ copy sys$input: zdef -$ deck -#define unix -#define fill_zlib_filefunc64_32_def_from_filefunc32 fillzffunc64from -#define Write_Zip64EndOfCentralDirectoryLocator Write_Zip64EoDLocator -#define Write_Zip64EndOfCentralDirectoryRecord Write_Zip64EoDRecord -#define Write_EndOfCentralDirectoryRecord Write_EoDRecord -$ eod -$ close zdef -$ copy vmsdefs.h,ioapi.h_orig ioapi.h -$ cc/include=[--]/prefix=all ioapi.c -$ cc/include=[--]/prefix=all miniunz.c -$ cc/include=[--]/prefix=all unzip.c -$ cc/include=[--]/prefix=all minizip.c -$ cc/include=[--]/prefix=all zip.c -$ link miniunz,unzip,ioapi,[--]libz.olb/lib -$ link minizip,zip,ioapi,[--]libz.olb/lib -$ mcr []minizip test minizip_info.txt -$ mcr []miniunz -l test.zip -$ rename minizip_info.txt; minizip_info.txt_old -$ mcr []miniunz test.zip -$ delete test.zip;* -$exit diff --git a/thirdparty/minizip/minigzip.c b/thirdparty/minizip/minigzip.c new file mode 100644 index 000000000..52fac6ccd --- /dev/null +++ b/thirdparty/minizip/minigzip.c @@ -0,0 +1,180 @@ +/* minigzip.c + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_os.h" +#include "mz_strm.h" +#include "mz_strm_os.h" +#include "mz_strm_zlib.h" + +#include /* printf */ + +/***************************************************************************/ + +#define MZ_GZIP_COMPRESS (1) +#define MZ_GZIP_DECOMPRESS (2) + +int32_t minigzip_banner(void); +int32_t minigzip_help(void); + +/***************************************************************************/ + +int32_t minigzip_banner(void) { + printf("Minigzip %s - https://github.com/zlib-ng/minizip-ng\n", MZ_VERSION); + printf("---------------------------------------------------\n"); + return MZ_OK; +} + +int32_t minigzip_help(void) { + printf( + "Usage: minigzip [-x] [-d] [-0 to -9] [files]\n\n" + " -x Extract file\n" + " -d Destination directory\n" + " -0 Store only\n" + " -1 Compress faster\n" + " -9 Compress better\n\n"); + return MZ_OK; +} + +/***************************************************************************/ + +int32_t minigzip_copy(const char *path, const char *destination, int16_t operation, int16_t level) { + void *target_stream = NULL; + void *source_stream = NULL; + void *zlib_stream = NULL; + const char *filename = NULL; + char target_path[1024]; + int32_t err = 0; + + memset(target_path, 0, sizeof(target_path)); + + if (destination) { + if (mz_os_file_exists(destination) != MZ_OK) + mz_dir_make(destination); + } + + if (operation == MZ_GZIP_COMPRESS) { + mz_path_combine(target_path, path, sizeof(target_path)); + strncat(target_path, ".gz", sizeof(target_path) - strlen(target_path) - 1); + printf("Compressing to %s\n", target_path); + } else if (operation == MZ_GZIP_DECOMPRESS) { + if (destination) + mz_path_combine(target_path, destination, sizeof(target_path)); + + if (mz_path_get_filename(path, &filename) != MZ_OK) + filename = path; + + mz_path_combine(target_path, filename, sizeof(target_path)); + mz_path_remove_extension(target_path); + printf("Decompressing to %s\n", target_path); + } + + zlib_stream = mz_stream_zlib_create(); + mz_stream_zlib_set_prop_int64(zlib_stream, MZ_STREAM_PROP_COMPRESS_WINDOW, 15 + 16); + + source_stream = mz_stream_os_create(); + err = mz_stream_os_open(source_stream, path, MZ_OPEN_MODE_READ); + + if (err == MZ_OK) { + target_stream = mz_stream_os_create(); + err = mz_stream_os_open(target_stream, target_path, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE); + + if (err == MZ_OK) { + if (operation == MZ_GZIP_COMPRESS) { + mz_stream_zlib_set_prop_int64(zlib_stream, MZ_STREAM_PROP_COMPRESS_LEVEL, level); + mz_stream_zlib_open(zlib_stream, target_path, MZ_OPEN_MODE_WRITE); + mz_stream_set_base(zlib_stream, target_stream); + err = mz_stream_copy_to_end(zlib_stream, source_stream); + } else if (operation == MZ_GZIP_DECOMPRESS) { + mz_stream_zlib_open(zlib_stream, path, MZ_OPEN_MODE_READ); + mz_stream_set_base(zlib_stream, source_stream); + err = mz_stream_copy_to_end(target_stream, zlib_stream); + } + + if (err != MZ_OK) + printf("Error %d in zlib stream (%d)\n", err, mz_stream_zlib_error(zlib_stream)); + else + printf("Operation completed successfully\n"); + + mz_stream_zlib_close(zlib_stream); + } else { + printf("Error %d opening target path %s\n", err, target_path); + } + + mz_stream_os_close(target_stream); + mz_stream_os_delete(&target_stream); + } else { + printf("Error %d opening source path %s\n", err, path); + } + + mz_stream_os_close(source_stream); + mz_stream_os_delete(&source_stream); + + mz_stream_zlib_delete(&zlib_stream); + return err; +} + +/***************************************************************************/ + +#if !defined(MZ_ZIP_NO_MAIN) +int main(int argc, const char *argv[]) { + int16_t operation_level = MZ_COMPRESS_LEVEL_DEFAULT; + int32_t path_arg = 0; + int32_t err = 0; + int32_t i = 0; + uint8_t operation = MZ_GZIP_COMPRESS; + const char *path = NULL; + const char *destination = NULL; + + minigzip_banner(); + if (argc == 1) { + minigzip_help(); + return 0; + } + + /* Parse command line options */ + for (i = 1; i < argc; i += 1) { + printf("%s ", argv[i]); + if (argv[i][0] == '-') { + char c = argv[i][1]; + if ((c == 'x') || (c == 'X')) + operation = MZ_GZIP_DECOMPRESS; + else if ((c >= '0') && (c <= '9')) + operation_level = (c - '0'); + else if (((c == 'd') || (c == 'D')) && (i + 1 < argc)) { + destination = argv[i + 1]; + printf("%s ", argv[i + 1]); + i += 1; + } else { + err = MZ_SUPPORT_ERROR; + } + } else if (path_arg == 0) { + path_arg = i; + break; + } + } + printf("\n"); + + if (err == MZ_SUPPORT_ERROR) { + printf("Feature not supported\n"); + return err; + } + + if (path_arg == 0) { + minigzip_help(); + return 0; + } + + path = argv[path_arg]; + err = minigzip_copy(path, destination, operation, operation_level); + + return err; +} +#endif diff --git a/thirdparty/minizip/miniunz.c b/thirdparty/minizip/miniunz.c deleted file mode 100644 index e727d5c42..000000000 --- a/thirdparty/minizip/miniunz.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - miniunz.c - Version 1.1, February 14h, 2010 - sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications of Unzip for Zip64 - Copyright (C) 2007-2008 Even Rouault - - Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) -*/ - -#ifndef _WIN32 - #ifndef __USE_FILE_OFFSET64 - #define __USE_FILE_OFFSET64 - #endif - #ifndef __USE_LARGEFILE64 - #define __USE_LARGEFILE64 - #endif - #ifndef _LARGEFILE64_SOURCE - #define _LARGEFILE64_SOURCE - #endif - #ifndef _FILE_OFFSET_BIT - #define _FILE_OFFSET_BIT 64 - #endif -#endif - -#include -#include -#include -#include -#include -#include - -#if unix || __APPLE__ -# include -# include -#else -# include -# include -#endif - -#include "minizip/unzip.h" - -#define CASESENSITIVITY (0) -#define WRITEBUFFERSIZE (8192) -#define MAXFILENAME (256) - -#ifdef _WIN32 -#define USEWIN32IOAPI -#include "minizip/iowin32.h" -#endif -/* - mini unzip, demo of unzip package - - usage : - Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] - - list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT - if it exists -*/ - - -/* change_file_date : change the date/time of a file - filename : the filename of the file where date/time must be modified - dosdate : the new date at the MSDos format (4 bytes) - tmu_date : the SAME new date at the tm_unz format */ -void change_file_date(filename,dosdate,tmu_date) - const char *filename; - uLong dosdate; - tm_unz tmu_date; -{ -#ifdef _WIN32 - HANDLE hFile; - FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; - - hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE, - 0,NULL,OPEN_EXISTING,0,NULL); - GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); - DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); - LocalFileTimeToFileTime(&ftLocal,&ftm); - SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); - CloseHandle(hFile); -#else -#ifdef unix - struct utimbuf ut; - struct tm newdate; - newdate.tm_sec = tmu_date.tm_sec; - newdate.tm_min=tmu_date.tm_min; - newdate.tm_hour=tmu_date.tm_hour; - newdate.tm_mday=tmu_date.tm_mday; - newdate.tm_mon=tmu_date.tm_mon; - if (tmu_date.tm_year > 1900) - newdate.tm_year=tmu_date.tm_year - 1900; - else - newdate.tm_year=tmu_date.tm_year ; - newdate.tm_isdst=-1; - - ut.actime=ut.modtime=mktime(&newdate); - utime(filename,&ut); -#endif -#endif -} - - -/* mymkdir and change_file_date are not 100 % portable - As I don't know well Unix, I wait feedback for the unix portion */ - -int mymkdir(dirname) - const char* dirname; -{ - int ret=0; -#ifdef _WIN32 - ret = _mkdir(dirname); -#else -#ifdef unix - ret = mkdir (dirname,0775); -#endif -#endif - return ret; -} - -int makedir (newdir) - char *newdir; -{ - char *buffer ; - char *p; - int len = (int)strlen(newdir); - - if (len <= 0) - return 0; - - buffer = (char*)malloc(len+1); - if (buffer==NULL) - { - printf("Error allocating memory\n"); - return UNZ_INTERNALERROR; - } - strcpy(buffer,newdir); - - if (buffer[len-1] == '/') { - buffer[len-1] = '\0'; - } - if (mymkdir(buffer) == 0) - { - free(buffer); - return 1; - } - - p = buffer+1; - while (1) - { - char hold; - - while(*p && *p != '\\' && *p != '/') - p++; - hold = *p; - *p = 0; - if ((mymkdir(buffer) == -1) && (errno == ENOENT)) - { - printf("couldn't create directory %s\n",buffer); - free(buffer); - return 0; - } - if (hold == 0) - break; - *p++ = hold; - } - free(buffer); - return 1; -} - -void do_banner() -{ - printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); - printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); -} - -void do_help() -{ - printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ - " -e Extract without pathname (junk paths)\n" \ - " -x Extract with pathname\n" \ - " -v list files\n" \ - " -l list files\n" \ - " -d directory to extract into\n" \ - " -o overwrite files without prompting\n" \ - " -p extract crypted file using password\n\n"); -} - -void Display64BitsSize(ZPOS64_T n, int size_char) -{ - /* to avoid compatibility problem , we do here the conversion */ - char number[21]; - int offset=19; - int pos_string = 19; - number[20]=0; - for (;;) { - number[offset]=(char)((n%10)+'0'); - if (number[offset] != '0') - pos_string=offset; - n/=10; - if (offset==0) - break; - offset--; - } - { - int size_display_string = 19-pos_string; - while (size_char > size_display_string) - { - size_char--; - printf(" "); - } - } - - printf("%s",&number[pos_string]); -} - -int do_list(uf) - unzFile uf; -{ - uLong i; - unz_global_info64 gi; - int err; - - err = unzGetGlobalInfo64(uf,&gi); - if (err!=UNZ_OK) - printf("error %d with zipfile in unzGetGlobalInfo \n",err); - printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); - printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); - for (i=0;i0) - ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size); - - /* display a '*' if the file is crypted */ - if ((file_info.flag & 1) != 0) - charCrypt='*'; - - if (file_info.compression_method==0) - string_method="Stored"; - else - if (file_info.compression_method==Z_DEFLATED) - { - uInt iLevel=(uInt)((file_info.flag & 0x6)/2); - if (iLevel==0) - string_method="Defl:N"; - else if (iLevel==1) - string_method="Defl:X"; - else if ((iLevel==2) || (iLevel==3)) - string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ - } - else - if (file_info.compression_method==Z_BZIP2ED) - { - string_method="BZip2 "; - } - else - string_method="Unkn. "; - - Display64BitsSize(file_info.uncompressed_size,7); - printf(" %6s%c",string_method,charCrypt); - Display64BitsSize(file_info.compressed_size,7); - printf(" %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", - ratio, - (uLong)file_info.tmu_date.tm_mon + 1, - (uLong)file_info.tmu_date.tm_mday, - (uLong)file_info.tmu_date.tm_year % 100, - (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, - (uLong)file_info.crc,filename_inzip); - if ((i+1)='a') && (rep<='z')) - rep -= 0x20; - } - while ((rep!='Y') && (rep!='N') && (rep!='A')); - } - - if (rep == 'N') - skip = 1; - - if (rep == 'A') - *popt_overwrite=1; - } - - if ((skip==0) && (err==UNZ_OK)) - { - fout=fopen64(write_filename,"wb"); - - /* some zipfile don't contain directory alone before file */ - if ((fout==NULL) && ((*popt_extract_without_path)==0) && - (filename_withoutpath!=(char*)filename_inzip)) - { - char c=*(filename_withoutpath-1); - *(filename_withoutpath-1)='\0'; - makedir(write_filename); - *(filename_withoutpath-1)=c; - fout=fopen64(write_filename,"wb"); - } - - if (fout==NULL) - { - printf("error opening %s\n",write_filename); - } - } - - if (fout!=NULL) - { - printf(" extracting: %s\n",write_filename); - - do - { - err = unzReadCurrentFile(uf,buf,size_buf); - if (err<0) - { - printf("error %d with zipfile in unzReadCurrentFile\n",err); - break; - } - if (err>0) - if (fwrite(buf,err,1,fout)!=1) - { - printf("error in writing extracted file\n"); - err=UNZ_ERRNO; - break; - } - } - while (err>0); - if (fout) - fclose(fout); - - if (err==0) - change_file_date(write_filename,file_info.dosDate, - file_info.tmu_date); - } - - if (err==UNZ_OK) - { - err = unzCloseCurrentFile (uf); - if (err!=UNZ_OK) - { - printf("error %d with zipfile in unzCloseCurrentFile\n",err); - } - } - else - unzCloseCurrentFile(uf); /* don't lose the error */ - } - - free(buf); - return err; -} - - -int do_extract(uf,opt_extract_without_path,opt_overwrite,password) - unzFile uf; - int opt_extract_without_path; - int opt_overwrite; - const char* password; -{ - uLong i; - unz_global_info64 gi; - int err; - FILE* fout=NULL; - - err = unzGetGlobalInfo64(uf,&gi); - if (err!=UNZ_OK) - printf("error %d with zipfile in unzGetGlobalInfo \n",err); - - for (i=0;i /* printf */ + +/***************************************************************************/ + +typedef struct minizip_opt_s { + int64_t disk_size; + int32_t encoding; + uint8_t include_path; + int16_t compress_level; + uint8_t compress_method; + uint8_t overwrite; + uint8_t append; + uint8_t follow_links; + uint8_t store_links; + uint8_t zip_cd; + uint8_t verbose; + uint8_t aes; +} minizip_opt; + +/***************************************************************************/ + +int32_t minizip_banner(void); +int32_t minizip_help(void); + +int32_t minizip_list(const char *path, int32_t encoding); + +int32_t minizip_add_entry_cb(void *handle, void *userdata, mz_zip_file *file_info); +int32_t minizip_add_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position); +int32_t minizip_add_overwrite_cb(void *handle, void *userdata, const char *path); +int32_t minizip_add(const char *path, const char *password, minizip_opt *options, int32_t arg_count, const char **args); + +int32_t minizip_extract_entry_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path); +int32_t minizip_extract_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position); +int32_t minizip_extract_overwrite_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path); +int32_t minizip_extract(const char *path, const char *pattern, const char *destination, const char *password, + minizip_opt *options); + +int32_t minizip_erase(const char *src_path, const char *target_path, int32_t arg_count, const char **args); + +/***************************************************************************/ + +int32_t minizip_banner(void) { + printf("minizip-ng %s - https://github.com/zlib-ng/minizip-ng\n", MZ_VERSION); + printf("---------------------------------------------------\n"); + return MZ_OK; +} -#ifndef _WIN32 - #ifndef __USE_FILE_OFFSET64 - #define __USE_FILE_OFFSET64 - #endif - #ifndef __USE_LARGEFILE64 - #define __USE_LARGEFILE64 - #endif - #ifndef _LARGEFILE64_SOURCE - #define _LARGEFILE64_SOURCE - #endif - #ifndef _FILE_OFFSET_BIT - #define _FILE_OFFSET_BIT 64 - #endif -#endif +int32_t minizip_help(void) { + printf( + "Usage: minizip [-x][-d dir|-l|-e][-o][-f][-y][-c cp][-a][-0 to -9][-b|-m|-t|-g][-k 512][-p pwd][-s] file.zip " + "[files]\n\n" + " -x Extract files\n" + " -l List files\n" + " -d Destination directory\n" + " -e Erase files\n" + " -o Overwrite existing files\n" + " -c File names use cp437 encoding (or specified codepage)\n" + " -a Append to existing zip file\n" + " -i Include full path of files\n" + " -f Follow symbolic links\n" + " -y Store symbolic links\n" + " -v Verbose info\n" + " -0 Store only\n" + " -1 Compress faster\n" + " -9 Compress better\n" + " -k Disk size in KB\n" + " -z Zip central directory\n" + " -p Encryption password\n" + " -s AES encryption\n" + " -b BZIP2 compression\n" + " -m LZMA compression\n" + " -n XZ compression\n" + " -t ZSTD compression\n" + " -g PPMD compression\n\n"); + return MZ_OK; +} -#include -#include -#include -#include -#include -#include - -#ifdef unix -# include -# include -# include -# include -#else -# include -# include -#endif +/***************************************************************************/ + +int32_t minizip_list(const char *path, int32_t encoding) { + mz_zip_file *file_info = NULL; + uint32_t ratio = 0; + int32_t err = MZ_OK; + struct tm tmu_date; + const char *method = NULL; + char *utf8_string = NULL; + char crypt = ' '; + void *reader = NULL; + + reader = mz_zip_reader_create(); + if (!reader) + return MZ_MEM_ERROR; + + err = mz_zip_reader_open_file(reader, path); + if (err != MZ_OK) { + printf("Error %" PRId32 " opening archive %s\n", err, path); + mz_zip_reader_delete(&reader); + return err; + } -#include "minizip/zip.h" + mz_zip_reader_set_encoding(reader, encoding); -#ifdef _WIN32 - #define USEWIN32IOAPI - #include "minizip/iowin32.h" -#endif + err = mz_zip_reader_goto_first_entry(reader); + + if (err != MZ_OK && err != MZ_END_OF_LIST) { + printf("Error %" PRId32 " going to first entry in archive\n", err); + mz_zip_reader_delete(&reader); + return err; + } + printf(" Packed Unpacked Ratio Method Attribs Date Time CRC-32 Name\n"); + printf(" ------ -------- ----- ------ ------- ---- ---- ------ ----\n"); + /* Enumerate all entries in the archive */ + while (err == MZ_OK) { + err = mz_zip_reader_entry_get_info(reader, &file_info); -#define WRITEBUFFERSIZE (16384) -#define MAXFILENAME (256) - -#ifdef _WIN32 -uLong filetime(f, tmzip, dt) - char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ - int ret = 0; - { - FILETIME ftLocal; - HANDLE hFind; - WIN32_FIND_DATAA ff32; - - hFind = FindFirstFileA(f,&ff32); - if (hFind != INVALID_HANDLE_VALUE) - { - FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); - FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); - FindClose(hFind); - ret = 1; - } - } - return ret; -} -#else -#ifdef unix -uLong filetime(f, tmzip, dt) - char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ - int ret=0; - struct stat s; /* results of stat() */ - struct tm* filedate; - time_t tm_t=0; - - if (strcmp(f,"-")!=0) - { - char name[MAXFILENAME+1]; - int len = strlen(f); - if (len > MAXFILENAME) - len = MAXFILENAME; - - strncpy(name, f,MAXFILENAME-1); - /* strncpy doesnt append the trailing NULL, of the string is too long. */ - name[ MAXFILENAME ] = '\0'; - - if (name[len - 1] == '/') - name[len - 1] = '\0'; - /* not all systems allow stat'ing a file with / appended */ - if (stat(name,&s)==0) - { - tm_t = s.st_mtime; - ret = 1; + if (err != MZ_OK) { + printf("Error %" PRId32 " getting entry info in archive\n", err); + break; + } + + ratio = 0; + if (file_info->uncompressed_size > 0) + ratio = (uint32_t)((file_info->compressed_size * 100) / file_info->uncompressed_size); + + /* Display a '*' if the file is encrypted */ + if (file_info->flag & MZ_ZIP_FLAG_ENCRYPTED) + crypt = '*'; + else + crypt = ' '; + + method = mz_zip_get_compression_method_string(file_info->compression_method); + mz_zip_time_t_to_tm(file_info->modified_date, &tmu_date); + + if ((encoding > 0) && (file_info->flag & MZ_ZIP_FLAG_UTF8) == 0) { + utf8_string = mz_os_utf8_string_create(file_info->filename, encoding); + if (!utf8_string) { + err = MZ_MEM_ERROR; + printf("Error %" PRId32 " creating UTF-8 string\n", err); + break; + } + } + + /* Print entry information */ + printf("%12" PRId64 " %12" PRId64 " %3" PRIu32 "%% %6s%c %8" PRIx32 " %2.2" PRIu32 "-%2.2" PRIu32 + "-%2.2" PRIu32 " %2.2" PRIu32 ":%2.2" PRIu32 " %8.8" PRIx32 " %s\n", + file_info->compressed_size, file_info->uncompressed_size, ratio, method, crypt, file_info->external_fa, + (uint32_t)tmu_date.tm_mon + 1, (uint32_t)tmu_date.tm_mday, (uint32_t)tmu_date.tm_year % 100, + (uint32_t)tmu_date.tm_hour, (uint32_t)tmu_date.tm_min, file_info->crc, + utf8_string ? utf8_string : file_info->filename); + + if (utf8_string) + mz_os_utf8_string_delete(&utf8_string); + + err = mz_zip_reader_goto_next_entry(reader); + + if (err != MZ_OK && err != MZ_END_OF_LIST) { + printf("Error %" PRId32 " going to next entry in archive\n", err); + break; + } } - } - filedate = localtime(&tm_t); - tmzip->tm_sec = filedate->tm_sec; - tmzip->tm_min = filedate->tm_min; - tmzip->tm_hour = filedate->tm_hour; - tmzip->tm_mday = filedate->tm_mday; - tmzip->tm_mon = filedate->tm_mon ; - tmzip->tm_year = filedate->tm_year; + mz_zip_reader_delete(&reader); - return ret; + if (err == MZ_END_OF_LIST) + return MZ_OK; + + return err; } -#else -uLong filetime(f, tmzip, dt) - char *f; /* name of file to get info on */ - tm_zip *tmzip; /* return value: access, modific. and creation times */ - uLong *dt; /* dostime */ -{ - return 0; + +/***************************************************************************/ + +int32_t minizip_add_entry_cb(void *handle, void *userdata, mz_zip_file *file_info) { + MZ_UNUSED(handle); + MZ_UNUSED(userdata); + + /* Print the current file we are trying to compress */ + printf("Adding %s\n", file_info->filename); + return MZ_OK; } -#endif -#endif +int32_t minizip_add_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position) { + minizip_opt *options = (minizip_opt *)userdata; + double progress = 0; + uint8_t raw = 0; + MZ_UNUSED(userdata); + mz_zip_writer_get_raw(handle, &raw); -int check_exist_file(filename) - const char* filename; -{ - FILE* ftestexist; - int ret = 1; - ftestexist = fopen64(filename,"rb"); - if (ftestexist==NULL) - ret = 0; - else - fclose(ftestexist); - return ret; + if (raw && file_info->compressed_size > 0) + progress = ((double)position / file_info->compressed_size) * 100; + else if (!raw && file_info->uncompressed_size > 0) + progress = ((double)position / file_info->uncompressed_size) * 100; + + /* Print the progress of the current compress operation */ + if (options->verbose) { + printf("%s - %" PRId64 " / %" PRId64 " (%.02f%%)\n", file_info->filename, position, + file_info->uncompressed_size, progress); + } + return MZ_OK; } -void do_banner() -{ - printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n"); - printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n"); +int32_t minizip_add_overwrite_cb(void *handle, void *userdata, const char *path) { + minizip_opt *options = (minizip_opt *)userdata; + + MZ_UNUSED(handle); + + if (!options->overwrite) { + /* If ask the user what to do because append and overwrite args not set */ + char rep = 0; + do { + char answer[128]; + printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ", path); + if (scanf("%1s", answer) != 1) + exit(EXIT_FAILURE); + rep = answer[0]; + + if ((rep >= 'a') && (rep <= 'z')) + rep -= 0x20; + } while ((rep != 'Y') && (rep != 'N') && (rep != 'A')); + + if (rep == 'A') { + return MZ_EXIST_ERROR; + } else if (rep == 'N') { + return MZ_INTERNAL_ERROR; + } + } + + return MZ_OK; } -void do_help() -{ - printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \ - " -o Overwrite existing file.zip\n" \ - " -a Append to existing file.zip\n" \ - " -0 Store only\n" \ - " -1 Compress faster\n" \ - " -9 Compress better\n\n" \ - " -j exclude path. store only the file name.\n\n"); +int32_t minizip_add(const char *path, const char *password, minizip_opt *options, int32_t arg_count, + const char **args) { + void *writer = NULL; + int32_t err = MZ_OK; + int32_t err_close = MZ_OK; + int32_t i = 0; + const char *filename_in_zip = NULL; + + printf("Archive %s\n", path); + + /* Create zip writer */ + writer = mz_zip_writer_create(); + if (!writer) + return MZ_MEM_ERROR; + + mz_zip_writer_set_password(writer, password); + mz_zip_writer_set_aes(writer, options->aes); + mz_zip_writer_set_compress_method(writer, options->compress_method); + mz_zip_writer_set_compress_level(writer, options->compress_level); + mz_zip_writer_set_follow_links(writer, options->follow_links); + mz_zip_writer_set_store_links(writer, options->store_links); + mz_zip_writer_set_overwrite_cb(writer, options, minizip_add_overwrite_cb); + mz_zip_writer_set_progress_cb(writer, options, minizip_add_progress_cb); + mz_zip_writer_set_entry_cb(writer, options, minizip_add_entry_cb); + mz_zip_writer_set_zip_cd(writer, options->zip_cd); + + err = mz_zip_writer_open_file(writer, path, options->disk_size, options->append); + + if (err == MZ_OK) { + for (i = 0; i < arg_count; i += 1) { + filename_in_zip = args[i]; + + /* Add file system path to archive */ + err = mz_zip_writer_add_path(writer, filename_in_zip, NULL, options->include_path, 1); + if (err != MZ_OK) + printf("Error %" PRId32 " adding path to archive %s\n", err, filename_in_zip); + } + } else { + printf("Error %" PRId32 " opening archive for writing\n", err); + } + + err_close = mz_zip_writer_close(writer); + if (err_close != MZ_OK) { + printf("Error %" PRId32 " closing archive for writing %s\n", err_close, path); + err = err_close; + } + + mz_zip_writer_delete(&writer); + return err; } -/* calculate the CRC32 of a file, - because to encrypt a file, we need known the CRC32 of the file before */ -int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) -{ - unsigned long calculate_crc=0; - int err=ZIP_OK; - FILE * fin = fopen64(filenameinzip,"rb"); - unsigned long size_read = 0; - unsigned long total_read = 0; - if (fin==NULL) - { - err = ZIP_ERRNO; - } - - if (err == ZIP_OK) - do - { - err = ZIP_OK; - size_read = (int)fread(buf,1,size_buf,fin); - if (size_read < size_buf) - if (feof(fin)==0) - { - printf("error in reading %s\n",filenameinzip); - err = ZIP_ERRNO; - } +/***************************************************************************/ - if (size_read>0) - calculate_crc = crc32(calculate_crc,buf,size_read); - total_read += size_read; +int32_t minizip_extract_entry_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path) { + minizip_opt *options = (minizip_opt *)userdata; + char *utf8_string = NULL; - } while ((err == ZIP_OK) && (size_read>0)); + MZ_UNUSED(handle); + MZ_UNUSED(path); - if (fin) - fclose(fin); + if ((options->encoding > 0) && (file_info->flag & MZ_ZIP_FLAG_UTF8) == 0) { + utf8_string = mz_os_utf8_string_create(file_info->filename, options->encoding); + if (!utf8_string) + return MZ_MEM_ERROR; + } - *result_crc=calculate_crc; - printf("file %s crc %lx\n", filenameinzip, calculate_crc); - return err; + /* Print the current entry extracting */ + printf("Extracting %s\n", utf8_string ? utf8_string : file_info->filename); + + if (utf8_string) + mz_os_utf8_string_delete(&utf8_string); + + return MZ_OK; } -int isLargeFile(const char* filename) -{ - int largeFile = 0; - ZPOS64_T pos = 0; - FILE* pFile = fopen64(filename, "rb"); +int32_t minizip_extract_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position) { + minizip_opt *options = (minizip_opt *)userdata; + double progress = 0; + uint8_t raw = 0; - if(pFile != NULL) - { - int n = fseeko64(pFile, 0, SEEK_END); + mz_zip_reader_get_raw(handle, &raw); - pos = ftello64(pFile); + if (raw && file_info->compressed_size > 0) + progress = ((double)position / file_info->compressed_size) * 100; + else if (!raw && file_info->uncompressed_size > 0) + progress = ((double)position / file_info->uncompressed_size) * 100; - printf("File : %s is %lld bytes\n", filename, pos); + /* Print the progress of the current extraction */ + if (options->verbose) { + printf("%s - %" PRId64 " / %" PRId64 " (%.02f%%)\n", file_info->filename, position, + file_info->uncompressed_size, progress); + } - if(pos >= 0xffffffff) - largeFile = 1; + return MZ_OK; +} - fclose(pFile); - } +int32_t minizip_extract_overwrite_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path) { + minizip_opt *options = (minizip_opt *)userdata; + + MZ_UNUSED(handle); + MZ_UNUSED(file_info); + + /* Verify if we want to overwrite current entry on disk */ + if (!options->overwrite) { + char rep = 0; + do { + char answer[128]; + printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ", path); + if (scanf("%1s", answer) != 1) + exit(EXIT_FAILURE); + rep = answer[0]; + if ((rep >= 'a') && (rep <= 'z')) + rep -= 0x20; + } while ((rep != 'Y') && (rep != 'N') && (rep != 'A')); + + if (rep == 'N') + return MZ_EXIST_ERROR; + if (rep == 'A') + options->overwrite = 1; + } - return largeFile; + return MZ_OK; } -int main(argc,argv) - int argc; - char *argv[]; -{ - int i; - int opt_overwrite=0; - int opt_compress_level=Z_DEFAULT_COMPRESSION; - int opt_exclude_path=0; - int zipfilenamearg = 0; - char filename_try[MAXFILENAME+16]; - int zipok; - int err=0; - int size_buf=0; - void* buf=NULL; - const char* password=NULL; - - - do_banner(); - if (argc==1) - { - do_help(); - return 0; +int32_t minizip_extract(const char *path, const char *pattern, const char *destination, const char *password, + minizip_opt *options) { + void *reader = NULL; + int32_t err = MZ_OK; + int32_t err_close = MZ_OK; + + printf("Archive %s\n", path); + + /* Create zip reader */ + reader = mz_zip_reader_create(); + if (!reader) + return MZ_MEM_ERROR; + + mz_zip_reader_set_pattern(reader, pattern, 1); + mz_zip_reader_set_password(reader, password); + mz_zip_reader_set_encoding(reader, options->encoding); + mz_zip_reader_set_entry_cb(reader, options, minizip_extract_entry_cb); + mz_zip_reader_set_progress_cb(reader, options, minizip_extract_progress_cb); + mz_zip_reader_set_overwrite_cb(reader, options, minizip_extract_overwrite_cb); + + err = mz_zip_reader_open_file(reader, path); + + if (err != MZ_OK) { + printf("Error %" PRId32 " opening archive %s\n", err, path); + } else { + /* Save all entries in archive to destination directory */ + err = mz_zip_reader_save_all(reader, destination); + + if (err == MZ_END_OF_LIST) { + if (pattern) { + printf("Files matching %s not found in archive\n", pattern); + } else { + printf("No files in archive\n"); + err = MZ_OK; + } + } else if (err != MZ_OK) { + printf("Error %" PRId32 " saving entries to disk %s\n", err, path); + } + } + + err_close = mz_zip_reader_close(reader); + if (err_close != MZ_OK) { + printf("Error %" PRId32 " closing archive for reading\n", err_close); + err = err_close; } - else - { - for (i=1;i='0') && (c<='9')) - opt_compress_level = c-'0'; - if ((c=='j') || (c=='J')) - opt_exclude_path = 1; - - if (((c=='p') || (c=='P')) && (i+1= (int32_t)sizeof(tmp_path)) + return MZ_BUF_ERROR; + if (mz_os_file_exists(tmp_path) == MZ_OK) + return MZ_EXIST_ERROR; } } +#endif + target_path_ptr = tmp_path; } - size_buf = WRITEBUFFERSIZE; - buf = (void*)malloc(size_buf); - if (buf==NULL) - { - printf("Error allocating memory\n"); - return ZIP_INTERNALERROR; + reader = mz_zip_reader_create(); + if (!reader) + return MZ_MEM_ERROR; + writer = mz_zip_writer_create(); + if (!writer) { + mz_zip_reader_delete(&reader); + return MZ_MEM_ERROR; } - if (zipfilenamearg==0) - { - zipok=0; + /* Open original archive we want to erase an entry in */ + err = mz_zip_reader_open_file(reader, src_path); + if (err != MZ_OK) { + printf("Error %" PRId32 " opening archive for reading %s\n", err, src_path); + mz_zip_reader_delete(&reader); + mz_zip_writer_delete(&writer); + return err; } - else - { - int i,len; - int dot_found=0; - zipok = 1 ; - strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1); - /* strncpy doesnt append the trailing NULL, of the string is too long. */ - filename_try[ MAXFILENAME ] = '\0'; + /* Open temporary archive */ + err = mz_zip_writer_open_file(writer, target_path_ptr, 0, 0); + if (err != MZ_OK) { + printf("Error %" PRId32 " opening archive for writing %s\n", err, target_path_ptr); + mz_zip_reader_delete(&reader); + mz_zip_writer_delete(&writer); + return err; + } - len=(int)strlen(filename_try); - for (i=0;i='a') && (rep<='z')) - rep -= 0x20; - } - while ((rep!='Y') && (rep!='N') && (rep!='A')); - if (rep=='N') - zipok = 0; - if (rep=='A') - opt_overwrite = 2; - } - } - if (zipok==1) - { - zipFile zf; - int errclose; -# ifdef USEWIN32IOAPI - zlib_filefunc64_def ffunc; - fill_win32_filefunc64A(&ffunc); - zf = zipOpen2_64(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc); -# else - zf = zipOpen64(filename_try,(opt_overwrite==2) ? 2 : 0); -# endif - - if (zf == NULL) - { - printf("error opening %s\n",filename_try); - err= ZIP_ERRNO; + /* Copy all entries from original archive to temporary archive + except the ones we don't want */ + for (i = 0, skip = 0; i < arg_count; i += 1) { + filename_in_zip = args[i]; + + if (mz_path_compare_wc(file_info->filename, filename_in_zip, 1) == MZ_OK) + skip = 1; } - else - printf("creating %s\n",filename_try); - for (i=zipfilenamearg+1;(i='0') || (argv[i][1]<='9'))) && - (strlen(argv[i]) == 2))) - { - FILE * fin; - int size_read; - const char* filenameinzip = argv[i]; - const char *savefilenameinzip; - zip_fileinfo zi; - unsigned long crcFile=0; - int zip64 = 0; - - zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = - zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; - zi.dosDate = 0; - zi.internal_fa = 0; - zi.external_fa = 0; - filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); - -/* - err = zipOpenNewFileInZip(zf,filenameinzip,&zi, - NULL,0,NULL,0,NULL / * comment * /, - (opt_compress_level != 0) ? Z_DEFLATED : 0, - opt_compress_level); -*/ - if ((password != NULL) && (err==ZIP_OK)) - err = getFileCrc(filenameinzip,buf,size_buf,&crcFile); - - zip64 = isLargeFile(filenameinzip); - - /* The path name saved, should not include a leading slash. */ - /*if it did, windows/xp and dynazip couldn't read the zip file. */ - savefilenameinzip = filenameinzip; - while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' ) - { - savefilenameinzip++; - } - - /*should the zip file contain any path at all?*/ - if( opt_exclude_path ) - { - const char *tmpptr; - const char *lastslash = 0; - for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++) - { - if( *tmpptr == '\\' || *tmpptr == '/') - { - lastslash = tmpptr; - } - } - if( lastslash != NULL ) - { - savefilenameinzip = lastslash+1; // base filename follows last slash. - } - } - - /**/ - err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi, - NULL,0,NULL,0,NULL /* comment*/, - (opt_compress_level != 0) ? Z_DEFLATED : 0, - opt_compress_level,0, - /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - password,crcFile, zip64); - - if (err != ZIP_OK) - printf("error in opening %s in zipfile\n",filenameinzip); - else - { - fin = fopen64(filenameinzip,"rb"); - if (fin==NULL) - { - err=ZIP_ERRNO; - printf("error in opening %s for reading\n",filenameinzip); - } - } - - if (err == ZIP_OK) - do - { - err = ZIP_OK; - size_read = (int)fread(buf,1,size_buf,fin); - if (size_read < size_buf) - if (feof(fin)==0) - { - printf("error in reading %s\n",filenameinzip); - err = ZIP_ERRNO; - } - - if (size_read>0) - { - err = zipWriteInFileInZip (zf,buf,size_read); - if (err<0) - { - printf("error in writing %s in the zipfile\n", - filenameinzip); - } - - } - } while ((err == ZIP_OK) && (size_read>0)); - - if (fin) - fclose(fin); - - if (err<0) - err=ZIP_ERRNO; - else - { - err = zipCloseFileInZip(zf); - if (err!=ZIP_OK) - printf("error in closing %s in the zipfile\n", - filenameinzip); - } + if (skip) { + printf("Skipping %s\n", file_info->filename); + } else { + printf("Copying %s\n", file_info->filename); + err = mz_zip_writer_copy_from_reader(writer, reader); + } + + if (err != MZ_OK) { + printf("Error %" PRId32 " copying entry into new zip\n", err); + break; + } + + err = mz_zip_reader_goto_next_entry(reader); + + if (err != MZ_OK && err != MZ_END_OF_LIST) + printf("Error %" PRId32 " going to next entry in archive\n", err); + } + + mz_zip_reader_get_zip_cd(reader, &zip_cd); + mz_zip_writer_set_zip_cd(writer, zip_cd); + + mz_zip_reader_close(reader); + mz_zip_reader_delete(&reader); + + mz_zip_writer_close(writer); + mz_zip_writer_delete(&writer); + + if (err == MZ_END_OF_LIST) { + if (!target_path) { + /* Swap original archive with temporary archive, backup old archive if possible */ + strncpy(bak_path, src_path, sizeof(bak_path) - 1); + bak_path[sizeof(bak_path) - 1] = 0; + strncat(bak_path, ".bak", sizeof(bak_path) - strlen(bak_path) - 1); + + if (mz_os_file_exists(bak_path) == MZ_OK) + mz_os_unlink(bak_path); + + err = mz_os_rename(src_path, bak_path); + if (err != MZ_OK) { + printf("Error backing up archive before replacing %s\n", bak_path); + } else { + err = mz_os_rename(tmp_path, src_path); + if (err != MZ_OK) + printf("Error replacing archive with temp %s\n", tmp_path); } + + return err; } - errclose = zipClose(zf,NULL); - if (errclose != ZIP_OK) - printf("error in closing %s\n",filename_try); + + return MZ_OK; + } + + return err; +} + +/***************************************************************************/ + +#if !defined(MZ_ZIP_NO_MAIN) +int main(int argc, const char *argv[]) { + minizip_opt options; + int32_t path_arg = 0; + int32_t err = 0; + int32_t i = 0; + uint8_t do_list = 0; + uint8_t do_extract = 0; + uint8_t do_erase = 0; + const char *path = NULL; + const char *password = NULL; + const char *destination = NULL; + const char *filename_to_extract = NULL; + + minizip_banner(); + if (argc == 1) { + minizip_help(); + return 0; } - else - { - do_help(); + + memset(&options, 0, sizeof(options)); + + options.compress_method = MZ_COMPRESS_METHOD_DEFLATE; + options.compress_level = MZ_COMPRESS_LEVEL_DEFAULT; + + /* Parse command line options */ + for (i = 1; i < argc; i += 1) { + printf("%s ", argv[i]); + if (argv[i][0] == '-') { + char c = argv[i][1]; + if ((c == 'l') || (c == 'L')) + do_list = 1; + else if ((c == 'x') || (c == 'X')) + do_extract = 1; + else if ((c == 'e') || (c == 'E')) + do_erase = 1; + else if ((c == 'a') || (c == 'A')) + options.append = 1; + else if ((c == 'o') || (c == 'O')) + options.overwrite = 1; + else if ((c == 'f') || (c == 'F')) + options.follow_links = 1; + else if ((c == 'y') || (c == 'Y')) + options.store_links = 1; + else if ((c == 'i') || (c == 'I')) + options.include_path = 1; + else if ((c == 'z') || (c == 'Z')) + options.zip_cd = 1; + else if ((c == 'v') || (c == 'V')) + options.verbose = 1; + else if ((c >= '0') && (c <= '9')) { + options.compress_level = (int16_t)atoi(&argv[i][1]); + if (options.compress_level == 0) + options.compress_method = MZ_COMPRESS_METHOD_STORE; + } else if ((c == 'b') || (c == 'B')) +# ifdef HAVE_BZIP2 + options.compress_method = MZ_COMPRESS_METHOD_BZIP2; +# else + err = MZ_SUPPORT_ERROR; +# endif + else if ((c == 'g') || (c == 'G')) +# ifdef HAVE_PPMD + options.compress_method = MZ_COMPRESS_METHOD_PPMD; +# else + err = MZ_SUPPORT_ERROR; +# endif + else if ((c == 'm') || (c == 'M')) +# ifdef HAVE_LZMA + options.compress_method = MZ_COMPRESS_METHOD_LZMA; +# else + err = MZ_SUPPORT_ERROR; +# endif + else if ((c == 'n') || (c == 'N')) +# if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP) + options.compress_method = MZ_COMPRESS_METHOD_XZ; +# else + err = MZ_SUPPORT_ERROR; +# endif + else if ((c == 't') || (c == 'T')) +# ifdef HAVE_ZSTD + options.compress_method = MZ_COMPRESS_METHOD_ZSTD; +# else + err = MZ_SUPPORT_ERROR; +# endif + else if ((c == 's') || (c == 'S')) +# ifdef HAVE_WZAES + options.aes = 1; +# else + err = MZ_SUPPORT_ERROR; +# endif + else if (((c == 'c') || (c == 'C')) && (i + 1 < argc)) { + options.encoding = (int32_t)atoi(argv[i + 1]); + i += 1; + } else if (((c == 'k') || (c == 'K')) && (i + 1 < argc)) { + options.disk_size = (int64_t)atoi(argv[i + 1]) * 1024; + printf("%s ", argv[i + 1]); + i += 1; + } else if (((c == 'd') || (c == 'D')) && (i + 1 < argc)) { + destination = argv[i + 1]; + printf("%s ", argv[i + 1]); + i += 1; + } else if (((c == 'p') || (c == 'P')) && (i + 1 < argc)) { +# ifndef MZ_ZIP_NO_ENCRYPTION + password = argv[i + 1]; + printf("*** "); +# else + err = MZ_SUPPORT_ERROR; +# endif + i += 1; + } + } else if (path_arg == 0) + path_arg = i; } + printf("\n"); - free(buf); - return 0; + if (err == MZ_SUPPORT_ERROR) { + printf("Feature not supported\n"); + return err; + } + + if (path_arg == 0) { + minizip_help(); + return 0; + } + + path = argv[path_arg]; + + if (do_list) { + /* List archive contents */ + err = minizip_list(path, options.encoding); + } else if (do_extract) { + if (argc > path_arg + 1) + filename_to_extract = argv[path_arg + 1]; + + /* Extract archive */ + err = minizip_extract(path, filename_to_extract, destination, password, &options); + } else if (do_erase) { + /* Erase file in archive */ + err = minizip_erase(path, NULL, argc - (path_arg + 1), &argv[path_arg + 1]); + } else { + /* Add files to archive */ + err = minizip_add(path, password, &options, argc - (path_arg + 1), &argv[path_arg + 1]); + } + + return err; } +#endif diff --git a/thirdparty/minizip/minizip.qbs b/thirdparty/minizip/minizip.qbs index 7f2b51399..1c63d5925 100644 --- a/thirdparty/minizip/minizip.qbs +++ b/thirdparty/minizip/minizip.qbs @@ -3,12 +3,22 @@ Project { property stringList srcFiles: { var sources = [ - "ioapi.c", - "mztools.c", - "zip.c" + "compat/ioapi.c", + "compat/unzip.c", + "compat/zip.c", + "mz_zip.c", + "mz_os.c", + "mz_strm.c", + "mz_strm_buf.c", + "mz_strm_mem.c", + "mz_crypt.c" ]; if(qbs.targetOS.contains("windows")) { - sources.push("../minizip/iowin32.c") + sources.push("mz_os_win32.c") + sources.push("mz_strm_os_win32.c") + } else { + sources.push("mz_os_posix.c") + sources.push("mz_strm_os_posix.c") } return sources; diff --git a/thirdparty/minizip/minizip/ioapi.h b/thirdparty/minizip/minizip/ioapi.h deleted file mode 100644 index 908468f04..000000000 --- a/thirdparty/minizip/minizip/ioapi.h +++ /dev/null @@ -1,204 +0,0 @@ -/* ioapi.h -- IO base function header for compress/uncompress .zip - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - Changes - - Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) - Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. - More if/def section may be needed to support other platforms - Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. - (but you should use iowin32.c for windows instead) - -*/ - -#ifndef _ZLIBIOAPI64_H -#define _ZLIBIOAPI64_H - -#if (!defined(_WIN32)) && (!defined(WIN32)) - - // Linux needs this to support file operation on files larger then 4+GB - // But might need better if/def to select just the platforms that needs them. - - #ifndef __USE_FILE_OFFSET64 - #define __USE_FILE_OFFSET64 - #endif - #ifndef __USE_LARGEFILE64 - #define __USE_LARGEFILE64 - #endif - #ifndef _LARGEFILE64_SOURCE - #define _LARGEFILE64_SOURCE - #endif - #ifndef _FILE_OFFSET_BIT - #define _FILE_OFFSET_BIT 64 - #endif -#endif - -#include -#include -#include "zlib.h" - -#if defined(USE_FILE32API) -#define fopen64 fopen -#define ftello64 ftell -#define fseeko64 fseek -#else -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__ANDROID__) - #define fopen64 fopen - #define ftello64 ftello - #define fseeko64 fseeko -#endif -#ifdef _MSC_VER - #define fopen64 fopen - #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) - #define ftello64 _ftelli64 - #define fseeko64 _fseeki64 - #else // old MSC - #define ftello64 ftell - #define fseeko64 fseek - #endif -#endif -#endif -/* -#ifndef ZPOS64_T - #ifdef _WIN32 - #define ZPOS64_T fpos_t - #else - #include - #define ZPOS64_T uint64_t - #endif -#endif -*/ - -#ifdef HAVE_MINIZIP64_CONF_H -#include "mz64conf.h" -#endif - -/* a type choosen by DEFINE */ -#ifdef HAVE_64BIT_INT_CUSTOM -typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; -#else -#ifdef HAS_STDINT_H -#include "stdint.h" -typedef uint64_t ZPOS64_T; -#else - - -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef unsigned __int64 ZPOS64_T; -#else -typedef unsigned long long int ZPOS64_T; -#endif -#endif -#endif - - - -#ifdef __cplusplus -extern "C" { -#endif - - -#define ZLIB_FILEFUNC_SEEK_CUR (1) -#define ZLIB_FILEFUNC_SEEK_END (2) -#define ZLIB_FILEFUNC_SEEK_SET (0) - -#define ZLIB_FILEFUNC_MODE_READ (1) -#define ZLIB_FILEFUNC_MODE_WRITE (2) -#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) - -#define ZLIB_FILEFUNC_MODE_EXISTING (4) -#define ZLIB_FILEFUNC_MODE_CREATE (8) - - -#ifndef ZCALLBACK - #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) - #define ZCALLBACK CALLBACK - #else - #define ZCALLBACK - #endif -#endif - - - - -typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); -typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); -typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); - -typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); - - -/* here is the "old" 32 bits structure structure */ -typedef struct zlib_filefunc_def_s -{ - open_file_func zopen_file; - read_file_func zread_file; - write_file_func zwrite_file; - tell_file_func ztell_file; - seek_file_func zseek_file; - close_file_func zclose_file; - testerror_file_func zerror_file; - voidpf opaque; -} zlib_filefunc_def; - -typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); -typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); - -typedef struct zlib_filefunc64_def_s -{ - open64_file_func zopen64_file; - read_file_func zread_file; - write_file_func zwrite_file; - tell64_file_func ztell64_file; - seek64_file_func zseek64_file; - close_file_func zclose_file; - testerror_file_func zerror_file; - voidpf opaque; -} zlib_filefunc64_def; - -void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); - -/* now internal definition, only for zip.c and unzip.h */ -typedef struct zlib_filefunc64_32_def_s -{ - zlib_filefunc64_def zfile_func64; - open_file_func zopen32_file; - tell_file_func ztell32_file; - seek_file_func zseek32_file; -} zlib_filefunc64_32_def; - - -#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) -#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) -//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) -//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) -#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) -#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) - -voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); -long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); -ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); - -void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); - -#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) -#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) -#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/thirdparty/minizip/minizip/iowin32.h b/thirdparty/minizip/minizip/iowin32.h deleted file mode 100644 index 0ca0969a7..000000000 --- a/thirdparty/minizip/minizip/iowin32.h +++ /dev/null @@ -1,28 +0,0 @@ -/* iowin32.h -- IO base function header for compress/uncompress .zip - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - -*/ - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - -void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); -void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def)); -void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def)); - -#ifdef __cplusplus -} -#endif diff --git a/thirdparty/minizip/minizip/mztools.h b/thirdparty/minizip/minizip/mztools.h deleted file mode 100644 index 88b34592b..000000000 --- a/thirdparty/minizip/minizip/mztools.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - Additional tools for Minizip - Code: Xavier Roche '2004 - License: Same as ZLIB (www.gzip.org) -*/ - -#ifndef _zip_tools_H -#define _zip_tools_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#include "unzip.h" - -/* Repair a ZIP file (missing central directory) - file: file to recover - fileOut: output file after recovery - fileOutTmp: temporary file name used for recovery -*/ -extern int ZEXPORT unzRepair(const char* file, - const char* fileOut, - const char* fileOutTmp, - uLong* nRecovered, - uLong* bytesRecovered); - -#endif diff --git a/thirdparty/minizip/minizip/unzip.h b/thirdparty/minizip/minizip/unzip.h deleted file mode 100644 index 3183968b7..000000000 --- a/thirdparty/minizip/minizip/unzip.h +++ /dev/null @@ -1,437 +0,0 @@ -/* unzip.h -- IO for uncompress .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications of Unzip for Zip64 - Copyright (C) 2007-2008 Even Rouault - - Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - --------------------------------------------------------------------------------- - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - --------------------------------------------------------------------------------- - - Changes - - See header of unzip64.c - -*/ - -#ifndef _unz64_H -#define _unz64_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.h" -#endif - -#ifdef HAVE_BZIP2 -#include "bzlib.h" -#endif - -#define Z_BZIP2ED 12 - -#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagunzFile__ { int unused; } unzFile__; -typedef unzFile__ *unzFile; -#else -typedef voidp unzFile; -#endif - - -#define UNZ_OK (0) -#define UNZ_END_OF_LIST_OF_FILE (-100) -#define UNZ_ERRNO (Z_ERRNO) -#define UNZ_EOF (0) -#define UNZ_PARAMERROR (-102) -#define UNZ_BADZIPFILE (-103) -#define UNZ_INTERNALERROR (-104) -#define UNZ_CRCERROR (-105) - -/* tm_unz contain date/time info */ -typedef struct tm_unz_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_unz; - -/* unz_global_info structure contain global data about the ZIPfile - These data comes from the end of central dir */ -typedef struct unz_global_info64_s -{ - ZPOS64_T number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info64; - -typedef struct unz_global_info_s -{ - uLong number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info; - -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_info64_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - ZPOS64_T compressed_size; /* compressed size 8 bytes */ - ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info64; - -typedef struct unz_file_info_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - uLong compressed_size; /* compressed size 4 bytes */ - uLong uncompressed_size; /* uncompressed size 4 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info; - -extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, - const char* fileName2, - int iCaseSensitivity)); -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) -*/ - - -extern unzFile ZEXPORT unzOpen OF((const char *path)); -extern unzFile ZEXPORT unzOpen64 OF((const void *path)); -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer - "zlib/zlib113.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. - the "64" function take a const void* pointer, because the path is just the - value passed to the open64_file_func callback. - Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path - is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* - does not describe the reality -*/ - - -extern unzFile ZEXPORT unzOpen2 OF((const char *path, - zlib_filefunc_def* pzlib_filefunc_def)); -/* - Open a Zip file, like unzOpen, but provide a set of file low level API - for read/write the zip file (see ioapi.h) -*/ - -extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, - zlib_filefunc64_def* pzlib_filefunc_def)); -/* - Open a Zip file, like unz64Open, but provide a set of file low level API - for read/write the zip file (see ioapi.h) -*/ - -extern int ZEXPORT unzClose OF((unzFile file)); -/* - Close a ZipFile opened with unzipOpen. - If there is files inside the .Zip opened with unzOpenCurrentFile (see later), - these files MUST be closed with unzipCloseCurrentFile before call unzipClose. - return UNZ_OK if there is no problem. */ - -extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, - unz_global_info *pglobal_info)); - -extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, - unz_global_info64 *pglobal_info)); -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ - - -extern int ZEXPORT unzGetGlobalComment OF((unzFile file, - char *szComment, - uLong uSizeBuf)); -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ - - -/***************************************************************************/ -/* Unzip package allow you browse the directory of the zipfile */ - -extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ - -extern int ZEXPORT unzGoToNextFile OF((unzFile file)); -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ - -extern int ZEXPORT unzLocateFile OF((unzFile file, - const char *szFileName, - int iCaseSensitivity)); -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ - - -/* ****************************************** */ -/* Ryan supplied functions */ -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_pos_s -{ - uLong pos_in_zip_directory; /* offset in zip file directory */ - uLong num_of_file; /* # of file */ -} unz_file_pos; - -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos); - -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos); - -typedef struct unz64_file_pos_s -{ - ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ - ZPOS64_T num_of_file; /* # of file */ -} unz64_file_pos; - -extern int ZEXPORT unzGetFilePos64( - unzFile file, - unz64_file_pos* file_pos); - -extern int ZEXPORT unzGoToFilePos64( - unzFile file, - const unz64_file_pos* file_pos); - -/* ****************************************** */ - -extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, - unz_file_info64 *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); -/* - Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about - the current file - if szFileName!=NULL, the filemane string will be copied in szFileName - (fileNameBufferSize is the size of the buffer) - if extraField!=NULL, the extra field information will be copied in extraField - (extraFieldBufferSize is the size of the buffer). - This is the Central-header version of the extra field - if szComment!=NULL, the comment string of the file will be copied in szComment - (commentBufferSize is the size of the buffer) -*/ - - -/** Addition for GDAL : START */ - -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); - -/** Addition for GDAL : END */ - - -/***************************************************************************/ -/* for reading the content of the current zipfile, you can open it, read data - from it, and close it (you can close it before reading all the file) - */ - -extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); -/* - Open for reading data the current file in the zipfile. - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, - const char* password)); -/* - Open for reading data the current file in the zipfile. - password is a crypting password - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, - int* method, - int* level, - int raw)); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - -extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, - int* method, - int* level, - int raw, - const char* password)); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - - -extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ - -extern int ZEXPORT unzReadCurrentFile OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read bytes from the current file (opened by unzOpenCurrentFile) - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ - -extern z_off_t ZEXPORT unztell OF((unzFile file)); - -extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); -/* - Give the current position in uncompressed data -*/ - -extern int ZEXPORT unzeof OF((unzFile file)); -/* - return 1 if the end of file was reached, 0 elsewhere -*/ - -extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ - -/***************************************************************************/ - -/* Get the current file offset */ -extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); -extern uLong ZEXPORT unzGetOffset (unzFile file); - -/* Set the current file offset */ -extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); - - - -#ifdef __cplusplus -} -#endif - -#endif /* _unz64_H */ diff --git a/thirdparty/minizip/minizip/zip.h b/thirdparty/minizip/minizip/zip.h deleted file mode 100644 index 8aaebb623..000000000 --- a/thirdparty/minizip/minizip/zip.h +++ /dev/null @@ -1,362 +0,0 @@ -/* zip.h -- IO on .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - --------------------------------------------------------------------------- - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - --------------------------------------------------------------------------- - - Changes - - See header of zip.h - -*/ - -#ifndef _zip12_H -#define _zip12_H - -#ifdef __cplusplus -extern "C" { -#endif - -//#define HAVE_BZIP2 - -#ifndef _ZLIB_H -#include "zlib.h" -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.h" -#endif - -#ifdef HAVE_BZIP2 -#include "bzlib.h" -#endif - -#define Z_BZIP2ED 12 - -#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagzipFile__ { int unused; } zipFile__; -typedef zipFile__ *zipFile; -#else -typedef voidp zipFile; -#endif - -#define ZIP_OK (0) -#define ZIP_EOF (0) -#define ZIP_ERRNO (Z_ERRNO) -#define ZIP_PARAMERROR (-102) -#define ZIP_BADZIPFILE (-103) -#define ZIP_INTERNALERROR (-104) - -#ifndef DEF_MEM_LEVEL -# if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -# else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -# endif -#endif -/* default memLevel */ - -/* tm_zip contain date/time info */ -typedef struct tm_zip_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_zip; - -typedef struct -{ - tm_zip tmz_date; /* date in understandable format */ - uLong dosDate; /* if dos_date == 0, tmu_date is used */ -/* uLong flag; */ /* general purpose bit flag 2 bytes */ - - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ -} zip_fileinfo; - -typedef const char* zipcharpc; - - -#define APPEND_STATUS_CREATE (0) -#define APPEND_STATUS_CREATEAFTER (1) -#define APPEND_STATUS_ADDINZIP (2) - -extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); -extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); -/* - Create a zipfile. - pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on - an Unix computer "zlib/zlib113.zip". - if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip - will be created at the end of the file. - (useful if the file contain a self extractor code) - if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will - add files in existing zip (be sure you don't add file that doesn't exist) - If the zipfile cannot be opened, the return value is NULL. - Else, the return value is a zipFile Handle, usable with other function - of this zip package. -*/ - -/* Note : there is no delete function into a zipfile. - If you want delete file into a zipfile, you must open a zipfile, and create another - Of couse, you can use RAW reading and writing to copy the file you did not want delte -*/ - -extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, - int append, - zipcharpc* globalcomment, - zlib_filefunc_def* pzlib_filefunc_def)); - -extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, - int append, - zipcharpc* globalcomment, - zlib_filefunc64_def* pzlib_filefunc_def)); - -extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level)); - -extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int zip64)); - -/* - Open a file in the ZIP for writing. - filename : the filename in zip (if NULL, '-' without quote will be used - *zipfi contain supplemental information - if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local - contains the extrafield data the the local header - if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global - contains the extrafield data the the local header - if comment != NULL, comment contain the comment string - method contain the compression method (0 for store, Z_DEFLATED for deflate) - level contain the level of compression (can be Z_DEFAULT_COMPRESSION) - zip64 is set to 1 if a zip64 extended information block should be added to the local file header. - this MUST be '1' if the uncompressed size is >= 0xffffffff. - -*/ - - -extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw)); - - -extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int zip64)); -/* - Same than zipOpenNewFileInZip, except if raw=1, we write raw file - */ - -extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting)); - -extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - int zip64 - )); - -/* - Same than zipOpenNewFileInZip2, except - windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 - password : crypting password (NULL for no crypting) - crcForCrypting : crc of file to compress (needed for crypting) - */ - -extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase - )); - - -extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, - const char* filename, - const zip_fileinfo* zipfi, - const void* extrafield_local, - uInt size_extrafield_local, - const void* extrafield_global, - uInt size_extrafield_global, - const char* comment, - int method, - int level, - int raw, - int windowBits, - int memLevel, - int strategy, - const char* password, - uLong crcForCrypting, - uLong versionMadeBy, - uLong flagBase, - int zip64 - )); -/* - Same than zipOpenNewFileInZip4, except - versionMadeBy : value for Version made by field - flag : value for flag field (compression level info will be added) - */ - - -extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, - const void* buf, - unsigned len)); -/* - Write data in the zipfile -*/ - -extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); -/* - Close the current file in the zipfile -*/ - -extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, - uLong uncompressed_size, - uLong crc32)); - -extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, - ZPOS64_T uncompressed_size, - uLong crc32)); - -/* - Close the current file in the zipfile, for file opened with - parameter raw=1 in zipOpenNewFileInZip2 - uncompressed_size and crc32 are value for the uncompressed size -*/ - -extern int ZEXPORT zipClose OF((zipFile file, - const char* global_comment)); -/* - Close the zipfile -*/ - - -extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); -/* - zipRemoveExtraInfoBlock - Added by Mathias Svensson - - Remove extra information block from a extra information data for the local file header or central directory header - - It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode. - - 0x0001 is the signature header for the ZIP64 extra information blocks - - usage. - Remove ZIP64 Extra information from a central director extra field data - zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001); - - Remove ZIP64 Extra information from a Local File Header extra field data - zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001); -*/ - -#ifdef __cplusplus -} -#endif - -#endif /* _zip64_H */ diff --git a/thirdparty/minizip/minizip/zipcrypt.h b/thirdparty/minizip/minizip/zipcrypt.h deleted file mode 100644 index a01d08d93..000000000 --- a/thirdparty/minizip/minizip/zipcrypt.h +++ /dev/null @@ -1,131 +0,0 @@ -/* crypt.h -- base code for crypt/uncrypt ZIPfile - - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This code is a modified version of crypting code in Infozip distribution - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - - If you don't need crypting in your application, just define symbols - NOCRYPT and NOUNCRYPT. - - This code support the "Traditional PKWARE Encryption". - - The new AES encryption added on Zip format by Winzip (see the page - http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong - Encryption is not supported. -*/ - -#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) - -/*********************************************************************** - * Return the next byte in the pseudo-random sequence - */ -static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) -{ - unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an - * unpredictable manner on 16-bit systems; not a problem - * with any known compiler so far, though */ - - temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; - return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); -} - -/*********************************************************************** - * Update the encryption keys with the next byte of plain text - */ -static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) -{ - (*(pkeys+0)) = CRC32((*(pkeys+0)), c); - (*(pkeys+1)) += (*(pkeys+0)) & 0xff; - (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; - { - register int keyshift = (int)((*(pkeys+1)) >> 24); - (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); - } - return c; -} - - -/*********************************************************************** - * Initialize the encryption keys and the random header according to - * the given password. - */ -static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) -{ - *(pkeys+0) = 305419896L; - *(pkeys+1) = 591751049L; - *(pkeys+2) = 878082192L; - while (*passwd != '\0') { - update_keys(pkeys,pcrc_32_tab,(int)*passwd); - passwd++; - } -} - -#define zdecode(pkeys,pcrc_32_tab,c) \ - (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) - -#define zencode(pkeys,pcrc_32_tab,c,t) \ - (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) - -#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED - -#define RAND_HEAD_LEN 12 - /* "last resort" source for second part of crypt seed pattern */ -# ifndef ZCR_SEED2 -# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ -# endif - -static int crypthead(const char* passwd, /* password string */ - unsigned char* buf, /* where to write header */ - int bufSize, - unsigned long* pkeys, - const unsigned long* pcrc_32_tab, - unsigned long crcForCrypting) -{ - int n; /* index in random header */ - int t; /* temporary */ - int c; /* random byte */ - unsigned char header[RAND_HEAD_LEN-2]; /* random header */ - static unsigned calls = 0; /* ensure different random header each time */ - - if (bufSize> 7) & 0xff; - header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); - } - /* Encrypt random header (last two bytes is high word of crc) */ - init_keys(passwd, pkeys, pcrc_32_tab); - for (n = 0; n < RAND_HEAD_LEN-2; n++) - { - buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); - } - buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); - buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); - return n; -} - -#endif diff --git a/thirdparty/minizip/mz.h b/thirdparty/minizip/mz.h new file mode 100644 index 000000000..2aa883074 --- /dev/null +++ b/thirdparty/minizip/mz.h @@ -0,0 +1,277 @@ +/* mz.h -- Errors codes, zip flags and magic + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_H +#define MZ_H + +/***************************************************************************/ + +/* MZ_VERSION */ +#define MZ_VERSION ("4.2.1") +#define MZ_VERSION_BUILD (0x040201) + +/* MZ_ERROR */ +#define MZ_OK (0) /* zlib */ +#define MZ_STREAM_ERROR (-1) /* zlib */ +#define MZ_DATA_ERROR (-3) /* zlib */ +#define MZ_MEM_ERROR (-4) /* zlib */ +#define MZ_BUF_ERROR (-5) /* zlib */ +#define MZ_VERSION_ERROR (-6) /* zlib */ + +#define MZ_END_OF_LIST (-100) +#define MZ_END_OF_STREAM (-101) + +#define MZ_PARAM_ERROR (-102) +#define MZ_FORMAT_ERROR (-103) +#define MZ_INTERNAL_ERROR (-104) +#define MZ_CRC_ERROR (-105) +#define MZ_CRYPT_ERROR (-106) +#define MZ_EXIST_ERROR (-107) +#define MZ_PASSWORD_ERROR (-108) +#define MZ_SUPPORT_ERROR (-109) +#define MZ_HASH_ERROR (-110) +#define MZ_OPEN_ERROR (-111) +#define MZ_CLOSE_ERROR (-112) +#define MZ_SEEK_ERROR (-113) +#define MZ_TELL_ERROR (-114) +#define MZ_READ_ERROR (-115) +#define MZ_WRITE_ERROR (-116) +#define MZ_SIGN_ERROR (-117) +#define MZ_SYMLINK_ERROR (-118) + +/* MZ_OPEN */ +#define MZ_OPEN_MODE_READ (0x01) +#define MZ_OPEN_MODE_WRITE (0x02) +#define MZ_OPEN_MODE_READWRITE (MZ_OPEN_MODE_READ | MZ_OPEN_MODE_WRITE) +#define MZ_OPEN_MODE_APPEND (0x04) +#define MZ_OPEN_MODE_CREATE (0x08) +#define MZ_OPEN_MODE_EXISTING (0x10) +#define MZ_OPEN_MODE_NOFOLLOW (0x20) + +/* MZ_SEEK */ +#define MZ_SEEK_SET (0) +#define MZ_SEEK_CUR (1) +#define MZ_SEEK_END (2) + +/* MZ_COMPRESS */ +#define MZ_COMPRESS_METHOD_STORE (0) +#define MZ_COMPRESS_METHOD_DEFLATE (8) +#define MZ_COMPRESS_METHOD_BZIP2 (12) +#define MZ_COMPRESS_METHOD_LZMA (14) +#define MZ_COMPRESS_METHOD_ZSTD (93) +#define MZ_COMPRESS_METHOD_XZ (95) +#define MZ_COMPRESS_METHOD_PPMD (98) +#define MZ_COMPRESS_METHOD_AES (99) + +#define MZ_COMPRESS_LEVEL_DEFAULT (-1) +#define MZ_COMPRESS_LEVEL_FAST (2) +#define MZ_COMPRESS_LEVEL_NORMAL (6) +#define MZ_COMPRESS_LEVEL_BEST (9) + +/* MZ_ZIP_FLAG */ +#define MZ_ZIP_FLAG_ENCRYPTED (1 << 0) +#define MZ_ZIP_FLAG_LZMA_EOS_MARKER (1 << 1) +#define MZ_ZIP_FLAG_DEFLATE_MAX (1 << 1) +#define MZ_ZIP_FLAG_DEFLATE_NORMAL (0) +#define MZ_ZIP_FLAG_DEFLATE_FAST (1 << 2) +#define MZ_ZIP_FLAG_DEFLATE_SUPER_FAST (MZ_ZIP_FLAG_DEFLATE_FAST | MZ_ZIP_FLAG_DEFLATE_MAX) +#define MZ_ZIP_FLAG_DATA_DESCRIPTOR (1 << 3) +#define MZ_ZIP_FLAG_UTF8 (1 << 11) +#define MZ_ZIP_FLAG_MASK_LOCAL_INFO (1 << 13) + +/* MZ_ZIP_EXTENSION */ +#define MZ_ZIP_EXTENSION_ZIP64 (0x0001) +#define MZ_ZIP_EXTENSION_NTFS (0x000a) +#define MZ_ZIP_EXTENSION_AES (0x9901) +#define MZ_ZIP_EXTENSION_UNIX1 (0x000d) +#define MZ_ZIP_EXTENSION_SIGN (0x10c5) +#define MZ_ZIP_EXTENSION_HASH (0x1a51) +#define MZ_ZIP_EXTENSION_CDCD (0xcdcd) + +/* MZ_ZIP64 */ +#define MZ_ZIP64_AUTO (0) +#define MZ_ZIP64_FORCE (1) +#define MZ_ZIP64_DISABLE (2) + +/* MZ_HOST_SYSTEM */ +#define MZ_HOST_SYSTEM(VERSION_MADEBY) ((uint8_t)(VERSION_MADEBY >> 8)) +#define MZ_HOST_SYSTEM_MSDOS (0) +#define MZ_HOST_SYSTEM_UNIX (3) +#define MZ_HOST_SYSTEM_WINDOWS_NTFS (10) +#define MZ_HOST_SYSTEM_RISCOS (13) +#define MZ_HOST_SYSTEM_OSX_DARWIN (19) + +/* MZ_PKCRYPT */ +#define MZ_PKCRYPT_HEADER_SIZE (12) + +/* MZ_AES */ +#define MZ_AES_VERSION (1) +#define MZ_AES_MODE_ECB (0) +#define MZ_AES_MODE_CBC (1) +#define MZ_AES_MODE_GCM (2) +#define MZ_AES_STRENGTH_128 (1) +#define MZ_AES_STRENGTH_192 (2) +#define MZ_AES_STRENGTH_256 (3) +#define MZ_AES_KEY_LENGTH_MAX (32) +#define MZ_AES_BLOCK_SIZE (16) +#define MZ_AES_FOOTER_SIZE (10) + +/* MZ_HASH */ +#define MZ_HASH_MD5 (10) +#define MZ_HASH_MD5_SIZE (16) +#define MZ_HASH_SHA1 (20) +#define MZ_HASH_SHA1_SIZE (20) +#define MZ_HASH_SHA224 (22) +#define MZ_HASH_SHA224_SIZE (28) +#define MZ_HASH_SHA256 (23) +#define MZ_HASH_SHA256_SIZE (32) +#define MZ_HASH_SHA384 (24) +#define MZ_HASH_SHA384_SIZE (48) +#define MZ_HASH_SHA512 (25) +#define MZ_HASH_SHA512_SIZE (64) +#define MZ_HASH_MAX_SIZE (256) + +/* MZ_ENCODING */ +#define MZ_ENCODING_CODEPAGE_437 (437) +#define MZ_ENCODING_CODEPAGE_932 (932) +#define MZ_ENCODING_CODEPAGE_936 (936) +#define MZ_ENCODING_CODEPAGE_950 (950) +#define MZ_ENCODING_UTF8 (65001) + +/* MZ_UTILITY */ +#define MZ_UNUSED(SYMBOL) ((void)SYMBOL) + +#if defined(_WIN32) && defined(MZ_EXPORTS) +# define MZ_EXPORT __declspec(dllexport) +#else +# define MZ_EXPORT +#endif + +/***************************************************************************/ + +#include /* size_t, NULL, malloc */ +#include /* time_t, time() */ +#include /* memset, strncpy, strlen */ +#include + +#include "mz_config.h" + +#if HAVE_STDINT_H +# include +#elif defined(__has_include) +# if __has_include() +# include +# endif +#endif + +#ifndef INT8_MAX +typedef signed char int8_t; +#endif +#ifndef INT16_MAX +typedef short int16_t; +#endif +#ifndef INT32_MAX +typedef int int32_t; +#endif +#ifndef INT64_MAX +typedef long long int64_t; +#endif +#ifndef UINT8_MAX +typedef unsigned char uint8_t; +#endif +#ifndef UINT16_MAX +typedef unsigned short uint16_t; +#endif +#ifndef UINT32_MAX +typedef unsigned int uint32_t; +#endif +#ifndef UINT64_MAX +typedef unsigned long long uint64_t; +#endif + +#if HAVE_INTTYPES_H +# include +#elif defined(__has_include) +# if __has_include() +# include +# endif +#endif + +#ifndef PRId8 +# define PRId8 "hhd" +#endif +#ifndef PRIu8 +# define PRIu8 "hhu" +#endif +#ifndef PRIx8 +# define PRIx8 "hhx" +#endif +#ifndef PRId16 +# define PRId16 "hd" +#endif +#ifndef PRIu16 +# define PRIu16 "hu" +#endif +#ifndef PRIx16 +# define PRIx16 "hx" +#endif +#ifndef PRId32 +# define PRId32 "d" +#endif +#ifndef PRIu32 +# define PRIu32 "u" +#endif +#ifndef PRIx32 +# define PRIx32 "x" +#endif +#if ULONG_MAX == 0xfffffffful +# ifndef PRId64 +# define PRId64 "ld" +# endif +# ifndef PRIu64 +# define PRIu64 "lu" +# endif +# ifndef PRIx64 +# define PRIx64 "lx" +# endif +#else +# ifndef PRId64 +# define PRId64 "lld" +# endif +# ifndef PRIu64 +# define PRIu64 "llu" +# endif +# ifndef PRIx64 +# define PRIx64 "llx" +# endif +#endif + +#ifndef INT16_MAX +# define INT16_MAX 32767 +#endif +#ifndef INT32_MAX +# define INT32_MAX 2147483647L +#endif +#ifndef INT64_MAX +# define INT64_MAX 9223372036854775807LL +#endif +#ifndef UINT16_MAX +# define UINT16_MAX 65535U +#endif +#ifndef UINT32_MAX +# define UINT32_MAX 4294967295UL +#endif +#ifndef UINT64_MAX +# define UINT64_MAX 18446744073709551615ULL +#endif + +/***************************************************************************/ + +#endif diff --git a/thirdparty/minizip/mz_config.h b/thirdparty/minizip/mz_config.h new file mode 100644 index 000000000..d9747f0d9 --- /dev/null +++ b/thirdparty/minizip/mz_config.h @@ -0,0 +1,28 @@ +#ifndef MZ_CONFIG_H +#define MZ_CONFIG_H + +// Define to 1 if you have the header file. +#define HAVE_DIRENT_H 0 + +// Define to 1 if you have the header file. +#define HAVE_SYS_DIRENT_H 0 + +// Define to 1 if you have the header file. +#define HAVE_INTTYPES_H 0 + +// Define to 1 if you have the header file. +#define HAVE_STDINT_H 1 + +// Define to 1 if DIR* is defined. +#define HAVE_PDIR 0 + +// Define to 1 if fseeko() is defined. +#define HAVE_FSEEKO 0 + +// Define to 1 if symlink() is defined. +#define HAVE_SYMLINK 0 + +// Define to 1 if readlink() is defined. +#define HAVE_READLINK 0 + +#endif diff --git a/thirdparty/minizip/mz_crypt.c b/thirdparty/minizip/mz_crypt.c new file mode 100644 index 000000000..997adf1a2 --- /dev/null +++ b/thirdparty/minizip/mz_crypt.c @@ -0,0 +1,182 @@ +/* mz_crypt.c -- Crypto/hash functions + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_os.h" +#include "mz_crypt.h" + +#if defined(HAVE_ZLIB) +# if !defined(ZLIB_COMPAT) +# include "zlib-ng.h" +# define ZLIB_PREFIX(x) zng_##x +# else +# include "zlib.h" +# define ZLIB_PREFIX(x) x +# endif +#elif defined(HAVE_LZMA) +# include "lzma.h" +#endif + +/***************************************************************************/ + +#if defined(MZ_ZIP_NO_CRYPTO) +int32_t mz_crypt_rand(uint8_t *buf, int32_t size) { + return mz_os_rand(buf, size); +} +#endif + +uint32_t mz_crypt_crc32_update(uint32_t value, const uint8_t *buf, int32_t size) { +#if defined(HAVE_ZLIB) +# ifndef ZLIB_VERNUM + /* HAVE_ZLIB but no ZLIB_VERNUM? */ + typedef uint32_t z_crc_t; +# elif (ZLIB_VERNUM & 0xf != 0xf) && (ZLIB_VERNUM < 0x1270) + /* Define z_crc_t in zlib 1.2.6 and less */ + typedef unsigned long z_crc_t; +# elif (ZLIB_VERNUM & 0xf == 0xf) && (ZLIB_VERNUM < 0x12df) + /* Define z_crc_t in zlib-ng 2.0.7 and less */ + typedef unsigned int z_crc_t; +# endif + return (uint32_t)ZLIB_PREFIX(crc32)((z_crc_t)value, buf, (uInt)size); +#elif defined(HAVE_LZMA) + return (uint32_t)lzma_crc32(buf, (size_t)size, (uint32_t)value); +#else + static uint32_t crc32_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, + 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, + 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, + 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, + 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, + 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, + 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, + 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, + 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, + 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, + 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, + 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + value = ~value; + + while (size > 0) { + value = (value >> 8) ^ crc32_table[(value ^ *buf) & 0xFF]; + + buf += 1; + size -= 1; + } + + return ~value; +#endif +} + +#if defined(HAVE_WZAES) +int32_t mz_crypt_pbkdf2(const uint8_t *password, int32_t password_length, const uint8_t *salt, int32_t salt_length, + uint32_t iteration_count, uint8_t *key, uint16_t key_length) { + void *hmac1 = NULL; + void *hmac2 = NULL; + void *hmac3 = NULL; + int32_t err = MZ_OK; + uint16_t i = 0; + uint32_t j = 0; + uint16_t k = 0; + uint16_t block_count = 0; + uint8_t uu[MZ_HASH_SHA1_SIZE]; + uint8_t ux[MZ_HASH_SHA1_SIZE]; + + if (!password || !salt || !key) + return MZ_PARAM_ERROR; + + memset(key, 0, key_length); + + hmac1 = mz_crypt_hmac_create(); + hmac2 = mz_crypt_hmac_create(); + hmac3 = mz_crypt_hmac_create(); + + if (!hmac1 || !hmac2 || !hmac3) { + err = MZ_MEM_ERROR; + goto pbkdf2_cleanup; + } + + mz_crypt_hmac_set_algorithm(hmac1, MZ_HASH_SHA1); + mz_crypt_hmac_set_algorithm(hmac2, MZ_HASH_SHA1); + mz_crypt_hmac_set_algorithm(hmac3, MZ_HASH_SHA1); + + err = mz_crypt_hmac_init(hmac1, password, password_length); + if (err == MZ_OK) + err = mz_crypt_hmac_init(hmac2, password, password_length); + if (err == MZ_OK) + err = mz_crypt_hmac_update(hmac2, salt, salt_length); + + block_count = 1 + ((uint16_t)key_length - 1) / MZ_HASH_SHA1_SIZE; + + for (i = 0; (err == MZ_OK) && (i < block_count); i += 1) { + memset(ux, 0, sizeof(ux)); + + err = mz_crypt_hmac_copy(hmac2, hmac3); + if (err != MZ_OK) + break; + + uu[0] = (uint8_t)((i + 1) >> 24); + uu[1] = (uint8_t)((i + 1) >> 16); + uu[2] = (uint8_t)((i + 1) >> 8); + uu[3] = (uint8_t)(i + 1); + + for (j = 0, k = 4; j < iteration_count; j += 1) { + err = mz_crypt_hmac_update(hmac3, uu, k); + if (err == MZ_OK) + err = mz_crypt_hmac_end(hmac3, uu, sizeof(uu)); + if (err != MZ_OK) + break; + + for (k = 0; k < MZ_HASH_SHA1_SIZE; k += 1) + ux[k] ^= uu[k]; + + err = mz_crypt_hmac_copy(hmac1, hmac3); + if (err != MZ_OK) + break; + } + + if (err != MZ_OK) + break; + + j = 0; + k = i * MZ_HASH_SHA1_SIZE; + + while (j < MZ_HASH_SHA1_SIZE && k < key_length) + key[k++] = ux[j++]; + } + +pbkdf2_cleanup: + /* hmac3 uses the same provider as hmac2, so it must be deleted + before the context is destroyed. */ + mz_crypt_hmac_delete(&hmac3); + mz_crypt_hmac_delete(&hmac1); + mz_crypt_hmac_delete(&hmac2); + + return err; +} +#endif + +/***************************************************************************/ diff --git a/thirdparty/minizip/mz_crypt.h b/thirdparty/minizip/mz_crypt.h new file mode 100644 index 000000000..65e059873 --- /dev/null +++ b/thirdparty/minizip/mz_crypt.h @@ -0,0 +1,65 @@ +/* mz_crypt.h -- Crypto/hash functions + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_CRYPT_H +#define MZ_CRYPT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +uint32_t mz_crypt_crc32_update(uint32_t value, const uint8_t *buf, int32_t size); + +int32_t mz_crypt_pbkdf2(const uint8_t *password, int32_t password_length, const uint8_t *salt, int32_t salt_length, + uint32_t iteration_count, uint8_t *key, uint16_t key_length); + +/***************************************************************************/ + +int32_t mz_crypt_rand(uint8_t *buf, int32_t size); + +void mz_crypt_sha_reset(void *handle); +int32_t mz_crypt_sha_begin(void *handle); +int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size); +int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size); +int32_t mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm); +void *mz_crypt_sha_create(void); +void mz_crypt_sha_delete(void **handle); + +void mz_crypt_aes_reset(void *handle); +int32_t mz_crypt_aes_encrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size); +int32_t mz_crypt_aes_encrypt_final(void *handle, uint8_t *buf, int32_t size, uint8_t *tag, int32_t tag_size); +int32_t mz_crypt_aes_decrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size); +int32_t mz_crypt_aes_decrypt_final(void *handle, uint8_t *buf, int32_t size, const uint8_t *tag, int32_t tag_size); +int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length); +int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length); +void mz_crypt_aes_set_mode(void *handle, int32_t mode); +void *mz_crypt_aes_create(void); +void mz_crypt_aes_delete(void **handle); + +void mz_crypt_hmac_reset(void *handle); +int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length); +int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size); +int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size); +int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle); +void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm); +void *mz_crypt_hmac_create(void); +void mz_crypt_hmac_delete(void **handle); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_crypt_apple.c b/thirdparty/minizip/mz_crypt_apple.c new file mode 100644 index 000000000..e3a9c6748 --- /dev/null +++ b/thirdparty/minizip/mz_crypt_apple.c @@ -0,0 +1,522 @@ +/* mz_crypt_apple.c -- Crypto/hash functions for Apple + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_crypt.h" + +#include +#include +#include +#include +#include +#include + +/***************************************************************************/ + +#ifndef MZ_TARGET_APPSTORE +# define MZ_TARGET_APPSTORE 1 +#endif + +/* Avoid use of private API for App Store as Apple does not allow it. Zip format doesn't need GCM. */ +#if !MZ_TARGET_APPSTORE +enum { + kCCModeGCM = 11, +}; + +CCCryptorStatus CCCryptorGCMReset(CCCryptorRef cryptorRef); +CCCryptorStatus CCCryptorGCMAddIV(CCCryptorRef cryptorRef, const void *iv, size_t ivLen); +CCCryptorStatus CCCryptorGCMAddAAD(CCCryptorRef cryptorRef, const void *aData, size_t aDataLen); +CCCryptorStatus CCCryptorGCMEncrypt(CCCryptorRef cryptorRef, const void *dataIn, size_t dataInLength, void *dataOut); +CCCryptorStatus CCCryptorGCMDecrypt(CCCryptorRef cryptorRef, const void *dataIn, size_t dataInLength, void *dataOut); +CCCryptorStatus CCCryptorGCMFinal(CCCryptorRef cryptorRef, void *tagOut, size_t *tagLength); +#endif + +/***************************************************************************/ + +int32_t mz_crypt_rand(uint8_t *buf, int32_t size) { + if (SecRandomCopyBytes(kSecRandomDefault, size, buf) != errSecSuccess) + return 0; + return size; +} + +/***************************************************************************/ + +typedef struct mz_crypt_sha_s { + union { + CC_SHA1_CTX ctx1; + CC_SHA256_CTX ctx256; + CC_SHA512_CTX ctx512; + }; + int32_t error; + int32_t initialized; + uint16_t algorithm; +} mz_crypt_sha; + +/***************************************************************************/ + +static const uint8_t mz_crypt_sha_digest_size[] = { + MZ_HASH_SHA1_SIZE, 0, MZ_HASH_SHA224_SIZE, MZ_HASH_SHA256_SIZE, MZ_HASH_SHA384_SIZE, MZ_HASH_SHA512_SIZE}; + +/***************************************************************************/ + +void mz_crypt_sha_reset(void *handle) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + + sha->error = 0; + sha->initialized = 0; +} + +int32_t mz_crypt_sha_begin(void *handle) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + + if (!sha) + return MZ_PARAM_ERROR; + + mz_crypt_sha_reset(handle); + + switch (sha->algorithm) { + case MZ_HASH_SHA1: + sha->error = CC_SHA1_Init(&sha->ctx1); + break; + case MZ_HASH_SHA224: + sha->error = CC_SHA224_Init(&sha->ctx256); + break; + case MZ_HASH_SHA256: + sha->error = CC_SHA256_Init(&sha->ctx256); + break; + case MZ_HASH_SHA384: + sha->error = CC_SHA384_Init(&sha->ctx512); + break; + case MZ_HASH_SHA512: + sha->error = CC_SHA512_Init(&sha->ctx512); + break; + default: + return MZ_PARAM_ERROR; + } + + if (!sha->error) + return MZ_HASH_ERROR; + + sha->initialized = 1; + return MZ_OK; +} + +int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + + if (!sha || !buf || !sha->initialized) + return MZ_PARAM_ERROR; + + switch (sha->algorithm) { + case MZ_HASH_SHA1: + sha->error = CC_SHA1_Update(&sha->ctx1, buf, size); + break; + case MZ_HASH_SHA224: + sha->error = CC_SHA224_Update(&sha->ctx256, buf, size); + break; + case MZ_HASH_SHA256: + sha->error = CC_SHA256_Update(&sha->ctx256, buf, size); + break; + case MZ_HASH_SHA384: + sha->error = CC_SHA384_Update(&sha->ctx512, buf, size); + break; + case MZ_HASH_SHA512: + sha->error = CC_SHA512_Update(&sha->ctx512, buf, size); + break; + } + + if (!sha->error) + return MZ_HASH_ERROR; + + return size; +} + +int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + + if (!sha || !digest || !sha->initialized) + return MZ_PARAM_ERROR; + if (digest_size < mz_crypt_sha_digest_size[sha->algorithm - MZ_HASH_SHA1]) + return MZ_PARAM_ERROR; + + switch (sha->algorithm) { + case MZ_HASH_SHA1: + sha->error = CC_SHA1_Final(digest, &sha->ctx1); + break; + case MZ_HASH_SHA224: + sha->error = CC_SHA224_Final(digest, &sha->ctx256); + break; + case MZ_HASH_SHA256: + sha->error = CC_SHA256_Final(digest, &sha->ctx256); + break; + case MZ_HASH_SHA384: + sha->error = CC_SHA384_Final(digest, &sha->ctx512); + break; + case MZ_HASH_SHA512: + sha->error = CC_SHA512_Final(digest, &sha->ctx512); + break; + } + + if (!sha->error) + return MZ_HASH_ERROR; + + return MZ_OK; +} + +int32_t mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + if (algorithm < MZ_HASH_SHA1 || algorithm > MZ_HASH_SHA512) + return MZ_PARAM_ERROR; + sha->algorithm = algorithm; + return MZ_OK; +} + +void *mz_crypt_sha_create(void) { + mz_crypt_sha *sha = (mz_crypt_sha *)calloc(1, sizeof(mz_crypt_sha)); + if (sha) { + memset(sha, 0, sizeof(mz_crypt_sha)); + sha->algorithm = MZ_HASH_SHA256; + } + return sha; +} + +void mz_crypt_sha_delete(void **handle) { + mz_crypt_sha *sha = NULL; + if (!handle) + return; + sha = (mz_crypt_sha *)*handle; + if (sha) { + mz_crypt_sha_reset(*handle); + free(sha); + } + *handle = NULL; +} + +/***************************************************************************/ + +typedef struct mz_crypt_aes_s { + CCCryptorRef crypt; + int32_t mode; + int32_t error; +} mz_crypt_aes; + +/***************************************************************************/ + +static void mz_crypt_aes_free(void *handle) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + + if (aes->crypt) + CCCryptorRelease(aes->crypt); + aes->crypt = NULL; +} + +void mz_crypt_aes_reset(void *handle) { + mz_crypt_aes_free(handle); +} + +int32_t mz_crypt_aes_encrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + size_t data_moved = 0; + + if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0 || !aes->crypt) + return MZ_PARAM_ERROR; + + if (aes->mode == MZ_AES_MODE_GCM) { +#if MZ_TARGET_APPSTORE + return MZ_SUPPORT_ERROR; +#else + if (aad && aad_size > 0) { + aes->error = CCCryptorGCMAddAAD(aes->crypt, aad, aad_size); + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + } + aes->error = CCCryptorGCMEncrypt(aes->crypt, buf, size, buf); +#endif + } else { + if (aad && aad_size > 0) + return MZ_PARAM_ERROR; + aes->error = CCCryptorUpdate(aes->crypt, buf, size, buf, size, &data_moved); + } + + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + + return size; +} + +int32_t mz_crypt_aes_encrypt_final(void *handle, uint8_t *buf, int32_t size, uint8_t *tag, int32_t tag_size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; +#if !MZ_TARGET_APPSTORE + size_t tag_outsize = tag_size; +#endif + + if (!aes || !tag || !tag_size || !aes->crypt || aes->mode != MZ_AES_MODE_GCM) + return MZ_PARAM_ERROR; + +#if MZ_TARGET_APPSTORE + return MZ_SUPPORT_ERROR; +#else + aes->error = CCCryptorGCMEncrypt(aes->crypt, buf, size, buf); + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + + aes->error = CCCryptorGCMFinal(aes->crypt, tag, &tag_outsize); + + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + + return size; +#endif +} + +int32_t mz_crypt_aes_decrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + size_t data_moved = 0; + + if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0 || !aes->crypt) + return MZ_PARAM_ERROR; + + if (aes->mode == MZ_AES_MODE_GCM) { +#if MZ_TARGET_APPSTORE + return MZ_SUPPORT_ERROR; +#else + if (aad && aad_size > 0) { + aes->error = CCCryptorGCMAddAAD(aes->crypt, aad, aad_size); + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + } + aes->error = CCCryptorGCMDecrypt(aes->crypt, buf, size, buf); +#endif + } else { + if (aad && aad_size > 0) + return MZ_PARAM_ERROR; + aes->error = CCCryptorUpdate(aes->crypt, buf, size, buf, size, &data_moved); + } + + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + + return size; +} + +int32_t mz_crypt_aes_decrypt_final(void *handle, uint8_t *buf, int32_t size, const uint8_t *tag, int32_t tag_length) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; +#if !MZ_TARGET_APPSTORE + uint8_t tag_actual_buf[MZ_AES_BLOCK_SIZE]; + size_t tag_actual_len = sizeof(tag_actual_buf); + uint8_t *tag_actual = tag_actual_buf; + int32_t c = tag_length; + int32_t is_ok = 0; +#endif + + if (!aes || !tag || !tag_length || !aes->crypt || aes->mode != MZ_AES_MODE_GCM) + return MZ_PARAM_ERROR; + +#if MZ_TARGET_APPSTORE + return MZ_SUPPORT_ERROR; +#else + aes->error = CCCryptorGCMDecrypt(aes->crypt, buf, size, buf); + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + + /* CCCryptorGCMFinal does not verify tag */ + aes->error = CCCryptorGCMFinal(aes->crypt, tag_actual, &tag_actual_len); + + if (aes->error != kCCSuccess) + return MZ_CRYPT_ERROR; + if (tag_length != (int32_t)tag_actual_len) + return MZ_CRYPT_ERROR; + + /* Timing safe comparison */ + for (; c > 0; c--) + is_ok |= *tag++ ^ *tag_actual++; + + if (is_ok) + return MZ_CRYPT_ERROR; + + return size; +#endif +} + +static int32_t mz_crypt_aes_set_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length, CCOperation op) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + CCMode mode; + + if (aes->mode == MZ_AES_MODE_CBC) + mode = kCCModeCBC; + else if (aes->mode == MZ_AES_MODE_ECB) + mode = kCCModeECB; + else if (aes->mode == MZ_AES_MODE_GCM) +#if !MZ_TARGET_APPSTORE + mode = kCCModeGCM; +#else + return MZ_SUPPORT_ERROR; +#endif + else + return MZ_PARAM_ERROR; + + mz_crypt_aes_reset(handle); + + aes->error = CCCryptorCreateWithMode(op, mode, kCCAlgorithmAES, ccNoPadding, iv, key, key_length, NULL, 0, 0, 0, + &aes->crypt); + + if (aes->error != kCCSuccess) + return MZ_HASH_ERROR; + +#if !MZ_TARGET_APPSTORE + if (aes->mode == MZ_AES_MODE_GCM) { + aes->error = CCCryptorGCMAddIV(aes->crypt, iv, iv_length); + + if (aes->error != kCCSuccess) + return MZ_HASH_ERROR; + } +#endif + + return MZ_OK; +} + +int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length) { + return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length, kCCEncrypt); +} + +int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length) { + return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length, kCCDecrypt); +} + +void mz_crypt_aes_set_mode(void *handle, int32_t mode) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + aes->mode = mode; +} + +void *mz_crypt_aes_create(void) { + mz_crypt_aes *aes = (mz_crypt_aes *)calloc(1, sizeof(mz_crypt_aes)); + return aes; +} + +void mz_crypt_aes_delete(void **handle) { + mz_crypt_aes *aes = NULL; + if (!handle) + return; + aes = (mz_crypt_aes *)*handle; + if (aes) { + mz_crypt_aes_free(*handle); + free(aes); + } + *handle = NULL; +} + +/***************************************************************************/ + +typedef struct mz_crypt_hmac_s { + CCHmacContext ctx; + int32_t initialized; + int32_t error; + uint16_t algorithm; +} mz_crypt_hmac; + +/***************************************************************************/ + +static void mz_crypt_hmac_free(void *handle) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + memset(&hmac->ctx, 0, sizeof(hmac->ctx)); +} + +void mz_crypt_hmac_reset(void *handle) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + mz_crypt_hmac_free(handle); + hmac->error = 0; +} + +int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + CCHmacAlgorithm algorithm = 0; + + if (!hmac || !key) + return MZ_PARAM_ERROR; + + mz_crypt_hmac_reset(handle); + + if (hmac->algorithm == MZ_HASH_SHA1) + algorithm = kCCHmacAlgSHA1; + else if (hmac->algorithm == MZ_HASH_SHA256) + algorithm = kCCHmacAlgSHA256; + else + return MZ_PARAM_ERROR; + + CCHmacInit(&hmac->ctx, algorithm, key, key_length); + return MZ_OK; +} + +int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + + if (!hmac || !buf) + return MZ_PARAM_ERROR; + + CCHmacUpdate(&hmac->ctx, buf, size); + return MZ_OK; +} + +int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + + if (!hmac || !digest) + return MZ_PARAM_ERROR; + + if (hmac->algorithm == MZ_HASH_SHA1) { + if (digest_size < MZ_HASH_SHA1_SIZE) + return MZ_BUF_ERROR; + CCHmacFinal(&hmac->ctx, digest); + } else { + if (digest_size < MZ_HASH_SHA256_SIZE) + return MZ_BUF_ERROR; + CCHmacFinal(&hmac->ctx, digest); + } + + return MZ_OK; +} + +void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + hmac->algorithm = algorithm; +} + +int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle) { + mz_crypt_hmac *source = (mz_crypt_hmac *)src_handle; + mz_crypt_hmac *target = (mz_crypt_hmac *)target_handle; + + if (!source || !target) + return MZ_PARAM_ERROR; + + memcpy(&target->ctx, &source->ctx, sizeof(CCHmacContext)); + return MZ_OK; +} + +void *mz_crypt_hmac_create(void) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)calloc(1, sizeof(mz_crypt_hmac)); + if (hmac) + hmac->algorithm = MZ_HASH_SHA256; + return hmac; +} + +void mz_crypt_hmac_delete(void **handle) { + mz_crypt_hmac *hmac = NULL; + if (!handle) + return; + hmac = (mz_crypt_hmac *)*handle; + if (hmac) { + mz_crypt_hmac_free(*handle); + free(hmac); + } + *handle = NULL; +} diff --git a/thirdparty/minizip/mz_crypt_openssl.c b/thirdparty/minizip/mz_crypt_openssl.c new file mode 100644 index 000000000..391210306 --- /dev/null +++ b/thirdparty/minizip/mz_crypt_openssl.c @@ -0,0 +1,698 @@ +/* mz_crypt_openssl.c -- Crypto/hash functions for OpenSSL + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_crypt.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +# include +#endif + +/***************************************************************************/ + +static void mz_crypt_init(void) { + static int32_t openssl_initialized = 0; + if (!openssl_initialized) { +#if OPENSSL_VERSION_NUMBER < 0x10100000L + OpenSSL_add_all_algorithms(); + + ERR_load_BIO_strings(); + ERR_load_crypto_strings(); + + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); +#else + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL); +#endif + + openssl_initialized = 1; + } +} + +int32_t mz_crypt_rand(uint8_t *buf, int32_t size) { + if (!RAND_bytes(buf, size)) + return MZ_CRYPT_ERROR; + + return size; +} + +/***************************************************************************/ + +typedef struct mz_crypt_sha_s { +#if OPENSSL_VERSION_NUMBER < 0x10100000L + union { + SHA512_CTX ctx512; + SHA256_CTX ctx256; + SHA_CTX ctx1; + }; +#else + EVP_MD_CTX *ctx; +#endif + unsigned long error; + int32_t initialized; + uint16_t algorithm; +} mz_crypt_sha; + +/***************************************************************************/ + +static const uint8_t mz_crypt_sha_digest_size[] = { + MZ_HASH_SHA1_SIZE, 0, MZ_HASH_SHA224_SIZE, MZ_HASH_SHA256_SIZE, MZ_HASH_SHA384_SIZE, MZ_HASH_SHA512_SIZE}; + +/***************************************************************************/ + +static void mz_crypt_sha_free(void *handle) { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + if (sha->ctx) + EVP_MD_CTX_free(sha->ctx); + sha->ctx = NULL; +#else + MZ_UNUSED(handle); +#endif +} + +void mz_crypt_sha_reset(void *handle) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + + mz_crypt_init(); + mz_crypt_sha_free(handle); + + sha->error = 0; + sha->initialized = 0; +} + +int32_t mz_crypt_sha_begin(void *handle) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + int32_t result = 0; + + if (!sha) + return MZ_PARAM_ERROR; + + mz_crypt_sha_reset(handle); + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + switch (sha->algorithm) { + case MZ_HASH_SHA1: + result = SHA1_Init(&sha->ctx1); + break; + case MZ_HASH_SHA224: + result = SHA224_Init(&sha->ctx256); + break; + case MZ_HASH_SHA256: + result = SHA256_Init(&sha->ctx256); + break; + case MZ_HASH_SHA384: + result = SHA384_Init(&sha->ctx512); + break; + case MZ_HASH_SHA512: + result = SHA512_Init(&sha->ctx512); + break; + } +#else + const EVP_MD *md = NULL; + switch (sha->algorithm) { + case MZ_HASH_SHA1: + md = EVP_sha1(); + break; + case MZ_HASH_SHA224: + md = EVP_sha224(); + break; + case MZ_HASH_SHA256: + md = EVP_sha256(); + break; + case MZ_HASH_SHA384: + md = EVP_sha384(); + break; + case MZ_HASH_SHA512: + md = EVP_sha512(); + break; + } + if (!md) + return MZ_PARAM_ERROR; + + sha->ctx = EVP_MD_CTX_new(); + if (!sha->ctx) + return MZ_MEM_ERROR; + result = EVP_DigestInit_ex(sha->ctx, md, NULL); +#endif + + if (!result) { + sha->error = ERR_get_error(); + return MZ_HASH_ERROR; + } + + sha->initialized = 1; + return MZ_OK; +} + +int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + int32_t result = 0; + + if (!sha || !buf || !sha->initialized) + return MZ_PARAM_ERROR; + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + switch (sha->algorithm) { + case MZ_HASH_SHA1: + result = SHA1_Update(&sha->ctx1, buf, size); + break; + case MZ_HASH_SHA224: + result = SHA224_Update(&sha->ctx256, buf, size); + break; + case MZ_HASH_SHA256: + result = SHA256_Update(&sha->ctx256, buf, size); + break; + case MZ_HASH_SHA384: + result = SHA384_Update(&sha->ctx512, buf, size); + break; + case MZ_HASH_SHA512: + result = SHA512_Update(&sha->ctx512, buf, size); + break; + } +#else + result = EVP_DigestUpdate(sha->ctx, buf, size); +#endif + + if (!result) { + sha->error = ERR_get_error(); + return MZ_HASH_ERROR; + } + + return size; +} + +int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + int32_t result = 0; + + if (!sha || !digest || !sha->initialized) + return MZ_PARAM_ERROR; + if (digest_size < mz_crypt_sha_digest_size[sha->algorithm - MZ_HASH_SHA1]) + return MZ_PARAM_ERROR; + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + switch (sha->algorithm) { + case MZ_HASH_SHA1: + result = SHA1_Final(digest, &sha->ctx1); + break; + case MZ_HASH_SHA224: + result = SHA224_Final(digest, &sha->ctx256); + break; + case MZ_HASH_SHA256: + result = SHA256_Final(digest, &sha->ctx256); + break; + case MZ_HASH_SHA384: + result = SHA384_Final(digest, &sha->ctx512); + break; + case MZ_HASH_SHA512: + result = SHA512_Final(digest, &sha->ctx512); + break; + } +#else + result = EVP_DigestFinal_ex(sha->ctx, digest, NULL); +#endif + + if (!result) { + sha->error = ERR_get_error(); + return MZ_HASH_ERROR; + } + + return MZ_OK; +} + +int32_t mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + if (algorithm < MZ_HASH_SHA1 || algorithm > MZ_HASH_SHA512) + return MZ_PARAM_ERROR; + sha->algorithm = algorithm; + return MZ_OK; +} + +void *mz_crypt_sha_create(void) { + mz_crypt_sha *sha = (mz_crypt_sha *)calloc(1, sizeof(mz_crypt_sha)); + if (sha) + sha->algorithm = MZ_HASH_SHA256; + return sha; +} + +void mz_crypt_sha_delete(void **handle) { + mz_crypt_sha *sha = NULL; + if (!handle) + return; + sha = (mz_crypt_sha *)*handle; + if (sha) { + mz_crypt_sha_free(*handle); + free(sha); + } + *handle = NULL; +} + +/***************************************************************************/ + +typedef struct mz_crypt_aes_s { + int32_t mode; + unsigned long error; + EVP_CIPHER_CTX *ctx; +} mz_crypt_aes; + +/***************************************************************************/ + +static void mz_crypt_aes_free(void *handle) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + if (aes->ctx) + EVP_CIPHER_CTX_free(aes->ctx); + aes->ctx = NULL; +} + +void mz_crypt_aes_reset(void *handle) { + mz_crypt_init(); + mz_crypt_aes_free(handle); +} + +int32_t mz_crypt_aes_encrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + + if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0 || !aes->ctx) + return MZ_PARAM_ERROR; + if (aes->mode != MZ_AES_MODE_GCM && aad && aad_size > 0) + return MZ_PARAM_ERROR; + + if (aad && aad_size > 0) { + int32_t how_many = 0; + if (!EVP_EncryptUpdate(aes->ctx, NULL, &how_many, aad, aad_size)) + return MZ_CRYPT_ERROR; + } + + if (!EVP_EncryptUpdate(aes->ctx, buf, &size, buf, size)) + return MZ_CRYPT_ERROR; + + return size; +} + +int32_t mz_crypt_aes_encrypt_final(void *handle, uint8_t *buf, int32_t size, uint8_t *tag, int32_t tag_size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + int result = 0; + int out_len = 0; + + if (!aes || !tag || !tag_size || !aes->ctx || aes->mode != MZ_AES_MODE_GCM) + return MZ_PARAM_ERROR; + + if (buf && size) { + if (!EVP_EncryptUpdate(aes->ctx, buf, &size, buf, size)) + return MZ_CRYPT_ERROR; + } + + /* Must call EncryptFinal for tag to be calculated */ + result = EVP_EncryptFinal_ex(aes->ctx, NULL, &out_len); + + if (result) + result = EVP_CIPHER_CTX_ctrl(aes->ctx, EVP_CTRL_GCM_GET_TAG, tag_size, tag); + + if (!result) { + aes->error = ERR_get_error(); + return MZ_CRYPT_ERROR; + } + + return size; +} + +int32_t mz_crypt_aes_decrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + + if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0 || !aes->ctx) + return MZ_PARAM_ERROR; + if (aes->mode != MZ_AES_MODE_GCM && aad && aad_size > 0) + return MZ_PARAM_ERROR; + + if (aad && aad_size > 0) { + int32_t how_many = 0; + if (!EVP_DecryptUpdate(aes->ctx, NULL, &how_many, aad, aad_size)) + return MZ_CRYPT_ERROR; + } + + if (!EVP_DecryptUpdate(aes->ctx, buf, &size, buf, size)) + return MZ_CRYPT_ERROR; + + return size; +} + +int32_t mz_crypt_aes_decrypt_final(void *handle, uint8_t *buf, int32_t size, const uint8_t *tag, int32_t tag_length) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + int out_len = 0; + + if (!aes || !tag || !tag_length || !aes->ctx || aes->mode != MZ_AES_MODE_GCM) + return MZ_PARAM_ERROR; + + if (buf && size) { + if (!EVP_DecryptUpdate(aes->ctx, buf, &size, buf, size)) + return MZ_CRYPT_ERROR; + } + + /* Set expected tag */ + if (!EVP_CIPHER_CTX_ctrl(aes->ctx, EVP_CTRL_GCM_SET_TAG, tag_length, (void *)tag)) { + aes->error = ERR_get_error(); + return MZ_CRYPT_ERROR; + } + + /* Must call DecryptFinal for tag verification */ + if (!EVP_DecryptFinal_ex(aes->ctx, NULL, &out_len)) { + aes->error = ERR_get_error(); + return MZ_CRYPT_ERROR; + } + + return size; +} + +static int32_t mz_crypt_aes_set_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length, int32_t encrypt) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + const EVP_CIPHER *type = NULL; + + switch (aes->mode) { + case MZ_AES_MODE_CBC: + if (key_length == 16) + type = EVP_aes_128_cbc(); + else if (key_length == 24) + type = EVP_aes_192_cbc(); + else if (key_length == 32) + type = EVP_aes_256_cbc(); + break; + case MZ_AES_MODE_ECB: + if (key_length == 16) + type = EVP_aes_128_ecb(); + else if (key_length == 24) + type = EVP_aes_192_ecb(); + else if (key_length == 32) + type = EVP_aes_256_ecb(); + break; + case MZ_AES_MODE_GCM: + if (key_length == 16) + type = EVP_aes_128_gcm(); + else if (key_length == 24) + type = EVP_aes_192_gcm(); + else if (key_length == 32) + type = EVP_aes_256_gcm(); + break; + } + if (!type) + return MZ_PARAM_ERROR; + + aes->ctx = EVP_CIPHER_CTX_new(); + if (!aes->ctx) + return MZ_MEM_ERROR; + + if (!EVP_CipherInit_ex(aes->ctx, type, NULL, key, iv, encrypt)) { + aes->error = ERR_get_error(); + return MZ_HASH_ERROR; + } + + EVP_CIPHER_CTX_set_padding(aes->ctx, aes->mode == MZ_AES_MODE_GCM); + + return MZ_OK; +} + +int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + + if (!aes || !key || !key_length) + return MZ_PARAM_ERROR; + if (key_length != 16 && key_length != 24 && key_length != 32) + return MZ_PARAM_ERROR; + if (iv && iv_length != MZ_AES_BLOCK_SIZE) + return MZ_PARAM_ERROR; + + mz_crypt_aes_reset(handle); + + return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length, 1); +} + +int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + + if (!aes || !key || !key_length) + return MZ_PARAM_ERROR; + if (key_length != 16 && key_length != 24 && key_length != 32) + return MZ_PARAM_ERROR; + if (iv && iv_length > MZ_AES_BLOCK_SIZE) + return MZ_PARAM_ERROR; + + mz_crypt_aes_reset(handle); + + return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length, 0); +} + +void mz_crypt_aes_set_mode(void *handle, int32_t mode) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + aes->mode = mode; +} + +void *mz_crypt_aes_create(void) { + mz_crypt_aes *aes = (mz_crypt_aes *)calloc(1, sizeof(mz_crypt_aes)); + return aes; +} + +void mz_crypt_aes_delete(void **handle) { + mz_crypt_aes *aes = NULL; + if (!handle) + return; + aes = (mz_crypt_aes *)*handle; + if (aes) { + mz_crypt_aes_free(*handle); + free(aes); + } + *handle = NULL; +} + +/***************************************************************************/ + +typedef struct mz_crypt_hmac_s { +#if OPENSSL_VERSION_NUMBER < 0x30000000L + HMAC_CTX *ctx; +#else + EVP_MAC *mac; + EVP_MAC_CTX *ctx; +#endif + unsigned long error; + int32_t initialized; + uint16_t algorithm; +} mz_crypt_hmac; + +/***************************************************************************/ + +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \ + (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2070000fL)) +static HMAC_CTX *HMAC_CTX_new(void) { + HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX)); + if (ctx) + HMAC_CTX_init(ctx); + return ctx; +} + +static void HMAC_CTX_free(HMAC_CTX *ctx) { + if (ctx) { + HMAC_CTX_cleanup(ctx); + OPENSSL_free(ctx); + } +} +#endif + +/***************************************************************************/ + +static void mz_crypt_hmac_free(void *handle) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + HMAC_CTX_free(hmac->ctx); +#else + if (hmac->ctx) + EVP_MAC_CTX_free(hmac->ctx); + if (hmac->mac) + EVP_MAC_free(hmac->mac); + hmac->mac = NULL; +#endif + + hmac->ctx = NULL; +} + +void mz_crypt_hmac_reset(void *handle) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + + mz_crypt_init(); + mz_crypt_hmac_free(handle); + + hmac->error = 0; +} + +int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + int32_t result = 0; + + if (!hmac || !key) + return MZ_PARAM_ERROR; + + mz_crypt_hmac_reset(handle); + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + const EVP_MD *evp_md = NULL; + + if (hmac->algorithm == MZ_HASH_SHA1) + evp_md = EVP_sha1(); + else + evp_md = EVP_sha256(); + + hmac->ctx = HMAC_CTX_new(); + if (!hmac->ctx) + return MZ_MEM_ERROR; + + result = HMAC_Init_ex(hmac->ctx, key, key_length, evp_md, NULL); +#else + char *digest_algorithm = NULL; + OSSL_PARAM params[2]; + + if (hmac->algorithm == MZ_HASH_SHA1) + digest_algorithm = "sha1"; + else + digest_algorithm = "sha256"; + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, digest_algorithm, 0); + params[1] = OSSL_PARAM_construct_end(); + + hmac->mac = EVP_MAC_fetch(NULL, "HMAC", NULL); + if (!hmac->mac) + return MZ_MEM_ERROR; + hmac->ctx = EVP_MAC_CTX_new(hmac->mac); + if (!hmac->ctx) + return MZ_MEM_ERROR; + result = EVP_MAC_init(hmac->ctx, key, key_length, params); +#endif + + if (!result) { + hmac->error = ERR_get_error(); + return MZ_HASH_ERROR; + } + + return MZ_OK; +} + +int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + int32_t result = 0; + + if (!hmac || !buf) + return MZ_PARAM_ERROR; + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + result = HMAC_Update(hmac->ctx, buf, size); +#else + result = EVP_MAC_update(hmac->ctx, buf, size); +#endif + if (!result) { + hmac->error = ERR_get_error(); + return MZ_HASH_ERROR; + } + + return MZ_OK; +} + +int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + int32_t result = 0; + + if (!hmac || !digest) + return MZ_PARAM_ERROR; + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + if (hmac->algorithm == MZ_HASH_SHA1) { + if (digest_size < MZ_HASH_SHA1_SIZE) + return MZ_BUF_ERROR; + + result = HMAC_Final(hmac->ctx, digest, (uint32_t *)&digest_size); + } else { + if (digest_size < MZ_HASH_SHA256_SIZE) + return MZ_BUF_ERROR; + result = HMAC_Final(hmac->ctx, digest, (uint32_t *)&digest_size); + } +#else + { + size_t digest_outsize = digest_size; + result = EVP_MAC_final(hmac->ctx, digest, &digest_outsize, digest_size); + } +#endif + + if (!result) { + hmac->error = ERR_get_error(); + return MZ_HASH_ERROR; + } + + return MZ_OK; +} + +void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + hmac->algorithm = algorithm; +} + +int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle) { + mz_crypt_hmac *source = (mz_crypt_hmac *)src_handle; + mz_crypt_hmac *target = (mz_crypt_hmac *)target_handle; + + if (!source || !target) + return MZ_PARAM_ERROR; + + mz_crypt_hmac_reset(target_handle); + +#if OPENSSL_VERSION_NUMBER < 0x30000000L + if (!target->ctx) + target->ctx = HMAC_CTX_new(); + + if (!HMAC_CTX_copy(target->ctx, source->ctx)) { + target->error = ERR_get_error(); + return MZ_HASH_ERROR; + } +#else + if (!target->ctx) + target->ctx = EVP_MAC_CTX_dup(source->ctx); + if (!target->ctx) + return MZ_MEM_ERROR; +#endif + + return MZ_OK; +} + +void *mz_crypt_hmac_create(void) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)calloc(1, sizeof(mz_crypt_hmac)); + if (hmac) + hmac->algorithm = MZ_HASH_SHA256; + return hmac; +} + +void mz_crypt_hmac_delete(void **handle) { + mz_crypt_hmac *hmac = NULL; + if (!handle) + return; + hmac = (mz_crypt_hmac *)*handle; + if (hmac) { + mz_crypt_hmac_free(*handle); + free(hmac); + } + *handle = NULL; +} diff --git a/thirdparty/minizip/mz_crypt_winvista.c b/thirdparty/minizip/mz_crypt_winvista.c new file mode 100644 index 000000000..27311fd2a --- /dev/null +++ b/thirdparty/minizip/mz_crypt_winvista.c @@ -0,0 +1,662 @@ +/* mz_crypt_winrt.c -- Crypto/hash functions for Windows Vista or later + part of the minizip-ng project + + Copyright (C) 2010-2022 Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_os.h" +#include "mz_crypt.h" + +#include + +#ifndef _WIN32_WINNT_VISTA +# define _WIN32_WINNT_VISTA 0x0600 +#endif + +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA +# include + +/***************************************************************************/ + +# define NT_SUCCESS(status) ((status) >= 0) + +/***************************************************************************/ + +int32_t mz_crypt_rand(uint8_t *buf, int32_t size) { + BCRYPT_ALG_HANDLE provider = NULL; + NTSTATUS status = 0; + + status = BCryptOpenAlgorithmProvider(&provider, BCRYPT_RNG_ALGORITHM, NULL, 0); + if (NT_SUCCESS(status)) { + status = BCryptGenRandom(provider, buf, size, 0); + BCryptCloseAlgorithmProvider(provider, 0); + } + if (NT_SUCCESS(status)) + return size; + + return mz_os_rand(buf, size); +} + +/***************************************************************************/ + +typedef struct mz_crypt_sha_s { + union { + struct { + BCRYPT_ALG_HANDLE provider; + BCRYPT_HASH_HANDLE hash; + uint8_t *buffer; + }; + }; + int32_t error; + uint16_t algorithm; +} mz_crypt_sha; + +/***************************************************************************/ + +static void mz_crypt_sha_free(void *handle) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + if (sha->hash) + BCryptDestroyHash(sha->hash); + sha->hash = NULL; + if (sha->provider) + BCryptCloseAlgorithmProvider(sha->provider, 0); + sha->provider = NULL; + free(sha->buffer); + sha->buffer = NULL; +} + +void mz_crypt_sha_reset(void *handle) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + mz_crypt_sha_free(handle); + sha->error = 0; +} + +int32_t mz_crypt_sha_begin(void *handle) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + NTSTATUS status = 0; + const wchar_t *alg_id = BCRYPT_SHA256_ALGORITHM; + ULONG buffer_size = 0; + ULONG result_size = sizeof(buffer_size); + int32_t err = MZ_OK; + + if (!sha) + return MZ_PARAM_ERROR; + + if (sha->algorithm == MZ_HASH_SHA224) + return MZ_SUPPORT_ERROR; + + switch (sha->algorithm) { + case MZ_HASH_SHA1: + alg_id = BCRYPT_SHA1_ALGORITHM; + break; + case MZ_HASH_SHA384: + alg_id = BCRYPT_SHA384_ALGORITHM; + break; + case MZ_HASH_SHA512: + alg_id = BCRYPT_SHA512_ALGORITHM; + break; + } + + status = BCryptOpenAlgorithmProvider(&sha->provider, alg_id, NULL, 0); + if (NT_SUCCESS(status)) { + status = + BCryptGetProperty(sha->provider, BCRYPT_OBJECT_LENGTH, (PUCHAR)&buffer_size, result_size, &result_size, 0); + } + if (NT_SUCCESS(status)) { + sha->buffer = malloc(buffer_size); + if (!sha->buffer) + return MZ_MEM_ERROR; + status = BCryptCreateHash(sha->provider, &sha->hash, sha->buffer, buffer_size, NULL, 0, 0); + } + if (!NT_SUCCESS(status)) { + sha->error = status; + err = MZ_HASH_ERROR; + } + + return err; +} + +int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + NTSTATUS status = 0; + + if (!sha || !buf || size < 0) + return MZ_PARAM_ERROR; + + if (sha->algorithm == MZ_HASH_SHA224) + return MZ_SUPPORT_ERROR; + + if (sha->hash == 0) + return MZ_PARAM_ERROR; + + status = BCryptHashData(sha->hash, (uint8_t *)buf, size, 0); + if (!NT_SUCCESS(status)) { + sha->error = status; + return MZ_HASH_ERROR; + } + return size; +} + +int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + NTSTATUS status = 0; + ULONG expected_size = 0; + ULONG result_size = sizeof(expected_size); + + if (!sha || !digest) + return MZ_PARAM_ERROR; + + if (sha->algorithm == MZ_HASH_SHA224) + return MZ_SUPPORT_ERROR; + + if (sha->hash == 0) + return MZ_PARAM_ERROR; + + status = BCryptGetProperty(sha->hash, BCRYPT_HASH_LENGTH, (PUCHAR)&expected_size, result_size, &result_size, 0); + if (!NT_SUCCESS(status)) + return MZ_HASH_ERROR; + if ((int32_t)expected_size > digest_size) + return MZ_BUF_ERROR; + status = BCryptFinishHash(sha->hash, digest, expected_size, 0); + if (!NT_SUCCESS(status)) { + sha->error = status; + return MZ_HASH_ERROR; + } + return MZ_OK; +} + +int32_t mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + if (algorithm < MZ_HASH_SHA1 || algorithm > MZ_HASH_SHA512) + return MZ_PARAM_ERROR; + sha->algorithm = algorithm; + return MZ_OK; +} + +void *mz_crypt_sha_create(void) { + mz_crypt_sha *sha = (mz_crypt_sha *)calloc(1, sizeof(mz_crypt_sha)); + if (sha) + sha->algorithm = MZ_HASH_SHA256; + return sha; +} + +void mz_crypt_sha_delete(void **handle) { + mz_crypt_sha *sha = NULL; + if (!handle) + return; + sha = (mz_crypt_sha *)*handle; + if (sha) { + mz_crypt_sha_free(*handle); + free(sha); + } + *handle = NULL; +} + +/***************************************************************************/ + +# define MZ_AES_MAX_TAG_SIZE (16) +# define MZ_AES_MAX_NONCE_SIZE (12) + +typedef struct mz_crypt_aes_s { + BCRYPT_ALG_HANDLE provider; + BCRYPT_KEY_HANDLE key; + uint8_t *key_buffer; + int32_t mode; + int32_t error; + uint8_t *iv; + uint32_t iv_length; + uint8_t nonce[MZ_AES_MAX_NONCE_SIZE]; + uint32_t nonce_length; + uint8_t mac[MZ_AES_MAX_TAG_SIZE]; + uint8_t tag[MZ_AES_MAX_TAG_SIZE]; + uint32_t tag_size; + BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info; +} mz_crypt_aes; + +/***************************************************************************/ + +static void mz_crypt_aes_free(void *handle) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + if (aes->key) + BCryptDestroyKey(aes->key); + aes->key = NULL; + if (aes->provider) + BCryptCloseAlgorithmProvider(aes->provider, 0); + aes->provider = NULL; + free(aes->key_buffer); + aes->key_buffer = NULL; + free(aes->iv); + aes->iv = NULL; + free(aes->auth_info); + aes->auth_info = NULL; +} + +void mz_crypt_aes_reset(void *handle) { + mz_crypt_aes_free(handle); +} + +int32_t mz_crypt_aes_encrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + ULONG output_size = 0; + NTSTATUS status = 0; + + if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0) + return MZ_PARAM_ERROR; + if (aes->mode != MZ_AES_MODE_GCM && aad && aad_size > 0) + return MZ_PARAM_ERROR; + if (aes->mode == MZ_AES_MODE_GCM && !aes->auth_info) + return MZ_PARAM_ERROR; + + if (aad && aes->auth_info && !(aes->auth_info->dwFlags & BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG)) { + aes->auth_info->pbAuthData = (uint8_t *)aad; + aes->auth_info->cbAuthData = aad_size; + } + + status = BCryptEncrypt(aes->key, buf, size, aes->auth_info, aes->iv, aes->iv_length, buf, size, &output_size, 0); + + if (aad && aes->auth_info) { + aes->auth_info->pbAuthData = NULL; + aes->auth_info->cbAuthData = 0; + } + + if (!NT_SUCCESS(status)) { + aes->error = status; + return MZ_CRYPT_ERROR; + } + return size; +} + +int32_t mz_crypt_aes_encrypt_final(void *handle, uint8_t *buf, int32_t size, uint8_t *tag, int32_t tag_size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + NTSTATUS status = 0; + ULONG output_size = 0; + + if (!aes || !tag || !tag_size || aes->mode != MZ_AES_MODE_GCM || !aes->auth_info) + return MZ_PARAM_ERROR; + + aes->auth_info->pbTag = tag; + aes->auth_info->cbTag = tag_size; + + aes->auth_info->dwFlags &= ~BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG; + + status = BCryptEncrypt(aes->key, buf, size, aes->auth_info, aes->iv, aes->iv_length, buf, size, &output_size, 0); + + if (!NT_SUCCESS(status)) { + aes->error = status; + return MZ_CRYPT_ERROR; + } + + return size; +} + +int32_t mz_crypt_aes_decrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + ULONG output_size = 0; + NTSTATUS status = 0; + + if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0) + return MZ_PARAM_ERROR; + if (aes->mode != MZ_AES_MODE_GCM && aad && aad_size > 0) + return MZ_PARAM_ERROR; + if (aes->mode == MZ_AES_MODE_GCM && !aes->auth_info) + return MZ_PARAM_ERROR; + + if (aad && aes->auth_info && !(aes->auth_info->dwFlags & BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG)) { + aes->auth_info->pbAuthData = (uint8_t *)aad; + aes->auth_info->cbAuthData = aad_size; + } + + status = BCryptDecrypt(aes->key, buf, size, aes->auth_info, aes->iv, aes->iv_length, buf, size, &output_size, 0); + + if (aad && aes->auth_info) { + aes->auth_info->pbAuthData = NULL; + aes->auth_info->cbAuthData = 0; + } + + if (!NT_SUCCESS(status)) { + aes->error = status; + return MZ_CRYPT_ERROR; + } + return size; +} + +int32_t mz_crypt_aes_decrypt_final(void *handle, uint8_t *buf, int32_t size, const uint8_t *tag, int32_t tag_length) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + NTSTATUS status = 0; + ULONG output_size = 0; + + if (!aes || !tag || !tag_length || aes->mode != MZ_AES_MODE_GCM || !aes->auth_info) + return MZ_PARAM_ERROR; + + aes->auth_info->pbTag = (uint8_t *)tag; + aes->auth_info->cbTag = tag_length; + + aes->auth_info->dwFlags &= ~BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG; + + status = BCryptDecrypt(aes->key, buf, size, aes->auth_info, aes->iv, aes->iv_length, buf, size, &output_size, 0); + + if (!NT_SUCCESS(status)) { + aes->error = status; + return MZ_CRYPT_ERROR; + } + + return size; +} + +static int32_t mz_crypt_aes_set_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + BCRYPT_KEY_DATA_BLOB_HEADER *key_blob = NULL; + int32_t key_blob_size = 0; + ULONG key_size = 0; + wchar_t *mode = NULL; + NTSTATUS status = 0; + int32_t err = MZ_OK; + + if (!aes || !key || !key_length) + return MZ_PARAM_ERROR; + if (key_length != 16 && key_length != 24 && key_length != 32) + return MZ_PARAM_ERROR; + if (iv && iv_length > MZ_AES_BLOCK_SIZE) + return MZ_PARAM_ERROR; + + if (aes->mode == MZ_AES_MODE_ECB) + mode = BCRYPT_CHAIN_MODE_ECB; + else if (aes->mode == MZ_AES_MODE_CBC) + mode = BCRYPT_CHAIN_MODE_CBC; + else if (aes->mode == MZ_AES_MODE_GCM) + mode = BCRYPT_CHAIN_MODE_GCM; + else + return MZ_PARAM_ERROR; + + mz_crypt_aes_reset(handle); + + if (iv && iv_length) { + if (aes->mode == MZ_AES_MODE_ECB) + return MZ_PARAM_ERROR; + + aes->iv_length = MZ_AES_BLOCK_SIZE; + aes->iv = calloc(MZ_AES_BLOCK_SIZE, sizeof(uint8_t)); + if (!aes->iv) + return MZ_MEM_ERROR; + memcpy(aes->iv, iv, iv_length); + } + + status = BCryptOpenAlgorithmProvider(&aes->provider, BCRYPT_AES_ALGORITHM, NULL, 0); + + if (NT_SUCCESS(status)) { + status = BCryptSetProperty(aes->provider, BCRYPT_CHAINING_MODE, (PBYTE)mode, sizeof(mode), 0); + } + + if (NT_SUCCESS(status)) { + ULONG result_size; + status = BCryptGetProperty(aes->provider, BCRYPT_OBJECT_LENGTH, (PUCHAR)&key_size, sizeof(key_size), + &result_size, 0); + } + + if (NT_SUCCESS(status)) { + aes->key_buffer = malloc(key_size); + if (!aes->key_buffer) + return MZ_MEM_ERROR; + key_blob_size = sizeof(*key_blob) + key_length; + key_blob = malloc(key_blob_size); + if (key_blob) { + key_blob->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC; + key_blob->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1; + key_blob->cbKeyData = key_length; + + memcpy((uint8_t *)key_blob + sizeof(*key_blob), key, key_length); + + status = BCryptImportKey(aes->provider, NULL, BCRYPT_KEY_DATA_BLOB, &aes->key, aes->key_buffer, key_size, + (PUCHAR)key_blob, key_blob_size, 0); + SecureZeroMemory(key_blob, key_blob_size); + free(key_blob); + } + } + + if (aes->mode == MZ_AES_MODE_GCM) { + ULONG result_size; + + aes->auth_info = malloc(sizeof(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO)); + if (!aes->auth_info) + return MZ_MEM_ERROR; + + BCRYPT_INIT_AUTH_MODE_INFO(*aes->auth_info); + aes->auth_info->dwFlags = BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG; + + if (NT_SUCCESS(status)) { + BCRYPT_AUTH_TAG_LENGTHS_STRUCT tag_lengths; + + status = BCryptGetProperty(aes->provider, BCRYPT_AUTH_TAG_LENGTH, (PUCHAR)&tag_lengths, sizeof(tag_lengths), + &result_size, 0); + + if (NT_SUCCESS(status)) { + aes->tag_size = tag_lengths.dwMaxLength; + if (aes->tag_size > sizeof(aes->tag)) + return MZ_CRYPT_ERROR; + + aes->auth_info->cbTag = aes->tag_size; + aes->auth_info->pbMacContext = aes->mac; + aes->auth_info->cbMacContext = aes->tag_size; + } + } + + if (NT_SUCCESS(status)) { + ULONG block_length; + + status = BCryptGetProperty(aes->provider, BCRYPT_BLOCK_LENGTH, (PUCHAR)&block_length, sizeof(block_length), + &result_size, 0); + + if (NT_SUCCESS(status) && iv) { + if (aes->iv_length > block_length) + return MZ_CRYPT_ERROR; + + aes->nonce_length = iv_length; + if (aes->nonce_length > MZ_AES_MAX_NONCE_SIZE) + aes->nonce_length = MZ_AES_MAX_NONCE_SIZE; + memcpy(aes->nonce, iv, aes->nonce_length); + + aes->auth_info->pbNonce = aes->nonce; + aes->auth_info->cbNonce = aes->nonce_length; + } + } + } + + if (!NT_SUCCESS(status)) { + aes->error = status; + err = MZ_CRYPT_ERROR; + } + + return err; +} + +int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length) { + return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length); +} + +int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length) { + return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length); +} + +void mz_crypt_aes_set_mode(void *handle, int32_t mode) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + aes->mode = mode; +} + +void *mz_crypt_aes_create(void) { + mz_crypt_aes *aes = (mz_crypt_aes *)calloc(1, sizeof(mz_crypt_aes)); + return aes; +} + +void mz_crypt_aes_delete(void **handle) { + mz_crypt_aes *aes = NULL; + if (!handle) + return; + aes = (mz_crypt_aes *)*handle; + if (aes) { + mz_crypt_aes_free(*handle); + free(aes); + } + *handle = NULL; +} + +/***************************************************************************/ + +typedef struct mz_crypt_hmac_s { + BCRYPT_ALG_HANDLE provider; + BCRYPT_KEY_HANDLE key; + BCRYPT_HASH_HANDLE hash; + uint8_t *buffer; + int32_t error; + uint16_t algorithm; +} mz_crypt_hmac; + +/***************************************************************************/ + +static void mz_crypt_hmac_free(void *handle) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + if (hmac->hash) + BCryptDestroyHash(hmac->hash); + hmac->hash = NULL; + if (hmac->key) + BCryptDestroyKey(hmac->key); + hmac->key = NULL; + if (hmac->provider) + BCryptCloseAlgorithmProvider(hmac->provider, 0); + hmac->provider = NULL; + free(hmac->buffer); + hmac->buffer = NULL; +} + +void mz_crypt_hmac_reset(void *handle) { + mz_crypt_hmac_free(handle); +} + +int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + wchar_t *alg_id = BCRYPT_SHA256_ALGORITHM; + ULONG buffer_size = 0; + ULONG result_size = sizeof(buffer_size); + NTSTATUS status = 0; + int32_t err = MZ_OK; + + if (!hmac || !key) + return MZ_PARAM_ERROR; + + mz_crypt_hmac_reset(handle); + + if (hmac->algorithm == MZ_HASH_SHA1) + alg_id = BCRYPT_SHA1_ALGORITHM; + + status = BCryptOpenAlgorithmProvider(&hmac->provider, alg_id, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG); + if (NT_SUCCESS(status)) { + status = + BCryptGetProperty(hmac->provider, BCRYPT_OBJECT_LENGTH, (PUCHAR)&buffer_size, result_size, &result_size, 0); + } + if (NT_SUCCESS(status)) { + hmac->buffer = malloc(buffer_size); + if (!hmac->buffer) + return MZ_MEM_ERROR; + } + if (NT_SUCCESS(status)) + status = BCryptCreateHash(hmac->provider, &hmac->hash, hmac->buffer, buffer_size, (PUCHAR)key, key_length, 0); + + if (!NT_SUCCESS(status)) { + hmac->error = status; + err = MZ_CRYPT_ERROR; + } + + if (err != MZ_OK) + mz_crypt_hmac_free(handle); + + return err; +} + +int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + NTSTATUS status = 0; + + if (!hmac || !buf || !hmac->hash) + return MZ_PARAM_ERROR; + + status = BCryptHashData(hmac->hash, (uint8_t *)buf, size, 0); + if (!NT_SUCCESS(status)) { + hmac->error = status; + return MZ_HASH_ERROR; + } + return MZ_OK; +} + +int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + NTSTATUS status = 0; + ULONG expected_size = 0; + ULONG result_size = sizeof(expected_size); + + if (!hmac || !digest || !hmac->hash) + return MZ_PARAM_ERROR; + status = BCryptGetProperty(hmac->hash, BCRYPT_HASH_LENGTH, (PUCHAR)&expected_size, result_size, &result_size, 0); + if (!NT_SUCCESS(status)) + return MZ_HASH_ERROR; + if ((int32_t)expected_size > digest_size) + return MZ_BUF_ERROR; + status = BCryptFinishHash(hmac->hash, digest, expected_size, 0); + if (!NT_SUCCESS(status)) { + hmac->error = status; + return MZ_HASH_ERROR; + } + return MZ_OK; +} + +void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + hmac->algorithm = algorithm; +} + +int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle) { + mz_crypt_hmac *source = (mz_crypt_hmac *)src_handle; + mz_crypt_hmac *target = (mz_crypt_hmac *)target_handle; + NTSTATUS status = 0; + int32_t err = MZ_OK; + + if (target->hash) { + BCryptDestroyHash(target->hash); + target->hash = NULL; + } + + status = BCryptDuplicateHash(source->hash, &target->hash, NULL, 0, 0); + + if (!NT_SUCCESS(status)) { + target->error = status; + err = MZ_HASH_ERROR; + } + return err; +} + +void *mz_crypt_hmac_create(void) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)calloc(1, sizeof(mz_crypt_hmac)); + if (hmac) + hmac->algorithm = MZ_HASH_SHA256; + return hmac; +} + +void mz_crypt_hmac_delete(void **handle) { + mz_crypt_hmac *hmac = NULL; + if (!handle) + return; + hmac = (mz_crypt_hmac *)*handle; + if (hmac) { + mz_crypt_hmac_free(*handle); + free(hmac); + } + *handle = NULL; +} + +#endif diff --git a/thirdparty/minizip/mz_crypt_winxp.c b/thirdparty/minizip/mz_crypt_winxp.c new file mode 100644 index 000000000..b96380ae9 --- /dev/null +++ b/thirdparty/minizip/mz_crypt_winxp.c @@ -0,0 +1,568 @@ +/* mz_crypt_win32.c -- Crypto/hash functions for Windows XP + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_os.h" +#include "mz_crypt.h" + +#include + +#if _WIN32_WINNT <= _WIN32_WINNT_WINXP +# include + +/***************************************************************************/ + +int32_t mz_crypt_rand(uint8_t *buf, int32_t size) { + HCRYPTPROV provider; + int32_t result = 0; + + result = CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT); + if (result) { + result = CryptGenRandom(provider, size, buf); + CryptReleaseContext(provider, 0); + if (result) + return size; + } + + return mz_os_rand(buf, size); +} + +/***************************************************************************/ + +typedef struct mz_crypt_sha_s { + union { + struct { + HCRYPTPROV provider; + HCRYPTHASH hash; + }; + }; + int32_t error; + uint16_t algorithm; +} mz_crypt_sha; + +/***************************************************************************/ + +static void mz_crypt_sha_free(void *handle) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + if (sha->hash) + CryptDestroyHash(sha->hash); + sha->hash = 0; + if (sha->provider) + CryptReleaseContext(sha->provider, 0); + sha->provider = 0; +} + +void mz_crypt_sha_reset(void *handle) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + mz_crypt_sha_free(handle); + sha->error = 0; +} + +int32_t mz_crypt_sha_begin(void *handle) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + ALG_ID alg_id = 0; + int32_t result = 0; + int32_t err = MZ_OK; + + if (!sha) + return MZ_PARAM_ERROR; + + if (sha->algorithm == MZ_HASH_SHA224) + return MZ_SUPPORT_ERROR; + + switch (sha->algorithm) { + case MZ_HASH_SHA1: + alg_id = CALG_SHA1; + break; +# if NTDDI_VERSION > NTDDI_WINXPSP2 + case MZ_HASH_SHA256: + alg_id = CALG_SHA_256; + break; + case MZ_HASH_SHA384: + alg_id = CALG_SHA_384; + break; + case MZ_HASH_SHA512: + alg_id = CALG_SHA_512; + break; +# else + case MZ_HASH_SHA256: + case MZ_HASH_SHA384: + case MZ_HASH_SHA512: + return MZ_SUPPORT_ERROR; +# endif + default: + return MZ_PARAM_ERROR; + } + + result = CryptAcquireContext(&sha->provider, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT); + if (!result) { + sha->error = GetLastError(); + err = MZ_CRYPT_ERROR; + } + + if (result) { + result = CryptCreateHash(sha->provider, alg_id, 0, 0, &sha->hash); + if (!result) { + sha->error = GetLastError(); + err = MZ_HASH_ERROR; + } + } + + return err; +} + +int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + int32_t result = 0; + + if (!sha || !buf || size < 0) + return MZ_PARAM_ERROR; + + if (sha->algorithm == MZ_HASH_SHA224) + return MZ_SUPPORT_ERROR; + + if (sha->hash == 0) + return MZ_PARAM_ERROR; + + result = CryptHashData(sha->hash, buf, size, 0); + if (!result) { + sha->error = GetLastError(); + return MZ_HASH_ERROR; + } + return size; +} + +int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + int32_t result = 0; + int32_t expected_size = 0; + + if (!sha || !digest) + return MZ_PARAM_ERROR; + + if (sha->algorithm == MZ_HASH_SHA224) + return MZ_SUPPORT_ERROR; + + if (sha->hash == 0) + return MZ_PARAM_ERROR; + + result = CryptGetHashParam(sha->hash, HP_HASHVAL, NULL, (DWORD *)&expected_size, 0); + if (expected_size > digest_size) + return MZ_BUF_ERROR; + if (!result) + return MZ_HASH_ERROR; + result = CryptGetHashParam(sha->hash, HP_HASHVAL, digest, (DWORD *)&digest_size, 0); + if (!result) { + sha->error = GetLastError(); + return MZ_HASH_ERROR; + } + return MZ_OK; +} + +int32_t mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) { + mz_crypt_sha *sha = (mz_crypt_sha *)handle; + if (algorithm != MZ_HASH_SHA1) + return MZ_SUPPORT_ERROR; + sha->algorithm = algorithm; + return MZ_OK; +} + +void *mz_crypt_sha_create(void) { + mz_crypt_sha *sha = (mz_crypt_sha *)calloc(1, sizeof(mz_crypt_sha)); + if (sha) + sha->algorithm = MZ_HASH_SHA256; + return sha; +} + +void mz_crypt_sha_delete(void **handle) { + mz_crypt_sha *sha = NULL; + if (!handle) + return; + sha = (mz_crypt_sha *)*handle; + if (sha) { + mz_crypt_sha_free(*handle); + free(sha); + } + *handle = NULL; +} + +/***************************************************************************/ + +typedef struct mz_crypt_aes_s { + HCRYPTPROV provider; + HCRYPTKEY key; + int32_t mode; + int32_t error; +} mz_crypt_aes; + +/***************************************************************************/ + +static void mz_crypt_aes_free(void *handle) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + if (aes->key) + CryptDestroyKey(aes->key); + aes->key = 0; + if (aes->provider) + CryptReleaseContext(aes->provider, 0); + aes->provider = 0; +} + +void mz_crypt_aes_reset(void *handle) { + mz_crypt_aes_free(handle); +} + +int32_t mz_crypt_aes_encrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + int32_t result = 0; + + if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0 || (aad && aad_size > 0)) + return MZ_PARAM_ERROR; + result = CryptEncrypt(aes->key, 0, 0, 0, buf, (DWORD *)&size, size); + if (!result) { + aes->error = GetLastError(); + return MZ_CRYPT_ERROR; + } + return size; +} + +int32_t mz_crypt_aes_encrypt_final(void *handle, uint8_t *buf, int32_t size, uint8_t *tag, int32_t tag_size) { + return MZ_SUPPORT_ERROR; +} + +int32_t mz_crypt_aes_decrypt(void *handle, const void *aad, int32_t aad_size, uint8_t *buf, int32_t size) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + int32_t result = 0; + if (!aes || !buf || size % MZ_AES_BLOCK_SIZE != 0 || (aad && aad_size > 0)) + return MZ_PARAM_ERROR; + result = CryptDecrypt(aes->key, 0, 0, 0, buf, (DWORD *)&size); + if (!result) { + aes->error = GetLastError(); + return MZ_CRYPT_ERROR; + } + return size; +} + +int32_t mz_crypt_aes_decrypt_final(void *handle, uint8_t *buf, int32_t size, const uint8_t *tag, int32_t tag_length) { + return MZ_SUPPORT_ERROR; +} + +static int32_t mz_crypt_aes_set_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + HCRYPTHASH hash = 0; + ALG_ID alg_id = 0; + typedef struct key_blob_header_s { + BLOBHEADER hdr; + uint32_t key_length; + } key_blob_header_s; + key_blob_header_s *key_blob_s = NULL; + uint32_t mode; + uint8_t *key_blob = NULL; + int32_t key_blob_size = 0; + int32_t result = 0; + int32_t err = MZ_OK; + + if (!aes || !key || !key_length) + return MZ_PARAM_ERROR; + if (iv && iv_length < MZ_AES_BLOCK_SIZE) + return MZ_PARAM_ERROR; + + mz_crypt_aes_reset(handle); + + if (aes->mode == MZ_AES_MODE_CBC) + mode = CRYPT_MODE_CBC; + else if (aes->mode == MZ_AES_MODE_ECB) + mode = CRYPT_MODE_ECB; + else if (aes->mode == MZ_AES_MODE_GCM) + return MZ_SUPPORT_ERROR; + else + return MZ_PARAM_ERROR; + + if (key_length == 16) + alg_id = CALG_AES_128; + else if (key_length == 24) + alg_id = CALG_AES_192; + else if (key_length == 32) + alg_id = CALG_AES_256; + else + return MZ_PARAM_ERROR; + + result = CryptAcquireContext(&aes->provider, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT); + if (result) { + key_blob_size = sizeof(key_blob_header_s) + key_length; + key_blob = (uint8_t *)malloc(key_blob_size); + if (key_blob) { + key_blob_s = (key_blob_header_s *)key_blob; + key_blob_s->hdr.bType = PLAINTEXTKEYBLOB; + key_blob_s->hdr.bVersion = CUR_BLOB_VERSION; + key_blob_s->hdr.aiKeyAlg = alg_id; + key_blob_s->hdr.reserved = 0; + key_blob_s->key_length = key_length; + + memcpy(key_blob + sizeof(key_blob_header_s), key, key_length); + + result = CryptImportKey(aes->provider, key_blob, key_blob_size, 0, 0, &aes->key); + + SecureZeroMemory(key_blob, key_blob_size); + free(key_blob); + } else { + err = MZ_MEM_ERROR; + } + } + + if (result && err == MZ_OK) + result = CryptSetKeyParam(aes->key, KP_MODE, (const uint8_t *)&mode, 0); + + if (!result && err == MZ_OK) { + aes->error = GetLastError(); + err = MZ_CRYPT_ERROR; + } + + if (result && err == MZ_OK && iv) { + if (aes->mode == MZ_AES_MODE_ECB) + return MZ_PARAM_ERROR; + + result = CryptSetKeyParam(aes->key, KP_IV, iv, 0); + + if (!result) { + aes->error = GetLastError(); + return MZ_CRYPT_ERROR; + } + } + + if (hash) + CryptDestroyHash(hash); + + return err; +} + +int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length) { + return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length); +} + +int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length, const void *iv, + int32_t iv_length) { + return mz_crypt_aes_set_key(handle, key, key_length, iv, iv_length); +} + +void mz_crypt_aes_set_mode(void *handle, int32_t mode) { + mz_crypt_aes *aes = (mz_crypt_aes *)handle; + aes->mode = mode; +} + +void *mz_crypt_aes_create(void) { + mz_crypt_aes *aes = (mz_crypt_aes *)calloc(1, sizeof(mz_crypt_aes)); + return aes; +} + +void mz_crypt_aes_delete(void **handle) { + mz_crypt_aes *aes = NULL; + if (!handle) + return; + aes = (mz_crypt_aes *)*handle; + if (aes) { + mz_crypt_aes_free(*handle); + free(aes); + } + *handle = NULL; +} + +/***************************************************************************/ + +typedef struct mz_crypt_hmac_s { + HCRYPTPROV provider; + HCRYPTHASH hash; + HCRYPTKEY key; + HMAC_INFO info; + int32_t mode; + int32_t error; + uint16_t algorithm; +} mz_crypt_hmac; + +/***************************************************************************/ + +static void mz_crypt_hmac_free(void *handle) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + if (hmac->key) + CryptDestroyKey(hmac->key); + hmac->key = 0; + if (hmac->hash) + CryptDestroyHash(hmac->hash); + hmac->hash = 0; + if (hmac->provider) + CryptReleaseContext(hmac->provider, 0); + hmac->provider = 0; + memset(&hmac->info, 0, sizeof(hmac->info)); +} + +void mz_crypt_hmac_reset(void *handle) { + mz_crypt_hmac_free(handle); +} + +int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + ALG_ID alg_id = 0; + typedef struct key_blob_header_s { + BLOBHEADER hdr; + uint32_t key_length; + } key_blob_header_s; + key_blob_header_s *key_blob_s = NULL; + uint8_t *key_blob = NULL; + int32_t key_blob_size = 0; + int32_t pad_key_length = key_length; + int32_t result = 0; + int32_t err = MZ_OK; + + if (!hmac || !key) + return MZ_PARAM_ERROR; + + mz_crypt_hmac_reset(handle); + + if (hmac->algorithm == MZ_HASH_SHA1) + alg_id = CALG_SHA1; + else +# ifdef CALG_SHA_256 + alg_id = CALG_SHA_256; +# else + return MZ_SUPPORT_ERROR; +# endif + + hmac->info.HashAlgid = alg_id; + + result = + CryptAcquireContext(&hmac->provider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT); + + if (!result) { + hmac->error = GetLastError(); + err = MZ_CRYPT_ERROR; + } else { + /* Pad single char key to work around CryptImportKey returning ERROR_INVALID_PARAMETER */ + if (pad_key_length == 1) + pad_key_length += 1; + key_blob_size = sizeof(key_blob_header_s) + pad_key_length; + key_blob = (uint8_t *)malloc(key_blob_size); + } + + if (key_blob) { + memset(key_blob, 0, key_blob_size); + key_blob_s = (key_blob_header_s *)key_blob; + key_blob_s->hdr.bType = PLAINTEXTKEYBLOB; + key_blob_s->hdr.bVersion = CUR_BLOB_VERSION; + key_blob_s->hdr.aiKeyAlg = CALG_RC2; + key_blob_s->hdr.reserved = 0; + key_blob_s->key_length = pad_key_length; + + memcpy(key_blob + sizeof(key_blob_header_s), key, key_length); + + result = CryptImportKey(hmac->provider, key_blob, key_blob_size, 0, CRYPT_IPSEC_HMAC_KEY, &hmac->key); + if (result) + result = CryptCreateHash(hmac->provider, CALG_HMAC, hmac->key, 0, &hmac->hash); + if (result) + result = CryptSetHashParam(hmac->hash, HP_HMAC_INFO, (uint8_t *)&hmac->info, 0); + + SecureZeroMemory(key_blob, key_blob_size); + free(key_blob); + } else if (err == MZ_OK) { + err = MZ_MEM_ERROR; + } + + if (!result) { + hmac->error = GetLastError(); + err = MZ_CRYPT_ERROR; + } + + if (err != MZ_OK) + mz_crypt_hmac_free(handle); + + return err; +} + +int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + int32_t result = 0; + + if (!hmac || !buf || !hmac->hash) + return MZ_PARAM_ERROR; + + result = CryptHashData(hmac->hash, buf, size, 0); + if (!result) { + hmac->error = GetLastError(); + return MZ_HASH_ERROR; + } + return MZ_OK; +} + +int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + int32_t result = 0; + int32_t expected_size = 0; + + if (!hmac || !digest || !hmac->hash) + return MZ_PARAM_ERROR; + result = CryptGetHashParam(hmac->hash, HP_HASHVAL, NULL, (DWORD *)&expected_size, 0); + if (expected_size > digest_size) + return MZ_BUF_ERROR; + if (!result) + return MZ_HASH_ERROR; + result = CryptGetHashParam(hmac->hash, HP_HASHVAL, digest, (DWORD *)&digest_size, 0); + if (!result) { + hmac->error = GetLastError(); + return MZ_HASH_ERROR; + } + return MZ_OK; +} + +void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle; + hmac->algorithm = algorithm; +} + +int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle) { + mz_crypt_hmac *source = (mz_crypt_hmac *)src_handle; + mz_crypt_hmac *target = (mz_crypt_hmac *)target_handle; + int32_t result = 0; + int32_t err = MZ_OK; + + if (target->hash) { + CryptDestroyHash(target->hash); + target->hash = 0; + } + + result = CryptDuplicateHash(source->hash, NULL, 0, &target->hash); + + if (!result) { + target->error = GetLastError(); + err = MZ_HASH_ERROR; + } + return err; +} + +void *mz_crypt_hmac_create(void) { + mz_crypt_hmac *hmac = (mz_crypt_hmac *)calloc(1, sizeof(mz_crypt_hmac)); + if (hmac) + hmac->algorithm = MZ_HASH_SHA256; + return hmac; +} + +void mz_crypt_hmac_delete(void **handle) { + mz_crypt_hmac *hmac = NULL; + if (!handle) + return; + hmac = (mz_crypt_hmac *)*handle; + if (hmac) { + mz_crypt_hmac_free(*handle); + free(hmac); + } + *handle = NULL; +} + +#endif diff --git a/thirdparty/minizip/mz_os.c b/thirdparty/minizip/mz_os.c new file mode 100644 index 000000000..8ba7cc976 --- /dev/null +++ b/thirdparty/minizip/mz_os.c @@ -0,0 +1,471 @@ +/* mz_os.c -- System functions + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Copyright (C) 1998-2010 Gilles Vollant + https://www.winimage.com/zLibDll/minizip.html + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_crypt.h" +#include "mz_os.h" +#include "mz_strm.h" +#include "mz_strm_os.h" + +#include /* tolower */ +#include + +/***************************************************************************/ + +int32_t mz_path_combine(char *path, const char *join, int32_t max_path) { + int32_t path_len = 0; + + if (!path || !join || !max_path) + return MZ_PARAM_ERROR; + + path_len = (int32_t)strlen(path); + + if (path_len == 0) { + strncpy(path, join, max_path - 1); + path[max_path - 1] = 0; + } else { + mz_path_append_slash(path, max_path, MZ_PATH_SLASH_PLATFORM); + path_len = (int32_t)strlen(path); + if (max_path > path_len) + strncat(path, join, max_path - path_len - 1); + } + + return MZ_OK; +} + +int32_t mz_path_append_slash(char *path, int32_t max_path, char slash) { + int32_t path_len = (int32_t)strlen(path); + if ((path_len + 2) >= max_path) + return MZ_BUF_ERROR; + if (!mz_os_is_dir_separator(path[path_len - 1])) { + path[path_len] = slash; + path[path_len + 1] = 0; + } + return MZ_OK; +} + +int32_t mz_path_remove_slash(char *path) { + int32_t path_len = (int32_t)strlen(path); + while (path_len > 0) { + if (mz_os_is_dir_separator(path[path_len - 1])) + path[path_len - 1] = 0; + else + break; + + path_len -= 1; + } + return MZ_OK; +} + +int32_t mz_path_has_slash(const char *path) { + int32_t path_len = (int32_t)strlen(path); + if (path_len > 0 && !mz_os_is_dir_separator(path[path_len - 1])) + return MZ_EXIST_ERROR; + return MZ_OK; +} + +int32_t mz_path_convert_slashes(char *path, char slash) { + int32_t i = 0; + + for (i = 0; i < (int32_t)strlen(path); i += 1) { + if (mz_os_is_dir_separator(path[i])) + path[i] = slash; + } + return MZ_OK; +} + +int32_t mz_path_compare_wc(const char *path, const char *wildcard, uint8_t ignore_case) { + while (*path != 0) { + switch (*wildcard) { + case '*': + + if (*(wildcard + 1) == 0) + return MZ_OK; + + while (*path != 0) { + if (mz_path_compare_wc(path, (wildcard + 1), ignore_case) == MZ_OK) + return MZ_OK; + + path += 1; + } + + return MZ_EXIST_ERROR; + + default: + /* Ignore differences in path slashes on platforms */ + if ((*path == '\\' && *wildcard == '/') || (*path == '/' && *wildcard == '\\')) + break; + + if (ignore_case) { + if (tolower(*path) != tolower(*wildcard)) + return MZ_EXIST_ERROR; + } else { + if (*path != *wildcard) + return MZ_EXIST_ERROR; + } + + break; + } + + path += 1; + wildcard += 1; + } + + if ((*wildcard != 0) && (*wildcard != '*')) + return MZ_EXIST_ERROR; + + return MZ_OK; +} + +int32_t mz_path_resolve(const char *path, char *output, int32_t max_output) { + const char *source = path; + const char *check = output; + char *target = output; + + if (max_output <= 0) + return MZ_PARAM_ERROR; + + while (*source != 0 && max_output > 1) { + check = source; + if (mz_os_is_dir_separator(*check)) + check += 1; + + if (source == path || target == output || check != source) { + /* Skip double paths */ + if (mz_os_is_dir_separator(*check)) { + source += 1; + continue; + } + if (*check == '.') { + check += 1; + + /* Remove . if at end of string and not at the beginning */ + if (*check == 0 && source != path && target != output) { + /* Copy last slash */ + *target = *source; + target += 1; + max_output -= 1; + source += (check - source); + continue; + } + /* Remove . if not at end of string */ + else if (mz_os_is_dir_separator(*check)) { + source += (check - source); + /* Skip slash if at beginning of string */ + if (target == output && *source != 0) + source += 1; + continue; + } + /* Go to parent directory .. */ + else if (*check == '.') { + check += 1; + if (*check == 0 || mz_os_is_dir_separator(*check)) { + source += (check - source); + + /* Search backwards for previous slash or the start of the output string */ + if (target != output) { + target -= 1; + do { + if (target == output || mz_os_is_dir_separator(*target)) + break; + + target -= 1; + max_output += 1; + } while (target > output); + } + + if ((target == output) && *source != 0) + source += 1; + if (mz_os_is_dir_separator(*target) && *source == 0) + target += 1; + + *target = 0; + continue; + } + } + } + } + + *target = *source; + + source += 1; + target += 1; + max_output -= 1; + } + + *target = 0; + + if (*path == 0) + return MZ_INTERNAL_ERROR; + + return MZ_OK; +} + +int32_t mz_path_remove_filename(char *path) { + char *path_ptr = NULL; + + if (!path) + return MZ_PARAM_ERROR; + + path_ptr = path + strlen(path) - 1; + + while (path_ptr > path) { + if (mz_os_is_dir_separator(*path_ptr)) { + *path_ptr = 0; + break; + } + + path_ptr -= 1; + } + + if (path_ptr == path) + *path_ptr = 0; + + return MZ_OK; +} + +int32_t mz_path_remove_extension(char *path) { + char *path_ptr = NULL; + + if (!path) + return MZ_PARAM_ERROR; + + path_ptr = path + strlen(path) - 1; + + while (path_ptr > path) { + if (mz_os_is_dir_separator(*path_ptr)) + break; + if (*path_ptr == '.') { + *path_ptr = 0; + break; + } + + path_ptr -= 1; + } + + if (path_ptr == path) + *path_ptr = 0; + + return MZ_OK; +} + +int32_t mz_path_get_filename(const char *path, const char **filename) { + const char *match = NULL; + + if (!path || !filename) + return MZ_PARAM_ERROR; + + *filename = NULL; + + for (match = path; *match != 0; match += 1) { + if (mz_os_is_dir_separator(*match)) + *filename = match + 1; + } + + if (!*filename) + return MZ_EXIST_ERROR; + + return MZ_OK; +} + +int32_t mz_dir_has_unsafe_symlink(const char *path, const char *base_path) { + char *check_path = NULL; + char *symlink_target = NULL; + char *combined = NULL; + char *resolved = NULL; + size_t path_len = 0; + size_t base_len = 0; + size_t max_path = 1024; + size_t parent_len = 0; + size_t pos = 0; + size_t cmp_len = 0; + int32_t err = MZ_OK; + + if (!path || *path == 0 || !base_path) + return MZ_PARAM_ERROR; + + path_len = strlen(path); + base_len = strlen(base_path); + + /* Remove trailing slash from base_path for comparison */ + while (base_len > 0 && mz_os_is_dir_separator(base_path[base_len - 1])) + base_len--; + + check_path = (char *)calloc(1, path_len + 1); + if (!check_path) + return MZ_MEM_ERROR; + + /* Walk through each path component */ + while (err == MZ_OK && pos < path_len) { + /* Copy separator if present */ + if (mz_os_is_dir_separator(path[pos])) { + check_path[pos] = path[pos]; + pos++; + } + + /* Copy next path component */ + while (pos < path_len && !mz_os_is_dir_separator(path[pos])) { + check_path[pos] = path[pos]; + pos++; + } + check_path[pos] = 0; + + /* Check if this existing path component is a symlink */ + if (mz_os_is_symlink(check_path) != MZ_OK) + continue; + + /* Skip components at or above the base dir. */ + cmp_len = pos; + if (mz_path_has_slash(check_path) == MZ_OK) + cmp_len--; + if (cmp_len <= base_len && strncmp(check_path, base_path, cmp_len) == 0) { + /* Verify that the prefix match is on a directory boundary. */ + if (cmp_len == base_len || mz_os_is_dir_separator(base_path[cmp_len])) + continue; + } + + /* Allocate symlink buffers on first use */ + if (!symlink_target) { + symlink_target = (char *)calloc(1, max_path); + combined = (char *)calloc(1, max_path); + resolved = (char *)calloc(1, max_path); + + if (!symlink_target || !combined || !resolved) { + err = MZ_MEM_ERROR; + break; + } + } + + if (mz_os_read_symlink(check_path, symlink_target, max_path) != MZ_OK) { + err = MZ_EXIST_ERROR; + break; + } + + /* Absolute symlink targets are not allowed */ + if (mz_os_is_dir_separator(symlink_target[0])) { + err = MZ_EXIST_ERROR; + break; + } + + /* Find parent directory length by scanning backwards past filename and trailing slashes */ + parent_len = pos; + while (parent_len > 0 && !mz_os_is_dir_separator(check_path[parent_len - 1])) + parent_len--; + while (parent_len > 0 && mz_os_is_dir_separator(check_path[parent_len - 1])) + parent_len--; + + /* Combine parent + symlink_target */ + combined[0] = 0; + if (parent_len > 0) { + strncpy(combined, check_path, parent_len); + combined[parent_len] = 0; + mz_path_append_slash(combined, (int32_t)max_path, MZ_PATH_SLASH_PLATFORM); + } + strncat(combined, symlink_target, max_path - strlen(combined) - 1); + + /* Resolve the combined path to eliminate .. */ + if (mz_path_resolve(combined, resolved, (int32_t)max_path) != MZ_OK) { + err = MZ_EXIST_ERROR; + break; + } + + /* Check that resolved path starts with base_path */ + if (strlen(resolved) < base_len || + strncmp(resolved, base_path, base_len) != 0 || + (resolved[base_len] != 0 && !mz_os_is_dir_separator(resolved[base_len]))) { + err = MZ_EXIST_ERROR; + break; + } + } + + free(check_path); + free(symlink_target); + free(combined); + free(resolved); + + return err; +} + +int32_t mz_dir_make(const char *path) { + int32_t err = MZ_OK; + char *current_dir = NULL; + char *match = NULL; + char hold = 0; + + if (!*path) + return MZ_OK; + + current_dir = strdup(path); + if (!current_dir) + return MZ_MEM_ERROR; + + mz_path_remove_slash(current_dir); + + err = mz_os_make_dir(current_dir); + if (err != MZ_OK) { + match = current_dir + 1; + while (1) { + while (*match != 0 && !mz_os_is_dir_separator(*match)) + match += 1; + hold = *match; + *match = 0; + + err = mz_os_make_dir(current_dir); + if (err != MZ_OK) + break; + if (hold == 0) + break; + + *match = hold; + match += 1; + } + } + + free(current_dir); + return err; +} + +int32_t mz_file_get_crc(const char *path, uint32_t *result_crc) { + void *stream = NULL; + uint32_t crc32 = 0; + int32_t read = 0; + int32_t err = MZ_OK; + uint8_t buf[16384]; + + stream = mz_stream_os_create(); + if (!stream) + return MZ_MEM_ERROR; + + err = mz_stream_os_open(stream, path, MZ_OPEN_MODE_READ); + if (err == MZ_OK) { + do { + read = mz_stream_os_read(stream, buf, sizeof(buf)); + + if (read < 0) { + err = read; + break; + } + + crc32 = mz_crypt_crc32_update(crc32, buf, read); + } while ((err == MZ_OK) && (read > 0)); + + mz_stream_os_close(stream); + } + + *result_crc = crc32; + + mz_stream_os_delete(&stream); + + return err; +} + +/***************************************************************************/ diff --git a/thirdparty/minizip/mz_os.h b/thirdparty/minizip/mz_os.h new file mode 100644 index 000000000..25cc6037b --- /dev/null +++ b/thirdparty/minizip/mz_os.h @@ -0,0 +1,198 @@ +/* mz_os.h -- System functions + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_OS_H +#define MZ_OS_H + +/***************************************************************************/ + +#if defined(__APPLE__) +# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_OSX_DARWIN) +#elif defined(__riscos__) +# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_RISCOS) +#elif defined(_WIN32) +# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_WINDOWS_NTFS) +#else +# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_UNIX) +#endif + +#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP) || defined(HAVE_PPMD) +# define MZ_VERSION_MADEBY_ZIP_VERSION (63) +#elif defined(HAVE_WZAES) +# define MZ_VERSION_MADEBY_ZIP_VERSION (51) +#elif defined(HAVE_BZIP2) +# define MZ_VERSION_MADEBY_ZIP_VERSION (46) +#else +# define MZ_VERSION_MADEBY_ZIP_VERSION (45) +#endif + +#define MZ_VERSION_MADEBY ((MZ_VERSION_MADEBY_HOST_SYSTEM << 8) | (MZ_VERSION_MADEBY_ZIP_VERSION)) + +#define MZ_PATH_SLASH_UNIX ('/') +#define MZ_PATH_SLASH_WINDOWS ('\\') +#if defined(_WIN32) +# define MZ_PATH_SLASH_PLATFORM (MZ_PATH_SLASH_WINDOWS) +#else +# define MZ_PATH_SLASH_PLATFORM (MZ_PATH_SLASH_UNIX) +#endif + +/***************************************************************************/ + +#include "mz_config.h" + +#if HAVE_DIRENT_H +# include +#elif HAVE_SYS_DIRENT_H +# include +#else +struct dirent { + char d_name[256]; +}; +#endif + +#if !HAVE_PDIR +typedef struct DIR DIR; +#endif + +/***************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ +/* Shared functions */ + +int32_t mz_path_combine(char *path, const char *join, int32_t max_path); +/* Combines two paths */ + +int32_t mz_path_append_slash(char *path, int32_t max_path, char slash); +/* Appends a path slash on to the end of the path */ + +int32_t mz_path_remove_slash(char *path); +/* Removes a path slash from the end of the path */ + +int32_t mz_path_has_slash(const char *path); +/* Returns whether or not the path ends with slash */ + +int32_t mz_path_convert_slashes(char *path, char slash); +/* Converts the slashes in a path */ + +int32_t mz_path_compare_wc(const char *path, const char *wildcard, uint8_t ignore_case); +/* Compare two paths with wildcard */ + +int32_t mz_path_resolve(const char *path, char *target, int32_t max_target); +/* Resolves path */ + +int32_t mz_path_remove_filename(char *path); +/* Remove the filename from a path */ + +int32_t mz_path_remove_extension(char *path); +/* Remove the extension from a path */ + +int32_t mz_path_get_filename(const char *path, const char **filename); +/* Get the filename from a path */ + +int32_t mz_dir_has_unsafe_symlink(const char *path, const char *base_path); +/* Checks if any existing component of path is a symlink that escapes base path. */ + +int32_t mz_dir_make(const char *path); +/* Creates a directory recursively */ + +int32_t mz_file_get_crc(const char *path, uint32_t *result_crc); +/* Gets the crc32 hash of a file */ + +/***************************************************************************/ +/* Platform specific functions */ + +wchar_t *mz_os_unicode_string_create(const char *string, int32_t encoding); +/* Create unicode string from a utf8 string */ + +void mz_os_unicode_string_delete(wchar_t **string); +/* Delete a unicode string that was created */ + +char *mz_os_utf8_string_create(const char *string, int32_t encoding); +/* Create a utf8 string from a string with another encoding */ + +void mz_os_utf8_string_delete(char **string); +/* Delete a utf8 string that was created */ + +int32_t mz_os_rand(uint8_t *buf, int32_t size); +/* Random number generator (not cryptographically secure) */ + +int32_t mz_os_rename(const char *source_path, const char *target_path); +/* Rename a file */ + +int32_t mz_os_unlink(const char *path); +/* Delete an existing file */ + +int32_t mz_os_file_exists(const char *path); +/* Check to see if a file exists */ + +int64_t mz_os_get_file_size(const char *path); +/* Gets the length of a file */ + +int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date); +/* Gets a file's modified, access, and creation dates if supported */ + +int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date); +/* Sets a file's modified, access, and creation dates if supported */ + +int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes); +/* Gets a file's attributes, following symbolic links */ + +int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes); +/* Sets a file's attributes */ + +int32_t mz_os_get_temp_path(char *path, int32_t max_path, const char *prefix); +/* Gets a unique temporary file path */ + +int32_t mz_os_path_same_fs(const char *path_a, const char *path_b); +/* Checks if both paths are on the same filesystem */ + +int32_t mz_os_make_dir(const char *path); +/* Recursively creates a directory */ + +DIR *mz_os_open_dir(const char *path); +/* Opens a directory for listing */ +struct dirent *mz_os_read_dir(DIR *dir); +/* Reads a directory listing entry */ + +int32_t mz_os_close_dir(DIR *dir); +/* Closes a directory that has been opened for listing */ + +int32_t mz_os_is_dir_separator(char c); +/* Checks to see if character is a directory separator */ + +int32_t mz_os_is_dir(const char *path); +/* Checks to see if path is a directory */ + +int32_t mz_os_is_symlink(const char *path); +/* Checks to see if path is a symbolic link */ + +int32_t mz_os_get_link_attribs(const char *path, uint32_t *attributes); +/* Gets a symbolic link's attributes */ + +int32_t mz_os_make_symlink(const char *path, const char *target_path); +/* Creates a symbolic link pointing to a target */ + +int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path); +/* Gets the target path for a symbolic link */ + +uint64_t mz_os_ms_time(void); +/* Gets the time in milliseconds */ + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_os_posix.c b/thirdparty/minizip/mz_os_posix.c new file mode 100644 index 000000000..b0378a248 --- /dev/null +++ b/thirdparty/minizip/mz_os_posix.c @@ -0,0 +1,445 @@ +/* mz_os_posix.c -- System functions for posix + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_config.h" +#include "mz_strm.h" +#include "mz_os.h" + +#include /* rename */ +#include +#if defined(HAVE_ICONV) +# include +#endif +#include +#include +#include + +#ifndef _WIN32 +# include +# include +#endif +#if defined(__APPLE__) +# include +# include +#endif + +#if defined(HAVE_GETRANDOM) +# include +#endif +#if defined(HAVE_LIBBSD) +# include /* arc4random_buf */ +#endif + +#ifndef MZ_PRESERVE_NATIVE_STRUCTURE +# define MZ_PRESERVE_NATIVE_STRUCTURE 1 +#endif + +/***************************************************************************/ + +#if defined(HAVE_ICONV) +char *mz_os_utf8_string_create(const char *string, int32_t encoding) { + iconv_t cd; + /// up to CP2147483647 + char string_encoding[13]; + const char *from_encoding = NULL; + size_t result = 0; + size_t string_length = 0; + size_t string_utf8_size = 0; + char *string_utf8 = NULL; + char *string_utf8_ptr = NULL; + + if (!string || encoding <= 0) + return NULL; + + if (encoding == MZ_ENCODING_UTF8) + from_encoding = "UTF-8"; + else { + snprintf(string_encoding, sizeof(string_encoding), "CP%03" PRId32, encoding); + from_encoding = string_encoding; + } + + cd = iconv_open("UTF-8", from_encoding); + if (cd == (iconv_t)-1) + return NULL; + + string_length = strlen(string); + string_utf8_size = string_length * 2; + string_utf8 = (char *)calloc((int32_t)(string_utf8_size + 1), sizeof(char)); + string_utf8_ptr = string_utf8; + + if (string_utf8) { + result = iconv(cd, (char **)&string, &string_length, (char **)&string_utf8_ptr, &string_utf8_size); + } + + iconv_close(cd); + + if (result == (size_t)-1) { + free(string_utf8); + string_utf8 = NULL; + } + + return string_utf8; +} +#else +char *mz_os_utf8_string_create(const char *string, int32_t encoding) { + return strdup(string); +} +#endif + +void mz_os_utf8_string_delete(char **string) { + if (string) { + free(*string); + *string = NULL; + } +} + +/***************************************************************************/ + +#if defined(HAVE_GETRANDOM) +int32_t mz_os_rand(uint8_t *buf, int32_t size) { + int32_t left = size; + int32_t written = 0; + + while (left > 0) { + written = getrandom(buf, left, 0); + if (written < 0) + return MZ_INTERNAL_ERROR; + + buf += written; + left -= written; + } + return size - left; +} +#elif defined(HAVE_ARC4RANDOM_BUF) +int32_t mz_os_rand(uint8_t *buf, int32_t size) { + if (size < 0) + return 0; + arc4random_buf(buf, (uint32_t)size); + return size; +} +#elif defined(HAVE_ARC4RANDOM) +int32_t mz_os_rand(uint8_t *buf, int32_t size) { + int32_t left = size; + for (; left > 2; left -= 3, buf += 3) { + uint32_t val = arc4random(); + + buf[0] = (val) & 0xFF; + buf[1] = (val >> 8) & 0xFF; + buf[2] = (val >> 16) & 0xFF; + } + for (; left > 0; left--, buf++) { + *buf = arc4random() & 0xFF; + } + return size - left; +} +#else +int32_t mz_os_rand(uint8_t *buf, int32_t size) { + static unsigned calls = 0; + int32_t i = 0; + + /* Ensure different random header each time */ + if (++calls == 1) { +# define PI_SEED 3141592654UL + srand((unsigned)(time(NULL) ^ PI_SEED)); + } + + while (i < size) + buf[i++] = (rand() >> 7) & 0xff; + + return size; +} +#endif + +int32_t mz_os_rename(const char *source_path, const char *target_path) { + if (rename(source_path, target_path) == -1) + return MZ_EXIST_ERROR; + + return MZ_OK; +} + +int32_t mz_os_path_same_fs(const char *path_a, const char *path_b) { + struct stat sa, sb; + if (!path_a || !path_b) + return MZ_PARAM_ERROR; + if (stat(path_a, &sa) != 0 || stat(path_b, &sb) != 0) + return MZ_EXIST_ERROR; + return (sa.st_dev == sb.st_dev) ? MZ_OK : MZ_EXIST_ERROR; +} + +int32_t mz_os_unlink(const char *path) { + if (unlink(path) == -1) + return MZ_EXIST_ERROR; + + return MZ_OK; +} + +int32_t mz_os_file_exists(const char *path) { + struct stat path_stat; + + memset(&path_stat, 0, sizeof(path_stat)); + if (stat(path, &path_stat) == 0) + return MZ_OK; + return MZ_EXIST_ERROR; +} + +int64_t mz_os_get_file_size(const char *path) { + struct stat path_stat; + + memset(&path_stat, 0, sizeof(path_stat)); + if (stat(path, &path_stat) == 0) { + /* Stat returns size taken up by directory entry, so return 0 */ + if (S_ISDIR(path_stat.st_mode)) + return 0; + + return path_stat.st_size; + } + + return 0; +} + +int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date) { + struct stat path_stat; + char *name = NULL; + int32_t err = MZ_INTERNAL_ERROR; + + memset(&path_stat, 0, sizeof(path_stat)); + + if (strcmp(path, "-") != 0) { + /* Not all systems allow stat'ing a file with / appended */ + name = strdup(path); + mz_path_remove_slash(name); + + if (stat(name, &path_stat) == 0) { + if (modified_date) + *modified_date = path_stat.st_mtime; + if (accessed_date) + *accessed_date = path_stat.st_atime; + /* Creation date not supported */ + if (creation_date) + *creation_date = 0; + + err = MZ_OK; + } + + free(name); + } + + return err; +} + +int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date) { + struct utimbuf ut; + + ut.actime = accessed_date; + ut.modtime = modified_date; + + /* Creation date not supported */ + MZ_UNUSED(creation_date); + + if (utime(path, &ut) != 0) + return MZ_INTERNAL_ERROR; + + return MZ_OK; +} + +int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes) { + struct stat path_stat; + int32_t err = MZ_OK; + + memset(&path_stat, 0, sizeof(path_stat)); + if (stat(path, &path_stat) == -1) + err = MZ_INTERNAL_ERROR; + *attributes = path_stat.st_mode; + return err; +} + +int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes) { + int32_t err = MZ_OK; + + if (chmod(path, (mode_t)attributes) == -1) + err = MZ_INTERNAL_ERROR; + + return err; +} + +int32_t mz_os_make_dir(const char *path) { + int32_t err = 0; + + err = mkdir(path, 0755); + + if (err != 0 && errno != EEXIST) + return MZ_INTERNAL_ERROR; + + return MZ_OK; +} + +DIR *mz_os_open_dir(const char *path) { + return opendir(path); +} + +struct dirent *mz_os_read_dir(DIR *dir) { + if (!dir) + return NULL; + return readdir(dir); +} + +int32_t mz_os_close_dir(DIR *dir) { + if (!dir) + return MZ_PARAM_ERROR; + if (closedir(dir) == -1) + return MZ_INTERNAL_ERROR; + return MZ_OK; +} + +int32_t mz_os_is_dir_separator(char c) { +#if MZ_PRESERVE_NATIVE_STRUCTURE + // While not strictly adhering to 4.4.17.1, + // this preserves UNIX filesystem structure. + return c == '/'; +#else + // While strictly adhering to 4.4.17.1, + // this corrupts UNIX filesystem structure (a filename with a '\\' will become a folder + a file). + return c == '\\' || c == '/'; +#endif +} + +int32_t mz_os_is_dir(const char *path) { + struct stat path_stat; + + memset(&path_stat, 0, sizeof(path_stat)); + stat(path, &path_stat); + if (S_ISDIR(path_stat.st_mode)) + return MZ_OK; + + return MZ_EXIST_ERROR; +} + +int32_t mz_os_is_symlink(const char *path) { + struct stat path_stat; + + memset(&path_stat, 0, sizeof(path_stat)); + lstat(path, &path_stat); + if (S_ISLNK(path_stat.st_mode)) + return MZ_OK; + + return MZ_EXIST_ERROR; +} + +int32_t mz_os_get_link_attribs(const char *path, uint32_t *attributes) { + struct stat path_stat; + int32_t err = MZ_OK; + + memset(&path_stat, 0, sizeof(path_stat)); + if (lstat(path, &path_stat) == -1) + err = MZ_INTERNAL_ERROR; + *attributes = path_stat.st_mode; + return err; +} + +int32_t mz_os_make_symlink(const char *path, const char *target_path) { +#if !HAVE_SYMLINK + return MZ_SUPPORT_ERROR; +#else + if (symlink(target_path, path) != 0) + return MZ_INTERNAL_ERROR; + return MZ_OK; +#endif +} + +int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path) { +#if !HAVE_READLINK + return MZ_SUPPORT_ERROR; +#else + size_t length = 0; + + length = (size_t)readlink(path, target_path, max_target_path - 1); + if (length == (size_t)-1) + return MZ_EXIST_ERROR; + if (length >= (size_t)(max_target_path - 1)) + return MZ_BUF_ERROR; + + target_path[length] = 0; + return MZ_OK; +#endif +} + +int32_t mz_os_get_temp_path(char *path, int32_t max_path, const char *prefix) { + const char *tmp_dir = NULL; + char *temp_path; + int32_t result = 0; + + if (!path || max_path <= 0) + return MZ_PARAM_ERROR; + + tmp_dir = getenv("TMPDIR"); + if (!tmp_dir) + tmp_dir = getenv("TMP"); + if (!tmp_dir) + tmp_dir = getenv("TEMP"); + if (!tmp_dir) + tmp_dir = "/tmp"; + + /* Construct path for mkdtemp in the form /XXXXXX */ + temp_path = (char *)calloc(max_path, sizeof(char)); + if (!temp_path) + return MZ_MEM_ERROR; + + /* mkdtemp replaces XXXXXX with unique characters */ + result = snprintf(temp_path, max_path, "%s/%sXXXXXX", tmp_dir, prefix ? prefix : ""); + if (result < 0 || result >= max_path) { + free(temp_path); + return MZ_BUF_ERROR; + } + + /* Create a temporary directory. */ + if (!mkdtemp(temp_path)) { + free(temp_path); + return MZ_INTERNAL_ERROR; + } + + /* Create a filename inside the temporary directory using current time */ + result = snprintf(path, max_path, "%s/%lux", temp_path, time(NULL)); + if (result < 0 || result >= max_path) { + rmdir(temp_path); + free(temp_path); + return MZ_BUF_ERROR; + } + + free(temp_path); + return MZ_OK; +} + +uint64_t mz_os_ms_time(void) { + struct timespec ts; + +#if defined(__APPLE__) + clock_serv_t cclock; + mach_timespec_t mts; + + host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + + ts.tv_sec = mts.tv_sec; + ts.tv_nsec = mts.tv_nsec; +#elif !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0 + clock_gettime(CLOCK_REALTIME, &ts); +#elif _POSIX_MONOTONIC_CLOCK > 0 + clock_gettime(CLOCK_MONOTONIC, &ts); +#else + if (sysconf(_SC_MONOTONIC_CLOCK) > 0) + clock_gettime(CLOCK_MONOTONIC, &ts); + else + clock_gettime(CLOCK_REALTIME, &ts); +#endif + + return ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000); +} diff --git a/thirdparty/minizip/mz_os_win32.c b/thirdparty/minizip/mz_os_win32.c new file mode 100644 index 000000000..ba2153411 --- /dev/null +++ b/thirdparty/minizip/mz_os_win32.c @@ -0,0 +1,760 @@ +/* mz_os_win32.c -- System functions for Windows + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_os.h" +#include "mz_strm_os.h" + +#include +#include + +#include +#include + +/***************************************************************************/ + +#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY +# define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1 +#endif + +#ifndef _WIN32_WINNT_WIN8 +# define _WIN32_WINNT_WIN8 0x0602 +#endif + +/***************************************************************************/ + +typedef struct DIR_int_s { + void *find_handle; + WIN32_FIND_DATAW find_data; + struct dirent entry; + uint8_t end; +} DIR_int; + +/***************************************************************************/ + +wchar_t *mz_os_unicode_string_create(const char *string, int32_t encoding) { + wchar_t *string_wide = NULL; + uint32_t string_wide_size = 0; + + string_wide_size = MultiByteToWideChar(encoding, 0, string, -1, NULL, 0); + if (string_wide_size == 0) + return NULL; + string_wide = (wchar_t *)calloc(string_wide_size + 1, sizeof(wchar_t)); + if (!string_wide) + return NULL; + + MultiByteToWideChar(encoding, 0, string, -1, string_wide, string_wide_size); + return string_wide; +} + +void mz_os_unicode_string_delete(wchar_t **string) { + if (string) { + free(*string); + *string = NULL; + } +} + +char *mz_os_utf8_string_create(const char *string, int32_t encoding) { + wchar_t *string_wide = NULL; + char *string_utf8 = NULL; + uint32_t string_utf8_size = 0; + + string_wide = mz_os_unicode_string_create(string, encoding); + if (string_wide) { + string_utf8_size = WideCharToMultiByte(CP_UTF8, 0, string_wide, -1, NULL, 0, NULL, NULL); + string_utf8 = (char *)calloc(string_utf8_size + 1, sizeof(char)); + + if (string_utf8) + WideCharToMultiByte(CP_UTF8, 0, string_wide, -1, string_utf8, string_utf8_size, NULL, NULL); + + mz_os_unicode_string_delete(&string_wide); + } + + return string_utf8; +} + +char *mz_os_utf8_string_create_from_unicode(const wchar_t *string, int32_t encoding) { + char *string_utf8 = NULL; + uint32_t string_utf8_size = 0; + + MZ_UNUSED(encoding); + + string_utf8_size = WideCharToMultiByte(CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL); + string_utf8 = (char *)calloc(string_utf8_size + 1, sizeof(char)); + + if (string_utf8) + WideCharToMultiByte(CP_UTF8, 0, string, -1, string_utf8, string_utf8_size, NULL, NULL); + + return string_utf8; +} + +void mz_os_utf8_string_delete(char **string) { + if (string) { + free(*string); + *string = NULL; + } +} + +/***************************************************************************/ + +int32_t mz_os_rand(uint8_t *buf, int32_t size) { + unsigned __int64 pentium_tsc[1]; + int32_t len = 0; + + for (len = 0; len < (int)size; len += 1) { + if (len % 8 == 0) + QueryPerformanceCounter((LARGE_INTEGER *)pentium_tsc); + buf[len] = ((unsigned char *)pentium_tsc)[len % 8]; + } + + return len; +} + +int32_t mz_os_path_same_fs(const char *path_a, const char *path_b) { + wchar_t *path_a_wide = NULL; + wchar_t *path_b_wide = NULL; + struct _stati64 sa; + struct _stati64 sb; + int32_t err = MZ_OK; + + if (!path_a || !path_b) + return MZ_PARAM_ERROR; + + path_a_wide = mz_os_unicode_string_create(path_a, MZ_ENCODING_UTF8); + if (!path_a_wide) + return MZ_PARAM_ERROR; + path_b_wide = mz_os_unicode_string_create(path_b, MZ_ENCODING_UTF8); + if (!path_b_wide) { + mz_os_unicode_string_delete(&path_a_wide); + return MZ_PARAM_ERROR; + } + + if (_wstati64(path_a_wide, &sa) != 0 || _wstati64(path_b_wide, &sb) != 0) + err = MZ_EXIST_ERROR; + else if (sa.st_dev != sb.st_dev) + err = MZ_EXIST_ERROR; + + mz_os_unicode_string_delete(&path_a_wide); + mz_os_unicode_string_delete(&path_b_wide); + return err; +} + +int32_t mz_os_rename(const char *source_path, const char *target_path) { + wchar_t *source_path_wide = NULL; + wchar_t *target_path_wide = NULL; + int32_t result = 0; + int32_t err = MZ_OK; + + if (!source_path || !target_path) + return MZ_PARAM_ERROR; + + source_path_wide = mz_os_unicode_string_create(source_path, MZ_ENCODING_UTF8); + if (!source_path_wide) { + err = MZ_PARAM_ERROR; + } else { + target_path_wide = mz_os_unicode_string_create(target_path, MZ_ENCODING_UTF8); + if (!target_path_wide) + err = MZ_PARAM_ERROR; + } + + if (err == MZ_OK) { +#if _WIN32_WINNT >= _WIN32_WINNT_WINXP + result = MoveFileExW(source_path_wide, target_path_wide, MOVEFILE_WRITE_THROUGH | MOVEFILE_COPY_ALLOWED); +#else + result = MoveFileW(source_path_wide, target_path_wide); +#endif + if (result == 0) + err = MZ_EXIST_ERROR; + } + + if (target_path_wide) + mz_os_unicode_string_delete(&target_path_wide); + if (source_path_wide) + mz_os_unicode_string_delete(&source_path_wide); + + return err; +} + +int32_t mz_os_unlink(const char *path) { + wchar_t *path_wide = NULL; + int32_t result = 0; + + if (!path) + return MZ_PARAM_ERROR; + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + + if (mz_os_is_dir(path) == MZ_OK) + result = RemoveDirectoryW(path_wide); + else + result = DeleteFileW(path_wide); + + mz_os_unicode_string_delete(&path_wide); + + if (result == 0) + return MZ_EXIST_ERROR; + + return MZ_OK; +} + +int32_t mz_os_file_exists(const char *path) { + wchar_t *path_wide = NULL; + DWORD attribs = 0; + + if (!path) + return MZ_PARAM_ERROR; + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + + attribs = GetFileAttributesW(path_wide); + mz_os_unicode_string_delete(&path_wide); + + if (attribs == 0xFFFFFFFF) + return MZ_EXIST_ERROR; + + return MZ_OK; +} + +int64_t mz_os_get_file_size(const char *path) { + HANDLE handle = NULL; + LARGE_INTEGER large_size; + wchar_t *path_wide = NULL; + + if (!path) + return MZ_PARAM_ERROR; + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 + handle = CreateFile2(path_wide, GENERIC_READ, 0, OPEN_EXISTING, NULL); +#else + handle = CreateFileW(path_wide, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); +#endif + mz_os_unicode_string_delete(&path_wide); + + large_size.QuadPart = 0; + + if (handle != INVALID_HANDLE_VALUE) { + GetFileSizeEx(handle, &large_size); + CloseHandle(handle); + } + + return large_size.QuadPart; +} + +static void mz_os_file_to_unix_time(FILETIME file_time, time_t *unix_time) { + uint64_t quad_file_time = 0; + quad_file_time = file_time.dwLowDateTime; + quad_file_time |= ((uint64_t)file_time.dwHighDateTime << 32); + *unix_time = (time_t)((quad_file_time - 116444736000000000LL) / 10000000); +} + +static void mz_os_unix_to_file_time(time_t unix_time, FILETIME *file_time) { + uint64_t quad_file_time = 0; + quad_file_time = ((uint64_t)unix_time * 10000000) + 116444736000000000LL; + file_time->dwHighDateTime = (quad_file_time >> 32); + file_time->dwLowDateTime = (uint32_t)(quad_file_time); +} + +int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date) { + WIN32_FILE_ATTRIBUTE_DATA wfad; + wchar_t *path_wide = NULL; + int32_t err = MZ_INTERNAL_ERROR; + + if (!path) + return MZ_PARAM_ERROR; + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + + if (GetFileAttributesExW(path_wide, GetFileExInfoStandard, &wfad)) { + if (modified_date) + mz_os_file_to_unix_time(wfad.ftLastWriteTime, modified_date); + if (accessed_date) + mz_os_file_to_unix_time(wfad.ftLastAccessTime, accessed_date); + if (creation_date) + mz_os_file_to_unix_time(wfad.ftCreationTime, creation_date); + + err = MZ_OK; + } + + free(path_wide); + + return err; +} + +int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date) { + HANDLE handle = NULL; + FILETIME ftm_creation, ftm_accessed, ftm_modified; + wchar_t *path_wide = NULL; + int32_t err = MZ_OK; + + if (!path) + return MZ_PARAM_ERROR; + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 + handle = CreateFile2(path_wide, GENERIC_READ | GENERIC_WRITE, 0, OPEN_EXISTING, NULL); +#else + handle = CreateFileW(path_wide, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); +#endif + mz_os_unicode_string_delete(&path_wide); + + if (handle != INVALID_HANDLE_VALUE) { + GetFileTime(handle, &ftm_creation, &ftm_accessed, &ftm_modified); + + if (modified_date != 0) + mz_os_unix_to_file_time(modified_date, &ftm_modified); + if (accessed_date != 0) + mz_os_unix_to_file_time(accessed_date, &ftm_accessed); + if (creation_date != 0) + mz_os_unix_to_file_time(creation_date, &ftm_creation); + + if (SetFileTime(handle, &ftm_creation, &ftm_accessed, &ftm_modified) == 0) + err = MZ_INTERNAL_ERROR; + + CloseHandle(handle); + } + + return err; +} + +int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes) { + wchar_t *path_wide = NULL; + int32_t err = MZ_OK; + + if (!path || !attributes) + return MZ_PARAM_ERROR; + + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + + *attributes = GetFileAttributesW(path_wide); + + /* If target is a reparse point, open with default flags to get attributes */ + if (*attributes != INVALID_FILE_ATTRIBUTES && (*attributes & FILE_ATTRIBUTE_REPARSE_POINT)) { + HANDLE handle = INVALID_HANDLE_VALUE; + BY_HANDLE_FILE_INFORMATION info; + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 + CREATEFILE2_EXTENDED_PARAMETERS extended_params; + + memset(&extended_params, 0, sizeof(extended_params)); + extended_params.dwSize = sizeof(extended_params); + extended_params.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS; + + handle = CreateFile2(path_wide, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, OPEN_EXISTING, + &extended_params); +#else + handle = CreateFileW(path_wide, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); +#endif + + if (handle != INVALID_HANDLE_VALUE) { + if (GetFileInformationByHandle(handle, &info)) + *attributes = info.dwFileAttributes; + CloseHandle(handle); + } + } + + mz_os_unicode_string_delete(&path_wide); + + if (*attributes == INVALID_FILE_ATTRIBUTES) + err = MZ_INTERNAL_ERROR; + + return err; +} + +int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes) { + wchar_t *path_wide = NULL; + int32_t err = MZ_OK; + + if (!path) + return MZ_PARAM_ERROR; + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + + if (SetFileAttributesW(path_wide, attributes) == 0) + err = MZ_INTERNAL_ERROR; + mz_os_unicode_string_delete(&path_wide); + + return err; +} + +int32_t mz_os_make_dir(const char *path) { + wchar_t *path_wide = NULL; + int32_t err = MZ_OK; + + if (!path) + return MZ_PARAM_ERROR; + + /* Don't try to create a drive letter */ + if ((path[0] != 0) && (strlen(path) <= 3) && (path[1] == ':')) + return mz_os_is_dir(path); + + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + + if (CreateDirectoryW(path_wide, NULL) == 0) { + if (GetLastError() != ERROR_ALREADY_EXISTS) + err = MZ_INTERNAL_ERROR; + } + + mz_os_unicode_string_delete(&path_wide); + + return err; +} + +DIR *mz_os_open_dir(const char *path) { + WIN32_FIND_DATAW find_data; + DIR_int *dir_int = NULL; + wchar_t *path_wide = NULL; + char fixed_path[320]; + void *handle = NULL; + + if (!path) + return NULL; + + strncpy(fixed_path, path, sizeof(fixed_path) - 1); + fixed_path[sizeof(fixed_path) - 1] = 0; + + mz_path_append_slash(fixed_path, sizeof(fixed_path), MZ_PATH_SLASH_PLATFORM); + mz_path_combine(fixed_path, "*", sizeof(fixed_path)); + + path_wide = mz_os_unicode_string_create(fixed_path, MZ_ENCODING_UTF8); + if (!path_wide) + return NULL; + + handle = FindFirstFileW(path_wide, &find_data); + mz_os_unicode_string_delete(&path_wide); + + if (handle == INVALID_HANDLE_VALUE) + return NULL; + + dir_int = (DIR_int *)malloc(sizeof(DIR_int)); + if (!dir_int) { + FindClose(handle); + return NULL; + } + dir_int->find_handle = handle; + dir_int->end = 0; + + memcpy(&dir_int->find_data, &find_data, sizeof(dir_int->find_data)); + + return (DIR *)dir_int; +} + +struct dirent *mz_os_read_dir(DIR *dir) { + DIR_int *dir_int; + + if (!dir) + return NULL; + + dir_int = (DIR_int *)dir; + if (dir_int->end) + return NULL; + + WideCharToMultiByte(CP_UTF8, 0, dir_int->find_data.cFileName, -1, dir_int->entry.d_name, + sizeof(dir_int->entry.d_name), NULL, NULL); + + if (FindNextFileW(dir_int->find_handle, &dir_int->find_data) == 0) { + if (GetLastError() != ERROR_NO_MORE_FILES) + return NULL; + + dir_int->end = 1; + } + + return &dir_int->entry; +} + +int32_t mz_os_close_dir(DIR *dir) { + DIR_int *dir_int; + + if (!dir) + return MZ_PARAM_ERROR; + + dir_int = (DIR_int *)dir; + if (dir_int->find_handle != INVALID_HANDLE_VALUE) + FindClose(dir_int->find_handle); + free(dir_int); + return MZ_OK; +} + +int32_t mz_os_is_dir_separator(char c) { + return c == '\\' || c == '/'; +} + +int32_t mz_os_is_dir(const char *path) { + wchar_t *path_wide = NULL; + uint32_t attribs = 0; + + if (!path) + return MZ_PARAM_ERROR; + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + + attribs = GetFileAttributesW(path_wide); + mz_os_unicode_string_delete(&path_wide); + + if (attribs != 0xFFFFFFFF) { + if (attribs & FILE_ATTRIBUTE_DIRECTORY) + return MZ_OK; + } + + return MZ_EXIST_ERROR; +} + +int32_t mz_os_is_symlink(const char *path) { + wchar_t *path_wide = NULL; + uint32_t attribs = 0; + + if (!path) + return MZ_PARAM_ERROR; + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + + attribs = GetFileAttributesW(path_wide); + mz_os_unicode_string_delete(&path_wide); + + if (attribs != 0xFFFFFFFF) { + if (attribs & FILE_ATTRIBUTE_REPARSE_POINT) + return MZ_OK; + } + + return MZ_EXIST_ERROR; +} + +int32_t mz_os_get_link_attribs(const char *path, uint32_t *attributes) { + wchar_t *path_wide = NULL; + int32_t err = MZ_OK; + + if (!path || !attributes) + return MZ_PARAM_ERROR; + + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + + *attributes = GetFileAttributesW(path_wide); + mz_os_unicode_string_delete(&path_wide); + + if (*attributes == INVALID_FILE_ATTRIBUTES) + err = MZ_INTERNAL_ERROR; + + return err; +} + +int32_t mz_os_make_symlink(const char *path, const char *target_path) { + typedef BOOLEAN(WINAPI * LPCREATESYMBOLICLINKW)(LPCWSTR, LPCWSTR, DWORD); + MEMORY_BASIC_INFORMATION mbi; + LPCREATESYMBOLICLINKW create_symbolic_link_w = NULL; + HMODULE kernel32_mod = NULL; + wchar_t *path_wide = NULL; + wchar_t *target_path_wide = NULL; + int32_t err = MZ_OK; + int32_t flags = 0; + + if (!path) + return MZ_PARAM_ERROR; + + /* Use VirtualQuery instead of GetModuleHandleW for UWP */ + memset(&mbi, 0, sizeof(mbi)); + VirtualQuery(VirtualQuery, &mbi, sizeof(mbi)); + kernel32_mod = (HMODULE)mbi.AllocationBase; + + if (!kernel32_mod) + return MZ_SUPPORT_ERROR; + + create_symbolic_link_w = (LPCREATESYMBOLICLINKW)GetProcAddress(kernel32_mod, "CreateSymbolicLinkW"); + if (!create_symbolic_link_w) { + return MZ_SUPPORT_ERROR; + } + + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) { + return MZ_PARAM_ERROR; + } + + target_path_wide = mz_os_unicode_string_create(target_path, MZ_ENCODING_UTF8); + if (target_path_wide) { + if (mz_path_has_slash(target_path) == MZ_OK) + flags |= SYMBOLIC_LINK_FLAG_DIRECTORY; + + if (create_symbolic_link_w(path_wide, target_path_wide, flags) == FALSE) + err = MZ_SYMLINK_ERROR; + + mz_os_unicode_string_delete(&target_path_wide); + } else { + err = MZ_PARAM_ERROR; + } + + mz_os_unicode_string_delete(&path_wide); + + return err; +} + +int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path) { + typedef struct _REPARSE_DATA_BUFFER { + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union { + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + }; + } REPARSE_DATA_BUFFER; + REPARSE_DATA_BUFFER *reparse_data = NULL; + DWORD length = 0; + HANDLE handle = NULL; + wchar_t *path_wide = NULL; + wchar_t *target_path_wide = NULL; + uint8_t buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + int32_t target_path_len = 0; + int32_t target_path_idx = 0; + int32_t err = MZ_OK; + char *target_path_utf8 = NULL; + + if (!path) + return MZ_PARAM_ERROR; + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 + CREATEFILE2_EXTENDED_PARAMETERS extended_params; + memset(&extended_params, 0, sizeof(extended_params)); + extended_params.dwSize = sizeof(extended_params); + extended_params.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; + extended_params.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT; + extended_params.dwSecurityQosFlags = SECURITY_ANONYMOUS; + extended_params.lpSecurityAttributes = NULL; + extended_params.hTemplateFile = NULL; + handle = CreateFile2(path_wide, FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, &extended_params); +#else + handle = CreateFileW(path_wide, FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); +#endif + + if (handle == INVALID_HANDLE_VALUE) { + mz_os_unicode_string_delete(&path_wide); + return MZ_OPEN_ERROR; + } + + if (DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, sizeof(buffer), &length, NULL) == TRUE) { + reparse_data = (REPARSE_DATA_BUFFER *)buffer; + if ((IsReparseTagMicrosoft(reparse_data->ReparseTag)) && (reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK)) { + target_path_len = max_target_path * sizeof(wchar_t); + if (target_path_len > reparse_data->SymbolicLinkReparseBuffer.PrintNameLength) + target_path_len = reparse_data->SymbolicLinkReparseBuffer.PrintNameLength; + + target_path_wide = (wchar_t *)malloc(target_path_len + sizeof(wchar_t)); + if (target_path_wide) { + target_path_idx = reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(wchar_t); + memcpy(target_path_wide, &reparse_data->SymbolicLinkReparseBuffer.PathBuffer[target_path_idx], + target_path_len); + + target_path_wide[target_path_len / sizeof(wchar_t)] = 0; + target_path_utf8 = mz_os_utf8_string_create_from_unicode(target_path_wide, MZ_ENCODING_UTF8); + + if (target_path_utf8) { + strncpy(target_path, target_path_utf8, max_target_path - 1); + target_path[max_target_path - 1] = 0; + /* Ensure directories have slash at the end so we can recreate them later */ + if (mz_os_is_dir(target_path_utf8) == MZ_OK) + mz_path_append_slash(target_path, max_target_path, MZ_PATH_SLASH_PLATFORM); + mz_os_utf8_string_delete(&target_path_utf8); + } else { + err = MZ_MEM_ERROR; + } + + free(target_path_wide); + } else { + err = MZ_MEM_ERROR; + } + } + } else { + err = MZ_INTERNAL_ERROR; + } + + CloseHandle(handle); + mz_os_unicode_string_delete(&path_wide); + return err; +} + +int32_t mz_os_get_temp_path(char *path, int32_t max_path, const char *prefix) { + wchar_t *prefix_wide = NULL; + wchar_t tmp_dir_wide[MAX_PATH]; + wchar_t tmp_path_wide[MAX_PATH]; + int32_t path_size = 0; + + if (!path || max_path <= 0) + return MZ_PARAM_ERROR; + + if (GetTempPathW(MAX_PATH, tmp_dir_wide) == 0) + return MZ_INTERNAL_ERROR; + + if (prefix) { + prefix_wide = mz_os_unicode_string_create(prefix, MZ_ENCODING_UTF8); + if (!prefix_wide) + return MZ_MEM_ERROR; + } + + if (GetTempFileNameW(tmp_dir_wide, prefix_wide ? prefix_wide : L"", 0, tmp_path_wide) == 0) { + mz_os_unicode_string_delete(&prefix_wide); + return MZ_INTERNAL_ERROR; + } + + mz_os_unicode_string_delete(&prefix_wide); + + path_size = WideCharToMultiByte(CP_UTF8, 0, tmp_path_wide, -1, path, max_path, NULL, NULL); + if (path_size == 0) + return MZ_INTERNAL_ERROR; + + return MZ_OK; +} + +uint64_t mz_os_ms_time(void) { + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t quad_file_time = 0; + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + + quad_file_time = file_time.dwLowDateTime; + quad_file_time |= ((uint64_t)file_time.dwHighDateTime << 32); + + return quad_file_time / 10000 - 11644473600000LL; +} diff --git a/thirdparty/minizip/mz_strm.c b/thirdparty/minizip/mz_strm.c new file mode 100644 index 000000000..1bacb2edb --- /dev/null +++ b/thirdparty/minizip/mz_strm.c @@ -0,0 +1,545 @@ +/* mz_strm.c -- Stream interface + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_strm.h" + +/***************************************************************************/ + +#define MZ_STREAM_FIND_SIZE (1024) + +/***************************************************************************/ + +int32_t mz_stream_open(void *stream, const char *path, int32_t mode) { + mz_stream *strm = (mz_stream *)stream; + if (!strm || !strm->vtbl || !strm->vtbl->open) + return MZ_STREAM_ERROR; + return strm->vtbl->open(strm, path, mode); +} + +int32_t mz_stream_is_open(void *stream) { + mz_stream *strm = (mz_stream *)stream; + if (!strm || !strm->vtbl || !strm->vtbl->is_open) + return MZ_STREAM_ERROR; + return strm->vtbl->is_open(strm); +} + +int32_t mz_stream_read(void *stream, void *buf, int32_t size) { + mz_stream *strm = (mz_stream *)stream; + if (!strm || !strm->vtbl || !strm->vtbl->read) + return MZ_PARAM_ERROR; + if (mz_stream_is_open(strm) != MZ_OK) + return MZ_STREAM_ERROR; + return strm->vtbl->read(strm, buf, size); +} + +static int32_t mz_stream_read_value(void *stream, uint64_t *value, int32_t len) { + uint8_t buf[8]; + int32_t n = 0; + int32_t i = 0; + + *value = 0; + if (mz_stream_read(stream, buf, len) == len) { + for (n = 0; n < len; n += 1, i += 8) + *value += ((uint64_t)buf[n]) << i; + } else if (mz_stream_error(stream)) + return MZ_STREAM_ERROR; + else + return MZ_END_OF_STREAM; + + return MZ_OK; +} + +int32_t mz_stream_read_uint8(void *stream, uint8_t *value) { + int32_t err = MZ_OK; + uint64_t value64 = 0; + + *value = 0; + err = mz_stream_read_value(stream, &value64, sizeof(uint8_t)); + if (err == MZ_OK) + *value = (uint8_t)value64; + return err; +} + +int32_t mz_stream_read_uint16(void *stream, uint16_t *value) { + int32_t err = MZ_OK; + uint64_t value64 = 0; + + *value = 0; + err = mz_stream_read_value(stream, &value64, sizeof(uint16_t)); + if (err == MZ_OK) + *value = (uint16_t)value64; + return err; +} + +int32_t mz_stream_read_uint32(void *stream, uint32_t *value) { + int32_t err = MZ_OK; + uint64_t value64 = 0; + + *value = 0; + err = mz_stream_read_value(stream, &value64, sizeof(uint32_t)); + if (err == MZ_OK) + *value = (uint32_t)value64; + return err; +} + +int32_t mz_stream_read_int64(void *stream, int64_t *value) { + return mz_stream_read_value(stream, (uint64_t *)value, sizeof(uint64_t)); +} + +int32_t mz_stream_read_uint64(void *stream, uint64_t *value) { + return mz_stream_read_value(stream, value, sizeof(uint64_t)); +} + +int32_t mz_stream_write(void *stream, const void *buf, int32_t size) { + mz_stream *strm = (mz_stream *)stream; + if (size == 0) + return size; + if (!strm || !strm->vtbl || !strm->vtbl->write) + return MZ_PARAM_ERROR; + if (mz_stream_is_open(strm) != MZ_OK) + return MZ_STREAM_ERROR; + return strm->vtbl->write(strm, buf, size); +} + +static int32_t mz_stream_write_value(void *stream, uint64_t value, int32_t len) { + mz_stream *strm = (mz_stream *)stream; + uint8_t buf[8]; + int32_t n = 0; + + if (!strm) + return MZ_PARAM_ERROR; + for (n = 0; n < len; n += 1) { + buf[n] = (uint8_t)(value & 0xff); + value >>= 8; + } + + if (value != 0) { + /* Data overflow - hack for ZIP64 (X Roche) */ + for (n = 0; n < len; n += 1) + buf[n] = 0xff; + } + + if (mz_stream_write(strm, buf, len) != len) + return MZ_STREAM_ERROR; + + return MZ_OK; +} + +int32_t mz_stream_write_uint8(void *stream, uint8_t value) { + return mz_stream_write_value(stream, value, sizeof(uint8_t)); +} + +int32_t mz_stream_write_uint16(void *stream, uint16_t value) { + return mz_stream_write_value(stream, value, sizeof(uint16_t)); +} + +int32_t mz_stream_write_uint32(void *stream, uint32_t value) { + return mz_stream_write_value(stream, value, sizeof(uint32_t)); +} + +int32_t mz_stream_write_int64(void *stream, int64_t value) { + return mz_stream_write_value(stream, (uint64_t)value, sizeof(uint64_t)); +} + +int32_t mz_stream_write_uint64(void *stream, uint64_t value) { + return mz_stream_write_value(stream, value, sizeof(uint64_t)); +} + +int32_t mz_stream_copy(void *target, void *source, int32_t len) { + return mz_stream_copy_stream(target, NULL, source, NULL, len); +} + +int32_t mz_stream_copy_to_end(void *target, void *source) { + return mz_stream_copy_stream_to_end(target, NULL, source, NULL); +} + +int32_t mz_stream_copy_stream(void *target, mz_stream_write_cb write_cb, void *source, mz_stream_read_cb read_cb, + int32_t len) { + uint8_t buf[16384]; + int32_t bytes_to_copy = 0; + int32_t read = 0; + int32_t written = 0; + + if (!write_cb) + write_cb = mz_stream_write; + if (!read_cb) + read_cb = mz_stream_read; + + while (len > 0) { + bytes_to_copy = len; + if (bytes_to_copy > (int32_t)sizeof(buf)) + bytes_to_copy = sizeof(buf); + read = read_cb(source, buf, bytes_to_copy); + if (read <= 0) + return MZ_STREAM_ERROR; + written = write_cb(target, buf, read); + if (written != read) + return MZ_STREAM_ERROR; + len -= read; + } + + return MZ_OK; +} + +int32_t mz_stream_copy_stream_to_end(void *target, mz_stream_write_cb write_cb, void *source, + mz_stream_read_cb read_cb) { + uint8_t buf[16384]; + int32_t read = 0; + int32_t written = 0; + + if (!write_cb) + write_cb = mz_stream_write; + if (!read_cb) + read_cb = mz_stream_read; + + read = read_cb(source, buf, sizeof(buf)); + while (read > 0) { + written = write_cb(target, buf, read); + if (written != read) + return MZ_STREAM_ERROR; + read = read_cb(source, buf, sizeof(buf)); + } + + if (read < 0) + return MZ_STREAM_ERROR; + + return MZ_OK; +} + +int64_t mz_stream_tell(void *stream) { + mz_stream *strm = (mz_stream *)stream; + if (!strm || !strm->vtbl || !strm->vtbl->tell) + return MZ_PARAM_ERROR; + if (mz_stream_is_open(strm) != MZ_OK) + return MZ_STREAM_ERROR; + return strm->vtbl->tell(strm); +} + +int32_t mz_stream_seek(void *stream, int64_t offset, int32_t origin) { + mz_stream *strm = (mz_stream *)stream; + if (!strm || !strm->vtbl || !strm->vtbl->seek) + return MZ_PARAM_ERROR; + if (mz_stream_is_open(strm) != MZ_OK) + return MZ_STREAM_ERROR; + if (origin == MZ_SEEK_SET && offset < 0) + return MZ_SEEK_ERROR; + return strm->vtbl->seek(strm, offset, origin); +} + +int32_t mz_stream_find(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position) { + uint8_t buf[MZ_STREAM_FIND_SIZE]; + int32_t buf_pos = 0; + int32_t read_size = sizeof(buf); + int32_t read = 0; + int64_t read_pos = 0; + int64_t start_pos = 0; + int64_t disk_pos = 0; + int32_t i = 0; + uint8_t first = 1; + int32_t err = MZ_OK; + + if (!stream || !find || !position) + return MZ_PARAM_ERROR; + if (find_size < 0 || find_size >= (int32_t)sizeof(buf)) + return MZ_PARAM_ERROR; + + *position = -1; + + start_pos = mz_stream_tell(stream); + + while (read_pos < max_seek) { + if (read_size > (int32_t)(max_seek - read_pos - buf_pos) && + (max_seek - read_pos - buf_pos) < (int64_t)sizeof(buf)) { + read_size = (int32_t)(max_seek - read_pos - buf_pos); + } + + read = mz_stream_read(stream, buf + buf_pos, read_size); + if ((read <= 0) || (read + buf_pos < find_size)) + break; + + for (i = 0; i <= read + buf_pos - find_size; i += 1) { + if (memcmp(&buf[i], find, find_size) != 0) + continue; + + disk_pos = mz_stream_tell(stream); + + /* Seek to position on disk where the data was found */ + err = mz_stream_seek(stream, disk_pos - ((int64_t)read + buf_pos - i), MZ_SEEK_SET); + if (err != MZ_OK) + return MZ_EXIST_ERROR; + + *position = start_pos + read_pos + i; + return MZ_OK; + } + + if (first) { + read -= find_size; + read_size -= find_size; + buf_pos = find_size; + first = 0; + } + + memmove(buf, buf + read, find_size); + read_pos += read; + } + + return MZ_EXIST_ERROR; +} + +int32_t mz_stream_find_reverse(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position) { + uint8_t buf[MZ_STREAM_FIND_SIZE]; + int32_t buf_pos = 0; + int32_t read_size = MZ_STREAM_FIND_SIZE; + int64_t read_pos = 0; + int32_t read = 0; + int64_t start_pos = 0; + int64_t disk_pos = 0; + uint8_t first = 1; + int32_t i = 0; + int32_t err = MZ_OK; + + if (!stream || !find || !position) + return MZ_PARAM_ERROR; + if (find_size < 0 || find_size >= (int32_t)sizeof(buf)) + return MZ_PARAM_ERROR; + + *position = -1; + + start_pos = mz_stream_tell(stream); + + while (read_pos < max_seek) { + if (read_size > (int32_t)(max_seek - read_pos) && (max_seek - read_pos) < (int64_t)sizeof(buf)) + read_size = (int32_t)(max_seek - read_pos); + + if (mz_stream_seek(stream, start_pos - (read_pos + read_size), MZ_SEEK_SET) != MZ_OK) + break; + read = mz_stream_read(stream, buf, read_size); + if ((read <= 0) || (read + buf_pos < find_size)) + break; + if (read + buf_pos < MZ_STREAM_FIND_SIZE) + memmove(buf + MZ_STREAM_FIND_SIZE - (read + buf_pos), buf, read); + + for (i = find_size; i <= (read + buf_pos); i += 1) { + if (memcmp(&buf[MZ_STREAM_FIND_SIZE - i], find, find_size) != 0) + continue; + + disk_pos = mz_stream_tell(stream); + + /* Seek to position on disk where the data was found */ + err = mz_stream_seek(stream, disk_pos + buf_pos - i, MZ_SEEK_SET); + if (err != MZ_OK) + return MZ_EXIST_ERROR; + + *position = start_pos - (read_pos - buf_pos + i); + return MZ_OK; + } + + if (first) { + read -= find_size; + read_size -= find_size; + buf_pos = find_size; + first = 0; + } + + if (read == 0) + break; + + memmove(buf + read_size, buf, find_size); + read_pos += read; + } + + return MZ_EXIST_ERROR; +} + +int32_t mz_stream_close(void *stream) { + mz_stream *strm = (mz_stream *)stream; + if (!strm || !strm->vtbl || !strm->vtbl->close) + return MZ_PARAM_ERROR; + if (mz_stream_is_open(stream) != MZ_OK) + return MZ_STREAM_ERROR; + return strm->vtbl->close(strm); +} + +int32_t mz_stream_error(void *stream) { + mz_stream *strm = (mz_stream *)stream; + if (!strm || !strm->vtbl || !strm->vtbl->error) + return MZ_PARAM_ERROR; + return strm->vtbl->error(strm); +} + +int32_t mz_stream_set_base(void *stream, void *base) { + mz_stream *strm = (mz_stream *)stream; + strm->base = (mz_stream *)base; + return MZ_OK; +} + +void *mz_stream_get_interface(void *stream) { + mz_stream *strm = (mz_stream *)stream; + if (!strm || !strm->vtbl) + return NULL; + return (void *)strm->vtbl; +} + +int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value) { + mz_stream *strm = (mz_stream *)stream; + if (!strm || !strm->vtbl || !strm->vtbl->get_prop_int64) + return MZ_PARAM_ERROR; + return strm->vtbl->get_prop_int64(strm, prop, value); +} + +int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value) { + mz_stream *strm = (mz_stream *)stream; + if (!strm || !strm->vtbl || !strm->vtbl->set_prop_int64) + return MZ_PARAM_ERROR; + return strm->vtbl->set_prop_int64(strm, prop, value); +} + +void *mz_stream_create(mz_stream_vtbl *vtbl) { + if (!vtbl || !vtbl->create) + return NULL; + return vtbl->create(); +} + +void mz_stream_delete(void **stream) { + mz_stream *strm = NULL; + if (!stream) + return; + strm = (mz_stream *)*stream; + if (strm && strm->vtbl && strm->vtbl->destroy) + strm->vtbl->destroy(stream); + *stream = NULL; +} + +/***************************************************************************/ + +typedef struct mz_stream_raw_s { + mz_stream stream; + int64_t total_in; + int64_t total_out; + int64_t max_total_in; +} mz_stream_raw; + +/***************************************************************************/ + +int32_t mz_stream_raw_open(void *stream, const char *path, int32_t mode) { + MZ_UNUSED(stream); + MZ_UNUSED(path); + MZ_UNUSED(mode); + + return MZ_OK; +} + +int32_t mz_stream_raw_is_open(void *stream) { + mz_stream_raw *raw = (mz_stream_raw *)stream; + return mz_stream_is_open(raw->stream.base); +} + +int32_t mz_stream_raw_read(void *stream, void *buf, int32_t size) { + mz_stream_raw *raw = (mz_stream_raw *)stream; + int32_t bytes_to_read = size; + int32_t read = 0; + + if (raw->max_total_in > 0) { + if ((int64_t)bytes_to_read > (raw->max_total_in - raw->total_in)) + bytes_to_read = (int32_t)(raw->max_total_in - raw->total_in); + } + + read = mz_stream_read(raw->stream.base, buf, bytes_to_read); + + if (read > 0) { + raw->total_in += read; + raw->total_out += read; + } + + return read; +} + +int32_t mz_stream_raw_write(void *stream, const void *buf, int32_t size) { + mz_stream_raw *raw = (mz_stream_raw *)stream; + int32_t written = 0; + + written = mz_stream_write(raw->stream.base, buf, size); + + if (written > 0) { + raw->total_out += written; + raw->total_in += written; + } + + return written; +} + +int64_t mz_stream_raw_tell(void *stream) { + mz_stream_raw *raw = (mz_stream_raw *)stream; + return mz_stream_tell(raw->stream.base); +} + +int32_t mz_stream_raw_seek(void *stream, int64_t offset, int32_t origin) { + mz_stream_raw *raw = (mz_stream_raw *)stream; + return mz_stream_seek(raw->stream.base, offset, origin); +} + +int32_t mz_stream_raw_close(void *stream) { + MZ_UNUSED(stream); + return MZ_OK; +} + +int32_t mz_stream_raw_error(void *stream) { + mz_stream_raw *raw = (mz_stream_raw *)stream; + return mz_stream_error(raw->stream.base); +} + +int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value) { + mz_stream_raw *raw = (mz_stream_raw *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN: + *value = raw->total_in; + return MZ_OK; + case MZ_STREAM_PROP_TOTAL_OUT: + *value = raw->total_out; + return MZ_OK; + } + return MZ_EXIST_ERROR; +} + +int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value) { + mz_stream_raw *raw = (mz_stream_raw *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN_MAX: + raw->max_total_in = value; + return MZ_OK; + } + return MZ_EXIST_ERROR; +} + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_raw_vtbl = { + mz_stream_raw_open, mz_stream_raw_is_open, mz_stream_raw_read, mz_stream_raw_write, + mz_stream_raw_tell, mz_stream_raw_seek, mz_stream_raw_close, mz_stream_raw_error, + mz_stream_raw_create, mz_stream_raw_delete, mz_stream_raw_get_prop_int64, mz_stream_raw_set_prop_int64}; + +/***************************************************************************/ + +void *mz_stream_raw_create(void) { + mz_stream_raw *raw = (mz_stream_raw *)calloc(1, sizeof(mz_stream_raw)); + if (raw) + raw->stream.vtbl = &mz_stream_raw_vtbl; + return raw; +} + +void mz_stream_raw_delete(void **stream) { + mz_stream_raw *raw = NULL; + if (!stream) + return; + raw = (mz_stream_raw *)*stream; + free(raw); + *stream = NULL; +} diff --git a/thirdparty/minizip/mz_strm.h b/thirdparty/minizip/mz_strm.h new file mode 100644 index 000000000..fcbdda4a9 --- /dev/null +++ b/thirdparty/minizip/mz_strm.h @@ -0,0 +1,135 @@ +/* mz_strm.h -- Stream interface + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_H +#define MZ_STREAM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +#define MZ_STREAM_PROP_TOTAL_IN (1) +#define MZ_STREAM_PROP_TOTAL_IN_MAX (2) +#define MZ_STREAM_PROP_TOTAL_OUT (3) +#define MZ_STREAM_PROP_TOTAL_OUT_MAX (4) +#define MZ_STREAM_PROP_HEADER_SIZE (5) +#define MZ_STREAM_PROP_FOOTER_SIZE (6) +#define MZ_STREAM_PROP_DISK_SIZE (7) +#define MZ_STREAM_PROP_DISK_NUMBER (8) +#define MZ_STREAM_PROP_COMPRESS_LEVEL (9) +#define MZ_STREAM_PROP_COMPRESS_METHOD (10) +#define MZ_STREAM_PROP_COMPRESS_WINDOW (11) +#define MZ_STREAM_PROP_COMPRESS_THREADS (12) + +/***************************************************************************/ + +typedef int32_t (*mz_stream_open_cb)(void *stream, const char *path, int32_t mode); +typedef int32_t (*mz_stream_is_open_cb)(void *stream); +typedef int32_t (*mz_stream_read_cb)(void *stream, void *buf, int32_t size); +typedef int32_t (*mz_stream_write_cb)(void *stream, const void *buf, int32_t size); +typedef int64_t (*mz_stream_tell_cb)(void *stream); +typedef int32_t (*mz_stream_seek_cb)(void *stream, int64_t offset, int32_t origin); +typedef int32_t (*mz_stream_close_cb)(void *stream); +typedef int32_t (*mz_stream_error_cb)(void *stream); +typedef void *(*mz_stream_create_cb)(void); +typedef void (*mz_stream_destroy_cb)(void **stream); + +typedef int32_t (*mz_stream_get_prop_int64_cb)(void *stream, int32_t prop, int64_t *value); +typedef int32_t (*mz_stream_set_prop_int64_cb)(void *stream, int32_t prop, int64_t value); + +typedef int32_t (*mz_stream_find_cb)(void *stream, const void *find, int32_t find_size, int64_t max_seek, + int64_t *position); + +/***************************************************************************/ + +typedef struct mz_stream_vtbl_s { + mz_stream_open_cb open; + mz_stream_is_open_cb is_open; + mz_stream_read_cb read; + mz_stream_write_cb write; + mz_stream_tell_cb tell; + mz_stream_seek_cb seek; + mz_stream_close_cb close; + mz_stream_error_cb error; + mz_stream_create_cb create; + mz_stream_destroy_cb destroy; + + mz_stream_get_prop_int64_cb get_prop_int64; + mz_stream_set_prop_int64_cb set_prop_int64; +} mz_stream_vtbl; + +typedef struct mz_stream_s { + mz_stream_vtbl *vtbl; + struct mz_stream_s *base; +} mz_stream; + +/***************************************************************************/ + +int32_t mz_stream_open(void *stream, const char *path, int32_t mode); +int32_t mz_stream_is_open(void *stream); +int32_t mz_stream_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_read_uint8(void *stream, uint8_t *value); +int32_t mz_stream_read_uint16(void *stream, uint16_t *value); +int32_t mz_stream_read_uint32(void *stream, uint32_t *value); +int32_t mz_stream_read_int64(void *stream, int64_t *value); +int32_t mz_stream_read_uint64(void *stream, uint64_t *value); +int32_t mz_stream_write(void *stream, const void *buf, int32_t size); +int32_t mz_stream_write_uint8(void *stream, uint8_t value); +int32_t mz_stream_write_uint16(void *stream, uint16_t value); +int32_t mz_stream_write_uint32(void *stream, uint32_t value); +int32_t mz_stream_write_int64(void *stream, int64_t value); +int32_t mz_stream_write_uint64(void *stream, uint64_t value); +int32_t mz_stream_copy(void *target, void *source, int32_t len); +int32_t mz_stream_copy_to_end(void *target, void *source); +int32_t mz_stream_copy_stream(void *target, mz_stream_write_cb write_cb, void *source, mz_stream_read_cb read_cb, + int32_t len); +int32_t mz_stream_copy_stream_to_end(void *target, mz_stream_write_cb write_cb, void *source, + mz_stream_read_cb read_cb); +int64_t mz_stream_tell(void *stream); +int32_t mz_stream_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_find(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position); +int32_t mz_stream_find_reverse(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position); +int32_t mz_stream_close(void *stream); +int32_t mz_stream_error(void *stream); + +int32_t mz_stream_set_base(void *stream, void *base); +void *mz_stream_get_interface(void *stream); +int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value); +int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value); + +void *mz_stream_create(mz_stream_vtbl *vtbl); +void mz_stream_delete(void **stream); + +/***************************************************************************/ + +int32_t mz_stream_raw_open(void *stream, const char *filename, int32_t mode); +int32_t mz_stream_raw_is_open(void *stream); +int32_t mz_stream_raw_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_raw_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_raw_tell(void *stream); +int32_t mz_stream_raw_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_raw_close(void *stream); +int32_t mz_stream_raw_error(void *stream); + +int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value); +int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value); + +void *mz_stream_raw_create(void); +void mz_stream_raw_delete(void **stream); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_buf.c b/thirdparty/minizip/mz_strm_buf.c new file mode 100644 index 000000000..2ca819706 --- /dev/null +++ b/thirdparty/minizip/mz_strm_buf.c @@ -0,0 +1,381 @@ +/* mz_strm_buf.c -- Stream for buffering reads/writes + part of the minizip-ng project + + This version of ioapi is designed to buffer IO. + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_strm.h" +#include "mz_strm_buf.h" + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_buffered_vtbl = {mz_stream_buffered_open, + mz_stream_buffered_is_open, + mz_stream_buffered_read, + mz_stream_buffered_write, + mz_stream_buffered_tell, + mz_stream_buffered_seek, + mz_stream_buffered_close, + mz_stream_buffered_error, + mz_stream_buffered_create, + mz_stream_buffered_delete, + NULL, + NULL}; + +/***************************************************************************/ + +typedef struct mz_stream_buffered_s { + mz_stream stream; + int32_t error; + char readbuf[INT16_MAX]; + int32_t readbuf_len; + int32_t readbuf_pos; + int32_t readbuf_hits; + int32_t readbuf_misses; + char writebuf[INT16_MAX]; + int32_t writebuf_len; + int32_t writebuf_pos; + int32_t writebuf_hits; + int32_t writebuf_misses; + int64_t position; +} mz_stream_buffered; + +/***************************************************************************/ + +#if 0 +# define mz_stream_buffered_print printf +#else +# define mz_stream_buffered_print(fmt, ...) +#endif + +/***************************************************************************/ + +static int32_t mz_stream_buffered_reset(void *stream) { + mz_stream_buffered *buffered = (mz_stream_buffered *)stream; + + buffered->readbuf_len = 0; + buffered->readbuf_pos = 0; + buffered->writebuf_len = 0; + buffered->writebuf_pos = 0; + buffered->position = 0; + + return MZ_OK; +} + +int32_t mz_stream_buffered_open(void *stream, const char *path, int32_t mode) { + mz_stream_buffered *buffered = (mz_stream_buffered *)stream; + mz_stream_buffered_print("Buffered - Open (mode %" PRId32 ")\n", mode); + mz_stream_buffered_reset(buffered); + return mz_stream_open(buffered->stream.base, path, mode); +} + +int32_t mz_stream_buffered_is_open(void *stream) { + mz_stream_buffered *buffered = (mz_stream_buffered *)stream; + return mz_stream_is_open(buffered->stream.base); +} + +static int32_t mz_stream_buffered_flush(void *stream, int32_t *written) { + mz_stream_buffered *buffered = (mz_stream_buffered *)stream; + int32_t total_bytes_written = 0; + int32_t bytes_to_write = buffered->writebuf_len; + int32_t bytes_left_to_write = buffered->writebuf_len; + int32_t bytes_written = 0; + + *written = 0; + + while (bytes_left_to_write > 0) { + bytes_written = mz_stream_write( + buffered->stream.base, buffered->writebuf + (bytes_to_write - bytes_left_to_write), bytes_left_to_write); + + if (bytes_written != bytes_left_to_write) + return MZ_WRITE_ERROR; + + buffered->writebuf_misses += 1; + + mz_stream_buffered_print("Buffered - Write flush (%" PRId32 ":%" PRId32 " len %" PRId32 ")\n", bytes_to_write, + bytes_left_to_write, buffered->writebuf_len); + + total_bytes_written += bytes_written; + bytes_left_to_write -= bytes_written; + buffered->position += bytes_written; + } + + buffered->writebuf_len = 0; + buffered->writebuf_pos = 0; + + *written = total_bytes_written; + return MZ_OK; +} + +int32_t mz_stream_buffered_read(void *stream, void *buf, int32_t size) { + mz_stream_buffered *buffered = (mz_stream_buffered *)stream; + int32_t buf_len = 0; + int32_t bytes_to_read = 0; + int32_t bytes_to_copy = 0; + int32_t bytes_left_to_read = size; + int32_t bytes_read = 0; + int32_t bytes_flushed = 0; + + mz_stream_buffered_print("Buffered - Read (size %" PRId32 " pos %" PRId64 ")\n", size, buffered->position); + + if (buffered->writebuf_len > 0) { + int64_t position = buffered->position + buffered->writebuf_pos; + + mz_stream_buffered_print("Buffered - Switch from write to read, flushing (pos %" PRId64 ")\n", position); + + mz_stream_buffered_flush(stream, &bytes_flushed); + mz_stream_buffered_seek(stream, position, MZ_SEEK_SET); + } + + while (bytes_left_to_read > 0) { + if ((buffered->readbuf_len == 0) || (buffered->readbuf_pos == buffered->readbuf_len)) { + if (buffered->readbuf_len == sizeof(buffered->readbuf)) { + buffered->readbuf_pos = 0; + buffered->readbuf_len = 0; + } + + bytes_to_read = (int32_t)sizeof(buffered->readbuf) - (buffered->readbuf_len - buffered->readbuf_pos); + bytes_read = + mz_stream_read(buffered->stream.base, buffered->readbuf + buffered->readbuf_pos, bytes_to_read); + if (bytes_read < 0) + return bytes_read; + + buffered->readbuf_misses += 1; + buffered->readbuf_len += bytes_read; + buffered->position += bytes_read; + + mz_stream_buffered_print( + "Buffered - Filled (read %" PRId32 "/%" PRId32 " buf %" PRId32 ":%" PRId32 " pos %" PRId64 ")\n", + bytes_read, bytes_to_read, buffered->readbuf_pos, buffered->readbuf_len, buffered->position); + + if (bytes_read == 0) + break; + } + + if ((buffered->readbuf_len - buffered->readbuf_pos) > 0) { + bytes_to_copy = buffered->readbuf_len - buffered->readbuf_pos; + if (bytes_to_copy > bytes_left_to_read) + bytes_to_copy = bytes_left_to_read; + + memcpy((char *)buf + buf_len, buffered->readbuf + buffered->readbuf_pos, bytes_to_copy); + + buf_len += bytes_to_copy; + bytes_left_to_read -= bytes_to_copy; + + buffered->readbuf_hits += 1; + buffered->readbuf_pos += bytes_to_copy; + + mz_stream_buffered_print("Buffered - Emptied (copied %" PRId32 " remaining %" PRId32 " buf %" PRId32 + ":%" PRId32 " pos %" PRId64 ")\n", + bytes_to_copy, bytes_left_to_read, buffered->readbuf_pos, buffered->readbuf_len, + buffered->position); + } + } + + return size - bytes_left_to_read; +} + +int32_t mz_stream_buffered_write(void *stream, const void *buf, int32_t size) { + mz_stream_buffered *buffered = (mz_stream_buffered *)stream; + int32_t bytes_to_write = size; + int32_t bytes_left_to_write = size; + int32_t bytes_to_copy = 0; + int32_t bytes_used = 0; + int32_t bytes_flushed = 0; + int32_t err = MZ_OK; + + mz_stream_buffered_print("Buffered - Write (size %" PRId32 " len %" PRId32 " pos %" PRId64 ")\n", size, + buffered->writebuf_len, buffered->position); + + if (buffered->readbuf_len > 0) { + buffered->position -= buffered->readbuf_len; + buffered->position += buffered->readbuf_pos; + + buffered->readbuf_len = 0; + buffered->readbuf_pos = 0; + + mz_stream_buffered_print("Buffered - Switch from read to write (pos %" PRId64 ")\n", buffered->position); + + err = mz_stream_seek(buffered->stream.base, buffered->position, MZ_SEEK_SET); + if (err != MZ_OK) + return err; + } + + while (bytes_left_to_write > 0) { + bytes_used = buffered->writebuf_len; + if (bytes_used > buffered->writebuf_pos) + bytes_used = buffered->writebuf_pos; + bytes_to_copy = (int32_t)sizeof(buffered->writebuf) - bytes_used; + if (bytes_to_copy > bytes_left_to_write) + bytes_to_copy = bytes_left_to_write; + + if (bytes_to_copy == 0) { + err = mz_stream_buffered_flush(stream, &bytes_flushed); + if (err != MZ_OK) + return err; + if (bytes_flushed == 0) + return 0; + + continue; + } + + memcpy(buffered->writebuf + buffered->writebuf_pos, (const char *)buf + (bytes_to_write - bytes_left_to_write), + bytes_to_copy); + + mz_stream_buffered_print("Buffered - Write copy (remaining %" PRId32 " write %" PRId32 ":%" PRId32 + " len %" PRId32 ")\n", + bytes_to_copy, bytes_to_write, bytes_left_to_write, buffered->writebuf_len); + + bytes_left_to_write -= bytes_to_copy; + + buffered->writebuf_pos += bytes_to_copy; + buffered->writebuf_hits += 1; + if (buffered->writebuf_pos > buffered->writebuf_len) + buffered->writebuf_len += buffered->writebuf_pos - buffered->writebuf_len; + } + + return size - bytes_left_to_write; +} + +int64_t mz_stream_buffered_tell(void *stream) { + mz_stream_buffered *buffered = (mz_stream_buffered *)stream; + int64_t position = mz_stream_tell(buffered->stream.base); + + buffered->position = position; + + mz_stream_buffered_print("Buffered - Tell (pos %" PRId64 " readpos %" PRId32 " writepos %" PRId32 ")\n", + buffered->position, buffered->readbuf_pos, buffered->writebuf_pos); + + if (buffered->readbuf_len > 0) + position -= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos); + if (buffered->writebuf_len > 0) + position += buffered->writebuf_pos; + return position; +} + +int32_t mz_stream_buffered_seek(void *stream, int64_t offset, int32_t origin) { + mz_stream_buffered *buffered = (mz_stream_buffered *)stream; + int32_t bytes_flushed = 0; + int32_t err = MZ_OK; + + mz_stream_buffered_print("Buffered - Seek (origin %" PRId32 " offset %" PRId64 " pos %" PRId64 ")\n", origin, + offset, buffered->position); + + switch (origin) { + case MZ_SEEK_SET: + + if ((buffered->readbuf_len > 0) && (offset < buffered->position) && + (offset >= buffered->position - buffered->readbuf_len)) { + buffered->readbuf_pos = (int32_t)(offset - (buffered->position - buffered->readbuf_len)); + return MZ_OK; + } + if (buffered->writebuf_len > 0) { + if ((offset >= buffered->position) && (offset <= buffered->position + buffered->writebuf_len)) { + buffered->writebuf_pos = (int32_t)(offset - buffered->position); + return MZ_OK; + } + } + + err = mz_stream_buffered_flush(stream, &bytes_flushed); + if (err != MZ_OK) + return err; + + buffered->position = offset; + break; + + case MZ_SEEK_CUR: + + if (buffered->readbuf_len > 0) { + if (offset <= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos)) { + buffered->readbuf_pos += (uint32_t)offset; + return MZ_OK; + } + offset -= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos); + buffered->position += offset; + } + if (buffered->writebuf_len > 0) { + if (offset <= ((int64_t)buffered->writebuf_len - buffered->writebuf_pos)) { + buffered->writebuf_pos += (uint32_t)offset; + return MZ_OK; + } + /* offset -= (buffered->writebuf_len - buffered->writebuf_pos); */ + } + + err = mz_stream_buffered_flush(stream, &bytes_flushed); + if (err != MZ_OK) + return err; + + break; + + case MZ_SEEK_END: + + if (buffered->writebuf_len > 0) { + buffered->writebuf_pos = buffered->writebuf_len; + return MZ_OK; + } + break; + } + + buffered->readbuf_len = 0; + buffered->readbuf_pos = 0; + buffered->writebuf_len = 0; + buffered->writebuf_pos = 0; + + return mz_stream_seek(buffered->stream.base, offset, origin); +} + +int32_t mz_stream_buffered_close(void *stream) { + mz_stream_buffered *buffered = (mz_stream_buffered *)stream; + int32_t bytes_flushed = 0; + + mz_stream_buffered_flush(stream, &bytes_flushed); + mz_stream_buffered_print("Buffered - Close (flushed %" PRId32 ")\n", bytes_flushed); + + if (buffered->readbuf_hits + buffered->readbuf_misses > 0) { + mz_stream_buffered_print( + "Buffered - Read efficiency %.02f%%\n", + (buffered->readbuf_hits / ((float)buffered->readbuf_hits + buffered->readbuf_misses)) * 100); + } + + if (buffered->writebuf_hits + buffered->writebuf_misses > 0) { + mz_stream_buffered_print( + "Buffered - Write efficiency %.02f%%\n", + (buffered->writebuf_hits / ((float)buffered->writebuf_hits + buffered->writebuf_misses)) * 100); + } + + mz_stream_buffered_reset(buffered); + + return mz_stream_close(buffered->stream.base); +} + +int32_t mz_stream_buffered_error(void *stream) { + mz_stream_buffered *buffered = (mz_stream_buffered *)stream; + return mz_stream_error(buffered->stream.base); +} + +void *mz_stream_buffered_create(void) { + mz_stream_buffered *buffered = (mz_stream_buffered *)calloc(1, sizeof(mz_stream_buffered)); + if (buffered) + buffered->stream.vtbl = &mz_stream_buffered_vtbl; + return buffered; +} + +void mz_stream_buffered_delete(void **stream) { + mz_stream_buffered *buffered = NULL; + if (!stream) + return; + buffered = (mz_stream_buffered *)*stream; + free(buffered); + *stream = NULL; +} + +void *mz_stream_buffered_get_interface(void) { + return (void *)&mz_stream_buffered_vtbl; +} diff --git a/thirdparty/minizip/mz_strm_buf.h b/thirdparty/minizip/mz_strm_buf.h new file mode 100644 index 000000000..61b382f37 --- /dev/null +++ b/thirdparty/minizip/mz_strm_buf.h @@ -0,0 +1,42 @@ +/* mz_strm_buf.h -- Stream for buffering reads/writes + part of the minizip-ng project + + This version of ioapi is designed to buffer IO. + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_BUFFERED_H +#define MZ_STREAM_BUFFERED_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_buffered_open(void *stream, const char *path, int32_t mode); +int32_t mz_stream_buffered_is_open(void *stream); +int32_t mz_stream_buffered_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_buffered_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_buffered_tell(void *stream); +int32_t mz_stream_buffered_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_buffered_close(void *stream); +int32_t mz_stream_buffered_error(void *stream); + +void *mz_stream_buffered_create(void); +void mz_stream_buffered_delete(void **stream); + +void *mz_stream_buffered_get_interface(void); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_bzip.c b/thirdparty/minizip/mz_strm_bzip.c new file mode 100644 index 000000000..d6d70a6fd --- /dev/null +++ b/thirdparty/minizip/mz_strm_bzip.c @@ -0,0 +1,349 @@ +/* mz_strm_bzip.c -- Stream for bzip inflate/deflate + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_strm.h" +#include "mz_strm_bzip.h" + +#include "bzlib.h" + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_bzip_vtbl = { + mz_stream_bzip_open, mz_stream_bzip_is_open, mz_stream_bzip_read, mz_stream_bzip_write, + mz_stream_bzip_tell, mz_stream_bzip_seek, mz_stream_bzip_close, mz_stream_bzip_error, + mz_stream_bzip_create, mz_stream_bzip_delete, mz_stream_bzip_get_prop_int64, mz_stream_bzip_set_prop_int64}; + +/***************************************************************************/ + +typedef struct mz_stream_bzip_s { + mz_stream stream; + bz_stream bzstream; + int32_t mode; + int32_t error; + uint8_t buffer[INT16_MAX]; + int8_t initialized; + int32_t buffer_len; + int16_t stream_end; + int16_t level; + int64_t total_in; + int64_t total_out; + int64_t max_total_in; +} mz_stream_bzip; + +/***************************************************************************/ + +int32_t mz_stream_bzip_open(void *stream, const char *path, int32_t mode) { + mz_stream_bzip *bzip = (mz_stream_bzip *)stream; + + MZ_UNUSED(path); + + bzip->bzstream.bzalloc = 0; + bzip->bzstream.bzfree = 0; + bzip->bzstream.opaque = 0; + bzip->bzstream.total_in_lo32 = 0; + bzip->bzstream.total_in_hi32 = 0; + bzip->bzstream.total_out_lo32 = 0; + bzip->bzstream.total_out_hi32 = 0; + + bzip->total_in = 0; + bzip->total_out = 0; + + if (mode & MZ_OPEN_MODE_WRITE) { +#ifdef MZ_ZIP_NO_COMPRESSION + return MZ_SUPPORT_ERROR; +#else + bzip->bzstream.next_out = (char *)bzip->buffer; + bzip->bzstream.avail_out = sizeof(bzip->buffer); + + bzip->error = BZ2_bzCompressInit(&bzip->bzstream, bzip->level, 0, 0); +#endif + } else if (mode & MZ_OPEN_MODE_READ) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + return MZ_SUPPORT_ERROR; +#else + bzip->bzstream.next_in = (char *)bzip->buffer; + bzip->bzstream.avail_in = 0; + + bzip->error = BZ2_bzDecompressInit(&bzip->bzstream, 0, 0); +#endif + } + + if (bzip->error != BZ_OK) + return MZ_OPEN_ERROR; + + bzip->initialized = 1; + bzip->stream_end = 0; + bzip->mode = mode; + return MZ_OK; +} + +int32_t mz_stream_bzip_is_open(void *stream) { + mz_stream_bzip *bzip = (mz_stream_bzip *)stream; + if (bzip->initialized != 1) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +int32_t mz_stream_bzip_read(void *stream, void *buf, int32_t size) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + MZ_UNUSED(stream); + MZ_UNUSED(buf); + MZ_UNUSED(size); + return MZ_SUPPORT_ERROR; +#else + mz_stream_bzip *bzip = (mz_stream_bzip *)stream; + uint64_t total_in_before = 0; + uint64_t total_out_before = 0; + uint64_t total_in_after = 0; + uint64_t total_out_after = 0; + int32_t total_out = 0; + int32_t in_bytes = 0; + int32_t out_bytes = 0; + int32_t bytes_to_read = sizeof(bzip->buffer); + int32_t read = 0; + int32_t err = BZ_OK; + + if (bzip->stream_end) + return 0; + + bzip->bzstream.next_out = (char *)buf; + bzip->bzstream.avail_out = (unsigned int)size; + + do { + if (bzip->bzstream.avail_in == 0) { + if (bzip->max_total_in > 0) { + if ((int64_t)bytes_to_read > (bzip->max_total_in - bzip->total_in)) + bytes_to_read = (int32_t)(bzip->max_total_in - bzip->total_in); + } + + read = mz_stream_read(bzip->stream.base, bzip->buffer, bytes_to_read); + + if (read < 0) + return read; + + bzip->bzstream.next_in = (char *)bzip->buffer; + bzip->bzstream.avail_in = (uint32_t)read; + } + + total_in_before = bzip->bzstream.avail_in; + total_out_before = bzip->bzstream.total_out_lo32 + (((uint64_t)bzip->bzstream.total_out_hi32) << 32); + + err = BZ2_bzDecompress(&bzip->bzstream); + + total_in_after = bzip->bzstream.avail_in; + total_out_after = bzip->bzstream.total_out_lo32 + (((uint64_t)bzip->bzstream.total_out_hi32) << 32); + + in_bytes = (int32_t)(total_in_before - total_in_after); + out_bytes = (int32_t)(total_out_after - total_out_before); + + total_out += out_bytes; + + bzip->total_in += in_bytes; + bzip->total_out += out_bytes; + + if (err == BZ_STREAM_END) { + bzip->stream_end = 1; + break; + } + if (err != BZ_OK && err != BZ_RUN_OK) { + bzip->error = err; + break; + } + } while (bzip->bzstream.avail_out > 0); + + if (bzip->error != 0) + return MZ_DATA_ERROR; + + return total_out; +#endif +} + +#ifndef MZ_ZIP_NO_COMPRESSION +static int32_t mz_stream_bzip_flush(void *stream) { + mz_stream_bzip *bzip = (mz_stream_bzip *)stream; + if (mz_stream_write(bzip->stream.base, bzip->buffer, bzip->buffer_len) != bzip->buffer_len) + return MZ_WRITE_ERROR; + return MZ_OK; +} + +static int32_t mz_stream_bzip_compress(void *stream, int flush) { + mz_stream_bzip *bzip = (mz_stream_bzip *)stream; + uint64_t total_out_before = 0; + uint64_t total_out_after = 0; + uint32_t out_bytes = 0; + int32_t err = BZ_OK; + + do { + if (bzip->bzstream.avail_out == 0) { + err = mz_stream_bzip_flush(bzip); + if (err != MZ_OK) + return err; + + bzip->bzstream.avail_out = sizeof(bzip->buffer); + bzip->bzstream.next_out = (char *)bzip->buffer; + + bzip->buffer_len = 0; + } + + total_out_before = bzip->bzstream.total_out_lo32 + (((uint64_t)bzip->bzstream.total_out_hi32) << 32); + + err = BZ2_bzCompress(&bzip->bzstream, flush); + + total_out_after = bzip->bzstream.total_out_lo32 + (((uint64_t)bzip->bzstream.total_out_hi32) << 32); + + out_bytes = (uint32_t)(total_out_after - total_out_before); + + bzip->buffer_len += out_bytes; + bzip->total_out += out_bytes; + + if (err == BZ_STREAM_END) + break; + if (err < 0) { + bzip->error = err; + return MZ_DATA_ERROR; + } + } while ((bzip->bzstream.avail_in > 0) || (flush == BZ_FINISH && err == BZ_FINISH_OK)); + + return MZ_OK; +} +#endif + +int32_t mz_stream_bzip_write(void *stream, const void *buf, int32_t size) { +#ifdef MZ_ZIP_NO_COMPRESSION + MZ_UNUSED(stream); + MZ_UNUSED(buf); + MZ_UNUSED(size); + return MZ_SUPPORT_ERROR; +#else + mz_stream_bzip *bzip = (mz_stream_bzip *)stream; + int32_t err = MZ_OK; + + bzip->bzstream.next_in = (char *)(intptr_t)buf; + bzip->bzstream.avail_in = (unsigned int)size; + + err = mz_stream_bzip_compress(stream, BZ_RUN); + if (err != MZ_OK) { + return err; + } + + bzip->total_in += size; + return size; +#endif +} + +int64_t mz_stream_bzip_tell(void *stream) { + MZ_UNUSED(stream); + + return MZ_TELL_ERROR; +} + +int32_t mz_stream_bzip_seek(void *stream, int64_t offset, int32_t origin) { + MZ_UNUSED(stream); + MZ_UNUSED(offset); + MZ_UNUSED(origin); + + return MZ_SEEK_ERROR; +} + +int32_t mz_stream_bzip_close(void *stream) { + mz_stream_bzip *bzip = (mz_stream_bzip *)stream; + + if (bzip->mode & MZ_OPEN_MODE_WRITE) { +#ifdef MZ_ZIP_NO_COMPRESSION + return MZ_SUPPORT_ERROR; +#else + mz_stream_bzip_compress(stream, BZ_FINISH); + mz_stream_bzip_flush(stream); + + BZ2_bzCompressEnd(&bzip->bzstream); +#endif + } else if (bzip->mode & MZ_OPEN_MODE_READ) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + return MZ_SUPPORT_ERROR; +#else + BZ2_bzDecompressEnd(&bzip->bzstream); +#endif + } + + bzip->initialized = 0; + + if (bzip->error != BZ_OK) + return MZ_CLOSE_ERROR; + return MZ_OK; +} + +int32_t mz_stream_bzip_error(void *stream) { + mz_stream_bzip *bzip = (mz_stream_bzip *)stream; + return bzip->error; +} + +int32_t mz_stream_bzip_get_prop_int64(void *stream, int32_t prop, int64_t *value) { + mz_stream_bzip *bzip = (mz_stream_bzip *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN: + *value = bzip->total_in; + break; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + *value = bzip->max_total_in; + break; + case MZ_STREAM_PROP_TOTAL_OUT: + *value = bzip->total_out; + break; + case MZ_STREAM_PROP_HEADER_SIZE: + *value = 0; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +int32_t mz_stream_bzip_set_prop_int64(void *stream, int32_t prop, int64_t value) { + mz_stream_bzip *bzip = (mz_stream_bzip *)stream; + switch (prop) { + case MZ_STREAM_PROP_COMPRESS_LEVEL: + if (value == MZ_COMPRESS_LEVEL_DEFAULT) + bzip->level = 6; + else + bzip->level = (int16_t)value; + return MZ_OK; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + bzip->max_total_in = value; + return MZ_OK; + } + return MZ_EXIST_ERROR; +} + +void *mz_stream_bzip_create(void) { + mz_stream_bzip *bzip = (mz_stream_bzip *)calloc(1, sizeof(mz_stream_bzip)); + if (bzip) { + bzip->stream.vtbl = &mz_stream_bzip_vtbl; + bzip->level = 6; + } + return bzip; +} + +void mz_stream_bzip_delete(void **stream) { + mz_stream_bzip *bzip = NULL; + if (!stream) + return; + bzip = (mz_stream_bzip *)*stream; + free(bzip); + *stream = NULL; +} + +void *mz_stream_bzip_get_interface(void) { + return (void *)&mz_stream_bzip_vtbl; +} + +extern void bz_internal_error(int errcode) { + MZ_UNUSED(errcode); +} diff --git a/thirdparty/minizip/mz_strm_bzip.h b/thirdparty/minizip/mz_strm_bzip.h new file mode 100644 index 000000000..06e3646f3 --- /dev/null +++ b/thirdparty/minizip/mz_strm_bzip.h @@ -0,0 +1,45 @@ +/* mz_strm_bzip.h -- Stream for bzip inflate/deflate + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_BZIP_H +#define MZ_STREAM_BZIP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_bzip_open(void *stream, const char *filename, int32_t mode); +int32_t mz_stream_bzip_is_open(void *stream); +int32_t mz_stream_bzip_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_bzip_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_bzip_tell(void *stream); +int32_t mz_stream_bzip_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_bzip_close(void *stream); +int32_t mz_stream_bzip_error(void *stream); + +int32_t mz_stream_bzip_get_prop_int64(void *stream, int32_t prop, int64_t *value); +int32_t mz_stream_bzip_set_prop_int64(void *stream, int32_t prop, int64_t value); + +void *mz_stream_bzip_create(void); +void mz_stream_bzip_delete(void **stream); + +void *mz_stream_bzip_get_interface(void); + +void bz_internal_error(int errcode); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_libcomp.c b/thirdparty/minizip/mz_strm_libcomp.c new file mode 100644 index 000000000..436d07ff4 --- /dev/null +++ b/thirdparty/minizip/mz_strm_libcomp.c @@ -0,0 +1,334 @@ +/* mz_strm_libcomp.c -- Stream for apple compression + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_strm.h" +#include "mz_strm_libcomp.h" + +#include + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_libcomp_vtbl = { + mz_stream_libcomp_open, mz_stream_libcomp_is_open, mz_stream_libcomp_read, + mz_stream_libcomp_write, mz_stream_libcomp_tell, mz_stream_libcomp_seek, + mz_stream_libcomp_close, mz_stream_libcomp_error, mz_stream_libcomp_create, + mz_stream_libcomp_delete, mz_stream_libcomp_get_prop_int64, mz_stream_libcomp_set_prop_int64}; + +/***************************************************************************/ + +typedef struct mz_stream_libcomp_s { + mz_stream stream; + compression_stream cstream; + uint8_t buffer[INT16_MAX]; + int32_t buffer_len; + int64_t total_in; + int64_t total_out; + int64_t max_total_in; + int8_t initialized; + int32_t mode; + int32_t error; + int16_t method; +} mz_stream_libcomp; + +/***************************************************************************/ + +int32_t mz_stream_libcomp_open(void *stream, const char *path, int32_t mode) { + mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; + int32_t err = 0; + int16_t operation = 0; + compression_algorithm algorithm = 0; + + MZ_UNUSED(path); + + if (libcomp->method == 0) + return MZ_PARAM_ERROR; + + libcomp->total_in = 0; + libcomp->total_out = 0; + + if (mode & MZ_OPEN_MODE_WRITE) { +#ifdef MZ_ZIP_NO_COMPRESSION + return MZ_SUPPORT_ERROR; +#else + operation = COMPRESSION_STREAM_ENCODE; +#endif + } else if (mode & MZ_OPEN_MODE_READ) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + return MZ_SUPPORT_ERROR; +#else + operation = COMPRESSION_STREAM_DECODE; +#endif + } + + if (libcomp->method == MZ_COMPRESS_METHOD_DEFLATE) + algorithm = COMPRESSION_ZLIB; + else if (libcomp->method == MZ_COMPRESS_METHOD_XZ) + algorithm = COMPRESSION_LZMA; + else + return MZ_SUPPORT_ERROR; + + err = compression_stream_init(&libcomp->cstream, (compression_stream_operation)operation, algorithm); + + if (err == COMPRESSION_STATUS_ERROR) { + libcomp->error = err; + return MZ_OPEN_ERROR; + } + + libcomp->initialized = 1; + libcomp->mode = mode; + return MZ_OK; +} + +int32_t mz_stream_libcomp_is_open(void *stream) { + mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; + if (libcomp->initialized != 1) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +int32_t mz_stream_libcomp_read(void *stream, void *buf, int32_t size) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + MZ_UNUSED(stream); + MZ_UNUSED(buf); + MZ_UNUSED(size); + return MZ_SUPPORT_ERROR; +#else + mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; + uint64_t total_in_before = 0; + uint64_t total_in_after = 0; + uint64_t total_out_before = 0; + uint64_t total_out_after = 0; + int32_t total_out = 0; + int32_t in_bytes = 0; + int32_t out_bytes = 0; + int32_t bytes_to_read = sizeof(libcomp->buffer); + int32_t read = 0; + int32_t err = MZ_OK; + int16_t flags = 0; + + libcomp->cstream.dst_ptr = buf; + libcomp->cstream.dst_size = (size_t)size; + + do { + if (libcomp->cstream.src_size == 0) { + if (libcomp->max_total_in > 0) { + if ((int64_t)bytes_to_read > (libcomp->max_total_in - libcomp->total_in)) + bytes_to_read = (int32_t)(libcomp->max_total_in - libcomp->total_in); + } + + read = mz_stream_read(libcomp->stream.base, libcomp->buffer, bytes_to_read); + + if (read < 0) + return read; + if (read == 0) + flags = COMPRESSION_STREAM_FINALIZE; + + libcomp->cstream.src_ptr = libcomp->buffer; + libcomp->cstream.src_size = (size_t)read; + } + + total_in_before = libcomp->cstream.src_size; + total_out_before = libcomp->cstream.dst_size; + + err = compression_stream_process(&libcomp->cstream, flags); + if (err == COMPRESSION_STATUS_ERROR) { + libcomp->error = err; + break; + } + + total_in_after = libcomp->cstream.src_size; + total_out_after = libcomp->cstream.dst_size; + + in_bytes = (int32_t)(total_in_before - total_in_after); + out_bytes = (int32_t)(total_out_before - total_out_after); + + total_out += out_bytes; + + libcomp->total_in += in_bytes; + libcomp->total_out += out_bytes; + + if (err == COMPRESSION_STATUS_END) + break; + if (err != COMPRESSION_STATUS_OK) { + libcomp->error = err; + break; + } + } while (libcomp->cstream.dst_size > 0); + + if (libcomp->error != 0) + return MZ_DATA_ERROR; + + return total_out; +#endif +} + +static int32_t mz_stream_libcomp_flush(void *stream) { + mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; + if (mz_stream_write(libcomp->stream.base, libcomp->buffer, libcomp->buffer_len) != libcomp->buffer_len) + return MZ_WRITE_ERROR; + return MZ_OK; +} + +static int32_t mz_stream_libcomp_deflate(void *stream, int flush) { + mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; + uint64_t total_out_before = 0; + uint64_t total_out_after = 0; + uint32_t out_bytes = 0; + int32_t err = MZ_OK; + + do { + if (libcomp->cstream.dst_size == 0) { + err = mz_stream_libcomp_flush(libcomp); + if (err != MZ_OK) { + libcomp->error = err; + return err; + } + + libcomp->cstream.dst_size = sizeof(libcomp->buffer); + libcomp->cstream.dst_ptr = libcomp->buffer; + + libcomp->buffer_len = 0; + } + + total_out_before = libcomp->cstream.dst_size; + err = compression_stream_process(&libcomp->cstream, flush); + total_out_after = libcomp->cstream.dst_size; + + out_bytes = (uint32_t)(total_out_before - total_out_after); + + libcomp->buffer_len += out_bytes; + libcomp->total_out += out_bytes; + + if (err == COMPRESSION_STATUS_END) + break; + if (err != COMPRESSION_STATUS_OK) { + libcomp->error = err; + return MZ_DATA_ERROR; + } + } while ((libcomp->cstream.src_size > 0) || (flush == COMPRESSION_STREAM_FINALIZE && err == COMPRESSION_STATUS_OK)); + + return MZ_OK; +} + +int32_t mz_stream_libcomp_write(void *stream, const void *buf, int32_t size) { + mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; + int32_t err = size; + +#ifdef MZ_ZIP_NO_COMPRESSION + MZ_UNUSED(libcomp); + err = MZ_SUPPORT_ERROR; +#else + libcomp->cstream.src_ptr = buf; + libcomp->cstream.src_size = (size_t)size; + + mz_stream_libcomp_deflate(stream, 0); + + libcomp->total_in += size; +#endif + return err; +} + +int64_t mz_stream_libcomp_tell(void *stream) { + MZ_UNUSED(stream); + + return MZ_TELL_ERROR; +} + +int32_t mz_stream_libcomp_seek(void *stream, int64_t offset, int32_t origin) { + MZ_UNUSED(stream); + MZ_UNUSED(offset); + MZ_UNUSED(origin); + + return MZ_SEEK_ERROR; +} + +int32_t mz_stream_libcomp_close(void *stream) { + mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; + + if (libcomp->mode & MZ_OPEN_MODE_WRITE) { +#ifdef MZ_ZIP_NO_COMPRESSION + return MZ_SUPPORT_ERROR; +#else + mz_stream_libcomp_deflate(stream, COMPRESSION_STREAM_FINALIZE); + mz_stream_libcomp_flush(stream); +#endif + } else if (libcomp->mode & MZ_OPEN_MODE_READ) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + return MZ_SUPPORT_ERROR; +#endif + } + + compression_stream_destroy(&libcomp->cstream); + + libcomp->initialized = 0; + + if (libcomp->error != MZ_OK) + return MZ_CLOSE_ERROR; + return MZ_OK; +} + +int32_t mz_stream_libcomp_error(void *stream) { + mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; + return libcomp->error; +} + +int32_t mz_stream_libcomp_get_prop_int64(void *stream, int32_t prop, int64_t *value) { + mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN: + *value = libcomp->total_in; + break; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + *value = libcomp->max_total_in; + break; + case MZ_STREAM_PROP_TOTAL_OUT: + *value = libcomp->total_out; + break; + case MZ_STREAM_PROP_HEADER_SIZE: + *value = 0; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +int32_t mz_stream_libcomp_set_prop_int64(void *stream, int32_t prop, int64_t value) { + mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream; + switch (prop) { + case MZ_STREAM_PROP_COMPRESS_METHOD: + libcomp->method = (int16_t)value; + break; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + libcomp->max_total_in = value; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +void *mz_stream_libcomp_create(void) { + mz_stream_libcomp *libcomp = (mz_stream_libcomp *)calloc(1, sizeof(mz_stream_libcomp)); + if (libcomp) + libcomp->stream.vtbl = &mz_stream_libcomp_vtbl; + return libcomp; +} + +void mz_stream_libcomp_delete(void **stream) { + mz_stream_libcomp *libcomp = NULL; + if (!stream) + return; + libcomp = (mz_stream_libcomp *)*stream; + if (libcomp) + free(libcomp); + *stream = NULL; +} diff --git a/thirdparty/minizip/mz_strm_libcomp.h b/thirdparty/minizip/mz_strm_libcomp.h new file mode 100644 index 000000000..5c89ac6b0 --- /dev/null +++ b/thirdparty/minizip/mz_strm_libcomp.h @@ -0,0 +1,43 @@ +/* mz_strm_libcomp.h -- Stream for apple compression + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_LIBCOMP_H +#define MZ_STREAM_LIBCOMP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_libcomp_open(void *stream, const char *filename, int32_t mode); +int32_t mz_stream_libcomp_is_open(void *stream); +int32_t mz_stream_libcomp_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_libcomp_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_libcomp_tell(void *stream); +int32_t mz_stream_libcomp_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_libcomp_close(void *stream); +int32_t mz_stream_libcomp_error(void *stream); + +int32_t mz_stream_libcomp_get_prop_int64(void *stream, int32_t prop, int64_t *value); +int32_t mz_stream_libcomp_set_prop_int64(void *stream, int32_t prop, int64_t value); + +void *mz_stream_libcomp_create(void); +void mz_stream_libcomp_delete(void **stream); + +void *mz_stream_libcomp_get_interface(void); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_lzma.c b/thirdparty/minizip/mz_strm_lzma.c new file mode 100644 index 000000000..c60f08c7c --- /dev/null +++ b/thirdparty/minizip/mz_strm_lzma.c @@ -0,0 +1,452 @@ +/* mz_strm_lzma.c -- Stream for lzma inflate/deflate + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_strm.h" +#include "mz_strm_lzma.h" + +#include "lzma.h" + +/***************************************************************************/ + +#define MZ_LZMA_MAGIC_SIZE (4) +#define MZ_LZMA_ZIP_HEADER_SIZE (5) +#define MZ_LZMA_ALONE_HEADER_SIZE (MZ_LZMA_ZIP_HEADER_SIZE + 8) + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_lzma_vtbl = { + mz_stream_lzma_open, mz_stream_lzma_is_open, mz_stream_lzma_read, mz_stream_lzma_write, + mz_stream_lzma_tell, mz_stream_lzma_seek, mz_stream_lzma_close, mz_stream_lzma_error, + mz_stream_lzma_create, mz_stream_lzma_delete, mz_stream_lzma_get_prop_int64, mz_stream_lzma_set_prop_int64}; + +/***************************************************************************/ + +typedef struct mz_stream_lzma_s { + mz_stream stream; + lzma_stream lstream; + int32_t mode; + int32_t error; + uint8_t buffer[INT16_MAX]; + int8_t header; + int32_t buffer_len; + int8_t initialized; + int16_t method; + int64_t total_in; + int64_t total_out; + int64_t max_total_in; + int64_t max_total_out; + int32_t header_size; + uint32_t preset; +} mz_stream_lzma; + +/***************************************************************************/ + +int32_t mz_stream_lzma_open(void *stream, const char *path, int32_t mode) { + mz_stream_lzma *lzma = (mz_stream_lzma *)stream; + lzma_filter filters[LZMA_FILTERS_MAX + 1]; + lzma_options_lzma opt_lzma; + uint32_t size = 0; + uint8_t major = 0; + uint8_t minor = 0; + + MZ_UNUSED(path); + + memset(&opt_lzma, 0, sizeof(opt_lzma)); + + lzma->lstream.total_in = 0; + lzma->lstream.total_out = 0; + + lzma->total_in = 0; + lzma->total_out = 0; + lzma->header = 0; + + if (mode & MZ_OPEN_MODE_WRITE) { +#ifdef MZ_ZIP_NO_COMPRESSION + MZ_UNUSED(filters); + MZ_UNUSED(major); + MZ_UNUSED(minor); + return MZ_SUPPORT_ERROR; +#else + lzma->lstream.next_out = lzma->buffer; + lzma->lstream.avail_out = sizeof(lzma->buffer); + + if (lzma_lzma_preset(&opt_lzma, lzma->preset)) + return MZ_OPEN_ERROR; + + memset(&filters, 0, sizeof(filters)); + + if (lzma->method == MZ_COMPRESS_METHOD_LZMA) + filters[0].id = LZMA_FILTER_LZMA1; + else if (lzma->method == MZ_COMPRESS_METHOD_XZ) + filters[0].id = LZMA_FILTER_LZMA2; + + filters[0].options = &opt_lzma; + filters[1].id = LZMA_VLI_UNKNOWN; + + lzma_properties_size(&size, (lzma_filter *)&filters); + + if (lzma->method == MZ_COMPRESS_METHOD_LZMA) { + mz_stream_write_uint8(lzma->stream.base, LZMA_VERSION_MAJOR); + mz_stream_write_uint8(lzma->stream.base, LZMA_VERSION_MINOR); + mz_stream_write_uint16(lzma->stream.base, (uint16_t)size); + + lzma->header = 1; + lzma->total_out += MZ_LZMA_MAGIC_SIZE; + + lzma->error = lzma_alone_encoder(&lzma->lstream, &opt_lzma); + } else if (lzma->method == MZ_COMPRESS_METHOD_XZ) + lzma->error = lzma_stream_encoder(&lzma->lstream, filters, LZMA_CHECK_CRC64); +#endif + } else if (mode & MZ_OPEN_MODE_READ) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + MZ_UNUSED(filters); + MZ_UNUSED(major); + MZ_UNUSED(minor); + return MZ_SUPPORT_ERROR; +#else + lzma->lstream.next_in = lzma->buffer; + lzma->lstream.avail_in = 0; + + if (lzma->method == MZ_COMPRESS_METHOD_LZMA) { + mz_stream_read_uint8(lzma->stream.base, &major); + mz_stream_read_uint8(lzma->stream.base, &minor); + mz_stream_read_uint16(lzma->stream.base, (uint16_t *)&size); + + lzma->header = 1; + lzma->total_in += MZ_LZMA_MAGIC_SIZE; + + lzma->error = lzma_alone_decoder(&lzma->lstream, UINT64_MAX); + } else if (lzma->method == MZ_COMPRESS_METHOD_XZ) + lzma->error = lzma_stream_decoder(&lzma->lstream, UINT64_MAX, 0); +#endif + } + + if (lzma->error != LZMA_OK) + return MZ_OPEN_ERROR; + + lzma->initialized = 1; + lzma->mode = mode; + return MZ_OK; +} + +int32_t mz_stream_lzma_is_open(void *stream) { + mz_stream_lzma *lzma = (mz_stream_lzma *)stream; + if (lzma->initialized != 1) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +int32_t mz_stream_lzma_read(void *stream, void *buf, int32_t size) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + MZ_UNUSED(stream); + MZ_UNUSED(buf); + MZ_UNUSED(size); + return MZ_SUPPORT_ERROR; +#else + mz_stream_lzma *lzma = (mz_stream_lzma *)stream; + uint64_t total_in_before = 0; + uint64_t total_out_before = 0; + uint64_t total_in_after = 0; + uint64_t total_out_after = 0; + int32_t total_in = 0; + int32_t total_out = 0; + int32_t in_bytes = 0; + int32_t out_bytes = 0; + int32_t bytes_to_read = sizeof(lzma->buffer); + int32_t read = 0; + int32_t err = LZMA_OK; + + lzma->lstream.next_out = (uint8_t *)buf; + lzma->lstream.avail_out = (size_t)size; + + do { + if (lzma->lstream.avail_in == 0) { + if (lzma->max_total_in > 0) { + if ((int64_t)bytes_to_read > (lzma->max_total_in - lzma->total_in)) + bytes_to_read = (int32_t)(lzma->max_total_in - lzma->total_in); + } + + if (lzma->header) { + bytes_to_read = MZ_LZMA_ZIP_HEADER_SIZE - lzma->header_size; + } + + read = mz_stream_read(lzma->stream.base, lzma->buffer, bytes_to_read); + + if (read < 0) + return read; + + /* Write uncompressed size for lzma alone header not in zip format */ + if (lzma->header) { + lzma->header_size += read; + + if (lzma->header_size == MZ_LZMA_ZIP_HEADER_SIZE) { + uint64_t uncompressed_size = UINT64_MAX; + + memcpy(lzma->buffer + MZ_LZMA_ZIP_HEADER_SIZE, &uncompressed_size, sizeof(uncompressed_size)); + + read += sizeof(uncompressed_size); + bytes_to_read = sizeof(lzma->buffer); + + lzma->total_in -= sizeof(uncompressed_size); + lzma->header = 0; + } + } + + lzma->lstream.next_in = lzma->buffer; + lzma->lstream.avail_in = (size_t)read; + } + + total_in_before = lzma->lstream.avail_in; + total_out_before = lzma->lstream.total_out; + + err = lzma_code(&lzma->lstream, LZMA_RUN); + + total_in_after = lzma->lstream.avail_in; + total_out_after = lzma->lstream.total_out; + if ((lzma->max_total_out != -1) && (int64_t)total_out_after > lzma->max_total_out) + total_out_after = (uint64_t)lzma->max_total_out; + + in_bytes = (int32_t)(total_in_before - total_in_after); + out_bytes = (int32_t)(total_out_after - total_out_before); + + total_in += in_bytes; + total_out += out_bytes; + + lzma->total_in += in_bytes; + lzma->total_out += out_bytes; + + if (err == LZMA_STREAM_END) + break; + if (err != LZMA_OK) { + lzma->error = err; + break; + } + } while (lzma->lstream.avail_out > 0); + + MZ_UNUSED(total_in); + + if (lzma->error != 0) + return MZ_DATA_ERROR; + + return total_out; +#endif +} + +#ifndef MZ_ZIP_NO_COMPRESSION +static int32_t mz_stream_lzma_flush(void *stream) { + mz_stream_lzma *lzma = (mz_stream_lzma *)stream; + int32_t buffer_len = lzma->buffer_len; + uint8_t *buffer = lzma->buffer; + + /* Skip writing lzma_alone header uncompressed size for zip format */ + if (lzma->header) { + uint64_t uncompressed_size = 0; + + if (lzma->buffer_len < MZ_LZMA_ALONE_HEADER_SIZE) + return MZ_OK; + + if (mz_stream_write(lzma->stream.base, buffer, MZ_LZMA_ZIP_HEADER_SIZE) != MZ_LZMA_ZIP_HEADER_SIZE) + return MZ_WRITE_ERROR; + + buffer += MZ_LZMA_ALONE_HEADER_SIZE; + buffer_len -= MZ_LZMA_ALONE_HEADER_SIZE; + + lzma->buffer_len -= sizeof(uncompressed_size); + lzma->total_out -= sizeof(uncompressed_size); + lzma->header = 0; + } + + if (mz_stream_write(lzma->stream.base, buffer, buffer_len) != buffer_len) + return MZ_WRITE_ERROR; + + return MZ_OK; +} + +static int32_t mz_stream_lzma_code(void *stream, int32_t flush) { + mz_stream_lzma *lzma = (mz_stream_lzma *)stream; + uint64_t total_out_before = 0; + uint64_t total_out_after = 0; + uint32_t out_bytes = 0; + int32_t err = LZMA_OK; + + do { + if (lzma->lstream.avail_out == 0) { + err = mz_stream_lzma_flush(lzma); + if (err != MZ_OK) + return err; + + lzma->lstream.avail_out = sizeof(lzma->buffer); + lzma->lstream.next_out = lzma->buffer; + + lzma->buffer_len = 0; + } + + total_out_before = lzma->lstream.total_out; + err = lzma_code(&lzma->lstream, (lzma_action)flush); + total_out_after = lzma->lstream.total_out; + + out_bytes = (uint32_t)(total_out_after - total_out_before); + + if (err != LZMA_OK && err != LZMA_STREAM_END) { + lzma->error = err; + return MZ_DATA_ERROR; + } + + lzma->buffer_len += out_bytes; + lzma->total_out += out_bytes; + } while ((lzma->lstream.avail_in > 0) || (flush == LZMA_FINISH && err == LZMA_OK)); + + return MZ_OK; +} +#endif + +int32_t mz_stream_lzma_write(void *stream, const void *buf, int32_t size) { +#ifdef MZ_ZIP_NO_COMPRESSION + MZ_UNUSED(stream); + MZ_UNUSED(buf); + MZ_UNUSED(size); + return MZ_SUPPORT_ERROR; +#else + mz_stream_lzma *lzma = (mz_stream_lzma *)stream; + int32_t err = MZ_OK; + + lzma->lstream.next_in = (uint8_t *)(intptr_t)buf; + lzma->lstream.avail_in = (size_t)size; + + err = mz_stream_lzma_code(stream, LZMA_RUN); + if (err != MZ_OK) { + return err; + } + + lzma->total_in += size; + return size; +#endif +} + +int64_t mz_stream_lzma_tell(void *stream) { + MZ_UNUSED(stream); + + return MZ_TELL_ERROR; +} + +int32_t mz_stream_lzma_seek(void *stream, int64_t offset, int32_t origin) { + MZ_UNUSED(stream); + MZ_UNUSED(offset); + MZ_UNUSED(origin); + + return MZ_SEEK_ERROR; +} + +int32_t mz_stream_lzma_close(void *stream) { + mz_stream_lzma *lzma = (mz_stream_lzma *)stream; + + if (lzma->mode & MZ_OPEN_MODE_WRITE) { +#ifdef MZ_ZIP_NO_COMPRESSION + return MZ_SUPPORT_ERROR; +#else + mz_stream_lzma_code(stream, LZMA_FINISH); + mz_stream_lzma_flush(stream); + + lzma_end(&lzma->lstream); +#endif + } else if (lzma->mode & MZ_OPEN_MODE_READ) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + return MZ_SUPPORT_ERROR; +#else + lzma_end(&lzma->lstream); +#endif + } + + lzma->initialized = 0; + + if (lzma->error != LZMA_OK) + return MZ_CLOSE_ERROR; + return MZ_OK; +} + +int32_t mz_stream_lzma_error(void *stream) { + mz_stream_lzma *lzma = (mz_stream_lzma *)stream; + return lzma->error; +} + +int32_t mz_stream_lzma_get_prop_int64(void *stream, int32_t prop, int64_t *value) { + mz_stream_lzma *lzma = (mz_stream_lzma *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN: + *value = lzma->total_in; + break; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + *value = lzma->max_total_in; + break; + case MZ_STREAM_PROP_TOTAL_OUT: + *value = lzma->total_out; + break; + case MZ_STREAM_PROP_TOTAL_OUT_MAX: + *value = lzma->max_total_out; + break; + case MZ_STREAM_PROP_HEADER_SIZE: + *value = MZ_LZMA_MAGIC_SIZE; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +int32_t mz_stream_lzma_set_prop_int64(void *stream, int32_t prop, int64_t value) { + mz_stream_lzma *lzma = (mz_stream_lzma *)stream; + switch (prop) { + case MZ_STREAM_PROP_COMPRESS_LEVEL: + if (value == MZ_COMPRESS_LEVEL_DEFAULT) + lzma->preset = LZMA_PRESET_DEFAULT; + else + lzma->preset = (uint32_t)value; + break; + case MZ_STREAM_PROP_COMPRESS_METHOD: + lzma->method = (int16_t)value; + break; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + lzma->max_total_in = value; + break; + case MZ_STREAM_PROP_TOTAL_OUT_MAX: + if (value < -1) + return MZ_PARAM_ERROR; + lzma->max_total_out = value; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +void *mz_stream_lzma_create(void) { + mz_stream_lzma *lzma = (mz_stream_lzma *)calloc(1, sizeof(mz_stream_lzma)); + if (lzma) { + lzma->stream.vtbl = &mz_stream_lzma_vtbl; + lzma->method = MZ_COMPRESS_METHOD_LZMA; + lzma->preset = LZMA_PRESET_DEFAULT; + lzma->max_total_out = -1; + } + return lzma; +} + +void mz_stream_lzma_delete(void **stream) { + mz_stream_lzma *lzma = NULL; + if (!stream) + return; + lzma = (mz_stream_lzma *)*stream; + free(lzma); + *stream = NULL; +} + +void *mz_stream_lzma_get_interface(void) { + return (void *)&mz_stream_lzma_vtbl; +} diff --git a/thirdparty/minizip/mz_strm_lzma.h b/thirdparty/minizip/mz_strm_lzma.h new file mode 100644 index 000000000..6a60f7f16 --- /dev/null +++ b/thirdparty/minizip/mz_strm_lzma.h @@ -0,0 +1,43 @@ +/* mz_strm_lzma.h -- Stream for lzma inflate/deflate + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as lzma. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_LZMA_H +#define MZ_STREAM_LZMA_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_lzma_open(void *stream, const char *filename, int32_t mode); +int32_t mz_stream_lzma_is_open(void *stream); +int32_t mz_stream_lzma_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_lzma_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_lzma_tell(void *stream); +int32_t mz_stream_lzma_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_lzma_close(void *stream); +int32_t mz_stream_lzma_error(void *stream); + +int32_t mz_stream_lzma_get_prop_int64(void *stream, int32_t prop, int64_t *value); +int32_t mz_stream_lzma_set_prop_int64(void *stream, int32_t prop, int64_t value); + +void *mz_stream_lzma_create(void); +void mz_stream_lzma_delete(void **stream); + +void *mz_stream_lzma_get_interface(void); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_mem.c b/thirdparty/minizip/mz_strm_mem.c new file mode 100644 index 000000000..7669712bc --- /dev/null +++ b/thirdparty/minizip/mz_strm_mem.c @@ -0,0 +1,265 @@ +/* mz_strm_mem.c -- Stream for memory access + part of the minizip-ng project + + This interface is designed to access memory rather than files. + We do use a region of memory to put data in to and take it out of. + + Based on Unzip ioapi.c version 0.22, May 19th, 2003 + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Copyright (C) 2003 Justin Fletcher + Copyright (C) 1998-2003 Gilles Vollant + https://www.winimage.com/zLibDll/minizip.html + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_strm.h" +#include "mz_strm_mem.h" + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_mem_vtbl = {mz_stream_mem_open, + mz_stream_mem_is_open, + mz_stream_mem_read, + mz_stream_mem_write, + mz_stream_mem_tell, + mz_stream_mem_seek, + mz_stream_mem_close, + mz_stream_mem_error, + mz_stream_mem_create, + mz_stream_mem_delete, + NULL, + NULL}; + +/***************************************************************************/ + +typedef struct mz_stream_mem_s { + mz_stream stream; + int32_t mode; + uint8_t *buffer; /* Memory buffer pointer */ + int32_t size; /* Size of the memory buffer */ + int32_t limit; /* Furthest we've written */ + int32_t position; /* Current position in the memory */ + int32_t grow_size; /* Size to grow when full */ +} mz_stream_mem; + +/***************************************************************************/ + +static int32_t mz_stream_mem_set_size(void *stream, int32_t size) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + int32_t new_size = size; + uint8_t *new_buf = NULL; + + new_buf = (uint8_t *)malloc((uint32_t)new_size); + if (!new_buf) + return MZ_BUF_ERROR; + + if (mem->buffer) { + memcpy(new_buf, mem->buffer, mem->size); + free(mem->buffer); + } + + mem->buffer = new_buf; + mem->size = new_size; + return MZ_OK; +} + +int32_t mz_stream_mem_open(void *stream, const char *path, int32_t mode) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + int32_t err = MZ_OK; + + MZ_UNUSED(path); + + mem->mode = mode; + mem->limit = 0; + mem->position = 0; + + if (mem->mode & MZ_OPEN_MODE_CREATE) + err = mz_stream_mem_set_size(stream, mem->grow_size); + else + mem->limit = mem->size; + + return err; +} + +int32_t mz_stream_mem_is_open(void *stream) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + if (!mem->buffer) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + + if (size > mem->size - mem->position) + size = mem->size - mem->position; + if (mem->position + size > mem->limit) + size = mem->limit - mem->position; + + if (size <= 0) + return 0; + + memcpy(buf, mem->buffer + mem->position, size); + mem->position += size; + + return size; +} + +int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + int32_t new_size = 0; + int32_t err = MZ_OK; + + if (!size) + return size; + + if (size > mem->size - mem->position) { + if (mem->mode & MZ_OPEN_MODE_CREATE) { + new_size = mem->size; + if (size < mem->grow_size) + new_size += mem->grow_size; + else + new_size += size; + + err = mz_stream_mem_set_size(stream, new_size); + if (err != MZ_OK) + return err; + } else { + size = mem->size - mem->position; + } + } + + memcpy(mem->buffer + mem->position, buf, size); + + mem->position += size; + if (mem->position > mem->limit) + mem->limit = mem->position; + + return size; +} + +int64_t mz_stream_mem_tell(void *stream) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + return mem->position; +} + +int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + int64_t new_pos = 0; + int32_t err = MZ_OK; + + switch (origin) { + case MZ_SEEK_CUR: + new_pos = mem->position + offset; + break; + case MZ_SEEK_END: + new_pos = mem->limit + offset; + break; + case MZ_SEEK_SET: + new_pos = offset; + break; + default: + return MZ_SEEK_ERROR; + } + + // While `malloc` accepts a size_t, mz_stream_mem_s.size only supports an int32_t + if (new_pos < 0 || new_pos > INT32_MAX) { + return MZ_SEEK_ERROR; + } + + if (new_pos > mem->size) { + if ((mem->mode & MZ_OPEN_MODE_CREATE) == 0) + return MZ_SEEK_ERROR; + + err = mz_stream_mem_set_size(stream, (int32_t)new_pos); + if (err != MZ_OK) + return err; + } + + mem->position = (int32_t)new_pos; + return MZ_OK; +} + +int32_t mz_stream_mem_close(void *stream) { + MZ_UNUSED(stream); + + /* We never return errors */ + return MZ_OK; +} + +int32_t mz_stream_mem_error(void *stream) { + MZ_UNUSED(stream); + + /* We never return errors */ + return MZ_OK; +} + +void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + mem->buffer = (uint8_t *)buf; + mem->size = size; + mem->limit = size; +} + +int32_t mz_stream_mem_get_buffer(void *stream, const void **buf) { + return mz_stream_mem_get_buffer_at(stream, 0, buf); +} + +int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + if (!buf || position < 0 || !mem->buffer || mem->size < position) + return MZ_SEEK_ERROR; + *buf = mem->buffer + position; + return MZ_OK; +} + +int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + return mz_stream_mem_get_buffer_at(stream, mem->position, buf); +} + +void mz_stream_mem_get_buffer_length(void *stream, int32_t *length) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + *length = mem->limit; +} + +void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + mem->limit = limit; +} + +void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size) { + mz_stream_mem *mem = (mz_stream_mem *)stream; + mem->grow_size = grow_size; +} + +void *mz_stream_mem_create(void) { + mz_stream_mem *mem = (mz_stream_mem *)calloc(1, sizeof(mz_stream_mem)); + if (mem) { + mem->stream.vtbl = &mz_stream_mem_vtbl; + mem->grow_size = 4096; + } + return mem; +} + +void mz_stream_mem_delete(void **stream) { + mz_stream_mem *mem = NULL; + if (!stream) + return; + mem = (mz_stream_mem *)*stream; + if (mem) { + if ((mem->mode & MZ_OPEN_MODE_CREATE) && (mem->buffer)) + free(mem->buffer); + free(mem); + } + *stream = NULL; +} + +void *mz_stream_mem_get_interface(void) { + return (void *)&mz_stream_mem_vtbl; +} diff --git a/thirdparty/minizip/mz_strm_mem.h b/thirdparty/minizip/mz_strm_mem.h new file mode 100644 index 000000000..1055634cc --- /dev/null +++ b/thirdparty/minizip/mz_strm_mem.h @@ -0,0 +1,48 @@ +/* mz_strm_mem.h -- Stream for memory access + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_MEM_H +#define MZ_STREAM_MEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_mem_open(void *stream, const char *filename, int32_t mode); +int32_t mz_stream_mem_is_open(void *stream); +int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_mem_tell(void *stream); +int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_mem_close(void *stream); +int32_t mz_stream_mem_error(void *stream); + +void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size); +int32_t mz_stream_mem_get_buffer(void *stream, const void **buf); +int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf); +int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf); +void mz_stream_mem_get_buffer_length(void *stream, int32_t *length); +void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit); +void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size); + +void *mz_stream_mem_create(void); +void mz_stream_mem_delete(void **stream); + +void *mz_stream_mem_get_interface(void); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_os.h b/thirdparty/minizip/mz_strm_os.h new file mode 100644 index 000000000..d6846d8cc --- /dev/null +++ b/thirdparty/minizip/mz_strm_os.h @@ -0,0 +1,40 @@ +/* mz_sstrm_os.h -- Stream for filesystem access + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_OS_H +#define MZ_STREAM_OS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode); +int32_t mz_stream_os_is_open(void *stream); +int32_t mz_stream_os_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_os_tell(void *stream); +int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_os_close(void *stream); +int32_t mz_stream_os_error(void *stream); + +void *mz_stream_os_create(void); +void mz_stream_os_delete(void **stream); + +void *mz_stream_os_get_interface(void); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_os_posix.c b/thirdparty/minizip/mz_strm_os_posix.c new file mode 100644 index 000000000..1bb5dc406 --- /dev/null +++ b/thirdparty/minizip/mz_strm_os_posix.c @@ -0,0 +1,212 @@ +/* mz_strm_posix.c -- Stream for filesystem access for posix/linux + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson + http://result42.com + Copyright (C) 1998-2010 Gilles Vollant + https://www.winimage.com/zLibDll/minizip.html + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_config.h" +#include "mz_strm.h" +#include "mz_strm_os.h" + +#include /* fopen, fread, ... */ +#include +#include /* S_IRUSR, S_IWUSR, ... */ +#include /* open, close, ... */ +#include /* O_NOFOLLOW, ... */ + +/***************************************************************************/ + +#define fopen64 fopen +#ifndef MZ_FILE32_API +# if HAVE_FSEEKO +# define ftello64 ftello +# define fseeko64 fseeko +# elif defined(_MSC_VER) && (_MSC_VER >= 1400) +# define ftello64 _ftelli64 +# define fseeko64 _fseeki64 +# endif +#endif +#ifndef ftello64 +# define ftello64 ftell +#endif +#ifndef fseeko64 +# define fseeko64 fseek +#endif + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_os_vtbl = {mz_stream_os_open, + mz_stream_os_is_open, + mz_stream_os_read, + mz_stream_os_write, + mz_stream_os_tell, + mz_stream_os_seek, + mz_stream_os_close, + mz_stream_os_error, + mz_stream_os_create, + mz_stream_os_delete, + NULL, + NULL}; + +/***************************************************************************/ + +typedef struct mz_stream_posix_s { + mz_stream stream; + int32_t error; + FILE *handle; +} mz_stream_posix; + +/***************************************************************************/ + +int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) { + mz_stream_posix *posix = (mz_stream_posix *)stream; + const char *mode_fopen = NULL; + int mode_open = 0; + int fd; + + if (!path) + return MZ_PARAM_ERROR; + + if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) { + mode_fopen = "r"; + mode_open = O_RDONLY; + } else if (mode & MZ_OPEN_MODE_APPEND) { + mode_fopen = "r+"; + mode_open = O_RDWR; + } else if (mode & MZ_OPEN_MODE_CREATE) { + mode_fopen = "w"; + mode_open = O_WRONLY | O_CREAT | O_TRUNC; + } else + return MZ_OPEN_ERROR; + + if (mode & MZ_OPEN_MODE_NOFOLLOW) + mode_open |= O_NOFOLLOW; + + fd = open(path, mode_open, S_IRUSR | S_IWUSR | S_IRGRP); + if (fd != -1) { + posix->handle = fdopen(fd, mode_fopen); + if (!posix->handle) + close(fd); + } + if (!posix->handle) { + posix->error = errno; + return MZ_OPEN_ERROR; + } + + if (mode & MZ_OPEN_MODE_APPEND) + return mz_stream_os_seek(stream, 0, MZ_SEEK_END); + + return MZ_OK; +} + +int32_t mz_stream_os_is_open(void *stream) { + mz_stream_posix *posix = (mz_stream_posix *)stream; + if (!posix->handle) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) { + mz_stream_posix *posix = (mz_stream_posix *)stream; + int32_t read = (int32_t)fread(buf, 1, (size_t)size, posix->handle); + if (read < size && ferror(posix->handle)) { + posix->error = errno; + return MZ_READ_ERROR; + } + return read; +} + +int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) { + mz_stream_posix *posix = (mz_stream_posix *)stream; + int32_t written = (int32_t)fwrite(buf, 1, (size_t)size, posix->handle); + if (written < size && ferror(posix->handle)) { + posix->error = errno; + return MZ_WRITE_ERROR; + } + return written; +} + +int64_t mz_stream_os_tell(void *stream) { + mz_stream_posix *posix = (mz_stream_posix *)stream; + int64_t position = ftello64(posix->handle); + if (position == -1) { + posix->error = errno; + return MZ_TELL_ERROR; + } + return position; +} + +int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) { + mz_stream_posix *posix = (mz_stream_posix *)stream; + int32_t fseek_origin = 0; + + switch (origin) { + case MZ_SEEK_CUR: + fseek_origin = SEEK_CUR; + break; + case MZ_SEEK_END: + fseek_origin = SEEK_END; + break; + case MZ_SEEK_SET: + fseek_origin = SEEK_SET; + break; + default: + return MZ_SEEK_ERROR; + } + + if (fseeko64(posix->handle, offset, fseek_origin) != 0) { + posix->error = errno; + return MZ_SEEK_ERROR; + } + + return MZ_OK; +} + +int32_t mz_stream_os_close(void *stream) { + mz_stream_posix *posix = (mz_stream_posix *)stream; + int32_t closed = 0; + if (posix->handle) { + closed = fclose(posix->handle); + posix->handle = NULL; + } + if (closed != 0) { + posix->error = errno; + return MZ_CLOSE_ERROR; + } + return MZ_OK; +} + +int32_t mz_stream_os_error(void *stream) { + mz_stream_posix *posix = (mz_stream_posix *)stream; + return posix->error; +} + +void *mz_stream_os_create(void) { + mz_stream_posix *posix = (mz_stream_posix *)calloc(1, sizeof(mz_stream_posix)); + if (posix) + posix->stream.vtbl = &mz_stream_os_vtbl; + return posix; +} + +void mz_stream_os_delete(void **stream) { + mz_stream_posix *posix = NULL; + if (!stream) + return; + posix = (mz_stream_posix *)*stream; + free(posix); + *stream = NULL; +} + +void *mz_stream_os_get_interface(void) { + return (void *)&mz_stream_os_vtbl; +} diff --git a/thirdparty/minizip/mz_strm_os_win32.c b/thirdparty/minizip/mz_strm_os_win32.c new file mode 100644 index 000000000..d79da7b8b --- /dev/null +++ b/thirdparty/minizip/mz_strm_os_win32.c @@ -0,0 +1,280 @@ +/* mz_strm_win32.c -- Stream for filesystem access for windows + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Copyright (C) 2009-2010 Mathias Svensson + Modifications for Zip64 support + http://result42.com + Copyright (C) 1998-2010 Gilles Vollant + https://www.winimage.com/zLibDll/minizip.html + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_os.h" +#include "mz_strm.h" +#include "mz_strm_os.h" + +#include + +/***************************************************************************/ + +#ifndef INVALID_HANDLE_VALUE +# define INVALID_HANDLE_VALUE 0xFFFFFFFF +#endif + +#ifndef INVALID_SET_FILE_POINTER +# define INVALID_SET_FILE_POINTER (DWORD)(-1) +#endif + +#ifndef _WIN32_WINNT_WIN8 +# define _WIN32_WINNT_WIN8 0x0602 +#endif + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_os_vtbl = {mz_stream_os_open, + mz_stream_os_is_open, + mz_stream_os_read, + mz_stream_os_write, + mz_stream_os_tell, + mz_stream_os_seek, + mz_stream_os_close, + mz_stream_os_error, + mz_stream_os_create, + mz_stream_os_delete, + NULL, + NULL}; + +/***************************************************************************/ + +typedef struct mz_stream_win32_s { + mz_stream stream; + HANDLE handle; + int32_t error; +} mz_stream_win32; + +/***************************************************************************/ + +#if 0 +# define mz_stream_os_print printf +#else +# define mz_stream_os_print(fmt, ...) +#endif + +/***************************************************************************/ + +int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) { + mz_stream_win32 *win32 = (mz_stream_win32 *)stream; + uint32_t desired_access = 0; + uint32_t creation_disposition = 0; + uint32_t share_mode = FILE_SHARE_READ; + uint32_t flags_attribs = FILE_ATTRIBUTE_NORMAL; + wchar_t *path_wide = NULL; + + if (!path) + return MZ_PARAM_ERROR; + + /* Some use cases require write sharing as well */ + share_mode |= FILE_SHARE_WRITE; + + if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) { + desired_access = GENERIC_READ; + creation_disposition = OPEN_EXISTING; + } else if (mode & MZ_OPEN_MODE_APPEND) { + desired_access = GENERIC_WRITE | GENERIC_READ; + creation_disposition = OPEN_EXISTING; + } else if (mode & MZ_OPEN_MODE_CREATE) { + desired_access = GENERIC_WRITE | GENERIC_READ; + creation_disposition = CREATE_ALWAYS; + } else { + return MZ_PARAM_ERROR; + } + + mz_stream_os_print("Win32 - Open - %s (mode %" PRId32 ")\n", path); + + path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8); + if (!path_wide) + return MZ_PARAM_ERROR; + +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 + win32->handle = CreateFile2(path_wide, desired_access, share_mode, creation_disposition, NULL); +#else + win32->handle = CreateFileW(path_wide, desired_access, share_mode, NULL, creation_disposition, flags_attribs, NULL); +#endif + + mz_os_unicode_string_delete(&path_wide); + + if (mz_stream_os_is_open(stream) != MZ_OK) { + win32->error = GetLastError(); + return MZ_OPEN_ERROR; + } + + if (mode & MZ_OPEN_MODE_APPEND) + return mz_stream_os_seek(stream, 0, MZ_SEEK_END); + + return MZ_OK; +} + +int32_t mz_stream_os_is_open(void *stream) { + mz_stream_win32 *win32 = (mz_stream_win32 *)stream; + if (!win32->handle || win32->handle == INVALID_HANDLE_VALUE) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) { + mz_stream_win32 *win32 = (mz_stream_win32 *)stream; + uint32_t read = 0; + + if (mz_stream_os_is_open(stream) != MZ_OK) + return MZ_OPEN_ERROR; + + if (!ReadFile(win32->handle, buf, size, (DWORD *)&read, NULL)) { + win32->error = GetLastError(); + if (win32->error == ERROR_HANDLE_EOF) + win32->error = 0; + } + + mz_stream_os_print("Win32 - Read - %" PRId32 "\n", read); + + return read; +} + +int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) { + mz_stream_win32 *win32 = (mz_stream_win32 *)stream; + int32_t written = 0; + + if (mz_stream_os_is_open(stream) != MZ_OK) + return MZ_OPEN_ERROR; + + if (!WriteFile(win32->handle, buf, size, (DWORD *)&written, NULL)) { + win32->error = GetLastError(); + if (win32->error == ERROR_HANDLE_EOF) + win32->error = 0; + } + + mz_stream_os_print("Win32 - Write - %" PRId32 "\n", written); + + return written; +} + +static int32_t mz_stream_os_seekinternal(HANDLE handle, LARGE_INTEGER large_pos, LARGE_INTEGER *new_pos, + uint32_t move_method) { +#if _WIN32_WINNT >= _WIN32_WINNT_WINXP + BOOL success = FALSE; + success = SetFilePointerEx(handle, large_pos, new_pos, move_method); + if ((success == FALSE) && (GetLastError() != NO_ERROR)) + return MZ_SEEK_ERROR; + + return MZ_OK; +#else + LONG high_part = 0; + uint32_t pos = 0; + + high_part = large_pos.HighPart; + pos = SetFilePointer(handle, large_pos.LowPart, &high_part, move_method); + + if ((pos == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR)) + return MZ_SEEK_ERROR; + + if (new_pos) { + new_pos->LowPart = pos; + new_pos->HighPart = high_part; + } + + return MZ_OK; +#endif +} + +int64_t mz_stream_os_tell(void *stream) { + mz_stream_win32 *win32 = (mz_stream_win32 *)stream; + LARGE_INTEGER large_pos; + + if (mz_stream_os_is_open(stream) != MZ_OK) + return MZ_OPEN_ERROR; + + large_pos.QuadPart = 0; + + if (mz_stream_os_seekinternal(win32->handle, large_pos, &large_pos, FILE_CURRENT) != MZ_OK) + win32->error = GetLastError(); + + mz_stream_os_print("Win32 - Tell - %" PRId64 "\n", large_pos.QuadPart); + + return large_pos.QuadPart; +} + +int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) { + mz_stream_win32 *win32 = (mz_stream_win32 *)stream; + uint32_t move_method = 0xFFFFFFFF; + int32_t err = MZ_OK; + LARGE_INTEGER large_pos; + + if (mz_stream_os_is_open(stream) != MZ_OK) + return MZ_OPEN_ERROR; + + switch (origin) { + case MZ_SEEK_CUR: + move_method = FILE_CURRENT; + break; + case MZ_SEEK_END: + move_method = FILE_END; + break; + case MZ_SEEK_SET: + move_method = FILE_BEGIN; + break; + default: + return MZ_SEEK_ERROR; + } + + mz_stream_os_print("Win32 - Seek - %" PRId64 " (origin %" PRId32 ")\n", offset, origin); + + large_pos.QuadPart = offset; + + err = mz_stream_os_seekinternal(win32->handle, large_pos, NULL, move_method); + if (err != MZ_OK) { + win32->error = GetLastError(); + return err; + } + + return MZ_OK; +} + +int32_t mz_stream_os_close(void *stream) { + mz_stream_win32 *win32 = (mz_stream_win32 *)stream; + + if (win32->handle) + CloseHandle(win32->handle); + mz_stream_os_print("Win32 - Close\n"); + win32->handle = NULL; + return MZ_OK; +} + +int32_t mz_stream_os_error(void *stream) { + mz_stream_win32 *win32 = (mz_stream_win32 *)stream; + return win32->error; +} + +void *mz_stream_os_create(void) { + mz_stream_win32 *win32 = (mz_stream_win32 *)calloc(1, sizeof(mz_stream_win32)); + if (win32) + win32->stream.vtbl = &mz_stream_os_vtbl; + return win32; +} + +void mz_stream_os_delete(void **stream) { + mz_stream_win32 *win32 = NULL; + if (!stream) + return; + win32 = (mz_stream_win32 *)*stream; + if (win32) + free(win32); + *stream = NULL; +} + +void *mz_stream_os_get_interface(void) { + return (void *)&mz_stream_os_vtbl; +} diff --git a/thirdparty/minizip/mz_strm_pkcrypt.c b/thirdparty/minizip/mz_strm_pkcrypt.c new file mode 100644 index 000000000..8098719a3 --- /dev/null +++ b/thirdparty/minizip/mz_strm_pkcrypt.c @@ -0,0 +1,324 @@ +/* mz_strm_pkcrypt.c -- Code for traditional PKWARE encryption + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Copyright (C) 1998-2005 Gilles Vollant + Modifications for Info-ZIP crypting + https://www.winimage.com/zLibDll/minizip.html + Copyright (C) 2003 Terry Thorsen + + This code is a modified version of crypting code in Info-ZIP distribution + + Copyright (C) 1990-2000 Info-ZIP. All rights reserved. + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). +*/ + +#include "mz.h" +#include "mz_crypt.h" +#include "mz_strm.h" +#include "mz_strm_pkcrypt.h" + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_pkcrypt_vtbl = { + mz_stream_pkcrypt_open, mz_stream_pkcrypt_is_open, mz_stream_pkcrypt_read, + mz_stream_pkcrypt_write, mz_stream_pkcrypt_tell, mz_stream_pkcrypt_seek, + mz_stream_pkcrypt_close, mz_stream_pkcrypt_error, mz_stream_pkcrypt_create, + mz_stream_pkcrypt_delete, mz_stream_pkcrypt_get_prop_int64, mz_stream_pkcrypt_set_prop_int64}; + +/***************************************************************************/ + +typedef struct mz_stream_pkcrypt_s { + mz_stream stream; + int32_t error; + int16_t initialized; + uint8_t buffer[UINT16_MAX]; + int64_t total_in; + int64_t max_total_in; + int64_t total_out; + uint32_t keys[3]; /* keys defining the pseudo-random sequence */ + uint8_t verify1; + uint8_t verify2; + uint16_t verify_version; + const char *password; +} mz_stream_pkcrypt; + +/***************************************************************************/ + +#define mz_stream_pkcrypt_decode(strm, c) \ + (mz_stream_pkcrypt_update_keys(strm, c ^= mz_stream_pkcrypt_decrypt_byte(strm))) + +#define mz_stream_pkcrypt_encode(strm, c, t) \ + (t = mz_stream_pkcrypt_decrypt_byte(strm), mz_stream_pkcrypt_update_keys(strm, (uint8_t)c), (uint8_t)(t ^ (c))) + +/***************************************************************************/ + +static uint8_t mz_stream_pkcrypt_decrypt_byte(void *stream) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an */ + /* unpredictable manner on 16-bit systems; not a problem */ + /* with any known compiler so far, though. */ + + temp = pkcrypt->keys[2] | 2; + return (uint8_t)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +static uint8_t mz_stream_pkcrypt_update_keys(void *stream, uint8_t c) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + uint8_t buf = c; + + pkcrypt->keys[0] = (uint32_t)~mz_crypt_crc32_update(~pkcrypt->keys[0], &buf, 1); + + pkcrypt->keys[1] += pkcrypt->keys[0] & 0xff; + pkcrypt->keys[1] *= 134775813L; + pkcrypt->keys[1] += 1; + + buf = (uint8_t)(pkcrypt->keys[1] >> 24); + pkcrypt->keys[2] = (uint32_t)~mz_crypt_crc32_update(~pkcrypt->keys[2], &buf, 1); + + return (uint8_t)c; +} + +static void mz_stream_pkcrypt_init_keys(void *stream, const char *password) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + + pkcrypt->keys[0] = 305419896L; + pkcrypt->keys[1] = 591751049L; + pkcrypt->keys[2] = 878082192L; + + while (*password != 0) { + mz_stream_pkcrypt_update_keys(stream, (uint8_t)*password); + password += 1; + } +} + +/***************************************************************************/ + +int32_t mz_stream_pkcrypt_open(void *stream, const char *path, int32_t mode) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + uint16_t t = 0; + int16_t i = 0; + uint8_t verify1 = 0; + uint8_t verify2 = 0; + uint8_t header[MZ_PKCRYPT_HEADER_SIZE]; + const char *password = path; + + pkcrypt->total_in = 0; + pkcrypt->total_out = 0; + pkcrypt->initialized = 0; + + if (mz_stream_is_open(pkcrypt->stream.base) != MZ_OK) + return MZ_OPEN_ERROR; + + if (!password) + password = pkcrypt->password; + if (!password) + return MZ_PARAM_ERROR; + + mz_stream_pkcrypt_init_keys(stream, password); + + if (mode & MZ_OPEN_MODE_WRITE) { + /* First generate RAND_HEAD_LEN - 2 random bytes. */ + mz_crypt_rand(header, MZ_PKCRYPT_HEADER_SIZE - 2); + + /* Encrypt random header (last two bytes is high word of crc) */ + for (i = 0; i < MZ_PKCRYPT_HEADER_SIZE - 2; i++) + header[i] = mz_stream_pkcrypt_encode(stream, header[i], t); + + header[i++] = mz_stream_pkcrypt_encode(stream, pkcrypt->verify1, t); + header[i++] = mz_stream_pkcrypt_encode(stream, pkcrypt->verify2, t); + + if (mz_stream_write(pkcrypt->stream.base, header, sizeof(header)) != sizeof(header)) + return MZ_WRITE_ERROR; + + pkcrypt->total_out += MZ_PKCRYPT_HEADER_SIZE; + } else if (mode & MZ_OPEN_MODE_READ) { + if (mz_stream_read(pkcrypt->stream.base, header, sizeof(header)) != sizeof(header)) + return MZ_READ_ERROR; + + for (i = 0; i < MZ_PKCRYPT_HEADER_SIZE - 2; i++) + header[i] = mz_stream_pkcrypt_decode(stream, header[i]); + + verify1 = mz_stream_pkcrypt_decode(stream, header[i++]); + verify2 = mz_stream_pkcrypt_decode(stream, header[i++]); + + /* PKZIP 2.0 and higher use 1 byte check, older versions used 2 byte check. + See app note section 6.1.6. */ + if (verify2 != pkcrypt->verify2) + return MZ_PASSWORD_ERROR; + if (pkcrypt->verify_version < 2) { + if (verify1 != pkcrypt->verify1) + return MZ_PASSWORD_ERROR; + } + + pkcrypt->total_in += MZ_PKCRYPT_HEADER_SIZE; + } + + pkcrypt->initialized = 1; + return MZ_OK; +} + +int32_t mz_stream_pkcrypt_is_open(void *stream) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + if (!pkcrypt->initialized) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +int32_t mz_stream_pkcrypt_read(void *stream, void *buf, int32_t size) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + uint8_t *buf_ptr = (uint8_t *)buf; + int32_t bytes_to_read = size; + int32_t read = 0; + int32_t i = 0; + + if ((int64_t)bytes_to_read > (pkcrypt->max_total_in - pkcrypt->total_in)) + bytes_to_read = (int32_t)(pkcrypt->max_total_in - pkcrypt->total_in); + + read = mz_stream_read(pkcrypt->stream.base, buf, bytes_to_read); + + for (i = 0; i < read; i++) + buf_ptr[i] = mz_stream_pkcrypt_decode(stream, buf_ptr[i]); + + if (read > 0) + pkcrypt->total_in += read; + + return read; +} + +int32_t mz_stream_pkcrypt_write(void *stream, const void *buf, int32_t size) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + const uint8_t *buf_ptr = (const uint8_t *)buf; + int32_t bytes_to_write = sizeof(pkcrypt->buffer); + int32_t total_written = 0; + int32_t written = 0; + int32_t i = 0; + uint16_t t = 0; + + if (size < 0) + return MZ_PARAM_ERROR; + + do { + if (bytes_to_write > (size - total_written)) + bytes_to_write = (size - total_written); + + for (i = 0; i < bytes_to_write; i += 1) { + pkcrypt->buffer[i] = mz_stream_pkcrypt_encode(stream, *buf_ptr, t); + buf_ptr += 1; + } + + written = mz_stream_write(pkcrypt->stream.base, pkcrypt->buffer, bytes_to_write); + if (written < 0) + return written; + + total_written += written; + } while (total_written < size && written > 0); + + pkcrypt->total_out += total_written; + return total_written; +} + +int64_t mz_stream_pkcrypt_tell(void *stream) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + return mz_stream_tell(pkcrypt->stream.base); +} + +int32_t mz_stream_pkcrypt_seek(void *stream, int64_t offset, int32_t origin) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + return mz_stream_seek(pkcrypt->stream.base, offset, origin); +} + +int32_t mz_stream_pkcrypt_close(void *stream) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + pkcrypt->initialized = 0; + return MZ_OK; +} + +int32_t mz_stream_pkcrypt_error(void *stream) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + return pkcrypt->error; +} + +void mz_stream_pkcrypt_set_password(void *stream, const char *password) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + pkcrypt->password = password; +} + +void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2, uint16_t version) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + pkcrypt->verify1 = verify1; + pkcrypt->verify2 = verify2; + pkcrypt->verify_version = version; +} + +void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2, uint16_t *version) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + *verify1 = pkcrypt->verify1; + *verify2 = pkcrypt->verify2; + *version = pkcrypt->verify_version; +} + +int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN: + *value = pkcrypt->total_in; + break; + case MZ_STREAM_PROP_TOTAL_OUT: + *value = pkcrypt->total_out; + break; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + *value = pkcrypt->max_total_in; + break; + case MZ_STREAM_PROP_HEADER_SIZE: + *value = MZ_PKCRYPT_HEADER_SIZE; + break; + case MZ_STREAM_PROP_FOOTER_SIZE: + *value = 0; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN_MAX: + pkcrypt->max_total_in = value; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +void *mz_stream_pkcrypt_create(void) { + mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)calloc(1, sizeof(mz_stream_pkcrypt)); + if (pkcrypt) + pkcrypt->stream.vtbl = &mz_stream_pkcrypt_vtbl; + return pkcrypt; +} + +void mz_stream_pkcrypt_delete(void **stream) { + mz_stream_pkcrypt *pkcrypt = NULL; + if (!stream) + return; + pkcrypt = (mz_stream_pkcrypt *)*stream; + free(pkcrypt); + *stream = NULL; +} + +void *mz_stream_pkcrypt_get_interface(void) { + return (void *)&mz_stream_pkcrypt_vtbl; +} diff --git a/thirdparty/minizip/mz_strm_pkcrypt.h b/thirdparty/minizip/mz_strm_pkcrypt.h new file mode 100644 index 000000000..5c4f8d0b2 --- /dev/null +++ b/thirdparty/minizip/mz_strm_pkcrypt.h @@ -0,0 +1,46 @@ +/* mz_strm_pkcrypt.h -- Code for traditional PKWARE encryption + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_PKCRYPT_H +#define MZ_STREAM_PKCRYPT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_pkcrypt_open(void *stream, const char *filename, int32_t mode); +int32_t mz_stream_pkcrypt_is_open(void *stream); +int32_t mz_stream_pkcrypt_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_pkcrypt_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_pkcrypt_tell(void *stream); +int32_t mz_stream_pkcrypt_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_pkcrypt_close(void *stream); +int32_t mz_stream_pkcrypt_error(void *stream); + +void mz_stream_pkcrypt_set_password(void *stream, const char *password); +void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2, uint16_t version); +void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2, uint16_t *version); +int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value); +int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value); + +void *mz_stream_pkcrypt_create(void); +void mz_stream_pkcrypt_delete(void **stream); + +void *mz_stream_pkcrypt_get_interface(void); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_ppmd.c b/thirdparty/minizip/mz_strm_ppmd.c new file mode 100644 index 000000000..4a355ee45 --- /dev/null +++ b/thirdparty/minizip/mz_strm_ppmd.c @@ -0,0 +1,490 @@ +/* mz_strm_ppmd.c -- Stream for PPMd compress/decompress + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include + +#include "mz.h" +#include "mz_strm.h" +#include "mz_strm_ppmd.h" + +#include "C/Ppmd8.h" +#include "C/7zTypes.h" + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_ppmd_vtbl = { + mz_stream_ppmd_open, mz_stream_ppmd_is_open, mz_stream_ppmd_read, mz_stream_ppmd_write, + mz_stream_ppmd_tell, mz_stream_ppmd_seek, mz_stream_ppmd_close, mz_stream_ppmd_error, + mz_stream_ppmd_create, mz_stream_ppmd_delete, mz_stream_ppmd_get_prop_int64, mz_stream_ppmd_set_prop_int64}; + +/***************************************************************************/ + +#define PPMD_PRESET_DEFAULT 9 // Should match default in 7-Zip + +// Return values from Ppmd8_DecodeSymbol +#define PPMD_RESULT_EOF (-1) +#define PPMD_RESULT_ERROR (-2) + +/***************************************************************************/ + +typedef struct mz_in_buffer_s { + const void *src; + size_t size; + size_t pos; +} mz_in_buffer; + +typedef struct mz_out_buffer_s { + void *dst; + size_t size; + size_t pos; +} mz_out_buffer; + +typedef struct mz_ppmd_info_s { + /* hold CPpmd8 or CPpmd7 struct pointer */ + void *cPpmd; + void *rc; + mz_in_buffer *in; + mz_out_buffer *out; + int max_length; + int result; + void *t; +} mz_ppmd_info; + +typedef struct { + /* Inherits from IByteIn */ + Byte (*read)(void *p); + mz_in_buffer *in_buffer; + void *t; +} mz_buffer_reader; + +typedef struct { + /* Inherits from IByteOut */ + void (*write)(void *p, Byte b); + mz_out_buffer *out_buffer; + mz_ppmd_info *t; +} mz_buffer_writer; + +typedef struct mz_stream_ppmd_s { + mz_stream stream; + CPpmd8 ppmd8; + uint8_t buffer[INT16_MAX]; + int64_t total_in; + int64_t total_out; + int64_t max_total_in; + int32_t mode; + int32_t error; + int8_t initialized; + ISzAlloc allocator; + + // Write specific + mz_buffer_writer writer; + mz_out_buffer out; + int32_t preset; // PPMD uses the term level for this + + // Read Specific + mz_buffer_reader reader; + mz_in_buffer in; + int8_t end_stream; +} mz_stream_ppmd; + +/***************************************************************************/ + +/* malloc wrapper for PPMD library */ +static void *mz_ppmd_alloc_func(const ISzAlloc *p, size_t size) { + MZ_UNUSED(p); + return malloc(size); +} + +/* free wrapper for PPMD library */ +static void mz_ppmd_free_func(const ISzAlloc *p, void *address) { + MZ_UNUSED(p); + free(address); +} + +#ifndef MZ_ZIP_NO_COMPRESSION + +static void writer(void *p, Byte b) { + mz_buffer_writer *buffer_writer = (mz_buffer_writer *)p; + if (buffer_writer->out_buffer->size == buffer_writer->out_buffer->pos) { + return; + } + *((Byte *)buffer_writer->out_buffer->dst + buffer_writer->out_buffer->pos++) = b; +} + +static int32_t mz_stream_ppmd_flush(void *stream) { + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream; + + if (ppmd->out.pos) { + if (mz_stream_write(ppmd->stream.base, ppmd->out.dst, ppmd->out.pos) != ppmd->out.pos) + return MZ_WRITE_ERROR; + ppmd->total_out += ppmd->out.pos; + ppmd->out.pos = 0; + } + + return MZ_OK; +} + +static void mz_setup_buffered_writer(mz_stream_ppmd *ppmd) { + ppmd->out.dst = ppmd->buffer; + ppmd->out.size = sizeof(ppmd->buffer); // INT16_MAX; + ppmd->out.pos = 0; + + ppmd->writer.write = writer; + ppmd->writer.out_buffer = &ppmd->out; + ppmd->ppmd8.Stream.Out = (IByteOut *)&ppmd->writer; +} +#endif + +#ifndef MZ_ZIP_NO_DECOMPRESSION + +static Byte reader(void *p) { + mz_buffer_reader *buffer_reader = (mz_buffer_reader *)p; + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)buffer_reader->t; + uint8_t b; + int32_t status; + + if (ppmd->max_total_in > 0 && ppmd->total_in >= ppmd->max_total_in) { + ppmd->error = MZ_STREAM_ERROR; + return 0; + } + + if ((status = mz_stream_read_uint8((mz_stream_ppmd *)ppmd->stream.base, &b)) != MZ_OK) { + ppmd->error = status; + b = 0; + } else + ++ppmd->total_in; + + return (Byte)b; +} + +static void mz_setup_buffered_reader(mz_stream_ppmd *ppmd) { + ppmd->in.src = ppmd->buffer; + ppmd->in.size = sizeof(ppmd->buffer); // INT16_MAX; + ppmd->in.pos = 0; + + ppmd->reader.read = reader; + ppmd->reader.in_buffer = &ppmd->in; + ppmd->ppmd8.Stream.In = (IByteIn *)&ppmd->reader; + + ppmd->reader.t = ppmd; +} + +#endif + +int32_t mz_stream_ppmd_open(void *stream, const char *path, int32_t mode) { + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream; + + MZ_UNUSED(path); + + Ppmd8_Construct(&ppmd->ppmd8); + + if (mode & MZ_OPEN_MODE_WRITE) { +#ifdef MZ_ZIP_NO_COMPRESSION + MZ_UNUSED(stream); + return MZ_SUPPORT_ERROR; +#else + /* PPMD8_MIN_ORDER (= 2) <= order <= PPMD8_MAX_ORDER (= 16) + * 2MB (= 2^ 1) <= memSize <= 128MB (= 2^ 7) (M = 2^ 20) + * restor = 0 (PPMD8_RESTORE_METHOD_RESTART), + * 1 (PPMD8_RESTORE_METHOD_CUT_OFF) + * + * Currently using 7-Zip-compatible values: + * order = 3 + level + * memory size = 2^ (level- 1) (MB) (level 9 treated as level 8.) + * restoration method = 0 for level <= 6, 1 for level >= 7. + * + */ + + /* PPMd parameters. */ + unsigned order = ppmd->preset; /* 2, 3, ..., 16. */ + uint32_t mem_size; + unsigned restor; + uint16_t ppmd_param_word; + + if (order < PPMD8_MIN_ORDER || order > PPMD8_MAX_ORDER) + return MZ_OPEN_ERROR; + + mz_setup_buffered_writer(ppmd); + + mem_size = 1 << ((order < 8 ? order : 8) - 1); /* 2MB, 4MB, ..., 128MB. */ + + restor = (order <= 6 ? 0 : 1); + + mem_size <<= 20; /* Convert B to MB. */ + + if (!Ppmd8_Alloc(&ppmd->ppmd8, mem_size, &ppmd->allocator)) { + return MZ_MEM_ERROR; + } + + Ppmd8_Init_RangeEnc(&ppmd->ppmd8); + Ppmd8_Init(&ppmd->ppmd8, order, restor); + + /* wPPMd = (Model order - 1) + + * ((Sub-allocator size - 1) << 4) + + * (Model restoration method << 12) + * + * 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + * Mdl_Res_Mth ___Sub-allocator_size-1 Mdl_Order-1 + */ + + /* Form the PPMd properties word. Put out the bytes. */ + ppmd_param_word = ((order - 1) & 0xf) + ((((mem_size >> 20) - 1) & 0xff) << 4) + ((restor & 0xf) << 12); + + // write header bytes directly to output buffer, bypassing the compression code + // These bytes will be included in the compressed size stored in the zip metadata. + + ((uint8_t *)ppmd->out.dst)[0] = (uint8_t)(ppmd_param_word & 0xff); + ((uint8_t *)ppmd->out.dst)[1] = (uint8_t)(ppmd_param_word >> 8); + ppmd->out.pos += 2; + mz_stream_ppmd_flush(ppmd); +#endif + } else if (mode & MZ_OPEN_MODE_READ) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + MZ_UNUSED(stream); + return MZ_SUPPORT_ERROR; +#else + + uint8_t ppmd_props[2]; /* PPMd properties. */ + uint16_t ppmd_prop_word; /* PPMd properties. */ + + /* Initialize the 7-Zip I/O structure. */ + mz_setup_buffered_reader(ppmd); + + /* Read & parse the 2 PPMD header bytes into a 16-bit word */ + if (mz_stream_read_uint8(ppmd->stream.base, &ppmd_props[0]) != MZ_OK || + mz_stream_read_uint8(ppmd->stream.base, &ppmd_props[1]) != MZ_OK) + return MZ_STREAM_ERROR; + ppmd_prop_word = ppmd_props[0] | (ppmd_props[1] << 8); + ppmd->total_in += 2; + + /* wPPMd = (Model order - 1) + + * ((Sub-allocator size - 1) << 4) + + * (Model restoration method << 12) + * + * 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 + * Mdl_Res_Mth ___Sub-allocator_size-1 Mdl_Order-1 + */ + unsigned order = (ppmd_prop_word & 0xf) + 1; + uint32_t mem_size = ((ppmd_prop_word >> 4) & 0xff) + 1; + unsigned restor = (ppmd_prop_word >> 12); + + /* Convert archive MB value into raw byte value. */ + mem_size <<= 20; + + if ((order < PPMD8_MIN_ORDER) || (order > PPMD8_MAX_ORDER)) + return MZ_STREAM_ERROR; + + if (!Ppmd8_Alloc(&ppmd->ppmd8, mem_size, &ppmd->allocator)) + return MZ_STREAM_ERROR; + + if (!Ppmd8_Init_RangeDec(&ppmd->ppmd8)) + return MZ_STREAM_ERROR; + + Ppmd8_Init(&ppmd->ppmd8, order, restor); +#endif + } + + ppmd->initialized = 1; + ppmd->mode = mode; + + return MZ_OK; +} + +int32_t mz_stream_ppmd_is_open(void *stream) { + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream; + if (ppmd->initialized != 1) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +int32_t mz_stream_ppmd_read(void *stream, void *buf, int32_t size) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + MZ_UNUSED(stream); + MZ_UNUSED(buf); + MZ_UNUSED(size); + return MZ_SUPPORT_ERROR; +#else + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream; + uint8_t *next_out = buf; + int32_t avail_out; + int64_t start_in = ppmd->total_in; + int64_t avail_in = (ppmd->max_total_in > 0 ? ppmd->max_total_in : INT64_MAX) - start_in; + int sym = 0; + int32_t written = 0; + + if (ppmd->end_stream) + return MZ_OK; + + /* Decode input to fill the output buffer. */ + for (avail_out = size; avail_out > 0 && avail_in > (ppmd->total_in - start_in); avail_out--) { + sym = Ppmd8_DecodeSymbol(&ppmd->ppmd8); + + /* There are two ways to terminate the loop early: + 1. Ppmd8_DecodeSymbol returns a negative number to flag EOF or stream error. + 2. ppmd->error gets set to true here when the call to mz_stream_read_uint8 + in reader() does not return MZ_OK. + */ + if (sym < 0 || ppmd->error) + break; + + *(next_out++) = sym; + ++written; + } + + // sym contains the return code from Ppmd8_DecodeSymbol + if (sym == PPMD_RESULT_EOF) { + ppmd->end_stream = 1; + + // Drop through and return written bytes + } else if (sym == PPMD_RESULT_ERROR) { + /* Insufficient input data. */ + return MZ_STREAM_ERROR; + } else if (ppmd->error) { + /* Invalid end of input data */ + return ppmd->error; + } + + ppmd->total_out += written; + return written; +#endif +} + +int32_t mz_stream_ppmd_write(void *stream, const void *buf, int32_t size) { +#ifdef MZ_ZIP_NO_COMPRESSION + MZ_UNUSED(stream); + MZ_UNUSED(buf); + MZ_UNUSED(size); + return MZ_SUPPORT_ERROR; +#else + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream; + const uint8_t *buf_ptr = (const uint8_t *)buf; + int32_t bytes_written = 0; + + mz_setup_buffered_writer(ppmd); + for (bytes_written = 0; bytes_written < size; bytes_written++) { + if (ppmd->out.pos == ppmd->out.size) { + if (mz_stream_ppmd_flush(ppmd) != MZ_OK) + return MZ_WRITE_ERROR; + } + + Ppmd8_EncodeSymbol(&ppmd->ppmd8, buf_ptr[bytes_written]); + } + ppmd->total_in += size; + + if (mz_stream_ppmd_flush(stream) != MZ_OK) + return MZ_WRITE_ERROR; + + return size; +#endif +} + +int64_t mz_stream_ppmd_tell(void *stream) { + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream; + return ppmd->total_in; +} + +int32_t mz_stream_ppmd_seek(void *stream, int64_t offset, int32_t origin) { + MZ_UNUSED(stream); + MZ_UNUSED(offset); + MZ_UNUSED(origin); + + return MZ_SEEK_ERROR; +} + +int32_t mz_stream_ppmd_close(void *stream) { + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream; + +#ifndef MZ_ZIP_NO_COMPRESSION + if (ppmd->mode & MZ_OPEN_MODE_WRITE) { + mz_setup_buffered_writer(ppmd); + + /* Encode end marker */ + Ppmd8_EncodeSymbol(&ppmd->ppmd8, -1); + + Ppmd8_Flush_RangeEnc(&ppmd->ppmd8); + + /* Flush any remaining buffered output */ + mz_stream_ppmd_flush(stream); + } +#endif + + Ppmd8_Free(&ppmd->ppmd8, &ppmd->allocator); + + ppmd->initialized = 0; + + return MZ_OK; +} + +int32_t mz_stream_ppmd_error(void *stream) { + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream; + return ppmd->error; +} + +int32_t mz_stream_ppmd_get_prop_int64(void *stream, int32_t prop, int64_t *value) { + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream; + + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN: + *value = ppmd->total_in; + return MZ_OK; + case MZ_STREAM_PROP_TOTAL_OUT: + *value = ppmd->total_out; + return MZ_OK; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + *value = ppmd->max_total_in; + return MZ_OK; + } + + return MZ_PARAM_ERROR; +} + +int32_t mz_stream_ppmd_set_prop_int64(void *stream, int32_t prop, int64_t value) { + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)stream; + + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN_MAX: + ppmd->max_total_in = value; + return MZ_OK; + case MZ_STREAM_PROP_COMPRESS_LEVEL: + if (value == MZ_COMPRESS_LEVEL_DEFAULT) + ppmd->preset = PPMD_PRESET_DEFAULT; + else + ppmd->preset = (int16_t)value; + return MZ_OK; + } + + return MZ_PARAM_ERROR; +} + +void *mz_stream_ppmd_create(void) { + mz_stream_ppmd *ppmd = (mz_stream_ppmd *)calloc(1, sizeof(mz_stream_ppmd)); + if (ppmd) { + ppmd->stream.vtbl = &mz_stream_ppmd_vtbl; + ppmd->allocator.Alloc = mz_ppmd_alloc_func; + ppmd->allocator.Free = mz_ppmd_free_func; + ppmd->preset = PPMD_PRESET_DEFAULT; + } + return ppmd; +} + +void mz_stream_ppmd_delete(void **stream) { + mz_stream_ppmd *ppmd = NULL; + if (!stream) + return; + ppmd = (mz_stream_ppmd *)*stream; + free(ppmd); + *stream = NULL; +} + +void *mz_stream_ppmd_get_interface(void) { + return (void *)&mz_stream_ppmd_vtbl; +} + +/***************************************************************************/ diff --git a/thirdparty/minizip/mz_strm_ppmd.h b/thirdparty/minizip/mz_strm_ppmd.h new file mode 100644 index 000000000..cf905e4b4 --- /dev/null +++ b/thirdparty/minizip/mz_strm_ppmd.h @@ -0,0 +1,43 @@ +/* mz_strm_ppmd.h -- Stream for PPMd compress/decompress + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_PPMD_H +#define MZ_STREAM_PPMD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_ppmd_open(void *stream, const char *filename, int32_t mode); +int32_t mz_stream_ppmd_is_open(void *stream); +int32_t mz_stream_ppmd_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_ppmd_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_ppmd_tell(void *stream); +int32_t mz_stream_ppmd_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_ppmd_close(void *stream); +int32_t mz_stream_ppmd_error(void *stream); + +int32_t mz_stream_ppmd_get_prop_int64(void *stream, int32_t prop, int64_t *value); +int32_t mz_stream_ppmd_set_prop_int64(void *stream, int32_t prop, int64_t value); + +void *mz_stream_ppmd_create(void); +void mz_stream_ppmd_delete(void **stream); + +void *mz_stream_ppmd_get_interface(void); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_split.c b/thirdparty/minizip/mz_strm_split.c new file mode 100644 index 000000000..417de08e5 --- /dev/null +++ b/thirdparty/minizip/mz_strm_split.c @@ -0,0 +1,416 @@ +/* mz_strm_split.c -- Stream for split files + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_os.h" +#include "mz_strm.h" +#include "mz_strm_split.h" + +#include /* snprintf */ +#include + +#if defined(_MSC_VER) && (_MSC_VER < 1900) +# define snprintf _snprintf +#endif + +/***************************************************************************/ + +#define MZ_ZIP_MAGIC_DISKHEADER (0x08074b50) + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_split_vtbl = { + mz_stream_split_open, mz_stream_split_is_open, mz_stream_split_read, mz_stream_split_write, + mz_stream_split_tell, mz_stream_split_seek, mz_stream_split_close, mz_stream_split_error, + mz_stream_split_create, mz_stream_split_delete, mz_stream_split_get_prop_int64, mz_stream_split_set_prop_int64}; + +/***************************************************************************/ + +typedef struct mz_stream_split_s { + mz_stream stream; + int64_t disk_size; + int64_t total_in; + int64_t total_in_disk; + int64_t total_out; + int64_t total_out_disk; + int32_t is_open; + int32_t mode; + char *path_cd; + char *path_disk; + uint32_t path_disk_size; + int32_t number_disk; + int64_t current_disk_size; + int32_t current_disk; + int32_t reached_end; +} mz_stream_split; + +/***************************************************************************/ + +#if 0 +# define mz_stream_split_print printf +#else +# define mz_stream_split_print(fmt, ...) +#endif + +/***************************************************************************/ + +static int32_t mz_stream_split_open_disk(void *stream, int32_t number_disk) { + mz_stream_split *split = (mz_stream_split *)stream; + uint32_t magic = 0; + int64_t position = 0; + int32_t i = 0; + int32_t err = MZ_OK; + int16_t disk_part = 0; + + /* Check if we are reading or writing a disk part or the cd disk */ + if (number_disk >= 0) { + if ((split->mode & MZ_OPEN_MODE_WRITE) == 0) + disk_part = MZ_OPEN_MODE_READ; + else if (split->disk_size > 0) + disk_part = MZ_OPEN_MODE_WRITE; + } + + /* Construct disk path */ + if (disk_part > 0) { + for (i = (int32_t)strlen(split->path_disk) - 1; i >= 0; i -= 1) { + if (split->path_disk[i] != '.') + continue; + snprintf(&split->path_disk[i], split->path_disk_size - (uint32_t)i, ".z%02" PRId32, number_disk + 1); + break; + } + } else { + strncpy(split->path_disk, split->path_cd, split->path_disk_size - 1); + split->path_disk[split->path_disk_size - 1] = 0; + } + + mz_stream_split_print("Split - Goto disk - %s (disk %" PRId32 ")\n", split->path_disk, number_disk); + + /* If disk part doesn't exist during reading then return MZ_EXIST_ERROR */ + if (disk_part == MZ_OPEN_MODE_READ) { + if (strcmp(split->path_disk, split->path_cd) == 0) { + err = MZ_EXIST_ERROR; + } else { + err = mz_os_file_exists(split->path_disk); + } + } + + if (err == MZ_OK) + err = mz_stream_open(split->stream.base, split->path_disk, split->mode); + + if (err == MZ_OK) { + split->total_in_disk = 0; + split->total_out_disk = 0; + split->current_disk = number_disk; + + if (split->mode & MZ_OPEN_MODE_WRITE) { + if ((split->current_disk == 0) && (split->disk_size > 0)) { + err = mz_stream_write_uint32(split->stream.base, MZ_ZIP_MAGIC_DISKHEADER); + + split->total_out_disk += 4; + split->total_out += split->total_out_disk; + } + } else if (split->mode & MZ_OPEN_MODE_READ) { + if (split->current_disk == 0) { + err = mz_stream_read_uint32(split->stream.base, &magic); + if (magic != MZ_ZIP_MAGIC_DISKHEADER) + err = MZ_FORMAT_ERROR; + } + } + } + + if (err == MZ_OK) { + /* Get the size of the current disk we are on */ + position = mz_stream_tell(split->stream.base); + mz_stream_seek(split->stream.base, 0, MZ_SEEK_END); + split->current_disk_size = mz_stream_tell(split->stream.base); + mz_stream_seek(split->stream.base, position, MZ_SEEK_SET); + + split->is_open = 1; + } + + return err; +} + +static int32_t mz_stream_split_close_disk(void *stream) { + mz_stream_split *split = (mz_stream_split *)stream; + + if (mz_stream_is_open(split->stream.base) != MZ_OK) + return MZ_OK; + + mz_stream_split_print("Split - Close disk\n"); + return mz_stream_close(split->stream.base); +} + +static int32_t mz_stream_split_goto_disk(void *stream, int32_t number_disk) { + mz_stream_split *split = (mz_stream_split *)stream; + int32_t err = MZ_OK; + int32_t err_is_open = MZ_OK; + + err_is_open = mz_stream_is_open(split->stream.base); + + if ((split->disk_size == 0) && (split->mode & MZ_OPEN_MODE_WRITE)) { + if (err_is_open != MZ_OK) + err = mz_stream_split_open_disk(stream, number_disk); + } else if ((number_disk != split->current_disk) || (err_is_open != MZ_OK)) { + err = mz_stream_split_close_disk(stream); + if (err == MZ_OK) { + err = mz_stream_split_open_disk(stream, number_disk); + if (err == MZ_OK) + split->number_disk = number_disk; + } + } + + return err; +} + +int32_t mz_stream_split_open(void *stream, const char *path, int32_t mode) { + mz_stream_split *split = (mz_stream_split *)stream; + int32_t number_disk = 0; + + split->mode = mode; + split->path_cd = strdup(path); + + if (!split->path_cd) + return MZ_MEM_ERROR; + + mz_stream_split_print("Split - Open - %s (disk %" PRId32 ")\n", split->path_cd, number_disk); + + split->path_disk_size = (uint32_t)strlen(path) + 10; + split->path_disk = (char *)malloc(split->path_disk_size); + + if (!split->path_disk) { + free(split->path_cd); + return MZ_MEM_ERROR; + } + + strncpy(split->path_disk, path, split->path_disk_size - 1); + split->path_disk[split->path_disk_size - 1] = 0; + + if ((mode & MZ_OPEN_MODE_WRITE) && ((mode & MZ_OPEN_MODE_APPEND) == 0)) { + number_disk = 0; + split->current_disk = -1; + } else { + number_disk = -1; + split->current_disk = 0; + } + + return mz_stream_split_goto_disk(stream, number_disk); +} + +int32_t mz_stream_split_is_open(void *stream) { + mz_stream_split *split = (mz_stream_split *)stream; + if (split->is_open != 1) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +int32_t mz_stream_split_read(void *stream, void *buf, int32_t size) { + mz_stream_split *split = (mz_stream_split *)stream; + int32_t bytes_left = size; + int32_t read = 0; + int32_t err = MZ_OK; + uint8_t *buf_ptr = (uint8_t *)buf; + + err = mz_stream_split_goto_disk(stream, split->number_disk); + if (err != MZ_OK) + return err; + + while (bytes_left > 0) { + read = mz_stream_read(split->stream.base, buf_ptr, bytes_left); + + mz_stream_split_print("Split - Read disk - %" PRId32 "\n", read); + + if (read < 0) + return read; + if (read == 0) { + if (split->current_disk < 0) /* No more disks to goto */ + break; + if (size != bytes_left) /* Report read from previous disk before switching */ + break; + err = mz_stream_split_goto_disk(stream, split->current_disk + 1); + if (err == MZ_EXIST_ERROR) + split->current_disk = -1; + if (err != MZ_OK) + return err; + } + + bytes_left -= read; + buf_ptr += read; + split->total_in += read; + split->total_in_disk += read; + } + return size - bytes_left; +} + +int32_t mz_stream_split_write(void *stream, const void *buf, int32_t size) { + mz_stream_split *split = (mz_stream_split *)stream; + int64_t position = 0; + int32_t written = 0; + int32_t bytes_left = size; + int32_t bytes_to_write = 0; + int64_t bytes_avail = 0; + int32_t number_disk = -1; + int32_t err = MZ_OK; + const uint8_t *buf_ptr = (const uint8_t *)buf; + + position = mz_stream_tell(split->stream.base); + + while (bytes_left > 0) { + bytes_to_write = bytes_left; + + if (split->disk_size > 0) { + if ((split->total_out_disk == split->disk_size && split->total_out > 0) || + (split->number_disk == -1 && split->number_disk != split->current_disk)) { + if (split->number_disk != -1) + number_disk = split->current_disk + 1; + + err = mz_stream_split_goto_disk(stream, number_disk); + if (err != MZ_OK) + return err; + + position = 0; + } + + if (split->number_disk != -1) { + bytes_avail = split->disk_size - split->total_out_disk; + if (bytes_to_write > bytes_avail) + bytes_to_write = bytes_avail; + } + } + + written = mz_stream_write(split->stream.base, buf_ptr, bytes_to_write); + if (written != bytes_to_write) + return MZ_WRITE_ERROR; + + mz_stream_split_print("Split - Write disk - %" PRId32 "\n", written); + + bytes_left -= written; + buf_ptr += written; + + split->total_out += written; + split->total_out_disk += written; + + position += written; + if (position > split->current_disk_size) + split->current_disk_size = position; + } + + return size - bytes_left; +} + +int64_t mz_stream_split_tell(void *stream) { + mz_stream_split *split = (mz_stream_split *)stream; + int32_t err = MZ_OK; + err = mz_stream_split_goto_disk(stream, split->number_disk); + if (err != MZ_OK) + return err; + return mz_stream_tell(split->stream.base); +} + +int32_t mz_stream_split_seek(void *stream, int64_t offset, int32_t origin) { + mz_stream_split *split = (mz_stream_split *)stream; + int64_t disk_left = 0; + int64_t position = 0; + int32_t err = MZ_OK; + + err = mz_stream_split_goto_disk(stream, split->number_disk); + + if (err != MZ_OK) + return err; + + mz_stream_split_print("Split - Seek disk - %" PRId64 " (origin %" PRId32 ")\n", offset, origin); + + if ((origin == MZ_SEEK_CUR) && (split->number_disk != -1)) { + position = mz_stream_tell(split->stream.base); + disk_left = split->current_disk_size - position; + + while (offset > disk_left) { + err = mz_stream_split_goto_disk(stream, split->current_disk + 1); + if (err != MZ_OK) + return err; + + offset -= disk_left; + disk_left = split->current_disk_size; + } + } + + return mz_stream_seek(split->stream.base, offset, origin); +} + +int32_t mz_stream_split_close(void *stream) { + mz_stream_split *split = (mz_stream_split *)stream; + int32_t err = MZ_OK; + + err = mz_stream_split_close_disk(stream); + split->is_open = 0; + return err; +} + +int32_t mz_stream_split_error(void *stream) { + mz_stream_split *split = (mz_stream_split *)stream; + return mz_stream_error(split->stream.base); +} + +int32_t mz_stream_split_get_prop_int64(void *stream, int32_t prop, int64_t *value) { + mz_stream_split *split = (mz_stream_split *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_OUT: + *value = split->total_out; + break; + case MZ_STREAM_PROP_DISK_NUMBER: + *value = split->number_disk; + break; + case MZ_STREAM_PROP_DISK_SIZE: + *value = split->disk_size; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +int32_t mz_stream_split_set_prop_int64(void *stream, int32_t prop, int64_t value) { + mz_stream_split *split = (mz_stream_split *)stream; + switch (prop) { + case MZ_STREAM_PROP_DISK_NUMBER: + split->number_disk = (int32_t)value; + break; + case MZ_STREAM_PROP_DISK_SIZE: + split->disk_size = value; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +void *mz_stream_split_create(void) { + mz_stream_split *split = (mz_stream_split *)calloc(1, sizeof(mz_stream_split)); + if (split) + split->stream.vtbl = &mz_stream_split_vtbl; + return split; +} + +void mz_stream_split_delete(void **stream) { + mz_stream_split *split = NULL; + if (!stream) + return; + split = (mz_stream_split *)*stream; + if (split) { + free(split->path_cd); + free(split->path_disk); + free(split); + } + *stream = NULL; +} + +void *mz_stream_split_get_interface(void) { + return (void *)&mz_stream_split_vtbl; +} diff --git a/thirdparty/minizip/mz_strm_split.h b/thirdparty/minizip/mz_strm_split.h new file mode 100644 index 000000000..2877f255b --- /dev/null +++ b/thirdparty/minizip/mz_strm_split.h @@ -0,0 +1,43 @@ +/* mz_strm_split.h -- Stream for split files + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_SPLIT_H +#define MZ_STREAM_SPLIT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_split_open(void *stream, const char *filename, int32_t mode); +int32_t mz_stream_split_is_open(void *stream); +int32_t mz_stream_split_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_split_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_split_tell(void *stream); +int32_t mz_stream_split_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_split_close(void *stream); +int32_t mz_stream_split_error(void *stream); + +int32_t mz_stream_split_get_prop_int64(void *stream, int32_t prop, int64_t *value); +int32_t mz_stream_split_set_prop_int64(void *stream, int32_t prop, int64_t value); + +void *mz_stream_split_create(void); +void mz_stream_split_delete(void **stream); + +void *mz_stream_split_get_interface(void); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_wzaes.c b/thirdparty/minizip/mz_strm_wzaes.c new file mode 100644 index 000000000..a0c9facba --- /dev/null +++ b/thirdparty/minizip/mz_strm_wzaes.c @@ -0,0 +1,355 @@ +/* mz_strm_wzaes.c -- Stream for WinZip AES encryption + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Copyright (C) 1998-2010 Brian Gladman, Worcester, UK + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_crypt.h" +#include "mz_strm.h" +#include "mz_strm_wzaes.h" + +/***************************************************************************/ + +#define MZ_AES_KEY_LENGTH(STRENGTH) (8 * (STRENGTH & 3) + 8) +#define MZ_AES_KEYING_ITERATIONS (1000) +#define MZ_AES_SALT_LENGTH(STRENGTH) (4 * (STRENGTH & 3) + 4) +#define MZ_AES_SALT_LENGTH_MAX (16) +#define MZ_AES_PW_LENGTH_MAX (128) +#define MZ_AES_PW_VERIFY_SIZE (2) +#define MZ_AES_AUTHCODE_SIZE (10) + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_wzaes_vtbl = { + mz_stream_wzaes_open, mz_stream_wzaes_is_open, mz_stream_wzaes_read, mz_stream_wzaes_write, + mz_stream_wzaes_tell, mz_stream_wzaes_seek, mz_stream_wzaes_close, mz_stream_wzaes_error, + mz_stream_wzaes_create, mz_stream_wzaes_delete, mz_stream_wzaes_get_prop_int64, mz_stream_wzaes_set_prop_int64}; + +/***************************************************************************/ + +typedef struct mz_stream_wzaes_s { + mz_stream stream; + int32_t mode; + int32_t error; + int16_t initialized; + uint8_t buffer[UINT16_MAX]; + int64_t total_in; + int64_t max_total_in; + int64_t total_out; + uint8_t strength; + const char *password; + void *aes; + uint32_t crypt_pos; + uint8_t crypt_block[MZ_AES_BLOCK_SIZE]; + void *hmac; + uint8_t nonce[MZ_AES_BLOCK_SIZE]; +} mz_stream_wzaes; + +/***************************************************************************/ + +int32_t mz_stream_wzaes_open(void *stream, const char *path, int32_t mode) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + uint16_t salt_length = 0; + uint16_t password_length = 0; + uint16_t key_length = 0; + uint8_t kbuf[2 * MZ_AES_KEY_LENGTH_MAX + MZ_AES_PW_VERIFY_SIZE]; + uint8_t verify[MZ_AES_PW_VERIFY_SIZE]; + uint8_t verify_expected[MZ_AES_PW_VERIFY_SIZE]; + uint8_t salt_value[MZ_AES_SALT_LENGTH_MAX]; + const char *password = path; + + wzaes->total_in = 0; + wzaes->total_out = 0; + wzaes->initialized = 0; + + if (mz_stream_is_open(wzaes->stream.base) != MZ_OK) + return MZ_OPEN_ERROR; + + if (!password) + password = wzaes->password; + if (!password) + return MZ_PARAM_ERROR; + password_length = (uint16_t)strlen(password); + if (password_length > MZ_AES_PW_LENGTH_MAX) + return MZ_PARAM_ERROR; + + if (wzaes->strength < 1 || wzaes->strength > 3) + return MZ_PARAM_ERROR; + + key_length = MZ_AES_KEY_LENGTH(wzaes->strength); + salt_length = MZ_AES_SALT_LENGTH(wzaes->strength); + + if (mode & MZ_OPEN_MODE_WRITE) { + mz_crypt_rand(salt_value, salt_length); + } else if (mode & MZ_OPEN_MODE_READ) { + if (mz_stream_read(wzaes->stream.base, salt_value, salt_length) != salt_length) + return MZ_READ_ERROR; + } + + /* Derive the encryption and authentication keys and the password verifier */ + mz_crypt_pbkdf2((uint8_t *)password, password_length, salt_value, salt_length, MZ_AES_KEYING_ITERATIONS, kbuf, + 2 * key_length + MZ_AES_PW_VERIFY_SIZE); + + /* Initialize the buffer pos */ + wzaes->crypt_pos = MZ_AES_BLOCK_SIZE; + + /* Use fixed zeroed IV/nonce for CTR mode */ + memset(wzaes->nonce, 0, sizeof(wzaes->nonce)); + + /* Initialize for encryption using key 1 */ + mz_crypt_aes_reset(wzaes->aes); + mz_crypt_aes_set_encrypt_key(wzaes->aes, kbuf, key_length, NULL, 0); + + /* Initialize for authentication using key 2 */ + mz_crypt_hmac_reset(wzaes->hmac); + mz_crypt_hmac_set_algorithm(wzaes->hmac, MZ_HASH_SHA1); + mz_crypt_hmac_init(wzaes->hmac, kbuf + key_length, key_length); + + memcpy(verify, kbuf + (2 * key_length), MZ_AES_PW_VERIFY_SIZE); + + if (mode & MZ_OPEN_MODE_WRITE) { + if (mz_stream_write(wzaes->stream.base, salt_value, salt_length) != salt_length) + return MZ_WRITE_ERROR; + + wzaes->total_out += salt_length; + + if (mz_stream_write(wzaes->stream.base, verify, MZ_AES_PW_VERIFY_SIZE) != MZ_AES_PW_VERIFY_SIZE) + return MZ_WRITE_ERROR; + + wzaes->total_out += MZ_AES_PW_VERIFY_SIZE; + } else if (mode & MZ_OPEN_MODE_READ) { + wzaes->total_in += salt_length; + + if (mz_stream_read(wzaes->stream.base, verify_expected, MZ_AES_PW_VERIFY_SIZE) != MZ_AES_PW_VERIFY_SIZE) + return MZ_READ_ERROR; + + wzaes->total_in += MZ_AES_PW_VERIFY_SIZE; + + if (memcmp(verify_expected, verify, MZ_AES_PW_VERIFY_SIZE) != 0) + return MZ_PASSWORD_ERROR; + } + + wzaes->mode = mode; + wzaes->initialized = 1; + + return MZ_OK; +} + +int32_t mz_stream_wzaes_is_open(void *stream) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + if (!wzaes->initialized) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +static int32_t mz_stream_wzaes_ctr_encrypt(void *stream, uint8_t *buf, int32_t size) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + uint32_t pos = wzaes->crypt_pos; + uint32_t i = 0; + int32_t err = MZ_OK; + + while (i < (uint32_t)size) { + if (pos == MZ_AES_BLOCK_SIZE) { + uint32_t j = 0; + + /* Increment encryption nonce */ + while (j < 8 && !++wzaes->nonce[j]) + j += 1; + + /* Encrypt the nonce using ECB mode to form next xor buffer */ + memcpy(wzaes->crypt_block, wzaes->nonce, MZ_AES_BLOCK_SIZE); + mz_crypt_aes_encrypt(wzaes->aes, NULL, 0, wzaes->crypt_block, sizeof(wzaes->crypt_block)); + pos = 0; + } + + buf[i++] ^= wzaes->crypt_block[pos++]; + } + + wzaes->crypt_pos = pos; + return err; +} + +int32_t mz_stream_wzaes_read(void *stream, void *buf, int32_t size) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + int64_t max_total_in = 0; + int32_t bytes_to_read = size; + int32_t read = 0; + + max_total_in = wzaes->max_total_in - MZ_AES_FOOTER_SIZE; + if ((int64_t)bytes_to_read > (max_total_in - wzaes->total_in)) + bytes_to_read = (int32_t)(max_total_in - wzaes->total_in); + + read = mz_stream_read(wzaes->stream.base, buf, bytes_to_read); + + if (read > 0) { + mz_crypt_hmac_update(wzaes->hmac, (uint8_t *)buf, read); + mz_stream_wzaes_ctr_encrypt(stream, (uint8_t *)buf, read); + + wzaes->total_in += read; + } + + return read; +} + +int32_t mz_stream_wzaes_write(void *stream, const void *buf, int32_t size) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + const uint8_t *buf_ptr = (const uint8_t *)buf; + int32_t bytes_to_write = sizeof(wzaes->buffer); + int32_t total_written = 0; + int32_t written = 0; + + if (size < 0) + return MZ_PARAM_ERROR; + + do { + if (bytes_to_write > (size - total_written)) + bytes_to_write = (size - total_written); + + memcpy(wzaes->buffer, buf_ptr, bytes_to_write); + buf_ptr += bytes_to_write; + + mz_stream_wzaes_ctr_encrypt(stream, (uint8_t *)wzaes->buffer, bytes_to_write); + mz_crypt_hmac_update(wzaes->hmac, wzaes->buffer, bytes_to_write); + + written = mz_stream_write(wzaes->stream.base, wzaes->buffer, bytes_to_write); + if (written < 0) + return written; + + total_written += written; + } while (total_written < size && written > 0); + + wzaes->total_out += total_written; + return total_written; +} + +int64_t mz_stream_wzaes_tell(void *stream) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + return mz_stream_tell(wzaes->stream.base); +} + +int32_t mz_stream_wzaes_seek(void *stream, int64_t offset, int32_t origin) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + return mz_stream_seek(wzaes->stream.base, offset, origin); +} + +int32_t mz_stream_wzaes_close(void *stream) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + uint8_t expected_hash[MZ_AES_AUTHCODE_SIZE]; + uint8_t computed_hash[MZ_HASH_SHA1_SIZE]; + + mz_crypt_hmac_end(wzaes->hmac, computed_hash, sizeof(computed_hash)); + + if (wzaes->mode & MZ_OPEN_MODE_WRITE) { + if (mz_stream_write(wzaes->stream.base, computed_hash, MZ_AES_AUTHCODE_SIZE) != MZ_AES_AUTHCODE_SIZE) + return MZ_WRITE_ERROR; + + wzaes->total_out += MZ_AES_AUTHCODE_SIZE; + } else if (wzaes->mode & MZ_OPEN_MODE_READ) { + if (mz_stream_read(wzaes->stream.base, expected_hash, MZ_AES_AUTHCODE_SIZE) != MZ_AES_AUTHCODE_SIZE) + return MZ_READ_ERROR; + + wzaes->total_in += MZ_AES_AUTHCODE_SIZE; + + /* If entire entry was not read this will fail */ + if (memcmp(computed_hash, expected_hash, MZ_AES_AUTHCODE_SIZE) != 0) + return MZ_CRC_ERROR; + } + + wzaes->initialized = 0; + return MZ_OK; +} + +int32_t mz_stream_wzaes_error(void *stream) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + return wzaes->error; +} + +void mz_stream_wzaes_set_password(void *stream, const char *password) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + wzaes->password = password; +} + +void mz_stream_wzaes_set_strength(void *stream, uint8_t strength) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + wzaes->strength = strength; +} + +int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN: + *value = wzaes->total_in; + break; + case MZ_STREAM_PROP_TOTAL_OUT: + *value = wzaes->total_out; + break; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + *value = wzaes->max_total_in; + break; + case MZ_STREAM_PROP_HEADER_SIZE: + *value = MZ_AES_SALT_LENGTH((int64_t)wzaes->strength) + MZ_AES_PW_VERIFY_SIZE; + break; + case MZ_STREAM_PROP_FOOTER_SIZE: + *value = MZ_AES_AUTHCODE_SIZE; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN_MAX: + wzaes->max_total_in = value; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +void *mz_stream_wzaes_create(void) { + mz_stream_wzaes *wzaes = (mz_stream_wzaes *)calloc(1, sizeof(mz_stream_wzaes)); + if (wzaes) { + wzaes->stream.vtbl = &mz_stream_wzaes_vtbl; + wzaes->strength = MZ_AES_STRENGTH_256; + + wzaes->hmac = mz_crypt_hmac_create(); + if (!wzaes->hmac) { + free(wzaes); + return NULL; + } + wzaes->aes = mz_crypt_aes_create(); + if (!wzaes->aes) { + mz_crypt_hmac_delete(&wzaes->hmac); + free(wzaes); + return NULL; + } + } + return wzaes; +} + +void mz_stream_wzaes_delete(void **stream) { + mz_stream_wzaes *wzaes = NULL; + if (!stream) + return; + wzaes = (mz_stream_wzaes *)*stream; + if (wzaes) { + mz_crypt_aes_delete(&wzaes->aes); + mz_crypt_hmac_delete(&wzaes->hmac); + free(wzaes); + } + *stream = NULL; +} + +void *mz_stream_wzaes_get_interface(void) { + return (void *)&mz_stream_wzaes_vtbl; +} diff --git a/thirdparty/minizip/mz_strm_wzaes.h b/thirdparty/minizip/mz_strm_wzaes.h new file mode 100644 index 000000000..ac206553b --- /dev/null +++ b/thirdparty/minizip/mz_strm_wzaes.h @@ -0,0 +1,46 @@ +/* mz_strm_wzaes.h -- Stream for WinZIP AES encryption + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_WZAES_SHA1_H +#define MZ_STREAM_WZAES_SHA1_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_wzaes_open(void *stream, const char *filename, int32_t mode); +int32_t mz_stream_wzaes_is_open(void *stream); +int32_t mz_stream_wzaes_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_wzaes_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_wzaes_tell(void *stream); +int32_t mz_stream_wzaes_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_wzaes_close(void *stream); +int32_t mz_stream_wzaes_error(void *stream); + +void mz_stream_wzaes_set_password(void *stream, const char *password); +void mz_stream_wzaes_set_strength(void *stream, uint8_t strength); + +int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value); +int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value); + +void *mz_stream_wzaes_create(void); +void mz_stream_wzaes_delete(void **stream); + +void *mz_stream_wzaes_get_interface(void); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_zlib.c b/thirdparty/minizip/mz_strm_zlib.c new file mode 100644 index 000000000..bcd5f30a5 --- /dev/null +++ b/thirdparty/minizip/mz_strm_zlib.c @@ -0,0 +1,378 @@ +/* mz_strm_zlib.c -- Stream for zlib inflate/deflate + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_strm.h" +#include "mz_strm_zlib.h" + +#if !defined(ZLIB_COMPAT) +# include "zlib-ng.h" +#else +# include "zlib.h" +#endif + +/***************************************************************************/ + +#if !defined(ZLIB_COMPAT) +# define ZLIB_PREFIX(x) zng_##x +typedef zng_stream zlib_stream; +#else +# define ZLIB_PREFIX(x) x +typedef z_stream zlib_stream; +#endif + +#if !defined(DEF_MEM_LEVEL) +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_zlib_vtbl = { + mz_stream_zlib_open, mz_stream_zlib_is_open, mz_stream_zlib_read, mz_stream_zlib_write, + mz_stream_zlib_tell, mz_stream_zlib_seek, mz_stream_zlib_close, mz_stream_zlib_error, + mz_stream_zlib_create, mz_stream_zlib_delete, mz_stream_zlib_get_prop_int64, mz_stream_zlib_set_prop_int64}; + +/***************************************************************************/ + +typedef struct mz_stream_zlib_s { + mz_stream stream; + zlib_stream zstream; + uint8_t buffer[INT16_MAX]; + int32_t buffer_len; + int64_t total_in; + int64_t total_out; + int64_t max_total_in; + int8_t initialized; + int16_t level; + int32_t window_bits; + int32_t mode; + int32_t error; +} mz_stream_zlib; + +/***************************************************************************/ + +int32_t mz_stream_zlib_open(void *stream, const char *path, int32_t mode) { + mz_stream_zlib *zlib = (mz_stream_zlib *)stream; + + MZ_UNUSED(path); + + zlib->zstream.data_type = Z_BINARY; + zlib->zstream.zalloc = Z_NULL; + zlib->zstream.zfree = Z_NULL; + zlib->zstream.opaque = Z_NULL; + zlib->zstream.total_in = 0; + zlib->zstream.total_out = 0; + + zlib->total_in = 0; + zlib->total_out = 0; + + if (mode & MZ_OPEN_MODE_WRITE) { +#ifdef MZ_ZIP_NO_COMPRESSION + return MZ_SUPPORT_ERROR; +#else + zlib->zstream.next_out = zlib->buffer; + zlib->zstream.avail_out = sizeof(zlib->buffer); + + zlib->error = ZLIB_PREFIX(deflateInit2)(&zlib->zstream, (int8_t)zlib->level, Z_DEFLATED, zlib->window_bits, + DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); +#endif + } else if (mode & MZ_OPEN_MODE_READ) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + return MZ_SUPPORT_ERROR; +#else + zlib->zstream.next_in = zlib->buffer; + zlib->zstream.avail_in = 0; + + zlib->error = ZLIB_PREFIX(inflateInit2)(&zlib->zstream, zlib->window_bits); +#endif + } + + if (zlib->error != Z_OK) + return MZ_OPEN_ERROR; + + zlib->initialized = 1; + zlib->mode = mode; + return MZ_OK; +} + +int32_t mz_stream_zlib_is_open(void *stream) { + mz_stream_zlib *zlib = (mz_stream_zlib *)stream; + if (zlib->initialized != 1) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +int32_t mz_stream_zlib_read(void *stream, void *buf, int32_t size) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + MZ_UNUSED(stream); + MZ_UNUSED(buf); + MZ_UNUSED(size); + return MZ_SUPPORT_ERROR; +#else + mz_stream_zlib *zlib = (mz_stream_zlib *)stream; + uint64_t total_in_before = 0; + uint64_t total_in_after = 0; + uint64_t total_out_before = 0; + uint64_t total_out_after = 0; + uint32_t total_in = 0; + uint32_t total_out = 0; + uint32_t in_bytes = 0; + uint32_t out_bytes = 0; + int32_t bytes_to_read = sizeof(zlib->buffer); + int32_t read = 0; + int32_t err = Z_OK; + + zlib->zstream.next_out = (Bytef *)buf; + zlib->zstream.avail_out = (uInt)size; + + do { + if (zlib->zstream.avail_in == 0) { + if (zlib->max_total_in > 0) { + if ((int64_t)bytes_to_read > (zlib->max_total_in - zlib->total_in)) + bytes_to_read = (int32_t)(zlib->max_total_in - zlib->total_in); + } + + read = mz_stream_read(zlib->stream.base, zlib->buffer, bytes_to_read); + + if (read < 0) + return read; + + zlib->zstream.next_in = zlib->buffer; + zlib->zstream.avail_in = read; + } + + total_in_before = zlib->zstream.avail_in; + total_out_before = zlib->zstream.total_out; + + err = ZLIB_PREFIX(inflate)(&zlib->zstream, Z_SYNC_FLUSH); + if ((err >= Z_OK) && (zlib->zstream.msg)) { + zlib->error = Z_DATA_ERROR; + break; + } + + total_in_after = zlib->zstream.avail_in; + total_out_after = zlib->zstream.total_out; + + in_bytes = (uint32_t)(total_in_before - total_in_after); + out_bytes = (uint32_t)(total_out_after - total_out_before); + + total_in += in_bytes; + total_out += out_bytes; + + zlib->total_in += in_bytes; + zlib->total_out += out_bytes; + + if (err == Z_STREAM_END) + break; + if (err != Z_OK) { + zlib->error = err; + break; + } + } while (zlib->zstream.avail_out > 0); + + MZ_UNUSED(total_in); + + if (zlib->error != 0) { + /* Zlib errors are compatible with MZ */ + return zlib->error; + } + + return total_out; +#endif +} + +#ifndef MZ_ZIP_NO_COMPRESSION +static int32_t mz_stream_zlib_flush(void *stream) { + mz_stream_zlib *zlib = (mz_stream_zlib *)stream; + if (mz_stream_write(zlib->stream.base, zlib->buffer, zlib->buffer_len) != zlib->buffer_len) + return MZ_WRITE_ERROR; + return MZ_OK; +} + +static int32_t mz_stream_zlib_deflate(void *stream, int flush) { + mz_stream_zlib *zlib = (mz_stream_zlib *)stream; + uint64_t total_out_before = 0; + uint64_t total_out_after = 0; + int32_t out_bytes = 0; + int32_t err = Z_OK; + + do { + if (zlib->zstream.avail_out == 0) { + err = mz_stream_zlib_flush(zlib); + if (err != MZ_OK) + return err; + + zlib->zstream.avail_out = sizeof(zlib->buffer); + zlib->zstream.next_out = zlib->buffer; + + zlib->buffer_len = 0; + } + + total_out_before = zlib->zstream.total_out; + err = ZLIB_PREFIX(deflate)(&zlib->zstream, flush); + total_out_after = zlib->zstream.total_out; + + out_bytes = (uint32_t)(total_out_after - total_out_before); + + zlib->buffer_len += out_bytes; + zlib->total_out += out_bytes; + + if (err == Z_STREAM_END) + break; + if (err != Z_OK) { + zlib->error = err; + return MZ_DATA_ERROR; + } + } while ((zlib->zstream.avail_in > 0) || (flush == Z_FINISH && err == Z_OK)); + + return MZ_OK; +} +#endif + +int32_t mz_stream_zlib_write(void *stream, const void *buf, int32_t size) { +#ifdef MZ_ZIP_NO_COMPRESSION + MZ_UNUSED(stream); + MZ_UNUSED(buf); + MZ_UNUSED(size); + return MZ_SUPPORT_ERROR; +#else + mz_stream_zlib *zlib = (mz_stream_zlib *)stream; + int32_t err = MZ_OK; + + zlib->zstream.next_in = (Bytef *)(intptr_t)buf; + zlib->zstream.avail_in = (uInt)size; + + err = mz_stream_zlib_deflate(stream, Z_NO_FLUSH); + if (err != MZ_OK) { + return err; + } + + zlib->total_in += size; + return size; +#endif +} + +int64_t mz_stream_zlib_tell(void *stream) { + MZ_UNUSED(stream); + + return MZ_TELL_ERROR; +} + +int32_t mz_stream_zlib_seek(void *stream, int64_t offset, int32_t origin) { + MZ_UNUSED(stream); + MZ_UNUSED(offset); + MZ_UNUSED(origin); + + return MZ_SEEK_ERROR; +} + +int32_t mz_stream_zlib_close(void *stream) { + mz_stream_zlib *zlib = (mz_stream_zlib *)stream; + + if (zlib->mode & MZ_OPEN_MODE_WRITE) { +#ifdef MZ_ZIP_NO_COMPRESSION + return MZ_SUPPORT_ERROR; +#else + mz_stream_zlib_deflate(stream, Z_FINISH); + mz_stream_zlib_flush(stream); + + ZLIB_PREFIX(deflateEnd)(&zlib->zstream); +#endif + } else if (zlib->mode & MZ_OPEN_MODE_READ) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + return MZ_SUPPORT_ERROR; +#else + ZLIB_PREFIX(inflateEnd)(&zlib->zstream); +#endif + } + + zlib->initialized = 0; + + if (zlib->error != Z_OK) + return MZ_CLOSE_ERROR; + return MZ_OK; +} + +int32_t mz_stream_zlib_error(void *stream) { + mz_stream_zlib *zlib = (mz_stream_zlib *)stream; + return zlib->error; +} + +int32_t mz_stream_zlib_get_prop_int64(void *stream, int32_t prop, int64_t *value) { + mz_stream_zlib *zlib = (mz_stream_zlib *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN: + *value = zlib->total_in; + break; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + *value = zlib->max_total_in; + break; + case MZ_STREAM_PROP_TOTAL_OUT: + *value = zlib->total_out; + break; + case MZ_STREAM_PROP_HEADER_SIZE: + *value = 0; + break; + case MZ_STREAM_PROP_COMPRESS_WINDOW: + *value = zlib->window_bits; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value) { + mz_stream_zlib *zlib = (mz_stream_zlib *)stream; + switch (prop) { + case MZ_STREAM_PROP_COMPRESS_LEVEL: + if (value == MZ_COMPRESS_LEVEL_DEFAULT) + zlib->level = Z_DEFAULT_COMPRESSION; + else + zlib->level = (int16_t)value; + break; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + zlib->max_total_in = value; + break; + case MZ_STREAM_PROP_COMPRESS_WINDOW: + zlib->window_bits = (int32_t)value; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +void *mz_stream_zlib_create(void) { + mz_stream_zlib *zlib = (mz_stream_zlib *)calloc(1, sizeof(mz_stream_zlib)); + if (zlib) { + zlib->stream.vtbl = &mz_stream_zlib_vtbl; + zlib->level = Z_DEFAULT_COMPRESSION; + zlib->window_bits = -MAX_WBITS; + } + return zlib; +} + +void mz_stream_zlib_delete(void **stream) { + mz_stream_zlib *zlib = NULL; + if (!stream) + return; + zlib = (mz_stream_zlib *)*stream; + free(zlib); + *stream = NULL; +} + +void *mz_stream_zlib_get_interface(void) { + return (void *)&mz_stream_zlib_vtbl; +} diff --git a/thirdparty/minizip/mz_strm_zlib.h b/thirdparty/minizip/mz_strm_zlib.h new file mode 100644 index 000000000..89f10f215 --- /dev/null +++ b/thirdparty/minizip/mz_strm_zlib.h @@ -0,0 +1,43 @@ +/* mz_strm_zlib.h -- Stream for zlib inflate/deflate + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_ZLIB_H +#define MZ_STREAM_ZLIB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_zlib_open(void *stream, const char *filename, int32_t mode); +int32_t mz_stream_zlib_is_open(void *stream); +int32_t mz_stream_zlib_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_zlib_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_zlib_tell(void *stream); +int32_t mz_stream_zlib_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_zlib_close(void *stream); +int32_t mz_stream_zlib_error(void *stream); + +int32_t mz_stream_zlib_get_prop_int64(void *stream, int32_t prop, int64_t *value); +int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value); + +void *mz_stream_zlib_create(void); +void mz_stream_zlib_delete(void **stream); + +void *mz_stream_zlib_get_interface(void); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_strm_zstd.c b/thirdparty/minizip/mz_strm_zstd.c new file mode 100644 index 000000000..c27162995 --- /dev/null +++ b/thirdparty/minizip/mz_strm_zstd.c @@ -0,0 +1,344 @@ +/* mz_strm_zstd.c -- Stream for zstd compress/decompress + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Authors: Force Charlie + https://github.com/fcharlie + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_strm.h" +#include "mz_strm_zstd.h" + +#include + +/***************************************************************************/ + +static mz_stream_vtbl mz_stream_zstd_vtbl = { + mz_stream_zstd_open, mz_stream_zstd_is_open, mz_stream_zstd_read, mz_stream_zstd_write, + mz_stream_zstd_tell, mz_stream_zstd_seek, mz_stream_zstd_close, mz_stream_zstd_error, + mz_stream_zstd_create, mz_stream_zstd_delete, mz_stream_zstd_get_prop_int64, mz_stream_zstd_set_prop_int64}; + +/***************************************************************************/ + +typedef struct mz_stream_zstd_s { + mz_stream stream; + ZSTD_CStream *zcstream; + ZSTD_DStream *zdstream; + ZSTD_outBuffer out; + ZSTD_inBuffer in; + int32_t mode; + int32_t error; + uint8_t buffer[INT16_MAX]; + int32_t buffer_len; + int64_t total_in; + int64_t total_out; + int64_t max_total_in; + int64_t max_total_out; + int8_t initialized; + int32_t preset; +} mz_stream_zstd; + +/***************************************************************************/ + +int32_t mz_stream_zstd_open(void *stream, const char *path, int32_t mode) { + mz_stream_zstd *zstd = (mz_stream_zstd *)stream; + + MZ_UNUSED(path); + + if (mode & MZ_OPEN_MODE_WRITE) { +#ifdef MZ_ZIP_NO_COMPRESSION + return MZ_SUPPORT_ERROR; +#else + zstd->zcstream = ZSTD_createCStream(); + zstd->out.dst = zstd->buffer; + zstd->out.size = sizeof(zstd->buffer); + zstd->out.pos = 0; + ZSTD_CCtx_setParameter(zstd->zcstream, ZSTD_c_compressionLevel, zstd->preset); +#endif + } else if (mode & MZ_OPEN_MODE_READ) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + return MZ_SUPPORT_ERROR; +#else + zstd->zdstream = ZSTD_createDStream(); + memset(&zstd->out, 0, sizeof(ZSTD_outBuffer)); +#endif + } + + memset(&zstd->in, 0, sizeof(ZSTD_inBuffer)); + + zstd->initialized = 1; + zstd->mode = mode; + zstd->error = MZ_OK; + + return MZ_OK; +} + +int32_t mz_stream_zstd_is_open(void *stream) { + mz_stream_zstd *zstd = (mz_stream_zstd *)stream; + if (zstd->initialized != 1) + return MZ_OPEN_ERROR; + return MZ_OK; +} + +int32_t mz_stream_zstd_read(void *stream, void *buf, int32_t size) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + MZ_UNUSED(stream); + MZ_UNUSED(buf); + MZ_UNUSED(size); + return MZ_SUPPORT_ERROR; +#else + mz_stream_zstd *zstd = (mz_stream_zstd *)stream; + uint64_t total_in_before = 0; + uint64_t total_in_after = 0; + uint64_t total_out_before = 0; + uint64_t total_out_after = 0; + int32_t total_out = 0; + int32_t in_bytes = 0; + int32_t out_bytes = 0; + int32_t bytes_to_read = sizeof(zstd->buffer); + int32_t read = 0; + size_t result = 0; + + zstd->out.dst = (void *)buf; + zstd->out.size = (size_t)size; + zstd->out.pos = 0; + + do { + if (zstd->in.pos == zstd->in.size) { + if (zstd->max_total_in > 0) { + if ((int64_t)bytes_to_read > (zstd->max_total_in - zstd->total_in)) + bytes_to_read = (int32_t)(zstd->max_total_in - zstd->total_in); + } + + read = mz_stream_read(zstd->stream.base, zstd->buffer, bytes_to_read); + + if (read < 0) + return read; + + zstd->in.src = (const void *)zstd->buffer; + zstd->in.pos = 0; + zstd->in.size = (size_t)read; + } + + total_in_before = zstd->in.pos; + total_out_before = zstd->out.pos; + + result = ZSTD_decompressStream(zstd->zdstream, &zstd->out, &zstd->in); + + if (ZSTD_isError(result)) { + zstd->error = (int32_t)result; + return MZ_DATA_ERROR; + } + + total_in_after = zstd->in.pos; + total_out_after = zstd->out.pos; + if ((zstd->max_total_out != -1) && (int64_t)total_out_after > zstd->max_total_out) + total_out_after = (uint64_t)zstd->max_total_out; + + in_bytes = (int32_t)(total_in_after - total_in_before); + out_bytes = (int32_t)(total_out_after - total_out_before); + + total_out += out_bytes; + + zstd->total_in += in_bytes; + zstd->total_out += out_bytes; + + } while ((zstd->in.size > 0 || out_bytes > 0) && (zstd->out.pos < zstd->out.size)); + + return total_out; +#endif +} + +#ifndef MZ_ZIP_NO_COMPRESSION +static int32_t mz_stream_zstd_flush(void *stream) { + mz_stream_zstd *zstd = (mz_stream_zstd *)stream; + if (mz_stream_write(zstd->stream.base, zstd->buffer, zstd->buffer_len) != zstd->buffer_len) + return MZ_WRITE_ERROR; + return MZ_OK; +} + +static int32_t mz_stream_zstd_compress(void *stream, ZSTD_EndDirective flush) { + mz_stream_zstd *zstd = (mz_stream_zstd *)stream; + uint64_t total_out_before = 0; + uint64_t total_out_after = 0; + int32_t out_bytes = 0; + size_t result = 0; + int32_t err = 0; + + do { + if (zstd->out.pos == zstd->out.size) { + err = mz_stream_zstd_flush(zstd); + if (err != MZ_OK) + return err; + + zstd->out.dst = zstd->buffer; + zstd->out.size = sizeof(zstd->buffer); + zstd->out.pos = 0; + + zstd->buffer_len = 0; + } + + total_out_before = zstd->out.pos; + + result = ZSTD_compressStream2(zstd->zcstream, &zstd->out, &zstd->in, flush); + + total_out_after = zstd->out.pos; + + out_bytes = (uint32_t)(total_out_after - total_out_before); + + zstd->buffer_len += out_bytes; + zstd->total_out += out_bytes; + + if (ZSTD_isError(result)) { + zstd->error = (int32_t)result; + return MZ_DATA_ERROR; + } + } while ((zstd->in.pos < zstd->in.size) || (flush == ZSTD_e_end && result != 0)); + + return MZ_OK; +} +#endif + +int32_t mz_stream_zstd_write(void *stream, const void *buf, int32_t size) { +#ifdef MZ_ZIP_NO_COMPRESSION + MZ_UNUSED(stream); + MZ_UNUSED(buf); + MZ_UNUSED(size); + return MZ_SUPPORT_ERROR; +#else + mz_stream_zstd *zstd = (mz_stream_zstd *)stream; + int32_t err = MZ_OK; + + zstd->in.src = buf; + zstd->in.pos = 0; + zstd->in.size = size; + + err = mz_stream_zstd_compress(stream, ZSTD_e_continue); + if (err != MZ_OK) { + return err; + } + + zstd->total_in += size; + return size; +#endif +} + +int64_t mz_stream_zstd_tell(void *stream) { + MZ_UNUSED(stream); + + return MZ_TELL_ERROR; +} + +int32_t mz_stream_zstd_seek(void *stream, int64_t offset, int32_t origin) { + MZ_UNUSED(stream); + MZ_UNUSED(offset); + MZ_UNUSED(origin); + + return MZ_SEEK_ERROR; +} + +int32_t mz_stream_zstd_close(void *stream) { + mz_stream_zstd *zstd = (mz_stream_zstd *)stream; + + if (zstd->mode & MZ_OPEN_MODE_WRITE) { +#ifdef MZ_ZIP_NO_COMPRESSION + return MZ_SUPPORT_ERROR; +#else + mz_stream_zstd_compress(stream, ZSTD_e_end); + mz_stream_zstd_flush(stream); + + ZSTD_freeCStream(zstd->zcstream); + zstd->zcstream = NULL; +#endif + } else if (zstd->mode & MZ_OPEN_MODE_READ) { +#ifdef MZ_ZIP_NO_DECOMPRESSION + return MZ_SUPPORT_ERROR; +#else + ZSTD_freeDStream(zstd->zdstream); + zstd->zdstream = NULL; +#endif + } + zstd->initialized = 0; + return MZ_OK; +} + +int32_t mz_stream_zstd_error(void *stream) { + mz_stream_zstd *zstd = (mz_stream_zstd *)stream; + return zstd->error; +} + +int32_t mz_stream_zstd_get_prop_int64(void *stream, int32_t prop, int64_t *value) { + mz_stream_zstd *zstd = (mz_stream_zstd *)stream; + switch (prop) { + case MZ_STREAM_PROP_TOTAL_IN: + *value = zstd->total_in; + break; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + *value = zstd->max_total_in; + break; + case MZ_STREAM_PROP_TOTAL_OUT: + *value = zstd->total_out; + break; + case MZ_STREAM_PROP_TOTAL_OUT_MAX: + *value = zstd->max_total_out; + break; + case MZ_STREAM_PROP_HEADER_SIZE: + *value = 0; + break; + default: + return MZ_EXIST_ERROR; + } + return MZ_OK; +} + +int32_t mz_stream_zstd_set_prop_int64(void *stream, int32_t prop, int64_t value) { + mz_stream_zstd *zstd = (mz_stream_zstd *)stream; + switch (prop) { + case MZ_STREAM_PROP_COMPRESS_LEVEL: + if (value == MZ_COMPRESS_LEVEL_DEFAULT) + zstd->preset = ZSTD_CLEVEL_DEFAULT; + else + zstd->preset = (int16_t)value; + return MZ_OK; + case MZ_STREAM_PROP_TOTAL_IN_MAX: + zstd->max_total_in = value; + return MZ_OK; + case MZ_STREAM_PROP_COMPRESS_THREADS: + if (zstd->zcstream) { + size_t rv = ZSTD_CCtx_setParameter(zstd->zcstream, ZSTD_c_nbWorkers, (int)value); + if (rv == (size_t)value) { + return MZ_OK; + } + } + return MZ_PARAM_ERROR; + } + return MZ_EXIST_ERROR; +} + +void *mz_stream_zstd_create(void) { + mz_stream_zstd *zstd = (mz_stream_zstd *)calloc(1, sizeof(mz_stream_zstd)); + if (zstd) { + zstd->stream.vtbl = &mz_stream_zstd_vtbl; + zstd->max_total_out = -1; + zstd->preset = ZSTD_CLEVEL_DEFAULT; + } + return zstd; +} + +void mz_stream_zstd_delete(void **stream) { + mz_stream_zstd *zstd = NULL; + if (!stream) + return; + zstd = (mz_stream_zstd *)*stream; + free(zstd); + *stream = NULL; +} + +void *mz_stream_zstd_get_interface(void) { + return (void *)&mz_stream_zstd_vtbl; +} diff --git a/thirdparty/minizip/mz_strm_zstd.h b/thirdparty/minizip/mz_strm_zstd.h new file mode 100644 index 000000000..d1bc66d95 --- /dev/null +++ b/thirdparty/minizip/mz_strm_zstd.h @@ -0,0 +1,44 @@ +/* mz_strm_zlib.h -- Stream for zlib inflate/deflate + Version 2.9.2, February 12, 2020 + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_STREAM_ZSTD_H +#define MZ_STREAM_ZSTD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +int32_t mz_stream_zstd_open(void *stream, const char *filename, int32_t mode); +int32_t mz_stream_zstd_is_open(void *stream); +int32_t mz_stream_zstd_read(void *stream, void *buf, int32_t size); +int32_t mz_stream_zstd_write(void *stream, const void *buf, int32_t size); +int64_t mz_stream_zstd_tell(void *stream); +int32_t mz_stream_zstd_seek(void *stream, int64_t offset, int32_t origin); +int32_t mz_stream_zstd_close(void *stream); +int32_t mz_stream_zstd_error(void *stream); + +int32_t mz_stream_zstd_get_prop_int64(void *stream, int32_t prop, int64_t *value); +int32_t mz_stream_zstd_set_prop_int64(void *stream, int32_t prop, int64_t value); + +void *mz_stream_zstd_create(void); +void mz_stream_zstd_delete(void **stream); + +void *mz_stream_zstd_get_interface(void); + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mz_zip.c b/thirdparty/minizip/mz_zip.c new file mode 100644 index 000000000..854f9bba2 --- /dev/null +++ b/thirdparty/minizip/mz_zip.c @@ -0,0 +1,2834 @@ +/* zip.c -- Zip manipulation + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Copyright (C) 2009-2010 Mathias Svensson + Modifications for Zip64 support + http://result42.com + Copyright (C) 2007-2008 Even Rouault + Modifications of Unzip for Zip64 + Copyright (C) 1998-2010 Gilles Vollant + https://www.winimage.com/zLibDll/minizip.html + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_crypt.h" +#include "mz_os.h" +#include "mz_strm.h" +#ifdef HAVE_BZIP2 +# include "mz_strm_bzip.h" +#endif +#ifdef HAVE_LIBCOMP +# include "mz_strm_libcomp.h" +#endif +#ifdef HAVE_LZMA +# include "mz_strm_lzma.h" +#endif +#include "mz_strm_mem.h" +#ifdef HAVE_PKCRYPT +# include "mz_strm_pkcrypt.h" +#endif +#ifdef HAVE_PPMD +# include "mz_strm_ppmd.h" +#endif +#ifdef HAVE_WZAES +# include "mz_strm_wzaes.h" +#endif +#ifdef HAVE_ZLIB +# include "mz_strm_zlib.h" +#endif +#ifdef HAVE_ZSTD +# include "mz_strm_zstd.h" +#endif +#include "mz_zip.h" + +#include /* tolower */ +#include /* snprintf */ + +#if defined(_MSC_VER) || defined(__MINGW32__) +# define localtime_r(t1, t2) (localtime_s(t2, t1) == 0 ? t1 : NULL) +#endif +#if defined(_MSC_VER) && (_MSC_VER < 1900) +# define snprintf _snprintf +#endif + +/***************************************************************************/ + +#define MZ_ZIP_MAGIC_LOCALHEADER (0x04034b50) +#define MZ_ZIP_MAGIC_LOCALHEADERU8 {0x50, 0x4b, 0x03, 0x04} +#define MZ_ZIP_MAGIC_CENTRALHEADER (0x02014b50) +#define MZ_ZIP_MAGIC_CENTRALHEADERU8 {0x50, 0x4b, 0x01, 0x02} +#define MZ_ZIP_MAGIC_ENDHEADER (0x06054b50) +#define MZ_ZIP_MAGIC_ENDHEADERU8 {0x50, 0x4b, 0x05, 0x06} +#define MZ_ZIP_MAGIC_ENDHEADER64 (0x06064b50) +#define MZ_ZIP_MAGIC_ENDLOCHEADER64 (0x07064b50) +#define MZ_ZIP_MAGIC_DATADESCRIPTOR (0x08074b50) +#define MZ_ZIP_MAGIC_DATADESCRIPTORU8 {0x50, 0x4b, 0x07, 0x08} + +#define MZ_ZIP_SIZE_LD_ITEM (30) +#define MZ_ZIP_SIZE_CD_ITEM (46) +#define MZ_ZIP_SIZE_CD_LOCATOR64 (20) +#define MZ_ZIP_SIZE_MAX_DATA_DESCRIPTOR (24) + +#define MZ_ZIP_OFFSET_CRC_SIZES (14) +#define MZ_ZIP_UNCOMPR_SIZE64_CUSHION (2 * 1024 * 1024) + +#ifndef MZ_ZIP_EOCD_MAX_BACK +# define MZ_ZIP_EOCD_MAX_BACK (1 << 20) +#endif + +/***************************************************************************/ + +typedef struct mz_zip_s { + mz_zip_file file_info; + mz_zip_file local_file_info; + + void *stream; /* main stream */ + void *cd_stream; /* pointer to the stream with the cd */ + void *cd_mem_stream; /* memory stream for central directory */ + void *compress_stream; /* compression stream */ + void *crypt_stream; /* encryption stream */ + void *file_info_stream; /* memory stream for storing file info */ + void *local_file_info_stream; /* memory stream for storing local file info */ + + int32_t open_mode; + uint8_t recover; + uint8_t data_descriptor; + + uint32_t disk_number_with_cd; /* number of the disk with the central dir */ + int64_t disk_offset_shift; /* correction for zips that have wrong offset start of cd */ + + int64_t cd_start_pos; /* pos of the first file in the central dir stream */ + int64_t cd_current_pos; /* pos of the current file in the central dir */ + int64_t cd_offset; /* offset of start of central directory */ + int64_t cd_size; /* size of the central directory */ + uint32_t cd_signature; /* signature of central directory */ + + uint8_t entry_scanned; /* entry header information read ok */ + uint8_t entry_opened; /* entry is open for read/write */ + uint8_t entry_raw; /* entry opened with raw mode */ + uint32_t entry_crc32; /* entry crc32 */ + + uint64_t number_entry; + + uint16_t version_madeby; + char *comment; +} mz_zip; + +/***************************************************************************/ + +#if 0 +# define mz_zip_print printf +#else +# define mz_zip_print(fmt, ...) +#endif + +/***************************************************************************/ + +/* Locate the end of central directory */ +static int32_t mz_zip_search_eocd(void *stream, int64_t *central_pos) { + int64_t file_size = 0; + int64_t max_back = MZ_ZIP_EOCD_MAX_BACK; + uint8_t find[4] = MZ_ZIP_MAGIC_ENDHEADERU8; + int32_t err = MZ_OK; + + err = mz_stream_seek(stream, 0, MZ_SEEK_END); + if (err != MZ_OK) + return err; + + file_size = mz_stream_tell(stream); + + if (max_back <= 0 || max_back > file_size) + max_back = file_size; + + return mz_stream_find_reverse(stream, (const void *)find, sizeof(find), max_back, central_pos); +} + +/* Locate the end of central directory 64 of a zip file */ +static int32_t mz_zip_search_zip64_eocd(void *stream, const int64_t end_central_offset, int64_t *central_pos) { + int64_t offset = 0; + uint32_t value32 = 0; + int32_t err = MZ_OK; + + *central_pos = 0; + + /* Zip64 end of central directory locator */ + err = mz_stream_seek(stream, end_central_offset - MZ_ZIP_SIZE_CD_LOCATOR64, MZ_SEEK_SET); + /* Read locator signature */ + if (err == MZ_OK) { + err = mz_stream_read_uint32(stream, &value32); + if (value32 != MZ_ZIP_MAGIC_ENDLOCHEADER64) + err = MZ_FORMAT_ERROR; + } + /* Number of the disk with the start of the zip64 end of central directory */ + if (err == MZ_OK) + err = mz_stream_read_uint32(stream, &value32); + /* Relative offset of the zip64 end of central directory record8 */ + if (err == MZ_OK) + err = mz_stream_read_uint64(stream, (uint64_t *)&offset); + /* Total number of disks */ + if (err == MZ_OK) + err = mz_stream_read_uint32(stream, &value32); + /* Goto end of central directory record */ + if (err == MZ_OK) + err = mz_stream_seek(stream, (int64_t)offset, MZ_SEEK_SET); + /* The signature */ + if (err == MZ_OK) { + err = mz_stream_read_uint32(stream, &value32); + if (value32 != MZ_ZIP_MAGIC_ENDHEADER64) + err = MZ_FORMAT_ERROR; + } + + if (err == MZ_OK) + *central_pos = offset; + + return err; +} + +#ifdef HAVE_PKCRYPT +/* Get PKWARE traditional encryption verifier */ +static uint16_t mz_zip_get_pk_verify(uint32_t dos_date, uint64_t crc, uint16_t flag) { + /* Info-ZIP modification to ZipCrypto format: if bit 3 of the general + * purpose bit flag is set, it uses high byte of 16-bit File Time. */ + if (flag & MZ_ZIP_FLAG_DATA_DESCRIPTOR) + return ((dos_date >> 16) & 0xff) << 8 | ((dos_date >> 8) & 0xff); + return ((crc >> 16) & 0xff) << 8 | ((crc >> 24) & 0xff); +} +#endif + +/* Get info about the current file in the zip file */ +static int32_t mz_zip_entry_read_header(void *stream, uint8_t local, mz_zip_file *file_info, void *file_extra_stream) { + uint64_t ntfs_time = 0; + uint32_t reserved = 0; + uint32_t magic = 0; + uint32_t dos_date = 0; + uint32_t field_pos = 0; + uint16_t field_type = 0; + uint16_t field_length = 0; + uint32_t field_length_read = 0; + uint16_t ntfs_attrib_id = 0; + uint16_t ntfs_attrib_size = 0; + uint16_t linkname_size; + uint16_t value16 = 0; + uint32_t value32 = 0; + int64_t extrafield_pos = 0; + int64_t comment_pos = 0; + int64_t linkname_pos = 0; + int64_t saved_pos = 0; + int32_t err = MZ_OK; + char *linkname = NULL; + + memset(file_info, 0, sizeof(mz_zip_file)); + + /* Check the magic */ + err = mz_stream_read_uint32(stream, &magic); + if (err == MZ_END_OF_STREAM) + err = MZ_END_OF_LIST; + else if (magic == MZ_ZIP_MAGIC_ENDHEADER || magic == MZ_ZIP_MAGIC_ENDHEADER64) + err = MZ_END_OF_LIST; + else if ((local) && (magic != MZ_ZIP_MAGIC_LOCALHEADER)) + err = MZ_FORMAT_ERROR; + else if ((!local) && (magic != MZ_ZIP_MAGIC_CENTRALHEADER)) + err = MZ_FORMAT_ERROR; + + /* Read header fields */ + if (err == MZ_OK) { + if (!local) + err = mz_stream_read_uint16(stream, &file_info->version_madeby); + if (err == MZ_OK) + err = mz_stream_read_uint16(stream, &file_info->version_needed); + if (err == MZ_OK) + err = mz_stream_read_uint16(stream, &file_info->flag); + if (err == MZ_OK) + err = mz_stream_read_uint16(stream, &file_info->compression_method); + if (err == MZ_OK) { + err = mz_stream_read_uint32(stream, &dos_date); + file_info->modified_date = mz_zip_dosdate_to_time_t(dos_date); + } + if (err == MZ_OK) + err = mz_stream_read_uint32(stream, &file_info->crc); +#ifdef HAVE_PKCRYPT + if (err == MZ_OK && file_info->flag & MZ_ZIP_FLAG_ENCRYPTED) { + /* Use dos_date from header instead of derived from time in zip extensions */ + file_info->pk_verify = mz_zip_get_pk_verify(dos_date, file_info->crc, file_info->flag); + } +#endif + if (err == MZ_OK) { + err = mz_stream_read_uint32(stream, &value32); + file_info->compressed_size = value32; + } + if (err == MZ_OK) { + err = mz_stream_read_uint32(stream, &value32); + file_info->uncompressed_size = value32; + } + if (err == MZ_OK) + err = mz_stream_read_uint16(stream, &file_info->filename_size); + if (err == MZ_OK) + err = mz_stream_read_uint16(stream, &file_info->extrafield_size); + if (!local) { + if (err == MZ_OK) + err = mz_stream_read_uint16(stream, &file_info->comment_size); + if (err == MZ_OK) { + err = mz_stream_read_uint16(stream, &value16); + file_info->disk_number = value16; + } + if (err == MZ_OK) + err = mz_stream_read_uint16(stream, &file_info->internal_fa); + if (err == MZ_OK) + err = mz_stream_read_uint32(stream, &file_info->external_fa); + if (err == MZ_OK) { + err = mz_stream_read_uint32(stream, &value32); + file_info->disk_offset = value32; + } + } + } + + if (err == MZ_OK) + err = mz_stream_seek(file_extra_stream, 0, MZ_SEEK_SET); + + /* Copy variable length data to memory stream for later retrieval */ + if ((err == MZ_OK) && (file_info->filename_size > 0)) + err = mz_stream_copy(file_extra_stream, stream, file_info->filename_size); + mz_stream_write_uint8(file_extra_stream, 0); + extrafield_pos = mz_stream_tell(file_extra_stream); + + if ((err == MZ_OK) && (file_info->extrafield_size > 0)) + err = mz_stream_copy(file_extra_stream, stream, file_info->extrafield_size); + mz_stream_write_uint8(file_extra_stream, 0); + + comment_pos = mz_stream_tell(file_extra_stream); + if ((err == MZ_OK) && (file_info->comment_size > 0)) + err = mz_stream_copy(file_extra_stream, stream, file_info->comment_size); + mz_stream_write_uint8(file_extra_stream, 0); + + linkname_pos = mz_stream_tell(file_extra_stream); + /* Overwrite if we encounter UNIX1 extra block */ + mz_stream_write_uint8(file_extra_stream, 0); + + if ((err == MZ_OK) && (file_info->extrafield_size > 0)) { + /* Seek to and parse the extra field */ + err = mz_stream_seek(file_extra_stream, extrafield_pos, MZ_SEEK_SET); + + while ((err == MZ_OK) && (field_pos + 4 <= file_info->extrafield_size)) { + err = mz_zip_extrafield_read(file_extra_stream, &field_type, &field_length); + if (err != MZ_OK) + break; + field_pos += 4; + + /* Don't allow field length to exceed size of remaining extrafield */ + if (field_length > (file_info->extrafield_size - field_pos)) + field_length = (uint16_t)(file_info->extrafield_size - field_pos); + + /* Read ZIP64 extra field */ + if ((field_type == MZ_ZIP_EXTENSION_ZIP64) && (field_length >= 8)) { + if ((err == MZ_OK) && (file_info->uncompressed_size == UINT32_MAX)) { + err = mz_stream_read_int64(file_extra_stream, &file_info->uncompressed_size); + if (file_info->uncompressed_size < 0) + err = MZ_FORMAT_ERROR; + } + if ((err == MZ_OK) && (file_info->compressed_size == UINT32_MAX)) { + err = mz_stream_read_int64(file_extra_stream, &file_info->compressed_size); + if (file_info->compressed_size < 0) + err = MZ_FORMAT_ERROR; + } + if ((err == MZ_OK) && (file_info->disk_offset == UINT32_MAX)) { + err = mz_stream_read_int64(file_extra_stream, &file_info->disk_offset); + if (file_info->disk_offset < 0) + err = MZ_FORMAT_ERROR; + } + if ((err == MZ_OK) && (file_info->disk_number == UINT16_MAX)) + err = mz_stream_read_uint32(file_extra_stream, &file_info->disk_number); + } + /* Read NTFS extra field */ + else if ((field_type == MZ_ZIP_EXTENSION_NTFS) && (field_length > 4)) { + if (err == MZ_OK) + err = mz_stream_read_uint32(file_extra_stream, &reserved); + field_length_read = 4; + + while ((err == MZ_OK) && (field_length_read + 4 <= field_length)) { + err = mz_stream_read_uint16(file_extra_stream, &ntfs_attrib_id); + if (err == MZ_OK) + err = mz_stream_read_uint16(file_extra_stream, &ntfs_attrib_size); + field_length_read += 4; + + if ((err == MZ_OK) && (ntfs_attrib_id == 0x01) && (ntfs_attrib_size == 24)) { + err = mz_stream_read_uint64(file_extra_stream, &ntfs_time); + mz_zip_ntfs_to_unix_time(ntfs_time, &file_info->modified_date); + + if (err == MZ_OK) { + err = mz_stream_read_uint64(file_extra_stream, &ntfs_time); + mz_zip_ntfs_to_unix_time(ntfs_time, &file_info->accessed_date); + } + if (err == MZ_OK) { + err = mz_stream_read_uint64(file_extra_stream, &ntfs_time); + mz_zip_ntfs_to_unix_time(ntfs_time, &file_info->creation_date); + } + } else if ((err == MZ_OK) && (field_length_read + ntfs_attrib_size <= field_length)) { + err = mz_stream_seek(file_extra_stream, ntfs_attrib_size, MZ_SEEK_CUR); + } + + field_length_read += ntfs_attrib_size; + } + } + /* Read UNIX1 extra field */ + else if ((field_type == MZ_ZIP_EXTENSION_UNIX1) && (field_length >= 12)) { + if (err == MZ_OK) { + err = mz_stream_read_uint32(file_extra_stream, &value32); + if (err == MZ_OK && file_info->accessed_date == 0) + file_info->accessed_date = value32; + } + if (err == MZ_OK) { + err = mz_stream_read_uint32(file_extra_stream, &value32); + if (err == MZ_OK && file_info->modified_date == 0) + file_info->modified_date = value32; + } + if (err == MZ_OK) + err = mz_stream_read_uint16(file_extra_stream, &value16); /* User id */ + if (err == MZ_OK) + err = mz_stream_read_uint16(file_extra_stream, &value16); /* Group id */ + + /* Copy linkname to end of file extra stream so we can return null + terminated string */ + linkname_size = field_length - 12; + if ((err == MZ_OK) && (linkname_size > 0)) { + linkname = (char *)malloc(linkname_size); + if (linkname) { + if (mz_stream_read(file_extra_stream, linkname, linkname_size) != linkname_size) + err = MZ_READ_ERROR; + if (err == MZ_OK) { + saved_pos = mz_stream_tell(file_extra_stream); + + mz_stream_seek(file_extra_stream, linkname_pos, MZ_SEEK_SET); + mz_stream_write(file_extra_stream, linkname, linkname_size); + mz_stream_write_uint8(file_extra_stream, 0); + + mz_stream_seek(file_extra_stream, saved_pos, MZ_SEEK_SET); + } + free(linkname); + } + } + } +#ifdef HAVE_WZAES + /* Read AES extra field */ + else if ((field_type == MZ_ZIP_EXTENSION_AES) && (field_length == 7)) { + uint8_t value8 = 0; + /* Verify version info */ + err = mz_stream_read_uint16(file_extra_stream, &value16); + /* Support AE-1 and AE-2 */ + if (value16 != 1 && value16 != 2) + err = MZ_FORMAT_ERROR; + file_info->aes_version = value16; + if (err == MZ_OK) + err = mz_stream_read_uint8(file_extra_stream, &value8); + if ((char)value8 != 'A') + err = MZ_FORMAT_ERROR; + if (err == MZ_OK) + err = mz_stream_read_uint8(file_extra_stream, &value8); + if ((char)value8 != 'E') + err = MZ_FORMAT_ERROR; + /* Get AES encryption strength and actual compression method */ + if (err == MZ_OK) { + err = mz_stream_read_uint8(file_extra_stream, &value8); + file_info->aes_strength = value8; + } + if (err == MZ_OK) { + err = mz_stream_read_uint16(file_extra_stream, &value16); + file_info->compression_method = value16; + } + } +#endif + else if (field_length > 0) { + err = mz_stream_seek(file_extra_stream, field_length, MZ_SEEK_CUR); + } + + field_pos += field_length; + } + } + + /* Get pointers to variable length data */ + mz_stream_mem_get_buffer(file_extra_stream, (const void **)&file_info->filename); + mz_stream_mem_get_buffer_at(file_extra_stream, extrafield_pos, (const void **)&file_info->extrafield); + mz_stream_mem_get_buffer_at(file_extra_stream, comment_pos, (const void **)&file_info->comment); + mz_stream_mem_get_buffer_at(file_extra_stream, linkname_pos, (const void **)&file_info->linkname); + + /* Set to empty string just in-case */ + if (!file_info->filename) + file_info->filename = ""; + if (!file_info->extrafield) + file_info->extrafield_size = 0; + if (!file_info->comment) + file_info->comment = ""; + if (!file_info->linkname) + file_info->linkname = ""; + + if (err == MZ_OK) { + mz_zip_print("Zip - Entry - Read header - %s (local %" PRId8 ")\n", file_info->filename, local); + mz_zip_print("Zip - Entry - Read header compress (ucs %" PRId64 " cs %" PRId64 " crc 0x%08" PRIx32 ")\n", + file_info->uncompressed_size, file_info->compressed_size, file_info->crc); + if (!local) { + mz_zip_print("Zip - Entry - Read header disk (disk %" PRIu32 " offset %" PRId64 ")\n", + file_info->disk_number, file_info->disk_offset); + } + mz_zip_print("Zip - Entry - Read header variable (fnl %" PRId32 " efs %" PRId32 " cms %" PRId32 ")\n", + file_info->filename_size, file_info->extrafield_size, file_info->comment_size); + } + + return err; +} + +static int32_t mz_zip_entry_read_descriptor(void *stream, uint8_t zip64, uint32_t *crc32, int64_t *compressed_size, + int64_t *uncompressed_size) { + uint32_t value32 = 0; + int64_t value64 = 0; + int32_t err = MZ_OK; + + err = mz_stream_read_uint32(stream, &value32); + if (value32 != MZ_ZIP_MAGIC_DATADESCRIPTOR) + err = MZ_FORMAT_ERROR; + if (err == MZ_OK) + err = mz_stream_read_uint32(stream, &value32); + if (err == MZ_OK && crc32) + *crc32 = value32; + if (err == MZ_OK) { + /* If zip 64 extension is enabled then read as 8 byte */ + if (!zip64) { + err = mz_stream_read_uint32(stream, &value32); + value64 = value32; + } else { + err = mz_stream_read_int64(stream, &value64); + if (value64 < 0) + err = MZ_FORMAT_ERROR; + } + if (err == MZ_OK && compressed_size) + *compressed_size = value64; + } + if (err == MZ_OK) { + if (!zip64) { + err = mz_stream_read_uint32(stream, &value32); + value64 = value32; + } else { + err = mz_stream_read_int64(stream, &value64); + if (value64 < 0) + err = MZ_FORMAT_ERROR; + } + if (err == MZ_OK && uncompressed_size) + *uncompressed_size = value64; + } + + return err; +} + +static int32_t mz_zip_entry_write_crc_sizes(void *stream, uint8_t zip64, uint8_t mask, mz_zip_file *file_info) { + int32_t err = MZ_OK; + + if (mask) + err = mz_stream_write_uint32(stream, 0); + else + err = mz_stream_write_uint32(stream, file_info->crc); /* crc */ + + /* For backwards-compatibility with older zip applications we set all sizes to UINT32_MAX + * when zip64 is needed, instead of only setting sizes larger than UINT32_MAX. */ + + if (err == MZ_OK) { + if (zip64) /* compr size */ + err = mz_stream_write_uint32(stream, UINT32_MAX); + else + err = mz_stream_write_uint32(stream, (uint32_t)file_info->compressed_size); + } + if (err == MZ_OK) { + if (mask) /* uncompr size */ + err = mz_stream_write_uint32(stream, 0); + else if (zip64) + err = mz_stream_write_uint32(stream, UINT32_MAX); + else + err = mz_stream_write_uint32(stream, (uint32_t)file_info->uncompressed_size); + } + return err; +} + +static int32_t mz_zip_entry_needs_zip64(mz_zip_file *file_info, uint8_t local, uint8_t *zip64) { + uint32_t max_uncompressed_size = UINT32_MAX; + uint8_t needs_zip64 = 0; + + if (!zip64) + return MZ_PARAM_ERROR; + + *zip64 = 0; + + if (local) { + /* At local header we might not know yet whether compressed size will overflow unsigned + 32-bit integer which might happen for high entropy data so we give it some cushion */ + + max_uncompressed_size -= MZ_ZIP_UNCOMPR_SIZE64_CUSHION; + } + + needs_zip64 = (file_info->uncompressed_size >= max_uncompressed_size) || (file_info->compressed_size >= UINT32_MAX); + + if (!local) { + /* Disk offset and number only used in central directory header */ + needs_zip64 |= (file_info->disk_offset >= UINT32_MAX) || (file_info->disk_number >= UINT16_MAX); + } + + if (file_info->zip64 == MZ_ZIP64_AUTO) { + /* If uncompressed size is unknown, assume zip64 for 64-bit data descriptors */ + if (local && file_info->uncompressed_size == 0) { + /* Don't use zip64 for local header directory entries */ + if (mz_zip_attrib_is_dir(file_info->external_fa, file_info->version_madeby) != MZ_OK) { + *zip64 = 1; + } + } + *zip64 |= needs_zip64; + } else if (file_info->zip64 == MZ_ZIP64_FORCE) { + *zip64 = 1; + } else if (file_info->zip64 == MZ_ZIP64_DISABLE) { + /* Zip64 extension is required to zip file */ + if (needs_zip64) + return MZ_PARAM_ERROR; + } + + return MZ_OK; +} + +static int32_t mz_zip_entry_write_header(void *stream, uint8_t local, mz_zip_file *file_info) { + uint64_t ntfs_time = 0; + uint32_t reserved = 0; + uint32_t dos_date = 0; + uint16_t extrafield_size = 0; + uint16_t field_type = 0; + uint16_t field_length = 0; + uint16_t field_length_zip64 = 0; + uint16_t field_length_ntfs = 0; + uint16_t field_length_aes = 0; + uint16_t field_length_unix1 = 0; + uint16_t filename_size = 0; + uint16_t filename_length = 0; + uint16_t linkname_size = 0; + uint16_t version_needed = 0; + int32_t comment_size = 0; + int32_t err = MZ_OK; + int32_t err_mem = MZ_OK; + uint8_t zip64 = 0; + uint8_t skip_aes = 0; + uint8_t mask = 0; + uint8_t write_end_slash = 0; + const char *filename = NULL; + char masked_name[64]; + void *file_extra_stream = NULL; + + if (!file_info) + return MZ_PARAM_ERROR; + + if ((local) && (file_info->flag & MZ_ZIP_FLAG_MASK_LOCAL_INFO)) + mask = 1; + + /* Determine if zip64 extra field is necessary */ + err = mz_zip_entry_needs_zip64(file_info, local, &zip64); + if (err != MZ_OK) + return err; + + /* Start calculating extra field sizes */ + if (zip64) { + /* Both compressed and uncompressed sizes must be included (at least in local header) */ + field_length_zip64 = 8 + 8; + if ((!local) && (file_info->disk_offset >= UINT32_MAX)) + field_length_zip64 += 8; + + extrafield_size += 4; + extrafield_size += field_length_zip64; + } + + /* Calculate extra field size and check for duplicates */ + if (file_info->extrafield_size > 0) { + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; + mz_stream_mem_set_buffer(file_extra_stream, (void *)file_info->extrafield, file_info->extrafield_size); + + do { + err_mem = mz_stream_read_uint16(file_extra_stream, &field_type); + if (err_mem == MZ_OK) + err_mem = mz_stream_read_uint16(file_extra_stream, &field_length); + if (err_mem != MZ_OK) + break; + + /* Prefer incoming aes extensions over ours */ + if (field_type == MZ_ZIP_EXTENSION_AES) + skip_aes = 1; + + /* Prefer our zip64, ntfs, unix1 extension over incoming */ + if (field_type != MZ_ZIP_EXTENSION_ZIP64 && field_type != MZ_ZIP_EXTENSION_NTFS && + field_type != MZ_ZIP_EXTENSION_UNIX1) + extrafield_size += 4 + field_length; + + if (err_mem == MZ_OK) + err_mem = mz_stream_seek(file_extra_stream, field_length, MZ_SEEK_CUR); + } while (err_mem == MZ_OK); + } + +#ifdef HAVE_WZAES + if (!skip_aes) { + if ((file_info->flag & MZ_ZIP_FLAG_ENCRYPTED) && (file_info->aes_version)) { + field_length_aes = 1 + 1 + 1 + 2 + 2; + extrafield_size += 4 + field_length_aes; + } + } +#else + MZ_UNUSED(field_length_aes); + MZ_UNUSED(skip_aes); +#endif + /* NTFS timestamps */ + if ((file_info->modified_date != 0) && (file_info->accessed_date != 0) && (file_info->creation_date != 0) && + (!mask)) { + field_length_ntfs = 8 + 8 + 8 + 4 + 2 + 2; + extrafield_size += 4 + field_length_ntfs; + } + + /* Unix1 symbolic links */ + if (file_info->linkname && *file_info->linkname != 0) { + linkname_size = (uint16_t)strlen(file_info->linkname); + field_length_unix1 = 12 + linkname_size; + extrafield_size += 4 + field_length_unix1; + } + + if (local) + err = mz_stream_write_uint32(stream, MZ_ZIP_MAGIC_LOCALHEADER); + else { + err = mz_stream_write_uint32(stream, MZ_ZIP_MAGIC_CENTRALHEADER); + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, file_info->version_madeby); + } + + /* Calculate version needed to extract */ + if (err == MZ_OK) { + version_needed = file_info->version_needed; + if (version_needed == 0) { + version_needed = 20; + if (zip64) + version_needed = 45; +#ifdef HAVE_BZIP2 + if (file_info->compression_method == MZ_COMPRESS_METHOD_BZIP2) + version_needed = 46; +#endif +#ifdef HAVE_WZAES + if ((file_info->flag & MZ_ZIP_FLAG_ENCRYPTED) && (file_info->aes_version)) + version_needed = 51; +#endif +#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP) || defined(HAVE_PPMD) + if ((file_info->compression_method == MZ_COMPRESS_METHOD_LZMA) || + (file_info->compression_method == MZ_COMPRESS_METHOD_PPMD) || + (file_info->compression_method == MZ_COMPRESS_METHOD_XZ)) + version_needed = 63; +#endif + } + err = mz_stream_write_uint16(stream, version_needed); + } + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, file_info->flag); + if (err == MZ_OK) { +#ifdef HAVE_WZAES + if ((file_info->flag & MZ_ZIP_FLAG_ENCRYPTED) && (file_info->aes_version)) + err = mz_stream_write_uint16(stream, MZ_COMPRESS_METHOD_AES); + else +#endif + err = mz_stream_write_uint16(stream, file_info->compression_method); + } + if (err == MZ_OK) { + if (file_info->modified_date != 0 && !mask) + dos_date = mz_zip_time_t_to_dos_date(file_info->modified_date); + err = mz_stream_write_uint32(stream, dos_date); + } + + if (err == MZ_OK) + err = mz_zip_entry_write_crc_sizes(stream, zip64, mask, file_info); + + if (mask) { + snprintf(masked_name, sizeof(masked_name), "%" PRIx32 "_%" PRIx64, file_info->disk_number, + file_info->disk_offset); + filename = masked_name; + } else { + filename = file_info->filename; + } + + filename_length = (uint16_t)strlen(filename); + filename_size += filename_length; + + if ((mz_zip_attrib_is_dir(file_info->external_fa, file_info->version_madeby) == MZ_OK) && + ((filename[filename_length - 1] != '/') && (filename[filename_length - 1] != '\\'))) { + filename_size += 1; + write_end_slash = 1; + } + + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, filename_size); + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, extrafield_size); + + if (!local) { + if (file_info->comment) { + comment_size = (int32_t)strlen(file_info->comment); + if (comment_size > UINT16_MAX) + comment_size = UINT16_MAX; + } + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, (uint16_t)comment_size); + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, (uint16_t)file_info->disk_number); + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, file_info->internal_fa); + if (err == MZ_OK) + err = mz_stream_write_uint32(stream, file_info->external_fa); + if (err == MZ_OK) { + if (file_info->disk_offset >= UINT32_MAX) + err = mz_stream_write_uint32(stream, UINT32_MAX); + else + err = mz_stream_write_uint32(stream, (uint32_t)file_info->disk_offset); + } + } + + if (err == MZ_OK) { + const char *next = filename; + int32_t left = filename_length; +#if defined(_WIN32) + const char *backslash = NULL; + + /* Ensure all slashes are written as forward slashes according to 4.4.17.1 */ + while ((err == MZ_OK) && (backslash = strchr(next, '\\'))) { + int32_t part_length = (int32_t)(backslash - next); + + if (mz_stream_write(stream, next, part_length) != part_length || mz_stream_write(stream, "/", 1) != 1) + err = MZ_WRITE_ERROR; + + left -= part_length + 1; + next = backslash + 1; + } +#endif + if (err == MZ_OK && left > 0) { + if (mz_stream_write(stream, next, left) != left) + err = MZ_WRITE_ERROR; + } + + /* Ensure that directories have a slash appended to them for compatibility */ + if (err == MZ_OK && write_end_slash) + err = mz_stream_write_uint8(stream, '/'); + } + + /* Write ZIP64 extra field first so we can update sizes later if data descriptor not used */ + if ((err == MZ_OK) && (zip64)) { + err = mz_zip_extrafield_write(stream, MZ_ZIP_EXTENSION_ZIP64, field_length_zip64); + if (err == MZ_OK) { + if (mask) + err = mz_stream_write_int64(stream, 0); + else + err = mz_stream_write_int64(stream, file_info->uncompressed_size); + } + if (err == MZ_OK) + err = mz_stream_write_int64(stream, file_info->compressed_size); + if ((err == MZ_OK) && (!local) && (file_info->disk_offset >= UINT32_MAX)) + err = mz_stream_write_int64(stream, file_info->disk_offset); + if ((err == MZ_OK) && (!local) && (file_info->disk_number >= UINT16_MAX)) + err = mz_stream_write_uint32(stream, file_info->disk_number); + } + /* Write NTFS extra field */ + if ((err == MZ_OK) && (field_length_ntfs > 0)) { + err = mz_zip_extrafield_write(stream, MZ_ZIP_EXTENSION_NTFS, field_length_ntfs); + if (err == MZ_OK) + err = mz_stream_write_uint32(stream, reserved); + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, 0x01); + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, field_length_ntfs - 8); + if (err == MZ_OK) { + mz_zip_unix_to_ntfs_time(file_info->modified_date, &ntfs_time); + err = mz_stream_write_uint64(stream, ntfs_time); + } + if (err == MZ_OK) { + mz_zip_unix_to_ntfs_time(file_info->accessed_date, &ntfs_time); + err = mz_stream_write_uint64(stream, ntfs_time); + } + if (err == MZ_OK) { + mz_zip_unix_to_ntfs_time(file_info->creation_date, &ntfs_time); + err = mz_stream_write_uint64(stream, ntfs_time); + } + } + /* Write UNIX extra block extra field */ + if ((err == MZ_OK) && (field_length_unix1 > 0)) { + err = mz_zip_extrafield_write(stream, MZ_ZIP_EXTENSION_UNIX1, field_length_unix1); + if (err == MZ_OK) + err = mz_stream_write_uint32(stream, (uint32_t)file_info->accessed_date); + if (err == MZ_OK) + err = mz_stream_write_uint32(stream, (uint32_t)file_info->modified_date); + if (err == MZ_OK) /* User id */ + err = mz_stream_write_uint16(stream, 0); + if (err == MZ_OK) /* Group id */ + err = mz_stream_write_uint16(stream, 0); + if (err == MZ_OK && linkname_size > 0) { + if (mz_stream_write(stream, file_info->linkname, linkname_size) != linkname_size) + err = MZ_WRITE_ERROR; + } + } +#ifdef HAVE_WZAES + /* Write AES extra field */ + if ((err == MZ_OK) && (!skip_aes) && (file_info->flag & MZ_ZIP_FLAG_ENCRYPTED) && (file_info->aes_version)) { + err = mz_zip_extrafield_write(stream, MZ_ZIP_EXTENSION_AES, field_length_aes); + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, file_info->aes_version); + if (err == MZ_OK) + err = mz_stream_write_uint8(stream, 'A'); + if (err == MZ_OK) + err = mz_stream_write_uint8(stream, 'E'); + if (err == MZ_OK) + err = mz_stream_write_uint8(stream, file_info->aes_strength); + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, file_info->compression_method); + } +#endif + + if (file_info->extrafield_size > 0) { + err_mem = mz_stream_mem_seek(file_extra_stream, 0, MZ_SEEK_SET); + while (err == MZ_OK && err_mem == MZ_OK) { + err_mem = mz_stream_read_uint16(file_extra_stream, &field_type); + if (err_mem == MZ_OK) + err_mem = mz_stream_read_uint16(file_extra_stream, &field_length); + if (err_mem != MZ_OK) + break; + + /* Prefer our zip 64, ntfs, unix1 extensions over incoming */ + if (field_type == MZ_ZIP_EXTENSION_ZIP64 || field_type == MZ_ZIP_EXTENSION_NTFS || + field_type == MZ_ZIP_EXTENSION_UNIX1) { + err_mem = mz_stream_seek(file_extra_stream, field_length, MZ_SEEK_CUR); + continue; + } + + err = mz_stream_write_uint16(stream, field_type); + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, field_length); + if (err == MZ_OK) + err = mz_stream_copy(stream, file_extra_stream, field_length); + } + + mz_stream_mem_delete(&file_extra_stream); + } + + if (err == MZ_OK && !local && file_info->comment) { + if (mz_stream_write(stream, file_info->comment, file_info->comment_size) != file_info->comment_size) + err = MZ_WRITE_ERROR; + } + + return err; +} + +static int32_t mz_zip_entry_write_descriptor(void *stream, uint8_t zip64, uint32_t crc32, int64_t compressed_size, + int64_t uncompressed_size) { + int32_t err = MZ_OK; + + err = mz_stream_write_uint32(stream, MZ_ZIP_MAGIC_DATADESCRIPTOR); + if (err == MZ_OK) + err = mz_stream_write_uint32(stream, crc32); + + /* Store data descriptor as 8 bytes if zip 64 extension enabled */ + if (err == MZ_OK) { + /* Zip 64 extension is enabled when uncompressed size is > UINT32_MAX */ + if (!zip64) + err = mz_stream_write_uint32(stream, (uint32_t)compressed_size); + else + err = mz_stream_write_int64(stream, compressed_size); + } + if (err == MZ_OK) { + if (!zip64) + err = mz_stream_write_uint32(stream, (uint32_t)uncompressed_size); + else + err = mz_stream_write_int64(stream, uncompressed_size); + } + + return err; +} + +static int32_t mz_zip_read_cd(void *handle) { + mz_zip *zip = (mz_zip *)handle; + uint64_t number_entry_cd64 = 0; + uint64_t number_entry_cd = 0; + int64_t eocd_pos = 0; + int64_t eocd_pos64 = 0; + int64_t value64i = 0; + uint16_t value16 = 0; + uint32_t value32 = 0; + uint64_t value64 = 0; + uint16_t comment_size = 0; + int32_t comment_read = 0; + int32_t err = MZ_OK; + + if (!zip) + return MZ_PARAM_ERROR; + + /* Read and cache central directory records */ + err = mz_zip_search_eocd(zip->stream, &eocd_pos); + if (err == MZ_OK) { + /* The signature, already checked */ + err = mz_stream_read_uint32(zip->stream, &value32); + /* Number of this disk */ + if (err == MZ_OK) + err = mz_stream_read_uint16(zip->stream, &value16); + /* Number of the disk with the start of the central directory */ + if (err == MZ_OK) + err = mz_stream_read_uint16(zip->stream, &value16); + zip->disk_number_with_cd = value16; + /* Total number of entries in the central dir on this disk */ + if (err == MZ_OK) + err = mz_stream_read_uint16(zip->stream, &value16); + zip->number_entry = value16; + /* Total number of entries in the central dir */ + if (err == MZ_OK) + err = mz_stream_read_uint16(zip->stream, &value16); + number_entry_cd = value16; + /* When recover is enabled, we can ignore incorrect number of entries */ + if (number_entry_cd != zip->number_entry && !zip->recover) + err = MZ_FORMAT_ERROR; + /* Size of the central directory */ + if (err == MZ_OK) + err = mz_stream_read_uint32(zip->stream, &value32); + if (err == MZ_OK) + zip->cd_size = value32; + /* Offset of start of central directory with respect to the starting disk number */ + if (err == MZ_OK) + err = mz_stream_read_uint32(zip->stream, &value32); + if (err == MZ_OK) + zip->cd_offset = value32; + /* Zip file global comment length */ + if (err == MZ_OK) + err = mz_stream_read_uint16(zip->stream, &comment_size); + if ((err == MZ_OK) && (comment_size > 0)) { + zip->comment = (char *)malloc(comment_size + 1); + if (zip->comment) { + comment_read = mz_stream_read(zip->stream, zip->comment, comment_size); + /* Don't fail if incorrect comment length read, not critical */ + if (comment_read < 0) + comment_read = 0; + zip->comment[comment_read] = 0; + } + } + + if ((err == MZ_OK) && ((number_entry_cd == UINT16_MAX) || (zip->cd_offset == UINT32_MAX))) { + /* Format should be Zip64, as the central directory or file size is too large */ + if (mz_zip_search_zip64_eocd(zip->stream, eocd_pos, &eocd_pos64) == MZ_OK) { + eocd_pos = eocd_pos64; + + err = mz_stream_seek(zip->stream, eocd_pos, MZ_SEEK_SET); + /* The signature, already checked */ + if (err == MZ_OK) + err = mz_stream_read_uint32(zip->stream, &value32); + /* Size of zip64 end of central directory record */ + if (err == MZ_OK) + err = mz_stream_read_uint64(zip->stream, &value64); + /* Version made by */ + if (err == MZ_OK) + err = mz_stream_read_uint16(zip->stream, &zip->version_madeby); + /* Version needed to extract */ + if (err == MZ_OK) + err = mz_stream_read_uint16(zip->stream, &value16); + /* Number of this disk */ + if (err == MZ_OK) + err = mz_stream_read_uint32(zip->stream, &value32); + /* Number of the disk with the start of the central directory */ + if (err == MZ_OK) + err = mz_stream_read_uint32(zip->stream, &zip->disk_number_with_cd); + /* Total number of entries in the central directory on this disk */ + if (err == MZ_OK) + err = mz_stream_read_uint64(zip->stream, &zip->number_entry); + /* Total number of entries in the central directory */ + if (err == MZ_OK) + err = mz_stream_read_uint64(zip->stream, &number_entry_cd64); + if (zip->number_entry != number_entry_cd64) + err = MZ_FORMAT_ERROR; + /* Size of the central directory */ + if (err == MZ_OK) { + err = mz_stream_read_int64(zip->stream, &zip->cd_size); + if (zip->cd_size < 0) + err = MZ_FORMAT_ERROR; + } + /* Offset of start of central directory with respect to the starting disk number */ + if (err == MZ_OK) { + err = mz_stream_read_int64(zip->stream, &zip->cd_offset); + if (zip->cd_offset < 0) + err = MZ_FORMAT_ERROR; + } + } else if ((zip->number_entry == UINT16_MAX) || (number_entry_cd != zip->number_entry) || + (zip->cd_size == UINT16_MAX) || (zip->cd_offset == UINT32_MAX)) { + err = MZ_FORMAT_ERROR; + } + } + } + + if (err == MZ_OK) { + mz_zip_print("Zip - Read cd (disk %" PRId32 " entries %" PRId64 " offset %" PRId64 " size %" PRId64 ")\n", + zip->disk_number_with_cd, zip->number_entry, zip->cd_offset, zip->cd_size); + + /* Verify central directory signature exists at offset */ + err = mz_stream_seek(zip->stream, zip->cd_offset, MZ_SEEK_SET); + if (err == MZ_OK) + err = mz_stream_read_uint32(zip->stream, &zip->cd_signature); + if ((err == MZ_OK) && (zip->cd_signature != MZ_ZIP_MAGIC_CENTRALHEADER)) { + /* If cd exists in large file and no zip-64 support, error for recover */ + if (eocd_pos > UINT32_MAX && eocd_pos64 == 0) + err = MZ_FORMAT_ERROR; + /* If cd not found attempt to seek backward to find it */ + if (err == MZ_OK) + err = mz_stream_seek(zip->stream, eocd_pos - zip->cd_size, MZ_SEEK_SET); + if (err == MZ_OK) + err = mz_stream_read_uint32(zip->stream, &zip->cd_signature); + if ((err == MZ_OK) && (zip->cd_signature == MZ_ZIP_MAGIC_CENTRALHEADER)) { + /* If found compensate for incorrect locations */ + value64i = zip->cd_offset; + zip->cd_offset = eocd_pos - zip->cd_size; + /* Assume disk has prepended data */ + zip->disk_offset_shift = zip->cd_offset - value64i; + } + } + } + + if (err == MZ_OK) { + if (eocd_pos < zip->cd_offset) { + /* End of central dir should always come after central dir */ + err = MZ_FORMAT_ERROR; + } else if ((uint64_t)eocd_pos < (uint64_t)zip->cd_offset + zip->cd_size) { + /* Truncate size of cd if incorrect size or offset provided */ + zip->cd_size = eocd_pos - zip->cd_offset; + } + } + + return err; +} + +static int32_t mz_zip_write_cd(void *handle) { + mz_zip *zip = (mz_zip *)handle; + int64_t zip64_eocd_pos_inzip = 0; + int64_t disk_number = 0; + int64_t disk_size = 0; + int32_t comment_size = 0; + int32_t err = MZ_OK; + + if (!zip) + return MZ_PARAM_ERROR; + + if (mz_stream_get_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, &disk_number) == MZ_OK) + zip->disk_number_with_cd = (uint32_t)disk_number; + if (mz_stream_get_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_SIZE, &disk_size) == MZ_OK && disk_size > 0) + zip->disk_number_with_cd += 1; + mz_stream_set_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, -1); + if ((zip->disk_number_with_cd > 0) && (zip->open_mode & MZ_OPEN_MODE_APPEND)) { + /* Overwrite existing central directory if using split disks */ + mz_stream_seek(zip->stream, 0, MZ_SEEK_SET); + } + + zip->cd_offset = mz_stream_tell(zip->stream); + mz_stream_seek(zip->cd_mem_stream, 0, MZ_SEEK_END); + zip->cd_size = (uint32_t)mz_stream_tell(zip->cd_mem_stream); + mz_stream_seek(zip->cd_mem_stream, 0, MZ_SEEK_SET); + + err = mz_stream_copy(zip->stream, zip->cd_mem_stream, (int32_t)zip->cd_size); + + mz_zip_print("Zip - Write cd (disk %" PRId32 " entries %" PRId64 " offset %" PRId64 " size %" PRId64 ")\n", + zip->disk_number_with_cd, zip->number_entry, zip->cd_offset, zip->cd_size); + + if (zip->cd_size == 0 && zip->number_entry > 0) { + /* Zip does not contain central directory, open with recovery option */ + return MZ_FORMAT_ERROR; + } + + /* Write the ZIP64 central directory header */ + if (zip->cd_offset >= UINT32_MAX || zip->number_entry >= UINT16_MAX) { + zip64_eocd_pos_inzip = mz_stream_tell(zip->stream); + + err = mz_stream_write_uint32(zip->stream, MZ_ZIP_MAGIC_ENDHEADER64); + + /* Size of this 'zip64 end of central directory' */ + if (err == MZ_OK) + err = mz_stream_write_uint64(zip->stream, (uint64_t)44); + /* Version made by */ + if (err == MZ_OK) + err = mz_stream_write_uint16(zip->stream, zip->version_madeby); + /* Version needed */ + if (err == MZ_OK) + err = mz_stream_write_uint16(zip->stream, (uint16_t)45); + /* Number of this disk */ + if (err == MZ_OK) + err = mz_stream_write_uint32(zip->stream, zip->disk_number_with_cd); + /* Number of the disk with the start of the central directory */ + if (err == MZ_OK) + err = mz_stream_write_uint32(zip->stream, zip->disk_number_with_cd); + /* Total number of entries in the central dir on this disk */ + if (err == MZ_OK) + err = mz_stream_write_uint64(zip->stream, zip->number_entry); + /* Total number of entries in the central dir */ + if (err == MZ_OK) + err = mz_stream_write_uint64(zip->stream, zip->number_entry); + /* Size of the central directory */ + if (err == MZ_OK) + err = mz_stream_write_int64(zip->stream, zip->cd_size); + /* Offset of start of central directory with respect to the starting disk number */ + if (err == MZ_OK) + err = mz_stream_write_int64(zip->stream, zip->cd_offset); + if (err == MZ_OK) + err = mz_stream_write_uint32(zip->stream, MZ_ZIP_MAGIC_ENDLOCHEADER64); + + /* Number of the disk with the start of the central directory */ + if (err == MZ_OK) + err = mz_stream_write_uint32(zip->stream, zip->disk_number_with_cd); + /* Relative offset to the end of zip64 central directory */ + if (err == MZ_OK) + err = mz_stream_write_int64(zip->stream, zip64_eocd_pos_inzip); + /* Number of the disk with the start of the central directory */ + if (err == MZ_OK) + err = mz_stream_write_uint32(zip->stream, zip->disk_number_with_cd + 1); + } + + /* Write the central directory header */ + + /* Signature */ + if (err == MZ_OK) + err = mz_stream_write_uint32(zip->stream, MZ_ZIP_MAGIC_ENDHEADER); + /* Number of this disk */ + if (err == MZ_OK) + err = mz_stream_write_uint16(zip->stream, (uint16_t)zip->disk_number_with_cd); + /* Number of the disk with the start of the central directory */ + if (err == MZ_OK) + err = mz_stream_write_uint16(zip->stream, (uint16_t)zip->disk_number_with_cd); + /* Total number of entries in the central dir on this disk */ + if (err == MZ_OK) { + if (zip->number_entry >= UINT16_MAX) + err = mz_stream_write_uint16(zip->stream, UINT16_MAX); + else + err = mz_stream_write_uint16(zip->stream, (uint16_t)zip->number_entry); + } + /* Total number of entries in the central dir */ + if (err == MZ_OK) { + if (zip->number_entry >= UINT16_MAX) + err = mz_stream_write_uint16(zip->stream, UINT16_MAX); + else + err = mz_stream_write_uint16(zip->stream, (uint16_t)zip->number_entry); + } + /* Size of the central directory */ + if (err == MZ_OK) + err = mz_stream_write_uint32(zip->stream, (uint32_t)zip->cd_size); + /* Offset of start of central directory with respect to the starting disk number */ + if (err == MZ_OK) { + if (zip->cd_offset >= UINT32_MAX) + err = mz_stream_write_uint32(zip->stream, UINT32_MAX); + else + err = mz_stream_write_uint32(zip->stream, (uint32_t)zip->cd_offset); + } + + /* Write global comment */ + if (zip->comment) { + comment_size = (int32_t)strlen(zip->comment); + if (comment_size > UINT16_MAX) + comment_size = UINT16_MAX; + } + if (err == MZ_OK) + err = mz_stream_write_uint16(zip->stream, (uint16_t)comment_size); + if (err == MZ_OK) { + if (mz_stream_write(zip->stream, zip->comment, comment_size) != comment_size) + err = MZ_READ_ERROR; + } + return err; +} + +static int32_t mz_zip_recover_cd(void *handle) { + mz_zip *zip = (mz_zip *)handle; + mz_zip_file local_file_info; + void *local_file_info_stream = NULL; + void *cd_mem_stream = NULL; + uint64_t number_entry = 0; + int64_t descriptor_pos = 0; + int64_t next_header_pos = 0; + int64_t disk_offset = 0; + int64_t disk_number = 0; + int64_t compressed_pos = 0; + int64_t compressed_end_pos = 0; + int64_t compressed_size = 0; + int64_t uncompressed_size = 0; + uint8_t descriptor_magic[4] = MZ_ZIP_MAGIC_DATADESCRIPTORU8; + uint8_t local_header_magic[4] = MZ_ZIP_MAGIC_LOCALHEADERU8; + uint8_t central_header_magic[4] = MZ_ZIP_MAGIC_CENTRALHEADERU8; + uint32_t crc32 = 0; + int32_t disk_number_with_cd = 0; + int32_t err = MZ_OK; + uint8_t zip64 = 0; + uint8_t eof = 0; + + mz_zip_print("Zip - Recover - Start\n"); + + err = mz_zip_get_cd_mem_stream(zip, &cd_mem_stream); + if (err != MZ_OK) + return err; + + /* Determine if we are on a split disk or not */ + mz_stream_set_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, 0); + if (mz_stream_tell(zip->stream) < 0) { + mz_stream_set_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, -1); + mz_stream_seek(zip->stream, 0, MZ_SEEK_SET); + } else + disk_number_with_cd = 1; + + local_file_info_stream = mz_stream_mem_create(); + if (!local_file_info_stream) + return MZ_MEM_ERROR; + + if (mz_stream_is_open(cd_mem_stream) != MZ_OK) + err = mz_stream_mem_open(cd_mem_stream, NULL, MZ_OPEN_MODE_CREATE); + + mz_stream_mem_open(local_file_info_stream, NULL, MZ_OPEN_MODE_CREATE); + + if (err == MZ_OK) { + err = mz_stream_find(zip->stream, (const void *)local_header_magic, sizeof(local_header_magic), INT64_MAX, + &next_header_pos); + } + + while (err == MZ_OK && !eof) { + /* Get current offset and disk number for central dir record */ + disk_offset = mz_stream_tell(zip->stream); + mz_stream_get_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, &disk_number); + + /* Read local headers */ + memset(&local_file_info, 0, sizeof(local_file_info)); + err = mz_zip_entry_read_header(zip->stream, 1, &local_file_info, local_file_info_stream); + if (err != MZ_OK) + break; + + local_file_info.disk_offset = disk_offset; + if (disk_number < 0) + disk_number = 0; + local_file_info.disk_number = (uint32_t)disk_number; + + compressed_pos = mz_stream_tell(zip->stream); + + if ((err == MZ_OK) && (local_file_info.compressed_size > 0)) { + mz_stream_seek(zip->stream, local_file_info.compressed_size, MZ_SEEK_CUR); + } + + for (;;) { + /* Search for the next local header */ + err = mz_stream_find(zip->stream, (const void *)local_header_magic, sizeof(local_header_magic), INT64_MAX, + &next_header_pos); + + if (err == MZ_EXIST_ERROR) { + mz_stream_seek(zip->stream, compressed_pos, MZ_SEEK_SET); + + /* Search for central dir if no local header found */ + err = mz_stream_find(zip->stream, (const void *)central_header_magic, sizeof(central_header_magic), + INT64_MAX, &next_header_pos); + + if (err == MZ_EXIST_ERROR) { + /* Get end of stream if no central header found */ + mz_stream_seek(zip->stream, 0, MZ_SEEK_END); + next_header_pos = mz_stream_tell(zip->stream); + } + + eof = 1; + } + + if (local_file_info.flag & MZ_ZIP_FLAG_DATA_DESCRIPTOR || local_file_info.compressed_size == 0) { + /* Search backwards for the descriptor, seeking too far back will be incorrect if compressed size is + * small */ + err = mz_stream_find_reverse(zip->stream, (const void *)descriptor_magic, sizeof(descriptor_magic), + MZ_ZIP_SIZE_MAX_DATA_DESCRIPTOR, &descriptor_pos); + if (err == MZ_OK) { + if (mz_zip_extrafield_contains(local_file_info.extrafield, local_file_info.extrafield_size, + MZ_ZIP_EXTENSION_ZIP64, NULL) == MZ_OK) + zip64 = 1; + + err = + mz_zip_entry_read_descriptor(zip->stream, zip64, &crc32, &compressed_size, &uncompressed_size); + + if (err == MZ_OK) { + if (local_file_info.crc == 0) + local_file_info.crc = crc32; + if (local_file_info.compressed_size == 0) + local_file_info.compressed_size = compressed_size; + if (local_file_info.uncompressed_size == 0) + local_file_info.uncompressed_size = uncompressed_size; + } + + compressed_end_pos = descriptor_pos; + } else if (eof) { + compressed_end_pos = next_header_pos; + } else if (local_file_info.flag & MZ_ZIP_FLAG_DATA_DESCRIPTOR) { + /* Wrong local file entry found, keep searching */ + next_header_pos += 1; + mz_stream_seek(zip->stream, next_header_pos, MZ_SEEK_SET); + continue; + } + } else { + compressed_end_pos = next_header_pos; + } + + break; + } + + compressed_size = compressed_end_pos - compressed_pos; + + if (compressed_size > UINT32_MAX) { + /* Update sizes if 4GB file is written with no ZIP64 support */ + if (local_file_info.uncompressed_size < UINT32_MAX) { + local_file_info.compressed_size = compressed_size; + local_file_info.uncompressed_size = 0; + } + } + + mz_zip_print("Zip - Recover - Entry %s (csize %" PRId64 " usize %" PRId64 " flags 0x%" PRIx16 ")\n", + local_file_info.filename, local_file_info.compressed_size, local_file_info.uncompressed_size, + local_file_info.flag); + + /* Rewrite central dir with local headers and offsets */ + err = mz_zip_entry_write_header(cd_mem_stream, 0, &local_file_info); + if (err == MZ_OK) + number_entry += 1; + + err = mz_stream_seek(zip->stream, next_header_pos, MZ_SEEK_SET); + } + + mz_stream_mem_delete(&local_file_info_stream); + + mz_zip_print("Zip - Recover - Complete (cddisk %" PRId32 " entries %" PRId64 ")\n", disk_number_with_cd, + number_entry); + + if (number_entry == 0) + return err; + + /* Set new upper seek boundary for central dir mem stream */ + disk_offset = mz_stream_tell(cd_mem_stream); + mz_stream_mem_set_buffer_limit(cd_mem_stream, (int32_t)disk_offset); + + /* Set new central directory info */ + mz_zip_set_cd_stream(zip, 0, cd_mem_stream); + mz_zip_set_number_entry(zip, number_entry); + mz_zip_set_disk_number_with_cd(zip, disk_number_with_cd); + + return MZ_OK; +} + +void *mz_zip_create(void) { + mz_zip *zip = (mz_zip *)calloc(1, sizeof(mz_zip)); + if (zip) + zip->data_descriptor = 1; + return zip; +} + +void mz_zip_delete(void **handle) { + mz_zip *zip = NULL; + if (!handle) + return; + zip = (mz_zip *)*handle; + free(zip); + *handle = NULL; +} + +int32_t mz_zip_open(void *handle, void *stream, int32_t mode) { + mz_zip *zip = (mz_zip *)handle; + int32_t err = MZ_OK; + + if (!zip) + return MZ_PARAM_ERROR; + + mz_zip_print("Zip - Open\n"); + + zip->stream = stream; + zip->cd_mem_stream = mz_stream_mem_create(); + if (!zip->cd_mem_stream) + return MZ_MEM_ERROR; + + if (mode & MZ_OPEN_MODE_WRITE) { + mz_stream_mem_open(zip->cd_mem_stream, NULL, MZ_OPEN_MODE_CREATE); + zip->cd_stream = zip->cd_mem_stream; + } else { + zip->cd_stream = stream; + } + + if ((mode & MZ_OPEN_MODE_READ) || (mode & MZ_OPEN_MODE_APPEND)) { + if ((mode & MZ_OPEN_MODE_CREATE) == 0) { + err = mz_zip_read_cd(zip); + if (err != MZ_OK) { + mz_zip_print("Zip - Error detected reading cd (%" PRId32 ")\n", err); + if (zip->recover && mz_zip_recover_cd(zip) == MZ_OK) + err = MZ_OK; + } + } + + if ((err == MZ_OK) && (mode & MZ_OPEN_MODE_APPEND)) { + if (zip->cd_size > 0) { + /* Store central directory in memory */ + err = mz_stream_seek(zip->stream, zip->cd_offset, MZ_SEEK_SET); + if (err == MZ_OK) + err = mz_stream_copy(zip->cd_mem_stream, zip->stream, (int32_t)zip->cd_size); + if (err == MZ_OK) + err = mz_stream_seek(zip->stream, zip->cd_offset, MZ_SEEK_SET); + } else { + if (zip->cd_signature == MZ_ZIP_MAGIC_ENDHEADER) { + /* If tiny zip then overwrite end header */ + err = mz_stream_seek(zip->stream, zip->cd_offset, MZ_SEEK_SET); + } else { + /* If no central directory, append new zip to end of file */ + err = mz_stream_seek(zip->stream, 0, MZ_SEEK_END); + } + } + + if (zip->disk_number_with_cd > 0) { + /* Move to last disk to begin appending */ + mz_stream_set_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, zip->disk_number_with_cd - 1); + } + } else { + zip->cd_start_pos = zip->cd_offset; + } + } + + if (err != MZ_OK) { + mz_zip_close(zip); + return err; + } + + /* Memory streams used to store variable length file info data */ + zip->file_info_stream = mz_stream_mem_create(); + if (!zip->file_info_stream) + return MZ_MEM_ERROR; + + mz_stream_mem_open(zip->file_info_stream, NULL, MZ_OPEN_MODE_CREATE); + + zip->local_file_info_stream = mz_stream_mem_create(); + if (!zip->local_file_info_stream) { + mz_stream_delete(&zip->file_info_stream); + return MZ_MEM_ERROR; + } + + mz_stream_mem_open(zip->local_file_info_stream, NULL, MZ_OPEN_MODE_CREATE); + + zip->open_mode = mode; + + return err; +} + +int32_t mz_zip_close(void *handle) { + mz_zip *zip = (mz_zip *)handle; + int32_t err = MZ_OK; + + if (!zip) + return MZ_PARAM_ERROR; + + mz_zip_print("Zip - Close\n"); + + if (mz_zip_entry_is_open(zip) == MZ_OK) + err = mz_zip_entry_close(zip); + + if ((err == MZ_OK) && (zip->open_mode & MZ_OPEN_MODE_WRITE)) + err = mz_zip_write_cd(zip); + + if (zip->cd_mem_stream) { + mz_stream_close(zip->cd_mem_stream); + mz_stream_delete(&zip->cd_mem_stream); + } + + if (zip->file_info_stream) { + mz_stream_mem_close(zip->file_info_stream); + mz_stream_mem_delete(&zip->file_info_stream); + } + if (zip->local_file_info_stream) { + mz_stream_mem_close(zip->local_file_info_stream); + mz_stream_mem_delete(&zip->local_file_info_stream); + } + + if (zip->comment) { + free(zip->comment); + zip->comment = NULL; + } + + zip->stream = NULL; + zip->cd_stream = NULL; + + return err; +} + +int32_t mz_zip_get_comment(void *handle, const char **comment) { + mz_zip *zip = (mz_zip *)handle; + if (!zip || !comment) + return MZ_PARAM_ERROR; + if (!zip->comment) + return MZ_EXIST_ERROR; + *comment = zip->comment; + return MZ_OK; +} + +int32_t mz_zip_set_comment(void *handle, const char *comment) { + mz_zip *zip = (mz_zip *)handle; + int32_t comment_size = 0; + if (!zip || !comment) + return MZ_PARAM_ERROR; + free(zip->comment); + comment_size = (int32_t)strlen(comment); + if (comment_size > UINT16_MAX) + return MZ_PARAM_ERROR; + zip->comment = (char *)calloc(comment_size + 1, sizeof(char)); + if (!zip->comment) + return MZ_MEM_ERROR; + strncpy(zip->comment, comment, comment_size); + return MZ_OK; +} + +int32_t mz_zip_get_version_madeby(void *handle, uint16_t *version_madeby) { + mz_zip *zip = (mz_zip *)handle; + if (!zip || !version_madeby) + return MZ_PARAM_ERROR; + *version_madeby = zip->version_madeby; + return MZ_OK; +} + +int32_t mz_zip_set_version_madeby(void *handle, uint16_t version_madeby) { + mz_zip *zip = (mz_zip *)handle; + if (!zip) + return MZ_PARAM_ERROR; + zip->version_madeby = version_madeby; + return MZ_OK; +} + +int32_t mz_zip_set_recover(void *handle, uint8_t recover) { + mz_zip *zip = (mz_zip *)handle; + if (!zip) + return MZ_PARAM_ERROR; + zip->recover = recover; + return MZ_OK; +} + +int32_t mz_zip_set_data_descriptor(void *handle, uint8_t data_descriptor) { + mz_zip *zip = (mz_zip *)handle; + if (!zip) + return MZ_PARAM_ERROR; + zip->data_descriptor = data_descriptor; + return MZ_OK; +} + +int32_t mz_zip_get_stream(void *handle, void **stream) { + mz_zip *zip = (mz_zip *)handle; + if (!zip || !stream) + return MZ_PARAM_ERROR; + *stream = zip->stream; + if (!*stream) + return MZ_EXIST_ERROR; + return MZ_OK; +} + +int32_t mz_zip_set_cd_stream(void *handle, int64_t cd_start_pos, void *cd_stream) { + mz_zip *zip = (mz_zip *)handle; + if (!zip || !cd_stream) + return MZ_PARAM_ERROR; + zip->cd_offset = 0; + zip->cd_stream = cd_stream; + zip->cd_start_pos = cd_start_pos; + return MZ_OK; +} + +int32_t mz_zip_get_cd_mem_stream(void *handle, void **cd_mem_stream) { + mz_zip *zip = (mz_zip *)handle; + if (!zip || !cd_mem_stream) + return MZ_PARAM_ERROR; + *cd_mem_stream = zip->cd_mem_stream; + if (!*cd_mem_stream) + return MZ_EXIST_ERROR; + return MZ_OK; +} + +int32_t mz_zip_set_number_entry(void *handle, uint64_t number_entry) { + mz_zip *zip = (mz_zip *)handle; + if (!zip) + return MZ_PARAM_ERROR; + zip->number_entry = number_entry; + return MZ_OK; +} + +int32_t mz_zip_get_number_entry(void *handle, uint64_t *number_entry) { + mz_zip *zip = (mz_zip *)handle; + if (!zip || !number_entry) + return MZ_PARAM_ERROR; + *number_entry = zip->number_entry; + return MZ_OK; +} + +int32_t mz_zip_set_disk_number_with_cd(void *handle, uint32_t disk_number_with_cd) { + mz_zip *zip = (mz_zip *)handle; + if (!zip) + return MZ_PARAM_ERROR; + zip->disk_number_with_cd = disk_number_with_cd; + return MZ_OK; +} + +int32_t mz_zip_get_disk_number_with_cd(void *handle, uint32_t *disk_number_with_cd) { + mz_zip *zip = (mz_zip *)handle; + if (!zip || !disk_number_with_cd) + return MZ_PARAM_ERROR; + *disk_number_with_cd = zip->disk_number_with_cd; + return MZ_OK; +} + +static int32_t mz_zip_entry_close_int(void *handle) { + mz_zip *zip = (mz_zip *)handle; + + if (zip->crypt_stream) + mz_stream_delete(&zip->crypt_stream); + zip->crypt_stream = NULL; + if (zip->compress_stream) + mz_stream_delete(&zip->compress_stream); + zip->compress_stream = NULL; + + zip->entry_opened = 0; + + return MZ_OK; +} + +static int32_t mz_zip_entry_open_int(void *handle, uint8_t raw, int16_t compress_level, const char *password) { + mz_zip *zip = (mz_zip *)handle; + int64_t max_total_in = 0; + int64_t header_size = 0; + int64_t footer_size = 0; + int32_t err = MZ_OK; + uint8_t use_crypt = 0; + + if (!zip) + return MZ_PARAM_ERROR; + + switch (zip->file_info.compression_method) { + case MZ_COMPRESS_METHOD_STORE: + case MZ_COMPRESS_METHOD_DEFLATE: +#ifdef HAVE_BZIP2 + case MZ_COMPRESS_METHOD_BZIP2: +#endif +#ifdef HAVE_LZMA + case MZ_COMPRESS_METHOD_LZMA: +#endif +#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP) + case MZ_COMPRESS_METHOD_XZ: +#endif +#ifdef HAVE_PPMD + case MZ_COMPRESS_METHOD_PPMD: +#endif +#ifdef HAVE_ZSTD + case MZ_COMPRESS_METHOD_ZSTD: +#endif + err = MZ_OK; + break; + default: + return MZ_SUPPORT_ERROR; + } + +#ifndef HAVE_WZAES + if (zip->file_info.aes_version) + return MZ_SUPPORT_ERROR; +#endif + + zip->entry_raw = raw; + + if ((zip->file_info.flag & MZ_ZIP_FLAG_ENCRYPTED) && (password)) { + if (zip->open_mode & MZ_OPEN_MODE_WRITE) { + /* Encrypt only when we are not trying to write raw and password is supplied. */ + if (!zip->entry_raw) + use_crypt = 1; + } else if (zip->open_mode & MZ_OPEN_MODE_READ) { + /* Decrypt only when password is supplied. Don't error when password */ + /* is not supplied as we may want to read the raw encrypted data. */ + use_crypt = 1; + } + } + + if ((err == MZ_OK) && (use_crypt)) { +#ifdef HAVE_WZAES + if (zip->file_info.aes_version) { + zip->crypt_stream = mz_stream_wzaes_create(); + if (!zip->crypt_stream) + return MZ_MEM_ERROR; + mz_stream_wzaes_set_password(zip->crypt_stream, password); + mz_stream_wzaes_set_strength(zip->crypt_stream, zip->file_info.aes_strength); + } else +#endif + { +#ifdef HAVE_PKCRYPT + uint8_t verify1 = (uint8_t)((zip->file_info.pk_verify >> 8) & 0xff); + uint8_t verify2 = (uint8_t)((zip->file_info.pk_verify) & 0xff); + + zip->crypt_stream = mz_stream_pkcrypt_create(); + if (!zip->crypt_stream) + return MZ_MEM_ERROR; + mz_stream_pkcrypt_set_password(zip->crypt_stream, password); + mz_stream_pkcrypt_set_verify(zip->crypt_stream, verify1, verify2, zip->file_info.version_needed); +#endif + } + } + + if (err == MZ_OK) { + if (!zip->crypt_stream) + zip->crypt_stream = mz_stream_raw_create(); + if (!zip->crypt_stream) + return MZ_MEM_ERROR; + + mz_stream_set_base(zip->crypt_stream, zip->stream); + + err = mz_stream_open(zip->crypt_stream, NULL, zip->open_mode); + } + + if (err == MZ_OK) { + if (zip->entry_raw || zip->file_info.compression_method == MZ_COMPRESS_METHOD_STORE) + zip->compress_stream = mz_stream_raw_create(); +#ifdef HAVE_ZLIB + else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_DEFLATE) + zip->compress_stream = mz_stream_zlib_create(); +#endif +#ifdef HAVE_BZIP2 + else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_BZIP2) + zip->compress_stream = mz_stream_bzip_create(); +#endif +#ifdef HAVE_LIBCOMP + else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_DEFLATE || + zip->file_info.compression_method == MZ_COMPRESS_METHOD_XZ) { + zip->compress_stream = mz_stream_libcomp_create(); + if (zip->compress_stream) { + mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_COMPRESS_METHOD, + zip->file_info.compression_method); + } + } +#endif +#ifdef HAVE_LZMA + else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_LZMA || + zip->file_info.compression_method == MZ_COMPRESS_METHOD_XZ) { + zip->compress_stream = mz_stream_lzma_create(); + if (zip->compress_stream) { + mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_COMPRESS_METHOD, + zip->file_info.compression_method); + } + } +#endif +#ifdef HAVE_PPMD + else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_PPMD) { + zip->compress_stream = mz_stream_ppmd_create(); + if (zip->compress_stream) { + mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_TOTAL_IN_MAX, + zip->file_info.compressed_size); + } + } +#endif +#ifdef HAVE_ZSTD + else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_ZSTD) + zip->compress_stream = mz_stream_zstd_create(); +#endif + else + err = MZ_PARAM_ERROR; + } + + if (err == MZ_OK && !zip->compress_stream) + err = MZ_MEM_ERROR; + + if (err == MZ_OK) { + if (zip->open_mode & MZ_OPEN_MODE_WRITE) { + mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_COMPRESS_LEVEL, compress_level); + } else { + int32_t set_end_of_stream = 0; + +#ifndef HAVE_LIBCOMP + if (zip->entry_raw || zip->file_info.compression_method == MZ_COMPRESS_METHOD_STORE || + zip->file_info.flag & MZ_ZIP_FLAG_ENCRYPTED) +#endif + { + max_total_in = zip->file_info.compressed_size; + mz_stream_set_prop_int64(zip->crypt_stream, MZ_STREAM_PROP_TOTAL_IN_MAX, max_total_in); + + if (mz_stream_get_prop_int64(zip->crypt_stream, MZ_STREAM_PROP_HEADER_SIZE, &header_size) == MZ_OK) + max_total_in -= header_size; + if (mz_stream_get_prop_int64(zip->crypt_stream, MZ_STREAM_PROP_FOOTER_SIZE, &footer_size) == MZ_OK) + max_total_in -= footer_size; + + mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_TOTAL_IN_MAX, max_total_in); + } + + switch (zip->file_info.compression_method) { + case MZ_COMPRESS_METHOD_LZMA: + case MZ_COMPRESS_METHOD_XZ: + set_end_of_stream = (zip->file_info.flag & MZ_ZIP_FLAG_LZMA_EOS_MARKER); + break; + case MZ_COMPRESS_METHOD_ZSTD: + set_end_of_stream = 1; + break; + } + + if (set_end_of_stream) { + mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_TOTAL_IN_MAX, + zip->file_info.compressed_size); + mz_stream_set_prop_int64(zip->compress_stream, MZ_STREAM_PROP_TOTAL_OUT_MAX, + zip->file_info.uncompressed_size); + } + } + + mz_stream_set_base(zip->compress_stream, zip->crypt_stream); + + err = mz_stream_open(zip->compress_stream, NULL, zip->open_mode); + } + + if (err == MZ_OK) { + zip->entry_opened = 1; + zip->entry_crc32 = 0; + } else { + mz_zip_entry_close_int(zip); + } + + return err; +} + +int32_t mz_zip_entry_is_open(void *handle) { + mz_zip *zip = (mz_zip *)handle; + if (!zip) + return MZ_PARAM_ERROR; + if (zip->entry_opened == 0) + return MZ_EXIST_ERROR; + return MZ_OK; +} + +int32_t mz_zip_entry_read_open(void *handle, uint8_t raw, const char *password) { + mz_zip *zip = (mz_zip *)handle; + int32_t err = MZ_OK; + int32_t err_shift = MZ_OK; + +#if defined(MZ_ZIP_NO_ENCRYPTION) + if (password) + return MZ_SUPPORT_ERROR; +#endif + if (!zip || !zip->entry_scanned) + return MZ_PARAM_ERROR; + if ((zip->open_mode & MZ_OPEN_MODE_READ) == 0) + return MZ_PARAM_ERROR; + + mz_zip_print("Zip - Entry - Read open (raw %" PRId32 ")\n", raw); + + err = mz_zip_entry_seek_local_header(zip); + if (err == MZ_OK) + err = mz_zip_entry_read_header(zip->stream, 1, &zip->local_file_info, zip->local_file_info_stream); + + if (err == MZ_FORMAT_ERROR && zip->disk_offset_shift > 0) { + /* Perhaps we didn't compensated correctly for incorrect cd offset */ + err_shift = mz_stream_seek(zip->stream, zip->file_info.disk_offset, MZ_SEEK_SET); + if (err_shift == MZ_OK) + err_shift = mz_zip_entry_read_header(zip->stream, 1, &zip->local_file_info, zip->local_file_info_stream); + if (err_shift == MZ_OK) { + zip->disk_offset_shift = 0; + err = err_shift; + } + } + +#ifdef MZ_ZIP_NO_DECOMPRESSION + if (!raw && zip->file_info.compression_method != MZ_COMPRESS_METHOD_STORE) + err = MZ_SUPPORT_ERROR; +#endif + if (err == MZ_OK) + err = mz_zip_entry_open_int(zip, raw, 0, password); + + return err; +} + +int32_t mz_zip_entry_write_open(void *handle, const mz_zip_file *file_info, int16_t compress_level, uint8_t raw, + const char *password) { + mz_zip *zip = (mz_zip *)handle; + int64_t filename_pos = -1; + int64_t extrafield_pos = 0; + int64_t comment_pos = 0; + int64_t linkname_pos = 0; + int64_t disk_number = 0; + uint8_t is_dir = 0; + int32_t err = MZ_OK; + +#if defined(MZ_ZIP_NO_ENCRYPTION) + if (password) + return MZ_SUPPORT_ERROR; +#endif + if (!zip || !file_info || !file_info->filename) + return MZ_PARAM_ERROR; + + if (mz_zip_entry_is_open(zip) == MZ_OK) { + err = mz_zip_entry_close(zip); + if (err != MZ_OK) + return err; + } + + memcpy(&zip->file_info, file_info, sizeof(mz_zip_file)); + + mz_zip_print("Zip - Entry - Write open - %s (level %" PRId16 " raw %" PRId8 ")\n", zip->file_info.filename, + compress_level, raw); + + mz_stream_seek(zip->file_info_stream, 0, MZ_SEEK_SET); + mz_stream_write(zip->file_info_stream, file_info, sizeof(mz_zip_file)); + + /* Copy filename, extrafield, and comment internally */ + filename_pos = mz_stream_tell(zip->file_info_stream); + if (file_info->filename) + mz_stream_write(zip->file_info_stream, file_info->filename, (int32_t)strlen(file_info->filename)); + mz_stream_write_uint8(zip->file_info_stream, 0); + + extrafield_pos = mz_stream_tell(zip->file_info_stream); + if (file_info->extrafield) + mz_stream_write(zip->file_info_stream, file_info->extrafield, file_info->extrafield_size); + mz_stream_write_uint8(zip->file_info_stream, 0); + + comment_pos = mz_stream_tell(zip->file_info_stream); + if (file_info->comment) + mz_stream_write(zip->file_info_stream, file_info->comment, file_info->comment_size); + mz_stream_write_uint8(zip->file_info_stream, 0); + + linkname_pos = mz_stream_tell(zip->file_info_stream); + if (file_info->linkname) + mz_stream_write(zip->file_info_stream, file_info->linkname, (int32_t)strlen(file_info->linkname)); + mz_stream_write_uint8(zip->file_info_stream, 0); + + mz_stream_mem_get_buffer_at(zip->file_info_stream, filename_pos, (const void **)&zip->file_info.filename); + mz_stream_mem_get_buffer_at(zip->file_info_stream, extrafield_pos, (const void **)&zip->file_info.extrafield); + mz_stream_mem_get_buffer_at(zip->file_info_stream, comment_pos, (const void **)&zip->file_info.comment); + mz_stream_mem_get_buffer_at(zip->file_info_stream, linkname_pos, (const void **)&zip->file_info.linkname); + + if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_DEFLATE) { + if ((compress_level == 8) || (compress_level == 9)) + zip->file_info.flag |= MZ_ZIP_FLAG_DEFLATE_MAX; + if (compress_level == 2) + zip->file_info.flag |= MZ_ZIP_FLAG_DEFLATE_FAST; + if (compress_level == 1) + zip->file_info.flag |= MZ_ZIP_FLAG_DEFLATE_SUPER_FAST; + } +#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP) + else if (zip->file_info.compression_method == MZ_COMPRESS_METHOD_LZMA || + zip->file_info.compression_method == MZ_COMPRESS_METHOD_XZ) + zip->file_info.flag |= MZ_ZIP_FLAG_LZMA_EOS_MARKER; +#endif + + if (mz_zip_attrib_is_dir(zip->file_info.external_fa, zip->file_info.version_madeby) == MZ_OK) + is_dir = 1; + + if (!raw && !is_dir) { + if (zip->data_descriptor) + zip->file_info.flag |= MZ_ZIP_FLAG_DATA_DESCRIPTOR; + if (password) + zip->file_info.flag |= MZ_ZIP_FLAG_ENCRYPTED; + } + + mz_stream_get_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, &disk_number); + zip->file_info.disk_number = (uint32_t)disk_number; + zip->file_info.disk_offset = mz_stream_tell(zip->stream); + + if (zip->file_info.flag & MZ_ZIP_FLAG_ENCRYPTED) { +#ifdef HAVE_PKCRYPT + /* Pre-calculated CRC value is required for PKWARE traditional encryption */ + uint32_t dos_date = mz_zip_time_t_to_dos_date(zip->file_info.modified_date); + zip->file_info.pk_verify = mz_zip_get_pk_verify(dos_date, zip->file_info.crc, zip->file_info.flag); +#endif +#ifdef HAVE_WZAES + if (zip->file_info.aes_version && zip->file_info.aes_strength == 0) + zip->file_info.aes_strength = MZ_AES_STRENGTH_256; +#endif + } + + zip->file_info.crc = 0; + zip->file_info.compressed_size = 0; + + if ((compress_level == 0) || (is_dir)) + zip->file_info.compression_method = MZ_COMPRESS_METHOD_STORE; + +#ifdef MZ_ZIP_NO_COMPRESSION + if (zip->file_info.compression_method != MZ_COMPRESS_METHOD_STORE) + err = MZ_SUPPORT_ERROR; +#endif + if (err == MZ_OK) + err = mz_zip_entry_write_header(zip->stream, 1, &zip->file_info); + if (err == MZ_OK) + err = mz_zip_entry_open_int(zip, raw, compress_level, password); + + return err; +} + +int32_t mz_zip_entry_read(void *handle, void *buf, int32_t len) { + mz_zip *zip = (mz_zip *)handle; + int32_t read = 0; + + if (!zip || mz_zip_entry_is_open(zip) != MZ_OK) + return MZ_PARAM_ERROR; + if (UINT_MAX == UINT16_MAX && len > UINT16_MAX) /* zlib limitation */ + return MZ_PARAM_ERROR; + if (len == 0) + return MZ_PARAM_ERROR; + + if (zip->file_info.compressed_size == 0) + return 0; + + /* Read entire entry even if uncompressed_size = 0, otherwise */ + /* aes encryption validation will fail if compressed_size > 0 */ + read = mz_stream_read(zip->compress_stream, buf, len); + if (read > 0) + zip->entry_crc32 = mz_crypt_crc32_update(zip->entry_crc32, buf, read); + + mz_zip_print("Zip - Entry - Read - %" PRId32 " (max %" PRId32 ")\n", read, len); + + return read; +} + +int32_t mz_zip_entry_write(void *handle, const void *buf, int32_t len) { + mz_zip *zip = (mz_zip *)handle; + int32_t written = 0; + + if (!zip || mz_zip_entry_is_open(zip) != MZ_OK) + return MZ_PARAM_ERROR; + written = mz_stream_write(zip->compress_stream, buf, len); + if (written > 0) + zip->entry_crc32 = mz_crypt_crc32_update(zip->entry_crc32, buf, written); + + mz_zip_print("Zip - Entry - Write - %" PRId32 " (max %" PRId32 ")\n", written, len); + return written; +} + +int32_t mz_zip_entry_read_close(void *handle, uint32_t *crc32, int64_t *compressed_size, int64_t *uncompressed_size) { + mz_zip *zip = (mz_zip *)handle; + int64_t total_in = 0; + int32_t err = MZ_OK; + uint8_t zip64 = 0; + + if (!zip || mz_zip_entry_is_open(zip) != MZ_OK) + return MZ_PARAM_ERROR; + + mz_stream_close(zip->compress_stream); + + mz_zip_print("Zip - Entry - Read Close\n"); + + if (crc32) + *crc32 = zip->file_info.crc; + if (compressed_size) + *compressed_size = zip->file_info.compressed_size; + if (uncompressed_size) + *uncompressed_size = zip->file_info.uncompressed_size; + + mz_stream_get_prop_int64(zip->compress_stream, MZ_STREAM_PROP_TOTAL_IN, &total_in); + + if ((zip->file_info.flag & MZ_ZIP_FLAG_DATA_DESCRIPTOR) && + ((zip->file_info.flag & MZ_ZIP_FLAG_MASK_LOCAL_INFO) == 0) && (crc32 || compressed_size || uncompressed_size)) { + /* Check to see if data descriptor is zip64 bit format or not */ + if (mz_zip_extrafield_contains(zip->local_file_info.extrafield, zip->local_file_info.extrafield_size, + MZ_ZIP_EXTENSION_ZIP64, NULL) == MZ_OK) { + zip64 = 1; + } + + err = mz_zip_entry_seek_local_header(zip); + + /* Seek to end of compressed stream since we might have over-read during decompression */ + if (err == MZ_OK) { + err = mz_stream_seek(zip->stream, + MZ_ZIP_SIZE_LD_ITEM + (int64_t)zip->local_file_info.filename_size + + (int64_t)zip->local_file_info.extrafield_size + total_in, + MZ_SEEK_CUR); + } + + /* Read data descriptor */ + if (err == MZ_OK) + err = mz_zip_entry_read_descriptor(zip->stream, zip64, crc32, compressed_size, uncompressed_size); + } + + /* If entire entry was not read verification will fail */ + if ((err == MZ_OK) && (total_in == zip->file_info.compressed_size) && (!zip->entry_raw)) { +#ifdef HAVE_WZAES + /* AES zip version AE-1 will expect a valid crc as well */ + if (zip->file_info.aes_version <= 0x0001) +#endif + { + if (zip->entry_crc32 != zip->file_info.crc) { + mz_zip_print("Zip - Entry - Crc failed (actual 0x%08" PRIx32 " expected 0x%08" PRIx32 ")\n", + zip->entry_crc32, zip->file_info.crc); + + err = MZ_CRC_ERROR; + } + } + } + + mz_zip_entry_close_int(zip); + + return err; +} + +int32_t mz_zip_entry_write_close(void *handle, uint32_t crc32, int64_t compressed_size, int64_t uncompressed_size) { + mz_zip *zip = (mz_zip *)handle; + int64_t end_disk_number = 0; + int32_t err = MZ_OK; + uint8_t zip64 = 0; + + if (!zip || mz_zip_entry_is_open(zip) != MZ_OK) + return MZ_PARAM_ERROR; + + mz_stream_close(zip->compress_stream); + + if (!zip->entry_raw) + crc32 = zip->entry_crc32; + + mz_zip_print("Zip - Entry - Write Close (crc 0x%08" PRIx32 " cs %" PRId64 " ucs %" PRId64 ")\n", crc32, + compressed_size, uncompressed_size); + + /* If sizes are not set, then read them from the compression stream */ + if (compressed_size < 0) + mz_stream_get_prop_int64(zip->compress_stream, MZ_STREAM_PROP_TOTAL_OUT, &compressed_size); + if (uncompressed_size < 0) + mz_stream_get_prop_int64(zip->compress_stream, MZ_STREAM_PROP_TOTAL_IN, &uncompressed_size); + + if (zip->file_info.flag & MZ_ZIP_FLAG_ENCRYPTED) { + mz_stream_set_base(zip->crypt_stream, zip->stream); + err = mz_stream_close(zip->crypt_stream); + + mz_stream_get_prop_int64(zip->crypt_stream, MZ_STREAM_PROP_TOTAL_OUT, &compressed_size); + } + + mz_zip_entry_needs_zip64(&zip->file_info, 1, &zip64); + + if ((err == MZ_OK) && (zip->file_info.flag & MZ_ZIP_FLAG_DATA_DESCRIPTOR)) { + /* Determine if we need to write data descriptor in zip64 format, + if local extrafield was saved with zip64 extrafield */ + + if (zip->file_info.flag & MZ_ZIP_FLAG_MASK_LOCAL_INFO) + err = mz_zip_entry_write_descriptor(zip->stream, zip64, 0, compressed_size, 0); + else + err = mz_zip_entry_write_descriptor(zip->stream, zip64, crc32, compressed_size, uncompressed_size); + } + + /* Write file info to central directory */ + + mz_zip_print("Zip - Entry - Write cd (ucs %" PRId64 " cs %" PRId64 " crc 0x%08" PRIx32 ")\n", uncompressed_size, + compressed_size, crc32); + + zip->file_info.crc = crc32; + zip->file_info.compressed_size = compressed_size; + zip->file_info.uncompressed_size = uncompressed_size; + + if (err == MZ_OK) + err = mz_zip_entry_write_header(zip->cd_mem_stream, 0, &zip->file_info); + + /* Update local header with crc32 and sizes */ + if ((err == MZ_OK) && ((zip->file_info.flag & MZ_ZIP_FLAG_DATA_DESCRIPTOR) == 0) && + ((zip->file_info.flag & MZ_ZIP_FLAG_MASK_LOCAL_INFO) == 0)) { + /* Save the disk number and position we are to seek back after updating local header */ + int64_t end_pos = mz_stream_tell(zip->stream); + mz_stream_get_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, &end_disk_number); + + err = mz_zip_entry_seek_local_header(zip); + + if (err == MZ_OK) { + /* Seek to crc32 and sizes offset in local header */ + mz_stream_set_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, zip->file_info.disk_number); + err = mz_stream_seek(zip->stream, zip->file_info.disk_offset + MZ_ZIP_OFFSET_CRC_SIZES, MZ_SEEK_SET); + } + + if (err == MZ_OK) + err = mz_zip_entry_write_crc_sizes(zip->stream, zip64, 0, &zip->file_info); + + /* Seek to and update zip64 extension sizes */ + if ((err == MZ_OK) && (zip64)) { + int64_t filename_size = zip->file_info.filename_size; + + if (filename_size == 0) + filename_size = strlen(zip->file_info.filename); + + /* Since we write zip64 extension first we know its offset */ + err = mz_stream_seek(zip->stream, 2 + 2 + filename_size + 4, MZ_SEEK_CUR); + + if (err == MZ_OK) + err = mz_stream_write_uint64(zip->stream, zip->file_info.uncompressed_size); + if (err == MZ_OK) + err = mz_stream_write_uint64(zip->stream, zip->file_info.compressed_size); + } + + mz_stream_set_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, end_disk_number); + mz_stream_seek(zip->stream, end_pos, MZ_SEEK_SET); + } + + zip->number_entry += 1; + + mz_zip_entry_close_int(zip); + + return err; +} + +int32_t mz_zip_entry_seek_local_header(void *handle) { + mz_zip *zip = (mz_zip *)handle; + int64_t disk_size = 0; + uint32_t disk_number = 0; + + if (!zip) + return MZ_PARAM_ERROR; + disk_number = zip->file_info.disk_number; + if (disk_number == zip->disk_number_with_cd) { + mz_stream_get_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_SIZE, &disk_size); + if ((disk_size == 0) || ((zip->open_mode & MZ_OPEN_MODE_WRITE) == 0)) + disk_number = (uint32_t)-1; + } + + mz_stream_set_prop_int64(zip->stream, MZ_STREAM_PROP_DISK_NUMBER, disk_number); + + mz_zip_print("Zip - Entry - Seek local (disk %" PRId32 " offset %" PRId64 ")\n", disk_number, + zip->file_info.disk_offset); + + /* Guard against seek overflows */ + if ((zip->disk_offset_shift > 0) && (zip->file_info.disk_offset > (INT64_MAX - zip->disk_offset_shift))) + return MZ_FORMAT_ERROR; + + return mz_stream_seek(zip->stream, zip->file_info.disk_offset + zip->disk_offset_shift, MZ_SEEK_SET); +} + +int32_t mz_zip_entry_get_compress_stream(void *handle, void **compress_stream) { + mz_zip *zip = (mz_zip *)handle; + if (!zip || !compress_stream) + return MZ_PARAM_ERROR; + *compress_stream = zip->compress_stream; + if (!*compress_stream) + return MZ_EXIST_ERROR; + return MZ_OK; +} + +int32_t mz_zip_entry_close(void *handle) { + return mz_zip_entry_close_raw(handle, UINT64_MAX, 0); +} + +int32_t mz_zip_entry_close_raw(void *handle, int64_t uncompressed_size, uint32_t crc32) { + mz_zip *zip = (mz_zip *)handle; + int32_t err = MZ_OK; + + if (!zip || mz_zip_entry_is_open(zip) != MZ_OK) + return MZ_PARAM_ERROR; + + if (zip->open_mode & MZ_OPEN_MODE_WRITE) + err = mz_zip_entry_write_close(zip, crc32, UINT64_MAX, uncompressed_size); + else + err = mz_zip_entry_read_close(zip, NULL, NULL, NULL); + + return err; +} + +int32_t mz_zip_entry_is_dir(void *handle) { + mz_zip *zip = (mz_zip *)handle; + int32_t filename_length = 0; + + if (!zip || !zip->entry_scanned) + return MZ_PARAM_ERROR; + if (mz_zip_attrib_is_dir(zip->file_info.external_fa, zip->file_info.version_madeby) == MZ_OK) + return MZ_OK; + + filename_length = (int32_t)strlen(zip->file_info.filename); + if (filename_length > 0) { + if (mz_os_is_dir_separator(zip->file_info.filename[filename_length - 1])) + return MZ_OK; + } + return MZ_EXIST_ERROR; +} + +int32_t mz_zip_entry_is_symlink(void *handle) { + mz_zip *zip = (mz_zip *)handle; + + if (!zip || !zip->entry_scanned) + return MZ_PARAM_ERROR; + if (mz_zip_attrib_is_symlink(zip->file_info.external_fa, zip->file_info.version_madeby) != MZ_OK) + return MZ_EXIST_ERROR; + + return MZ_OK; +} + +int32_t mz_zip_entry_get_info(void *handle, mz_zip_file **file_info) { + mz_zip *zip = (mz_zip *)handle; + + if (!zip) + return MZ_PARAM_ERROR; + + if ((zip->open_mode & MZ_OPEN_MODE_WRITE) == 0) { + if (!zip->entry_scanned) + return MZ_PARAM_ERROR; + } + + *file_info = &zip->file_info; + return MZ_OK; +} + +int32_t mz_zip_entry_get_local_info(void *handle, mz_zip_file **local_file_info) { + mz_zip *zip = (mz_zip *)handle; + if (!zip || mz_zip_entry_is_open(zip) != MZ_OK) + return MZ_PARAM_ERROR; + *local_file_info = &zip->local_file_info; + return MZ_OK; +} + +int32_t mz_zip_entry_set_extrafield(void *handle, const uint8_t *extrafield, uint16_t extrafield_size) { + mz_zip *zip = (mz_zip *)handle; + + if (!zip || mz_zip_entry_is_open(zip) != MZ_OK) + return MZ_PARAM_ERROR; + + zip->file_info.extrafield = extrafield; + zip->file_info.extrafield_size = extrafield_size; + return MZ_OK; +} + +static int32_t mz_zip_goto_next_entry_int(void *handle) { + mz_zip *zip = (mz_zip *)handle; + int32_t err = MZ_OK; + + if (!zip) + return MZ_PARAM_ERROR; + + zip->entry_scanned = 0; + + mz_stream_set_prop_int64(zip->cd_stream, MZ_STREAM_PROP_DISK_NUMBER, -1); + + err = mz_stream_seek(zip->cd_stream, zip->cd_current_pos, MZ_SEEK_SET); + if (err == MZ_OK) + err = mz_zip_entry_read_header(zip->cd_stream, 0, &zip->file_info, zip->file_info_stream); + if (err == MZ_OK) + zip->entry_scanned = 1; + return err; +} + +int64_t mz_zip_get_entry(void *handle) { + mz_zip *zip = (mz_zip *)handle; + + if (!zip) + return MZ_PARAM_ERROR; + + return zip->cd_current_pos; +} + +int32_t mz_zip_goto_entry(void *handle, int64_t cd_pos) { + mz_zip *zip = (mz_zip *)handle; + + if (!zip) + return MZ_PARAM_ERROR; + + if (cd_pos < zip->cd_start_pos || cd_pos > zip->cd_start_pos + zip->cd_size) + return MZ_PARAM_ERROR; + + zip->cd_current_pos = cd_pos; + + return mz_zip_goto_next_entry_int(zip); +} + +int32_t mz_zip_goto_first_entry(void *handle) { + mz_zip *zip = (mz_zip *)handle; + + if (!zip) + return MZ_PARAM_ERROR; + + zip->cd_current_pos = zip->cd_start_pos; + + return mz_zip_goto_next_entry_int(zip); +} + +int32_t mz_zip_goto_next_entry(void *handle) { + mz_zip *zip = (mz_zip *)handle; + + if (!zip) + return MZ_PARAM_ERROR; + + zip->cd_current_pos += (int64_t)MZ_ZIP_SIZE_CD_ITEM + zip->file_info.filename_size + + zip->file_info.extrafield_size + zip->file_info.comment_size; + + return mz_zip_goto_next_entry_int(zip); +} + +int32_t mz_zip_locate_entry(void *handle, const char *filename, uint8_t ignore_case) { + mz_zip *zip = (mz_zip *)handle; + int32_t err = MZ_OK; + int32_t result = 0; + + if (!zip || !filename) + return MZ_PARAM_ERROR; + + /* If we are already on the current entry, no need to search */ + if (zip->entry_scanned && zip->file_info.filename) { + result = mz_zip_path_compare(zip->file_info.filename, filename, ignore_case); + if (result == 0) + return MZ_OK; + } + + /* Search all entries starting at the first */ + err = mz_zip_goto_first_entry(zip); + while (err == MZ_OK) { + result = mz_zip_path_compare(zip->file_info.filename, filename, ignore_case); + if (result == 0) + return MZ_OK; + + err = mz_zip_goto_next_entry(zip); + } + + return err; +} + +int32_t mz_zip_locate_first_entry(void *handle, void *userdata, mz_zip_locate_entry_cb cb) { + mz_zip *zip = (mz_zip *)handle; + int32_t err = MZ_OK; + int32_t result = 0; + + /* Search first entry looking for match */ + err = mz_zip_goto_first_entry(zip); + if (err != MZ_OK) + return err; + + result = cb(zip, userdata, &zip->file_info); + if (result == 0) + return MZ_OK; + + return mz_zip_locate_next_entry(zip, userdata, cb); +} + +int32_t mz_zip_locate_next_entry(void *handle, void *userdata, mz_zip_locate_entry_cb cb) { + mz_zip *zip = (mz_zip *)handle; + int32_t err = MZ_OK; + int32_t result = 0; + + /* Search next entries looking for match */ + err = mz_zip_goto_next_entry(zip); + while (err == MZ_OK) { + result = cb(zip, userdata, &zip->file_info); + if (result == 0) + return MZ_OK; + + err = mz_zip_goto_next_entry(zip); + } + + return err; +} + +/***************************************************************************/ + +int32_t mz_zip_attrib_is_dir(uint32_t attrib, int32_t version_madeby) { + uint32_t posix_attrib = 0; + uint8_t system = MZ_HOST_SYSTEM(version_madeby); + int32_t err = MZ_OK; + + err = mz_zip_attrib_convert(system, attrib, MZ_HOST_SYSTEM_UNIX, &posix_attrib); + if (err == MZ_OK) { + if ((posix_attrib & 0170000) == 0040000) /* S_ISDIR */ + return MZ_OK; + } + + return MZ_EXIST_ERROR; +} + +int32_t mz_zip_attrib_is_symlink(uint32_t attrib, int32_t version_madeby) { + uint32_t posix_attrib = 0; + uint8_t system = MZ_HOST_SYSTEM(version_madeby); + int32_t err = MZ_OK; + + err = mz_zip_attrib_convert(system, attrib, MZ_HOST_SYSTEM_UNIX, &posix_attrib); + if (err == MZ_OK) { + if ((posix_attrib & 0170000) == 0120000) /* S_ISLNK */ + return MZ_OK; + } + + return MZ_EXIST_ERROR; +} + +int32_t mz_zip_attrib_convert(uint8_t src_sys, uint32_t src_attrib, uint8_t target_sys, uint32_t *target_attrib) { + if (!target_attrib) + return MZ_PARAM_ERROR; + + *target_attrib = 0; + + if ((src_sys == MZ_HOST_SYSTEM_MSDOS) || (src_sys == MZ_HOST_SYSTEM_WINDOWS_NTFS)) { + if ((target_sys == MZ_HOST_SYSTEM_MSDOS) || (target_sys == MZ_HOST_SYSTEM_WINDOWS_NTFS)) { + *target_attrib = src_attrib; + return MZ_OK; + } + if ((target_sys == MZ_HOST_SYSTEM_UNIX) || (target_sys == MZ_HOST_SYSTEM_OSX_DARWIN) || + (target_sys == MZ_HOST_SYSTEM_RISCOS)) + return mz_zip_attrib_win32_to_posix(src_attrib, target_attrib); + } else if ((src_sys == MZ_HOST_SYSTEM_UNIX) || (src_sys == MZ_HOST_SYSTEM_OSX_DARWIN) || + (src_sys == MZ_HOST_SYSTEM_RISCOS)) { + /* If high bytes are set, it contains unix specific attributes */ + if ((src_attrib >> 16) != 0) + src_attrib >>= 16; + + if ((target_sys == MZ_HOST_SYSTEM_UNIX) || (target_sys == MZ_HOST_SYSTEM_OSX_DARWIN) || + (target_sys == MZ_HOST_SYSTEM_RISCOS)) { + *target_attrib = src_attrib; + return MZ_OK; + } + if ((target_sys == MZ_HOST_SYSTEM_MSDOS) || (target_sys == MZ_HOST_SYSTEM_WINDOWS_NTFS)) + return mz_zip_attrib_posix_to_win32(src_attrib, target_attrib); + } + + return MZ_SUPPORT_ERROR; +} + +int32_t mz_zip_attrib_posix_to_win32(uint32_t posix_attrib, uint32_t *win32_attrib) { + if (!win32_attrib) + return MZ_PARAM_ERROR; + + *win32_attrib = 0; + + /* S_IWUSR | S_IWGRP | S_IWOTH | S_IXUSR | S_IXGRP | S_IXOTH */ + if ((posix_attrib & 0000333) == 0 && (posix_attrib & 0000444) != 0) + *win32_attrib |= 0x01; /* FILE_ATTRIBUTE_READONLY */ + /* S_IFLNK */ + if ((posix_attrib & 0170000) == 0120000) + *win32_attrib |= 0x400; /* FILE_ATTRIBUTE_REPARSE_POINT */ + /* S_IFDIR */ + else if ((posix_attrib & 0170000) == 0040000) + *win32_attrib |= 0x10; /* FILE_ATTRIBUTE_DIRECTORY */ + /* S_IFREG */ + else + *win32_attrib |= 0x80; /* FILE_ATTRIBUTE_NORMAL */ + + return MZ_OK; +} + +int32_t mz_zip_attrib_win32_to_posix(uint32_t win32_attrib, uint32_t *posix_attrib) { + if (!posix_attrib) + return MZ_PARAM_ERROR; + + *posix_attrib = 0000444; /* S_IRUSR | S_IRGRP | S_IROTH */ + /* FILE_ATTRIBUTE_READONLY */ + if ((win32_attrib & 0x01) == 0) + *posix_attrib |= 0000222; /* S_IWUSR | S_IWGRP | S_IWOTH */ + /* FILE_ATTRIBUTE_REPARSE_POINT */ + if ((win32_attrib & 0x400) == 0x400) + *posix_attrib |= 0120000; /* S_IFLNK */ + /* FILE_ATTRIBUTE_DIRECTORY */ + else if ((win32_attrib & 0x10) == 0x10) + *posix_attrib |= 0040111; /* S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH */ + else + *posix_attrib |= 0100000; /* S_IFREG */ + + return MZ_OK; +} + +/***************************************************************************/ + +int32_t mz_zip_extrafield_find(void *stream, uint16_t type, int32_t max_seek, uint16_t *length) { + int32_t err = MZ_OK; + uint16_t field_type = 0; + uint16_t field_length = 0; + + if (max_seek < 4) + return MZ_EXIST_ERROR; + + do { + err = mz_stream_read_uint16(stream, &field_type); + if (err == MZ_OK) + err = mz_stream_read_uint16(stream, &field_length); + if (err != MZ_OK) + break; + + if (type == field_type) { + if (length) + *length = field_length; + return MZ_OK; + } + + max_seek -= field_length - 4; + if (max_seek < 0) + return MZ_EXIST_ERROR; + + err = mz_stream_seek(stream, field_length, MZ_SEEK_CUR); + } while (err == MZ_OK); + + return MZ_EXIST_ERROR; +} + +int32_t mz_zip_extrafield_contains(const uint8_t *extrafield, int32_t extrafield_size, uint16_t type, + uint16_t *length) { + void *file_extra_stream = NULL; + int32_t err = MZ_OK; + + if (!extrafield || !extrafield_size) + return MZ_PARAM_ERROR; + + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; + + mz_stream_mem_set_buffer(file_extra_stream, (void *)extrafield, extrafield_size); + err = mz_zip_extrafield_find(file_extra_stream, type, extrafield_size, length); + mz_stream_mem_delete(&file_extra_stream); + return err; +} + +int32_t mz_zip_extrafield_read(void *stream, uint16_t *type, uint16_t *length) { + int32_t err = MZ_OK; + if (!type || !length) + return MZ_PARAM_ERROR; + err = mz_stream_read_uint16(stream, type); + if (err == MZ_OK) + err = mz_stream_read_uint16(stream, length); + return err; +} + +int32_t mz_zip_extrafield_write(void *stream, uint16_t type, uint16_t length) { + int32_t err = MZ_OK; + err = mz_stream_write_uint16(stream, type); + if (err == MZ_OK) + err = mz_stream_write_uint16(stream, length); + return err; +} + +/***************************************************************************/ + +/** + This is mostly validating a given time struct is convertible to and from a valid dos date. + This does not however perform a calendar validation (like February 31). + */ +static int32_t mz_zip_invalid_date(const struct tm *ptm) { +#define datevalue_in_range(min, max, value) ((min) <= (value) && (value) <= (max)) + return (!datevalue_in_range(0, 127 + 80, ptm->tm_year) || /* 1980-based year, allow 80 extra */ + !datevalue_in_range(0, 11, ptm->tm_mon) || /* allowing months 0-11 in a year */ + !datevalue_in_range(1, 31, ptm->tm_mday) || /* allowing days 1-31 in a month */ + !datevalue_in_range(0, 23, ptm->tm_hour) || /* allowing hours 0-23 in a day */ + !datevalue_in_range(0, 59, ptm->tm_min) || /* allowing minutes 0-59 in an hour */ + !datevalue_in_range(0, 59, ptm->tm_sec)); /* allowing seconds 0-59 in a minute */ +#undef datevalue_in_range +} + +/** + Returns a year-1900 indexed time struct. + This may produce slightly out-of-range months, hours, minutes, seconds. + This may also produce invalid calendar days (like the 31st of February). + */ +static void mz_zip_dosdate_to_raw_tm(uint64_t dos_date, struct tm *ptm) { + uint64_t date = (uint64_t)(dos_date >> 16); + + ptm->tm_year = (int16_t)(((date & 0x0FE00) / 0x0200) + 80); /* result in 80..207 */ + ptm->tm_mon = (int16_t)(((date & 0x1E0) / 0x20) - 1); /* result in -1..14 */ + ptm->tm_mday = (int16_t)(date & 0x1f); /* result in 0..31 */ + ptm->tm_hour = (int16_t)((dos_date & 0xF800) / 0x800); /* result in 0..31 */ + ptm->tm_min = (int16_t)((dos_date & 0x7E0) / 0x20); /* result in 0..63 */ + ptm->tm_sec = (int16_t)(2 * (dos_date & 0x1f)); /* result in 0..62 */ + ptm->tm_isdst = -1; +} + +int32_t mz_zip_dosdate_to_tm(uint64_t dos_date, struct tm *ptm) { + if (!ptm) + return MZ_PARAM_ERROR; + + mz_zip_dosdate_to_raw_tm(dos_date, ptm); + + if (mz_zip_invalid_date(ptm)) { + /* Invalid date stored, so don't return it */ + memset(ptm, 0, sizeof(struct tm)); + return MZ_FORMAT_ERROR; + } + return MZ_OK; +} + +time_t mz_zip_dosdate_to_time_t(uint64_t dos_date) { + struct tm ptm; + mz_zip_dosdate_to_raw_tm(dos_date, &ptm); + return mz_zip_tm_to_time_t(&ptm); +} + +time_t mz_zip_tm_to_time_t(struct tm *ptm) { + // `ptm->tm_year` must be 1900-indexed. + return mktime(ptm); +} + +int32_t mz_zip_time_t_to_tm(time_t unix_time, struct tm *ptm) { + struct tm ltm; + if (!ptm) + return MZ_PARAM_ERROR; + if (!localtime_r(&unix_time, <m)) { /* Returns a 1900-based year */ + /* Invalid date stored, so don't return it */ + memset(ptm, 0, sizeof(struct tm)); + return MZ_INTERNAL_ERROR; + } + memcpy(ptm, <m, sizeof(struct tm)); + return MZ_OK; +} + +uint32_t mz_zip_time_t_to_dos_date(time_t unix_time) { + struct tm ptm; + mz_zip_time_t_to_tm(unix_time, &ptm); + return mz_zip_tm_to_dosdate((const struct tm *)&ptm); +} + +uint32_t mz_zip_tm_to_dosdate(const struct tm *ptm) { + struct tm fixed_tm; + + /* Years supported: */ + + /* [00, 79] (assumed to be between 2000 and 2079) */ + /* [80, 207] (assumed to be between 1980 and 2107, typical output of old */ + /* software that does 'year-1900' to get a double digit year) */ + /* [1980, 2107] (due to format limitations, only years 1980-2107 can be stored.) */ + + memcpy(&fixed_tm, ptm, sizeof(struct tm)); + if (fixed_tm.tm_year >= 1980) /* range [1980, 2107] */ + fixed_tm.tm_year -= 1980; + else if (fixed_tm.tm_year >= 80) /* range [80, 207] */ + fixed_tm.tm_year -= 80; + else /* range [00, 79] */ + fixed_tm.tm_year += 20; + + if (mz_zip_invalid_date(&fixed_tm)) + return 0; + + return (((uint32_t)fixed_tm.tm_mday + (32 * ((uint32_t)fixed_tm.tm_mon + 1)) + (512 * (uint32_t)fixed_tm.tm_year)) + << 16) | + (((uint32_t)fixed_tm.tm_sec / 2) + (32 * (uint32_t)fixed_tm.tm_min) + (2048 * (uint32_t)fixed_tm.tm_hour)); +} + +int32_t mz_zip_ntfs_to_unix_time(uint64_t ntfs_time, time_t *unix_time) { + *unix_time = (time_t)((ntfs_time - 116444736000000000LL) / 10000000); + return MZ_OK; +} + +int32_t mz_zip_unix_to_ntfs_time(time_t unix_time, uint64_t *ntfs_time) { + *ntfs_time = ((uint64_t)unix_time * 10000000) + 116444736000000000LL; + return MZ_OK; +} + +/***************************************************************************/ + +int32_t mz_zip_path_compare(const char *path1, const char *path2, uint8_t ignore_case) { + do { + if ((*path1 == '\\' && *path2 == '/') || (*path2 == '\\' && *path1 == '/')) { + /* Ignore comparison of path slashes */ + } else if (ignore_case) { + if (tolower(*path1) != tolower(*path2)) + break; + } else if (*path1 != *path2) { + break; + } + + path1 += 1; + path2 += 1; + } while (*path1 != 0 && *path2 != 0); + + if (ignore_case) + return (int32_t)(tolower(*path1) - tolower(*path2)); + + return (int32_t)(*path1 - *path2); +} + +/***************************************************************************/ + +const char *mz_zip_get_compression_method_string(int32_t compression_method) { + const char *method = "?"; + switch (compression_method) { + case MZ_COMPRESS_METHOD_STORE: + method = "stored"; + break; + case MZ_COMPRESS_METHOD_DEFLATE: + method = "deflate"; + break; + case MZ_COMPRESS_METHOD_BZIP2: + method = "bzip2"; + break; + case MZ_COMPRESS_METHOD_LZMA: + method = "lzma"; + break; + case MZ_COMPRESS_METHOD_XZ: + method = "xz"; + break; + case MZ_COMPRESS_METHOD_ZSTD: + method = "zstd"; + break; + } + return method; +} + +/***************************************************************************/ diff --git a/thirdparty/minizip/mz_zip.h b/thirdparty/minizip/mz_zip.h new file mode 100644 index 000000000..dd1269c75 --- /dev/null +++ b/thirdparty/minizip/mz_zip.h @@ -0,0 +1,257 @@ +/* mz_zip.h -- Zip manipulation + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + Copyright (C) 2009-2010 Mathias Svensson + Modifications for Zip64 support + http://result42.com + Copyright (C) 1998-2010 Gilles Vollant + https://www.winimage.com/zLibDll/minizip.html + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_ZIP_H +#define MZ_ZIP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +typedef struct mz_zip_file_s { + uint16_t version_madeby; /* version made by */ + uint16_t version_needed; /* version needed to extract */ + uint16_t flag; /* general purpose bit flag */ + uint16_t compression_method; /* compression method */ + time_t modified_date; /* last modified date in unix time */ + time_t accessed_date; /* last accessed date in unix time */ + time_t creation_date; /* creation date in unix time */ + uint32_t crc; /* crc-32 */ + int64_t compressed_size; /* compressed size */ + int64_t uncompressed_size; /* uncompressed size */ + uint16_t filename_size; /* filename length */ + uint16_t extrafield_size; /* extra field length */ + uint16_t comment_size; /* file comment length */ + uint32_t disk_number; /* disk number start */ + int64_t disk_offset; /* relative offset of local header */ + uint16_t internal_fa; /* internal file attributes */ + uint32_t external_fa; /* external file attributes */ + const char *filename; /* filename utf8 null-terminated string */ + const uint8_t *extrafield; /* extrafield data */ + const char *comment; /* comment utf8 null-terminated string */ + const char *linkname; /* sym-link filename utf8 null-terminated string */ + uint16_t zip64; /* zip64 extension mode */ + uint16_t aes_version; /* winzip aes extension if not 0 */ + uint8_t aes_strength; /* winzip aes encryption strength */ + uint16_t pk_verify; /* pkware encryption verifier */ +} mz_zip_file, mz_zip_entry; + +/***************************************************************************/ + +typedef int32_t (*mz_zip_locate_entry_cb)(void *handle, void *userdata, mz_zip_file *file_info); + +/***************************************************************************/ + +void *mz_zip_create(void); +/* Create zip instance for opening */ + +void mz_zip_delete(void **handle); +/* Delete zip object */ + +int32_t mz_zip_open(void *handle, void *stream, int32_t mode); +/* Create a zip file, no delete file in zip functionality */ + +int32_t mz_zip_close(void *handle); +/* Close the zip file */ + +int32_t mz_zip_get_comment(void *handle, const char **comment); +/* Get a pointer to the global comment */ + +int32_t mz_zip_set_comment(void *handle, const char *comment); +/* Sets the global comment used for writing zip file */ + +int32_t mz_zip_get_version_madeby(void *handle, uint16_t *version_madeby); +/* Get the version made by */ + +int32_t mz_zip_set_version_madeby(void *handle, uint16_t version_madeby); +/* Sets the version made by used for writing zip file */ + +int32_t mz_zip_set_recover(void *handle, uint8_t recover); +/* Sets the ability to recover the central dir by reading local file headers */ + +int32_t mz_zip_set_data_descriptor(void *handle, uint8_t data_descriptor); +/* Sets the use of data descriptor flag when writing zip entries */ + +int32_t mz_zip_get_stream(void *handle, void **stream); +/* Get a pointer to the stream used to open */ + +int32_t mz_zip_set_cd_stream(void *handle, int64_t cd_start_pos, void *cd_stream); +/* Sets the stream to use for reading the central dir */ + +int32_t mz_zip_get_cd_mem_stream(void *handle, void **cd_mem_stream); +/* Get a pointer to the stream used to store the central dir in memory */ + +int32_t mz_zip_set_number_entry(void *handle, uint64_t number_entry); +/* Sets the total number of entries */ + +int32_t mz_zip_get_number_entry(void *handle, uint64_t *number_entry); +/* Get the total number of entries */ + +int32_t mz_zip_set_disk_number_with_cd(void *handle, uint32_t disk_number_with_cd); +/* Sets the disk number containing the central directory record */ + +int32_t mz_zip_get_disk_number_with_cd(void *handle, uint32_t *disk_number_with_cd); +/* Get the disk number containing the central directory record */ + +/***************************************************************************/ + +int32_t mz_zip_entry_is_open(void *handle); +/* Check to see if entry is open for read/write */ + +int32_t mz_zip_entry_read_open(void *handle, uint8_t raw, const char *password); +/* Open for reading the current file in the zip file */ + +int32_t mz_zip_entry_read(void *handle, void *buf, int32_t len); +/* Read bytes from the current file in the zip file */ + +int32_t mz_zip_entry_read_close(void *handle, uint32_t *crc32, int64_t *compressed_size, int64_t *uncompressed_size); +/* Close the current file for reading and get data descriptor values */ + +int32_t mz_zip_entry_write_open(void *handle, const mz_zip_file *file_info, int16_t compress_level, uint8_t raw, + const char *password); +/* Open for writing the current file in the zip file */ + +int32_t mz_zip_entry_write(void *handle, const void *buf, int32_t len); +/* Write bytes from the current file in the zip file */ + +int32_t mz_zip_entry_write_close(void *handle, uint32_t crc32, int64_t compressed_size, int64_t uncompressed_size); +/* Close the current file for writing and set data descriptor values */ + +int32_t mz_zip_entry_seek_local_header(void *handle); +/* Seeks to the local header for the entry */ + +int32_t mz_zip_entry_get_compress_stream(void *handle, void **compress_stream); +/* Get a pointer to the compression stream used for the current entry */ + +int32_t mz_zip_entry_close_raw(void *handle, int64_t uncompressed_size, uint32_t crc32); +/* Close the current file in the zip file where raw is compressed data */ + +int32_t mz_zip_entry_close(void *handle); +/* Close the current file in the zip file */ + +/***************************************************************************/ + +int32_t mz_zip_entry_is_dir(void *handle); +/* Checks to see if the entry is a directory */ + +int32_t mz_zip_entry_is_symlink(void *handle); +/* Checks to see if the entry is a symbolic link */ + +int32_t mz_zip_entry_get_info(void *handle, mz_zip_file **file_info); +/* Get info about the current file, only valid while current entry is open */ + +int32_t mz_zip_entry_get_local_info(void *handle, mz_zip_file **local_file_info); +/* Get local info about the current file, only valid while current entry is being read */ + +int32_t mz_zip_entry_set_extrafield(void *handle, const uint8_t *extrafield, uint16_t extrafield_size); +/* Sets or updates the extra field for the entry to be used before writing cd */ + +int64_t mz_zip_get_entry(void *handle); +/* Return offset of the current entry in the zip file */ + +int32_t mz_zip_goto_entry(void *handle, int64_t cd_pos); +/* Go to specified entry in the zip file */ + +int32_t mz_zip_goto_first_entry(void *handle); +/* Go to the first entry in the zip file */ + +int32_t mz_zip_goto_next_entry(void *handle); +/* Go to the next entry in the zip file or MZ_END_OF_LIST if reaching the end */ + +int32_t mz_zip_locate_entry(void *handle, const char *filename, uint8_t ignore_case); +/* Locate the file with the specified name in the zip file or MZ_END_LIST if not found */ + +int32_t mz_zip_locate_first_entry(void *handle, void *userdata, mz_zip_locate_entry_cb cb); +/* Locate the first matching entry based on a match callback */ + +int32_t mz_zip_locate_next_entry(void *handle, void *userdata, mz_zip_locate_entry_cb cb); +/* Locate the next matching entry based on a match callback */ + +/***************************************************************************/ + +int32_t mz_zip_attrib_is_dir(uint32_t attrib, int32_t version_madeby); +/* Checks to see if the attribute is a directory based on platform */ + +int32_t mz_zip_attrib_is_symlink(uint32_t attrib, int32_t version_madeby); +/* Checks to see if the attribute is a symbolic link based on platform */ + +int32_t mz_zip_attrib_convert(uint8_t src_sys, uint32_t src_attrib, uint8_t target_sys, uint32_t *target_attrib); +/* Converts file attributes from one host system to another */ + +int32_t mz_zip_attrib_posix_to_win32(uint32_t posix_attrib, uint32_t *win32_attrib); +/* Converts posix file attributes to win32 file attributes */ + +int32_t mz_zip_attrib_win32_to_posix(uint32_t win32_attrib, uint32_t *posix_attrib); +/* Converts win32 file attributes to posix file attributes */ + +/***************************************************************************/ + +int32_t mz_zip_extrafield_find(void *stream, uint16_t type, int32_t max_seek, uint16_t *length); +/* Seeks to extra field by its type and returns its length */ + +int32_t mz_zip_extrafield_contains(const uint8_t *extrafield, int32_t extrafield_size, uint16_t type, uint16_t *length); +/* Gets whether an extrafield exists and its size */ + +int32_t mz_zip_extrafield_read(void *stream, uint16_t *type, uint16_t *length); +/* Reads an extrafield header from a stream */ + +int32_t mz_zip_extrafield_write(void *stream, uint16_t type, uint16_t length); +/* Writes an extrafield header to a stream */ + +/***************************************************************************/ + +int32_t mz_zip_dosdate_to_tm(uint64_t dos_date, struct tm *ptm); +/* Convert dos date/time format to struct tm */ + +time_t mz_zip_dosdate_to_time_t(uint64_t dos_date); +/* Convert dos date/time format to time_t */ + +time_t mz_zip_tm_to_time_t(struct tm *ptm); +/* Convert year-1900 indexed time struct to time_t */ + +int32_t mz_zip_time_t_to_tm(time_t unix_time, struct tm *ptm); +/* Convert time_t to time struct */ + +uint32_t mz_zip_time_t_to_dos_date(time_t unix_time); +/* Convert time_t to dos date/time format */ + +uint32_t mz_zip_tm_to_dosdate(const struct tm *ptm); +/* Convert struct tm to dos date/time format */ + +int32_t mz_zip_ntfs_to_unix_time(uint64_t ntfs_time, time_t *unix_time); +/* Convert ntfs time to unix time */ + +int32_t mz_zip_unix_to_ntfs_time(time_t unix_time, uint64_t *ntfs_time); +/* Convert unix time to ntfs time */ + +/***************************************************************************/ + +int32_t mz_zip_path_compare(const char *path1, const char *path2, uint8_t ignore_case); +/* Compare two paths without regard to slashes */ + +/***************************************************************************/ + +const char *mz_zip_get_compression_method_string(int32_t compression_method); +/* Gets a string representing the compression method */ + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* _ZIP_H */ diff --git a/thirdparty/minizip/mz_zip_rw.c b/thirdparty/minizip/mz_zip_rw.c new file mode 100644 index 000000000..13bff1ffd --- /dev/null +++ b/thirdparty/minizip/mz_zip_rw.c @@ -0,0 +1,2029 @@ +/* mz_zip_rw.c -- Zip reader/writer + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#include "mz.h" +#include "mz_crypt.h" +#include "mz_os.h" +#include "mz_strm.h" +#include "mz_strm_buf.h" +#include "mz_strm_mem.h" +#include "mz_strm_os.h" +#include "mz_strm_split.h" +#include "mz_strm_wzaes.h" +#include "mz_zip.h" + +#include "mz_zip_rw.h" + +/***************************************************************************/ + +#define MZ_DEFAULT_PROGRESS_INTERVAL (1000u) + +#define MZ_ZIP_CD_FILENAME ("__cdcd__") + +/***************************************************************************/ + +typedef struct mz_zip_reader_s { + void *zip_handle; + void *file_stream; + void *buffered_stream; + void *split_stream; + void *mem_stream; + void *hash; + uint16_t hash_algorithm; + uint16_t hash_digest_size; + mz_zip_file *file_info; + const char *pattern; + uint8_t pattern_ignore_case; + const char *password; + void *overwrite_userdata; + mz_zip_reader_overwrite_cb overwrite_cb; + void *password_userdata; + mz_zip_reader_password_cb password_cb; + void *progress_userdata; + mz_zip_reader_progress_cb progress_cb; + uint32_t progress_cb_interval_ms; + void *entry_userdata; + mz_zip_reader_entry_cb entry_cb; + uint8_t raw; + uint8_t buffer[UINT16_MAX]; + int32_t encoding; + uint8_t sign_required; + uint8_t cd_verified; + uint8_t cd_zipped; + uint8_t entry_verified; + uint8_t recover; + const char *destination_dir; +} mz_zip_reader; + +/***************************************************************************/ + +int32_t mz_zip_reader_is_open(void *handle) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader) + return MZ_PARAM_ERROR; + if (!reader->zip_handle) + return MZ_PARAM_ERROR; + return MZ_OK; +} + +int32_t mz_zip_reader_open(void *handle, void *stream) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + + if (!reader) + return MZ_PARAM_ERROR; + reader->cd_verified = 0; + reader->cd_zipped = 0; + + reader->zip_handle = mz_zip_create(); + if (!reader->zip_handle) + return MZ_MEM_ERROR; + + mz_zip_set_recover(reader->zip_handle, reader->recover); + + err = mz_zip_open(reader->zip_handle, stream, MZ_OPEN_MODE_READ); + + if (err != MZ_OK) { + mz_zip_reader_close(reader); + return err; + } + + mz_zip_reader_unzip_cd(reader); + return MZ_OK; +} + +int32_t mz_zip_reader_open_file(void *handle, const char *path) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + + if (!reader) + return MZ_PARAM_ERROR; + mz_zip_reader_close(reader); + + reader->file_stream = mz_stream_os_create(); + if (!reader->file_stream) + return MZ_MEM_ERROR; + + reader->buffered_stream = mz_stream_buffered_create(); + if (!reader->buffered_stream) { + mz_stream_os_delete(&reader->file_stream); + return MZ_MEM_ERROR; + } + + reader->split_stream = mz_stream_split_create(); + if (!reader->split_stream) { + mz_stream_os_delete(&reader->file_stream); + mz_stream_buffered_delete(&reader->buffered_stream); + return MZ_MEM_ERROR; + } + + mz_stream_set_base(reader->buffered_stream, reader->file_stream); + mz_stream_set_base(reader->split_stream, reader->buffered_stream); + + err = mz_stream_open(reader->split_stream, path, MZ_OPEN_MODE_READ); + if (err == MZ_OK) + err = mz_zip_reader_open(reader, reader->split_stream); + return err; +} + +int32_t mz_zip_reader_open_file_in_memory(void *handle, const char *path) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + void *file_stream = NULL; + int64_t file_size = 0; + int32_t err = 0; + + if (!reader) + return MZ_PARAM_ERROR; + mz_zip_reader_close(reader); + + file_stream = mz_stream_os_create(); + if (!file_stream) + return MZ_MEM_ERROR; + + err = mz_stream_os_open(file_stream, path, MZ_OPEN_MODE_READ); + + if (err != MZ_OK) { + mz_stream_os_delete(&file_stream); + mz_zip_reader_close(reader); + return err; + } + + mz_stream_os_seek(file_stream, 0, MZ_SEEK_END); + file_size = mz_stream_os_tell(file_stream); + mz_stream_os_seek(file_stream, 0, MZ_SEEK_SET); + + reader->mem_stream = mz_stream_mem_create(); + + if ((file_size <= 0) || (file_size > UINT32_MAX) || (!reader->mem_stream)) { + /* Memory size is too large or too small */ + + mz_stream_os_close(file_stream); + mz_stream_os_delete(&file_stream); + mz_zip_reader_close(reader); + return MZ_MEM_ERROR; + } + + mz_stream_mem_set_grow_size(reader->mem_stream, (int32_t)file_size); + mz_stream_mem_open(reader->mem_stream, NULL, MZ_OPEN_MODE_CREATE); + + err = mz_stream_copy(reader->mem_stream, file_stream, (int32_t)file_size); + + mz_stream_os_close(file_stream); + mz_stream_os_delete(&file_stream); + + if (err == MZ_OK) + err = mz_zip_reader_open(reader, reader->mem_stream); + if (err != MZ_OK) + mz_zip_reader_close(reader); + + return err; +} + +int32_t mz_zip_reader_open_buffer(void *handle, const uint8_t *buf, int32_t len, uint8_t copy) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + + if (!reader) + return MZ_PARAM_ERROR; + mz_zip_reader_close(reader); + + reader->mem_stream = mz_stream_mem_create(); + if (!reader->mem_stream) + return MZ_MEM_ERROR; + + if (copy) { + mz_stream_mem_set_grow_size(reader->mem_stream, len); + mz_stream_mem_open(reader->mem_stream, NULL, MZ_OPEN_MODE_CREATE); + mz_stream_mem_write(reader->mem_stream, buf, len); + mz_stream_mem_seek(reader->mem_stream, 0, MZ_SEEK_SET); + } else { + mz_stream_mem_open(reader->mem_stream, NULL, MZ_OPEN_MODE_READ); + mz_stream_mem_set_buffer(reader->mem_stream, (void *)buf, len); + } + + if (err == MZ_OK) + err = mz_zip_reader_open(reader, reader->mem_stream); + + return err; +} + +int32_t mz_zip_reader_close(void *handle) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + + if (!reader) + return MZ_PARAM_ERROR; + if (reader->zip_handle) { + err = mz_zip_close(reader->zip_handle); + mz_zip_delete(&reader->zip_handle); + } + + if (reader->split_stream) { + mz_stream_split_close(reader->split_stream); + mz_stream_split_delete(&reader->split_stream); + } + + if (reader->buffered_stream) + mz_stream_buffered_delete(&reader->buffered_stream); + + if (reader->file_stream) + mz_stream_os_delete(&reader->file_stream); + + if (reader->mem_stream) { + mz_stream_close(reader->mem_stream); + mz_stream_delete(&reader->mem_stream); + } + + return err; +} + +/***************************************************************************/ + +int32_t mz_zip_reader_unzip_cd(void *handle) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + mz_zip_file *cd_info = NULL; + void *cd_mem_stream = NULL; + void *new_cd_stream = NULL; + void *file_extra_stream = NULL; + uint64_t number_entry = 0; + int32_t err = MZ_OK; + + err = mz_zip_reader_goto_first_entry(reader); + if (err != MZ_OK) + return err; + err = mz_zip_reader_entry_get_info(reader, &cd_info); + if (err != MZ_OK) + return err; + + if (strcmp(cd_info->filename, MZ_ZIP_CD_FILENAME) != 0) + return mz_zip_reader_goto_first_entry(reader); + + err = mz_zip_reader_entry_open(reader); + if (err != MZ_OK) + return err; + + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; + + mz_stream_mem_set_buffer(file_extra_stream, (void *)cd_info->extrafield, cd_info->extrafield_size); + + err = mz_zip_extrafield_find(file_extra_stream, MZ_ZIP_EXTENSION_CDCD, INT32_MAX, NULL); + if (err == MZ_OK) + err = mz_stream_read_uint64(file_extra_stream, &number_entry); + + mz_stream_mem_delete(&file_extra_stream); + + if (err != MZ_OK) + return err; + + mz_zip_get_cd_mem_stream(reader->zip_handle, &cd_mem_stream); + if (mz_stream_mem_is_open(cd_mem_stream) != MZ_OK) + mz_stream_mem_open(cd_mem_stream, NULL, MZ_OPEN_MODE_CREATE); + + err = mz_stream_seek(cd_mem_stream, 0, MZ_SEEK_SET); + if (err == MZ_OK) { + err = mz_stream_copy_stream(cd_mem_stream, NULL, handle, mz_zip_reader_entry_read, + (int32_t)cd_info->uncompressed_size); + } + + if (err == MZ_OK) { + reader->cd_zipped = 1; + + mz_zip_set_cd_stream(reader->zip_handle, 0, cd_mem_stream); + mz_zip_set_number_entry(reader->zip_handle, number_entry); + + err = mz_zip_reader_goto_first_entry(reader); + } + + reader->cd_verified = reader->entry_verified; + + mz_stream_mem_delete(&new_cd_stream); + return err; +} + +/***************************************************************************/ + +static int32_t mz_zip_reader_locate_entry_cb(void *handle, void *userdata, mz_zip_file *file_info) { + mz_zip_reader *reader = (mz_zip_reader *)userdata; + int32_t result = 0; + MZ_UNUSED(handle); + result = mz_path_compare_wc(file_info->filename, reader->pattern, reader->pattern_ignore_case); + return result; +} + +int32_t mz_zip_reader_goto_first_entry(void *handle) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + + if (mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + + if (mz_zip_entry_is_open(reader->zip_handle) == MZ_OK) + mz_zip_reader_entry_close(reader); + + if (!reader->pattern) + err = mz_zip_goto_first_entry(reader->zip_handle); + else + err = mz_zip_locate_first_entry(reader->zip_handle, reader, mz_zip_reader_locate_entry_cb); + + reader->file_info = NULL; + if (err == MZ_OK) + err = mz_zip_entry_get_info(reader->zip_handle, &reader->file_info); + + return err; +} + +int32_t mz_zip_reader_goto_next_entry(void *handle) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + + if (mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + + if (mz_zip_entry_is_open(reader->zip_handle) == MZ_OK) + mz_zip_reader_entry_close(reader); + + if (!reader->pattern) + err = mz_zip_goto_next_entry(reader->zip_handle); + else + err = mz_zip_locate_next_entry(reader->zip_handle, reader, mz_zip_reader_locate_entry_cb); + + reader->file_info = NULL; + if (err == MZ_OK) + err = mz_zip_entry_get_info(reader->zip_handle, &reader->file_info); + + return err; +} + +int32_t mz_zip_reader_locate_entry(void *handle, const char *filename, uint8_t ignore_case) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + + if (!reader) + return MZ_PARAM_ERROR; + if (mz_zip_entry_is_open(reader->zip_handle) == MZ_OK) + mz_zip_reader_entry_close(reader); + + err = mz_zip_locate_entry(reader->zip_handle, filename, ignore_case); + + reader->file_info = NULL; + if (err == MZ_OK) + err = mz_zip_entry_get_info(reader->zip_handle, &reader->file_info); + + return err; +} + +/***************************************************************************/ + +int32_t mz_zip_reader_entry_open(void *handle) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + const char *password = NULL; + char password_buf[120]; + + if (!reader) + return MZ_PARAM_ERROR; + reader->entry_verified = 0; + + if (mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + if (!reader->file_info) + return MZ_PARAM_ERROR; + + /* If the entry isn't open for reading, open it */ + if (mz_zip_entry_is_open(reader->zip_handle) == MZ_OK) + return MZ_OK; + + password = reader->password; + + /* Check if we need a password and ask for it if we need to */ + if (!password && reader->password_cb && (reader->file_info->flag & MZ_ZIP_FLAG_ENCRYPTED)) { + reader->password_cb(reader, reader->password_userdata, reader->file_info, password_buf, sizeof(password_buf)); + + password = password_buf; + } + + err = mz_zip_entry_read_open(reader->zip_handle, reader->raw, password); +#ifndef MZ_ZIP_NO_CRYPTO + if (err != MZ_OK) + return err; + + if (mz_zip_reader_entry_get_first_hash(reader, &reader->hash_algorithm, &reader->hash_digest_size) == MZ_OK) { + reader->hash = mz_crypt_sha_create(); + if (!reader->hash) + return MZ_MEM_ERROR; + + if (reader->hash_algorithm == MZ_HASH_SHA1) + err = mz_crypt_sha_set_algorithm(reader->hash, MZ_HASH_SHA1); + else if (reader->hash_algorithm == MZ_HASH_SHA256) + err = mz_crypt_sha_set_algorithm(reader->hash, MZ_HASH_SHA256); + else + err = MZ_SUPPORT_ERROR; + + if (err == MZ_OK) + mz_crypt_sha_begin(reader->hash); + } else if (reader->sign_required && !reader->cd_verified) + err = MZ_SIGN_ERROR; +#endif + + return err; +} + +int32_t mz_zip_reader_entry_close(void *handle) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + int32_t err_close = MZ_OK; +#ifndef MZ_ZIP_NO_CRYPTO + int32_t err_hash = MZ_OK; + uint8_t computed_hash[MZ_HASH_MAX_SIZE]; + uint8_t expected_hash[MZ_HASH_MAX_SIZE]; +#endif + + if (!reader) + return MZ_PARAM_ERROR; +#ifndef MZ_ZIP_NO_CRYPTO + if (reader->hash) { + mz_crypt_sha_end(reader->hash, computed_hash, sizeof(computed_hash)); + mz_crypt_sha_delete(&reader->hash); + + err_hash = + mz_zip_reader_entry_get_hash(reader, reader->hash_algorithm, expected_hash, reader->hash_digest_size); + + if (err_hash == MZ_OK) { + /* Verify expected hash against computed hash */ + if (memcmp(computed_hash, expected_hash, reader->hash_digest_size) != 0) + err = MZ_CRC_ERROR; + } + } +#endif + + err_close = mz_zip_entry_close(reader->zip_handle); + if (err == MZ_OK) + err = err_close; + return err; +} + +int32_t mz_zip_reader_entry_read(void *handle, void *buf, int32_t len) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t read = 0; + if (!reader) + return MZ_PARAM_ERROR; + read = mz_zip_entry_read(reader->zip_handle, buf, len); +#ifndef MZ_ZIP_NO_CRYPTO + if (read > 0 && reader->hash) + mz_crypt_sha_update(reader->hash, buf, read); +#endif + return read; +} + +int32_t mz_zip_reader_entry_get_hash(void *handle, uint16_t algorithm, uint8_t *digest, int32_t digest_size) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + void *file_extra_stream = NULL; + int32_t err = MZ_OK; + int32_t return_err = MZ_EXIST_ERROR; + uint16_t cur_algorithm = 0; + uint16_t cur_digest_size = 0; + + if (!reader) + return MZ_PARAM_ERROR; + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; + + mz_stream_mem_set_buffer(file_extra_stream, (void *)reader->file_info->extrafield, + reader->file_info->extrafield_size); + + do { + err = mz_zip_extrafield_find(file_extra_stream, MZ_ZIP_EXTENSION_HASH, INT32_MAX, NULL); + if (err != MZ_OK) + break; + + err = mz_stream_read_uint16(file_extra_stream, &cur_algorithm); + if (err == MZ_OK) + err = mz_stream_read_uint16(file_extra_stream, &cur_digest_size); + if ((err == MZ_OK) && (cur_algorithm == algorithm) && (cur_digest_size <= digest_size) && + (cur_digest_size <= MZ_HASH_MAX_SIZE)) { + /* Read hash digest */ + if (mz_stream_read(file_extra_stream, digest, digest_size) == cur_digest_size) + return_err = MZ_OK; + break; + } else { + err = mz_stream_seek(file_extra_stream, cur_digest_size, MZ_SEEK_CUR); + } + } while (err == MZ_OK); + + mz_stream_mem_delete(&file_extra_stream); + + return return_err; +} + +int32_t mz_zip_reader_entry_get_first_hash(void *handle, uint16_t *algorithm, uint16_t *digest_size) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + void *file_extra_stream = NULL; + int32_t err = MZ_OK; + uint16_t cur_algorithm = 0; + uint16_t cur_digest_size = 0; + + if (!reader || !algorithm) + return MZ_PARAM_ERROR; + + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; + + mz_stream_mem_set_buffer(file_extra_stream, (void *)reader->file_info->extrafield, + reader->file_info->extrafield_size); + + err = mz_zip_extrafield_find(file_extra_stream, MZ_ZIP_EXTENSION_HASH, INT32_MAX, NULL); + if (err == MZ_OK) + err = mz_stream_read_uint16(file_extra_stream, &cur_algorithm); + if (err == MZ_OK) + err = mz_stream_read_uint16(file_extra_stream, &cur_digest_size); + + if (algorithm) + *algorithm = cur_algorithm; + if (digest_size) + *digest_size = cur_digest_size; + + mz_stream_mem_delete(&file_extra_stream); + + return err; +} + +int32_t mz_zip_reader_entry_get_info(void *handle, mz_zip_file **file_info) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + if (!file_info || mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + *file_info = reader->file_info; + if (!*file_info) + return MZ_EXIST_ERROR; + return err; +} + +int32_t mz_zip_reader_entry_is_dir(void *handle) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + return mz_zip_entry_is_dir(reader->zip_handle); +} + +int32_t mz_zip_reader_entry_save_process(void *handle, void *stream, mz_stream_write_cb write_cb) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + int32_t read = 0; + int32_t written = 0; + + if (mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + if (!reader->file_info || !write_cb) + return MZ_PARAM_ERROR; + + /* If the entry isn't open for reading, open it */ + if (mz_zip_entry_is_open(reader->zip_handle) != MZ_OK) + err = mz_zip_reader_entry_open(reader); + + if (err != MZ_OK) + return err; + + /* Unzip entry in zip file */ + read = mz_zip_reader_entry_read(reader, reader->buffer, sizeof(reader->buffer)); + + if (read == 0) { + /* If we are done close the entry */ + err = mz_zip_reader_entry_close(reader); + if (err != MZ_OK) + return err; + + return MZ_END_OF_STREAM; + } + + if (read > 0) { + /* Write the data to the specified stream */ + written = write_cb(stream, reader->buffer, read); + if (written != read) + return MZ_WRITE_ERROR; + } + + return read; +} + +int32_t mz_zip_reader_entry_save(void *handle, void *stream, mz_stream_write_cb write_cb) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + uint64_t current_time = 0; + uint64_t update_time = 0; + int64_t current_pos = 0; + int64_t update_pos = 0; + int32_t err = MZ_OK; + int32_t written = 0; + + if (mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + if (!reader->file_info) + return MZ_PARAM_ERROR; + + /* Update the progress at the beginning */ + if (reader->progress_cb) + reader->progress_cb(reader, reader->progress_userdata, reader->file_info, current_pos); + + /* Write data to stream until done */ + while (err == MZ_OK) { + written = mz_zip_reader_entry_save_process(reader, stream, write_cb); + if (written == MZ_END_OF_STREAM) + break; + if (written > 0) + current_pos += written; + if (written < 0) + err = written; + + /* Update progress if enough time have passed */ + current_time = mz_os_ms_time(); + if ((current_time - update_time) > reader->progress_cb_interval_ms) { + if (reader->progress_cb) + reader->progress_cb(reader, reader->progress_userdata, reader->file_info, current_pos); + + update_pos = current_pos; + update_time = current_time; + } + } + + /* Update the progress at the end */ + if (reader->progress_cb && update_pos != current_pos) + reader->progress_cb(reader, reader->progress_userdata, reader->file_info, current_pos); + + return err; +} + +int32_t mz_zip_reader_entry_save_file(void *handle, const char *path) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + void *stream = NULL; + uint32_t target_attrib = 0; + int32_t err_attrib = 0; + int32_t err = MZ_OK; + int32_t err_cb = MZ_OK; + char *pathwfs = NULL; + char *directory = NULL; + + if (mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + if (!reader->file_info || !path) + return MZ_PARAM_ERROR; + + pathwfs = (char *)strdup(path); + if (!pathwfs) + return MZ_MEM_ERROR; + + if (reader->entry_cb) + reader->entry_cb(reader, reader->entry_userdata, reader->file_info, pathwfs); + + directory = (char *)strdup(pathwfs); + if (!directory) { + err = MZ_MEM_ERROR; + goto save_cleanup; + } + mz_path_remove_filename(directory); + + /* If it is a directory entry then create a directory instead of writing file */ + if ((mz_zip_entry_is_dir(reader->zip_handle) == MZ_OK) && (mz_zip_entry_is_symlink(reader->zip_handle) != MZ_OK)) { + err = mz_dir_make(directory); + goto save_cleanup; + } + + /* Check if path traverses through an existing symlink that escapes destination */ + if (reader->destination_dir && + mz_dir_has_unsafe_symlink(directory, reader->destination_dir) != MZ_OK) { + err = MZ_EXIST_ERROR; + goto save_cleanup; + } + + /* Check if file exists and ask if we want to overwrite */ + if (reader->overwrite_cb && mz_os_file_exists(pathwfs) == MZ_OK) { + err_cb = reader->overwrite_cb(reader, reader->overwrite_userdata, reader->file_info, pathwfs); + if (err_cb != MZ_OK) + goto save_cleanup; + /* We want to overwrite the file so we delete the existing one */ + mz_os_unlink(pathwfs); + } + + /* If symbolic link then properly construct destination path and link path */ + if ((mz_zip_entry_is_symlink(reader->zip_handle) == MZ_OK) && (mz_path_has_slash(pathwfs) == MZ_OK)) { + mz_path_remove_slash(pathwfs); + mz_path_remove_filename(directory); + } + + /* Create the output directory if it doesn't already exist */ + if (mz_os_is_dir(directory) != MZ_OK) { + err = mz_dir_make(directory); + if (err != MZ_OK) + goto save_cleanup; + } + + /* If it is a symbolic link then create symbolic link instead of writing file */ + if (mz_zip_entry_is_symlink(reader->zip_handle) == MZ_OK) { + if (reader->file_info->linkname && *reader->file_info->linkname != 0) { + /* Create symbolic link from UNIX1 extrafield */ + err = mz_os_make_symlink(pathwfs, reader->file_info->linkname); + } else if (reader->file_info->uncompressed_size < UINT16_MAX) { + /* Create symbolic link from zip entry contents */ + stream = mz_stream_mem_create(); + if (!stream) { + err = MZ_MEM_ERROR; + goto save_cleanup; + } + + err = mz_stream_mem_open(stream, NULL, MZ_OPEN_MODE_CREATE); + + if (err == MZ_OK) + err = mz_zip_reader_entry_save(reader, stream, mz_stream_write); + + if (err == MZ_OK) + err = mz_stream_write_uint8(stream, 0); + + if (err == MZ_OK) { + const char *linkname = NULL; + if (mz_stream_mem_get_buffer(stream, (const void **)&linkname) == MZ_OK) + err = mz_os_make_symlink(pathwfs, linkname); + } + + mz_stream_mem_close(stream); + mz_stream_mem_delete(&stream); + } + + goto save_cleanup; + } + + /* Create the file on disk so we can save to it */ + stream = mz_stream_os_create(); + if (!stream) { + err = MZ_MEM_ERROR; + goto save_cleanup; + } + + err = mz_stream_os_open(stream, pathwfs, MZ_OPEN_MODE_CREATE); + + if (err == MZ_OK) + err = mz_zip_reader_entry_save(reader, stream, mz_stream_write); + + mz_stream_close(stream); + mz_stream_delete(&stream); + + if (err == MZ_OK) { + /* Set the time of the file that has been created */ + mz_os_set_file_date(pathwfs, reader->file_info->modified_date, reader->file_info->accessed_date, + reader->file_info->creation_date); + } + + if (err == MZ_OK) { + /* Set file attributes for the correct system */ + err_attrib = + mz_zip_attrib_convert(MZ_HOST_SYSTEM(reader->file_info->version_madeby), reader->file_info->external_fa, + MZ_VERSION_MADEBY_HOST_SYSTEM, &target_attrib); + + if (err_attrib == MZ_OK) + mz_os_set_file_attribs(pathwfs, target_attrib); + } + +save_cleanup: + free(pathwfs); + free(directory); + + return err; +} + +int32_t mz_zip_reader_entry_save_buffer(void *handle, void *buf, int32_t len) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + void *mem_stream = NULL; + int32_t err = MZ_OK; + + if (mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + if (!reader->file_info || reader->file_info->uncompressed_size > INT32_MAX) + return MZ_PARAM_ERROR; + if (len != (int32_t)reader->file_info->uncompressed_size) + return MZ_BUF_ERROR; + + /* Create a memory stream backed by our buffer and save to it */ + mem_stream = mz_stream_mem_create(); + if (!mem_stream) + return MZ_MEM_ERROR; + + mz_stream_mem_set_buffer(mem_stream, buf, len); + + err = mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_WRITE); + if (err == MZ_OK) + err = mz_zip_reader_entry_save(reader, mem_stream, mz_stream_mem_write); + + mz_stream_mem_delete(&mem_stream); + return err; +} + +int32_t mz_zip_reader_entry_save_buffer_length(void *handle) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + + if (mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + if (!reader->file_info || reader->file_info->uncompressed_size > INT32_MAX) + return MZ_PARAM_ERROR; + + /* Get the maximum size required for the save buffer */ + return (int32_t)reader->file_info->uncompressed_size; +} + +/***************************************************************************/ + +int32_t mz_zip_reader_save_all(void *handle, const char *destination_dir) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + int32_t err = MZ_OK; + int32_t utf8_name_size = 0; + int32_t resolved_name_size = 0; + int32_t destination_dir_len = 0; + char *utf8_string = NULL; + char *path = NULL; + char *utf8_name = NULL; + char *resolved_name = NULL; + char *new_alloc = NULL; + + if (!reader) + return MZ_PARAM_ERROR; + + reader->destination_dir = destination_dir; + err = mz_zip_reader_goto_first_entry(reader); + + if (err == MZ_END_OF_LIST) + return err; + + if (destination_dir) + destination_dir_len = (int32_t)strlen(destination_dir) + 1; + + while (err == MZ_OK) { + /* Assume 4 bytes per character needed + 1 for terminating null */ + utf8_name_size = reader->file_info->filename_size * 4 + 1; + resolved_name_size = utf8_name_size; + + if (destination_dir) { + /* +1 is for the "/" separator */ + resolved_name_size += destination_dir_len; + } + + new_alloc = (char *)realloc(path, resolved_name_size); + if (!new_alloc) { + err = MZ_MEM_ERROR; + goto save_all_cleanup; + } + path = new_alloc; + new_alloc = (char *)realloc(utf8_name, utf8_name_size); + if (!new_alloc) { + err = MZ_MEM_ERROR; + goto save_all_cleanup; + } + utf8_name = new_alloc; + new_alloc = (char *)realloc(resolved_name, resolved_name_size); + if (!new_alloc) { + err = MZ_MEM_ERROR; + goto save_all_cleanup; + } + resolved_name = new_alloc; + + /* Construct output path */ + path[0] = 0; + + strncpy(utf8_name, reader->file_info->filename, utf8_name_size - 1); + utf8_name[utf8_name_size - 1] = 0; + + if ((reader->encoding > 0) && (reader->file_info->flag & MZ_ZIP_FLAG_UTF8) == 0) { + utf8_string = mz_os_utf8_string_create(reader->file_info->filename, reader->encoding); + if (utf8_string) { + strncpy(utf8_name, utf8_string, utf8_name_size - 1); + utf8_name[utf8_name_size - 1] = 0; + mz_os_utf8_string_delete(&utf8_string); + } + } + + err = mz_path_resolve(utf8_name, resolved_name, resolved_name_size); + if (err != MZ_OK) + break; + + if (destination_dir) + mz_path_combine(path, destination_dir, resolved_name_size); + + mz_path_combine(path, resolved_name, resolved_name_size); + + /* Save file to disk */ + err = mz_zip_reader_entry_save_file(reader, path); + + if (err == MZ_OK) + err = mz_zip_reader_goto_next_entry(reader); + } + + if (err == MZ_END_OF_LIST) + err = MZ_OK; + +save_all_cleanup: + free(path); + free(utf8_name); + free(resolved_name); + + return err; +} + +/***************************************************************************/ + +void mz_zip_reader_set_pattern(void *handle, const char *pattern, uint8_t ignore_case) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader) + return; + reader->pattern = pattern; + reader->pattern_ignore_case = ignore_case; +} + +void mz_zip_reader_set_password(void *handle, const char *password) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader) + return; + reader->password = password; +} + +void mz_zip_reader_set_raw(void *handle, uint8_t raw) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader) + return; + reader->raw = raw; +} + +int32_t mz_zip_reader_get_raw(void *handle, uint8_t *raw) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader || !raw) + return MZ_PARAM_ERROR; + *raw = reader->raw; + return MZ_OK; +} + +int32_t mz_zip_reader_get_zip_cd(void *handle, uint8_t *zip_cd) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader || !zip_cd) + return MZ_PARAM_ERROR; + *zip_cd = reader->cd_zipped; + return MZ_OK; +} + +int32_t mz_zip_reader_get_comment(void *handle, const char **comment) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + if (!comment) + return MZ_PARAM_ERROR; + return mz_zip_get_comment(reader->zip_handle, comment); +} + +int32_t mz_zip_reader_set_recover(void *handle, uint8_t recover) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader) + return MZ_PARAM_ERROR; + reader->recover = recover; + return MZ_OK; +} + +void mz_zip_reader_set_encoding(void *handle, int32_t encoding) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader) + return; + reader->encoding = encoding; +} + +void mz_zip_reader_set_overwrite_cb(void *handle, void *userdata, mz_zip_reader_overwrite_cb cb) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader) + return; + reader->overwrite_cb = cb; + reader->overwrite_userdata = userdata; +} + +void mz_zip_reader_set_password_cb(void *handle, void *userdata, mz_zip_reader_password_cb cb) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader) + return; + reader->password_cb = cb; + reader->password_userdata = userdata; +} + +void mz_zip_reader_set_progress_cb(void *handle, void *userdata, mz_zip_reader_progress_cb cb) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader) + return; + reader->progress_cb = cb; + reader->progress_userdata = userdata; +} + +void mz_zip_reader_set_progress_interval(void *handle, uint32_t milliseconds) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader) + return; + reader->progress_cb_interval_ms = milliseconds; +} + +void mz_zip_reader_set_entry_cb(void *handle, void *userdata, mz_zip_reader_entry_cb cb) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader) + return; + reader->entry_cb = cb; + reader->entry_userdata = userdata; +} + +int32_t mz_zip_reader_get_zip_handle(void *handle, void **zip_handle) { + mz_zip_reader *reader = (mz_zip_reader *)handle; + if (!reader || !zip_handle) + return MZ_PARAM_ERROR; + *zip_handle = reader->zip_handle; + if (!*zip_handle) + return MZ_EXIST_ERROR; + return MZ_OK; +} + +/***************************************************************************/ + +void *mz_zip_reader_create(void) { + mz_zip_reader *reader = (mz_zip_reader *)calloc(1, sizeof(mz_zip_reader)); + if (reader) { + reader->recover = 1; + reader->progress_cb_interval_ms = MZ_DEFAULT_PROGRESS_INTERVAL; + } + return reader; +} + +void mz_zip_reader_delete(void **handle) { + mz_zip_reader *reader = NULL; + if (!handle) + return; + reader = (mz_zip_reader *)*handle; + if (reader) { + mz_zip_reader_close(reader); + free(reader); + } + *handle = NULL; +} + +/***************************************************************************/ + +typedef struct mz_zip_writer_s { + void *zip_handle; + void *file_stream; + void *buffered_stream; + void *split_stream; + void *hash; + uint16_t hash_algorithm; + void *mem_stream; + void *file_extra_stream; + mz_zip_file file_info; + void *overwrite_userdata; + mz_zip_writer_overwrite_cb overwrite_cb; + void *password_userdata; + mz_zip_writer_password_cb password_cb; + void *progress_userdata; + mz_zip_writer_progress_cb progress_cb; + uint32_t progress_cb_interval_ms; + void *entry_userdata; + mz_zip_writer_entry_cb entry_cb; + const char *password; + const char *comment; + uint16_t compress_method; + int16_t compress_level; + uint8_t follow_links; + uint8_t store_links; + uint8_t zip_cd; + uint8_t aes; + uint8_t raw; + uint8_t buffer[UINT16_MAX]; +} mz_zip_writer; + +/***************************************************************************/ + +int32_t mz_zip_writer_zip_cd(void *handle) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + mz_zip_file cd_file; + uint64_t number_entry = 0; + int64_t cd_mem_length = 0; + int32_t err = MZ_OK; + int32_t extrafield_size = 0; + void *file_extra_stream = NULL; + void *cd_mem_stream = NULL; + + memset(&cd_file, 0, sizeof(cd_file)); + + mz_zip_get_number_entry(writer->zip_handle, &number_entry); + mz_zip_get_cd_mem_stream(writer->zip_handle, &cd_mem_stream); + mz_stream_seek(cd_mem_stream, 0, MZ_SEEK_END); + cd_mem_length = (uint32_t)mz_stream_tell(cd_mem_stream); + mz_stream_seek(cd_mem_stream, 0, MZ_SEEK_SET); + + cd_file.filename = MZ_ZIP_CD_FILENAME; + cd_file.modified_date = time(NULL); + cd_file.version_madeby = MZ_VERSION_MADEBY; + cd_file.compression_method = writer->compress_method; + cd_file.uncompressed_size = (int32_t)cd_mem_length; + cd_file.flag = MZ_ZIP_FLAG_UTF8; + + if (writer->password) + cd_file.flag |= MZ_ZIP_FLAG_ENCRYPTED; + + file_extra_stream = mz_stream_mem_create(); + if (!file_extra_stream) + return MZ_MEM_ERROR; + + mz_stream_mem_open(file_extra_stream, NULL, MZ_OPEN_MODE_CREATE); + + mz_zip_extrafield_write(file_extra_stream, MZ_ZIP_EXTENSION_CDCD, 8); + + mz_stream_write_uint64(file_extra_stream, number_entry); + + mz_stream_mem_get_buffer(file_extra_stream, (const void **)&cd_file.extrafield); + mz_stream_mem_get_buffer_length(file_extra_stream, &extrafield_size); + cd_file.extrafield_size = (uint16_t)extrafield_size; + + err = mz_zip_writer_entry_open(writer, &cd_file); + if (err == MZ_OK) { + mz_stream_copy_stream(writer, mz_zip_writer_entry_write, cd_mem_stream, NULL, (int32_t)cd_mem_length); + + mz_stream_seek(cd_mem_stream, 0, MZ_SEEK_SET); + mz_stream_mem_set_buffer_limit(cd_mem_stream, 0); + + err = mz_zip_writer_entry_close(writer); + } + + mz_stream_mem_delete(&file_extra_stream); + + return err; +} + +/***************************************************************************/ + +int32_t mz_zip_writer_is_open(void *handle) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer || !writer->zip_handle) + return MZ_PARAM_ERROR; + return MZ_OK; +} + +static int32_t mz_zip_writer_open_int(void *handle, void *stream, int32_t mode) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + int32_t err = MZ_OK; + + writer->zip_handle = mz_zip_create(); + if (writer->zip_handle == NULL) + return MZ_MEM_ERROR; + + err = mz_zip_open(writer->zip_handle, stream, mode); + + if (err != MZ_OK) { + mz_zip_writer_close(writer); + return err; + } + + return MZ_OK; +} + +int32_t mz_zip_writer_open(void *handle, void *stream, uint8_t append) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + int32_t mode = MZ_OPEN_MODE_WRITE; + + if (!writer) + return MZ_PARAM_ERROR; + if (append) { + mode |= MZ_OPEN_MODE_APPEND; + } else { + mode |= MZ_OPEN_MODE_CREATE; + } + + return mz_zip_writer_open_int(writer, stream, mode); +} + +int32_t mz_zip_writer_open_file(void *handle, const char *path, int64_t disk_size, uint8_t append) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + int32_t mode = MZ_OPEN_MODE_READWRITE; + int32_t err = MZ_OK; + int32_t err_cb = 0; + char directory[320]; + + if (!writer) + return MZ_PARAM_ERROR; + mz_zip_writer_close(writer); + + if (mz_os_file_exists(path) != MZ_OK) { + /* If the file doesn't exist, we don't append file */ + mode |= MZ_OPEN_MODE_CREATE; + + /* Create destination directory if it doesn't already exist */ + if (strchr(path, '/') || strrchr(path, '\\')) { + strncpy(directory, path, sizeof(directory) - 1); + directory[sizeof(directory) - 1] = 0; + mz_path_remove_filename(directory); + if (mz_os_file_exists(directory) != MZ_OK) + mz_dir_make(directory); + } + } else if (append) { + mode |= MZ_OPEN_MODE_APPEND; + } else { + if (writer->overwrite_cb) + err_cb = writer->overwrite_cb(writer, writer->overwrite_userdata, path); + + if (err_cb == MZ_INTERNAL_ERROR) + return err; + + if (err_cb == MZ_OK) + mode |= MZ_OPEN_MODE_CREATE; + else + mode |= MZ_OPEN_MODE_APPEND; + } + + writer->file_stream = mz_stream_os_create(); + if (!writer->file_stream) + return MZ_MEM_ERROR; + writer->buffered_stream = mz_stream_buffered_create(); + if (!writer->buffered_stream) { + mz_stream_os_delete(&writer->file_stream); + return MZ_MEM_ERROR; + } + writer->split_stream = mz_stream_split_create(); + if (!writer->split_stream) { + mz_stream_buffered_delete(&writer->buffered_stream); + mz_stream_os_delete(&writer->file_stream); + return MZ_MEM_ERROR; + } + + mz_stream_set_base(writer->buffered_stream, writer->file_stream); + mz_stream_set_base(writer->split_stream, writer->buffered_stream); + + mz_stream_split_set_prop_int64(writer->split_stream, MZ_STREAM_PROP_DISK_SIZE, disk_size); + + err = mz_stream_open(writer->split_stream, path, mode); + if (err == MZ_OK) + err = mz_zip_writer_open_int(writer, writer->split_stream, mode); + + return err; +} + +int32_t mz_zip_writer_open_file_in_memory(void *handle, const char *path) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + void *file_stream = NULL; + int64_t file_size = 0; + int32_t err = 0; + + if (!writer) + return MZ_PARAM_ERROR; + mz_zip_writer_close(writer); + + file_stream = mz_stream_os_create(); + if (!file_stream) + return MZ_MEM_ERROR; + + err = mz_stream_os_open(file_stream, path, MZ_OPEN_MODE_READ); + + if (err != MZ_OK) { + mz_stream_os_delete(&file_stream); + mz_zip_writer_close(writer); + return err; + } + + mz_stream_os_seek(file_stream, 0, MZ_SEEK_END); + file_size = mz_stream_os_tell(file_stream); + mz_stream_os_seek(file_stream, 0, MZ_SEEK_SET); + writer->mem_stream = mz_stream_mem_create(); + + if ((file_size <= 0) || (file_size > UINT32_MAX) || (!writer->mem_stream)) { + /* Memory size is too large or too small */ + + mz_stream_os_close(file_stream); + mz_stream_os_delete(&file_stream); + mz_zip_writer_close(writer); + return MZ_MEM_ERROR; + } + + mz_stream_mem_set_grow_size(writer->mem_stream, (int32_t)file_size); + mz_stream_mem_open(writer->mem_stream, NULL, MZ_OPEN_MODE_CREATE); + + err = mz_stream_copy(writer->mem_stream, file_stream, (int32_t)file_size); + + mz_stream_os_close(file_stream); + mz_stream_os_delete(&file_stream); + + if (err == MZ_OK) + err = mz_zip_writer_open(writer, writer->mem_stream, 1); + if (err != MZ_OK) + mz_zip_writer_close(writer); + + return err; +} + +int32_t mz_zip_writer_close(void *handle) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + int32_t err = MZ_OK; + + if (!writer) + return MZ_PARAM_ERROR; + if (writer->zip_handle) { + mz_zip_set_version_madeby(writer->zip_handle, MZ_VERSION_MADEBY); + if (writer->comment) + mz_zip_set_comment(writer->zip_handle, writer->comment); + if (writer->zip_cd) + mz_zip_writer_zip_cd(writer); + + err = mz_zip_close(writer->zip_handle); + mz_zip_delete(&writer->zip_handle); + } + + if (writer->split_stream) { + mz_stream_split_close(writer->split_stream); + mz_stream_split_delete(&writer->split_stream); + } + + if (writer->buffered_stream) + mz_stream_buffered_delete(&writer->buffered_stream); + + if (writer->file_stream) + mz_stream_os_delete(&writer->file_stream); + + if (writer->mem_stream) { + mz_stream_mem_close(writer->mem_stream); + mz_stream_mem_delete(&writer->mem_stream); + } + + return err; +} + +/***************************************************************************/ + +int32_t mz_zip_writer_entry_open(void *handle, mz_zip_file *file_info) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + int32_t err = MZ_OK; + const char *password = NULL; + char password_buf[120]; + + if (!writer) + return MZ_PARAM_ERROR; + /* Copy file info to access data upon close */ + memcpy(&writer->file_info, file_info, sizeof(mz_zip_file)); + + if (writer->entry_cb) + writer->entry_cb(writer, writer->entry_userdata, &writer->file_info); + + password = writer->password; + + /* Check if we need a password and ask for it if we need to */ + if (!password && writer->password_cb && (writer->file_info.flag & MZ_ZIP_FLAG_ENCRYPTED)) { + writer->password_cb(writer, writer->password_userdata, &writer->file_info, password_buf, sizeof(password_buf)); + password = password_buf; + } + +#ifndef MZ_ZIP_NO_CRYPTO + if (mz_zip_attrib_is_dir(writer->file_info.external_fa, writer->file_info.version_madeby) != MZ_OK) { + /* Start calculating hash */ + writer->hash = mz_crypt_sha_create(); + writer->hash_algorithm = MZ_HASH_SHA256; + if (!writer->hash) + return MZ_MEM_ERROR; + err = mz_crypt_sha_set_algorithm(writer->hash, writer->hash_algorithm); + if (err != MZ_OK) { + writer->hash_algorithm = MZ_HASH_SHA1; + err = mz_crypt_sha_set_algorithm(writer->hash, writer->hash_algorithm); + } + + mz_crypt_sha_begin(writer->hash); + } +#endif + + /* Open entry in zip */ + if (err == MZ_OK) { + err = mz_zip_entry_write_open(writer->zip_handle, &writer->file_info, writer->compress_level, writer->raw, + password); + } + + return err; +} + +int32_t mz_zip_writer_entry_close(void *handle) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + int32_t err = MZ_OK; +#ifndef MZ_ZIP_NO_CRYPTO + const uint8_t *extrafield = NULL; + int32_t extrafield_size = 0; + int16_t field_length_hash = 0; + uint8_t hash_digest[MZ_HASH_MAX_SIZE]; +#endif + + if (!writer) + return MZ_PARAM_ERROR; +#ifndef MZ_ZIP_NO_CRYPTO + if (writer->hash) { + uint16_t hash_digest_size = 0; + + switch (writer->hash_algorithm) { + case MZ_HASH_SHA1: + hash_digest_size = MZ_HASH_SHA1_SIZE; + break; + case MZ_HASH_SHA256: + hash_digest_size = MZ_HASH_SHA256_SIZE; + break; + default: + return MZ_PARAM_ERROR; + } + + mz_crypt_sha_end(writer->hash, hash_digest, hash_digest_size); + mz_crypt_sha_delete(&writer->hash); + + /* Copy extrafield so we can append our own fields before close */ + writer->file_extra_stream = mz_stream_mem_create(); + if (!writer->file_extra_stream) + return MZ_MEM_ERROR; + + mz_stream_mem_open(writer->file_extra_stream, NULL, MZ_OPEN_MODE_CREATE); + + /* Write digest to extrafield */ + field_length_hash = 4 + hash_digest_size; + err = mz_zip_extrafield_write(writer->file_extra_stream, MZ_ZIP_EXTENSION_HASH, field_length_hash); + if (err == MZ_OK) + err = mz_stream_write_uint16(writer->file_extra_stream, writer->hash_algorithm); + if (err == MZ_OK) + err = mz_stream_write_uint16(writer->file_extra_stream, hash_digest_size); + if (err == MZ_OK) { + if (mz_stream_write(writer->file_extra_stream, hash_digest, hash_digest_size) != hash_digest_size) + err = MZ_WRITE_ERROR; + } + + if (writer->file_info.extrafield && writer->file_info.extrafield_size > 0) { + mz_stream_mem_write(writer->file_extra_stream, writer->file_info.extrafield, + writer->file_info.extrafield_size); + } + + /* Update extra field for central directory after adding extra fields */ + mz_stream_mem_get_buffer(writer->file_extra_stream, (const void **)&extrafield); + mz_stream_mem_get_buffer_length(writer->file_extra_stream, &extrafield_size); + + mz_zip_entry_set_extrafield(writer->zip_handle, extrafield, (uint16_t)extrafield_size); + } +#endif + + if (err == MZ_OK) { + if (writer->raw) + err = + mz_zip_entry_close_raw(writer->zip_handle, writer->file_info.uncompressed_size, writer->file_info.crc); + else + err = mz_zip_entry_close(writer->zip_handle); + } + + if (writer->file_extra_stream) + mz_stream_mem_delete(&writer->file_extra_stream); + + return err; +} + +int32_t mz_zip_writer_entry_write(void *handle, const void *buf, int32_t len) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + int32_t written = 0; + if (!writer) + return MZ_PARAM_ERROR; + written = mz_zip_entry_write(writer->zip_handle, buf, len); +#ifndef MZ_ZIP_NO_CRYPTO + if (written > 0 && writer->hash) + mz_crypt_sha_update(writer->hash, buf, written); +#endif + return written; +} +/***************************************************************************/ + +int32_t mz_zip_writer_add_process(void *handle, void *stream, mz_stream_read_cb read_cb) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + int32_t read = 0; + int32_t written = 0; + int32_t err = MZ_OK; + + if (mz_zip_writer_is_open(writer) != MZ_OK) + return MZ_PARAM_ERROR; + /* If the entry isn't open for writing, open it */ + if (mz_zip_entry_is_open(writer->zip_handle) != MZ_OK) + return MZ_PARAM_ERROR; + if (!read_cb) + return MZ_PARAM_ERROR; + + read = read_cb(stream, writer->buffer, sizeof(writer->buffer)); + if (read == 0) + return MZ_END_OF_STREAM; + if (read < 0) { + err = read; + return err; + } + + written = mz_zip_writer_entry_write(writer, writer->buffer, read); + if (written != read) + return MZ_WRITE_ERROR; + + return written; +} + +int32_t mz_zip_writer_add(void *handle, void *stream, mz_stream_read_cb read_cb) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + uint64_t current_time = 0; + uint64_t update_time = 0; + int64_t current_pos = 0; + int64_t update_pos = 0; + int32_t err = MZ_OK; + int32_t written = 0; + + if (!writer) + return MZ_PARAM_ERROR; + /* Update the progress at the beginning */ + if (writer->progress_cb) + writer->progress_cb(writer, writer->progress_userdata, &writer->file_info, current_pos); + + /* Write data to stream until done */ + while (err == MZ_OK) { + written = mz_zip_writer_add_process(writer, stream, read_cb); + if (written == MZ_END_OF_STREAM) + break; + if (written > 0) + current_pos += written; + if (written < 0) + err = written; + + /* Update progress if enough time have passed */ + current_time = mz_os_ms_time(); + if ((current_time - update_time) > writer->progress_cb_interval_ms) { + if (writer->progress_cb) + writer->progress_cb(writer, writer->progress_userdata, &writer->file_info, current_pos); + + update_pos = current_pos; + update_time = current_time; + } + } + + /* Update the progress at the end */ + if (writer->progress_cb && update_pos != current_pos) + writer->progress_cb(writer, writer->progress_userdata, &writer->file_info, current_pos); + + return err; +} + +int32_t mz_zip_writer_add_info(void *handle, void *stream, mz_stream_read_cb read_cb, mz_zip_file *file_info) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + int32_t err = MZ_OK; + + if (mz_zip_writer_is_open(writer) != MZ_OK) + return MZ_PARAM_ERROR; + if (!file_info) + return MZ_PARAM_ERROR; + + /* Add to zip */ + err = mz_zip_writer_entry_open(writer, file_info); + if (err != MZ_OK) + return err; + + if (stream) { + if (mz_zip_attrib_is_dir(writer->file_info.external_fa, writer->file_info.version_madeby) != MZ_OK) { + err = mz_zip_writer_add(writer, stream, read_cb); + if (err != MZ_OK) + return err; + } + } + + err = mz_zip_writer_entry_close(writer); + + return err; +} + +int32_t mz_zip_writer_add_buffer(void *handle, const void *buf, int32_t len, mz_zip_file *file_info) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + void *mem_stream = NULL; + int32_t err = MZ_OK; + + if (mz_zip_writer_is_open(writer) != MZ_OK) + return MZ_PARAM_ERROR; + if (!buf) + return MZ_PARAM_ERROR; + + /* Create a memory stream backed by our buffer and add from it */ + mem_stream = mz_stream_mem_create(); + if (!mem_stream) + return MZ_STREAM_ERROR; + + mz_stream_mem_set_buffer(mem_stream, (void *)buf, len); + + err = mz_stream_mem_open(mem_stream, NULL, MZ_OPEN_MODE_READ); + if (err == MZ_OK) + err = mz_zip_writer_add_info(writer, mem_stream, mz_stream_mem_read, file_info); + + mz_stream_mem_delete(&mem_stream); + return err; +} + +int32_t mz_zip_writer_add_file(void *handle, const char *path, const char *filename_in_zip) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + mz_zip_file file_info; + uint32_t target_attrib = 0; + uint32_t src_attrib = 0; + int32_t err = MZ_OK; + uint8_t src_sys = 0; + uint8_t is_symlink = 0; + void *stream = NULL; + char link_path[1024]; + const char *filename = filename_in_zip; + + if (mz_zip_writer_is_open(writer) != MZ_OK) + return MZ_PARAM_ERROR; + if (!path) + return MZ_PARAM_ERROR; + + if (!filename) { + err = mz_path_get_filename(path, &filename); + if (err != MZ_OK) + return err; + } + + if (mz_os_is_symlink(path) == MZ_OK) + is_symlink = 1; + + if (is_symlink && !writer->store_links && !writer->follow_links) + return MZ_OK; + + memset(&file_info, 0, sizeof(file_info)); + + /* The path name saved, should not include a leading slash. */ + /* If it did, windows/xp and dynazip couldn't read the zip file. */ + + while (filename[0] == '\\' || filename[0] == '/') + filename += 1; + + /* Get information about the file on disk so we can store it in zip */ + + file_info.version_madeby = MZ_VERSION_MADEBY; + file_info.compression_method = writer->compress_method; + file_info.filename = filename; + file_info.uncompressed_size = mz_os_get_file_size(path); + file_info.flag = MZ_ZIP_FLAG_UTF8; + + if (writer->zip_cd) + file_info.flag |= MZ_ZIP_FLAG_MASK_LOCAL_INFO; + if (writer->aes) + file_info.aes_version = MZ_AES_VERSION; + + mz_os_get_file_date(path, &file_info.modified_date, &file_info.accessed_date, &file_info.creation_date); + + if (is_symlink && writer->store_links) + mz_os_get_link_attribs(path, &src_attrib); + else + mz_os_get_file_attribs(path, &src_attrib); + + src_sys = MZ_HOST_SYSTEM(file_info.version_madeby); + + if ((src_sys != MZ_HOST_SYSTEM_MSDOS) && (src_sys != MZ_HOST_SYSTEM_WINDOWS_NTFS)) { + /* High bytes are OS specific attributes, low byte is always DOS attributes */ + if (mz_zip_attrib_convert(src_sys, src_attrib, MZ_HOST_SYSTEM_MSDOS, &target_attrib) == MZ_OK) + file_info.external_fa = target_attrib; + file_info.external_fa |= (src_attrib << 16); + } else { + file_info.external_fa = src_attrib; + } + + if (is_symlink && writer->store_links) { + err = mz_os_read_symlink(path, link_path, sizeof(link_path)); + if (err == MZ_OK) + file_info.linkname = link_path; + } else if (mz_os_is_dir(path) != MZ_OK) { + uint32_t mode = MZ_OPEN_MODE_READ; + stream = mz_stream_os_create(); + if (!stream) + return MZ_STREAM_ERROR; + if (!writer->follow_links) + mode |= MZ_OPEN_MODE_NOFOLLOW; + err = mz_stream_os_open(stream, path, mode); + } + + if (err == MZ_OK) + err = mz_zip_writer_add_info(writer, stream, mz_stream_read, &file_info); + + if (stream) { + mz_stream_close(stream); + mz_stream_delete(&stream); + } + + return err; +} + +int32_t mz_zip_writer_add_path(void *handle, const char *path, const char *root_path, uint8_t include_path, + uint8_t recursive) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + DIR *dir = NULL; + struct dirent *entry = NULL; + int32_t err = MZ_OK; + int16_t is_dir = 0; + const char *filename = NULL; + const char *filenameinzip = path; + char *wildcard_ptr = NULL; + char full_path[1024]; + char path_dir[1024]; + + if (!writer) + return MZ_PARAM_ERROR; + if (strrchr(path, '*') && mz_os_file_exists(path) != MZ_OK) { + strncpy(path_dir, path, sizeof(path_dir) - 1); + path_dir[sizeof(path_dir) - 1] = 0; + mz_path_remove_filename(path_dir); + wildcard_ptr = path_dir + strlen(path_dir) + 1; + root_path = path = path_dir; + } else { + if (mz_os_is_dir(path) == MZ_OK) + is_dir = 1; + + /* Construct the filename that our file will be stored in the zip as */ + if (!root_path) + root_path = path; + + /* Should the file be stored with any path info at all? */ + if (!include_path) { + if (!is_dir && root_path == path) { + if (mz_path_get_filename(filenameinzip, &filename) == MZ_OK) + filenameinzip = filename; + } else { + filenameinzip += strlen(root_path); + } + } + + if (!writer->store_links && !writer->follow_links) { + if (mz_os_is_symlink(path) == MZ_OK) + return err; + } + + if (*filenameinzip != 0) + err = mz_zip_writer_add_file(writer, path, filenameinzip); + + if (!is_dir) + return err; + + if (writer->store_links) { + if (mz_os_is_symlink(path) == MZ_OK) + return err; + } + } + + dir = mz_os_open_dir(path); + + if (!dir) + return MZ_EXIST_ERROR; + + while ((entry = mz_os_read_dir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + + full_path[0] = 0; + mz_path_combine(full_path, path, sizeof(full_path)); + mz_path_combine(full_path, entry->d_name, sizeof(full_path)); + + if (!recursive && mz_os_is_dir(full_path) == MZ_OK) + continue; + + if ((wildcard_ptr) && (mz_path_compare_wc(entry->d_name, wildcard_ptr, 1) != MZ_OK)) + continue; + + err = mz_zip_writer_add_path(writer, full_path, root_path, include_path, recursive); + if (err != MZ_OK) + break; + } + + mz_os_close_dir(dir); + return err; +} + +int32_t mz_zip_writer_copy_from_reader(void *handle, void *reader) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + mz_zip_file *file_info = NULL; + int64_t compressed_size = 0; + int64_t uncompressed_size = 0; + uint32_t crc32 = 0; + int32_t err = MZ_OK; + uint8_t original_raw = 0; + void *reader_zip_handle = NULL; + void *writer_zip_handle = NULL; + + if (mz_zip_reader_is_open(reader) != MZ_OK) + return MZ_PARAM_ERROR; + if (mz_zip_writer_is_open(writer) != MZ_OK) + return MZ_PARAM_ERROR; + + err = mz_zip_reader_entry_get_info(reader, &file_info); + + if (err != MZ_OK) + return err; + + mz_zip_reader_get_zip_handle(reader, &reader_zip_handle); + mz_zip_writer_get_zip_handle(writer, &writer_zip_handle); + + /* Open entry for raw reading */ + err = mz_zip_entry_read_open(reader_zip_handle, 1, NULL); + + if (err == MZ_OK) { + /* Write entry raw, save original raw value */ + original_raw = writer->raw; + writer->raw = 1; + + err = mz_zip_writer_entry_open(writer, file_info); + + if ((err == MZ_OK) && + (mz_zip_attrib_is_dir(writer->file_info.external_fa, writer->file_info.version_madeby) != MZ_OK)) { + err = mz_zip_writer_add(writer, reader_zip_handle, mz_zip_entry_read); + } + + if (err == MZ_OK) { + err = mz_zip_entry_read_close(reader_zip_handle, &crc32, &compressed_size, &uncompressed_size); + if (err == MZ_OK) + err = mz_zip_entry_write_close(writer_zip_handle, crc32, compressed_size, uncompressed_size); + } + + if (mz_zip_entry_is_open(reader_zip_handle) == MZ_OK) + mz_zip_entry_close(reader_zip_handle); + + if (mz_zip_entry_is_open(writer_zip_handle) == MZ_OK) + mz_zip_entry_close(writer_zip_handle); + +#ifndef MZ_ZIP_NO_CRYPTO + mz_crypt_sha_delete(&writer->hash); +#endif + + writer->raw = original_raw; + } + + return err; +} + +/***************************************************************************/ + +void mz_zip_writer_set_password(void *handle, const char *password) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->password = password; +} + +void mz_zip_writer_set_comment(void *handle, const char *comment) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->comment = comment; +} + +void mz_zip_writer_set_raw(void *handle, uint8_t raw) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->raw = raw; +} + +int32_t mz_zip_writer_get_raw(void *handle, uint8_t *raw) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer || !raw) + return MZ_PARAM_ERROR; + *raw = writer->raw; + return MZ_OK; +} + +void mz_zip_writer_set_aes(void *handle, uint8_t aes) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->aes = aes; +} + +void mz_zip_writer_set_compress_method(void *handle, uint16_t compress_method) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->compress_method = compress_method; +} + +void mz_zip_writer_set_compress_level(void *handle, int16_t compress_level) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->compress_level = compress_level; +} + +void mz_zip_writer_set_follow_links(void *handle, uint8_t follow_links) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->follow_links = follow_links; +} + +int32_t mz_zip_writer_get_follow_links(void *handle, uint8_t *follow_links) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer || !follow_links) + return MZ_PARAM_ERROR; + *follow_links = writer->follow_links; + return MZ_OK; +} + +void mz_zip_writer_set_store_links(void *handle, uint8_t store_links) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->store_links = store_links; +} + +void mz_zip_writer_set_zip_cd(void *handle, uint8_t zip_cd) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->zip_cd = zip_cd; +} + +void mz_zip_writer_set_overwrite_cb(void *handle, void *userdata, mz_zip_writer_overwrite_cb cb) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->overwrite_cb = cb; + writer->overwrite_userdata = userdata; +} + +void mz_zip_writer_set_password_cb(void *handle, void *userdata, mz_zip_writer_password_cb cb) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->password_cb = cb; + writer->password_userdata = userdata; +} + +void mz_zip_writer_set_progress_cb(void *handle, void *userdata, mz_zip_writer_progress_cb cb) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->progress_cb = cb; + writer->progress_userdata = userdata; +} + +void mz_zip_writer_set_progress_interval(void *handle, uint32_t milliseconds) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->progress_cb_interval_ms = milliseconds; +} + +void mz_zip_writer_set_entry_cb(void *handle, void *userdata, mz_zip_writer_entry_cb cb) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer) + return; + writer->entry_cb = cb; + writer->entry_userdata = userdata; +} + +int32_t mz_zip_writer_get_zip_handle(void *handle, void **zip_handle) { + mz_zip_writer *writer = (mz_zip_writer *)handle; + if (!writer || !zip_handle) + return MZ_PARAM_ERROR; + *zip_handle = writer->zip_handle; + if (!*zip_handle) + return MZ_EXIST_ERROR; + return MZ_OK; +} + +/***************************************************************************/ + +void *mz_zip_writer_create(void) { + mz_zip_writer *writer = (mz_zip_writer *)calloc(1, sizeof(mz_zip_writer)); + if (writer) { +#if defined(HAVE_WZAES) + writer->aes = 1; +#endif +#if defined(HAVE_ZLIB) || defined(HAVE_LIBCOMP) + writer->compress_method = MZ_COMPRESS_METHOD_DEFLATE; +#elif defined(HAVE_BZIP2) + writer->compress_method = MZ_COMPRESS_METHOD_BZIP2; +#elif defined(HAVE_LZMA) + writer->compress_method = MZ_COMPRESS_METHOD_LZMA; +#elif defined(HAVE_PPMD) + writer->compress_method = MZ_COMPRESS_METHOD_PPMD; +#else + writer->compress_method = MZ_COMPRESS_METHOD_STORE; +#endif + writer->compress_level = MZ_COMPRESS_LEVEL_BEST; + writer->progress_cb_interval_ms = MZ_DEFAULT_PROGRESS_INTERVAL; + } + return writer; +} + +void mz_zip_writer_delete(void **handle) { + mz_zip_writer *writer = NULL; + if (!handle) + return; + writer = (mz_zip_writer *)*handle; + if (writer) { + mz_zip_writer_close(writer); + free(writer); + } + *handle = NULL; +} + +/***************************************************************************/ diff --git a/thirdparty/minizip/mz_zip_rw.h b/thirdparty/minizip/mz_zip_rw.h new file mode 100644 index 000000000..085572929 --- /dev/null +++ b/thirdparty/minizip/mz_zip_rw.h @@ -0,0 +1,281 @@ +/* mz_zip_rw.h -- Zip reader/writer + part of the minizip-ng project + + Copyright (C) Nathan Moinvaziri + https://github.com/zlib-ng/minizip-ng + + This program is distributed under the terms of the same license as zlib. + See the accompanying LICENSE file for the full text of the license. +*/ + +#ifndef MZ_ZIP_RW_H +#define MZ_ZIP_RW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************/ + +typedef int32_t (*mz_zip_reader_overwrite_cb)(void *handle, void *userdata, mz_zip_file *file_info, const char *path); +typedef int32_t (*mz_zip_reader_password_cb)(void *handle, void *userdata, mz_zip_file *file_info, char *password, + int32_t max_password); +typedef int32_t (*mz_zip_reader_progress_cb)(void *handle, void *userdata, mz_zip_file *file_info, int64_t position); +typedef int32_t (*mz_zip_reader_entry_cb)(void *handle, void *userdata, mz_zip_file *file_info, const char *path); + +/***************************************************************************/ + +int32_t mz_zip_reader_is_open(void *handle); +/* Checks to see if the zip file is open */ + +int32_t mz_zip_reader_open(void *handle, void *stream); +/* Opens zip file from stream */ + +int32_t mz_zip_reader_open_file(void *handle, const char *path); +/* Opens zip file from a file path */ + +int32_t mz_zip_reader_open_file_in_memory(void *handle, const char *path); +/* Opens zip file from a file path into memory for faster access */ + +int32_t mz_zip_reader_open_buffer(void *handle, const uint8_t *buf, int32_t len, uint8_t copy); +/* Opens zip file from memory buffer */ + +int32_t mz_zip_reader_close(void *handle); +/* Closes the zip file */ + +/***************************************************************************/ + +int32_t mz_zip_reader_unzip_cd(void *handle); +/* Unzip the central directory */ + +/***************************************************************************/ + +int32_t mz_zip_reader_goto_first_entry(void *handle); +/* Goto the first entry in the zip file that matches the pattern */ + +int32_t mz_zip_reader_goto_next_entry(void *handle); +/* Goto the next entry in the zip file that matches the pattern */ + +int32_t mz_zip_reader_locate_entry(void *handle, const char *filename, uint8_t ignore_case); +/* Locates an entry by filename */ + +int32_t mz_zip_reader_entry_open(void *handle); +/* Opens an entry for reading */ + +int32_t mz_zip_reader_entry_close(void *handle); +/* Closes an entry */ + +int32_t mz_zip_reader_entry_read(void *handle, void *buf, int32_t len); +/* Reads an entry after being opened */ + +int32_t mz_zip_reader_entry_get_hash(void *handle, uint16_t algorithm, uint8_t *digest, int32_t digest_size); +/* Gets a hash algorithm from the entry's extra field */ + +int32_t mz_zip_reader_entry_get_first_hash(void *handle, uint16_t *algorithm, uint16_t *digest_size); +/* Gets the most secure hash algorithm from the entry's extra field */ + +int32_t mz_zip_reader_entry_get_info(void *handle, mz_zip_file **file_info); +/* Gets the current entry file info */ + +int32_t mz_zip_reader_entry_is_dir(void *handle); +/* Gets the current entry is a directory */ + +int32_t mz_zip_reader_entry_save(void *handle, void *stream, mz_stream_write_cb write_cb); +/* Save the current entry to a stream */ + +int32_t mz_zip_reader_entry_save_process(void *handle, void *stream, mz_stream_write_cb write_cb); +/* Saves a portion of the current entry to a stream callback */ + +int32_t mz_zip_reader_entry_save_file(void *handle, const char *path); +/* Save the current entry to a file */ + +int32_t mz_zip_reader_entry_save_buffer(void *handle, void *buf, int32_t len); +/* Save the current entry to a memory buffer */ + +int32_t mz_zip_reader_entry_save_buffer_length(void *handle); +/* Gets the length of the buffer required to save */ + +/***************************************************************************/ + +int32_t mz_zip_reader_save_all(void *handle, const char *destination_dir); +/* Save all files into a directory */ + +/***************************************************************************/ + +void mz_zip_reader_set_pattern(void *handle, const char *pattern, uint8_t ignore_case); +/* Sets the match pattern for entries in the zip file, if null all entries are matched */ + +void mz_zip_reader_set_password(void *handle, const char *password); +/* Sets the password required for extraction */ + +void mz_zip_reader_set_raw(void *handle, uint8_t raw); +/* Sets whether or not it should save the entry raw */ + +int32_t mz_zip_reader_get_raw(void *handle, uint8_t *raw); +/* Gets whether or not it should save the entry raw */ + +int32_t mz_zip_reader_get_zip_cd(void *handle, uint8_t *zip_cd); +/* Gets whether or not the archive has a zipped central directory */ + +int32_t mz_zip_reader_get_comment(void *handle, const char **comment); +/* Gets the comment for the central directory */ + +int32_t mz_zip_reader_set_recover(void *handle, uint8_t recover); +/* Sets the ability to recover the central dir by reading local file headers */ + +void mz_zip_reader_set_encoding(void *handle, int32_t encoding); +/* Sets whether or not it should support a special character encoding in zip file names. */ + +void mz_zip_reader_set_overwrite_cb(void *handle, void *userdata, mz_zip_reader_overwrite_cb cb); +/* Callback for what to do when a file is being overwritten */ + +void mz_zip_reader_set_password_cb(void *handle, void *userdata, mz_zip_reader_password_cb cb); +/* Callback for when a password is required and hasn't been set */ + +void mz_zip_reader_set_progress_cb(void *handle, void *userdata, mz_zip_reader_progress_cb cb); +/* Callback for extraction progress */ + +void mz_zip_reader_set_progress_interval(void *handle, uint32_t milliseconds); +/* Let at least milliseconds pass between calls to progress callback */ + +void mz_zip_reader_set_entry_cb(void *handle, void *userdata, mz_zip_reader_entry_cb cb); +/* Callback for zip file entries */ + +int32_t mz_zip_reader_get_zip_handle(void *handle, void **zip_handle); +/* Gets the underlying zip instance handle */ + +void *mz_zip_reader_create(void); +/* Create new instance of zip reader */ + +void mz_zip_reader_delete(void **handle); +/* Delete instance of zip reader */ + +/***************************************************************************/ + +typedef int32_t (*mz_zip_writer_overwrite_cb)(void *handle, void *userdata, const char *path); +typedef int32_t (*mz_zip_writer_password_cb)(void *handle, void *userdata, mz_zip_file *file_info, char *password, + int32_t max_password); +typedef int32_t (*mz_zip_writer_progress_cb)(void *handle, void *userdata, mz_zip_file *file_info, int64_t position); +typedef int32_t (*mz_zip_writer_entry_cb)(void *handle, void *userdata, mz_zip_file *file_info); + +/***************************************************************************/ + +int32_t mz_zip_writer_is_open(void *handle); +/* Checks to see if the zip file is open */ + +int32_t mz_zip_writer_open(void *handle, void *stream, uint8_t append); +/* Opens zip file from stream */ + +int32_t mz_zip_writer_open_file(void *handle, const char *path, int64_t disk_size, uint8_t append); +/* Opens zip file from a file path */ + +int32_t mz_zip_writer_open_file_in_memory(void *handle, const char *path); +/* Opens zip file from a file path into memory for faster access */ + +int32_t mz_zip_writer_close(void *handle); +/* Closes the zip file */ + +/***************************************************************************/ + +int32_t mz_zip_writer_entry_open(void *handle, mz_zip_file *file_info); +/* Opens an entry in the zip file for writing */ + +int32_t mz_zip_writer_entry_close(void *handle); +/* Closes entry in zip file */ + +int32_t mz_zip_writer_entry_write(void *handle, const void *buf, int32_t len); +/* Writes data into entry for zip */ + +/***************************************************************************/ + +int32_t mz_zip_writer_add(void *handle, void *stream, mz_stream_read_cb read_cb); +/* Writes all data to the currently open entry in the zip */ + +int32_t mz_zip_writer_add_process(void *handle, void *stream, mz_stream_read_cb read_cb); +/* Writes a portion of data to the currently open entry in the zip */ + +int32_t mz_zip_writer_add_info(void *handle, void *stream, mz_stream_read_cb read_cb, mz_zip_file *file_info); +/* Adds an entry to the zip based on the info */ + +int32_t mz_zip_writer_add_buffer(void *handle, const void *buf, int32_t len, mz_zip_file *file_info); +/* Adds an entry to the zip with a memory buffer */ + +int32_t mz_zip_writer_add_file(void *handle, const char *path, const char *filename_in_zip); +/* Adds an entry to the zip from a file */ + +int32_t mz_zip_writer_add_path(void *handle, const char *path, const char *root_path, uint8_t include_path, + uint8_t recursive); +/* Enumerates a directory or pattern and adds entries to the zip */ + +int32_t mz_zip_writer_copy_from_reader(void *handle, void *reader); +/* Adds an entry from a zip reader instance */ + +/***************************************************************************/ + +void mz_zip_writer_set_password(void *handle, const char *password); +/* Password to use for encrypting files in the zip */ + +void mz_zip_writer_set_comment(void *handle, const char *comment); +/* Comment to use for the archive */ + +void mz_zip_writer_set_raw(void *handle, uint8_t raw); +/* Sets whether or not we should write the entry raw */ + +int32_t mz_zip_writer_get_raw(void *handle, uint8_t *raw); +/* Gets whether or not we should write the entry raw */ + +void mz_zip_writer_set_aes(void *handle, uint8_t aes); +/* Use aes encryption when adding files in zip */ + +void mz_zip_writer_set_compress_method(void *handle, uint16_t compress_method); +/* Sets the compression method when adding files in zip */ + +void mz_zip_writer_set_compress_level(void *handle, int16_t compress_level); +/* Sets the compression level when adding files in zip */ + +void mz_zip_writer_set_follow_links(void *handle, uint8_t follow_links); +/* Follow symbolic links when traversing directories and files to add */ + +int32_t mz_zip_writer_get_follow_links(void *handle, uint8_t *follow_links); +/* Gets whether to follow symbolic links when traversing directories and files to add */ + +void mz_zip_writer_set_store_links(void *handle, uint8_t store_links); +/* Store symbolic links in zip file */ + +void mz_zip_writer_set_zip_cd(void *handle, uint8_t zip_cd); +/* Sets whether or not central directory should be zipped */ + +int32_t mz_zip_writer_set_certificate(void *handle, const char *cert_path, const char *cert_pwd); +/* Sets the certificate and timestamp url to use for signing when adding files in zip */ + +void mz_zip_writer_set_overwrite_cb(void *handle, void *userdata, mz_zip_writer_overwrite_cb cb); +/* Callback for what to do when zip file already exists */ + +void mz_zip_writer_set_password_cb(void *handle, void *userdata, mz_zip_writer_password_cb cb); +/* Callback for ask if a password is required for adding */ + +void mz_zip_writer_set_progress_cb(void *handle, void *userdata, mz_zip_writer_progress_cb cb); +/* Callback for compression progress */ + +void mz_zip_writer_set_progress_interval(void *handle, uint32_t milliseconds); +/* Let at least milliseconds pass between calls to progress callback */ + +void mz_zip_writer_set_entry_cb(void *handle, void *userdata, mz_zip_writer_entry_cb cb); +/* Callback for zip file entries */ + +int32_t mz_zip_writer_get_zip_handle(void *handle, void **zip_handle); +/* Gets the underlying zip handle */ + +void *mz_zip_writer_create(void); +/* Create new instance of zip writer */ + +void mz_zip_writer_delete(void **handle); +/* Delete instance of zip writer */ + +/***************************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/thirdparty/minizip/mztools.c b/thirdparty/minizip/mztools.c deleted file mode 100644 index 8bd32fa18..000000000 --- a/thirdparty/minizip/mztools.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - Additional tools for Minizip - Code: Xavier Roche '2004 - License: Same as ZLIB (www.gzip.org) -*/ - -/* Code */ -#include -#include -#include -#include "zlib.h" -#include "minizip/unzip.h" - -#define READ_8(adr) ((unsigned char)*(adr)) -#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) -#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) - -#define WRITE_8(buff, n) do { \ - *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ -} while(0) -#define WRITE_16(buff, n) do { \ - WRITE_8((unsigned char*)(buff), n); \ - WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ -} while(0) -#define WRITE_32(buff, n) do { \ - WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ - WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ -} while(0) - -extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) -const char* file; -const char* fileOut; -const char* fileOutTmp; -uLong* nRecovered; -uLong* bytesRecovered; -{ - int err = Z_OK; - FILE* fpZip = fopen(file, "rb"); - FILE* fpOut = fopen(fileOut, "wb"); - FILE* fpOutCD = fopen(fileOutTmp, "wb"); - if (fpZip != NULL && fpOut != NULL) { - int entries = 0; - uLong totalBytes = 0; - char header[30]; - char filename[256]; - char extra[1024]; - int offset = 0; - int offsetCD = 0; - while ( fread(header, 1, 30, fpZip) == 30 ) { - int currentOffset = offset; - - /* File entry */ - if (READ_32(header) == 0x04034b50) { - unsigned int version = READ_16(header + 4); - unsigned int gpflag = READ_16(header + 6); - unsigned int method = READ_16(header + 8); - unsigned int filetime = READ_16(header + 10); - unsigned int filedate = READ_16(header + 12); - unsigned int crc = READ_32(header + 14); /* crc */ - unsigned int cpsize = READ_32(header + 18); /* compressed size */ - unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ - unsigned int fnsize = READ_16(header + 26); /* file name length */ - unsigned int extsize = READ_16(header + 28); /* extra field length */ - filename[0] = extra[0] = '\0'; - - /* Header */ - if (fwrite(header, 1, 30, fpOut) == 30) { - offset += 30; - } else { - err = Z_ERRNO; - break; - } - - /* Filename */ - if (fnsize > 0) { - if (fread(filename, 1, fnsize, fpZip) == fnsize) { - if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { - offset += fnsize; - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_STREAM_ERROR; - break; - } - - /* Extra field */ - if (extsize > 0) { - if (fread(extra, 1, extsize, fpZip) == extsize) { - if (fwrite(extra, 1, extsize, fpOut) == extsize) { - offset += extsize; - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_ERRNO; - break; - } - } - - /* Data */ - { - int dataSize = cpsize; - if (dataSize == 0) { - dataSize = uncpsize; - } - if (dataSize > 0) { - char* data = malloc(dataSize); - if (data != NULL) { - if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { - if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { - offset += dataSize; - totalBytes += dataSize; - } else { - err = Z_ERRNO; - } - } else { - err = Z_ERRNO; - } - free(data); - if (err != Z_OK) { - break; - } - } else { - err = Z_MEM_ERROR; - break; - } - } - } - - /* Central directory entry */ - { - char header[46]; - char* comment = ""; - int comsize = (int) strlen(comment); - WRITE_32(header, 0x02014b50); - WRITE_16(header + 4, version); - WRITE_16(header + 6, version); - WRITE_16(header + 8, gpflag); - WRITE_16(header + 10, method); - WRITE_16(header + 12, filetime); - WRITE_16(header + 14, filedate); - WRITE_32(header + 16, crc); - WRITE_32(header + 20, cpsize); - WRITE_32(header + 24, uncpsize); - WRITE_16(header + 28, fnsize); - WRITE_16(header + 30, extsize); - WRITE_16(header + 32, comsize); - WRITE_16(header + 34, 0); /* disk # */ - WRITE_16(header + 36, 0); /* int attrb */ - WRITE_32(header + 38, 0); /* ext attrb */ - WRITE_32(header + 42, currentOffset); - /* Header */ - if (fwrite(header, 1, 46, fpOutCD) == 46) { - offsetCD += 46; - - /* Filename */ - if (fnsize > 0) { - if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { - offsetCD += fnsize; - } else { - err = Z_ERRNO; - break; - } - } else { - err = Z_STREAM_ERROR; - break; - } - - /* Extra field */ - if (extsize > 0) { - if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { - offsetCD += extsize; - } else { - err = Z_ERRNO; - break; - } - } - - /* Comment field */ - if (comsize > 0) { - if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { - offsetCD += comsize; - } else { - err = Z_ERRNO; - break; - } - } - - - } else { - err = Z_ERRNO; - break; - } - } - - /* Success */ - entries++; - - } else { - break; - } - } - - /* Final central directory */ - { - int entriesZip = entries; - char header[22]; - char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; - int comsize = (int) strlen(comment); - if (entriesZip > 0xffff) { - entriesZip = 0xffff; - } - WRITE_32(header, 0x06054b50); - WRITE_16(header + 4, 0); /* disk # */ - WRITE_16(header + 6, 0); /* disk # */ - WRITE_16(header + 8, entriesZip); /* hack */ - WRITE_16(header + 10, entriesZip); /* hack */ - WRITE_32(header + 12, offsetCD); /* size of CD */ - WRITE_32(header + 16, offset); /* offset to CD */ - WRITE_16(header + 20, comsize); /* comment */ - - /* Header */ - if (fwrite(header, 1, 22, fpOutCD) == 22) { - - /* Comment field */ - if (comsize > 0) { - if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { - err = Z_ERRNO; - } - } - - } else { - err = Z_ERRNO; - } - } - - /* Final merge (file + central directory) */ - fclose(fpOutCD); - if (err == Z_OK) { - fpOutCD = fopen(fileOutTmp, "rb"); - if (fpOutCD != NULL) { - int nRead; - char buffer[8192]; - while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { - if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { - err = Z_ERRNO; - break; - } - } - fclose(fpOutCD); - } - } - - /* Close */ - fclose(fpZip); - fclose(fpOut); - - /* Wipe temporary file */ - (void)remove(fileOutTmp); - - /* Number of recovered entries */ - if (err == Z_OK) { - if (nRecovered != NULL) { - *nRecovered = entries; - } - if (bytesRecovered != NULL) { - *bytesRecovered = totalBytes; - } - } - } else { - err = Z_STREAM_ERROR; - } - return err; -} diff --git a/thirdparty/minizip/unzip.c b/thirdparty/minizip/unzip.c deleted file mode 100644 index 96211fb4a..000000000 --- a/thirdparty/minizip/unzip.c +++ /dev/null @@ -1,2125 +0,0 @@ -/* unzip.c -- IO for uncompress .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications of Unzip for Zip64 - Copyright (C) 2007-2008 Even Rouault - - Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - - ------------------------------------------------------------------------------------ - Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of - compatibility with older software. The following is from the original crypt.c. - Code woven in by Terry Thorsen 1/2003. - - Copyright (c) 1990-2000 Info-ZIP. All rights reserved. - - See the accompanying file LICENSE, version 2000-Apr-09 or later - (the contents of which are also included in zip.h) for terms of use. - If, for some reason, all these files are missing, the Info-ZIP license - also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html - - crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - - ------------------------------------------------------------------------------------ - - Changes in unzip.c - - 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos - 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* - 2007-2008 - Even Rouault - Remove old C style function prototypes - 2007-2008 - Even Rouault - Add unzip support for ZIP64 - - Copyright (C) 2007-2008 Even Rouault - - - Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). - Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G - should only read the compressed/uncompressed size from the Zip64 format if - the size from normal header was 0xFFFFFFFF - Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant - Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) - Patch created by Daniel Borca - - Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer - - Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson - -*/ - - -#include -#include -#include - -#ifndef NOUNCRYPT - #define NOUNCRYPT -#endif - -#include "zlib.h" -#include "minizip/unzip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - - -#ifndef CASESENSITIVITYDEFAULT_NO -# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) -# define CASESENSITIVITYDEFAULT_NO -# endif -#endif - - -#ifndef UNZ_BUFSIZE -#define UNZ_BUFSIZE (16384) -#endif - -#ifndef UNZ_MAXFILENAMEINZIP -#define UNZ_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) - - -const char unz_copyright[] = - " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; - -/* unz_file_info_interntal contain internal info about a file in zipfile*/ -typedef struct unz_file_info64_internal_s -{ - ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ -} unz_file_info64_internal; - - -/* file_in_zip_read_info_s contain internal information about a file in zipfile, - when reading and decompress it */ -typedef struct -{ - char *read_buffer; /* internal buffer for compressed data */ - z_stream stream; /* zLib stream structure for inflate */ - -#ifdef HAVE_BZIP2 - bz_stream bstream; /* bzLib stream structure for bziped */ -#endif - - ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ - uLong stream_initialised; /* flag set if stream structure is initialised*/ - - ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ - uInt size_local_extrafield;/* size of the local extra field */ - ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ - ZPOS64_T total_out_64; - - uLong crc32; /* crc32 of all data uncompressed */ - uLong crc32_wait; /* crc32 we must obtain after decompress all */ - ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ - ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ - zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - uLong compression_method; /* compression method (0==store) */ - ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - int raw; -} file_in_zip64_read_info_s; - - -/* unz64_s contain internal information about the zipfile -*/ -typedef struct -{ - zlib_filefunc64_32_def z_filefunc; - int is64bitOpenFunction; - voidpf filestream; /* io structore of the zipfile */ - unz_global_info64 gi; /* public global information */ - ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - ZPOS64_T num_file; /* number of the current file in the zipfile*/ - ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ - ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ - ZPOS64_T central_pos; /* position of the beginning of the central dir*/ - - ZPOS64_T size_central_dir; /* size of the central directory */ - ZPOS64_T offset_central_dir; /* offset of start of central directory with - respect to the starting disk number */ - - unz_file_info64 cur_file_info; /* public info about the current file in zip*/ - unz_file_info64_internal cur_file_info_internal; /* private info about it*/ - file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current - file if we are decompressing it */ - int encrypted; - - int isZip64; - -# ifndef NOUNCRYPT - unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const unsigned long* pcrc_32_tab; -# endif -} unz64_s; - - -#ifndef NOUNCRYPT -#include "zipcrypt.h" -#endif - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ - - -local int unz64local_getByte OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - int *pi)); - -local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) -{ - unsigned char c; - int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return UNZ_OK; - } - else - { - if (ZERROR64(*pzlib_filefunc_def,filestream)) - return UNZ_ERRNO; - else - return UNZ_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unz64local_getShort OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unz64local_getLong OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX) -{ - uLong x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unz64local_getLong64 OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX)); - - -local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream, - ZPOS64_T *pX) -{ - ZPOS64_T x ; - int i = 0; - int err; - - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (ZPOS64_T)i; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<8; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<16; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<24; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<32; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<40; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<48; - - if (err==UNZ_OK) - err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); - x |= ((ZPOS64_T)i)<<56; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -/* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) -{ - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= 0x20; - if ((c2>='a') && (c2<='z')) - c2 -= 0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1c2) - return 1; - } -} - - -#ifdef CASESENSITIVITYDEFAULT_NO -#define CASESENSITIVITYDEFAULTVALUE 2 -#else -#define CASESENSITIVITYDEFAULTVALUE 1 -#endif - -#ifndef STRCMPCASENOSENTIVEFUNCTION -#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal -#endif - -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) - -*/ -extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, - const char* fileName2, - int iCaseSensitivity) - -{ - if (iCaseSensitivity==0) - iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; - - if (iCaseSensitivity==1) - return strcmp(fileName1,fileName2); - - return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); -} - -#ifndef BUFREADCOMMENT -#define BUFREADCOMMENT (0x400) -#endif - -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); -local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - - -/* - Locate the Central directory 64 of a zipfile (at the end, just before - the global comment) -*/ -local ZPOS64_T unz64local_SearchCentralDir64 OF(( - const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream)); - -local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, - voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - uLong uL; - ZPOS64_T relativeOffset; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - if (uPosFound == 0) - return 0; - - /* Zip64 end of central directory locator */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature, already checked */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - - /* number of the disk with the start of the zip64 end of central directory */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - if (uL != 0) - return 0; - - /* relative offset of the zip64 end of central directory record */ - if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) - return 0; - - /* total number of disks */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - if (uL != 1) - return 0; - - /* Goto end of central directory record */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature */ - if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) - return 0; - - if (uL != 0x06064b50) - return 0; - - return relativeOffset; -} - -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer - "zlib/zlib114.zip". - If the zipfile cannot be opened (file doesn't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ -local unzFile unzOpenInternal (const void *path, - zlib_filefunc64_32_def* pzlib_filefunc64_32_def, - int is64bitOpenFunction) -{ - unz64_s us; - unz64_s *s; - ZPOS64_T central_pos; - uLong uL; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - ZPOS64_T number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - - int err=UNZ_OK; - - if (unz_copyright[0]!=' ') - return NULL; - - us.z_filefunc.zseek32_file = NULL; - us.z_filefunc.ztell32_file = NULL; - if (pzlib_filefunc64_32_def==NULL) - fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); - else - us.z_filefunc = *pzlib_filefunc64_32_def; - us.is64bitOpenFunction = is64bitOpenFunction; - - - - us.filestream = ZOPEN64(us.z_filefunc, - path, - ZLIB_FILEFUNC_MODE_READ | - ZLIB_FILEFUNC_MODE_EXISTING); - if (us.filestream==NULL) - return NULL; - - central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); - if (central_pos) - { - uLong uS; - ZPOS64_T uL64; - - us.isZip64 = 1; - - if (ZSEEK64(us.z_filefunc, us.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* size of zip64 end of central directory record */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) - err=UNZ_ERRNO; - - /* version made by */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) - err=UNZ_ERRNO; - - /* version needed to extract */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central directory on this disk */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central directory */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - us.gi.size_comment = 0; - } - else - { - central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); - if (central_pos==0) - err=UNZ_ERRNO; - - us.isZip64 = 0; - - if (ZSEEK64(us.z_filefunc, us.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - us.gi.number_entry = uL; - - /* total number of entries in the central dir */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - number_entry_CD = uL; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - us.size_central_dir = uL; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - us.offset_central_dir = uL; - - /* zipfile comment length */ - if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) - err=UNZ_ERRNO; - } - - if ((central_pospfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - ZCLOSE64(s->z_filefunc, s->filestream); - TRYFREE(s); - return UNZ_OK; -} - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) -{ - unz64_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; -} - -extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) -{ - unz64_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - /* to do : check if number_entry is not truncated */ - pglobal_info32->number_entry = (uLong)s->gi.number_entry; - pglobal_info32->size_comment = s->gi.size_comment; - return UNZ_OK; -} -/* - Translate date/time from Dos format to tm_unz (readable more easilty) -*/ -local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) -{ - ZPOS64_T uDate; - uDate = (ZPOS64_T)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; - - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; -} - -/* - Get Info about the current file in the zipfile, with internal only info -*/ -local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, - unz_file_info64 *pfile_info, - unz_file_info64_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -local int unz64local_GetCurrentFileInfoInternal (unzFile file, - unz_file_info64 *pfile_info, - unz_file_info64_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize) -{ - unz64_s* s; - unz_file_info64 file_info; - unz_file_info64_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; - uLong uL; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (ZSEEK64(s->z_filefunc, s->filestream, - s->pos_in_central_dir+s->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - - /* we check the magic */ - if (err==UNZ_OK) - { - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - } - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - file_info.compressed_size = uL; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - file_info.uncompressed_size = uL; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - // relative offset of local header - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - file_info_internal.offset_curfile = uL; - - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename0) && (fileNameBufferSize>0)) - if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - // Read extrafield - if ((err==UNZ_OK) && (extraField!=NULL)) - { - ZPOS64_T uSizeRead ; - if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - - lSeek += file_info.size_file_extra - (uLong)uSizeRead; - } - else - lSeek += file_info.size_file_extra; - - - if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) - { - uLong acc = 0; - - // since lSeek now points to after the extra field we need to move back - lSeek -= file_info.size_file_extra; - - if (lSeek!=0) - { - if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - - while(acc < file_info.size_file_extra) - { - uLong headerId; - uLong dataSize; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) - err=UNZ_ERRNO; - - /* ZIP64 extra fields */ - if (headerId == 0x0001) - { - uLong uL; - - if(file_info.uncompressed_size == (ZPOS64_T)(unsigned long)-1) - { - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - } - - if(file_info.compressed_size == (ZPOS64_T)(unsigned long)-1) - { - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - } - - if(file_info_internal.offset_curfile == (ZPOS64_T)(unsigned long)-1) - { - /* Relative Header offset */ - if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - } - - if(file_info.disk_num_start == (unsigned long)-1) - { - /* Disk Start Number */ - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) - err=UNZ_ERRNO; - } - - } - else - { - if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) - err=UNZ_ERRNO; - } - - acc += 2 + 2 + dataSize; - } - } - - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; - } - else - lSeek+=file_info.size_file_comment; - - - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; - - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; - - return err; -} - - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. -*/ -extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, - unz_file_info64 * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ - return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); -} - -extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, - unz_file_info * pfile_info, - char * szFileName, uLong fileNameBufferSize, - void *extraField, uLong extraFieldBufferSize, - char* szComment, uLong commentBufferSize) -{ - int err; - unz_file_info64 file_info64; - err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); - if (err==UNZ_OK) - { - pfile_info->version = file_info64.version; - pfile_info->version_needed = file_info64.version_needed; - pfile_info->flag = file_info64.flag; - pfile_info->compression_method = file_info64.compression_method; - pfile_info->dosDate = file_info64.dosDate; - pfile_info->crc = file_info64.crc; - - pfile_info->size_filename = file_info64.size_filename; - pfile_info->size_file_extra = file_info64.size_file_extra; - pfile_info->size_file_comment = file_info64.size_file_comment; - - pfile_info->disk_num_start = file_info64.disk_num_start; - pfile_info->internal_fa = file_info64.internal_fa; - pfile_info->external_fa = file_info64.external_fa; - - pfile_info->tmu_date = file_info64.tmu_date, - - - pfile_info->compressed_size = (uLong)file_info64.compressed_size; - pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; - - } - return err; -} -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ -extern int ZEXPORT unzGoToFirstFile (unzFile file) -{ - int err=UNZ_OK; - unz64_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ -extern int ZEXPORT unzGoToNextFile (unzFile file) -{ - unz64_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; - - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzipStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ -extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) -{ - unz64_s* s; - int err; - - /* We remember the 'current' position in the file so that we can jump - * back there if we fail. - */ - unz_file_info64 cur_file_infoSaved; - unz_file_info64_internal cur_file_info_internalSaved; - ZPOS64_T num_fileSaved; - ZPOS64_T pos_in_central_dirSaved; - - - if (file==NULL) - return UNZ_PARAMERROR; - - if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) - return UNZ_PARAMERROR; - - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - /* Save the current state */ - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - cur_file_infoSaved = s->cur_file_info; - cur_file_info_internalSaved = s->cur_file_info_internal; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - err = unzGetCurrentFileInfo64(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (err == UNZ_OK) - { - if (unzStringFileNameCompare(szCurrentFileName, - szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - } - - /* We failed, so restore the state of the 'current file' to where we - * were. - */ - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - s->cur_file_info = cur_file_infoSaved; - s->cur_file_info_internal = cur_file_info_internalSaved; - return err; -} - - -/* -/////////////////////////////////////////// -// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) -// I need random access -// -// Further optimization could be realized by adding an ability -// to cache the directory in memory. The goal being a single -// comprehensive file read to put the file I need in a memory. -*/ - -/* -typedef struct unz_file_pos_s -{ - ZPOS64_T pos_in_zip_directory; // offset in file - ZPOS64_T num_of_file; // # of file -} unz_file_pos; -*/ - -extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) -{ - unz64_s* s; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - file_pos->pos_in_zip_directory = s->pos_in_central_dir; - file_pos->num_of_file = s->num_file; - - return UNZ_OK; -} - -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos) -{ - unz64_file_pos file_pos64; - int err = unzGetFilePos64(file,&file_pos64); - if (err==UNZ_OK) - { - file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; - file_pos->num_of_file = (uLong)file_pos64.num_of_file; - } - return err; -} - -extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) -{ - unz64_s* s; - int err; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - - /* jump to the right spot */ - s->pos_in_central_dir = file_pos->pos_in_zip_directory; - s->num_file = file_pos->num_of_file; - - /* set the current file */ - err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - /* return results */ - s->current_file_ok = (err == UNZ_OK); - return err; -} - -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos) -{ - unz64_file_pos file_pos64; - if (file_pos == NULL) - return UNZ_PARAMERROR; - - file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; - file_pos64.num_of_file = file_pos->num_of_file; - return unzGoToFilePos64(file,&file_pos64); -} - -/* -// Unzip Helper Functions - should be here? -/////////////////////////////////////////// -*/ - -/* - Read the local header of the current zipfile - Check the coherency of the local header and info in the end of central - directory about this file - store in *piSizeVar the size of extra info in local header - (filename and size of extra field data) -*/ -local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, - ZPOS64_T * poffset_local_extrafield, - uInt * psize_local_extrafield) -{ - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; - - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; - - if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) - { - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - } - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; -/* - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) - err=UNZ_BADZIPFILE; -*/ - if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; - - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && -/* #ifdef HAVE_BZIP2 */ - (s->cur_file_info.compression_method!=Z_BZIP2ED) && -/* #endif */ - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ - err=UNZ_ERRNO; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ - err=UNZ_ERRNO; - else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ - err=UNZ_ERRNO; - else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; - - *piSizeVar += (uInt)size_filename; - - if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; - - *piSizeVar += (uInt)size_extra_field; - - return err; -} - -/* - Open for reading data the current file in the zipfile. - If there is no error and the file is opened, the return value is UNZ_OK. -*/ -extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, - int* level, int raw, const char* password) -{ - int err=UNZ_OK; - uInt iSizeVar; - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ - uInt size_local_extrafield; /* size of the local extra field */ -# ifndef NOUNCRYPT - char source[12]; -# else - if (password != NULL) - return UNZ_PARAMERROR; -# endif - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; - - if (s->pfile_in_zip_read != NULL) - unzCloseCurrentFile(file); - - if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; - - pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; - - pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; - pfile_in_zip_read_info->raw=raw; - - if (pfile_in_zip_read_info->read_buffer==NULL) - { - TRYFREE(pfile_in_zip_read_info); - return UNZ_INTERNALERROR; - } - - pfile_in_zip_read_info->stream_initialised=0; - - if (method!=NULL) - *method = (int)s->cur_file_info.compression_method; - - if (level!=NULL) - { - *level = 6; - switch (s->cur_file_info.flag & 0x06) - { - case 6 : *level = 1; break; - case 4 : *level = 2; break; - case 2 : *level = 9; break; - } - } - - if ((s->cur_file_info.compression_method!=0) && -/* #ifdef HAVE_BZIP2 */ - (s->cur_file_info.compression_method!=Z_BZIP2ED) && -/* #endif */ - (s->cur_file_info.compression_method!=Z_DEFLATED)) - - err=UNZ_BADZIPFILE; - - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->total_out_64=0; - pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; - pfile_in_zip_read_info->filestream=s->filestream; - pfile_in_zip_read_info->z_filefunc=s->z_filefunc; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) - { -#ifdef HAVE_BZIP2 - pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; - pfile_in_zip_read_info->bstream.bzfree = (free_func)0; - pfile_in_zip_read_info->bstream.opaque = (voidpf)0; - pfile_in_zip_read_info->bstream.state = (voidpf)0; - - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - pfile_in_zip_read_info->stream.next_in = (voidpf)0; - pfile_in_zip_read_info->stream.avail_in = 0; - - err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; - else - { - TRYFREE(pfile_in_zip_read_info); - return err; - } -#else - pfile_in_zip_read_info->raw=1; -#endif - } - else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - pfile_in_zip_read_info->stream.next_in = 0; - pfile_in_zip_read_info->stream.avail_in = 0; - - err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; - else - { - TRYFREE(pfile_in_zip_read_info); - return err; - } - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - } - pfile_in_zip_read_info->rest_read_compressed = - s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = - s->cur_file_info.uncompressed_size ; - - - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; - - pfile_in_zip_read_info->stream.avail_in = (uInt)0; - - s->pfile_in_zip_read = pfile_in_zip_read_info; - s->encrypted = 0; - -# ifndef NOUNCRYPT - if (password != NULL) - { - int i; - s->pcrc_32_tab = get_crc_table(); - init_keys(password,s->keys,s->pcrc_32_tab); - if (ZSEEK64(s->z_filefunc, s->filestream, - s->pfile_in_zip_read->pos_in_zipfile + - s->pfile_in_zip_read->byte_before_the_zipfile, - SEEK_SET)!=0) - return UNZ_INTERNALERROR; - if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) - return UNZ_INTERNALERROR; - - for (i = 0; i<12; i++) - zdecode(s->keys,s->pcrc_32_tab,source[i]); - - s->pfile_in_zip_read->pos_in_zipfile+=12; - s->encrypted=1; - } -# endif - - - return UNZ_OK; -} - -extern int ZEXPORT unzOpenCurrentFile (unzFile file) -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); -} - -extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, password); -} - -extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) -{ - return unzOpenCurrentFile3(file, method, level, raw, NULL); -} - -/** Addition for GDAL : START */ - -extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - s=(unz64_s*)file; - if (file==NULL) - return 0; //UNZ_PARAMERROR; - pfile_in_zip_read_info=s->pfile_in_zip_read; - if (pfile_in_zip_read_info==NULL) - return 0; //UNZ_PARAMERROR; - return pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile; -} - -/** Addition for GDAL : END */ - -/* - Read bytes from the current file. - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ -extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) -{ - int err=UNZ_OK; - uInt iRead = 0; - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if ((pfile_in_zip_read_info->read_buffer == NULL)) - return UNZ_END_OF_LIST_OF_FILE; - if (len==0) - return 0; - - pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; - - pfile_in_zip_read_info->stream.avail_out = (uInt)len; - - if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && - (!(pfile_in_zip_read_info->raw))) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - - if ((len>pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in) && - (pfile_in_zip_read_info->raw)) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in; - - while (pfile_in_zip_read_info->stream.avail_out>0) - { - if ((pfile_in_zip_read_info->stream.avail_in==0) && - (pfile_in_zip_read_info->rest_read_compressed>0)) - { - uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; - if (uReadThis == 0) - return UNZ_EOF; - if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - if (ZREAD64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->read_buffer, - uReadThis)!=uReadThis) - return UNZ_ERRNO; - - -# ifndef NOUNCRYPT - if(s->encrypted) - { - uInt i; - for(i=0;iread_buffer[i] = - zdecode(s->keys,s->pcrc_32_tab, - pfile_in_zip_read_info->read_buffer[i]); - } -# endif - - - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - - pfile_in_zip_read_info->stream.next_in = - (Bytef*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - } - - if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) - { - uInt uDoCopy,i ; - - if ((pfile_in_zip_read_info->stream.avail_in == 0) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - return (iRead==0) ? UNZ_EOF : iRead; - - if (pfile_in_zip_read_info->stream.avail_out < - pfile_in_zip_read_info->stream.avail_in) - uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - else - uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - - for (i=0;istream.next_out+i) = - *(pfile_in_zip_read_info->stream.next_in+i); - - pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, - pfile_in_zip_read_info->stream.next_out, - uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - } - else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) - { -#ifdef HAVE_BZIP2 - uLong uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - uLong uOutThis; - - pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; - pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; - pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; - pfile_in_zip_read_info->bstream.total_in_hi32 = 0; - pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; - pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; - pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; - pfile_in_zip_read_info->bstream.total_out_hi32 = 0; - - uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; - bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; - - err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); - - uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); - pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; - pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; - pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; - pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; - pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; - pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; - - if (err==BZ_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=BZ_OK) - break; -#endif - } // end Z_BZIP2ED - else - { - ZPOS64_T uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - ZPOS64_T uOutThis; - int flush=Z_SYNC_FLUSH; - - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - - /* - if ((pfile_in_zip_read_info->rest_read_uncompressed == - pfile_in_zip_read_info->stream.avail_out) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - flush = Z_FINISH; - */ - err=inflate(&pfile_in_zip_read_info->stream,flush); - - if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) - err = Z_DATA_ERROR; - - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; - - pfile_in_zip_read_info->crc32 = - crc32(pfile_in_zip_read_info->crc32,bufBefore, - (uInt)(uOutThis)); - - pfile_in_zip_read_info->rest_read_uncompressed -= - uOutThis; - - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - if (err==Z_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=Z_OK) - break; - } - } - - if (err==Z_OK) - return iRead; - return err; -} - - -/* - Give the current position in uncompressed data -*/ -extern z_off_t ZEXPORT unztell (unzFile file) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - return (z_off_t)pfile_in_zip_read_info->stream.total_out; -} - -extern ZPOS64_T ZEXPORT unztell64 (unzFile file) -{ - - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return (ZPOS64_T)-1; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return (ZPOS64_T)-1; - - return pfile_in_zip_read_info->total_out_64; -} - - -/* - return 1 if the end of file was reached, 0 elsewhere -*/ -extern int ZEXPORT unzeof (unzFile file) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; -} - - - -/* -Read extra field from the current file (opened by unzOpenCurrentFile) -This is the local-header version of the extra field (sometimes, there is -more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field that can be read - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ -extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) -{ - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - uInt read_now; - ZPOS64_T size_to_read; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); - - if (buf==NULL) - return (int)size_to_read; - - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; - - if (read_now==0) - return 0; - - if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (ZREAD64(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - buf,read_now)!=read_now) - return UNZ_ERRNO; - - return (int)read_now; -} - -/* - Close the file in zip opened with unzipOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ -extern int ZEXPORT unzCloseCurrentFile (unzFile file) -{ - int err=UNZ_OK; - - unz64_s* s; - file_in_zip64_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && - (!pfile_in_zip_read_info->raw)) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } - - - TRYFREE(pfile_in_zip_read_info->read_buffer); - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) - inflateEnd(&pfile_in_zip_read_info->stream); -#ifdef HAVE_BZIP2 - else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) - BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); -#endif - - - pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); - - s->pfile_in_zip_read=NULL; - - return err; -} - - -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ -extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) -{ - unz64_s* s; - uLong uReadThis ; - if (file==NULL) - return (int)UNZ_PARAMERROR; - s=(unz64_s*)file; - - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) - uReadThis = s->gi.size_comment; - - if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (uReadThis>0) - { - *szComment='\0'; - if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) - return UNZ_ERRNO; - } - - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) - *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} - -/* Additions by RX '2004 */ -extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) -{ - unz64_s* s; - - if (file==NULL) - return 0; //UNZ_PARAMERROR; - s=(unz64_s*)file; - if (!s->current_file_ok) - return 0; - if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) - if (s->num_file==s->gi.number_entry) - return 0; - return s->pos_in_central_dir; -} - -extern uLong ZEXPORT unzGetOffset (unzFile file) -{ - ZPOS64_T offset64; - - if (file==NULL) - return 0; //UNZ_PARAMERROR; - offset64 = unzGetOffset64(file); - return (uLong)offset64; -} - -extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) -{ - unz64_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz64_s*)file; - - s->pos_in_central_dir = pos; - s->num_file = s->gi.number_entry; /* hack */ - err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) -{ - return unzSetOffset64(file,pos); -} diff --git a/thirdparty/minizip/zip.c b/thirdparty/minizip/zip.c deleted file mode 100644 index f42f24ca3..000000000 --- a/thirdparty/minizip/zip.c +++ /dev/null @@ -1,2004 +0,0 @@ -/* zip.c -- IO on .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) - - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) - - Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) - - For more info read MiniZip_info.txt - - Changes - Oct-2009 - Mathias Svensson - Remove old C style function prototypes - Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives - Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. - Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data - It is used when recreting zip archive with RAW when deleting items from a zip. - ZIP64 data is automaticly added to items that needs it, and existing ZIP64 data need to be removed. - Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) - Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer - -*/ - - -#include -#include -#include -#include -#include "zlib.h" -#include "minizip/zip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -#ifndef VERSIONMADEBY -# define VERSIONMADEBY (0x0) /* platform depedent */ -#endif - -#ifndef Z_BUFSIZE -#define Z_BUFSIZE (64*1024) //(16384) -#endif - -#ifndef Z_MAXFILENAMEINZIP -#define Z_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -/* -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) -*/ - -/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ - - -// NOT sure that this work on ALL platform -#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -#ifndef DEF_MEM_LEVEL -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -#endif -const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; - - -#define SIZEDATA_INDATABLOCK (4096-(4*4)) - -#define LOCALHEADERMAGIC (0x04034b50) -#define CENTRALHEADERMAGIC (0x02014b50) -#define ENDHEADERMAGIC (0x06054b50) -#define ZIP64ENDHEADERMAGIC (0x6064b50) -#define ZIP64ENDLOCHEADERMAGIC (0x7064b50) - -#define FLAG_LOCALHEADER_OFFSET (0x06) -#define CRC_LOCALHEADER_OFFSET (0x0e) - -#define SIZECENTRALHEADER (0x2e) /* 46 */ - -typedef struct linkedlist_datablock_internal_s -{ - struct linkedlist_datablock_internal_s* next_datablock; - uLong avail_in_this_block; - uLong filled_in_this_block; - uLong unused; /* for future use and alignement */ - unsigned char data[SIZEDATA_INDATABLOCK]; -} linkedlist_datablock_internal; - -typedef struct linkedlist_data_s -{ - linkedlist_datablock_internal* first_block; - linkedlist_datablock_internal* last_block; -} linkedlist_data; - - -typedef struct -{ - z_stream stream; /* zLib stream structure for inflate */ -#ifdef HAVE_BZIP2 - bz_stream bstream; /* bzLib stream structure for bziped */ -#endif - - int stream_initialised; /* 1 is stream is initialised */ - uInt pos_in_buffered_data; /* last written byte in buffered_data */ - - ZPOS64_T pos_local_header; /* offset of the local header of the file - currenty writing */ - char* central_header; /* central header data for the current file */ - uLong size_centralExtra; - uLong size_centralheader; /* size of the central header for cur file */ - uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ - uLong flag; /* flag of the file currently writing */ - - int method; /* compression method of file currenty wr.*/ - int raw; /* 1 for directly writing raw data */ - Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ - uLong dosDate; - uLong crc32; - int encrypt; - int zip64; /* Add ZIP64 extened information in the extra field */ - ZPOS64_T pos_zip64extrainfo; - ZPOS64_T totalCompressedData; - ZPOS64_T totalUncompressedData; -#ifndef NOCRYPT - unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const unsigned long* pcrc_32_tab; - int crypt_header_size; -#endif -} curfile64_info; - -typedef struct -{ - zlib_filefunc64_32_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - linkedlist_data central_dir;/* datablock with central dir in construction*/ - int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ - curfile64_info ci; /* info on the file curretly writing */ - - ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ - ZPOS64_T add_position_when_writting_offset; - ZPOS64_T number_entry; - -#ifndef NO_ADDFILEINEXISTINGZIP - char *globalcomment; -#endif - -} zip64_internal; - - -#ifndef NOCRYPT -#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED -#include "minizip/zipcrypt.h" -#endif - -local linkedlist_datablock_internal* allocate_new_datablock() -{ - linkedlist_datablock_internal* ldi; - ldi = (linkedlist_datablock_internal*) - ALLOC(sizeof(linkedlist_datablock_internal)); - if (ldi!=NULL) - { - ldi->next_datablock = NULL ; - ldi->filled_in_this_block = 0 ; - ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; - } - return ldi; -} - -local void free_datablock(linkedlist_datablock_internal* ldi) -{ - while (ldi!=NULL) - { - linkedlist_datablock_internal* ldinext = ldi->next_datablock; - TRYFREE(ldi); - ldi = ldinext; - } -} - -local void init_linkedlist(linkedlist_data* ll) -{ - ll->first_block = ll->last_block = NULL; -} - -local void free_linkedlist(linkedlist_data* ll) -{ - free_datablock(ll->first_block); - ll->first_block = ll->last_block = NULL; -} - - -local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) -{ - linkedlist_datablock_internal* ldi; - const unsigned char* from_copy; - - if (ll==NULL) - return ZIP_INTERNALERROR; - - if (ll->last_block == NULL) - { - ll->first_block = ll->last_block = allocate_new_datablock(); - if (ll->first_block == NULL) - return ZIP_INTERNALERROR; - } - - ldi = ll->last_block; - from_copy = (unsigned char*)buf; - - while (len>0) - { - uInt copy_this; - uInt i; - unsigned char* to_copy; - - if (ldi->avail_in_this_block==0) - { - ldi->next_datablock = allocate_new_datablock(); - if (ldi->next_datablock == NULL) - return ZIP_INTERNALERROR; - ldi = ldi->next_datablock ; - ll->last_block = ldi; - } - - if (ldi->avail_in_this_block < len) - copy_this = (uInt)ldi->avail_in_this_block; - else - copy_this = (uInt)len; - - to_copy = &(ldi->data[ldi->filled_in_this_block]); - - for (i=0;ifilled_in_this_block += copy_this; - ldi->avail_in_this_block -= copy_this; - from_copy += copy_this ; - len -= copy_this; - } - return ZIP_OK; -} - - - -/****************************************************************************/ - -#ifndef NO_ADDFILEINEXISTINGZIP -/* =========================================================================== - Inputs a long in LSB order to the given file - nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) -*/ - -local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); -local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) -{ - unsigned char buf[8]; - int n; - for (n = 0; n < nbByte; n++) - { - buf[n] = (unsigned char)(x & 0xff); - x >>= 8; - } - if (x != 0) - { /* data overflow - hack for ZIP64 (X Roche) */ - for (n = 0; n < nbByte; n++) - { - buf[n] = 0xff; - } - } - - if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) - return ZIP_ERRNO; - else - return ZIP_OK; -} - -local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); -local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) -{ - unsigned char* buf=(unsigned char*)dest; - int n; - for (n = 0; n < nbByte; n++) { - buf[n] = (unsigned char)(x & 0xff); - x >>= 8; - } - - if (x != 0) - { /* data overflow - hack for ZIP64 */ - for (n = 0; n < nbByte; n++) - { - buf[n] = 0xff; - } - } -} - -/****************************************************************************/ - - -local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) -{ - uLong year = (uLong)ptm->tm_year; - if (year>=1980) - year-=1980; - else if (year>=80) - year-=80; - return - (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | - ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); -} - - -/****************************************************************************/ - -local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); - -local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) -{ - unsigned char c; - int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return ZIP_OK; - } - else - { - if (ZERROR64(*pzlib_filefunc_def,filestream)) - return ZIP_ERRNO; - else - return ZIP_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ - uLong x ; - int i = 0; - int err; - - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==ZIP_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); - -local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) -{ - uLong x ; - int i = 0; - int err; - - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<16; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<24; - - if (err==ZIP_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); - - -local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) -{ - ZPOS64_T x; - int i = 0; - int err; - - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x = (ZPOS64_T)i; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<8; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<16; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<24; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<32; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<40; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<48; - - if (err==ZIP_OK) - err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); - x += ((ZPOS64_T)i)<<56; - - if (err==ZIP_OK) - *pX = x; - else - *pX = 0; - - return err; -} - -#ifndef BUFREADCOMMENT -#define BUFREADCOMMENT (0x400) -#endif -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - -/* -Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before -the global comment) -*/ -local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); - -local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) -{ - unsigned char* buf; - ZPOS64_T uSizeFile; - ZPOS64_T uBackRead; - ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ - ZPOS64_T uPosFound=0; - uLong uL; - ZPOS64_T relativeOffset; - - if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); - if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - { - // Signature "0x07064b50" Zip64 end of central directory locater - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) - { - uPosFound = uReadPos+i; - break; - } - } - - if (uPosFound!=0) - break; - } - - TRYFREE(buf); - if (uPosFound == 0) - return 0; - - /* Zip64 end of central directory locator */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature, already checked */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - - /* number of the disk with the start of the zip64 end of central directory */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - if (uL != 0) - return 0; - - /* relative offset of the zip64 end of central directory record */ - if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) - return 0; - - /* total number of disks */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - if (uL != 1) - return 0; - - /* Goto Zip64 end of central directory record */ - if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) - return 0; - - /* the signature */ - if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) - return 0; - - if (uL != 0x06064b50) // signature of 'Zip64 end of central directory' - return 0; - - return relativeOffset; -} - -int LoadCentralDirectoryRecord(zip64_internal* pziinit) -{ - int err=ZIP_OK; - ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - - ZPOS64_T size_central_dir; /* size of the central directory */ - ZPOS64_T offset_central_dir; /* offset of start of central directory */ - ZPOS64_T central_pos; - uLong uL; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - ZPOS64_T number_entry; - ZPOS64_T number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - uLong VersionMadeBy; - uLong VersionNeeded; - uLong size_comment; - - int hasZIP64Record = 0; - - // check first if we find a ZIP64 record - central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); - if(central_pos > 0) - { - hasZIP64Record = 1; - } - else if(central_pos == 0) - { - central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream); - } - -/* disable to allow appending to empty ZIP archive - if (central_pos==0) - err=ZIP_ERRNO; -*/ - - if(hasZIP64Record) - { - ZPOS64_T sizeEndOfCentralDirectory; - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) - err=ZIP_ERRNO; - - /* the signature, already checked */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) - err=ZIP_ERRNO; - - /* size of zip64 end of central directory record */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK) - err=ZIP_ERRNO; - - /* version made by */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK) - err=ZIP_ERRNO; - - /* version needed to extract */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of this disk */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of the disk with the start of the central directory */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) - err=ZIP_ERRNO; - - /* total number of entries in the central directory on this disk */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK) - err=ZIP_ERRNO; - - /* total number of entries in the central directory */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK) - err=ZIP_ERRNO; - - if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) - err=ZIP_BADZIPFILE; - - /* size of the central directory */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK) - err=ZIP_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) - err=ZIP_ERRNO; - - // TODO.. - // read the comment from the standard central header. - size_comment = 0; - } - else - { - // Read End of central Directory info - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=ZIP_ERRNO; - - /* the signature, already checked */ - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of this disk */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) - err=ZIP_ERRNO; - - /* number of the disk with the start of the central directory */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) - err=ZIP_ERRNO; - - /* total number of entries in the central dir on this disk */ - number_entry = 0; - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - number_entry = uL; - - /* total number of entries in the central dir */ - number_entry_CD = 0; - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - number_entry_CD = uL; - - if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) - err=ZIP_BADZIPFILE; - - /* size of the central directory */ - size_central_dir = 0; - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - size_central_dir = uL; - - /* offset of start of central directory with respect to the starting disk number */ - offset_central_dir = 0; - if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) - err=ZIP_ERRNO; - else - offset_central_dir = uL; - - - /* zipfile global comment length */ - if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK) - err=ZIP_ERRNO; - } - - if ((central_posz_filefunc, pziinit->filestream); - return ZIP_ERRNO; - } - - if (size_comment>0) - { - pziinit->globalcomment = (char*)ALLOC(size_comment+1); - if (pziinit->globalcomment) - { - size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment); - pziinit->globalcomment[size_comment]=0; - } - } - - byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); - pziinit->add_position_when_writting_offset = byte_before_the_zipfile; - - { - ZPOS64_T size_central_dir_to_read = size_central_dir; - size_t buf_size = SIZEDATA_INDATABLOCK; - void* buf_read = (void*)ALLOC(buf_size); - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) - err=ZIP_ERRNO; - - while ((size_central_dir_to_read>0) && (err==ZIP_OK)) - { - ZPOS64_T read_this = SIZEDATA_INDATABLOCK; - if (read_this > size_central_dir_to_read) - read_this = size_central_dir_to_read; - - if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this) - err=ZIP_ERRNO; - - if (err==ZIP_OK) - err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); - - size_central_dir_to_read-=read_this; - } - TRYFREE(buf_read); - } - pziinit->begin_pos = byte_before_the_zipfile; - pziinit->number_entry = number_entry_CD; - - if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) - err=ZIP_ERRNO; - - return err; -} - - -#endif /* !NO_ADDFILEINEXISTINGZIP*/ - - -/************************************************************/ -extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) -{ - zip64_internal ziinit; - zip64_internal* zi; - int err=ZIP_OK; - - ziinit.z_filefunc.zseek32_file = NULL; - ziinit.z_filefunc.ztell32_file = NULL; - if (pzlib_filefunc64_32_def==NULL) - fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); - else - ziinit.z_filefunc = *pzlib_filefunc64_32_def; - - ziinit.filestream = ZOPEN64(ziinit.z_filefunc, - pathname, - (append == APPEND_STATUS_CREATE) ? - (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : - (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); - - if (ziinit.filestream == NULL) - return NULL; - - if (append == APPEND_STATUS_CREATEAFTER) - ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); - - ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream); - ziinit.in_opened_file_inzip = 0; - ziinit.ci.stream_initialised = 0; - ziinit.number_entry = 0; - ziinit.add_position_when_writting_offset = 0; - init_linkedlist(&(ziinit.central_dir)); - - - - zi = (zip64_internal*)ALLOC(sizeof(zip64_internal)); - if (zi==NULL) - { - ZCLOSE64(ziinit.z_filefunc,ziinit.filestream); - return NULL; - } - - /* now we add file in a zipfile */ -# ifndef NO_ADDFILEINEXISTINGZIP - ziinit.globalcomment = NULL; - if (append == APPEND_STATUS_ADDINZIP) - { - // Read and Cache Central Directory Records - err = LoadCentralDirectoryRecord(&ziinit); - } - - if (globalcomment) - { - *globalcomment = ziinit.globalcomment; - } -# endif /* !NO_ADDFILEINEXISTINGZIP*/ - - if (err != ZIP_OK) - { -# ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(ziinit.globalcomment); -# endif /* !NO_ADDFILEINEXISTINGZIP*/ - TRYFREE(zi); - return NULL; - } - else - { - *zi = ziinit; - return (zipFile)zi; - } -} - -extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) -{ - if (pzlib_filefunc32_def != NULL) - { - zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; - fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); - return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); - } - else - return zipOpen3(pathname, append, globalcomment, NULL); -} - -extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) -{ - if (pzlib_filefunc_def != NULL) - { - zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; - zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; - zlib_filefunc64_32_def_fill.ztell32_file = NULL; - zlib_filefunc64_32_def_fill.zseek32_file = NULL; - return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); - } - else - return zipOpen3(pathname, append, globalcomment, NULL); -} - - - -extern zipFile ZEXPORT zipOpen (const char* pathname, int append) -{ - return zipOpen3((const void*)pathname,append,NULL,NULL); -} - -extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) -{ - return zipOpen3(pathname,append,NULL,NULL); -} - -int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) -{ - /* write the local header */ - int err; - uInt size_filename = (uInt)strlen(filename); - uInt size_extrafield = size_extrafield_local; - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4); - - if (err==ZIP_OK) - { - if(zi->ci.zip64) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ - } - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); - - // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ - if (err==ZIP_OK) - { - if(zi->ci.zip64) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ - } - if (err==ZIP_OK) - { - if(zi->ci.zip64) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ - } - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); - - if(zi->ci.zip64) - { - size_extrafield += 20; - } - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2); - - if ((err==ZIP_OK) && (size_filename > 0)) - { - if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) - err = ZIP_ERRNO; - } - - if ((err==ZIP_OK) && (size_extrafield_local > 0)) - { - if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) - err = ZIP_ERRNO; - } - - - if ((err==ZIP_OK) && (zi->ci.zip64)) - { - // write the Zip64 extended info - short HeaderID = 1; - short DataSize = 16; - ZPOS64_T CompressedSize = 0; - ZPOS64_T UncompressedSize = 0; - - // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) - zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); - - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); - - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); - } - - return err; -} - -/* - NOTE. - When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped - before calling this function it can be done with zipRemoveExtraInfoBlock - - It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize - unnecessary allocations. - */ -extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, - uLong versionMadeBy, uLong flagBase, int zip64) -{ - zip64_internal* zi; - uInt size_filename; - uInt size_comment; - uInt i; - int err = ZIP_OK; - -# ifdef NOCRYPT - if (password != NULL) - return ZIP_PARAMERROR; -# endif - - if (file == NULL) - return ZIP_PARAMERROR; - -#ifdef HAVE_BZIP2 - if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) - return ZIP_PARAMERROR; -#else - if ((method!=0) && (method!=Z_DEFLATED)) - return ZIP_PARAMERROR; -#endif - - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 1) - { - err = zipCloseFileInZip (file); - if (err != ZIP_OK) - return err; - } - - if (filename==NULL) - filename="-"; - - if (comment==NULL) - size_comment = 0; - else - size_comment = (uInt)strlen(comment); - - size_filename = (uInt)strlen(filename); - - if (zipfi == NULL) - zi->ci.dosDate = 0; - else - { - if (zipfi->dosDate != 0) - zi->ci.dosDate = zipfi->dosDate; - else - zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); - } - - zi->ci.flag = flagBase; - if ((level==8) || (level==9)) - zi->ci.flag |= 2; - if ((level==2)) - zi->ci.flag |= 4; - if ((level==1)) - zi->ci.flag |= 6; - if (password != NULL) - zi->ci.flag |= 1; - - zi->ci.crc32 = 0; - zi->ci.method = method; - zi->ci.encrypt = 0; - zi->ci.stream_initialised = 0; - zi->ci.pos_in_buffered_data = 0; - zi->ci.raw = raw; - zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); - - zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; - zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data - - zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); - - zi->ci.size_centralExtra = size_extrafield_global; - zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); - /* version info */ - zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); - zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); - zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); - zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); - zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); - zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ - zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ - zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ - zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); - zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); - zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); - zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ - - if (zipfi==NULL) - zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); - else - zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); - - if (zipfi==NULL) - zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); - else - zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); - - if(zi->ci.pos_local_header >= 0xffffffff) - zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); - else - zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset,4); - - for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); - - for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = - *(((const char*)extrafield_global)+i); - - for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ - size_extrafield_global+i) = *(comment+i); - if (zi->ci.central_header == NULL) - return ZIP_INTERNALERROR; - - zi->ci.zip64 = zip64; - zi->ci.totalCompressedData = 0; - zi->ci.totalUncompressedData = 0; - zi->ci.pos_zip64extrainfo = 0; - - err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local); - -#ifdef HAVE_BZIP2 - zi->ci.bstream.avail_in = (uInt)0; - zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; - zi->ci.bstream.total_in_hi32 = 0; - zi->ci.bstream.total_in_lo32 = 0; - zi->ci.bstream.total_out_hi32 = 0; - zi->ci.bstream.total_out_lo32 = 0; -#endif - - zi->ci.stream.avail_in = (uInt)0; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - zi->ci.stream.total_in = 0; - zi->ci.stream.total_out = 0; - zi->ci.stream.data_type = Z_BINARY; - -#ifdef HAVE_BZIP2 - if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) -#else - if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) -#endif - { - if(zi->ci.method == Z_DEFLATED) - { - zi->ci.stream.zalloc = (alloc_func)0; - zi->ci.stream.zfree = (free_func)0; - zi->ci.stream.opaque = (voidpf)0; - - if (windowBits>0) - windowBits = -windowBits; - - err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); - - if (err==Z_OK) - zi->ci.stream_initialised = Z_DEFLATED; - } - else if(zi->ci.method == Z_BZIP2ED) - { -#ifdef HAVE_BZIP2 - // Init BZip stuff here - zi->ci.bstream.bzalloc = 0; - zi->ci.bstream.bzfree = 0; - zi->ci.bstream.opaque = (voidpf)0; - - err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35); - if(err == BZ_OK) - zi->ci.stream_initialised = Z_BZIP2ED; -#endif - } - - } - -# ifndef NOCRYPT - zi->ci.crypt_header_size = 0; - if ((err==Z_OK) && (password != NULL)) - { - unsigned char bufHead[RAND_HEAD_LEN]; - unsigned int sizeHead; - zi->ci.encrypt = 1; - zi->ci.pcrc_32_tab = get_crc_table(); - /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ - - sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); - zi->ci.crypt_header_size = sizeHead; - - if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) - err = ZIP_ERRNO; - } -# endif - - if (err==Z_OK) - zi->in_opened_file_inzip = 1; - return err; -} - -extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, - uLong versionMadeBy, uLong flagBase) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, versionMadeBy, flagBase, 0); -} - -extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, 0); -} - -extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, - int windowBits,int memLevel, int strategy, - const char* password, uLong crcForCrypting, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - windowBits, memLevel, strategy, - password, crcForCrypting, VERSIONMADEBY, 0, zip64); -} - -extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); -} - -extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void* extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int raw, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, raw, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); -} - -extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level, int zip64) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, zip64); -} - -extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, - const void* extrafield_local, uInt size_extrafield_local, - const void*extrafield_global, uInt size_extrafield_global, - const char* comment, int method, int level) -{ - return zipOpenNewFileInZip4_64 (file, filename, zipfi, - extrafield_local, size_extrafield_local, - extrafield_global, size_extrafield_global, - comment, method, level, 0, - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - NULL, 0, VERSIONMADEBY, 0, 0); -} - -local int zip64FlushWriteBuffer(zip64_internal* zi) -{ - int err=ZIP_OK; - - if (zi->ci.encrypt != 0) - { -#ifndef NOCRYPT - uInt i; - int t; - for (i=0;ici.pos_in_buffered_data;i++) - zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t); -#endif - } - - if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data) - err = ZIP_ERRNO; - - zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data; - -#ifdef HAVE_BZIP2 - if(zi->ci.method == Z_BZIP2ED) - { - zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32; - zi->ci.bstream.total_in_lo32 = 0; - zi->ci.bstream.total_in_hi32 = 0; - } - else -#endif - { - zi->ci.totalUncompressedData += zi->ci.stream.total_in; - zi->ci.stream.total_in = 0; - } - - - zi->ci.pos_in_buffered_data = 0; - - return err; -} - -extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) -{ - zip64_internal* zi; - int err=ZIP_OK; - - if (file == NULL) - return ZIP_PARAMERROR; - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 0) - return ZIP_PARAMERROR; - - zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len); - -#ifdef HAVE_BZIP2 - if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw)) - { - zi->ci.bstream.next_in = (void*)buf; - zi->ci.bstream.avail_in = len; - err = BZ_RUN_OK; - - while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0)) - { - if (zi->ci.bstream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; - } - - - if(err != BZ_RUN_OK) - break; - - if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) - { - uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; -// uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; - err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN); - - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ; - } - } - - if(err == BZ_RUN_OK) - err = ZIP_OK; - } - else -#endif - { - zi->ci.stream.next_in = (Bytef*)buf; - zi->ci.stream.avail_in = len; - - while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) - { - if (zi->ci.stream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - } - - - if(err != ZIP_OK) - break; - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - uLong uTotalOutBefore = zi->ci.stream.total_out; - err=deflate(&zi->ci.stream, Z_NO_FLUSH); - if(uTotalOutBefore > zi->ci.stream.total_out) - { - int bBreak = 0; - bBreak++; - } - - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; - } - else - { - uInt copy_this,i; - if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) - copy_this = zi->ci.stream.avail_in; - else - copy_this = zi->ci.stream.avail_out; - - for (i = 0; i < copy_this; i++) - *(((char*)zi->ci.stream.next_out)+i) = - *(((const char*)zi->ci.stream.next_in)+i); - { - zi->ci.stream.avail_in -= copy_this; - zi->ci.stream.avail_out-= copy_this; - zi->ci.stream.next_in+= copy_this; - zi->ci.stream.next_out+= copy_this; - zi->ci.stream.total_in+= copy_this; - zi->ci.stream.total_out+= copy_this; - zi->ci.pos_in_buffered_data += copy_this; - } - } - }// while(...) - } - - return err; -} - -extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) -{ - return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); -} - -extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) -{ - zip64_internal* zi; - ZPOS64_T compressed_size; - uLong invalidValue = 0xffffffff; - short datasize = 0; - int err=ZIP_OK; - - if (file == NULL) - return ZIP_PARAMERROR; - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 0) - return ZIP_PARAMERROR; - zi->ci.stream.avail_in = 0; - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - while (err==ZIP_OK) - { - uLong uTotalOutBefore; - if (zi->ci.stream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.stream.next_out = zi->ci.buffered_data; - } - uTotalOutBefore = zi->ci.stream.total_out; - err=deflate(&zi->ci.stream, Z_FINISH); - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; - } - } - else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) - { -#ifdef HAVE_BZIP2 - err = BZ_FINISH_OK; - while (err==BZ_FINISH_OK) - { - uLong uTotalOutBefore; - if (zi->ci.bstream.avail_out == 0) - { - if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) - err = ZIP_ERRNO; - zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; - zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; - } - uTotalOutBefore = zi->ci.bstream.total_out_lo32; - err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH); - if(err == BZ_STREAM_END) - err = Z_STREAM_END; - - zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore); - } - - if(err == BZ_FINISH_OK) - err = ZIP_OK; -#endif - } - - if (err==Z_STREAM_END) - err=ZIP_OK; /* this is normal */ - - if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) - { - if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO) - err = ZIP_ERRNO; - } - - if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) - { - int tmp_err = deflateEnd(&zi->ci.stream); - if (err == ZIP_OK) - err = tmp_err; - zi->ci.stream_initialised = 0; - } -#ifdef HAVE_BZIP2 - else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) - { - int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream); - if (err==ZIP_OK) - err = tmperr; - zi->ci.stream_initialised = 0; - } -#endif - - if (!zi->ci.raw) - { - crc32 = (uLong)zi->ci.crc32; - uncompressed_size = zi->ci.totalUncompressedData; - } - compressed_size = zi->ci.totalCompressedData; - -# ifndef NOCRYPT - compressed_size += zi->ci.crypt_header_size; -# endif - - // update Current Item crc and sizes, - if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) - { - /*version Made by*/ - zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2); - /*version needed*/ - zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2); - - } - - zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ - - - if(compressed_size >= 0xffffffff) - zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/ - else - zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ - - /// set internal file attributes field - if (zi->ci.stream.data_type == Z_ASCII) - zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); - - if(uncompressed_size >= 0xffffffff) - zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/ - else - zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ - - // Add ZIP64 extra info field for uncompressed size - if(uncompressed_size >= 0xffffffff) - datasize += 8; - - // Add ZIP64 extra info field for compressed size - if(compressed_size >= 0xffffffff) - datasize += 8; - - // Add ZIP64 extra info field for relative offset to local file header of current file - if(zi->ci.pos_local_header >= 0xffffffff) - datasize += 8; - - if(datasize > 0) - { - char* p = NULL; - - if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) - { - // we can not write more data to the buffer that we have room for. - return ZIP_BADZIPFILE; - } - - p = zi->ci.central_header + zi->ci.size_centralheader; - - // Add Extra Information Header for 'ZIP64 information' - zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID - p += 2; - zip64local_putValue_inmemory(p, datasize, 2); // DataSize - p += 2; - - if(uncompressed_size >= 0xffffffff) - { - zip64local_putValue_inmemory(p, uncompressed_size, 8); - p += 8; - } - - if(compressed_size >= 0xffffffff) - { - zip64local_putValue_inmemory(p, compressed_size, 8); - p += 8; - } - - if(zi->ci.pos_local_header >= 0xffffffff) - { - zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8); - p += 8; - } - - // Update how much extra free space we got in the memory buffer - // and increase the centralheader size so the new ZIP64 fields are included - // ( 4 below is the size of HeaderID and DataSize field ) - zi->ci.size_centralExtraFree -= datasize + 4; - zi->ci.size_centralheader += datasize + 4; - - // Update the extra info size field - zi->ci.size_centralExtra += datasize + 4; - zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2); - } - - if (err==ZIP_OK) - err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader); - - free(zi->ci.central_header); - - if (err==ZIP_OK) - { - // Update the LocalFileHeader with the new values. - - ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); - - if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) - err = ZIP_ERRNO; - - if (err==ZIP_OK) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ - - if(uncompressed_size >= 0xffffffff) - { - if(zi->ci.pos_zip64extrainfo > 0) - { - // Update the size in the ZIP64 extended field. - if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0) - err = ZIP_ERRNO; - - if (err==ZIP_OK) /* compressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8); - - if (err==ZIP_OK) /* uncompressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); - } - } - else - { - if (err==ZIP_OK) /* compressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); - - if (err==ZIP_OK) /* uncompressed size, unknown */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); - } - - if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) - err = ZIP_ERRNO; - } - - zi->number_entry ++; - zi->in_opened_file_inzip = 0; - - return err; -} - -extern int ZEXPORT zipCloseFileInZip (zipFile file) -{ - return zipCloseFileInZipRaw (file,0,0); -} - -int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) -{ - int err = ZIP_OK; - ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset; - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); - - /*num disks*/ - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); - - /*relative offset*/ - if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8); - - /*total disks*/ /* Do not support spawning of disk so always say 1 here*/ - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4); - - return err; -} - -int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ - int err = ZIP_OK; - - uLong Zip64DataSize = 44; - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); - - if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ? - - if (err==ZIP_OK) /* version made by */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); - - if (err==ZIP_OK) /* version needed */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); - - if (err==ZIP_OK) /* number of this disk */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); - - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); - - if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); - - if (err==ZIP_OK) /* total number of entries in the central dir */ - err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); - - if (err==ZIP_OK) /* size of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8); - - if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ - { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); - } - return err; -} -int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) -{ - int err = ZIP_OK; - - /*signature*/ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); - - if (err==ZIP_OK) /* number of this disk */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); - - if (err==ZIP_OK) /* number of the disk with the start of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); - - if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ - { - { - if(zi->number_entry >= 0xFFFF) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); - } - } - - if (err==ZIP_OK) /* total number of entries in the central dir */ - { - if(zi->number_entry >= 0xFFFF) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); - } - - if (err==ZIP_OK) /* size of the central directory */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); - - if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ - { - ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; - if(pos >= 0xffffffff) - { - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); - } - else - err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); - } - - return err; -} - -int Write_GlobalComment(zip64_internal* zi, const char* global_comment) -{ - int err = ZIP_OK; - uInt size_global_comment = 0; - - if(global_comment != NULL) - size_global_comment = (uInt)strlen(global_comment); - - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); - - if (err == ZIP_OK && size_global_comment > 0) - { - if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment) - err = ZIP_ERRNO; - } - return err; -} - -extern int ZEXPORT zipClose (zipFile file, const char* global_comment) -{ - zip64_internal* zi; - int err = 0; - uLong size_centraldir = 0; - ZPOS64_T centraldir_pos_inzip; - ZPOS64_T pos; - - if (file == NULL) - return ZIP_PARAMERROR; - - zi = (zip64_internal*)file; - - if (zi->in_opened_file_inzip == 1) - { - err = zipCloseFileInZip (file); - } - -#ifndef NO_ADDFILEINEXISTINGZIP - if (global_comment==NULL) - global_comment = zi->globalcomment; -#endif - - centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); - - if (err==ZIP_OK) - { - linkedlist_datablock_internal* ldi = zi->central_dir.first_block; - while (ldi!=NULL) - { - if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) - { - if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block) - err = ZIP_ERRNO; - } - - size_centraldir += ldi->filled_in_this_block; - ldi = ldi->next_datablock; - } - } - free_linkedlist(&(zi->central_dir)); - - pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; - if(pos >= 0xffffffff) - { - ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); - Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); - - Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos); - } - - if (err==ZIP_OK) - err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); - - if(err == ZIP_OK) - err = Write_GlobalComment(zi, global_comment); - - if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0) - if (err == ZIP_OK) - err = ZIP_ERRNO; - -#ifndef NO_ADDFILEINEXISTINGZIP - TRYFREE(zi->globalcomment); -#endif - TRYFREE(zi); - - return err; -} - -extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) -{ - char* p = pData; - int size = 0; - char* pNewHeader; - char* pTmp; - short header; - short dataSize; - - int retVal = ZIP_OK; - - if(pData == NULL || *dataLen < 4) - return ZIP_PARAMERROR; - - pNewHeader = (char*)ALLOC(*dataLen); - pTmp = pNewHeader; - - while(p < (pData + *dataLen)) - { - header = *(short*)p; - dataSize = *(((short*)p)+1); - - if( header == sHeader ) // Header found. - { - p += dataSize + 4; // skip it. do not copy to temp buffer - } - else - { - // Extra Info block should not be removed, So copy it to the temp buffer. - memcpy(pTmp, p, dataSize + 4); - p += dataSize + 4; - size += dataSize + 4; - } - - } - - if(size < *dataLen) - { - // clean old extra info block. - memset(pData,0, *dataLen); - - // copy the new extra info block over the old - if(size > 0) - memcpy(pData, pNewHeader, size); - - // set the new extra info size - *dataLen = size; - - retVal = ZIP_OK; - } - else - retVal = ZIP_ERRNO; - - TRYFREE(pNewHeader); - - return retVal; -} From 4d68e3b84b5a84b27d14754163efa80418a87082 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 15:23:51 +0300 Subject: [PATCH 05/12] a --- builder/builder.cpp | 2 +- modules/editor/buildtools/converter/androidbuilder.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/builder.cpp b/builder/builder.cpp index 7c53bc741..9cff984db 100644 --- a/builder/builder.cpp +++ b/builder/builder.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include diff --git a/modules/editor/buildtools/converter/androidbuilder.cpp b/modules/editor/buildtools/converter/androidbuilder.cpp index 48803712f..9d3140668 100644 --- a/modules/editor/buildtools/converter/androidbuilder.cpp +++ b/modules/editor/buildtools/converter/androidbuilder.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include namespace { const char *gAndroidJava("Builder/Android/Java_Path"); From 12b8358467dec3100700e5d265c44dba781aac05 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 16:20:44 +0300 Subject: [PATCH 06/12] update --- thirdparty/minizip/minizip.qbs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/thirdparty/minizip/minizip.qbs b/thirdparty/minizip/minizip.qbs index 1c63d5925..a26191584 100644 --- a/thirdparty/minizip/minizip.qbs +++ b/thirdparty/minizip/minizip.qbs @@ -16,7 +16,9 @@ Project { if(qbs.targetOS.contains("windows")) { sources.push("mz_os_win32.c") sources.push("mz_strm_os_win32.c") - } else { + } + + if(qbs.targetOS.contains("linux")) { sources.push("mz_os_posix.c") sources.push("mz_strm_os_posix.c") } From 3723afbaf8fb734a421c115ec8cbc77052686fc1 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 16:41:25 +0300 Subject: [PATCH 07/12] a --- thirdparty/minizip/minizip.qbs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/thirdparty/minizip/minizip.qbs b/thirdparty/minizip/minizip.qbs index a26191584..1c63d5925 100644 --- a/thirdparty/minizip/minizip.qbs +++ b/thirdparty/minizip/minizip.qbs @@ -16,9 +16,7 @@ Project { if(qbs.targetOS.contains("windows")) { sources.push("mz_os_win32.c") sources.push("mz_strm_os_win32.c") - } - - if(qbs.targetOS.contains("linux")) { + } else { sources.push("mz_os_posix.c") sources.push("mz_strm_os_posix.c") } From 34e917248cc034b5e15e01630655416211824a4d Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 17:00:12 +0300 Subject: [PATCH 08/12] a --- thirdparty/minizip/mz_os_posix.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/thirdparty/minizip/mz_os_posix.c b/thirdparty/minizip/mz_os_posix.c index b0378a248..3677c4441 100644 --- a/thirdparty/minizip/mz_os_posix.c +++ b/thirdparty/minizip/mz_os_posix.c @@ -29,6 +29,9 @@ #if defined(__APPLE__) # include # include + +# include +# include #endif #if defined(HAVE_GETRANDOM) From 4fec3ef839a216ffa446651a9579554bf52944ae Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 17:09:12 +0300 Subject: [PATCH 09/12] update --- thirdparty/minizip/mz_os_posix.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/thirdparty/minizip/mz_os_posix.c b/thirdparty/minizip/mz_os_posix.c index 3677c4441..c9596b609 100644 --- a/thirdparty/minizip/mz_os_posix.c +++ b/thirdparty/minizip/mz_os_posix.c @@ -30,8 +30,7 @@ # include # include -# include -# include +# include #endif #if defined(HAVE_GETRANDOM) From 472ed93348cdcb7af3307205f49155a932211230 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 17:25:01 +0300 Subject: [PATCH 10/12] a --- thirdparty/minizip/mz_config.h | 2 +- thirdparty/minizip/mz_os_posix.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/thirdparty/minizip/mz_config.h b/thirdparty/minizip/mz_config.h index d9747f0d9..2a15c4f4a 100644 --- a/thirdparty/minizip/mz_config.h +++ b/thirdparty/minizip/mz_config.h @@ -2,7 +2,7 @@ #define MZ_CONFIG_H // Define to 1 if you have the header file. -#define HAVE_DIRENT_H 0 +#define HAVE_DIRENT_H 1 // Define to 1 if you have the header file. #define HAVE_SYS_DIRENT_H 0 diff --git a/thirdparty/minizip/mz_os_posix.c b/thirdparty/minizip/mz_os_posix.c index c9596b609..b0378a248 100644 --- a/thirdparty/minizip/mz_os_posix.c +++ b/thirdparty/minizip/mz_os_posix.c @@ -29,8 +29,6 @@ #if defined(__APPLE__) # include # include - -# include #endif #if defined(HAVE_GETRANDOM) From 9a68134dbd64999716ce231843e50b41cad5cb58 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 17:28:48 +0300 Subject: [PATCH 11/12] a --- thirdparty/minizip/mz_config.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/thirdparty/minizip/mz_config.h b/thirdparty/minizip/mz_config.h index 2a15c4f4a..2ecdc1fd1 100644 --- a/thirdparty/minizip/mz_config.h +++ b/thirdparty/minizip/mz_config.h @@ -2,7 +2,11 @@ #define MZ_CONFIG_H // Define to 1 if you have the header file. -#define HAVE_DIRENT_H 1 +#if defined(__APPLE__) +# define HAVE_DIRENT_H 1 +#else +# define HAVE_DIRENT_H 0 +#endif // Define to 1 if you have the header file. #define HAVE_SYS_DIRENT_H 0 From 36ba20ae1030f223446d1381a881ed7279e1e4a7 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Jun 2026 17:50:29 +0300 Subject: [PATCH 12/12] a --- thirdparty/minizip/mz_config.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/thirdparty/minizip/mz_config.h b/thirdparty/minizip/mz_config.h index 2ecdc1fd1..0369b9a5d 100644 --- a/thirdparty/minizip/mz_config.h +++ b/thirdparty/minizip/mz_config.h @@ -18,7 +18,11 @@ #define HAVE_STDINT_H 1 // Define to 1 if DIR* is defined. -#define HAVE_PDIR 0 +#if defined(__APPLE__) +# define HAVE_PDIR 1 +#else +# define HAVE_PDIR 0 +#endif // Define to 1 if fseeko() is defined. #define HAVE_FSEEKO 0