diff options
49 files changed, 2513 insertions, 2735 deletions
diff --git a/src/Common/Zip.vcxproj b/src/Common/Zip.vcxproj index 086657b5..ec907d94 100644 --- a/src/Common/Zip.vcxproj +++ b/src/Common/Zip.vcxproj @@ -19,7 +19,6 @@ </ProjectConfiguration> </ItemGroup> <ItemGroup> - <ClCompile Include="libzip\mkstemp.c" /> <ClCompile Include="libzip\zip_add.c" /> <ClCompile Include="libzip\zip_add_dir.c" /> <ClCompile Include="libzip\zip_add_entry.c" /> @@ -72,6 +71,7 @@ <ClCompile Include="libzip\zip_name_locate.c" /> <ClCompile Include="libzip\zip_new.c" /> <ClCompile Include="libzip\zip_open.c" /> + <ClCompile Include="libzip\zip_pkware.c" /> <ClCompile Include="libzip\zip_progress.c" /> <ClCompile Include="libzip\zip_rename.c" /> <ClCompile Include="libzip\zip_replace.c" /> @@ -90,16 +90,21 @@ <ClCompile Include="libzip\zip_source_commit_write.c" /> <ClCompile Include="libzip\zip_source_compress.c" /> <ClCompile Include="libzip\zip_source_crc.c" /> - <ClCompile Include="libzip\zip_source_deflate.c" /> <ClCompile Include="libzip\zip_source_error.c" /> - <ClCompile Include="libzip\zip_source_filep.c" /> + <ClCompile Include="libzip\zip_source_file_common.c" /> + <ClCompile Include="libzip\zip_source_file_stdio.c" /> + <ClCompile Include="libzip\zip_source_file_win32.c" /> + <ClCompile Include="libzip\zip_source_file_win32_named.c" /> + <ClCompile Include="libzip\zip_source_file_win32_utf16.c" /> + <ClCompile Include="libzip\zip_source_file_win32_utf8.c" /> <ClCompile Include="libzip\zip_source_free.c" /> <ClCompile Include="libzip\zip_source_function.c" /> - <ClCompile Include="libzip\zip_source_get_compression_flags.c" /> + <ClCompile Include="libzip\zip_source_get_file_attributes.c" /> <ClCompile Include="libzip\zip_source_is_deleted.c" /> <ClCompile Include="libzip\zip_source_layered.c" /> <ClCompile Include="libzip\zip_source_open.c" /> - <ClCompile Include="libzip\zip_source_pkware.c" /> + <ClCompile Include="libzip\zip_source_pkware_decode.c" /> + <ClCompile Include="libzip\zip_source_pkware_encode.c" /> <ClCompile Include="libzip\zip_source_read.c" /> <ClCompile Include="libzip\zip_source_remove.c" /> <ClCompile Include="libzip\zip_source_rollback_write.c" /> @@ -109,10 +114,6 @@ <ClCompile Include="libzip\zip_source_supports.c" /> <ClCompile Include="libzip\zip_source_tell.c" /> <ClCompile Include="libzip\zip_source_tell_write.c" /> - <ClCompile Include="libzip\zip_source_win32a.c" /> - <ClCompile Include="libzip\zip_source_win32handle.c" /> - <ClCompile Include="libzip\zip_source_win32utf8.c" /> - <ClCompile Include="libzip\zip_source_win32w.c" /> <ClCompile Include="libzip\zip_source_window.c" /> <ClCompile Include="libzip\zip_source_write.c" /> <ClCompile Include="libzip\zip_source_zip.c" /> @@ -145,7 +146,9 @@ <ClInclude Include="libzip\zip.h" /> <ClInclude Include="libzip\zipconf.h" /> <ClInclude Include="libzip\zipint.h" /> - <ClInclude Include="libzip\zipwin32.h" /> + <ClInclude Include="libzip\zip_source_file.h" /> + <ClInclude Include="libzip\zip_source_file_stdio.h" /> + <ClInclude Include="libzip\zip_source_file_win32.h" /> <ClInclude Include="zlib\crc32.h" /> <ClInclude Include="zlib\deflate.h" /> <ClInclude Include="zlib\inffast.h" /> diff --git a/src/Common/Zip.vcxproj.filters b/src/Common/Zip.vcxproj.filters index f274e809..88c8ff6f 100644 --- a/src/Common/Zip.vcxproj.filters +++ b/src/Common/Zip.vcxproj.filters @@ -9,9 +9,6 @@ </Filter> </ItemGroup> <ItemGroup> - <ClCompile Include="libzip\mkstemp.c"> - <Filter>libzip</Filter> - </ClCompile> <ClCompile Include="libzip\zip_add.c"> <Filter>libzip</Filter> </ClCompile> @@ -57,9 +54,6 @@ <ClCompile Include="libzip\zip_error_strerror.c"> <Filter>libzip</Filter> </ClCompile> - <ClCompile Include="libzip\zip_err_str.c"> - <Filter>libzip</Filter> - </ClCompile> <ClCompile Include="libzip\zip_extra_field.c"> <Filter>libzip</Filter> </ClCompile> @@ -207,15 +201,9 @@ <ClCompile Include="libzip\zip_source_crc.c"> <Filter>libzip</Filter> </ClCompile> - <ClCompile Include="libzip\zip_source_deflate.c"> - <Filter>libzip</Filter> - </ClCompile> <ClCompile Include="libzip\zip_source_error.c"> <Filter>libzip</Filter> </ClCompile> - <ClCompile Include="libzip\zip_source_filep.c"> - <Filter>libzip</Filter> - </ClCompile> <ClCompile Include="libzip\zip_source_free.c"> <Filter>libzip</Filter> </ClCompile> @@ -231,9 +219,6 @@ <ClCompile Include="libzip\zip_source_open.c"> <Filter>libzip</Filter> </ClCompile> - <ClCompile Include="libzip\zip_source_pkware.c"> - <Filter>libzip</Filter> - </ClCompile> <ClCompile Include="libzip\zip_source_read.c"> <Filter>libzip</Filter> </ClCompile> @@ -261,18 +246,6 @@ <ClCompile Include="libzip\zip_source_tell_write.c"> <Filter>libzip</Filter> </ClCompile> - <ClCompile Include="libzip\zip_source_win32a.c"> - <Filter>libzip</Filter> - </ClCompile> - <ClCompile Include="libzip\zip_source_win32handle.c"> - <Filter>libzip</Filter> - </ClCompile> - <ClCompile Include="libzip\zip_source_win32utf8.c"> - <Filter>libzip</Filter> - </ClCompile> - <ClCompile Include="libzip\zip_source_win32w.c"> - <Filter>libzip</Filter> - </ClCompile> <ClCompile Include="libzip\zip_source_window.c"> <Filter>libzip</Filter> </ClCompile> @@ -357,10 +330,40 @@ <ClCompile Include="libzip\zip_algorithm_deflate.c"> <Filter>libzip</Filter> </ClCompile> - <ClCompile Include="libzip\zip_source_get_compression_flags.c"> + <ClCompile Include="libzip\zip_source_accept_empty.c"> <Filter>libzip</Filter> </ClCompile> - <ClCompile Include="libzip\zip_source_accept_empty.c"> + <ClCompile Include="libzip\zip_source_get_file_attributes.c"> + <Filter>libzip</Filter> + </ClCompile> + <ClCompile Include="libzip\zip_source_pkware_decode.c"> + <Filter>libzip</Filter> + </ClCompile> + <ClCompile Include="libzip\zip_source_pkware_encode.c"> + <Filter>libzip</Filter> + </ClCompile> + <ClCompile Include="libzip\zip_pkware.c"> + <Filter>libzip</Filter> + </ClCompile> + <ClCompile Include="libzip\zip_source_file_common.c"> + <Filter>libzip</Filter> + </ClCompile> + <ClCompile Include="libzip\zip_source_file_stdio.c"> + <Filter>libzip</Filter> + </ClCompile> + <ClCompile Include="libzip\zip_source_file_win32_named.c"> + <Filter>libzip</Filter> + </ClCompile> + <ClCompile Include="libzip\zip_source_file_win32_utf8.c"> + <Filter>libzip</Filter> + </ClCompile> + <ClCompile Include="libzip\zip_source_file_win32_utf16.c"> + <Filter>libzip</Filter> + </ClCompile> + <ClCompile Include="libzip\zip_source_file_win32.c"> + <Filter>libzip</Filter> + </ClCompile> + <ClCompile Include="libzip\zip_err_str.c"> <Filter>libzip</Filter> </ClCompile> </ItemGroup> @@ -383,9 +386,6 @@ <ClInclude Include="libzip\zipint.h"> <Filter>libzip</Filter> </ClInclude> - <ClInclude Include="libzip\zipwin32.h"> - <Filter>libzip</Filter> - </ClInclude> <ClInclude Include="zlib\crc32.h"> <Filter>zlib</Filter> </ClInclude> @@ -416,5 +416,14 @@ <ClInclude Include="zlib\zutil.h"> <Filter>zlib</Filter> </ClInclude> + <ClInclude Include="libzip\zip_source_file.h"> + <Filter>libzip</Filter> + </ClInclude> + <ClInclude Include="libzip\zip_source_file_stdio.h"> + <Filter>libzip</Filter> + </ClInclude> + <ClInclude Include="libzip\zip_source_file_win32.h"> + <Filter>libzip</Filter> + </ClInclude> </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/Common/libzip/LICENSE b/src/Common/libzip/LICENSE index e93454e8..573d5d94 100644 --- a/src/Common/libzip/LICENSE +++ b/src/Common/libzip/LICENSE @@ -1,4 +1,4 @@ -Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner +Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner The authors can be contacted at <libzip@nih.at> diff --git a/src/Common/libzip/NEWS.md b/src/Common/libzip/NEWS.md index 9d8d2a33..d48b59ac 100644 --- a/src/Common/libzip/NEWS.md +++ b/src/Common/libzip/NEWS.md @@ -1,5 +1,52 @@ +1.7.3 [2020-07-15] +================== + +* Support cmake < 3.17 again. +* Fix pkgconfig file (regression in 1.7.2). + +1.7.2 [2020-07-11] +================== + +* Fixes for the CMake `find_project()` files. +* libzip moved to the CMake `libzip::` `NAMESPACE`. +* CMake usage best practice cleanups. + +1.7.1 [2020-06-13] +================== + +* Restore `LIBZIP_VERSION_{MAJOR,MINOR,MICRO}` symbols. +* Fixes warnings reported by PVS-Studio. +* Add `LIBZIP_DO_INSTALL` build setting to make it easier to use + libzip as subproject. + +1.7.0 [2020-06-05] +================== + +* Add support for encrypting using traditional PKWare encryption. +* Add `zip_compression_method_supported()`. +* Add `zip_encryption_method_supported()`. +* Add the `ZIP_SOURCE_GET_FILE_ATTRIBUTES` source command. +* Refactor stdio file backend. +* Add CMake find_project() support. + +1.6.1 [2020-02-03] +================== + +* Bugfix for double-free in `zipcmp(1)` during cleanup. + +1.6.0 [2020-01-24] +================== + +* Avoid using `umask()` since it's not thread-safe. +* Set close-on-exec flag when opening files. +* Do not accept empty files as valid zip archives any longer. +* Add support for XZ compressed files (using liblzma). +* Add support for cancelling while closing zip archives. +* Add support for setting the time in the on-disk format. + 1.5.2 [2019-03-12] ================== + * Fix bug in AES encryption affecting certain file sizes * Keep file permissions when modifying zip archives * Support systems with small stack size. @@ -37,6 +84,7 @@ 1.3.2 [2017-11-20] ================== + * Fix bug introduced in last: zip_t was erroneously freed if zip_close() failed. 1.3.1 [2017-11-19] @@ -181,7 +229,7 @@ 0.9 [2008-07-25] ================== -* on Windows, explictly set dllimport/dllexport +* on Windows, explicitly set dllimport/dllexport * remove erroneous references to GPL * add support for torrentzip * new functions: zip_get_archive_flag, zip_set_archive_flag diff --git a/src/Common/libzip/compat.h b/src/Common/libzip/compat.h index e0a27beb..fb2c56e1 100644 --- a/src/Common/libzip/compat.h +++ b/src/Common/libzip/compat.h @@ -36,9 +36,7 @@ #include "zipconf.h" -#ifdef HAVE_CONFIG_H #include "config.h" -#endif /* to have *_MAX definitions for all types when compiling with g++ */ #define __STDC_LIMIT_MACROS @@ -103,10 +101,6 @@ typedef char bool; #if !defined(HAVE_FILENO) && defined(HAVE__FILENO) #define fileno _fileno #endif -/* Windows' open() doesn't understand Unix permissions */ -#if defined(HAVE__OPEN) -#define open(a, b, c) _open((a), (b)) -#endif #if defined(HAVE__SNPRINTF) #define snprintf _snprintf #endif diff --git a/src/Common/libzip/config.h b/src/Common/libzip/config.h index 4de10dff..1edd29ba 100644 --- a/src/Common/libzip/config.h +++ b/src/Common/libzip/config.h @@ -76,7 +76,7 @@ #define HAVE_SHARED /* END DEFINES */ #define PACKAGE "libzip" -#define VERSION "1.5.2" +#define VERSION "1.7.3" #ifndef HAVE_SSIZE_T_LIBZIP # if SIZE_T_LIBZIP == INT_LIBZIP diff --git a/src/Common/libzip/mkstemp.c b/src/Common/libzip/mkstemp.c deleted file mode 100644 index 01a531fc..00000000 --- a/src/Common/libzip/mkstemp.c +++ /dev/null @@ -1,153 +0,0 @@ -/* Adapted from NetBSB libc by Dieter Baron */ - -/* NetBSD: gettemp.c,v 1.13 2003/12/05 00:57:36 uebayasi Exp */ - -/* - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/stat.h> -#include <sys/types.h> - -#include <assert.h> -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#ifdef _WIN32 -#include <io.h> -#include <process.h> -#else -#include <unistd.h> -#endif -#include <stdio.h> -#include <stdlib.h> - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - - -int -_zip_mkstemp(char *path) { -#ifdef _WIN32 - int ret; - ret = _creat(_mktemp(path), _S_IREAD | _S_IWRITE); - if (ret == -1) { - return 0; - } - else { - return ret; - } -#else - int fd; - char *start, *trv; - struct stat sbuf; - pid_t pid; - - /* To guarantee multiple calls generate unique names even if - the file is not created. 676 different possibilities with 7 - or more X's, 26 with 6 or less. */ - static char xtra[2] = "aa"; - int xcnt = 0; - - pid = getpid(); - - /* Move to end of path and count trailing X's. */ - for (trv = path; *trv; ++trv) - if (*trv == 'X') - xcnt++; - else - xcnt = 0; - - /* Use at least one from xtra. Use 2 if more than 6 X's. */ - if (*(trv - 1) == 'X') - *--trv = xtra[0]; - if (xcnt > 6 && *(trv - 1) == 'X') - *--trv = xtra[1]; - - /* Set remaining X's to pid digits with 0's to the left. */ - while (*--trv == 'X') { - *trv = (pid % 10) + '0'; - pid /= 10; - } - - /* update xtra for next call. */ - if (xtra[0] != 'z') - xtra[0]++; - else { - xtra[0] = 'a'; - if (xtra[1] != 'z') - xtra[1]++; - else - xtra[1] = 'a'; - } - - /* - * check the target directory; if you have six X's and it - * doesn't exist this runs for a *very* long time. - */ - for (start = trv + 1;; --trv) { - if (trv <= path) - break; - if (*trv == '/') { - *trv = '\0'; - if (stat(path, &sbuf)) - return (0); - if (!S_ISDIR(sbuf.st_mode)) { - errno = ENOTDIR; - return (0); - } - *trv = '/'; - break; - } - } - - for (;;) { - if ((fd = open(path, O_CREAT | O_EXCL | O_RDWR | O_BINARY, 0600)) >= 0) - return (fd); - if (errno != EEXIST) - return (0); - - /* tricky little algorithm for backward compatibility */ - for (trv = start;;) { - if (!*trv) - return (0); - if (*trv == 'z') - *trv++ = 'a'; - else { - if (isdigit((unsigned char)*trv)) - *trv = 'a'; - else - ++*trv; - break; - } - } - } - /*NOTREACHED*/ -#endif -} diff --git a/src/Common/libzip/zip.h b/src/Common/libzip/zip.h index 34b544ef..ba0b6ba2 100644 --- a/src/Common/libzip/zip.h +++ b/src/Common/libzip/zip.h @@ -58,6 +58,9 @@ extern "C" { #endif #endif +#define _Nullable +#define _Nonnull + #include <stdio.h> #include <sys/types.h> #include <time.h> @@ -161,8 +164,8 @@ extern "C" { /* 13 - Reserved by PKWARE */ #define ZIP_CM_LZMA 14 /* LZMA (EFS) */ /* 15-17 - Reserved by PKWARE */ -#define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */ -#define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */ +#define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */ +#define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */ #define ZIP_CM_LZMA2 33 #define ZIP_CM_XZ 95 /* XZ compressed data */ #define ZIP_CM_JPEG 96 /* Compressed Jpeg data */ @@ -214,31 +217,32 @@ extern "C" { enum zip_source_cmd { - ZIP_SOURCE_OPEN, /* prepare for reading */ - ZIP_SOURCE_READ, /* read data */ - ZIP_SOURCE_CLOSE, /* reading is done */ - ZIP_SOURCE_STAT, /* get meta information */ - ZIP_SOURCE_ERROR, /* get error information */ - ZIP_SOURCE_FREE, /* cleanup and free resources */ - ZIP_SOURCE_SEEK, /* set position for reading */ - ZIP_SOURCE_TELL, /* get read position */ - ZIP_SOURCE_BEGIN_WRITE, /* prepare for writing */ - ZIP_SOURCE_COMMIT_WRITE, /* writing is done */ - ZIP_SOURCE_ROLLBACK_WRITE, /* discard written changes */ - ZIP_SOURCE_WRITE, /* write data */ - ZIP_SOURCE_SEEK_WRITE, /* set position for writing */ - ZIP_SOURCE_TELL_WRITE, /* get write position */ - ZIP_SOURCE_SUPPORTS, /* check whether source supports command */ - ZIP_SOURCE_REMOVE, /* remove file */ - ZIP_SOURCE_GET_COMPRESSION_FLAGS, /* get compression flags, internal only */ - ZIP_SOURCE_BEGIN_WRITE_CLONING, /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */ - ZIP_SOURCE_ACCEPT_EMPTY /* whether empty files are valid archives */ + ZIP_SOURCE_OPEN, /* prepare for reading */ + ZIP_SOURCE_READ, /* read data */ + ZIP_SOURCE_CLOSE, /* reading is done */ + ZIP_SOURCE_STAT, /* get meta information */ + ZIP_SOURCE_ERROR, /* get error information */ + ZIP_SOURCE_FREE, /* cleanup and free resources */ + ZIP_SOURCE_SEEK, /* set position for reading */ + ZIP_SOURCE_TELL, /* get read position */ + ZIP_SOURCE_BEGIN_WRITE, /* prepare for writing */ + ZIP_SOURCE_COMMIT_WRITE, /* writing is done */ + ZIP_SOURCE_ROLLBACK_WRITE, /* discard written changes */ + ZIP_SOURCE_WRITE, /* write data */ + ZIP_SOURCE_SEEK_WRITE, /* set position for writing */ + ZIP_SOURCE_TELL_WRITE, /* get write position */ + ZIP_SOURCE_SUPPORTS, /* check whether source supports command */ + ZIP_SOURCE_REMOVE, /* remove file */ + ZIP_SOURCE_RESERVED_1, /* previously used internally */ + ZIP_SOURCE_BEGIN_WRITE_CLONING, /* like ZIP_SOURCE_BEGIN_WRITE, but keep part of original file */ + ZIP_SOURCE_ACCEPT_EMPTY, /* whether empty files are valid archives */ + ZIP_SOURCE_GET_FILE_ATTRIBUTES /* get additional file attributes */ }; typedef enum zip_source_cmd zip_source_cmd_t; #define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_int64_t)1) << (cmd)) -// clang-format off +/* clang-format off */ #define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \ | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_READ) \ @@ -261,7 +265,7 @@ typedef enum zip_source_cmd zip_source_cmd_t; | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_TELL_WRITE) \ | ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_REMOVE)) -// clang-format on +/* clang-format on */ /* for use by sources */ struct zip_source_args_seek { @@ -276,9 +280,9 @@ typedef struct zip_source_args_seek zip_source_args_seek_t; /* error information */ /* use zip_error_*() to access */ struct zip_error { - int zip_err; /* libzip error code (ZIP_ER_*) */ - int sys_err; /* copy of errno (E*) or zlib error code */ - char *str; /* string representation or NULL */ + int zip_err; /* libzip error code (ZIP_ER_*) */ + int sys_err; /* copy of errno (E*) or zlib error code */ + char *_Nullable str; /* string representation or NULL */ }; #define ZIP_STAT_NAME 0x0001u @@ -293,7 +297,7 @@ struct zip_error { struct zip_stat { zip_uint64_t valid; /* which fields have valid values */ - const char * name; /* name of the file */ + const char *_Nullable name; /* name of the file */ zip_uint64_t index; /* index within archive */ zip_uint64_t size; /* size of file (uncompressed) */ zip_uint64_t comp_size; /* size of file (compressed) */ @@ -305,10 +309,27 @@ struct zip_stat { }; struct zip_buffer_fragment { - zip_uint8_t * data; + zip_uint8_t *_Nonnull data; zip_uint64_t length; }; +struct zip_file_attributes { + zip_uint64_t valid; /* which fields have valid values */ + zip_uint8_t version; /* version of this struct, currently 1 */ + zip_uint8_t host_system; /* host system on which file was created */ + zip_uint8_t ascii; /* flag whether file is ASCII text */ + zip_uint8_t version_needed; /* minimum version needed to extract file */ + zip_uint32_t external_file_attributes; /* external file attributes (host-system specific) */ + zip_uint16_t general_purpose_bit_flags; /* general purpose big flags, only some bits are honored */ + zip_uint16_t general_purpose_bit_mask; /* which bits in general_purpose_bit_flags are valid */ +}; + +#define ZIP_FILE_ATTRIBUTES_HOST_SYSTEM 0x0001u +#define ZIP_FILE_ATTRIBUTES_ASCII 0x0002u +#define ZIP_FILE_ATTRIBUTES_VERSION_NEEDED 0x0004u +#define ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES 0x0008u +#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS 0x0010u + struct zip; struct zip_file; struct zip_source; @@ -316,121 +337,124 @@ struct zip_source; typedef struct zip zip_t; typedef struct zip_error zip_error_t; typedef struct zip_file zip_file_t; +typedef struct zip_file_attributes zip_file_attributes_t; typedef struct zip_source zip_source_t; typedef struct zip_stat zip_stat_t; typedef struct zip_buffer_fragment zip_buffer_fragment_t; typedef zip_uint32_t zip_flags_t; -typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t, zip_source_cmd_t); -typedef void (*zip_progress_callback)(zip_t *, double, void *); -typedef int (*zip_cancel_callback)(zip_t *, void *); +typedef zip_int64_t (*zip_source_callback)(void *_Nullable, void *_Nullable, zip_uint64_t, zip_source_cmd_t); +typedef void (*zip_progress_callback)(zip_t *_Nonnull, double, void *_Nullable); +typedef int (*zip_cancel_callback)(zip_t *_Nonnull, void *_Nullable); #ifndef ZIP_DISABLE_DEPRECATED typedef void (*zip_progress_callback_t)(double); -ZIP_EXTERN void zip_register_progress_callback(zip_t *, zip_progress_callback_t); /* use zip_register_progress_callback_with_state */ - -ZIP_EXTERN zip_int64_t zip_add(zip_t *, const char *, zip_source_t *); /* use zip_file_add */ -ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *, const char *); /* use zip_dir_add */ -ZIP_EXTERN const char * zip_get_file_comment(zip_t *, zip_uint64_t, int *, int); /* use zip_file_get_comment */ -ZIP_EXTERN int zip_get_num_files(zip_t *); /* use zip_get_num_entries instead */ -ZIP_EXTERN int zip_rename(zip_t *, zip_uint64_t, const char *); /* use zip_file_rename */ -ZIP_EXTERN int zip_replace(zip_t *, zip_uint64_t, zip_source_t *); /* use zip_file_replace */ -ZIP_EXTERN int zip_set_file_comment(zip_t *, zip_uint64_t, const char *, int); /* use zip_file_set_comment */ -ZIP_EXTERN int zip_error_get_sys_type(int); /* use zip_error_system_type */ -ZIP_EXTERN void zip_error_get(zip_t *, int *, int *); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */ -ZIP_EXTERN int zip_error_to_str(char *, zip_uint64_t, int, int); /* use zip_error_init_with_code / zip_error_strerror */ -ZIP_EXTERN void zip_file_error_get(zip_file_t *, int *, int *); /* use zip_file_get_error, zip_error_code_zip / zip_error_code_system */ +ZIP_EXTERN void zip_register_progress_callback(zip_t *_Nonnull, zip_progress_callback_t _Nullable); /* use zip_register_progress_callback_with_state */ + +ZIP_EXTERN zip_int64_t zip_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull); /* use zip_file_add */ +ZIP_EXTERN zip_int64_t zip_add_dir(zip_t *_Nonnull, const char *_Nonnull); /* use zip_dir_add */ +ZIP_EXTERN const char *_Nullable zip_get_file_comment(zip_t *_Nonnull, zip_uint64_t, int *_Nullable, int); /* use zip_file_get_comment */ +ZIP_EXTERN int zip_get_num_files(zip_t *_Nonnull); /* use zip_get_num_entries instead */ +ZIP_EXTERN int zip_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull); /* use zip_file_rename */ +ZIP_EXTERN int zip_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull); /* use zip_file_replace */ +ZIP_EXTERN int zip_set_file_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, int); /* use zip_file_set_comment */ +ZIP_EXTERN int zip_error_get_sys_type(int); /* use zip_error_system_type */ +ZIP_EXTERN void zip_error_get(zip_t *_Nonnull, int *_Nullable, int *_Nullable); /* use zip_get_error, zip_error_code_zip / zip_error_code_system */ +ZIP_EXTERN int zip_error_to_str(char *_Nonnull, zip_uint64_t, int, int); /* use zip_error_init_with_code / zip_error_strerror */ +ZIP_EXTERN void zip_file_error_get(zip_file_t *_Nonnull, int *_Nullable, int *_Nullable); /* use zip_file_get_error, zip_error_code_zip / zip_error_code_system */ #endif -ZIP_EXTERN int zip_close(zip_t *); -ZIP_EXTERN int zip_delete(zip_t *, zip_uint64_t); -ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *, const char *, zip_flags_t); -ZIP_EXTERN void zip_discard(zip_t *); - -ZIP_EXTERN zip_error_t * zip_get_error(zip_t *); -ZIP_EXTERN void zip_error_clear(zip_t *); -ZIP_EXTERN int zip_error_code_zip(const zip_error_t *); -ZIP_EXTERN int zip_error_code_system(const zip_error_t *); -ZIP_EXTERN void zip_error_fini(zip_error_t *); -ZIP_EXTERN void zip_error_init(zip_error_t *); -ZIP_EXTERN void zip_error_init_with_code(zip_error_t *, int); -ZIP_EXTERN void zip_error_set(zip_error_t *, int, int); -ZIP_EXTERN const char * zip_error_strerror(zip_error_t *); -ZIP_EXTERN int zip_error_system_type(const zip_error_t *); -ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *, void *, zip_uint64_t); - -ZIP_EXTERN int zip_fclose(zip_file_t *); -ZIP_EXTERN zip_t * zip_fdopen(int, int, int *); -ZIP_EXTERN zip_int64_t zip_file_add(zip_t *, const char *, zip_source_t *, zip_flags_t); -ZIP_EXTERN void zip_file_error_clear(zip_file_t *); -ZIP_EXTERN int zip_file_extra_field_delete(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t); -ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); -ZIP_EXTERN int zip_file_extra_field_set(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t, zip_flags_t); -ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(zip_t *, zip_uint64_t, zip_flags_t); -ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_flags_t); -ZIP_EXTERN const zip_uint8_t * zip_file_extra_field_get(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *, zip_flags_t); -ZIP_EXTERN const zip_uint8_t * zip_file_extra_field_get_by_id(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *, zip_flags_t); -ZIP_EXTERN const char * zip_file_get_comment(zip_t *, zip_uint64_t, zip_uint32_t *, zip_flags_t); -ZIP_EXTERN zip_error_t * zip_file_get_error(zip_file_t *); -ZIP_EXTERN int zip_file_get_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t *, zip_uint32_t *); -ZIP_EXTERN int zip_file_rename(zip_t *, zip_uint64_t, const char *, zip_flags_t); -ZIP_EXTERN int zip_file_replace(zip_t *, zip_uint64_t, zip_source_t *, zip_flags_t); -ZIP_EXTERN int zip_file_set_comment(zip_t *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t); -ZIP_EXTERN int zip_file_set_dostime(zip_t *, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); -ZIP_EXTERN int zip_file_set_encryption(zip_t *, zip_uint64_t, zip_uint16_t, const char *); -ZIP_EXTERN int zip_file_set_external_attributes(zip_t *, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t); -ZIP_EXTERN int zip_file_set_mtime(zip_t *, zip_uint64_t, time_t, zip_flags_t); -ZIP_EXTERN const char * zip_file_strerror(zip_file_t *); -ZIP_EXTERN zip_file_t * zip_fopen(zip_t *, const char *, zip_flags_t); -ZIP_EXTERN zip_file_t * zip_fopen_encrypted(zip_t *, const char *, zip_flags_t, const char *); -ZIP_EXTERN zip_file_t * zip_fopen_index(zip_t *, zip_uint64_t, zip_flags_t); -ZIP_EXTERN zip_file_t * zip_fopen_index_encrypted(zip_t *, zip_uint64_t, zip_flags_t, const char *); -ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *, void *, zip_uint64_t); -ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *, zip_int64_t, int); -ZIP_EXTERN zip_int64_t zip_ftell(zip_file_t *); -ZIP_EXTERN const char * zip_get_archive_comment(zip_t *, int *, zip_flags_t); -ZIP_EXTERN int zip_get_archive_flag(zip_t *, zip_flags_t, zip_flags_t); -ZIP_EXTERN const char * zip_get_name(zip_t *, zip_uint64_t, zip_flags_t); -ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *, zip_flags_t); -ZIP_EXTERN const char * zip_libzip_version(void); -ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *, const char *, zip_flags_t); -ZIP_EXTERN zip_t * zip_open(const char *, int, int *); -ZIP_EXTERN zip_t * zip_open_from_source(zip_source_t *, int, zip_error_t *); -ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *, double, zip_progress_callback, void (*)(void *), void *); -ZIP_EXTERN int zip_register_cancel_callback_with_state(zip_t *, zip_cancel_callback, void (*)(void *), void *); -ZIP_EXTERN int zip_set_archive_comment(zip_t *, const char *, zip_uint16_t); -ZIP_EXTERN int zip_set_archive_flag(zip_t *, zip_flags_t, int); -ZIP_EXTERN int zip_set_default_password(zip_t *, const char *); -ZIP_EXTERN int zip_set_file_compression(zip_t *, zip_uint64_t, zip_int32_t, zip_uint32_t); -ZIP_EXTERN int zip_source_begin_write(zip_source_t *); -ZIP_EXTERN int zip_source_begin_write_cloning(zip_source_t *, zip_uint64_t); -ZIP_EXTERN zip_source_t * zip_source_buffer(zip_t *, const void *, zip_uint64_t, int); -ZIP_EXTERN zip_source_t * zip_source_buffer_create(const void *, zip_uint64_t, int, zip_error_t *); -ZIP_EXTERN zip_source_t * zip_source_buffer_fragment(zip_t *, const zip_buffer_fragment_t *, zip_uint64_t, int); -ZIP_EXTERN zip_source_t * zip_source_buffer_fragment_create(const zip_buffer_fragment_t *, zip_uint64_t, int, zip_error_t *); -ZIP_EXTERN int zip_source_close(zip_source_t *); -ZIP_EXTERN int zip_source_commit_write(zip_source_t *); -ZIP_EXTERN zip_error_t * zip_source_error(zip_source_t *); -ZIP_EXTERN zip_source_t * zip_source_file(zip_t *, const char *, zip_uint64_t, zip_int64_t); -ZIP_EXTERN zip_source_t * zip_source_file_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *); -ZIP_EXTERN zip_source_t * zip_source_filep(zip_t *, FILE *, zip_uint64_t, zip_int64_t); -ZIP_EXTERN zip_source_t * zip_source_filep_create(FILE *, zip_uint64_t, zip_int64_t, zip_error_t *); -ZIP_EXTERN void zip_source_free(zip_source_t *); -ZIP_EXTERN zip_source_t * zip_source_function(zip_t *, zip_source_callback , void *); -ZIP_EXTERN zip_source_t * zip_source_function_create(zip_source_callback , void *, zip_error_t *); -ZIP_EXTERN int zip_source_is_deleted(zip_source_t *); -ZIP_EXTERN void zip_source_keep(zip_source_t *); +ZIP_EXTERN int zip_close(zip_t *_Nonnull); +ZIP_EXTERN int zip_delete(zip_t *_Nonnull, zip_uint64_t); +ZIP_EXTERN zip_int64_t zip_dir_add(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t); +ZIP_EXTERN void zip_discard(zip_t *_Nonnull); + +ZIP_EXTERN zip_error_t *_Nonnull zip_get_error(zip_t *_Nonnull); +ZIP_EXTERN void zip_error_clear(zip_t *_Nonnull); +ZIP_EXTERN int zip_error_code_zip(const zip_error_t *_Nonnull); +ZIP_EXTERN int zip_error_code_system(const zip_error_t *_Nonnull); +ZIP_EXTERN void zip_error_fini(zip_error_t *_Nonnull); +ZIP_EXTERN void zip_error_init(zip_error_t *_Nonnull); +ZIP_EXTERN void zip_error_init_with_code(zip_error_t *_Nonnull, int); +ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int); +ZIP_EXTERN const char *_Nonnull zip_error_strerror(zip_error_t *_Nonnull); +ZIP_EXTERN int zip_error_system_type(const zip_error_t *_Nonnull); +ZIP_EXTERN zip_int64_t zip_error_to_data(const zip_error_t *_Nonnull, void *_Nonnull, zip_uint64_t); + +ZIP_EXTERN int zip_fclose(zip_file_t *_Nonnull); +ZIP_EXTERN zip_t *_Nullable zip_fdopen(int, int, int *_Nullable); +ZIP_EXTERN zip_int64_t zip_file_add(zip_t *_Nonnull, const char *_Nonnull, zip_source_t *_Nonnull, zip_flags_t); +ZIP_EXTERN void zip_file_attributes_init(zip_file_attributes_t *_Nonnull); +ZIP_EXTERN void zip_file_error_clear(zip_file_t *_Nonnull); +ZIP_EXTERN int zip_file_extra_field_delete(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_extra_field_delete_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_extra_field_set(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *_Nullable, zip_uint16_t, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count(zip_t *_Nonnull, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_int16_t zip_file_extra_fields_count_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_uint16_t *_Nullable, zip_flags_t); +ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get_by_id(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *_Nullable, zip_flags_t); +ZIP_EXTERN const char *_Nullable zip_file_get_comment(zip_t *_Nonnull, zip_uint64_t, zip_uint32_t *_Nullable, zip_flags_t); +ZIP_EXTERN zip_error_t *_Nonnull zip_file_get_error(zip_file_t *_Nonnull); +ZIP_EXTERN int zip_file_get_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t *_Nullable, zip_uint32_t *_Nullable); +ZIP_EXTERN int zip_file_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull, zip_flags_t); +ZIP_EXTERN int zip_file_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull, zip_flags_t); +ZIP_EXTERN int zip_file_set_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_set_dostime(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, zip_uint16_t, zip_flags_t); +ZIP_EXTERN int zip_file_set_encryption(zip_t *_Nonnull, zip_uint64_t, zip_uint16_t, const char *_Nullable); +ZIP_EXTERN int zip_file_set_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t); +ZIP_EXTERN int zip_file_set_mtime(zip_t *_Nonnull, zip_uint64_t, time_t, zip_flags_t); +ZIP_EXTERN const char *_Nonnull zip_file_strerror(zip_file_t *_Nonnull); +ZIP_EXTERN zip_file_t *_Nullable zip_fopen(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t); +ZIP_EXTERN zip_file_t *_Nullable zip_fopen_encrypted(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, const char *_Nullable); +ZIP_EXTERN zip_file_t *_Nullable zip_fopen_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_file_t *_Nullable zip_fopen_index_encrypted(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, const char *_Nullable); +ZIP_EXTERN zip_int64_t zip_fread(zip_file_t *_Nonnull, void *_Nonnull, zip_uint64_t); +ZIP_EXTERN zip_int8_t zip_fseek(zip_file_t *_Nonnull, zip_int64_t, int); +ZIP_EXTERN zip_int64_t zip_ftell(zip_file_t *_Nonnull); +ZIP_EXTERN const char *_Nullable zip_get_archive_comment(zip_t *_Nonnull, int *_Nullable, zip_flags_t); +ZIP_EXTERN int zip_get_archive_flag(zip_t *_Nonnull, zip_flags_t, zip_flags_t); +ZIP_EXTERN const char *_Nullable zip_get_name(zip_t *_Nonnull, zip_uint64_t, zip_flags_t); +ZIP_EXTERN zip_int64_t zip_get_num_entries(zip_t *_Nonnull, zip_flags_t); +ZIP_EXTERN const char *_Nonnull zip_libzip_version(void); +ZIP_EXTERN zip_int64_t zip_name_locate(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t); +ZIP_EXTERN zip_t *_Nullable zip_open(const char *_Nonnull, int, int *_Nullable); +ZIP_EXTERN zip_t *_Nullable zip_open_from_source(zip_source_t *_Nonnull, int, zip_error_t *_Nullable); +ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *_Nonnull, double, zip_progress_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable); +ZIP_EXTERN int zip_register_cancel_callback_with_state(zip_t *_Nonnull, zip_cancel_callback _Nullable, void (*_Nullable)(void *_Nullable), void *_Nullable); +ZIP_EXTERN int zip_set_archive_comment(zip_t *_Nonnull, const char *_Nullable, zip_uint16_t); +ZIP_EXTERN int zip_set_archive_flag(zip_t *_Nonnull, zip_flags_t, int); +ZIP_EXTERN int zip_set_default_password(zip_t *_Nonnull, const char *_Nullable); +ZIP_EXTERN int zip_set_file_compression(zip_t *_Nonnull, zip_uint64_t, zip_int32_t, zip_uint32_t); +ZIP_EXTERN int zip_source_begin_write(zip_source_t *_Nonnull); +ZIP_EXTERN int zip_source_begin_write_cloning(zip_source_t *_Nonnull, zip_uint64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer(zip_t *_Nonnull, const void *_Nullable, zip_uint64_t, int); +ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_create(const void *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_fragment(zip_t *_Nonnull, const zip_buffer_fragment_t *_Nonnull, zip_uint64_t, int); +ZIP_EXTERN zip_source_t *_Nullable zip_source_buffer_fragment_create(const zip_buffer_fragment_t *_Nullable, zip_uint64_t, int, zip_error_t *_Nullable); +ZIP_EXTERN int zip_source_close(zip_source_t *_Nonnull); +ZIP_EXTERN int zip_source_commit_write(zip_source_t *_Nonnull); +ZIP_EXTERN zip_error_t *_Nonnull zip_source_error(zip_source_t *_Nonnull); +ZIP_EXTERN zip_source_t *_Nullable zip_source_file(zip_t *_Nonnull, const char *_Nonnull, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_file_create(const char *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_filep(zip_t *_Nonnull, FILE *_Nonnull, zip_uint64_t, zip_int64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_filep_create(FILE *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable); +ZIP_EXTERN void zip_source_free(zip_source_t *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_function(zip_t *_Nonnull, zip_source_callback _Nonnull, void *_Nullable); +ZIP_EXTERN zip_source_t *_Nullable zip_source_function_create(zip_source_callback _Nonnull, void *_Nullable, zip_error_t *_Nullable); +ZIP_EXTERN int zip_source_get_file_attributes(zip_source_t *_Nonnull, zip_file_attributes_t *_Nonnull); +ZIP_EXTERN int zip_source_is_deleted(zip_source_t *_Nonnull); +ZIP_EXTERN void zip_source_keep(zip_source_t *_Nonnull); ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t, ...); -ZIP_EXTERN int zip_source_open(zip_source_t *); -ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *, void *, zip_uint64_t); -ZIP_EXTERN void zip_source_rollback_write(zip_source_t *); -ZIP_EXTERN int zip_source_seek(zip_source_t *, zip_int64_t, int); -ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *, zip_uint64_t, zip_error_t *); -ZIP_EXTERN int zip_source_seek_write(zip_source_t *, zip_int64_t, int); -ZIP_EXTERN int zip_source_stat(zip_source_t *, zip_stat_t *); -ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *); -ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *); +ZIP_EXTERN int zip_source_open(zip_source_t *_Nonnull); +ZIP_EXTERN zip_int64_t zip_source_read(zip_source_t *_Nonnull, void *_Nonnull, zip_uint64_t); +ZIP_EXTERN void zip_source_rollback_write(zip_source_t *_Nonnull); +ZIP_EXTERN int zip_source_seek(zip_source_t *_Nonnull, zip_int64_t, int); +ZIP_EXTERN zip_int64_t zip_source_seek_compute_offset(zip_uint64_t, zip_uint64_t, void *_Nonnull, zip_uint64_t, zip_error_t *_Nullable); +ZIP_EXTERN int zip_source_seek_write(zip_source_t *_Nonnull, zip_int64_t, int); +ZIP_EXTERN int zip_source_stat(zip_source_t *_Nonnull, zip_stat_t *_Nonnull); +ZIP_EXTERN zip_int64_t zip_source_tell(zip_source_t *_Nonnull); +ZIP_EXTERN zip_int64_t zip_source_tell_write(zip_source_t *_Nonnull); #ifdef _WIN32 ZIP_EXTERN zip_source_t *zip_source_win32a(zip_t *, const char *, zip_uint64_t, zip_int64_t); ZIP_EXTERN zip_source_t *zip_source_win32a_create(const char *, zip_uint64_t, zip_int64_t, zip_error_t *); @@ -439,15 +463,17 @@ ZIP_EXTERN zip_source_t *zip_source_win32handle_create(void *, zip_uint64_t, zip ZIP_EXTERN zip_source_t *zip_source_win32w(zip_t *, const wchar_t *, zip_uint64_t, zip_int64_t); ZIP_EXTERN zip_source_t *zip_source_win32w_create(const wchar_t *, zip_uint64_t, zip_int64_t, zip_error_t *); #endif -ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *, const void *, zip_uint64_t); -ZIP_EXTERN zip_source_t * zip_source_zip(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t); -ZIP_EXTERN int zip_stat(zip_t *, const char *, zip_flags_t, zip_stat_t *); -ZIP_EXTERN int zip_stat_index(zip_t *, zip_uint64_t, zip_flags_t, zip_stat_t *); -ZIP_EXTERN void zip_stat_init( zip_stat_t *); -ZIP_EXTERN const char * zip_strerror(zip_t *); -ZIP_EXTERN int zip_unchange(zip_t *, zip_uint64_t); -ZIP_EXTERN int zip_unchange_all(zip_t *); -ZIP_EXTERN int zip_unchange_archive(zip_t *); +ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *_Nonnull, const void *_Nullable, zip_uint64_t); +ZIP_EXTERN zip_source_t *_Nullable zip_source_zip(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t); +ZIP_EXTERN int zip_stat(zip_t *_Nonnull, const char *_Nonnull, zip_flags_t, zip_stat_t *_Nonnull); +ZIP_EXTERN int zip_stat_index(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_stat_t *_Nonnull); +ZIP_EXTERN void zip_stat_init(zip_stat_t *_Nonnull); +ZIP_EXTERN const char *_Nonnull zip_strerror(zip_t *_Nonnull); +ZIP_EXTERN int zip_unchange(zip_t *_Nonnull, zip_uint64_t); +ZIP_EXTERN int zip_unchange_all(zip_t *_Nonnull); +ZIP_EXTERN int zip_unchange_archive(zip_t *_Nonnull); +ZIP_EXTERN int zip_compression_method_supported(zip_int32_t method, int compress); +ZIP_EXTERN int zip_encryption_method_supported(zip_uint16_t method, int encode); #ifdef __cplusplus } diff --git a/src/Common/libzip/zip_algorithm_deflate.c b/src/Common/libzip/zip_algorithm_deflate.c index 30e072a5..d28a1ac5 100644 --- a/src/Common/libzip/zip_algorithm_deflate.c +++ b/src/Common/libzip/zip_algorithm_deflate.c @@ -91,8 +91,8 @@ deallocate(void *ud) { } -static int -compression_flags(void *ud) { +static zip_uint16_t +general_purpose_bit_flags(void *ud) { struct ctx *ctx = (struct ctx *)ud; if (!ctx->compress) { @@ -100,10 +100,10 @@ compression_flags(void *ud) { } if (ctx->compression_flags < 3) { - return 2; + return 2 << 1; } else if (ctx->compression_flags > 7) { - return 1; + return 1 << 1; } return 0; } @@ -220,12 +220,13 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) { } } -// clang-format off +/* clang-format off */ zip_compression_algorithm_t zip_algorithm_deflate_compress = { compress_allocate, deallocate, - compression_flags, + general_purpose_bit_flags, + 20, start, end, input, @@ -237,7 +238,8 @@ zip_compression_algorithm_t zip_algorithm_deflate_compress = { zip_compression_algorithm_t zip_algorithm_deflate_decompress = { decompress_allocate, deallocate, - compression_flags, + general_purpose_bit_flags, + 20, start, end, input, @@ -245,4 +247,4 @@ zip_compression_algorithm_t zip_algorithm_deflate_decompress = { process }; -// clang-format on +/* clang-format on */ diff --git a/src/Common/libzip/zip_close.c b/src/Common/libzip/zip_close.c index 2a9fed25..816fcefa 100644 --- a/src/Common/libzip/zip_close.c +++ b/src/Common/libzip/zip_close.c @@ -36,25 +36,17 @@ #include <stdio.h> #include <stdlib.h> -#include <string.h> -#ifdef HAVE_STRINGS_H -#include <strings.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif -#include <sys/stat.h> -#include <sys/types.h> #ifdef _WIN32 #include <fcntl.h> #include <io.h> #endif -static int add_data(zip_t *, zip_source_t *, zip_dirent_t *); +static int add_data(zip_t *, zip_source_t *, zip_dirent_t *, zip_uint32_t); static int copy_data(zip_t *, zip_uint64_t); static int copy_source(zip_t *, zip_source_t *, zip_int64_t); static int write_cdir(zip_t *, const zip_filelist_t *, zip_uint64_t); +static int write_data_descriptor(zip_t *za, const zip_dirent_t *dirent, int is_zip64); ZIP_EXTERN int zip_close(zip_t *za) { @@ -204,6 +196,7 @@ zip_close(zip_t *za) { } if ((off = zip_source_tell_write(za->src)) < 0) { + _zip_error_set_from_source(&za->error, za->src); error = 1; break; } @@ -221,7 +214,7 @@ zip_close(zip_t *za) { } /* add_data writes dirent */ - if (add_data(za, zs ? zs : entry->source, de) < 0) { + if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) { error = 1; if (zs) zip_source_free(zs); @@ -233,8 +226,11 @@ zip_close(zip_t *za) { else { zip_uint64_t offset; - /* when copying data, all sizes are known -> no data descriptor needed */ - de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; + if (de->encryption_method != ZIP_EM_TRAD_PKWARE) { + /* when copying data, all sizes are known -> no data descriptor needed */ + /* except for PKWare encryption, where removing the data descriptor breaks password validation */ + de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR; + } if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) { error = 1; break; @@ -245,13 +241,20 @@ zip_close(zip_t *za) { } if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) { _zip_error_set_from_source(&za->error, za->src); - error = 1; + error = 1; break; } if (copy_data(za, de->comp_size) < 0) { - error = 1; + error = 1; break; } + + if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { + if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) { + error = 1; + break; + } + } } } @@ -282,14 +285,14 @@ zip_close(zip_t *za) { static int -add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) { +add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) { zip_int64_t offstart, offdata, offend, data_length; - struct zip_stat st; + zip_stat_t st; + zip_file_attributes_t attributes; zip_source_t *src_final, *src_tmp; int ret; int is_zip64; zip_flags_t flags; - zip_int8_t compression_flags; bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt; if (zip_source_stat(src, &st) < 0) { @@ -453,6 +456,9 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) { zip_source_free(src_final); return -1; } + if (de->encryption_method == ZIP_EM_TRAD_PKWARE) { + de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR; + } zip_source_free(src_final); src_final = src_tmp; @@ -471,7 +477,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) { ret = -1; } - if ((compression_flags = zip_source_get_compression_flags(src_final)) < 0) { + if (zip_source_get_file_attributes(src_final, &attributes) != 0) { _zip_error_set_from_source(&za->error, src_final); ret = -1; } @@ -507,8 +513,7 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) { de->crc = st.crc; de->uncomp_size = st.size; de->comp_size = (zip_uint64_t)(offend - offdata); - de->bitflags = (zip_uint16_t)((de->bitflags & (zip_uint16_t)~6) | ((zip_uint8_t)compression_flags << 1)); - _zip_dirent_set_version_needed(de, (flags & ZIP_FL_FORCE_ZIP64) != 0); + _zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed); if ((ret = _zip_dirent_write(za, de, flags)) < 0) return -1; @@ -524,6 +529,12 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de) { return -1; } + if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) { + if (write_data_descriptor(za, de, is_zip64) < 0) { + return -1; + } + } + return 0; } @@ -656,3 +667,37 @@ _zip_changed(const zip_t *za, zip_uint64_t *survivorsp) { return changed; } + +static int +write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) { + zip_buffer_t *buffer = _zip_buffer_new(NULL, MAX_DATA_DESCRIPTOR_LENGTH); + int ret = 0; + + if (buffer == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + return -1; + } + + _zip_buffer_put(buffer, DATADES_MAGIC, 4); + _zip_buffer_put_32(buffer, de->crc); + if (is_zip64) { + _zip_buffer_put_64(buffer, de->comp_size); + _zip_buffer_put_64(buffer, de->uncomp_size); + } + else { + _zip_buffer_put_32(buffer, (zip_uint32_t)de->comp_size); + _zip_buffer_put_32(buffer, (zip_uint32_t)de->uncomp_size); + } + + if (!_zip_buffer_ok(buffer)) { + zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); + ret = -1; + } + else { + ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer)); + } + + _zip_buffer_free(buffer); + + return ret; +} diff --git a/src/Common/libzip/zip_dirent.c b/src/Common/libzip/zip_dirent.c index 2bbb63dc..1691071f 100644 --- a/src/Common/libzip/zip_dirent.c +++ b/src/Common/libzip/zip_dirent.c @@ -35,7 +35,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <sys/stat.h> #include <sys/types.h> #include <time.h> @@ -522,29 +521,54 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo return -1; } - if (zde->uncomp_size == ZIP_UINT32_MAX) + if (zde->uncomp_size == ZIP_UINT32_MAX) { zde->uncomp_size = _zip_buffer_get_64(ef_buffer); + } else if (local) { /* From appnote.txt: This entry in the Local header MUST include BOTH original and compressed file size fields. */ (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */ } - if (zde->comp_size == ZIP_UINT32_MAX) + if (zde->comp_size == ZIP_UINT32_MAX) { zde->comp_size = _zip_buffer_get_64(ef_buffer); + } if (!local) { - if (zde->offset == ZIP_UINT32_MAX) + if (zde->offset == ZIP_UINT32_MAX) { zde->offset = _zip_buffer_get_64(ef_buffer); - if (zde->disk_number == ZIP_UINT16_MAX) + } + if (zde->disk_number == ZIP_UINT16_MAX) { zde->disk_number = _zip_buffer_get_32(ef_buffer); + } } if (!_zip_buffer_eof(ef_buffer)) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_buffer_free(ef_buffer); - if (!from_buffer) { - _zip_buffer_free(buffer); + /* accept additional fields if values match */ + bool ok = true; + switch (got_len) { + case 28: + _zip_buffer_set_offset(ef_buffer, 24); + if (zde->disk_number != _zip_buffer_get_32(ef_buffer)) { + ok = false; + } + /* fallthrough */ + case 24: + _zip_buffer_set_offset(ef_buffer, 0); + if ((zde->uncomp_size != _zip_buffer_get_64(ef_buffer)) || (zde->comp_size != _zip_buffer_get_64(ef_buffer)) || (zde->offset != _zip_buffer_get_64(ef_buffer))) { + ok = false; + } + break; + + default: + ok = false; + } + if (!ok) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_buffer_free(ef_buffer); + if (!from_buffer) { + _zip_buffer_free(buffer); + } + return -1; } - return -1; } _zip_buffer_free(ef_buffer); } @@ -572,7 +596,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields); - return (zip_int64_t)(size + variable_size); + return (zip_int64_t)size + (zip_int64_t)variable_size; } @@ -867,9 +891,9 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) { _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4); if ((flags & ZIP_FL_LOCAL) == 0) { - _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby)); + _zip_buffer_put_16(buffer, de->version_madeby); } - _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_needed)); + _zip_buffer_put_16(buffer, ZIP_MAX(is_really_zip64 ? 45 : 0, de->version_needed)); _zip_buffer_put_16(buffer, de->bitflags); if (is_winzip_aes) { _zip_buffer_put_16(buffer, ZIP_CM_WINZIP_AES); @@ -1074,7 +1098,7 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) { tpm = localtime(&intime); #endif if (tpm == NULL) { - /* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */ + /* if localtime() fails, return an arbitrary date (1980-01-01 00:00:00) */ *ddate = (1 << 5) + 1; *dtime = 0; return; @@ -1091,36 +1115,49 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) { void -_zip_dirent_set_version_needed(zip_dirent_t *de, bool force_zip64) { +_zip_dirent_apply_attributes(zip_dirent_t *de, zip_file_attributes_t *attributes, bool force_zip64, zip_uint32_t changed) { zip_uint16_t length; + if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) { + zip_uint16_t mask = attributes->general_purpose_bit_mask & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK; + de->bitflags = (de->bitflags & ~mask) | (attributes->general_purpose_bit_flags & mask); + } + if (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) { + de->int_attrib = (de->int_attrib & ~0x1) | (attributes->ascii ? 1 : 0); + } + /* manually set attributes are preferred over attributes provided by source */ + if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES)) { + de->ext_attrib = attributes->external_file_attributes; + } + if (de->comp_method == ZIP_CM_LZMA) { de->version_needed = 63; - return; } - - if (de->comp_method == ZIP_CM_BZIP2) { + else if (de->encryption_method == ZIP_EM_AES_128 || de->encryption_method == ZIP_EM_AES_192 || de->encryption_method == ZIP_EM_AES_256) { + de->version_needed = 51; + } + else if (de->comp_method == ZIP_CM_BZIP2) { de->version_needed = 46; - return; } - - if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) { + else if (force_zip64 || _zip_dirent_needs_zip64(de, 0)) { de->version_needed = 45; - return; } - - if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) { + else if (de->comp_method == ZIP_CM_DEFLATE || de->encryption_method == ZIP_EM_TRAD_PKWARE) { + de->version_needed = 20; + } + else if ((length = _zip_string_length(de->filename)) > 0 && de->filename->raw[length - 1] == '/') { de->version_needed = 20; - return; + } + else { + de->version_needed = 10; } - /* directory */ - if ((length = _zip_string_length(de->filename)) > 0) { - if (de->filename->raw[length - 1] == '/') { - de->version_needed = 20; - return; - } + if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) { + de->version_needed = ZIP_MAX(de->version_needed, attributes->version_needed); } - de->version_needed = 10; + de->version_madeby = 63 | (de->version_madeby & 0xff00); + if ((changed & ZIP_DIRENT_ATTRIBUTES) == 0 && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM)) { + de->version_madeby = (de->version_madeby & 0xff) | (zip_uint16_t)(attributes->host_system << 8); + } } diff --git a/src/Common/libzip/zip_error_strerror.c b/src/Common/libzip/zip_error_strerror.c index 63585779..93b24eab 100644 --- a/src/Common/libzip/zip_error_strerror.c +++ b/src/Common/libzip/zip_error_strerror.c @@ -35,6 +35,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <zlib.h> #include "zipint.h" diff --git a/src/Common/libzip/zip_error_to_str.c b/src/Common/libzip/zip_error_to_str.c index 13faf962..34a3331f 100644 --- a/src/Common/libzip/zip_error_to_str.c +++ b/src/Common/libzip/zip_error_to_str.c @@ -33,8 +33,8 @@ #include <stdio.h> -#include <stdlib.h> #include <string.h> +#include <zlib.h> #define _ZIP_COMPILING_DEPRECATED #include "zipint.h" diff --git a/src/Common/libzip/zip_file_get_offset.c b/src/Common/libzip/zip_file_get_offset.c index 9ea89090..2cf4480d 100644 --- a/src/Common/libzip/zip_file_get_offset.c +++ b/src/Common/libzip/zip_file_get_offset.c @@ -33,10 +33,7 @@ #include <stdio.h> -#include <stdlib.h> #include <string.h> -#include <sys/stat.h> -#include <sys/types.h> #include "zipint.h" diff --git a/src/Common/libzip/zip_fopen_index.c b/src/Common/libzip/zip_fopen_index.c index ffca281d..e5205b73 100644 --- a/src/Common/libzip/zip_fopen_index.c +++ b/src/Common/libzip/zip_fopen_index.c @@ -32,9 +32,6 @@ */ -#include <stdio.h> -#include <stdlib.h> - #include "zipint.h" diff --git a/src/Common/libzip/zip_get_encryption_implementation.c b/src/Common/libzip/zip_get_encryption_implementation.c index c9d52ad5..3909e6f6 100644 --- a/src/Common/libzip/zip_get_encryption_implementation.c +++ b/src/Common/libzip/zip_get_encryption_implementation.c @@ -39,10 +39,7 @@ zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t em, int operation) { switch (em) { case ZIP_EM_TRAD_PKWARE: - if (operation == ZIP_CODEC_ENCODE) { - return NULL; - } - return zip_source_pkware; + return operation == ZIP_CODEC_DECODE ? zip_source_pkware_decode : zip_source_pkware_encode; #if defined(HAVE_CRYPTO) case ZIP_EM_AES_128: @@ -55,3 +52,11 @@ _zip_get_encryption_implementation(zip_uint16_t em, int operation) { return NULL; } } + +ZIP_EXTERN int +zip_encryption_method_supported(zip_uint16_t method, int encode) { + if (method == ZIP_EM_NONE) { + return 1; + } + return _zip_get_encryption_implementation(method, encode ? ZIP_CODEC_ENCODE : ZIP_CODEC_DECODE) != NULL; +} diff --git a/src/Common/libzip/zip_open.c b/src/Common/libzip/zip_open.c index 4e29c5b9..019cd987 100644 --- a/src/Common/libzip/zip_open.c +++ b/src/Common/libzip/zip_open.c @@ -32,19 +32,13 @@ */ -#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <sys/stat.h> #include "zipint.h" -typedef enum { - EXISTS_ERROR = -1, - EXISTS_NOT = 0, - EXISTS_OK -} exists_t; +typedef enum { EXISTS_ERROR = -1, EXISTS_NOT = 0, EXISTS_OK } exists_t; static zip_t *_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error); static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cdir, zip_error_t *error); static zip_cdir_t *_zip_find_central_dir(zip_t *za, zip_uint64_t len); diff --git a/src/Common/libzip/zip_pkware.c b/src/Common/libzip/zip_pkware.c new file mode 100644 index 00000000..eb12b1e9 --- /dev/null +++ b/src/Common/libzip/zip_pkware.c @@ -0,0 +1,112 @@ +/* + zip_pkware.c -- Traditional PKWARE de/encryption backend routines + Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include <stdlib.h> +#include <zlib.h> + +#include "zipint.h" + +#define PKWARE_KEY0 305419896 +#define PKWARE_KEY1 591751049 +#define PKWARE_KEY2 878082192 + + +static void +update_keys(zip_pkware_keys_t *keys, zip_uint8_t b) { + keys->key[0] = (zip_uint32_t)crc32(keys->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; + keys->key[1] = (keys->key[1] + (keys->key[0] & 0xff)) * 134775813 + 1; + b = (zip_uint8_t)(keys->key[1] >> 24); + keys->key[2] = (zip_uint32_t)crc32(keys->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; +} + + +static zip_uint8_t +crypt_byte(zip_pkware_keys_t *keys) { + zip_uint16_t tmp; + tmp = (zip_uint16_t)(keys->key[2] | 2); + tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8); + return (zip_uint8_t)tmp; +} + + +void +_zip_pkware_keys_reset(zip_pkware_keys_t *keys) { + keys->key[0] = PKWARE_KEY0; + keys->key[1] = PKWARE_KEY1; + keys->key[2] = PKWARE_KEY2; +} + + +void +_zip_pkware_encrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len) { + zip_uint64_t i; + zip_uint8_t b; + zip_uint8_t tmp; + + for (i = 0; i < len; i++) { + b = in[i]; + + if (out != NULL) { + tmp = crypt_byte(keys); + update_keys(keys, b); + b ^= tmp; + out[i] = b; + } + else { + /* during initialization, we're only interested in key updates */ + update_keys(keys, b); + } + } +} + + +void +_zip_pkware_decrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len) { + zip_uint64_t i; + zip_uint8_t b; + zip_uint8_t tmp; + + for (i = 0; i < len; i++) { + b = in[i]; + + /* during initialization, we're only interested in key updates */ + if (out != NULL) { + tmp = crypt_byte(keys); + b ^= tmp; + out[i] = b; + } + + update_keys(keys, b); + } +} diff --git a/src/Common/libzip/zip_progress.c b/src/Common/libzip/zip_progress.c index d48ae563..ddb47c70 100644 --- a/src/Common/libzip/zip_progress.c +++ b/src/Common/libzip/zip_progress.c @@ -209,10 +209,8 @@ _zip_progress_update(zip_progress_t *progress, double sub_current) { ZIP_EXTERN int zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progress_callback callback, void (*ud_free)(void *), void *ud) { - zip_progress_t *progress = NULL; - if (callback != NULL) { - if (za->progress == NULL) { + if (za->progress == NULL) { if ((za->progress = _zip_progress_new(za)) == NULL) { return -1; } @@ -238,10 +236,8 @@ zip_register_progress_callback_with_state(zip_t *za, double precision, zip_progr ZIP_EXTERN int zip_register_cancel_callback_with_state(zip_t *za, zip_cancel_callback callback, void (*ud_free)(void *), void *ud) { - zip_progress_t *progress = NULL; - if (callback != NULL) { - if (za->progress == NULL) { + if (za->progress == NULL) { if ((za->progress = _zip_progress_new(za)) == NULL) { return -1; } diff --git a/src/Common/libzip/zip_rename.c b/src/Common/libzip/zip_rename.c index e5f16823..75b456de 100644 --- a/src/Common/libzip/zip_rename.c +++ b/src/Common/libzip/zip_rename.c @@ -32,8 +32,6 @@ */ -#include <string.h> - #define _ZIP_COMPILING_DEPRECATED #include "zipint.h" diff --git a/src/Common/libzip/zip_set_file_comment.c b/src/Common/libzip/zip_set_file_comment.c index 1fa01ae6..4277893f 100644 --- a/src/Common/libzip/zip_set_file_comment.c +++ b/src/Common/libzip/zip_set_file_comment.c @@ -32,8 +32,6 @@ */ -#include <stdlib.h> - #define _ZIP_COMPILING_DEPRECATED #include "zipint.h" diff --git a/src/Common/libzip/zip_source_buffer.c b/src/Common/libzip/zip_source_buffer.c index 0685fb39..519d2c30 100644 --- a/src/Common/libzip/zip_source_buffer.c +++ b/src/Common/libzip/zip_source_buffer.c @@ -61,6 +61,7 @@ typedef struct buffer buffer_t; struct read_data { zip_error_t error; time_t mtime; + zip_file_attributes_t attributes; buffer_t *in; buffer_t *out; }; @@ -79,33 +80,42 @@ static zip_int64_t buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_u static zip_int64_t read_data(void *, void *, zip_uint64_t, zip_source_cmd_t); +zip_source_t *zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error); +zip_source_t *zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error); + ZIP_EXTERN zip_source_t * zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) { if (za == NULL) return NULL; - return zip_source_buffer_create(data, len, freep, &za->error); + return zip_source_buffer_with_attributes_create(data, len, freep, NULL, &za->error); } ZIP_EXTERN zip_source_t * zip_source_buffer_create(const void *data, zip_uint64_t len, int freep, zip_error_t *error) { + return zip_source_buffer_with_attributes_create(data, len, freep, NULL, error); +} + + +zip_source_t * +zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes, zip_error_t *error) { zip_buffer_fragment_t fragment; if (data == NULL) { - if (len > 0) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } + if (len > 0) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } - return zip_source_buffer_fragment_create(NULL, 0, freep, error); + return zip_source_buffer_fragment_with_attributes_create(NULL, 0, freep, attributes, error); } fragment.data = (zip_uint8_t *)data; fragment.length = len; - return zip_source_buffer_fragment_create(&fragment, 1, freep, error); + return zip_source_buffer_fragment_with_attributes_create(&fragment, 1, freep, attributes, error); } @@ -115,12 +125,17 @@ zip_source_buffer_fragment(zip_t *za, const zip_buffer_fragment_t *fragments, zi return NULL; } - return zip_source_buffer_fragment_create(fragments, nfragments, freep, &za->error); + return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, &za->error); } ZIP_EXTERN zip_source_t * zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_error_t *error) { + return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, error); +} + +zip_source_t * +zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep, zip_file_attributes_t *attributes, zip_error_t *error) { struct read_data *ctx; zip_source_t *zs; buffer_t *buffer; @@ -143,6 +158,12 @@ zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_ui ctx->in = buffer; ctx->out = NULL; ctx->mtime = time(NULL); + if (attributes) { + memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes)); + } + else { + zip_file_attributes_init(&ctx->attributes); + } zip_error_init(&ctx->error); if ((zs = zip_source_function_create(read_data, ctx, error)) == NULL) { @@ -155,6 +176,11 @@ zip_source_buffer_fragment_create(const zip_buffer_fragment_t *fragments, zip_ui } +zip_source_t * +zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes) { + return zip_source_buffer_with_attributes_create(data, len, freep, attributes, &za->error); +} + static zip_int64_t read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { struct read_data *ctx = (struct read_data *)state; @@ -194,6 +220,17 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { free(ctx); return 0; + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: { + if (len < sizeof(ctx->attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + memcpy(data, &ctx->attributes, sizeof(ctx->attributes)); + + return sizeof(ctx->attributes); + } + case ZIP_SOURCE_OPEN: ctx->in->offset = 0; ctx->in->current_fragment = 0; @@ -250,7 +287,7 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { } case ZIP_SOURCE_SUPPORTS: - return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_BEGIN_WRITE_CLONING, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1); + return zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_BEGIN_WRITE_CLONING, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_WRITE, -1); case ZIP_SOURCE_TELL: if (ctx->in->offset > ZIP_INT64_MAX) { diff --git a/src/Common/libzip/zip_source_compress.c b/src/Common/libzip/zip_source_compress.c index 59b1212d..e49929f5 100644 --- a/src/Common/libzip/zip_source_compress.c +++ b/src/Common/libzip/zip_source_compress.c @@ -31,7 +31,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <limits.h> #include <stdlib.h> #include <string.h> @@ -68,12 +67,12 @@ static struct implementation implementations[] = { {ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress}, #endif #if defined(HAVE_LIBLZMA) -/* Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2 - archives made this way - and vice versa. + /* Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2 + archives made this way - and vice versa. - {ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, - {ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, -*/ + {ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, + {ZIP_CM_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, + */ {ZIP_CM_XZ, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress}, #endif @@ -106,10 +105,10 @@ get_algorithm(zip_int32_t method, bool compress) { return NULL; } -bool -zip_compression_method_supported(zip_int32_t method, bool compress) { +ZIP_EXTERN int +zip_compression_method_supported(zip_int32_t method, int compress) { if (method == ZIP_CM_STORE) { - return true; + return 1; } return get_algorithm(method, compress) != NULL; } @@ -357,9 +356,6 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip } return 0; - case ZIP_SOURCE_GET_COMPRESSION_FLAGS: - return ctx->is_stored ? 0 : ctx->algorithm->compression_flags(ctx->ud); - case ZIP_SOURCE_ERROR: return zip_error_to_data(&ctx->error, data, len); @@ -367,8 +363,24 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip context_free(ctx); return 0; + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: { + zip_file_attributes_t *attributes = (zip_file_attributes_t *)data; + + if (len < sizeof(*attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS; + attributes->version_needed = ctx->algorithm->version_needed; + attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK; + attributes->general_purpose_bit_flags = (ctx->is_stored ? 0 : ctx->algorithm->general_purpose_bit_flags(ctx->ud)); + + return sizeof(*attributes); + } + case ZIP_SOURCE_SUPPORTS: - return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1); + return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); default: zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); diff --git a/src/Common/libzip/zip_source_crc.c b/src/Common/libzip/zip_source_crc.c index 56572c0b..4f3f223f 100644 --- a/src/Common/libzip/zip_source_crc.c +++ b/src/Common/libzip/zip_source_crc.c @@ -34,7 +34,7 @@ #include <limits.h> #include <stdlib.h> -#include <string.h> +#include <zlib.h> #include "zipint.h" @@ -167,7 +167,7 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source return -1; } - return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_COMPRESSION_FLAGS, -1); + return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); } case ZIP_SOURCE_SEEK: { diff --git a/src/Common/libzip/zip_source_deflate.c b/src/Common/libzip/zip_source_deflate.c deleted file mode 100644 index 2574ad01..00000000 --- a/src/Common/libzip/zip_source_deflate.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - zip_source_deflate.c -- deflate (de)compressoin routines - Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner - - This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at <libzip@nih.at> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. The names of the authors may not be used to endorse or promote - products derived from this software without specific prior - written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include <stdlib.h> -#include <string.h> -#include <limits.h> - -#include "zipint.h" - -struct deflate { - zip_error_t error; - - bool eof; - bool can_store; - bool is_stored; - int mem_level; - zip_uint64_t size; - zip_uint8_t buffer[BUFSIZE]; - z_stream zstr; -}; - -static zip_int64_t compress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t); -static zip_int64_t decompress_read(zip_source_t *, struct deflate *, void *, zip_uint64_t); -static zip_int64_t deflate_compress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); -static zip_int64_t deflate_decompress(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); -static void deflate_free(struct deflate *); - - -zip_source_t * -zip_source_deflate(zip_t *za, zip_source_t *src, zip_int32_t cm, int flags) -{ - struct deflate *ctx; - zip_source_t *s2; - - if (src == NULL || (cm != ZIP_CM_DEFLATE && !ZIP_CM_IS_DEFAULT(cm))) { - zip_error_set(&za->error, ZIP_ER_INVAL, 0); - return NULL; - } - - if ((ctx=(struct deflate *)malloc(sizeof(*ctx))) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - return NULL; - } - - zip_error_init(&ctx->error); - ctx->eof = false; - ctx->is_stored = false; - ctx->can_store = ZIP_CM_IS_DEFAULT(cm); - if (flags & ZIP_CODEC_ENCODE) { - ctx->mem_level = MAX_MEM_LEVEL; - } - - if ((s2=zip_source_layered(za, src, - ((flags & ZIP_CODEC_ENCODE) - ? deflate_compress : deflate_decompress), - ctx)) == NULL) { - deflate_free(ctx); - return NULL; - } - - return s2; -} - - -static zip_int64_t -compress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len) -{ - int end, ret; - zip_int64_t n; - zip_uint64_t out_offset; - uInt out_len; - - if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) - return -1; - - if (len == 0 || ctx->is_stored) { - return 0; - } - - out_offset = 0; - out_len = (uInt)ZIP_MIN(UINT_MAX, len); - ctx->zstr.next_out = (Bytef *)data; - ctx->zstr.avail_out = out_len; - - end = 0; - while (!end) { - ret = deflate(&ctx->zstr, ctx->eof ? Z_FINISH : 0); - - switch (ret) { - case Z_STREAM_END: - if (ctx->can_store && ctx->zstr.total_in <= ctx->zstr.total_out) { - ctx->is_stored = true; - ctx->size = ctx->zstr.total_in; - memcpy(data, ctx->buffer, ctx->size); - return (zip_int64_t)ctx->size; - } - /* fallthrough */ - case Z_OK: - /* all ok */ - - if (ctx->zstr.avail_out == 0) { - out_offset += out_len; - if (out_offset < len) { - out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset); - ctx->zstr.next_out = (Bytef *)data+out_offset; - ctx->zstr.avail_out = out_len; - } - else { - ctx->can_store = false; - end = 1; - } - } - else if (ctx->eof && ctx->zstr.avail_in == 0) - end = 1; - break; - - case Z_BUF_ERROR: - if (ctx->zstr.avail_in == 0) { - if (ctx->eof) { - end = 1; - break; - } - - if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { - _zip_error_set_from_source(&ctx->error, src); - end = 1; - break; - } - else if (n == 0) { - ctx->eof = true; - /* TODO: check against stat of src? */ - ctx->size = ctx->zstr.total_in; - } - else { - if (ctx->zstr.total_in > 0) { - /* we overwrote a previously filled ctx->buffer */ - ctx->can_store = false; - } - ctx->zstr.next_in = (Bytef *)ctx->buffer; - ctx->zstr.avail_in = (uInt)n; - } - continue; - } - /* fallthrough */ - case Z_NEED_DICT: - case Z_DATA_ERROR: - case Z_STREAM_ERROR: - case Z_MEM_ERROR: - zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret); - - end = 1; - break; - } - } - - if (ctx->zstr.avail_out < len) { - ctx->can_store = false; - return (zip_int64_t)(len - ctx->zstr.avail_out); - } - - return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1; -} - - -static zip_int64_t -decompress_read(zip_source_t *src, struct deflate *ctx, void *data, zip_uint64_t len) -{ - int end, ret; - zip_int64_t n; - zip_uint64_t out_offset; - uInt out_len; - - if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) - return -1; - - if (len == 0) - return 0; - - out_offset = 0; - out_len = (uInt)ZIP_MIN(UINT_MAX, len); - ctx->zstr.next_out = (Bytef *)data; - ctx->zstr.avail_out = out_len; - - end = 0; - while (!end) { - ret = inflate(&ctx->zstr, Z_SYNC_FLUSH); - - switch (ret) { - case Z_OK: - if (ctx->zstr.avail_out == 0) { - out_offset += out_len; - if (out_offset < len) { - out_len = (uInt)ZIP_MIN(UINT_MAX, len-out_offset); - ctx->zstr.next_out = (Bytef *)data+out_offset; - ctx->zstr.avail_out = out_len; - } - else { - end = 1; - } - } - break; - - case Z_STREAM_END: - ctx->eof = 1; - end = 1; - break; - - case Z_BUF_ERROR: - if (ctx->zstr.avail_in == 0) { - if (ctx->eof) { - end = 1; - break; - } - - if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { - _zip_error_set_from_source(&ctx->error, src); - end = 1; - break; - } - else if (n == 0) { - ctx->eof = 1; - } - else { - ctx->zstr.next_in = (Bytef *)ctx->buffer; - ctx->zstr.avail_in = (uInt)n; - } - continue; - } - /* fallthrough */ - case Z_NEED_DICT: - case Z_DATA_ERROR: - case Z_STREAM_ERROR: - case Z_MEM_ERROR: - zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret); - end = 1; - break; - } - } - - if (ctx->zstr.avail_out < len) - return (zip_int64_t)(len - ctx->zstr.avail_out); - - return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1; -} - - -static zip_int64_t -deflate_compress(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_source_cmd_t cmd) -{ - struct deflate *ctx; - int ret; - - ctx = (struct deflate *)ud; - - switch (cmd) { - case ZIP_SOURCE_OPEN: - ctx->zstr.zalloc = Z_NULL; - ctx->zstr.zfree = Z_NULL; - ctx->zstr.opaque = NULL; - ctx->zstr.avail_in = 0; - ctx->zstr.next_in = NULL; - ctx->zstr.avail_out = 0; - ctx->zstr.next_out = NULL; - - /* negative value to tell zlib not to write a header */ - if ((ret=deflateInit2(&ctx->zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, ctx->mem_level, Z_DEFAULT_STRATEGY)) != Z_OK) { - zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret); - return -1; - } - - return 0; - - case ZIP_SOURCE_READ: - return compress_read(src, ctx, data, len); - - case ZIP_SOURCE_CLOSE: - deflateEnd(&ctx->zstr); - return 0; - - case ZIP_SOURCE_STAT: - { - zip_stat_t *st; - - st = (zip_stat_t *)data; - - st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_DEFLATE; - st->valid |= ZIP_STAT_COMP_METHOD; - if (ctx->eof) { - st->comp_size = ctx->size; - st->valid |= ZIP_STAT_COMP_SIZE; - } - else - st->valid &= ~ZIP_STAT_COMP_SIZE; - } - return 0; - - case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, len); - - case ZIP_SOURCE_FREE: - deflate_free(ctx); - return 0; - - case ZIP_SOURCE_SUPPORTS: - return ZIP_SOURCE_SUPPORTS_READABLE; - - default: - zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); - return -1; - } -} - - -static zip_int64_t -deflate_decompress(zip_source_t *src, void *ud, void *data, - zip_uint64_t len, zip_source_cmd_t cmd) -{ - struct deflate *ctx; - zip_int64_t n; - int ret; - - ctx = (struct deflate *)ud; - - switch (cmd) { - case ZIP_SOURCE_OPEN: - if ((n=zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; - } - - ctx->zstr.zalloc = Z_NULL; - ctx->zstr.zfree = Z_NULL; - ctx->zstr.opaque = NULL; - ctx->zstr.next_in = (Bytef *)ctx->buffer; - ctx->zstr.avail_in = (uInt)n; - - /* negative value to tell zlib that there is no header */ - if ((ret=inflateInit2(&ctx->zstr, -MAX_WBITS)) != Z_OK) { - zip_error_set(&ctx->error, ZIP_ER_ZLIB, ret); - return -1; - } - return 0; - - case ZIP_SOURCE_READ: - return decompress_read(src, ctx, data, len); - - case ZIP_SOURCE_CLOSE: - inflateEnd(&ctx->zstr); - return 0; - - case ZIP_SOURCE_STAT: - { - zip_stat_t *st; - - st = (zip_stat_t *)data; - - st->comp_method = ZIP_CM_STORE; - if (st->comp_size > 0 && st->size > 0) - st->comp_size = st->size; - - return 0; - } - - case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, len); - - case ZIP_SOURCE_FREE: - free(ctx); - return 0; - - case ZIP_SOURCE_SUPPORTS: - return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); - - default: - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; - } -} - - -static void -deflate_free(struct deflate *ctx) -{ - free(ctx); -} diff --git a/src/Common/libzip/zip_source_file.c b/src/Common/libzip/zip_source_file.c deleted file mode 100644 index 3fff4e3b..00000000 --- a/src/Common/libzip/zip_source_file.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - zip_source_file.c -- create data source from file - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner - - This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at <libzip@nih.at> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. The names of the authors may not be used to endorse or promote - products derived from this software without specific prior - written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include <stdio.h> - -#include "zipint.h" - -#ifdef _WIN32 -#error This file is incompatible with Windows, use zip_source_win32utf8.c instead. -#error Something probably went wrong with configure/cmake. -#endif - -ZIP_EXTERN zip_source_t * -zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) { - if (za == NULL) - return NULL; - - return zip_source_file_create(fname, start, len, &za->error); -} - - -ZIP_EXTERN zip_source_t * -zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { - if (fname == NULL || length < -1) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } - - return _zip_source_file_or_p(fname, NULL, start, length, NULL, error); -} diff --git a/src/Common/libzip/zip_source_file.h b/src/Common/libzip/zip_source_file.h new file mode 100644 index 00000000..43a46453 --- /dev/null +++ b/src/Common/libzip/zip_source_file.h @@ -0,0 +1,90 @@ +/* + zip_source_file.h -- header for common file operations + Copyright (C) 2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +struct zip_source_file_stat { + zip_uint64_t size; /* must be valid for regular files */ + time_t mtime; /* must always be valid, is initialized to current time */ + bool exists; /* must always be vaild */ + bool regular_file; /* must always be valid */ +}; + +typedef struct zip_source_file_context zip_source_file_context_t; +typedef struct zip_source_file_operations zip_source_file_operations_t; +typedef struct zip_source_file_stat zip_source_file_stat_t; + +struct zip_source_file_context { + zip_error_t error; /* last error information */ + zip_int64_t supports; + + /* reading */ + char *fname; /* name of file to read from */ + void *f; /* file to read from */ + zip_stat_t st; /* stat information passed in */ + zip_file_attributes_t attributes; /* additional file attributes */ + zip_error_t stat_error; /* error returned for stat */ + zip_uint64_t start; /* start offset of data to read */ + zip_uint64_t len; /* length of the file, 0 for up to EOF */ + zip_uint64_t offset; /* current offset relative to start (0 is beginning of part we read) */ + + /* writing */ + char *tmpname; + void *fout; + + zip_source_file_operations_t *ops; + void *ops_userdata; +}; + + +/* The following methods must be implemented to support each feature: + - close, read, seek, and stat must always be implemented. + - To support specifying the file by name, open, and strdup must be implemented. + - For write support, the file must be specified by name and close, commit_write, create_temp_output, remove, rollback_write, and tell must be implemented. + - create_temp_output_cloning is always optional. */ + +struct zip_source_file_operations { + void (*close)(zip_source_file_context_t *ctx); + zip_int64_t (*commit_write)(zip_source_file_context_t *ctx); + zip_int64_t (*create_temp_output)(zip_source_file_context_t *ctx); + zip_int64_t (*create_temp_output_cloning)(zip_source_file_context_t *ctx, zip_uint64_t len); + bool (*open)(zip_source_file_context_t *ctx); + zip_int64_t (*read)(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len); + zip_int64_t (*remove)(zip_source_file_context_t *ctx); + void (*rollback_write)(zip_source_file_context_t *ctx); + bool (*seek)(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence); + bool (*stat)(zip_source_file_context_t *ctx, zip_source_file_stat_t *st); + char *(*string_duplicate)(zip_source_file_context_t *ctx, const char *); + zip_int64_t (*tell)(zip_source_file_context_t *ctx, void *f); + zip_int64_t (*write)(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len); +}; + +zip_source_t *zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_source_file_operations_t *ops, void *ops_userdata, zip_error_t *error); diff --git a/src/Common/libzip/zip_source_file_common.c b/src/Common/libzip/zip_source_file_common.c new file mode 100644 index 00000000..74e21009 --- /dev/null +++ b/src/Common/libzip/zip_source_file_common.c @@ -0,0 +1,378 @@ +/* + zip_source_file_common.c -- create data source from file + Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + +#include "zip_source_file.h" + +static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd); + +static void +zip_source_file_stat_init(zip_source_file_stat_t *st) { + st->size = 0; + st->mtime = time(NULL); + st->exists = false; + st->regular_file = false; +} + +zip_source_t * +zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_source_file_operations_t *ops, void *ops_userdata, zip_error_t *error) { + zip_source_file_context_t *ctx; + zip_source_t *zs; + zip_source_file_stat_t sb; + + if (ops == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (ops->close == NULL || ops->read == NULL || ops->seek == NULL || ops->stat == NULL) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + + if (ops->write != NULL && (ops->commit_write == NULL || ops->create_temp_output == NULL || ops->remove == NULL || ops->rollback_write == NULL || ops->tell == NULL)) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + + if (fname != NULL) { + if (ops->open == NULL || ops->string_duplicate == NULL) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + } + else if (file == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if (len < 0) { + len = 0; + } + + if (start > ZIP_INT64_MAX || start + (zip_uint64_t)len < start) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + if ((ctx = (zip_source_file_context_t *)malloc(sizeof(zip_source_file_context_t))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + ctx->ops = ops; + ctx->ops_userdata = ops_userdata; + ctx->fname = NULL; + if (fname) { + if ((ctx->fname = ops->string_duplicate(ctx, fname)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; + } + } + ctx->f = file; + ctx->start = start; + ctx->len = (zip_uint64_t)len; + if (st) { + memcpy(&ctx->st, st, sizeof(ctx->st)); + ctx->st.name = NULL; + ctx->st.valid &= ~ZIP_STAT_NAME; + } + else { + zip_stat_init(&ctx->st); + } + + if (ctx->len > 0) { + ctx->st.size = ctx->len; + ctx->st.valid |= ZIP_STAT_SIZE; + } + + zip_error_init(&ctx->stat_error); + + ctx->tmpname = NULL; + ctx->fout = NULL; + + zip_error_init(&ctx->error); + zip_file_attributes_init(&ctx->attributes); + + ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1); + + zip_source_file_stat_init(&sb); + if (!ops->stat(ctx, &sb)) { + _zip_error_copy(error, &ctx->error); + free(ctx->fname); + free(ctx); + return NULL; + } + + if (!sb.exists) { + if (ctx->fname && ctx->start == 0 && ctx->len == 0 && ops->write != NULL) { + ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + /* zip_open_from_source checks for this to detect non-existing files */ + zip_error_set(&ctx->stat_error, ZIP_ER_READ, ENOENT); + } + else { + zip_error_set(&ctx->stat_error, ZIP_ER_READ, ENOENT); + free(ctx->fname); + free(ctx); + return NULL; + } + } + else { + if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) { + ctx->st.mtime = sb.mtime; + ctx->st.valid |= ZIP_STAT_MTIME; + } + if (sb.regular_file) { + ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE; + + if (ctx->start + ctx->len > sb.size) { + zip_error_set(error, ZIP_ER_INVAL, 0); + free(ctx->fname); + free(ctx); + return NULL; + } + + if (ctx->len == 0) { + ctx->len = sb.size - ctx->start; + ctx->st.size = ctx->len; + ctx->st.valid |= ZIP_STAT_SIZE; + + /* when using a partial file, don't allow writing */ + if (ctx->fname && start == 0 && ops->write != NULL) { + ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; + } + } + } + + ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES); + } + + ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY); + if (ops->create_temp_output_cloning != NULL) { + if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) { + ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING); + } + } + + if ((zs = zip_source_function_create(read_file, ctx, error)) == NULL) { + free(ctx->fname); + free(ctx); + return NULL; + } + + return zs; +} + + +static zip_int64_t +read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { + zip_source_file_context_t *ctx; + char *buf; + + ctx = (zip_source_file_context_t *)state; + buf = (char *)data; + + switch (cmd) { + case ZIP_SOURCE_ACCEPT_EMPTY: + return 0; + + case ZIP_SOURCE_BEGIN_WRITE: + /* write support should not be set if fname is NULL */ + if (ctx->fname == NULL) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; + } + return ctx->ops->create_temp_output(ctx); + + case ZIP_SOURCE_BEGIN_WRITE_CLONING: + /* write support should not be set if fname is NULL */ + if (ctx->fname == NULL) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + return -1; + } + return ctx->ops->create_temp_output_cloning(ctx, len); + + case ZIP_SOURCE_CLOSE: + if (ctx->fname) { + ctx->ops->close(ctx); + ctx->f = NULL; + } + return 0; + + case ZIP_SOURCE_COMMIT_WRITE: { + zip_int64_t ret = ctx->ops->commit_write(ctx); + ctx->fout = NULL; + if (ret == 0) { + free(ctx->tmpname); + ctx->tmpname = NULL; + } + return ret; + } + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, len); + + case ZIP_SOURCE_FREE: + free(ctx->fname); + free(ctx->tmpname); + if (ctx->f) { + ctx->ops->close(ctx); + } + free(ctx); + return 0; + + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: + if (len < sizeof(ctx->attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + memcpy(data, &ctx->attributes, sizeof(ctx->attributes)); + return sizeof(ctx->attributes); + + case ZIP_SOURCE_OPEN: + if (ctx->fname) { + if (ctx->ops->open(ctx) == false) { + return -1; + } + } + + if (ctx->start > 0) { // TODO: rewind on re-open + if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)ctx->start, SEEK_SET) == false) { + /* TODO: skip by reading */ + return -1; + } + } + ctx->offset = 0; + return 0; + + case ZIP_SOURCE_READ: { + zip_int64_t i; + zip_uint64_t n; + + if (ctx->len > 0) { + n = ZIP_MIN(ctx->len - ctx->offset, len); + } + else { + n = len; + } + + if ((i = ctx->ops->read(ctx, buf, n)) < 0) { + zip_error_set(&ctx->error, ZIP_ER_READ, errno); + return -1; + } + ctx->offset += (zip_uint64_t)i; + + return i; + } + + case ZIP_SOURCE_REMOVE: + return ctx->ops->remove(ctx); + + case ZIP_SOURCE_ROLLBACK_WRITE: + ctx->ops->rollback_write(ctx); + ctx->fout = NULL; + free(ctx->tmpname); + ctx->tmpname = NULL; + return 0; + + case ZIP_SOURCE_SEEK: { + zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error); + + if (new_offset < 0) { + return -1; + } + + /* The actual offset inside the file must be representable as zip_int64_t. */ + if (new_offset > ZIP_INT64_MAX - (zip_int64_t)ctx->start) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW); + return -1; + } + + ctx->offset = (zip_uint64_t)new_offset; + + if (ctx->ops->seek(ctx, ctx->f, (zip_int64_t)(ctx->offset + ctx->start), SEEK_SET) == false) { + return -1; + } + return 0; + } + + case ZIP_SOURCE_SEEK_WRITE: { + zip_source_args_seek_t *args; + + args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); + if (args == NULL) { + return -1; + } + + if (ctx->ops->seek(ctx, ctx->fout, args->offset, args->whence) == false) { + return -1; + } + return 0; + } + + case ZIP_SOURCE_STAT: { + if (len < sizeof(ctx->st)) + return -1; + + if (zip_error_code_zip(&ctx->stat_error) != 0) { + zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error)); + return -1; + } + + memcpy(data, &ctx->st, sizeof(ctx->st)); + return sizeof(ctx->st); + } + + case ZIP_SOURCE_SUPPORTS: + return ctx->supports; + + case ZIP_SOURCE_TELL: + return (zip_int64_t)ctx->offset; + + case ZIP_SOURCE_TELL_WRITE: + return ctx->ops->tell(ctx, ctx->fout); + + case ZIP_SOURCE_WRITE: + return ctx->ops->write(ctx, data, len); + + default: + zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); + return -1; + } +} diff --git a/src/Common/libzip/zip_source_file_stdio.c b/src/Common/libzip/zip_source_file_stdio.c new file mode 100644 index 00000000..4a22f78c --- /dev/null +++ b/src/Common/libzip/zip_source_file_stdio.c @@ -0,0 +1,208 @@ +/* + zip_source_file_stdio.c -- read-only stdio file source implementation + Copyright (C) 2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +#include "zip_source_file.h" +#include "zip_source_file_stdio.h" + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> + +#ifdef _WIN32 +#ifndef S_IWUSR +#define S_IWUSR _S_IWRITE +#endif +#endif + +/* clang-format off */ +static zip_source_file_operations_t ops_stdio_read = { + _zip_stdio_op_close, + NULL, + NULL, + NULL, + NULL, + _zip_stdio_op_read, + NULL, + NULL, + _zip_stdio_op_seek, + _zip_stdio_op_stat, + NULL, + _zip_stdio_op_tell, + NULL +}; +/* clang-format on */ + + +ZIP_EXTERN zip_source_t * +zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) { + if (za == NULL) { + return NULL; + } + + return zip_source_filep_create(file, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { + if (file == NULL || length < -1) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + return zip_source_file_common_new(NULL, file, start, length, NULL, &ops_stdio_read, NULL, error); +} + + +void +_zip_stdio_op_close(zip_source_file_context_t *ctx) { + fclose((FILE *)ctx->f); +} + + +zip_int64_t +_zip_stdio_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len) { + size_t i; + if (len > SIZE_MAX) { + len = SIZE_MAX; + } + + if ((i = fread(buf, 1, (size_t)len, ctx->f)) == 0) { + if (ferror((FILE *)ctx->f)) { + zip_error_set(&ctx->error, ZIP_ER_READ, errno); + return -1; + } + } + + return (zip_int64_t)i; +} + + +bool +_zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence) { +#if ZIP_FSEEK_MAX > ZIP_INT64_MAX + if (offset > ZIP_FSEEK_MAX || offset < ZIP_FSEEK_MIN) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, EOVERFLOW); + return false; + } +#endif + + if (fseeko((FILE *)f, (off_t)offset, whence) < 0) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + return false; + } + return true; +} + + +bool +_zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) { + struct stat sb; + + int ret; + + if (ctx->fname) { + ret = stat(ctx->fname, &sb); + } + else { + ret = fstat(fileno((FILE *)ctx->f), &sb); + } + + if (ret < 0) { + if (errno == ENOENT) { + st->exists = false; + return true; + } + zip_error_set(&ctx->error, ZIP_ER_READ, errno); + return false; + } + + st->size = (zip_uint64_t)sb.st_size; + st->mtime = sb.st_mtime; + + st->regular_file = S_ISREG(sb.st_mode); + st->exists = true; + + /* We're using UNIX file API, even on Windows; thus, we supply external file attributes with Unix values. */ + /* TODO: This could be improved on Windows by providing Windows-specific file attributes */ + ctx->attributes.valid = ZIP_FILE_ATTRIBUTES_HOST_SYSTEM | ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES; + ctx->attributes.host_system = ZIP_OPSYS_UNIX; + ctx->attributes.external_file_attributes = (((zip_uint32_t)sb.st_mode) << 16) | ((sb.st_mode & S_IWUSR) ? 0 : 1); + + return true; +} + + +zip_int64_t +_zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f) { + off_t offset = ftello((FILE *)f); + + if (offset < 0) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); + } + + return offset; +} + + +/* + * fopen replacement that sets the close-on-exec flag + * some implementations support an fopen 'e' flag for that, + * but e.g. macOS doesn't. + */ +FILE * +_zip_fopen_close_on_exec(const char *name, bool writeable) { + int fd; + int flags; + FILE *fp; + + flags = O_CLOEXEC; + if (writeable) { + flags |= O_RDWR; + } + else { + flags |= O_RDONLY; + } + + /* mode argument needed on Windows */ + if ((fd = open(name, flags, 0666)) < 0) { + return NULL; + } + if ((fp = fdopen(fd, writeable ? "r+b" : "rb")) == NULL) { + return NULL; + } + return fp; +} diff --git a/src/Common/libzip/zip_source_get_compression_flags.c b/src/Common/libzip/zip_source_file_stdio.h index 7e04bed6..1bf698ce 100644 --- a/src/Common/libzip/zip_source_get_compression_flags.c +++ b/src/Common/libzip/zip_source_file_stdio.h @@ -1,6 +1,9 @@ +#ifndef _HAD_ZIP_SOURCE_FILE_STDIO_H +#define _HAD_ZIP_SOURCE_FILE_STDIO_H + /* - zip_source_get_compression_flags.c -- get compression flags for entry - Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner + zip_source_file_stdio.h -- common header for stdio file implementation + Copyright (C) 2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -31,27 +34,14 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <stdio.h> + +void _zip_stdio_op_close(zip_source_file_context_t *ctx); +zip_int64_t _zip_stdio_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len); +bool _zip_stdio_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence); +bool _zip_stdio_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st); +zip_int64_t _zip_stdio_op_tell(zip_source_file_context_t *ctx, void *f); + +FILE *_zip_fopen_close_on_exec(const char *name, bool writeable); -#include "zipint.h" - -#define ZIP_COMPRESSION_BITFLAG_MAX 3 - -zip_int8_t -zip_source_get_compression_flags(zip_source_t *src) { - while (src) { - if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_COMPRESSION_FLAGS))) { - zip_int64_t ret = _zip_source_call(src, NULL, 0, ZIP_SOURCE_GET_COMPRESSION_FLAGS); - if (ret < 0) { - return -1; - } - if (ret > ZIP_COMPRESSION_BITFLAG_MAX) { - zip_error_set(&src->error, ZIP_ER_INTERNAL, 0); - return -1; - } - return (zip_int8_t)ret; - } - src = src->src; - } - - return 0; -} +#endif /* _HAD_ZIP_SOURCE_FILE_STDIO_H */ diff --git a/src/Common/libzip/zip_source_file_win32.c b/src/Common/libzip/zip_source_file_win32.c new file mode 100644 index 00000000..2fe838f1 --- /dev/null +++ b/src/Common/libzip/zip_source_file_win32.c @@ -0,0 +1,230 @@ +/* + zip_source_file_win32.c -- read-only Windows file source implementation + Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zip_source_file_win32.h" + +static bool _zip_win32_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st); + +static bool _zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HANDLE h); + +static zip_source_file_operations_t ops_win32_read = { + _zip_win32_op_close, + NULL, + NULL, + NULL, + NULL, + _zip_win32_op_read, + NULL, + NULL, + _zip_win32_op_seek, + _zip_win32_op_stat, + NULL, + _zip_win32_op_tell, + NULL +}; + + +ZIP_EXTERN zip_source_t * +zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len) { + if (za == NULL) { + return NULL; + } + + return zip_source_win32handle_create(h, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_win32handle_create(HANDLE h, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { + if (h == INVALID_HANDLE_VALUE || length < -1) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + return zip_source_file_common_new(NULL, h, start, length, NULL, &ops_win32_read, NULL, error); +} + + +void +_zip_win32_op_close(zip_source_file_context_t *ctx) { + CloseHandle((HANDLE)ctx->f); +} + + +zip_int64_t +_zip_win32_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len) { + DWORD i; + + /* TODO: cap len to "DWORD_MAX" */ + if (!ReadFile((HANDLE)ctx->f, buf, (DWORD)len, &i, NULL)) { + zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + return (zip_int64_t)i; +} + + +bool +_zip_win32_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence) { + LARGE_INTEGER li; + DWORD method; + + switch (whence) { + case SEEK_SET: + method = FILE_BEGIN; + break; + case SEEK_END: + method = FILE_END; + break; + case SEEK_CUR: + method = FILE_CURRENT; + break; + default: + zip_error_set(&ctx->error, ZIP_ER_SEEK, EINVAL); + return -1; + } + + li.QuadPart = (LONGLONG)offset; + if (!SetFilePointerEx((HANDLE)f, li, NULL, method)) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError())); + return false; + } + + return true; +} + + +static bool +_zip_win32_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) { + return _zip_stat_win32(ctx, st, (HANDLE)ctx->f); +} + + +zip_int64_t +_zip_win32_op_tell(zip_source_file_context_t *ctx, void *f) { + LARGE_INTEGER zero; + LARGE_INTEGER new_offset; + + zero.QuadPart = 0; + if (!SetFilePointerEx((HANDLE)f, zero, &new_offset, FILE_CURRENT)) { + zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + return (zip_int64_t)new_offset.QuadPart; +} + + +int +_zip_win32_error_to_errno(DWORD win32err) { + /* Note: This list isn't exhaustive, but should cover common cases. */ + switch (win32err) { + case ERROR_INVALID_PARAMETER: + return EINVAL; + case ERROR_FILE_NOT_FOUND: + return ENOENT; + case ERROR_INVALID_HANDLE: + return EBADF; + case ERROR_ACCESS_DENIED: + return EACCES; + case ERROR_FILE_EXISTS: + return EEXIST; + case ERROR_TOO_MANY_OPEN_FILES: + return EMFILE; + case ERROR_DISK_FULL: + return ENOSPC; + default: + return 10000 + win32err; + } +} + + +static bool +_zip_stat_win32(zip_source_file_context_t *ctx, zip_source_file_stat_t *st, HANDLE h) { + FILETIME mtimeft; + time_t mtime; + LARGE_INTEGER size; + + if (!GetFileTime(h, NULL, NULL, &mtimeft)) { + zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); + return false; + } + if (_zip_filetime_to_time_t(mtimeft, &mtime) < 0) { + zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE); + return false; + } + + st->exists = true; + st->mtime = mtime; + + if (GetFileType(h) == FILE_TYPE_DISK) { + st->regular_file = 1; + + if (!GetFileSizeEx(h, &size)) { + zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); + return false; + } + + st->size = (zip_uint64_t)size.QuadPart; + } + + /* TODO: fill in ctx->attributes */ + + return true; +} + + +bool +_zip_filetime_to_time_t(FILETIME ft, time_t *t) { + /* + Inspired by http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux + */ + const zip_int64_t WINDOWS_TICK = 10000000LL; + const zip_int64_t SEC_TO_UNIX_EPOCH = 11644473600LL; + ULARGE_INTEGER li; + zip_int64_t secs; + time_t temp; + + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + secs = (li.QuadPart / WINDOWS_TICK - SEC_TO_UNIX_EPOCH); + + temp = (time_t)secs; + if (secs != (zip_int64_t)temp) { + return false; + } + + *t = temp; + return true; +} diff --git a/src/Common/libzip/zip_source_file_win32.h b/src/Common/libzip/zip_source_file_win32.h new file mode 100644 index 00000000..5092e630 --- /dev/null +++ b/src/Common/libzip/zip_source_file_win32.h @@ -0,0 +1,74 @@ +#ifndef _HAD_ZIP_SOURCE_FILE_WIN32_H +#define _HAD_ZIP_SOURCE_FILE_WIN32_H + +/* + zip_source_file_win32.h -- common header for Windows file implementation + Copyright (C) 2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* 0x0501 => Windows XP; needs to be at least this value because of GetFileSizeEx */ +#if !defined(MS_UWP) && !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0501 +#endif + +#include <windows.h> + +#include <aclapi.h> + +#include "zipint.h" + +#include "zip_source_file.h" + +struct zip_win32_file_operations { + char *(*allocate_tempname)(const char *name, size_t extra_chars, size_t *lengthp); + HANDLE (__stdcall *create_file)(const void *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file); + BOOL (__stdcall *delete_file)(const void *name); + DWORD (__stdcall *get_file_attributes)(const void *name); + BOOL (__stdcall *get_file_attributes_ex)(const void *name, GET_FILEEX_INFO_LEVELS info_level, void *information); + void (*make_tempname)(char *buf, size_t len, const char *name, zip_uint32_t i); + BOOL (__stdcall *move_file)(const void *from, const void *to, DWORD flags); + BOOL (__stdcall *set_file_attributes)(const void *name, DWORD attributes); + char *(*string_duplicate)(const char *string); +}; + +typedef struct zip_win32_file_operations zip_win32_file_operations_t; + +extern zip_source_file_operations_t _zip_source_file_win32_named_ops; + +void _zip_win32_op_close(zip_source_file_context_t *ctx); +zip_int64_t _zip_win32_op_read(zip_source_file_context_t *ctx, void *buf, zip_uint64_t len); +bool _zip_win32_op_seek(zip_source_file_context_t *ctx, void *f, zip_int64_t offset, int whence); +zip_int64_t _zip_win32_op_tell(zip_source_file_context_t *ctx, void *f); + +bool _zip_filetime_to_time_t(FILETIME ft, time_t *t); +int _zip_win32_error_to_errno(DWORD win32err); + +#endif /* _HAD_ZIP_SOURCE_FILE_WIN32_H */ diff --git a/src/Common/libzip/zip_source_file_win32_named.c b/src/Common/libzip/zip_source_file_win32_named.c new file mode 100644 index 00000000..63791f8e --- /dev/null +++ b/src/Common/libzip/zip_source_file_win32_named.c @@ -0,0 +1,268 @@ +/* + zip_source_file_win32_named.c -- source for Windows file opened by name + Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zip_source_file_win32.h" + +static zip_int64_t _zip_win32_named_op_commit_write(zip_source_file_context_t *ctx); +static zip_int64_t _zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx); +static bool _zip_win32_named_op_open(zip_source_file_context_t *ctx); +static zip_int64_t _zip_win32_named_op_remove(zip_source_file_context_t *ctx); +static void _zip_win32_named_op_rollback_write(zip_source_file_context_t *ctx); +static bool _zip_win32_named_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st); +static char *_zip_win32_named_op_string_duplicate(zip_source_file_context_t *ctx, const char *string); +static zip_int64_t _zip_win32_named_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len); + +static HANDLE win32_named_open(zip_source_file_context_t *ctx, const char *name, bool temporary, PSECURITY_ATTRIBUTES security_attributes); + +/* clang-format off */ +zip_source_file_operations_t _zip_source_file_win32_named_ops = { + _zip_win32_op_close, + _zip_win32_named_op_commit_write, + _zip_win32_named_op_create_temp_output, + NULL, + _zip_win32_named_op_open, + _zip_win32_op_read, + _zip_win32_named_op_remove, + _zip_win32_named_op_rollback_write, + _zip_win32_op_seek, + _zip_win32_named_op_stat, + _zip_win32_named_op_string_duplicate, + _zip_win32_op_tell, + _zip_win32_named_op_write +}; +/* clang-format on */ + +static zip_int64_t +_zip_win32_named_op_commit_write(zip_source_file_context_t *ctx) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + DWORD attributes; + + if (!CloseHandle((HANDLE)ctx->fout)) { + zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + attributes = file_ops->get_file_attributes(ctx->tmpname); + if (attributes == INVALID_FILE_ATTRIBUTES) { + zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + if (attributes & FILE_ATTRIBUTE_TEMPORARY) { + if (!file_ops->set_file_attributes(ctx->tmpname, attributes & ~FILE_ATTRIBUTE_TEMPORARY)) { + zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + } + + if (!file_ops->move_file(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING)) { + zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + return 0; +} + +static zip_int64_t +_zip_win32_named_op_create_temp_output(zip_source_file_context_t *ctx) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + zip_uint32_t value, i; + HANDLE th = INVALID_HANDLE_VALUE; + void *temp = NULL; + PSECURITY_DESCRIPTOR psd = NULL; + PSECURITY_ATTRIBUTES psa = NULL; + SECURITY_ATTRIBUTES sa; + SECURITY_INFORMATION si; + DWORD success; + PACL dacl = NULL; + char *tempname = NULL; + size_t tempname_size = 0; + + if ((HANDLE)ctx->f != INVALID_HANDLE_VALUE && GetFileType((HANDLE)ctx->f) == FILE_TYPE_DISK) { + si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION; + success = GetSecurityInfo((HANDLE)ctx->f, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd); + if (success == ERROR_SUCCESS) { + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = FALSE; + sa.lpSecurityDescriptor = psd; + psa = &sa; + } + } + + #ifndef MS_UWP + value = GetTickCount(); +#else + value = (zip_uint32_t)(GetTickCount64() & 0xffffffff); +#endif + + if ((tempname = file_ops->allocate_tempname(ctx->fname, 10, &tempname_size)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + + for (i = 0; i < 1024 && th == INVALID_HANDLE_VALUE; i++) { + file_ops->make_tempname(tempname, tempname_size, ctx->fname, value + i); + + th = win32_named_open(ctx, tempname, true, psa); + if (th == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_EXISTS) + break; + } + + if (th == INVALID_HANDLE_VALUE) { + free(tempname); + LocalFree(psd); + zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + LocalFree(psd); + ctx->fout = th; + ctx->tmpname = tempname; + + return 0; +} + + +static bool +_zip_win32_named_op_open(zip_source_file_context_t *ctx) { + HANDLE h = win32_named_open(ctx, ctx->fname, false, NULL); + + if (h == INVALID_HANDLE_VALUE) { + return false; + } + + ctx->f = h; + return true; +} + + +static zip_int64_t +_zip_win32_named_op_remove(zip_source_file_context_t *ctx) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + if (!file_ops->delete_file(ctx->fname)) { + zip_error_set(&ctx->error, ZIP_ER_REMOVE, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + return 0; +} + + +static void +_zip_win32_named_op_rollback_write(zip_source_file_context_t *ctx) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + if (ctx->fout) { + CloseHandle((HANDLE)ctx->fout); + } + file_ops->delete_file(ctx->tmpname); +} + + +static bool +_zip_win32_named_op_stat(zip_source_file_context_t *ctx, zip_source_file_stat_t *st) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + WIN32_FILE_ATTRIBUTE_DATA file_attributes; + + if (!file_ops->get_file_attributes_ex(ctx->fname, GetFileExInfoStandard, &file_attributes)) { + DWORD error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND) { + st->exists = false; + return true; + } + zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(error)); + return false; + } + + st->exists = true; + st->regular_file = true; /* TODO: Is this always right? How to determine without a HANDLE? */ + if (!_zip_filetime_to_time_t(file_attributes.ftLastWriteTime, &st->mtime)) { + zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE); + return false; + } + st->size = ((zip_uint64_t)file_attributes.nFileSizeHigh << 32) | file_attributes.nFileSizeLow; + + /* TODO: fill in ctx->attributes */ + + return true; +} + + +static char * +_zip_win32_named_op_string_duplicate(zip_source_file_context_t *ctx, const char *string) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + return file_ops->string_duplicate(string); +} + + +static zip_int64_t +_zip_win32_named_op_write(zip_source_file_context_t *ctx, const void *data, zip_uint64_t len) { + DWORD ret; + if (!WriteFile((HANDLE)ctx->fout, data, (DWORD)len, &ret, NULL) || ret != len) { + zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError())); + return -1; + } + + return (zip_int64_t)ret; +} + + +static HANDLE +win32_named_open(zip_source_file_context_t *ctx, const char *name, bool temporary, PSECURITY_ATTRIBUTES security_attributes) { + zip_win32_file_operations_t *file_ops = (zip_win32_file_operations_t *)ctx->ops_userdata; + + DWORD access = GENERIC_READ; + DWORD share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE; + DWORD creation_disposition = OPEN_EXISTING; + DWORD file_attributes = FILE_ATTRIBUTE_NORMAL; + HANDLE h; + + if (temporary) { + access = GENERIC_READ | GENERIC_WRITE; + share_mode = FILE_SHARE_READ; + creation_disposition = CREATE_NEW; + file_attributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY; + } + + h = file_ops->create_file(name, access, share_mode, security_attributes, creation_disposition, file_attributes, NULL); + + if (h == INVALID_HANDLE_VALUE) { + zip_error_set(&ctx->error, ZIP_ER_OPEN, _zip_win32_error_to_errno(GetLastError())); + } + + return h; +} diff --git a/src/Common/libzip/zip_source_file_win32_utf16.c b/src/Common/libzip/zip_source_file_win32_utf16.c new file mode 100644 index 00000000..83786483 --- /dev/null +++ b/src/Common/libzip/zip_source_file_win32_utf16.c @@ -0,0 +1,117 @@ +/* + zip_source_file_win32_utf16.c -- source for Windows file opened by UTF-16 name + Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zip_source_file_win32.h" + +#define RtlGenRandom SystemFunction036 +BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); + +bool zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) +{ + return RtlGenRandom (buffer, (ULONG) length); +} + + +static char *utf16_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp); +static HANDLE __stdcall utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file); +static void utf16_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i); +static char *utf16_strdup(const char *string); + +zip_win32_file_operations_t ops_utf16 = { + utf16_allocate_tempname, + utf16_create_file, + DeleteFileW, + GetFileAttributesW, + GetFileAttributesExW, + utf16_make_tempname, + MoveFileExW, + SetFileAttributesW, + utf16_strdup +}; + +ZIP_EXTERN zip_source_t * +zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64_t len) { + if (za == NULL) + return NULL; + + return zip_source_win32w_create(fname, start, len, &za->error); +} + + +ZIP_EXTERN zip_source_t * +zip_source_win32w_create(const wchar_t *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { + if (fname == NULL || length < -1) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; + } + + + return zip_source_file_common_new((const char *)fname, NULL, start, length, NULL, &_zip_source_file_win32_named_ops, &ops_utf16, error); +} + + +static char * +utf16_allocate_tempname(const char *name, size_t extra_chars, size_t *lengthp) { + *lengthp = wcslen((const wchar_t *)name) + extra_chars; + return (char *)malloc(*lengthp * sizeof(wchar_t)); +} + + +static HANDLE __stdcall +utf16_create_file(const char *name, DWORD access, DWORD share_mode, PSECURITY_ATTRIBUTES security_attributes, DWORD creation_disposition, DWORD file_attributes, HANDLE template_file) { +#ifdef MS_UWP + CREATEFILE2_EXTENDED_PARAMETERS extParams = {0}; + extParams.dwFileAttributes = file_attributes; + extParams.dwFileFlags = FILE_FLAG_RANDOM_ACCESS; + extParams.dwSecurityQosFlags = SECURITY_ANONYMOUS; + extParams.dwSize = sizeof(extParams); + extParams.hTemplateFile = template_file; + extParams.lpSecurityAttributes = security_attributes; + + return CreateFile2((const wchar_t *)name, access, share_mode, creation_disposition, &extParams); +#else + return CreateFileW((const wchar_t *)name, access, share_mode, security_attributes, creation_disposition, file_attributes, template_file); +#endif +} + + +static void +utf16_make_tempname(char *buf, size_t len, const char *name, zip_uint32_t i) { + _snwprintf((wchar_t *)buf, len, L"%s.%08x", (const wchar_t *)name, i); +} + + +static char * +utf16_strdup(const char *string) { + return (char *)_wcsdup((const wchar_t *)string); +} diff --git a/src/Common/libzip/zip_source_win32utf8.c b/src/Common/libzip/zip_source_file_win32_utf8.c index 083f5bcb..4f258bc4 100644 --- a/src/Common/libzip/zip_source_win32utf8.c +++ b/src/Common/libzip/zip_source_file_win32_utf8.c @@ -1,6 +1,6 @@ /* - zip_source_win32utf8.c -- create data source from Windows file (UTF-8) - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner + zip_source_file_win32_ansi.c -- source for Windows file opened by UTF-8 name + Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -31,23 +31,14 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* 0x0501 => Windows XP; needs to be at least this value because of GetFileSizeEx */ -#if !defined(MS_UWP) && !defined(_WIN32_WINNT) -#define _WIN32_WINNT 0x0501 -#endif -#include <windows.h> - -#include <stdlib.h> - -#include "zipint.h" -#include "zipwin32.h" - +#include "zip_source_file_win32.h" ZIP_EXTERN zip_source_t * zip_source_file(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) { - if (za == NULL) - return NULL; - + if (za == NULL) { + return NULL; + } + return zip_source_file_create(fname, start, len, &za->error); } @@ -59,24 +50,24 @@ zip_source_file_create(const char *fname, zip_uint64_t start, zip_int64_t length zip_source_t *source; if (fname == NULL || length < -1) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } /* Convert fname from UTF-8 to Windows-friendly UTF-16. */ size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, NULL, 0); if (size == 0) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; + zip_error_set(error, ZIP_ER_INVAL, 0); + return NULL; } if ((wfname = (wchar_t *)malloc(sizeof(wchar_t) * size)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; } MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fname, -1, wfname, size); source = zip_source_win32w_create(wfname, start, length, error); - + free(wfname); return source; } diff --git a/src/Common/libzip/zip_source_filep.c b/src/Common/libzip/zip_source_filep.c deleted file mode 100644 index 30e5991c..00000000 --- a/src/Common/libzip/zip_source_filep.c +++ /dev/null @@ -1,663 +0,0 @@ -/* - zip_source_filep.c -- create data source from FILE * - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner - - This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at <libzip@nih.at> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. The names of the authors may not be used to endorse or promote - products derived from this software without specific prior - written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include "zipint.h" - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#ifdef HAVE_CLONEFILE -#include <sys/attr.h> -#include <sys/clonefile.h> -#define CAN_CLONE -#endif -#ifdef HAVE_FICLONERANGE -#include <linux/fs.h> -#include <sys/ioctl.h> -#define CAN_CLONE -#endif - -struct read_file { - zip_error_t error; /* last error information */ - zip_int64_t supports; - - /* reading */ - char *fname; /* name of file to read from */ - FILE *f; /* file to read from */ - struct zip_stat st; /* stat information passed in */ - zip_error_t stat_error; /* error returned for stat */ - zip_uint64_t start; /* start offset of data to read */ - zip_uint64_t end; /* end offset of data to read relative to start, 0 for up to EOF */ - zip_uint64_t current; /* current offset relative to start (0 is beginning of part we read) */ - - /* writing */ - char *tmpname; - FILE *fout; -}; - -static zip_int64_t read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd); -static int create_temp_output(struct read_file *ctx); -#ifdef CAN_CLONE -static zip_int64_t create_temp_output_cloning(struct read_file *ctx, zip_uint64_t offset); -#endif -static FILE *_zip_fopen(const char *name, bool writeable); -static int _zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error); -static int _zip_fseek(FILE *f, zip_int64_t offset, int whence, zip_error_t *error); - - -ZIP_EXTERN zip_source_t * -zip_source_filep(zip_t *za, FILE *file, zip_uint64_t start, zip_int64_t len) { - if (za == NULL) - return NULL; - - return zip_source_filep_create(file, start, len, &za->error); -} - - -ZIP_EXTERN zip_source_t * -zip_source_filep_create(FILE *file, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { - if (file == NULL || length < -1) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } - - return _zip_source_file_or_p(NULL, file, start, length, NULL, error); -} - - -zip_source_t * -_zip_source_file_or_p(const char *fname, FILE *file, zip_uint64_t start, zip_int64_t len, const zip_stat_t *st, zip_error_t *error) { - struct read_file *ctx; - zip_source_t *zs; - struct stat sb; - bool stat_valid; - - if (file == NULL && fname == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } - - if (len < 0) { - len = 0; - } - - if (start > ZIP_INT64_MAX || start + (zip_uint64_t)len < start) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } - - if ((ctx = (struct read_file *)malloc(sizeof(struct read_file))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; - } - - ctx->fname = NULL; - if (fname) { - if ((ctx->fname = strdup(fname)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - free(ctx); - return NULL; - } - } - ctx->f = file; - ctx->start = start; - ctx->end = (zip_uint64_t)len; - if (st) { - memcpy(&ctx->st, st, sizeof(ctx->st)); - ctx->st.name = NULL; - ctx->st.valid &= ~ZIP_STAT_NAME; - } - else { - zip_stat_init(&ctx->st); - } - - if (ctx->end > 0) { - ctx->st.size = ctx->end; - ctx->st.valid |= ZIP_STAT_SIZE; - } - - zip_error_init(&ctx->stat_error); - - ctx->tmpname = NULL; - ctx->fout = NULL; - - zip_error_init(&ctx->error); - - ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1); - - if (ctx->fname) { - stat_valid = stat(ctx->fname, &sb) >= 0; - - if (!stat_valid) { - if (ctx->start == 0 && ctx->end == 0) { - ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; - } - } - } - else { - stat_valid = fstat(fileno(ctx->f), &sb) >= 0; - } - - if (!stat_valid) { - zip_error_set(&ctx->stat_error, ZIP_ER_READ, errno); - } - else { - if ((ctx->st.valid & ZIP_STAT_MTIME) == 0) { - ctx->st.mtime = sb.st_mtime; - ctx->st.valid |= ZIP_STAT_MTIME; - } - if (S_ISREG(sb.st_mode)) { - ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE; - - if (ctx->start + ctx->end > (zip_uint64_t)sb.st_size) { - zip_error_set(error, ZIP_ER_INVAL, 0); - free(ctx->fname); - free(ctx); - return NULL; - } - - if (ctx->end == 0) { - ctx->st.size = (zip_uint64_t)sb.st_size - ctx->start; - ctx->st.valid |= ZIP_STAT_SIZE; - - if (ctx->fname && start == 0) { - ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; - } - } - } - } - - ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY); -#ifdef CAN_CLONE - if (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE)) { - ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING); - } -#endif - - if ((zs = zip_source_function_create(read_file, ctx, error)) == NULL) { - free(ctx->fname); - free(ctx); - return NULL; - } - - return zs; -} - - -static int -create_temp_output(struct read_file *ctx) { - char *temp; - int tfd; - int mode; - FILE *tfp; - struct stat st; - - if ((temp = (char *)malloc(strlen(ctx->fname) + 8)) == NULL) { - zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); - return -1; - } - - if (stat(ctx->fname, &st) == 0) { - mode = st.st_mode; - } - else { - mode = -1; - } - - sprintf(temp, "%s.XXXXXX", ctx->fname); - - if ((tfd = _zip_mkstempm(temp, mode)) == -1) { - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); - free(temp); - return -1; - } - - if ((tfp = fdopen(tfd, "r+b")) == NULL) { - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); - close(tfd); - (void)remove(temp); - free(temp); - return -1; - } - - ctx->fout = tfp; - ctx->tmpname = temp; - - return 0; -} - -#ifdef CAN_CLONE -zip_int64_t static create_temp_output_cloning(struct read_file *ctx, zip_uint64_t offset) { - char *temp; - FILE *tfp; - - if (offset > ZIP_OFF_MAX) { - zip_error_set(&ctx->error, ZIP_ER_SEEK, E2BIG); - return -1; - } - - if ((temp = (char *)malloc(strlen(ctx->fname) + 8)) == NULL) { - zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); - return -1; - } - sprintf(temp, "%s.XXXXXX", ctx->fname); - -#ifdef HAVE_CLONEFILE -#ifndef __clang_analyzer__ - /* we can't use mkstemp, since clonefile insists on creating the file */ - if (mktemp(temp) == NULL) { - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); - free(temp); - return -1; - } -#endif - - if (clonefile(ctx->fname, temp, 0) < 0) { - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); - free(temp); - return -1; - } - if ((tfp = _zip_fopen(temp, true)) == NULL) { - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); - (void)remove(temp); - free(temp); - return -1; - } -#else - { - int fd; - struct file_clone_range range; - struct stat st; - - if (fstat(fileno(ctx->f), &st) < 0) { - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); - return -1; - } - - if ((fd = mkstemp(temp)) < 0) { - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); - free(temp); - return -1; - } - - range.src_fd = fileno(ctx->f); - range.src_offset = 0; - range.src_length = ((offset + st.st_blksize - 1) / st.st_blksize) * st.st_blksize; - if (range.src_length > st.st_size) { - range.src_length = 0; - } - range.dest_offset = 0; - if (ioctl(fd, FICLONERANGE, &range) < 0) { - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); - (void)close(fd); - (void)remove(temp); - free(temp); - return -1; - } - - if ((tfp = fdopen(fd, "r+b")) == NULL) { - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); - (void)close(fd); - (void)remove(temp); - free(temp); - return -1; - } - } -#endif - - if (ftruncate(fileno(tfp), (off_t)offset) < 0) { - (void)fclose(tfp); - (void)remove(temp); - free(temp); - return -1; - } - if (fseeko(tfp, (off_t)offset, SEEK_SET) < 0) { - (void)fclose(tfp); - (void)remove(temp); - free(temp); - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); - } - - ctx->fout = tfp; - ctx->tmpname = temp; - - return 0; -} -#endif - - -static zip_int64_t -read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { - struct read_file *ctx; - char *buf; - zip_uint64_t n; - size_t i; - - ctx = (struct read_file *)state; - buf = (char *)data; - - switch (cmd) { - case ZIP_SOURCE_ACCEPT_EMPTY: - return 0; - - case ZIP_SOURCE_BEGIN_WRITE: -#ifdef _WIN32 - return -1; -#else - if (ctx->fname == NULL) { - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; - } - return create_temp_output(ctx); -#endif - -#ifdef CAN_CLONE - case ZIP_SOURCE_BEGIN_WRITE_CLONING: - if (ctx->fname == NULL) { - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; - } - return create_temp_output_cloning(ctx, len); -#endif - - case ZIP_SOURCE_CLOSE: - if (ctx->fname) { - fclose(ctx->f); - ctx->f = NULL; - } - return 0; - - case ZIP_SOURCE_COMMIT_WRITE: { - if (fclose(ctx->fout) < 0) { - ctx->fout = NULL; - zip_error_set(&ctx->error, ZIP_ER_WRITE, errno); - } - ctx->fout = NULL; - if (rename(ctx->tmpname, ctx->fname) < 0) { - zip_error_set(&ctx->error, ZIP_ER_RENAME, errno); - return -1; - } - free(ctx->tmpname); - ctx->tmpname = NULL; - return 0; - } - - case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, len); - - case ZIP_SOURCE_FREE: - free(ctx->fname); - free(ctx->tmpname); - if (ctx->f) - fclose(ctx->f); - free(ctx); - return 0; - - case ZIP_SOURCE_OPEN: - if (ctx->fname) { - if ((ctx->f = _zip_fopen(ctx->fname, false)) == NULL) { - zip_error_set(&ctx->error, ZIP_ER_OPEN, errno); - return -1; - } - } - - if (ctx->start > 0) { - if (_zip_fseek_u(ctx->f, ctx->start, SEEK_SET, &ctx->error) < 0) { - /* TODO: skip by reading */ - return -1; - } - } - ctx->current = 0; - return 0; - - case ZIP_SOURCE_READ: - if (ctx->end > 0) { - n = ctx->end - ctx->current; - if (n > len) { - n = len; - } - } - else { - n = len; - } - - if (n > SIZE_MAX) - n = SIZE_MAX; - - if ((i = fread(buf, 1, (size_t)n, ctx->f)) == 0) { - if (ferror(ctx->f)) { - zip_error_set(&ctx->error, ZIP_ER_READ, errno); - return -1; - } - } - ctx->current += i; - - return (zip_int64_t)i; - - case ZIP_SOURCE_REMOVE: - if (remove(ctx->fname) < 0) { - zip_error_set(&ctx->error, ZIP_ER_REMOVE, errno); - return -1; - } - return 0; - - case ZIP_SOURCE_ROLLBACK_WRITE: - if (ctx->fout) { - fclose(ctx->fout); - ctx->fout = NULL; - } - (void)remove(ctx->tmpname); - free(ctx->tmpname); - ctx->tmpname = NULL; - return 0; - - case ZIP_SOURCE_SEEK: { - zip_int64_t new_current; - int need_seek; - zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); - - if (args == NULL) - return -1; - - need_seek = 1; - - switch (args->whence) { - case SEEK_SET: - new_current = args->offset; - break; - - case SEEK_END: - if (ctx->end == 0) { - if (_zip_fseek(ctx->f, args->offset, SEEK_END, &ctx->error) < 0) { - return -1; - } - if ((new_current = ftello(ctx->f)) < 0) { - zip_error_set(&ctx->error, ZIP_ER_SEEK, errno); - return -1; - } - new_current -= (zip_int64_t)ctx->start; - need_seek = 0; - } - else { - new_current = (zip_int64_t)ctx->end + args->offset; - } - break; - - case SEEK_CUR: - new_current = (zip_int64_t)ctx->current + args->offset; - break; - - default: - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } - - if (new_current < 0 || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end) || (zip_uint64_t)new_current + ctx->start < ctx->start) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } - - ctx->current = (zip_uint64_t)new_current; - - if (need_seek) { - if (_zip_fseek_u(ctx->f, ctx->current + ctx->start, SEEK_SET, &ctx->error) < 0) { - return -1; - } - } - return 0; - } - - case ZIP_SOURCE_SEEK_WRITE: { - zip_source_args_seek_t *args; - - args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); - if (args == NULL) { - return -1; - } - - if (_zip_fseek(ctx->fout, args->offset, args->whence, &ctx->error) < 0) { - return -1; - } - return 0; - } - - case ZIP_SOURCE_STAT: { - if (len < sizeof(ctx->st)) - return -1; - - if (zip_error_code_zip(&ctx->stat_error) != 0) { - zip_error_set(&ctx->error, zip_error_code_zip(&ctx->stat_error), zip_error_code_system(&ctx->stat_error)); - return -1; - } - - memcpy(data, &ctx->st, sizeof(ctx->st)); - return sizeof(ctx->st); - } - - case ZIP_SOURCE_SUPPORTS: - return ctx->supports; - - case ZIP_SOURCE_TELL: - return (zip_int64_t)ctx->current; - - case ZIP_SOURCE_TELL_WRITE: { - off_t ret = ftello(ctx->fout); - - if (ret < 0) { - zip_error_set(&ctx->error, ZIP_ER_TELL, errno); - return -1; - } - return ret; - } - - case ZIP_SOURCE_WRITE: { - size_t ret; - - clearerr(ctx->fout); - ret = fwrite(data, 1, len, ctx->fout); - if (ret != len || ferror(ctx->fout)) { - zip_error_set(&ctx->error, ZIP_ER_WRITE, errno); - return -1; - } - - return (zip_int64_t)ret; - } - - default: - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; - } -} - - -static int -_zip_fseek_u(FILE *f, zip_uint64_t offset, int whence, zip_error_t *error) { - if (offset > ZIP_INT64_MAX) { - zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW); - return -1; - } - return _zip_fseek(f, (zip_int64_t)offset, whence, error); -} - - -static int -_zip_fseek(FILE *f, zip_int64_t offset, int whence, zip_error_t *error) { - if (offset > ZIP_FSEEK_MAX || offset < ZIP_FSEEK_MIN) { - zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW); - return -1; - } - if (fseeko(f, (off_t)offset, whence) < 0) { - zip_error_set(error, ZIP_ER_SEEK, errno); - return -1; - } - return 0; -} - - -/* - * fopen replacement that sets the close-on-exec flag - * some implementations support an fopen 'e' flag for that, - * but e.g. macOS doesn't. - */ -static FILE * -_zip_fopen(const char *name, bool writeable) -{ - int fd; - int flags; - FILE *fp; - - flags = O_CLOEXEC; - if (writeable) { - flags |= O_RDWR; - } - else { - flags |= O_RDONLY; - } - - /* mode argument needed on Windows */ - if ((fd = open(name, flags, 0666)) < 0) { - return NULL; - } - if ((fp = fdopen(fd, writeable ? "r+b" : "rb")) == NULL) { - return NULL; - } - return fp; -} diff --git a/src/Common/libzip/zip_source_get_file_attributes.c b/src/Common/libzip/zip_source_get_file_attributes.c new file mode 100644 index 00000000..acbede1d --- /dev/null +++ b/src/Common/libzip/zip_source_get_file_attributes.c @@ -0,0 +1,104 @@ +/* + zip_source_get_file_attributes.c -- get attributes for file from source + Copyright (C) 2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "zipint.h" + +ZIP_EXTERN void +zip_file_attributes_init(zip_file_attributes_t *attributes) { + attributes->valid = 0; + attributes->version = 1; +} + +int +zip_source_get_file_attributes(zip_source_t *src, zip_file_attributes_t *attributes) { + if (src->source_closed) { + return -1; + } + if (attributes == NULL) { + zip_error_set(&src->error, ZIP_ER_INVAL, 0); + return -1; + } + + zip_file_attributes_init(attributes); + + if (src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_GET_FILE_ATTRIBUTES)) { + if (_zip_source_call(src, attributes, sizeof(*attributes), ZIP_SOURCE_GET_FILE_ATTRIBUTES) < 0) { + return -1; + } + } + + if (ZIP_SOURCE_IS_LAYERED(src)) { + zip_file_attributes_t lower_attributes; + + if (zip_source_get_file_attributes(src->src, &lower_attributes) < 0) { + _zip_error_set_from_source(&src->error, src->src); + return -1; + } + + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) && (attributes->valid & ZIP_FILE_ATTRIBUTES_HOST_SYSTEM) == 0) { + attributes->host_system = lower_attributes.host_system; + attributes->valid |= ZIP_FILE_ATTRIBUTES_HOST_SYSTEM; + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_ASCII) && (attributes->valid & ZIP_FILE_ATTRIBUTES_ASCII) == 0) { + attributes->ascii = lower_attributes.ascii; + attributes->valid |= ZIP_FILE_ATTRIBUTES_ASCII; + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED)) { + if (attributes->valid & ZIP_FILE_ATTRIBUTES_VERSION_NEEDED) { + attributes->version_needed = ZIP_MAX(lower_attributes.version_needed, attributes->version_needed); + } + else { + attributes->version_needed = lower_attributes.version_needed; + attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED; + } + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) && (attributes->valid & ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES) == 0) { + attributes->external_file_attributes = lower_attributes.external_file_attributes; + attributes->valid |= ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES; + } + if ((lower_attributes.valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS)) { + if (attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) { + attributes->general_purpose_bit_flags &= ~lower_attributes.general_purpose_bit_mask; + attributes->general_purpose_bit_flags |= lower_attributes.general_purpose_bit_flags & lower_attributes.general_purpose_bit_mask; + attributes->general_purpose_bit_mask |= lower_attributes.general_purpose_bit_mask; + } + else { + attributes->valid |= ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS; + attributes->general_purpose_bit_flags = lower_attributes.general_purpose_bit_flags; + attributes->general_purpose_bit_mask = lower_attributes.general_purpose_bit_mask; + } + } + } + + return 0; +} diff --git a/src/Common/libzip/zip_source_pkware.c b/src/Common/libzip/zip_source_pkware_decode.c index 1b59d7a7..c85b590c 100644 --- a/src/Common/libzip/zip_source_pkware.c +++ b/src/Common/libzip/zip_source_pkware_decode.c @@ -1,6 +1,6 @@ /* - zip_source_pkware.c -- Traditional PKWARE de/encryption routines - Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner + zip_source_pkware_decode.c -- Traditional PKWARE decryption routines + Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,24 +38,20 @@ #include "zipint.h" struct trad_pkware { + char *password; + zip_pkware_keys_t keys; zip_error_t error; - zip_uint32_t key[3]; }; -#define HEADERLEN 12 -#define KEY0 305419896 -#define KEY1 591751049 -#define KEY2 878082192 - -static void decrypt(struct trad_pkware *, zip_uint8_t *, const zip_uint8_t *, zip_uint64_t, int); static int decrypt_header(zip_source_t *, struct trad_pkware *); static zip_int64_t pkware_decrypt(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); -static void pkware_free(struct trad_pkware *); +static struct trad_pkware *trad_pkware_new(const char *password, zip_error_t *error); +static void trad_pkware_free(struct trad_pkware *); zip_source_t * -zip_source_pkware(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, const char *password) { +zip_source_pkware_decode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, const char *password) { struct trad_pkware *ctx; zip_source_t *s2; @@ -68,20 +64,12 @@ zip_source_pkware(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, cons return NULL; } - if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + if ((ctx = trad_pkware_new(password, &za->error)) == NULL) { return NULL; } - zip_error_init(&ctx->error); - - ctx->key[0] = KEY0; - ctx->key[1] = KEY1; - ctx->key[2] = KEY2; - decrypt(ctx, NULL, (const zip_uint8_t *)password, strlen(password), 1); - if ((s2 = zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) { - pkware_free(ctx); + trad_pkware_free(ctx); return NULL; } @@ -89,62 +77,52 @@ zip_source_pkware(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, cons } -static void -decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len, int update_only) { - zip_uint16_t tmp; - zip_uint64_t i; - Bytef b; - - for (i = 0; i < len; i++) { - b = in[i]; - - if (!update_only) { - /* decrypt next byte */ - tmp = (zip_uint16_t)(ctx->key[2] | 2); - tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8); - b ^= (Bytef)tmp; - } - - /* store cleartext */ - if (out) - out[i] = b; - - /* update keys */ - ctx->key[0] = (zip_uint32_t)crc32(ctx->key[0] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; - ctx->key[1] = (ctx->key[1] + (ctx->key[0] & 0xff)) * 134775813 + 1; - b = (Bytef)(ctx->key[1] >> 24); - ctx->key[2] = (zip_uint32_t)crc32(ctx->key[2] ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL; - } -} - - static int decrypt_header(zip_source_t *src, struct trad_pkware *ctx) { - zip_uint8_t header[HEADERLEN]; + zip_uint8_t header[ZIP_CRYPTO_PKWARE_HEADERLEN]; struct zip_stat st; zip_int64_t n; - unsigned short dostime, dosdate; + bool ok; - if ((n = zip_source_read(src, header, HEADERLEN)) < 0) { + if ((n = zip_source_read(src, header, ZIP_CRYPTO_PKWARE_HEADERLEN)) < 0) { _zip_error_set_from_source(&ctx->error, src); return -1; } - if (n != HEADERLEN) { + if (n != ZIP_CRYPTO_PKWARE_HEADERLEN) { zip_error_set(&ctx->error, ZIP_ER_EOF, 0); return -1; } - decrypt(ctx, header, header, HEADERLEN, 0); + _zip_pkware_decrypt(&ctx->keys, header, header, ZIP_CRYPTO_PKWARE_HEADERLEN); - if (zip_source_stat(src, &st) < 0) { + if (zip_source_stat(src, &st)) { /* stat failed, skip password validation */ return 0; } - _zip_u2d_time(st.mtime, &dostime, &dosdate); + /* password verification - two ways: + * mtime - InfoZIP way, to avoid computing complete CRC before encrypting data + * CRC - old PKWare way + */ + + ok = false; + + if (st.valid & ZIP_STAT_MTIME) { + unsigned short dostime, dosdate; + _zip_u2d_time(st.mtime, &dostime, &dosdate); + if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == dostime >> 8) { + ok = true; + } + } + + if (st.valid & ZIP_STAT_CRC) { + if (header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] == st.crc >> 24) { + ok = true; + } + } - if (header[HEADERLEN - 1] != st.crc >> 24 && header[HEADERLEN - 1] != dostime >> 8) { + if (!ok && ((st.valid & (ZIP_STAT_MTIME | ZIP_STAT_CRC)) != 0)) { zip_error_set(&ctx->error, ZIP_ER_WRONGPASSWD, 0); return -1; } @@ -162,8 +140,11 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so switch (cmd) { case ZIP_SOURCE_OPEN: - if (decrypt_header(src, ctx) < 0) + _zip_pkware_keys_reset(&ctx->keys); + _zip_pkware_decrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password)); + if (decrypt_header(src, ctx) < 0) { return -1; + } return 0; case ZIP_SOURCE_READ: @@ -172,7 +153,7 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so return -1; } - decrypt((struct trad_pkware *)ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n, 0); + _zip_pkware_decrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n); return n; case ZIP_SOURCE_CLOSE: @@ -185,9 +166,9 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so st->encryption_method = ZIP_EM_NONE; st->valid |= ZIP_STAT_ENCRYPTION_METHOD; - /* TODO: deduce HEADERLEN from size for uncompressed */ - if (st->valid & ZIP_STAT_COMP_SIZE) - st->comp_size -= HEADERLEN; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size -= ZIP_CRYPTO_PKWARE_HEADERLEN; + } return 0; } @@ -199,7 +180,7 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so return zip_error_to_data(&ctx->error, data, len); case ZIP_SOURCE_FREE: - pkware_free(ctx); + trad_pkware_free(ctx); return 0; default: @@ -209,7 +190,33 @@ pkware_decrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip_so } +static struct trad_pkware * +trad_pkware_new(const char *password, zip_error_t *error) { + struct trad_pkware *ctx; + + if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((ctx->password = strdup(password)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; + } + + zip_error_init(&ctx->error); + + return ctx; +} + + static void -pkware_free(struct trad_pkware *ctx) { +trad_pkware_free(struct trad_pkware *ctx) { + if (ctx == NULL) { + return; + } + + free(ctx->password); free(ctx); } diff --git a/src/Common/libzip/zip_source_pkware_encode.c b/src/Common/libzip/zip_source_pkware_encode.c new file mode 100644 index 00000000..1e8f42c3 --- /dev/null +++ b/src/Common/libzip/zip_source_pkware_encode.c @@ -0,0 +1,249 @@ +/* + zip_source_pkware_encode.c -- Traditional PKWARE encryption routines + Copyright (C) 2009-2020 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include <stdlib.h> +#include <string.h> + +#include "zipint.h" + +struct trad_pkware { + char *password; + zip_pkware_keys_t keys; + zip_buffer_t *buffer; + bool eof; + zip_error_t error; +}; + + +static int encrypt_header(zip_source_t *, struct trad_pkware *); +static zip_int64_t pkware_encrypt(zip_source_t *, void *, void *, zip_uint64_t, zip_source_cmd_t); +static void trad_pkware_free(struct trad_pkware *); +static struct trad_pkware *trad_pkware_new(const char *password, zip_error_t *error); + + +zip_source_t * +zip_source_pkware_encode(zip_t *za, zip_source_t *src, zip_uint16_t em, int flags, const char *password) { + struct trad_pkware *ctx; + zip_source_t *s2; + + if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) { + zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + if (!(flags & ZIP_CODEC_ENCODE)) { + zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0); + return NULL; + } + + if ((ctx = trad_pkware_new(password, &za->error)) == NULL) { + return NULL; + } + + if ((s2 = zip_source_layered(za, src, pkware_encrypt, ctx)) == NULL) { + trad_pkware_free(ctx); + return NULL; + } + + return s2; +} + + +static int +encrypt_header(zip_source_t *src, struct trad_pkware *ctx) { + struct zip_stat st; + unsigned short dostime, dosdate; + zip_uint8_t *header; + + if (zip_source_stat(src, &st) != 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + _zip_u2d_time(st.mtime, &dostime, &dosdate); + + if ((ctx->buffer = _zip_buffer_new(NULL, ZIP_CRYPTO_PKWARE_HEADERLEN)) == NULL) { + zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); + return -1; + } + + header = _zip_buffer_data(ctx->buffer); + + /* generate header from random bytes and mtime + see appnote.iz, XIII. Decryption, Step 2, last paragraph */ + if (!zip_secure_random(header, ZIP_CRYPTO_PKWARE_HEADERLEN - 1)) { + zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0); + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + return -1; + } + header[ZIP_CRYPTO_PKWARE_HEADERLEN - 1] = (zip_uint8_t)((dostime >> 8) & 0xff); + + _zip_pkware_encrypt(&ctx->keys, header, header, ZIP_CRYPTO_PKWARE_HEADERLEN); + + return 0; +} + + +static zip_int64_t +pkware_encrypt(zip_source_t *src, void *ud, void *data, zip_uint64_t length, zip_source_cmd_t cmd) { + struct trad_pkware *ctx; + zip_int64_t n; + zip_uint64_t buffer_n; + + ctx = (struct trad_pkware *)ud; + + switch (cmd) { + case ZIP_SOURCE_OPEN: + ctx->eof = false; + + /* initialize keys */ + _zip_pkware_keys_reset(&ctx->keys); + _zip_pkware_encrypt(&ctx->keys, NULL, (const zip_uint8_t *)ctx->password, strlen(ctx->password)); + + if (encrypt_header(src, ctx) < 0) { + return -1; + } + return 0; + + case ZIP_SOURCE_READ: + buffer_n = 0; + + if (ctx->buffer) { + /* write header values to data */ + buffer_n = _zip_buffer_read(ctx->buffer, data, length); + data = (zip_uint8_t *)data + buffer_n; + length -= buffer_n; + + if (_zip_buffer_eof(ctx->buffer)) { + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + } + } + + if (ctx->eof) { + return (zip_int64_t)buffer_n; + } + + if ((n = zip_source_read(src, data, length)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + _zip_pkware_encrypt(&ctx->keys, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n); + + if ((zip_uint64_t)n < length) { + ctx->eof = true; + } + + return (zip_int64_t)buffer_n + n; + + case ZIP_SOURCE_CLOSE: + _zip_buffer_free(ctx->buffer); + ctx->buffer = NULL; + return 0; + + case ZIP_SOURCE_STAT: { + zip_stat_t *st; + + st = (zip_stat_t *)data; + st->encryption_method = ZIP_EM_TRAD_PKWARE; + st->valid |= ZIP_STAT_ENCRYPTION_METHOD; + if (st->valid & ZIP_STAT_COMP_SIZE) { + st->comp_size += ZIP_CRYPTO_PKWARE_HEADERLEN; + } + + return 0; + } + + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: { + zip_file_attributes_t *attributes = (zip_file_attributes_t *)data; + if (length < sizeof(*attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + attributes->valid |= ZIP_FILE_ATTRIBUTES_VERSION_NEEDED; + attributes->version_needed = 20; + + return 0; + } + + case ZIP_SOURCE_SUPPORTS: + return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -1); + + case ZIP_SOURCE_ERROR: + return zip_error_to_data(&ctx->error, data, length); + + case ZIP_SOURCE_FREE: + trad_pkware_free(ctx); + return 0; + + default: + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } +} + + +static struct trad_pkware * +trad_pkware_new(const char *password, zip_error_t *error) { + struct trad_pkware *ctx; + + if ((ctx = (struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + if ((ctx->password = strdup(password)) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + free(ctx); + return NULL; + } + ctx->buffer = NULL; + zip_error_init(&ctx->error); + + return ctx; +} + + +static void +trad_pkware_free(struct trad_pkware *ctx) { + if (ctx == NULL) { + return; + } + + free(ctx->password); + _zip_buffer_free(ctx->buffer); + zip_error_fini(&ctx->error); + free(ctx); +} diff --git a/src/Common/libzip/zip_source_win32a.c b/src/Common/libzip/zip_source_win32a.c deleted file mode 100644 index 257fc6aa..00000000 --- a/src/Common/libzip/zip_source_win32a.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - zip_source_win32a.c -- create data source from Windows file (ANSI) - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner - - This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at <libzip@nih.at> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. The names of the authors may not be used to endorse or promote - products derived from this software without specific prior - written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* 0x0501 => Windows XP; needs to be at least this value because of GetFileSizeEx */ -#if !defined(MS_UWP) && !defined(_WIN32_WINNT) -#define _WIN32_WINNT 0x0501 -#endif -#include <windows.h> - -#include <stdio.h> -#include <stdlib.h> - -#include "zipint.h" -#include "zipwin32.h" - -static void *_win32_strdup_a(const void *str); -static HANDLE _win32_open_a(_zip_source_win32_read_file_t *ctx); -static HANDLE _win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa); -static int _win32_rename_temp_a(_zip_source_win32_read_file_t *ctx); -static int _win32_remove_a(const void *fname); - -// clang-format off -static _zip_source_win32_file_ops_t win32_ops_a = { - _win32_strdup_a, - _win32_open_a, - _win32_create_temp_a, - _win32_rename_temp_a, - _win32_remove_a -}; -// clang-format on - -ZIP_EXTERN zip_source_t * -zip_source_win32a(zip_t *za, const char *fname, zip_uint64_t start, zip_int64_t len) { - if (za == NULL) - return NULL; - - return zip_source_win32a_create(fname, start, len, &za->error); -} - - -ZIP_EXTERN zip_source_t * -zip_source_win32a_create(const char *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { - if (fname == NULL || length < -1) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } - - return _zip_source_win32_handle_or_name(fname, INVALID_HANDLE_VALUE, start, length, 1, NULL, &win32_ops_a, error); -} - - -static void * -_win32_strdup_a(const void *str) { - return strdup((const char *)str); -} - - -static HANDLE -_win32_open_a(_zip_source_win32_read_file_t *ctx) { - return CreateFileA(ctx->fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); -} - - -static HANDLE -_win32_create_temp_a(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa) { - size_t len; - - len = strlen((const char *)ctx->fname) + 10; - if (*temp == NULL) { - if ((*temp = malloc(sizeof(char) * len)) == NULL) { - zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); - return INVALID_HANDLE_VALUE; - } - } - if (sprintf((char *)*temp, "%s.%08x", (const char *)ctx->fname, value) != len - 1) { - return INVALID_HANDLE_VALUE; - } - - return CreateFileA((const char *)*temp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY, NULL); -} - - -static int -_win32_rename_temp_a(_zip_source_win32_read_file_t *ctx) { - DWORD attributes = GetFileAttributesA(ctx->tmpname); - if (INVALID_FILE_ATTRIBUTES == attributes) - return -1; - - if (FILE_ATTRIBUTE_TEMPORARY & attributes) { - if (!SetFileAttributesA(ctx->tmpname, attributes & ~FILE_ATTRIBUTE_TEMPORARY)) - return -1; - } - - if (!MoveFileExA(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING)) - return -1; - - return 0; -} - - -static int -_win32_remove_a(const void *fname) { - DeleteFileA((const char *)fname); - return 0; -} diff --git a/src/Common/libzip/zip_source_win32handle.c b/src/Common/libzip/zip_source_win32handle.c deleted file mode 100644 index 8746cdd1..00000000 --- a/src/Common/libzip/zip_source_win32handle.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - zip_source_win32file.c -- create data source from HANDLE (Win32) - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner - - This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at <libzip@nih.at> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. The names of the authors may not be used to endorse or promote - products derived from this software without specific prior - written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include <aclapi.h> -#include <stdlib.h> -#include <string.h> -#include <wchar.h> - -#include "zipint.h" -#include "zipwin32.h" - -static zip_int64_t _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd); -static int _win32_create_temp_file(_zip_source_win32_read_file_t *ctx); -static int _zip_filetime_to_time_t(FILETIME ft, time_t *t); -static int _zip_seek_win32_u(void *h, zip_uint64_t offset, int whence, zip_error_t *error); -static int _zip_seek_win32(void *h, zip_int64_t offset, int whence, zip_error_t *error); -static int _zip_win32_error_to_errno(unsigned long win32err); -static int _zip_stat_win32(void *h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx); - -ZIP_EXTERN zip_source_t * -zip_source_win32handle(zip_t *za, HANDLE h, zip_uint64_t start, zip_int64_t len) { - if (za == NULL) - return NULL; - - return zip_source_win32handle_create(h, start, len, &za->error); -} - - -ZIP_EXTERN zip_source_t * -zip_source_win32handle_create(HANDLE h, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { - if (h == INVALID_HANDLE_VALUE || length < -1) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } - - return _zip_source_win32_handle_or_name(NULL, h, start, length, 1, NULL, NULL, error); -} - - -zip_source_t * -_zip_source_win32_handle_or_name(const void *fname, HANDLE h, zip_uint64_t start, zip_int64_t len, int closep, const zip_stat_t *st, _zip_source_win32_file_ops_t *ops, zip_error_t *error) { - _zip_source_win32_read_file_t *ctx; - zip_source_t *zs; - - if (h == INVALID_HANDLE_VALUE && fname == NULL) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } - - if ((ctx = (_zip_source_win32_read_file_t *)malloc(sizeof(_zip_source_win32_read_file_t))) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; - } - - ctx->fname = NULL; - if (fname) { - if ((ctx->fname = ops->op_strdup(fname)) == NULL) { - zip_error_set(error, ZIP_ER_MEMORY, 0); - free(ctx); - return NULL; - } - } - - ctx->ops = ops; - ctx->h = h; - ctx->start = start; - ctx->end = (len < 0 ? 0 : start + (zip_uint64_t)len); - ctx->closep = ctx->fname ? 1 : closep; - if (st) { - memcpy(&ctx->st, st, sizeof(ctx->st)); - ctx->st.name = NULL; - ctx->st.valid &= ~ZIP_STAT_NAME; - } - else { - zip_stat_init(&ctx->st); - } - - ctx->tmpname = NULL; - ctx->hout = INVALID_HANDLE_VALUE; - - zip_error_init(&ctx->error); - - ctx->supports = ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1); - if (ctx->fname) { - HANDLE th; - - th = ops->op_open(ctx); - if (th == INVALID_HANDLE_VALUE || GetFileType(th) == FILE_TYPE_DISK) { - ctx->supports = ZIP_SOURCE_SUPPORTS_WRITABLE; - } - if (th != INVALID_HANDLE_VALUE) { - CloseHandle(th); - } - } - else if (GetFileType(ctx->h) == FILE_TYPE_DISK) { - ctx->supports = ZIP_SOURCE_SUPPORTS_SEEKABLE; - } - - ctx->supports |= ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY); - - if ((zs = zip_source_function_create(_win32_read_file, ctx, error)) == NULL) { - free(ctx->fname); - free(ctx); - return NULL; - } - - return zs; -} - - -static zip_int64_t -_win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) { - _zip_source_win32_read_file_t *ctx; - char *buf; - zip_uint64_t n; - DWORD i; - - ctx = (_zip_source_win32_read_file_t *)state; - buf = (char *)data; - - switch (cmd) { - case ZIP_SOURCE_ACCEPT_EMPTY: - return 0; - - case ZIP_SOURCE_BEGIN_WRITE: - if (ctx->fname == NULL) { - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; - } - return _win32_create_temp_file(ctx); - - case ZIP_SOURCE_COMMIT_WRITE: { - if (!CloseHandle(ctx->hout)) { - ctx->hout = INVALID_HANDLE_VALUE; - zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError())); - } - ctx->hout = INVALID_HANDLE_VALUE; - if (ctx->ops->op_rename_temp(ctx) < 0) { - zip_error_set(&ctx->error, ZIP_ER_RENAME, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - free(ctx->tmpname); - ctx->tmpname = NULL; - return 0; - } - - case ZIP_SOURCE_CLOSE: - if (ctx->fname) { - CloseHandle(ctx->h); - ctx->h = INVALID_HANDLE_VALUE; - } - return 0; - - case ZIP_SOURCE_ERROR: - return zip_error_to_data(&ctx->error, data, len); - - case ZIP_SOURCE_FREE: - free(ctx->fname); - free(ctx->tmpname); - if (ctx->closep && ctx->h != INVALID_HANDLE_VALUE) - CloseHandle(ctx->h); - free(ctx); - return 0; - - case ZIP_SOURCE_OPEN: - if (ctx->fname) { - if ((ctx->h = ctx->ops->op_open(ctx)) == INVALID_HANDLE_VALUE) { - zip_error_set(&ctx->error, ZIP_ER_OPEN, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - } - - if (ctx->closep && ctx->start > 0) { - if (_zip_seek_win32_u(ctx->h, ctx->start, SEEK_SET, &ctx->error) < 0) { - return -1; - } - } - ctx->current = ctx->start; - return 0; - - case ZIP_SOURCE_READ: - if (ctx->end > 0) { - n = ctx->end - ctx->current; - if (n > len) { - n = len; - } - } - else { - n = len; - } - - if (n > SIZE_MAX) - n = SIZE_MAX; - - if (!ctx->closep) { - if (_zip_seek_win32_u(ctx->h, ctx->current, SEEK_SET, &ctx->error) < 0) { - return -1; - } - } - - if (!ReadFile(ctx->h, buf, (DWORD)n, &i, NULL)) { - zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - ctx->current += i; - - return (zip_int64_t)i; - - case ZIP_SOURCE_REMOVE: - if (ctx->ops->op_remove(ctx->fname) < 0) { - zip_error_set(&ctx->error, ZIP_ER_REMOVE, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - return 0; - - case ZIP_SOURCE_ROLLBACK_WRITE: - if (ctx->hout) { - CloseHandle(ctx->hout); - ctx->hout = INVALID_HANDLE_VALUE; - } - ctx->ops->op_remove(ctx->tmpname); - free(ctx->tmpname); - ctx->tmpname = NULL; - return 0; - - case ZIP_SOURCE_SEEK: { - zip_int64_t new_current; - int need_seek; - zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); - - if (args == NULL) - return -1; - - need_seek = ctx->closep; - - switch (args->whence) { - case SEEK_SET: - new_current = args->offset + ctx->start; - break; - - case SEEK_END: - if (ctx->end == 0) { - LARGE_INTEGER zero; - LARGE_INTEGER new_offset; - - if (_zip_seek_win32(ctx->h, args->offset, SEEK_END, &ctx->error) < 0) { - return -1; - } - zero.QuadPart = 0; - if (!SetFilePointerEx(ctx->h, zero, &new_offset, FILE_CURRENT)) { - zip_error_set(&ctx->error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - new_current = new_offset.QuadPart; - need_seek = 0; - } - else { - new_current = (zip_int64_t)ctx->end + args->offset; - } - break; - case SEEK_CUR: - new_current = (zip_int64_t)ctx->current + args->offset; - break; - - default: - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } - - if (new_current < 0 || (zip_uint64_t)new_current < ctx->start || (ctx->end != 0 && (zip_uint64_t)new_current > ctx->end)) { - zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); - return -1; - } - - ctx->current = (zip_uint64_t)new_current; - - if (need_seek) { - if (_zip_seek_win32_u(ctx->h, ctx->current, SEEK_SET, &ctx->error) < 0) { - return -1; - } - } - return 0; - } - - case ZIP_SOURCE_SEEK_WRITE: { - zip_source_args_seek_t *args; - - args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); - if (args == NULL) { - return -1; - } - - if (_zip_seek_win32(ctx->hout, args->offset, args->whence, &ctx->error) < 0) { - return -1; - } - return 0; - } - - case ZIP_SOURCE_STAT: { - if (len < sizeof(ctx->st)) - return -1; - - if (ctx->st.valid != 0) - memcpy(data, &ctx->st, sizeof(ctx->st)); - else { - DWORD win32err; - zip_stat_t *st; - HANDLE h; - int success; - - st = (zip_stat_t *)data; - - if (ctx->h != INVALID_HANDLE_VALUE) { - h = ctx->h; - } - else { - h = ctx->ops->op_open(ctx); - if (h == INVALID_HANDLE_VALUE) { - win32err = GetLastError(); - if (win32err == ERROR_FILE_NOT_FOUND || win32err == ERROR_PATH_NOT_FOUND) { - zip_error_set(&ctx->error, ZIP_ER_READ, ENOENT); - return -1; - } - } - } - - success = _zip_stat_win32(h, st, ctx); - win32err = GetLastError(); - - /* We're done with the handle, so close it if we just opened it. */ - if (h != ctx->h) { - CloseHandle(h); - } - - if (success < 0) { - /* TODO: Is this the correct error to return in all cases? */ - zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(win32err)); - return -1; - } - } - return sizeof(ctx->st); - } - - case ZIP_SOURCE_SUPPORTS: - return ctx->supports; - - case ZIP_SOURCE_TELL: - return (zip_int64_t)ctx->current; - - case ZIP_SOURCE_TELL_WRITE: { - LARGE_INTEGER zero; - LARGE_INTEGER offset; - - zero.QuadPart = 0; - if (!SetFilePointerEx(ctx->hout, zero, &offset, FILE_CURRENT)) { - zip_error_set(&ctx->error, ZIP_ER_TELL, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - - return offset.QuadPart; - } - - case ZIP_SOURCE_WRITE: { - DWORD ret; - if (!WriteFile(ctx->hout, data, (DWORD)len, &ret, NULL) || ret != len) { - zip_error_set(&ctx->error, ZIP_ER_WRITE, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - - return (zip_int64_t)ret; - } - - default: - zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); - return -1; - } -} - - -static int -_win32_create_temp_file(_zip_source_win32_read_file_t *ctx) { - zip_uint32_t value; - /* - Windows has GetTempFileName(), but it closes the file after - creation, leaving it open to a horrible race condition. So - we reinvent the wheel. - */ - int i; - HANDLE th = INVALID_HANDLE_VALUE; - void *temp = NULL; - PSECURITY_DESCRIPTOR psd = NULL; - PSECURITY_ATTRIBUTES psa = NULL; - SECURITY_ATTRIBUTES sa; - SECURITY_INFORMATION si; - DWORD success; - PACL dacl = NULL; - - /* - Read the DACL from the original file, so we can copy it to the temp file. - If there is no original file, or if we can't read the DACL, we'll use the - default security descriptor. - */ - if (ctx->h != INVALID_HANDLE_VALUE && GetFileType(ctx->h) == FILE_TYPE_DISK) { - si = DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION; - success = GetSecurityInfo(ctx->h, SE_FILE_OBJECT, si, NULL, NULL, &dacl, NULL, &psd); - if (success == ERROR_SUCCESS) { - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = FALSE; - sa.lpSecurityDescriptor = psd; - psa = &sa; - } - } - - -#ifndef MS_UWP - value = GetTickCount(); -#else - value = (zip_uint32_t)GetTickCount64(); -#endif - - for (i = 0; i < 1024 && th == INVALID_HANDLE_VALUE; i++) { - th = ctx->ops->op_create_temp(ctx, &temp, value + i, psa); - if (th == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_EXISTS) - break; - } - - if (th == INVALID_HANDLE_VALUE) { - free(temp); - LocalFree(psd); - zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - - LocalFree(psd); - ctx->hout = th; - ctx->tmpname = temp; - - return 0; -} - - -static int -_zip_seek_win32_u(HANDLE h, zip_uint64_t offset, int whence, zip_error_t *error) { - if (offset > ZIP_INT64_MAX) { - zip_error_set(error, ZIP_ER_SEEK, EOVERFLOW); - return -1; - } - return _zip_seek_win32(h, (zip_int64_t)offset, whence, error); -} - - -static int -_zip_seek_win32(HANDLE h, zip_int64_t offset, int whence, zip_error_t *error) { - LARGE_INTEGER li; - DWORD method; - - switch (whence) { - case SEEK_SET: - method = FILE_BEGIN; - break; - case SEEK_END: - method = FILE_END; - break; - case SEEK_CUR: - method = FILE_CURRENT; - break; - default: - zip_error_set(error, ZIP_ER_SEEK, EINVAL); - return -1; - } - - li.QuadPart = (LONGLONG)offset; - if (!SetFilePointerEx(h, li, NULL, method)) { - zip_error_set(error, ZIP_ER_SEEK, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - - return 0; -} - - -static int -_zip_win32_error_to_errno(DWORD win32err) { - /* - Note: This list isn't exhaustive, but should cover common cases. - */ - switch (win32err) { - case ERROR_INVALID_PARAMETER: - return EINVAL; - case ERROR_FILE_NOT_FOUND: - return ENOENT; - case ERROR_INVALID_HANDLE: - return EBADF; - case ERROR_ACCESS_DENIED: - return EACCES; - case ERROR_FILE_EXISTS: - return EEXIST; - case ERROR_TOO_MANY_OPEN_FILES: - return EMFILE; - case ERROR_DISK_FULL: - return ENOSPC; - default: - return 0; - } -} - - -static int -_zip_stat_win32(HANDLE h, zip_stat_t *st, _zip_source_win32_read_file_t *ctx) { - FILETIME mtimeft; - time_t mtime; - LARGE_INTEGER size; - int regularp; - - if (!GetFileTime(h, NULL, NULL, &mtimeft)) { - zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - if (_zip_filetime_to_time_t(mtimeft, &mtime) < 0) { - zip_error_set(&ctx->error, ZIP_ER_READ, ERANGE); - return -1; - } - - regularp = 0; - if (GetFileType(h) == FILE_TYPE_DISK) { - regularp = 1; - } - - if (!GetFileSizeEx(h, &size)) { - zip_error_set(&ctx->error, ZIP_ER_READ, _zip_win32_error_to_errno(GetLastError())); - return -1; - } - - zip_stat_init(st); - st->mtime = mtime; - st->valid |= ZIP_STAT_MTIME; - if (ctx->end != 0) { - st->size = ctx->end - ctx->start; - st->valid |= ZIP_STAT_SIZE; - } - else if (regularp) { - st->size = (zip_uint64_t)size.QuadPart; - st->valid |= ZIP_STAT_SIZE; - } - - return 0; -} - - -static int -_zip_filetime_to_time_t(FILETIME ft, time_t *t) { - /* - Inspired by http://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux - */ - const zip_int64_t WINDOWS_TICK = 10000000LL; - const zip_int64_t SEC_TO_UNIX_EPOCH = 11644473600LL; - ULARGE_INTEGER li; - zip_int64_t secs; - time_t temp; - - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - secs = (li.QuadPart / WINDOWS_TICK - SEC_TO_UNIX_EPOCH); - - temp = (time_t)secs; - if (secs != (zip_int64_t)temp) - return -1; - - *t = temp; - return 0; -} diff --git a/src/Common/libzip/zip_source_win32w.c b/src/Common/libzip/zip_source_win32w.c deleted file mode 100644 index cb8d64e6..00000000 --- a/src/Common/libzip/zip_source_win32w.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - zip_source_win32w.c -- create data source from Windows file (UTF-16) - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner - - This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at <libzip@nih.at> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. The names of the authors may not be used to endorse or promote - products derived from this software without specific prior - written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* 0x0501 => Windows XP; needs to be at least this value because of GetFileSizeEx */ -#if !defined(MS_UWP) && !defined(_WIN32_WINNT) -#define _WIN32_WINNT 0x0501 -#endif -#include <windows.h> - -#include <stdio.h> -#include <stdlib.h> - -#include "zipint.h" -#include "zipwin32.h" - -static void *_win32_strdup_w(const void *str); -static HANDLE _win32_open_w(_zip_source_win32_read_file_t *ctx); -static HANDLE _win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa); -static int _win32_rename_temp_w(_zip_source_win32_read_file_t *ctx); -static int _win32_remove_w(const void *fname); - -// clang-format off -static _zip_source_win32_file_ops_t win32_ops_w = { - _win32_strdup_w, - _win32_open_w, - _win32_create_temp_w, - _win32_rename_temp_w, - _win32_remove_w -}; -// clang-format on - -ZIP_EXTERN zip_source_t * -zip_source_win32w(zip_t *za, const wchar_t *fname, zip_uint64_t start, zip_int64_t len) { - if (za == NULL) - return NULL; - - return zip_source_win32w_create(fname, start, len, &za->error); -} - - -ZIP_EXTERN zip_source_t * -zip_source_win32w_create(const wchar_t *fname, zip_uint64_t start, zip_int64_t length, zip_error_t *error) { - if (fname == NULL || length < -1) { - zip_error_set(error, ZIP_ER_INVAL, 0); - return NULL; - } - - return _zip_source_win32_handle_or_name(fname, INVALID_HANDLE_VALUE, start, length, 1, NULL, &win32_ops_w, error); -} - - -static void * -_win32_strdup_w(const void *str) { - return _wcsdup((const wchar_t *)str); -} - - -static HANDLE -_win32_open_w(_zip_source_win32_read_file_t *ctx) { -#ifdef MS_UWP - CREATEFILE2_EXTENDED_PARAMETERS extParams = {0}; - extParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; - extParams.dwFileFlags = FILE_FLAG_RANDOM_ACCESS; - extParams.dwSecurityQosFlags = SECURITY_ANONYMOUS; - extParams.dwSize = sizeof(extParams); - extParams.hTemplateFile = NULL; - extParams.lpSecurityAttributes = NULL; - - return CreateFile2(ctx->fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, &extParams); -#else - return CreateFileW(ctx->fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); -#endif -} - - -static HANDLE -_win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32_t value, PSECURITY_ATTRIBUTES sa) { - size_t len; - - len = wcslen((const wchar_t *)ctx->fname) + 10; - if (*temp == NULL) { - if ((*temp = malloc(sizeof(wchar_t) * len)) == NULL) { - zip_error_set(&ctx->error, ZIP_ER_MEMORY, 0); - return INVALID_HANDLE_VALUE; - } - } - if (_snwprintf((wchar_t *)*temp, len, L"%s.%08x", (const wchar_t *)ctx->fname, value) != len - 1) { - return INVALID_HANDLE_VALUE; - } - -#ifdef MS_UWP - CREATEFILE2_EXTENDED_PARAMETERS extParams = {0}; - extParams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY; - extParams.dwFileFlags = FILE_FLAG_RANDOM_ACCESS; - extParams.dwSecurityQosFlags = SECURITY_ANONYMOUS; - extParams.dwSize = sizeof(extParams); - extParams.hTemplateFile = NULL; - extParams.lpSecurityAttributes = NULL; - - return CreateFile2((const wchar_t *)*temp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, CREATE_NEW, &extParams); -#else - return CreateFileW((const wchar_t *)*temp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY, NULL); -#endif -} - - -static int -_win32_rename_temp_w(_zip_source_win32_read_file_t *ctx) { - DWORD attributes = GetFileAttributesW(ctx->tmpname); - if (INVALID_FILE_ATTRIBUTES == attributes) - return -1; - - if (FILE_ATTRIBUTE_TEMPORARY & attributes) { - if (!SetFileAttributesW(ctx->tmpname, attributes & ~FILE_ATTRIBUTE_TEMPORARY)) - return -1; - } - - if (!MoveFileExW(ctx->tmpname, ctx->fname, MOVEFILE_REPLACE_EXISTING)) - return -1; - - return 0; -} - - -static int -_win32_remove_w(const void *fname) { - DeleteFileW((const wchar_t *)fname); - return 0; -} diff --git a/src/Common/libzip/zip_source_window.c b/src/Common/libzip/zip_source_window.c index 1276485d..d996015d 100644 --- a/src/Common/libzip/zip_source_window.c +++ b/src/Common/libzip/zip_source_window.c @@ -48,7 +48,7 @@ struct window { zip_uint64_t offset; /* offset in src for next read */ zip_stat_t stat; - zip_int8_t compression_flags; + zip_file_attributes_t attributes; zip_error_t error; zip_int64_t supports; bool needs_seek; @@ -64,7 +64,7 @@ zip_source_window(zip_t *za, zip_source_t *src, zip_uint64_t start, zip_uint64_t zip_source_t * -_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) { +_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error) { struct window *ctx; if (src == NULL || start + length < start || (source_archive == NULL && source_index != 0)) { @@ -80,11 +80,16 @@ _zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t lengt ctx->start = start; ctx->end = start + length; zip_stat_init(&ctx->stat); - ctx->compression_flags = compression_flags; + if (attributes != NULL) { + memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes)); + } + else { + zip_file_attributes_init(&ctx->attributes); + } ctx->source_archive = source_archive; ctx->source_index = source_index; zip_error_init(&ctx->error); - ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_COMPRESSION_FLAGS, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1)); + ctx->supports = (zip_source_supports(src) & ZIP_SOURCE_SUPPORTS_SEEKABLE) | (zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, ZIP_SOURCE_SUPPORTS, ZIP_SOURCE_TELL, -1)); ctx->needs_seek = (ctx->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) ? true : false; if (st) { @@ -173,7 +178,7 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou return -1; } } - + byte_array_fini(b); } @@ -231,8 +236,14 @@ window_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_sou return 0; } - case ZIP_SOURCE_GET_COMPRESSION_FLAGS: - return ctx->compression_flags; + case ZIP_SOURCE_GET_FILE_ATTRIBUTES: + if (len < sizeof(ctx->attributes)) { + zip_error_set(&ctx->error, ZIP_ER_INVAL, 0); + return -1; + } + + memcpy(data, &ctx->attributes, sizeof(ctx->attributes)); + return sizeof(ctx->attributes); case ZIP_SOURCE_SUPPORTS: return ctx->supports; diff --git a/src/Common/libzip/zip_source_zip.c b/src/Common/libzip/zip_source_zip.c index 1f77aaaf..8a7feaa4 100644 --- a/src/Common/libzip/zip_source_zip.c +++ b/src/Common/libzip/zip_source_zip.c @@ -33,7 +33,6 @@ #include <stdlib.h> -#include <string.h> #include "zipint.h" diff --git a/src/Common/libzip/zip_source_zip_new.c b/src/Common/libzip/zip_source_zip_new.c index f36609b1..6d547f0e 100644 --- a/src/Common/libzip/zip_source_zip_new.c +++ b/src/Common/libzip/zip_source_zip_new.c @@ -36,15 +36,19 @@ #include "zipint.h" +static void _zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de); zip_source_t * _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t flags, zip_uint64_t start, zip_uint64_t len, const char *password) { zip_source_t *src, *s2; - struct zip_stat st; + zip_stat_t st; + zip_file_attributes_t attributes; + zip_dirent_t *de; bool partial_data, needs_crc, needs_decrypt, needs_decompress; - if (za == NULL) + if (za == NULL) { return NULL; + } if (srcza == NULL || srcidx >= srcza->nentry) { zip_error_set(&za->error, ZIP_ER_INVAL, 0); @@ -61,8 +65,9 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl return NULL; } - if (flags & ZIP_FL_ENCRYPTED) + if (flags & ZIP_FL_ENCRYPTED) { flags |= ZIP_FL_COMPRESSED; + } if ((start > 0 || len > 0) && (flags & ZIP_FL_COMPRESSED)) { zip_error_set(&za->error, ZIP_ER_INVAL, 0); @@ -95,8 +100,13 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl } } + if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) { + return NULL; + } + _zip_file_attributes_from_dirent(&attributes, de); + if (st.comp_size == 0) { - return zip_source_buffer(za, NULL, 0, 0); + return zip_source_buffer_with_attributes(za, NULL, 0, 0, &attributes); } if (partial_data && !needs_decrypt && !needs_decompress) { @@ -108,17 +118,12 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl st2.mtime = st.mtime; st2.valid = ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_MTIME; - if ((src = _zip_source_window_new(srcza->src, start, len, &st2, 0, srcza, srcidx, &za->error)) == NULL) { + if ((src = _zip_source_window_new(srcza->src, start, len, &st2, &attributes, srcza, srcidx, &za->error)) == NULL) { return NULL; } } else { - zip_dirent_t *de; - - if ((de = _zip_get_dirent(srcza, srcidx, flags, &za->error)) == NULL) { - return NULL; - } - if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, (de->bitflags >> 1) & 3, srcza, srcidx, &za->error)) == NULL) { + if ((src = _zip_source_window_new(srcza->src, 0, st.comp_size, &st, &attributes, srcza, srcidx, &za->error)) == NULL) { return NULL; } } @@ -173,3 +178,14 @@ _zip_source_zip_new(zip_t *za, zip_t *srcza, zip_uint64_t srcidx, zip_flags_t fl return src; } + +static void +_zip_file_attributes_from_dirent(zip_file_attributes_t *attributes, zip_dirent_t *de) { + zip_file_attributes_init(attributes); + attributes->valid = ZIP_FILE_ATTRIBUTES_ASCII | ZIP_FILE_ATTRIBUTES_HOST_SYSTEM | ZIP_FILE_ATTRIBUTES_EXTERNAL_FILE_ATTRIBUTES | ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS; + attributes->ascii = de->int_attrib & 1; + attributes->host_system = de->version_madeby >> 8; + attributes->external_file_attributes = de->ext_attrib; + attributes->general_purpose_bit_flags = de->bitflags; + attributes->general_purpose_bit_mask = ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK; +} diff --git a/src/Common/libzip/zip_string.c b/src/Common/libzip/zip_string.c index a6edbc5d..122721d8 100644 --- a/src/Common/libzip/zip_string.c +++ b/src/Common/libzip/zip_string.c @@ -34,10 +34,10 @@ #include <stdlib.h> #include <string.h> +#include <zlib.h> #include "zipint.h" - zip_uint32_t _zip_string_crc32(const zip_string_t *s) { zip_uint32_t crc; @@ -145,7 +145,7 @@ _zip_string_new(const zip_uint8_t *raw, zip_uint16_t length, zip_flags_t flags, return NULL; } - if ((s->raw = (zip_uint8_t *)malloc((size_t)(length + 1))) == NULL) { + if ((s->raw = (zip_uint8_t *)malloc((size_t)length + 1)) == NULL) { free(s); return NULL; } diff --git a/src/Common/libzip/zip_unchange_all.c b/src/Common/libzip/zip_unchange_all.c index 5e7df80a..2ae742f8 100644 --- a/src/Common/libzip/zip_unchange_all.c +++ b/src/Common/libzip/zip_unchange_all.c @@ -32,8 +32,6 @@ */ -#include <stdlib.h> - #include "zipint.h" diff --git a/src/Common/libzip/zipint.h b/src/Common/libzip/zipint.h index 721d36e8..5f504ca9 100644 --- a/src/Common/libzip/zipint.h +++ b/src/Common/libzip/zipint.h @@ -34,10 +34,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif - #include "compat.h" #ifdef ZIP_ALLOCATE_BUFFER @@ -69,6 +66,9 @@ #define BUFSIZE 8192 #define EFZIP64SIZE 28 #define EF_WINZIP_AES_SIZE 7 +#define MAX_DATA_DESCRIPTOR_LENGTH 24 + +#define ZIP_CRYPTO_PKWARE_HEADERLEN 12 #define ZIP_CM_REPLACED_DEFAULT (-2) #define ZIP_CM_WINZIP_AES 99 /* Winzip AES encrypted */ @@ -95,6 +95,7 @@ /* according to unzip-6.0's zipinfo.c, this corresponds to a directory with rwx permissions for everyone */ #define ZIP_EXT_ATTRIB_DEFAULT_DIR (0040777u << 16) +#define ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS_ALLOWED_MASK 0x0836 #define ZIP_MAX(a, b) ((a) > (b) ? (a) : (b)) #define ZIP_MIN(a, b) ((a) < (b) ? (a) : (b)) @@ -111,14 +112,14 @@ typedef zip_source_t *(*zip_encryption_implementation)(zip_t *, zip_source_t *, zip_encryption_implementation _zip_get_encryption_implementation(zip_uint16_t method, int operation); -// clang-format off +/* clang-format off */ enum zip_compression_status { ZIP_COMPRESSION_OK, ZIP_COMPRESSION_END, ZIP_COMPRESSION_ERROR, ZIP_COMPRESSION_NEED_DATA }; -// clang-format on +/* clang-format on */ typedef enum zip_compression_status zip_compression_status_t; struct zip_compression_algorithm { @@ -128,7 +129,9 @@ struct zip_compression_algorithm { void (*deallocate)(void *ctx); /* get compression specific general purpose bitflags */ - int (*compression_flags)(void *ctx); + zip_uint16_t (*general_purpose_bit_flags)(void *ctx); + /* minimum version needed when using this algorithm */ + zip_uint8_t version_needed; /* start processing */ bool (*start)(void *ctx); @@ -154,8 +157,6 @@ extern zip_compression_algorithm_t zip_algorithm_xz_compress; extern zip_compression_algorithm_t zip_algorithm_xz_decompress; -bool zip_compression_method_supported(zip_int32_t method, bool compress); - /* This API is not final yet, but we need it internally, so it's private for now. */ const zip_uint8_t *zip_get_extra_field_by_id(zip_t *, int, int, zip_uint16_t, int, zip_uint16_t *); @@ -170,13 +171,14 @@ zip_source_t *zip_source_crc(zip_t *, zip_source_t *, int); zip_source_t *zip_source_decompress(zip_t *za, zip_source_t *src, zip_int32_t cm); zip_source_t *zip_source_layered(zip_t *, zip_source_t *, zip_source_layered_callback, void *); zip_source_t *zip_source_layered_create(zip_source_t *src, zip_source_layered_callback cb, void *ud, zip_error_t *error); -zip_source_t *zip_source_pkware(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); +zip_source_t *zip_source_pkware_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); +zip_source_t *zip_source_pkware_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); int zip_source_remove(zip_source_t *); zip_int64_t zip_source_supports(zip_source_t *src); zip_source_t *zip_source_window(zip_t *, zip_source_t *, zip_uint64_t, zip_uint64_t); zip_source_t *zip_source_winzip_aes_decode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); zip_source_t *zip_source_winzip_aes_encode(zip_t *, zip_source_t *, zip_uint16_t, int, const char *); - +zip_source_t *zip_source_buffer_with_attributes(zip_t *za, const void *data, zip_uint64_t len, int freep, zip_file_attributes_t *attributes); /* error source for layered sources */ @@ -381,13 +383,13 @@ struct zip_string { for those, use malloc()/free() */ #ifdef ZIP_ALLOCATE_BUFFER -#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t *buf -#define byte_array_init(buf, size) (((buf) = (zip_uint8_t *)malloc(size)) != NULL) -#define byte_array_fini(buf) (free(buf)) +#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t *buf +#define byte_array_init(buf, size) (((buf) = (zip_uint8_t *)malloc(size)) != NULL) +#define byte_array_fini(buf) (free(buf)) #else -#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t buf[size] -#define byte_array_init(buf, size) (1) -#define byte_array_fini(buf) ((void)0) +#define DEFINE_BYTE_ARRAY(buf, size) zip_uint8_t buf[size] +#define byte_array_init(buf, size) (1) +#define byte_array_fini(buf) ((void)0) #endif @@ -414,6 +416,11 @@ typedef struct zip_filelist zip_filelist_t; struct _zip_winzip_aes; typedef struct _zip_winzip_aes zip_winzip_aes_t; +struct _zip_pkware_keys { + zip_uint32_t key[3]; +}; +typedef struct _zip_pkware_keys zip_pkware_keys_t; + extern const char *const _zip_err_str[]; extern const int _zip_nerr_str; extern const int _zip_err_type[]; @@ -466,7 +473,6 @@ int _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length); int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset); zip_uint64_t _zip_buffer_size(zip_buffer_t *buffer); -int _zip_cdir_compute_crc(zip_t *, uLong *); void _zip_cdir_free(zip_cdir_t *); bool _zip_cdir_grow(zip_cdir_t *cd, zip_uint64_t additional_entries, zip_error_t *error); zip_cdir_t *_zip_cdir_new(zip_uint64_t, zip_error_t *); @@ -474,6 +480,7 @@ zip_int64_t _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint6 time_t _zip_d2u_time(zip_uint16_t, zip_uint16_t); void _zip_deregister_source(zip_t *za, zip_source_t *src); +void _zip_dirent_apply_attributes(zip_dirent_t *, zip_file_attributes_t *, bool, zip_uint32_t); zip_dirent_t *_zip_dirent_clone(const zip_dirent_t *); void _zip_dirent_free(zip_dirent_t *); void _zip_dirent_finalize(zip_dirent_t *); @@ -512,8 +519,6 @@ int _zip_file_fillbuf(void *, size_t, zip_file_t *); zip_uint64_t _zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error); zip_uint64_t _zip_file_get_offset(const zip_t *, zip_uint64_t, zip_error_t *); -int _zip_filerange_crc(zip_source_t *src, zip_uint64_t offset, zip_uint64_t length, uLong *crcp, zip_error_t *error); - zip_dirent_t *_zip_get_dirent(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *); enum zip_encoding_type _zip_guess_encoding(zip_string_t *, enum zip_encoding_type); @@ -545,7 +550,7 @@ int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_err int _zip_read_at_offset(zip_source_t *src, zip_uint64_t offset, unsigned char *b, size_t length, zip_error_t *error); zip_uint8_t *_zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp, zip_error_t *error); int _zip_read_local_ef(zip_t *, zip_uint64_t); -zip_string_t *_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t lenght, bool nulp, zip_error_t *error); +zip_string_t *_zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t length, bool nulp, zip_error_t *error); int _zip_register_source(zip_t *za, zip_source_t *src); void _zip_set_open_error(int *zep, const zip_error_t *err, int ze); @@ -554,12 +559,11 @@ bool zip_source_accept_empty(zip_source_t *src); zip_int64_t _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_cmd_t command); bool _zip_source_eof(zip_source_t *); zip_source_t *_zip_source_file_or_p(const char *, FILE *, zip_uint64_t, zip_int64_t, const zip_stat_t *, zip_error_t *error); -zip_int8_t zip_source_get_compression_flags(zip_source_t *); bool _zip_source_had_error(zip_source_t *); void _zip_source_invalidate(zip_source_t *src); zip_source_t *_zip_source_new(zip_error_t *error); int _zip_source_set_source_archive(zip_source_t *, zip_t *); -zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_int8_t compression_flags, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error); +zip_source_t *_zip_source_window_new(zip_source_t *src, zip_uint64_t start, zip_uint64_t length, zip_stat_t *st, zip_file_attributes_t *attributes, zip_t *source_archive, zip_uint64_t source_index, zip_error_t *error); zip_source_t *_zip_source_zip_new(zip_t *, zip_t *, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_uint64_t, const char *); int _zip_stat_merge(zip_stat_t *dst, const zip_stat_t *src, zip_error_t *error); @@ -576,6 +580,12 @@ bool _zip_winzip_aes_finish(zip_winzip_aes_t *ctx, zip_uint8_t *hmac); void _zip_winzip_aes_free(zip_winzip_aes_t *ctx); zip_winzip_aes_t *_zip_winzip_aes_new(const zip_uint8_t *password, zip_uint64_t password_length, const zip_uint8_t *salt, zip_uint16_t key_size, zip_uint8_t *password_verify, zip_error_t *error); +void _zip_pkware_encrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len); +void _zip_pkware_decrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t *in, zip_uint64_t len); +zip_pkware_keys_t *_zip_pkware_keys_new(zip_error_t *error); +void _zip_pkware_keys_free(zip_pkware_keys_t *keys); +void _zip_pkware_keys_reset(zip_pkware_keys_t *keys); + int _zip_changed(const zip_t *, zip_uint64_t *); const char *_zip_get_name(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *); int _zip_local_header_read(zip_t *, int); diff --git a/src/Common/libzip/zipwin32.h b/src/Common/libzip/zipwin32.h deleted file mode 100644 index 870f1d5a..00000000 --- a/src/Common/libzip/zipwin32.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef _HAD_ZIPWIN32_H -#define _HAD_ZIPWIN32_H - -/* - zipwin32.h -- internal declarations for Windows. - Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner - - This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at <libzip@nih.at> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. The names of the authors may not be used to endorse or promote - products derived from this software without specific prior - written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/* 0x0501 => Windows XP; needs to be at least this value because of GetFileSizeEx */ -#if !defined(MS_UWP) && !defined(_WIN32_WINNT) -#define _WIN32_WINNT 0x0501 -#endif - -#include <windows.h> - -/* context for Win32 source */ - -struct _zip_source_win32_file_ops; - -struct _zip_source_win32_read_file { - zip_error_t error; /* last error information */ - zip_int64_t supports; - - /* operations */ - struct _zip_source_win32_file_ops *ops; - - /* reading */ - void *fname; /* name of file to read from - ANSI (char *) or Unicode (wchar_t *) */ - void *h; /* HANDLE for file to read from */ - int closep; /* whether to close f on ZIP_CMD_FREE */ - struct zip_stat st; /* stat information passed in */ - zip_uint64_t start; /* start offset of data to read */ - zip_uint64_t end; /* end offset of data to read, 0 for up to EOF */ - zip_uint64_t current; /* current offset */ - - /* writing */ - void *tmpname; /* name of temp file - ANSI (char *) or Unicode (wchar_t *) */ - void *hout; /* HANDLE for output file */ -}; - -typedef struct _zip_source_win32_read_file _zip_source_win32_read_file_t; - -/* internal operations for Win32 source */ - -struct _zip_source_win32_file_ops { - void *(*op_strdup)(const void *); - void *(*op_open)(_zip_source_win32_read_file_t *); - void *(*op_create_temp)(_zip_source_win32_read_file_t *, void **, zip_uint32_t, PSECURITY_ATTRIBUTES); - int (*op_rename_temp)(_zip_source_win32_read_file_t *); - int (*op_remove)(const void *); -}; - -typedef struct _zip_source_win32_file_ops _zip_source_win32_file_ops_t; - -zip_source_t *_zip_source_win32_handle_or_name(const void *, void *, zip_uint64_t, zip_int64_t, int, const zip_stat_t *, _zip_source_win32_file_ops_t *, zip_error_t *); - -#endif /* zipwin32.h */ |