Update Libzip to latest 1.9.2 (#1071)

* Libzip 1.9.2

Updated Libzip to latest version 1.9.2 and changed version number in the config.h from 1.7.3 to 1.9.2. Not sure if anything else needs to be tweaked :)

* Modified Libzip to work with Visual studio

* Update README.md

Update libzip copyright.

* Added the missing files.

I've added the missing files zipconf.h and config.h, I've missed those sorry for that!
This commit is contained in:
DLL125 2023-05-25 12:52:53 +02:00 committed by GitHub
parent b872702309
commit 1fc4168b81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
145 changed files with 8187 additions and 3942 deletions

View File

@ -219,7 +219,7 @@ Copyright (c) 1998-2000 Paul Le Roux. All rights reserved.
Copyright (c) 1998-2008 Brian Gladman, Worcester, UK. All rights reserved.
Copyright (c) 1995-2017 Jean-loup Gailly and Mark Adler.
Copyright (c) 2016 Disk Cryptography Services for EFI (DCS), Alex Kolotnikov
Copyright (c) 1999-2017 Dieter Baron and Thomas Klausner.
Copyright (c) 1999-2020 Dieter Baron and Thomas Klausner.
Copyright (c) 2013, Alexey Degtyarev. All rights reserved.
Copyright (c) 1999-2016 Jack Lloyd. All rights reserved.
Copyright (c) 2013-2019 Stephan Mueller <smueller@chronox.de>

View File

@ -1,6 +1,6 @@
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -1,3 +1,35 @@
1.9.2 [2022-06-28]
* Fix version number in header file.
1.9.1 [2022-06-28]
===================
* Fix `zip_file_is_seekable()`.
1.9.0 [2022-06-13]
==================
* Add `zip_file_is_seekable()`.
* Improve compatibility with WinAES.
* Fix encoding handling in `zip_name_locate()`.
* Add option to `zipcmp` to output summary of changes.
* Various bug fixes and documentation improvements.
1.8.0 [2021-06-18]
==================
* Add support for zstd (Zstandard) compression.
* Add support for lzma (ID 14) compression.
* Add `zip_source_window_create()`.
* Add `zip_source_zip_create()` variant to `zip_source_zip()`.
* Allow method specific `comp_flags` in `zip_set_file_compression()`.
* Allow `zip_source_tell()` on sources that don't support seeking and `zip_ftell()` on compressed data.
* Provide more details for consistency check errors.
* Improve output of `zipcmp`.
* In `zipcmp`, dont ignore empty directories when comparing directory listing.
* Treat empty string as no password given in `zip_file_set_encryption()`, `zip_fopen_encrypted()`, and `zip_set_default_password()`.
1.7.3 [2020-07-15]
==================

View File

@ -3,10 +3,10 @@
/*
compat.h -- compatibility defines.
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -41,27 +41,26 @@
/* to have *_MAX definitions for all types when compiling with g++ */
#define __STDC_LIMIT_MACROS
#ifdef _WIN32
#ifndef ZIP_EXTERN
#ifndef ZIP_STATIC
#if defined(_WIN32) && defined(ZIP_DLL) && !defined(ZIP_STATIC)
#ifdef BUILDING_LIBZIP
#define ZIP_EXTERN __declspec(dllexport)
#else
#define ZIP_EXTERN
#define ZIP_EXTERN __declspec(dllimport)
#endif
#endif
#ifdef _WIN32
/* for dup(), close(), etc. */
#include <io.h>
#endif
#ifdef HAVE_STDBOOL_H
#include <stdbool.h>
#else
#ifndef __cplusplus
#elif !defined(__BOOL_DEFINED)
typedef char bool;
#define true 1
#define false 0
#endif
#endif
#include <errno.h>
@ -85,9 +84,6 @@ typedef char bool;
#endif
#ifdef _WIN32
#if defined(HAVE__CHMOD)
#define chmod _chmod
#endif
#if defined(HAVE__CLOSE)
#define close _close
#endif
@ -101,7 +97,7 @@ typedef char bool;
#if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
#define fileno _fileno
#endif
#if defined(HAVE__SNPRINTF)
#if !defined(HAVE_SNPRINTF) && defined(HAVE__SNPRINTF)
#define snprintf _snprintf
#endif
#if defined(HAVE__STRDUP)

View File

@ -5,68 +5,72 @@
#endif
/* BEGIN DEFINES */
/* #undef HAVE___PROGNAME */
#define HAVE__CHMOD
#define HAVE__CLOSE
#define HAVE__DUP
#define HAVE__FDOPEN
#define HAVE__FILENO
#define HAVE__OPEN
#define HAVE__SETMODE
#if defined(_MSC_VER) && _MSC_VER < 1900
#define HAVE__SNPRINTF
#else
/* #undef HAVE__SNPRINTF */
#endif
#define HAVE__STRDUP
#define HAVE__STRICMP
#define HAVE__STRTOI64
#define HAVE__STRTOUI64
#define HAVE__UMASK
/* #undef HAVE__UMASK */
#define HAVE__UNLINK
/* #undef HAVE_ARC4RANDOM */
/* #undef HAVE_CLONEFILE */
/* #undef HAVE_COMMONCRYPTO */
/* #undef HAVE_CRYPTO */
#define HAVE_CRYPTO
/* #undef HAVE_FICLONERANGE */
#define HAVE_FILENO
/* #undef HAVE_FCHMOD */
/* #undef HAVE_FSEEKO */
/* #undef HAVE_FTELLO */
/* #undef HAVE_GETPROGNAME */
/* #undef HAVE_GNUTLS */
/* #undef HAVE_LIBBZ2 */
#define HAVE_OPEN
/* #undef HAVE_OPENSSL */
/* #undef HAVE_LIBLZMA */
/* #undef HAVE_LIBZSTD */
/* #undef HAVE_LOCALTIME_R */
/* #undef HAVE_MBEDTLS */
/* #undef HAVE_MKSTEMP */
/* #undef HAVE_NULLABLE */
/* #undef HAVE_OPENSSL */
#define HAVE_SETMODE
#if defined(_MSC_VER) && _MSC_VER < 1900
/* #undef HAVE_SNPRINTF */
/* #undef HAVE_SSIZE_T_LIBZIP */
#else
#define HAVE_SNPRINTF
#endif
/* #undef HAVE_STRCASECMP */
#define HAVE_STRDUP
#define HAVE_STRICMP
#if defined(_MSC_VER) && _MSC_VER < 1800
/* #undef HAVE_STRTOLL */
/* #undef HAVE_STRTOULL */
#else
#define HAVE_STRTOLL
#define HAVE_STRTOULL
#endif
/* #undef HAVE_STRUCT_TM_TM_ZONE */
#if defined(_MSC_VER) && _MSC_VER < 1800
/* #undef HAVE_STDBOOL_H */
#else
#define HAVE_STDBOOL_H
#endif
/* #undef HAVE_STRINGS_H */
/* #undef HAVE_UNISTD_H */
#define __INT8_LIBZIP 1
#define INT8_T_LIBZIP 1
#define UINT8_T_LIBZIP 1
#define __INT16_LIBZIP 2
#define INT16_T_LIBZIP 2
#define UINT16_T_LIBZIP 2
#define __INT32_LIBZIP 4
#define INT32_T_LIBZIP 4
#define UINT32_T_LIBZIP 4
#define __INT64_LIBZIP 8
#define INT64_T_LIBZIP 8
#define UINT64_T_LIBZIP 8
#define SHORT_LIBZIP 2
#define INT_LIBZIP 4
#define LONG_LIBZIP 4
#define LONG_LONG_LIBZIP 8
#define HAVE_WINDOWS_CRYPTO
#define SIZEOF_OFF_T 4
#ifdef _WIN64
#define SIZE_T_LIBZIP 8
#define SIZEOF_SIZE_T 8
#else
#define SIZE_T_LIBZIP 4
#define SIZEOF_SIZE_T 4
#endif
/* #undef SSIZE_T_LIBZIP */
/* #undef HAVE_DIRENT_H */
/* #undef HAVE_FTS_H */
/* #undef HAVE_NDIR_H */
@ -76,18 +80,6 @@
#define HAVE_SHARED
/* END DEFINES */
#define PACKAGE "libzip"
#define VERSION "1.7.3"
#ifndef HAVE_SSIZE_T_LIBZIP
# if SIZE_T_LIBZIP == INT_LIBZIP
typedef int ssize_t;
# elif SIZE_T_LIBZIP == LONG_LIBZIP
typedef long ssize_t;
# elif SIZE_T_LIBZIP == LONG_LONG_LIBZIP
typedef long long ssize_t;
# else
#error no suitable type for ssize_t found
# endif
#endif
#define VERSION "1.9.2"
#endif /* HAD_CONFIG_H */

View File

@ -3,10 +3,10 @@
/*
zip.h -- exported declarations.
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -45,9 +45,13 @@ extern "C" {
#include <zipconf.h>
#ifndef ZIP_EXTERN
#ifndef ZIP_STATIC
#if defined(ZIP_DLL) && !defined(ZIP_STATIC)
#ifdef _WIN32
#ifdef BUILDING_LIBZIP
#define ZIP_EXTERN __declspec(dllexport)
#else
#define ZIP_EXTERN __declspec(dllimport)
#endif
#elif defined(__GNUC__) && __GNUC__ >= 4
#define ZIP_EXTERN __attribute__((visibility("default")))
#else
@ -58,9 +62,6 @@ extern "C" {
#endif
#endif
#define _Nullable
#define _Nonnull
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
@ -126,7 +127,7 @@ extern "C" {
#define ZIP_ER_INVAL 18 /* N Invalid argument */
#define ZIP_ER_NOZIP 19 /* N Not a zip archive */
#define ZIP_ER_INTERNAL 20 /* N Internal error */
#define ZIP_ER_INCONS 21 /* N Zip archive inconsistent */
#define ZIP_ER_INCONS 21 /* L Zip archive inconsistent */
#define ZIP_ER_REMOVE 22 /* S Can't remove file */
#define ZIP_ER_DELETED 23 /* N Entry has been deleted */
#define ZIP_ER_ENCRNOTSUPP 24 /* N Encryption method not supported */
@ -141,9 +142,10 @@ extern "C" {
/* type of system error value */
#define ZIP_ET_NONE 0 /* sys_err unused */
#define ZIP_ET_SYS 1 /* sys_err is errno */
#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */
#define ZIP_ET_NONE 0 /* sys_err unused */
#define ZIP_ET_SYS 1 /* sys_err is errno */
#define ZIP_ET_ZLIB 2 /* sys_err is zlib error code */
#define ZIP_ET_LIBZIP 3 /* sys_err is libzip error code */
/* compression methods */
@ -166,7 +168,9 @@ extern "C" {
/* 15-17 - Reserved by PKWARE */
#define ZIP_CM_TERSE 18 /* compressed using IBM TERSE (new) */
#define ZIP_CM_LZ77 19 /* IBM LZ77 z Architecture (PFS) */
/* 20 - old value for Zstandard */
#define ZIP_CM_LZMA2 33
#define ZIP_CM_ZSTD 93 /* Zstandard compressed data */
#define ZIP_CM_XZ 95 /* XZ compressed data */
#define ZIP_CM_JPEG 96 /* Compressed Jpeg data */
#define ZIP_CM_WAVPACK 97 /* WavPack compressed data */
@ -242,6 +246,8 @@ typedef enum zip_source_cmd zip_source_cmd_t;
#define ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd) (((zip_int64_t)1) << (cmd))
#define ZIP_SOURCE_CHECK_SUPPORTED(supported, cmd) (((supported) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(cmd)) != 0)
/* clang-format off */
#define ZIP_SOURCE_SUPPORTS_READABLE (ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_OPEN) \
@ -397,6 +403,7 @@ ZIP_EXTERN const zip_uint8_t *_Nullable zip_file_extra_field_get_by_id(zip_t *_N
ZIP_EXTERN const char *_Nullable zip_file_get_comment(zip_t *_Nonnull, zip_uint64_t, zip_uint32_t *_Nullable, zip_flags_t);
ZIP_EXTERN zip_error_t *_Nonnull zip_file_get_error(zip_file_t *_Nonnull);
ZIP_EXTERN int zip_file_get_external_attributes(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint8_t *_Nullable, zip_uint32_t *_Nullable);
ZIP_EXTERN int zip_file_is_seekable(zip_file_t *_Nonnull);
ZIP_EXTERN int zip_file_rename(zip_t *_Nonnull, zip_uint64_t, const char *_Nonnull, zip_flags_t);
ZIP_EXTERN int zip_file_replace(zip_t *_Nonnull, zip_uint64_t, zip_source_t *_Nonnull, zip_flags_t);
ZIP_EXTERN int zip_file_set_comment(zip_t *_Nonnull, zip_uint64_t, const char *_Nullable, zip_uint16_t, zip_flags_t);
@ -463,8 +470,10 @@ 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_source_t *_Nullable zip_source_window_create(zip_source_t *_Nonnull, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
ZIP_EXTERN zip_int64_t zip_source_write(zip_source_t *_Nonnull, const void *_Nullable, zip_uint64_t);
ZIP_EXTERN zip_source_t *_Nullable zip_source_zip(zip_t *_Nonnull, zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t);
ZIP_EXTERN zip_source_t *_Nullable zip_source_zip_create(zip_t *_Nonnull, zip_uint64_t, zip_flags_t, zip_uint64_t, zip_int64_t, zip_error_t *_Nullable);
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);

View File

@ -1,9 +1,9 @@
/*
zip_add.c -- add file via callback function
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -38,9 +38,9 @@
/*
NOTE: Return type is signed so we can return -1 on error.
The index can not be larger than ZIP_INT64_MAX since the size
of the central directory cannot be larger than
ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
The index can not be larger than ZIP_INT64_MAX since the size
of the central directory cannot be larger than
ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
*/
ZIP_EXTERN zip_int64_t

View File

@ -1,9 +1,9 @@
/*
zip_add_dir.c -- add directory
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -1,9 +1,9 @@
/*
zip_add_entry.c -- create and init struct zip_entry
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -44,32 +44,32 @@ _zip_add_entry(zip_t *za) {
zip_uint64_t idx;
if (za->nentry + 1 >= za->nentry_alloc) {
zip_entry_t *rentries;
zip_uint64_t nalloc = za->nentry_alloc;
zip_uint64_t additional_entries = 2 * nalloc;
zip_uint64_t realloc_size;
zip_entry_t *rentries;
zip_uint64_t nalloc = za->nentry_alloc;
zip_uint64_t additional_entries = 2 * nalloc;
zip_uint64_t realloc_size;
if (additional_entries < 16) {
additional_entries = 16;
}
else if (additional_entries > 1024) {
additional_entries = 1024;
}
/* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
nalloc += additional_entries;
realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
if (additional_entries < 16) {
additional_entries = 16;
}
else if (additional_entries > 1024) {
additional_entries = 1024;
}
/* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
nalloc += additional_entries;
realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc);
if (!rentries) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
za->entry = rentries;
za->nentry_alloc = nalloc;
if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
rentries = (zip_entry_t *)realloc(za->entry, sizeof(struct zip_entry) * (size_t)nalloc);
if (!rentries) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
za->entry = rentries;
za->nentry_alloc = nalloc;
}
idx = za->nentry++;

View File

@ -0,0 +1,285 @@
/*
zip_algorithm_bzip2.c -- bzip2 (de)compression routines
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "zipint.h"
#include <bzlib.h>
#include <limits.h>
#include <stdlib.h>
struct ctx {
zip_error_t *error;
bool compress;
int compression_flags;
bool end_of_input;
bz_stream zstr;
};
static zip_uint64_t
maximum_compressed_size(zip_uint64_t uncompressed_size) {
zip_uint64_t compressed_size = (zip_uint64_t)((double)uncompressed_size * 1.006);
if (compressed_size < uncompressed_size) {
return ZIP_UINT64_MAX;
}
return compressed_size;
}
static void *
allocate(bool compress, int compression_flags, zip_error_t *error) {
struct ctx *ctx;
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
return NULL;
}
ctx->error = error;
ctx->compress = compress;
ctx->compression_flags = compression_flags;
if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
ctx->compression_flags = 9;
}
ctx->end_of_input = false;
ctx->zstr.bzalloc = NULL;
ctx->zstr.bzfree = NULL;
ctx->zstr.opaque = NULL;
return ctx;
}
static void *
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
return allocate(true, compression_flags, error);
}
static void *
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
return allocate(false, compression_flags, error);
}
static void
deallocate(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
free(ctx);
}
static zip_uint16_t
general_purpose_bit_flags(void *ud) {
return 0;
}
static int
map_error(int ret) {
switch (ret) {
case BZ_FINISH_OK:
case BZ_FLUSH_OK:
case BZ_OK:
case BZ_RUN_OK:
case BZ_STREAM_END:
return ZIP_ER_OK;
case BZ_DATA_ERROR:
case BZ_DATA_ERROR_MAGIC:
case BZ_UNEXPECTED_EOF:
return ZIP_ER_COMPRESSED_DATA;
case BZ_MEM_ERROR:
return ZIP_ER_MEMORY;
case BZ_PARAM_ERROR:
return ZIP_ER_INVAL;
case BZ_CONFIG_ERROR: /* actually, bzip2 miscompiled */
case BZ_IO_ERROR:
case BZ_OUTBUFF_FULL:
case BZ_SEQUENCE_ERROR:
return ZIP_ER_INTERNAL;
default:
return ZIP_ER_INTERNAL;
}
}
static bool
start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
struct ctx *ctx = (struct ctx *)ud;
int ret;
ctx->zstr.avail_in = 0;
ctx->zstr.next_in = NULL;
ctx->zstr.avail_out = 0;
ctx->zstr.next_out = NULL;
if (ctx->compress) {
ret = BZ2_bzCompressInit(&ctx->zstr, ctx->compression_flags, 0, 30);
}
else {
ret = BZ2_bzDecompressInit(&ctx->zstr, 0, 0);
}
if (ret != BZ_OK) {
zip_error_set(ctx->error, map_error(ret), 0);
return false;
}
return true;
}
static bool
end(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
int err;
if (ctx->compress) {
err = BZ2_bzCompressEnd(&ctx->zstr);
}
else {
err = BZ2_bzDecompressEnd(&ctx->zstr);
}
if (err != BZ_OK) {
zip_error_set(ctx->error, map_error(err), 0);
return false;
}
return true;
}
static bool
input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
struct ctx *ctx = (struct ctx *)ud;
if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
return false;
}
ctx->zstr.avail_in = (unsigned int)length;
ctx->zstr.next_in = (char *)data;
return true;
}
static void
end_of_input(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
ctx->end_of_input = true;
}
static zip_compression_status_t
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
struct ctx *ctx = (struct ctx *)ud;
int ret;
if (ctx->zstr.avail_in == 0 && !ctx->end_of_input) {
*length = 0;
return ZIP_COMPRESSION_NEED_DATA;
}
ctx->zstr.avail_out = (unsigned int)ZIP_MIN(UINT_MAX, *length);
ctx->zstr.next_out = (char *)data;
if (ctx->compress) {
ret = BZ2_bzCompress(&ctx->zstr, ctx->end_of_input ? BZ_FINISH : BZ_RUN);
}
else {
ret = BZ2_bzDecompress(&ctx->zstr);
}
*length = *length - ctx->zstr.avail_out;
switch (ret) {
case BZ_FINISH_OK: /* compression */
return ZIP_COMPRESSION_OK;
case BZ_OK: /* decompression */
case BZ_RUN_OK: /* compression */
if (ctx->zstr.avail_in == 0) {
return ZIP_COMPRESSION_NEED_DATA;
}
return ZIP_COMPRESSION_OK;
case BZ_STREAM_END:
return ZIP_COMPRESSION_END;
default:
zip_error_set(ctx->error, map_error(ret), 0);
return ZIP_COMPRESSION_ERROR;
}
}
/* clang-format off */
zip_compression_algorithm_t zip_algorithm_bzip2_compress = {
maximum_compressed_size,
compress_allocate,
deallocate,
general_purpose_bit_flags,
46,
start,
end,
input,
end_of_input,
process
};
zip_compression_algorithm_t zip_algorithm_bzip2_decompress = {
maximum_compressed_size,
decompress_allocate,
deallocate,
general_purpose_bit_flags,
46,
start,
end,
input,
end_of_input,
process
};
/* clang-format on */

View File

@ -1,9 +1,9 @@
/*
zip_algorithm_deflate.c -- deflate (de)compression routines
Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -46,20 +46,33 @@ struct ctx {
};
static zip_uint64_t
maximum_compressed_size(zip_uint64_t uncompressed_size) {
/* max deflate size increase: size + ceil(size/16k)*5+6 */
zip_uint64_t compressed_size = uncompressed_size + (uncompressed_size + 16383) / 16384 * 5 + 6;
if (compressed_size < uncompressed_size) {
return ZIP_UINT64_MAX;
}
return compressed_size;
}
static void *
allocate(bool compress, int compression_flags, zip_error_t *error) {
struct ctx *ctx;
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
zip_error_set(error, ZIP_ET_SYS, errno);
return NULL;
zip_error_set(error, ZIP_ET_SYS, errno);
return NULL;
}
ctx->error = error;
ctx->compress = compress;
ctx->compression_flags = compression_flags;
if (ctx->compression_flags < 1 || ctx->compression_flags > 9) {
ctx->compression_flags = Z_BEST_COMPRESSION;
ctx->compression_flags = Z_BEST_COMPRESSION;
}
ctx->end_of_input = false;
@ -96,21 +109,21 @@ general_purpose_bit_flags(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
if (!ctx->compress) {
return 0;
return 0;
}
if (ctx->compression_flags < 3) {
return 2 << 1;
return 2 << 1;
}
else if (ctx->compression_flags > 7) {
return 1 << 1;
return 1 << 1;
}
return 0;
}
static bool
start(void *ud) {
start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
struct ctx *ctx = (struct ctx *)ud;
int ret;
@ -120,16 +133,16 @@ start(void *ud) {
ctx->zstr.next_out = NULL;
if (ctx->compress) {
/* negative value to tell zlib not to write a header */
ret = deflateInit2(&ctx->zstr, ctx->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
/* negative value to tell zlib not to write a header */
ret = deflateInit2(&ctx->zstr, ctx->compression_flags, Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
}
else {
ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
ret = inflateInit2(&ctx->zstr, -MAX_WBITS);
}
if (ret != Z_OK) {
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
return false;
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
return false;
}
@ -143,15 +156,15 @@ end(void *ud) {
int err;
if (ctx->compress) {
err = deflateEnd(&ctx->zstr);
err = deflateEnd(&ctx->zstr);
}
else {
err = inflateEnd(&ctx->zstr);
err = inflateEnd(&ctx->zstr);
}
if (err != Z_OK) {
zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
return false;
zip_error_set(ctx->error, ZIP_ER_ZLIB, err);
return false;
}
return true;
@ -163,8 +176,8 @@ input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
struct ctx *ctx = (struct ctx *)ud;
if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
return false;
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
return false;
}
ctx->zstr.avail_in = (uInt)length;
@ -192,37 +205,38 @@ process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
ctx->zstr.next_out = (Bytef *)data;
if (ctx->compress) {
ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);
ret = deflate(&ctx->zstr, ctx->end_of_input ? Z_FINISH : 0);
}
else {
ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
ret = inflate(&ctx->zstr, Z_SYNC_FLUSH);
}
*length = *length - ctx->zstr.avail_out;
switch (ret) {
case Z_OK:
return ZIP_COMPRESSION_OK;
return ZIP_COMPRESSION_OK;
case Z_STREAM_END:
return ZIP_COMPRESSION_END;
return ZIP_COMPRESSION_END;
case Z_BUF_ERROR:
if (ctx->zstr.avail_in == 0) {
return ZIP_COMPRESSION_NEED_DATA;
}
if (ctx->zstr.avail_in == 0) {
return ZIP_COMPRESSION_NEED_DATA;
}
/* fallthrough */
/* fallthrough */
default:
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
return ZIP_COMPRESSION_ERROR;
zip_error_set(ctx->error, ZIP_ER_ZLIB, ret);
return ZIP_COMPRESSION_ERROR;
}
}
/* clang-format off */
zip_compression_algorithm_t zip_algorithm_deflate_compress = {
maximum_compressed_size,
compress_allocate,
deallocate,
general_purpose_bit_flags,
@ -236,6 +250,7 @@ zip_compression_algorithm_t zip_algorithm_deflate_compress = {
zip_compression_algorithm_t zip_algorithm_deflate_decompress = {
maximum_compressed_size,
decompress_allocate,
deallocate,
general_purpose_bit_flags,

View File

@ -0,0 +1,406 @@
/*
zip_algorithm_xz.c -- LZMA/XZ (de)compression routines
Bazed on zip_algorithm_deflate.c -- deflate (de)compression routines
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "zipint.h"
#include <limits.h>
#include <lzma.h>
#include <stdlib.h>
#include <zlib.h>
enum header_state { INCOMPLETE, OUTPUT, DONE };
#define HEADER_BYTES_ZIP 9
#define HEADER_MAGIC_LENGTH 4
#define HEADER_MAGIC1_OFFSET 0
#define HEADER_MAGIC2_OFFSET 2
#define HEADER_SIZE_OFFSET 9
#define HEADER_SIZE_LENGTH 8
#define HEADER_PARAMETERS_LENGTH 5
#define HEADER_LZMA_ALONE_LENGTH (HEADER_PARAMETERS_LENGTH + HEADER_SIZE_LENGTH)
struct ctx {
zip_error_t *error;
bool compress;
zip_uint32_t compression_flags;
bool end_of_input;
lzma_stream zstr;
zip_uint16_t method;
/* header member is used for converting from zip to "lzma alone"
* format
*
* "lzma alone" file format starts with:
* 5 bytes lzma parameters
* 8 bytes uncompressed size
* compressed data
*
* zip archive on-disk format starts with
* 4 bytes magic (first two bytes vary, e.g. 0x0914 or 0x1002, next bytes are 0x0500)
* 5 bytes lzma parameters
* compressed data
*
* we read the data into a header of the form
* 4 bytes magic
* 5 bytes lzma parameters
* 8 bytes uncompressed size
*/
zip_uint8_t header[HEADER_MAGIC_LENGTH + HEADER_LZMA_ALONE_LENGTH];
zip_uint8_t header_bytes_offset;
enum header_state header_state;
zip_uint64_t uncompresssed_size;
};
static zip_uint64_t
maximum_compressed_size(zip_uint64_t uncompressed_size) {
/*
According to https://sourceforge.net/p/sevenzip/discussion/45797/thread/b6bd62f8/
1) you can use
outSize = 1.10 * originalSize + 64 KB.
in most cases outSize is less then 1.02 from originalSize.
2) You can try LZMA2, where
outSize can be = 1.001 * originalSize + 1 KB.
*/
/* 13 bytes added for lzma alone header */
zip_uint64_t compressed_size = (zip_uint64_t)((double)uncompressed_size * 1.1) + 64 * 1024 + 13;
if (compressed_size < uncompressed_size) {
return ZIP_UINT64_MAX;
}
return compressed_size;
}
static void *
allocate(bool compress, int compression_flags, zip_error_t *error, zip_uint16_t method) {
struct ctx *ctx;
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
ctx->error = error;
ctx->compress = compress;
if (compression_flags < 0 || compression_flags > 9) {
ctx->compression_flags = 6; /* default value */
} else {
ctx->compression_flags = (zip_uint32_t)compression_flags;
}
ctx->compression_flags |= LZMA_PRESET_EXTREME;
ctx->end_of_input = false;
memset(ctx->header, 0, sizeof(ctx->header));
ctx->header_bytes_offset = 0;
if (ZIP_CM_LZMA) {
ctx->header_state = INCOMPLETE;
}
else {
ctx->header_state = DONE;
}
memset(&ctx->zstr, 0, sizeof(ctx->zstr));
ctx->method = method;
return ctx;
}
static void *
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
return allocate(true, compression_flags, error, method);
}
static void *
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
return allocate(false, compression_flags, error, method);
}
static void
deallocate(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
free(ctx);
}
static zip_uint16_t
general_purpose_bit_flags(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
if (!ctx->compress) {
return 0;
}
if (ctx->method == ZIP_CM_LZMA) {
/* liblzma always returns an EOS/EOPM marker, see
* https://sourceforge.net/p/lzmautils/discussion/708858/thread/84c5dbb9/#a5e4/3764 */
return 1 << 1;
}
return 0;
}
static int
map_error(lzma_ret ret) {
switch (ret) {
case LZMA_DATA_ERROR:
case LZMA_UNSUPPORTED_CHECK:
return ZIP_ER_COMPRESSED_DATA;
case LZMA_MEM_ERROR:
return ZIP_ER_MEMORY;
case LZMA_OPTIONS_ERROR:
return ZIP_ER_INVAL;
default:
return ZIP_ER_INTERNAL;
}
}
static bool
start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
struct ctx *ctx = (struct ctx *)ud;
lzma_ret ret;
lzma_options_lzma opt_lzma;
lzma_lzma_preset(&opt_lzma, ctx->compression_flags);
lzma_filter filters[] = {
{.id = (ctx->method == ZIP_CM_LZMA ? LZMA_FILTER_LZMA1 : LZMA_FILTER_LZMA2), .options = &opt_lzma},
{.id = LZMA_VLI_UNKNOWN, .options = NULL},
};
ctx->zstr.avail_in = 0;
ctx->zstr.next_in = NULL;
ctx->zstr.avail_out = 0;
ctx->zstr.next_out = NULL;
if (ctx->compress) {
if (ctx->method == ZIP_CM_LZMA)
ret = lzma_alone_encoder(&ctx->zstr, filters[0].options);
else
ret = lzma_stream_encoder(&ctx->zstr, filters, LZMA_CHECK_CRC64);
}
else {
if (ctx->method == ZIP_CM_LZMA)
ret = lzma_alone_decoder(&ctx->zstr, UINT64_MAX);
else
ret = lzma_stream_decoder(&ctx->zstr, UINT64_MAX, LZMA_CONCATENATED);
}
if (ret != LZMA_OK) {
zip_error_set(ctx->error, map_error(ret), 0);
return false;
}
/* If general purpose bits 1 & 2 are both zero, write real uncompressed size in header. */
if ((attributes->valid & ZIP_FILE_ATTRIBUTES_GENERAL_PURPOSE_BIT_FLAGS) && (attributes->general_purpose_bit_mask & 0x6) == 0x6 && (attributes->general_purpose_bit_flags & 0x06) == 0 && (st->valid & ZIP_STAT_SIZE)) {
ctx->uncompresssed_size = st->size;
}
else {
ctx->uncompresssed_size = ZIP_UINT64_MAX;
}
return true;
}
static bool
end(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
lzma_end(&ctx->zstr);
return true;
}
static bool
input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
struct ctx *ctx = (struct ctx *)ud;
if (length > UINT_MAX || ctx->zstr.avail_in > 0) {
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
return false;
}
/* For decompression of LZMA1: Have we read the full "lzma alone" header yet? */
if (ctx->method == ZIP_CM_LZMA && !ctx->compress && ctx->header_state == INCOMPLETE) {
/* if not, get more of the data */
zip_uint8_t got = (zip_uint8_t)ZIP_MIN(HEADER_BYTES_ZIP - ctx->header_bytes_offset, length);
memcpy(ctx->header + ctx->header_bytes_offset, data, got);
ctx->header_bytes_offset += got;
length -= got;
data += got;
/* Do we have a complete header now? */
if (ctx->header_bytes_offset == HEADER_BYTES_ZIP) {
Bytef empty_buffer[1];
zip_buffer_t *buffer;
/* check magic */
if (ctx->header[HEADER_MAGIC2_OFFSET] != 0x05 || ctx->header[HEADER_MAGIC2_OFFSET + 1] != 0x00) {
/* magic does not match */
zip_error_set(ctx->error, ZIP_ER_COMPRESSED_DATA, 0);
return false;
}
/* set size of uncompressed data in "lzma alone" header to "unknown" */
if ((buffer = _zip_buffer_new(ctx->header + HEADER_SIZE_OFFSET, HEADER_SIZE_LENGTH)) == NULL) {
zip_error_set(ctx->error, ZIP_ER_MEMORY, 0);
return false;
}
_zip_buffer_put_64(buffer, ctx->uncompresssed_size);
_zip_buffer_free(buffer);
/* Feed header into "lzma alone" decoder, for
* initialization; this should not produce output. */
ctx->zstr.next_in = (void *)(ctx->header + HEADER_MAGIC_LENGTH);
ctx->zstr.avail_in = HEADER_LZMA_ALONE_LENGTH;
ctx->zstr.total_in = 0;
ctx->zstr.next_out = empty_buffer;
ctx->zstr.avail_out = sizeof(*empty_buffer);
ctx->zstr.total_out = 0;
/* this just initializes the decoder and does not produce output, so it consumes the complete header */
if (lzma_code(&ctx->zstr, LZMA_RUN) != LZMA_OK || ctx->zstr.total_out > 0) {
zip_error_set(ctx->error, ZIP_ER_COMPRESSED_DATA, 0);
return false;
}
ctx->header_state = DONE;
}
}
ctx->zstr.avail_in = (uInt)length;
ctx->zstr.next_in = (Bytef *)data;
return true;
}
static void
end_of_input(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
ctx->end_of_input = true;
}
static zip_compression_status_t
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
struct ctx *ctx = (struct ctx *)ud;
lzma_ret ret;
/* for compression of LZMA1 */
if (ctx->method == ZIP_CM_LZMA && ctx->compress) {
if (ctx->header_state == INCOMPLETE) {
/* write magic to output buffer */
ctx->header[0] = 0x09;
ctx->header[1] = 0x14;
ctx->header[2] = 0x05;
ctx->header[3] = 0x00;
/* generate lzma parameters into output buffer */
ctx->zstr.avail_out = HEADER_LZMA_ALONE_LENGTH;
ctx->zstr.next_out = ctx->header + HEADER_MAGIC_LENGTH;
ret = lzma_code(&ctx->zstr, LZMA_RUN);
if (ret != LZMA_OK || ctx->zstr.avail_out != 0) {
/* assume that the whole header will be provided with the first call to lzma_code */
return ZIP_COMPRESSION_ERROR;
}
ctx->header_state = OUTPUT;
}
if (ctx->header_state == OUTPUT) {
/* write header */
zip_uint8_t write_len = (zip_uint8_t)ZIP_MIN(HEADER_BYTES_ZIP - ctx->header_bytes_offset, *length);
memcpy(data, ctx->header + ctx->header_bytes_offset, write_len);
ctx->header_bytes_offset += write_len;
*length = write_len;
if (ctx->header_bytes_offset == HEADER_BYTES_ZIP) {
ctx->header_state = DONE;
}
return ZIP_COMPRESSION_OK;
}
}
ctx->zstr.avail_out = (uInt)ZIP_MIN(UINT_MAX, *length);
ctx->zstr.next_out = (Bytef *)data;
ret = lzma_code(&ctx->zstr, ctx->end_of_input ? LZMA_FINISH : LZMA_RUN);
*length = *length - ctx->zstr.avail_out;
switch (ret) {
case LZMA_OK:
return ZIP_COMPRESSION_OK;
case LZMA_STREAM_END:
return ZIP_COMPRESSION_END;
case LZMA_BUF_ERROR:
if (ctx->zstr.avail_in == 0) {
return ZIP_COMPRESSION_NEED_DATA;
}
/* fallthrough */
default:
zip_error_set(ctx->error, map_error(ret), 0);
return ZIP_COMPRESSION_ERROR;
}
}
/* Version Required should be set to 63 (6.3) because this compression
method was only defined in appnote.txt version 6.3.8, but Winzip
does not unpack it if the value is not 20. */
/* clang-format off */
zip_compression_algorithm_t zip_algorithm_xz_compress = {
maximum_compressed_size,
compress_allocate,
deallocate,
general_purpose_bit_flags,
20,
start,
end,
input,
end_of_input,
process
};
zip_compression_algorithm_t zip_algorithm_xz_decompress = {
maximum_compressed_size,
decompress_allocate,
deallocate,
general_purpose_bit_flags,
20,
start,
end,
input,
end_of_input,
process
};
/* clang-format on */

View File

@ -0,0 +1,294 @@
/*
zip_algorithm_zstd.c -- zstd (de)compression routines
Copyright (C) 2020-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "zipint.h"
#include <limits.h>
#include <stdlib.h>
#include <zstd.h>
#include <zstd_errors.h>
struct ctx {
zip_error_t *error;
bool compress;
int compression_flags;
bool end_of_input;
ZSTD_DStream *zdstream;
ZSTD_CStream *zcstream;
ZSTD_outBuffer out;
ZSTD_inBuffer in;
};
static zip_uint64_t
maximum_compressed_size(zip_uint64_t uncompressed_size) {
return ZSTD_compressBound(uncompressed_size);
}
static void *
allocate(bool compress, int compression_flags, zip_error_t *error) {
struct ctx *ctx;
/* 0: let zstd choose */
if (compression_flags < ZSTD_minCLevel() || compression_flags > ZSTD_maxCLevel()) {
compression_flags = 0;
}
if ((ctx = (struct ctx *)malloc(sizeof(*ctx))) == NULL) {
return NULL;
}
ctx->error = error;
ctx->compress = compress;
ctx->compression_flags = compression_flags;
ctx->end_of_input = false;
ctx->zdstream = NULL;
ctx->zcstream = NULL;
ctx->in.src = NULL;
ctx->in.pos = 0;
ctx->in.size = 0;
ctx->out.dst = NULL;
ctx->out.pos = 0;
ctx->out.size = 0;
return ctx;
}
static void *
compress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
return allocate(true, compression_flags, error);
}
static void *
decompress_allocate(zip_uint16_t method, int compression_flags, zip_error_t *error) {
return allocate(false, compression_flags, error);
}
static void
deallocate(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
free(ctx);
}
static zip_uint16_t
general_purpose_bit_flags(void *ud) {
/* struct ctx *ctx = (struct ctx *)ud; */
return 0;
}
static int
map_error(size_t ret) {
switch (ret) {
case ZSTD_error_no_error:
return ZIP_ER_OK;
case ZSTD_error_corruption_detected:
case ZSTD_error_checksum_wrong:
case ZSTD_error_dictionary_corrupted:
case ZSTD_error_dictionary_wrong:
return ZIP_ER_COMPRESSED_DATA;
case ZSTD_error_memory_allocation:
return ZIP_ER_MEMORY;
case ZSTD_error_parameter_unsupported:
case ZSTD_error_parameter_outOfBound:
return ZIP_ER_INVAL;
default:
return ZIP_ER_INTERNAL;
}
}
static bool
start(void *ud, zip_stat_t *st, zip_file_attributes_t *attributes) {
struct ctx *ctx = (struct ctx *)ud;
ctx->in.src = NULL;
ctx->in.pos = 0;
ctx->in.size = 0;
ctx->out.dst = NULL;
ctx->out.pos = 0;
ctx->out.size = 0;
if (ctx->compress) {
size_t ret;
ctx->zcstream = ZSTD_createCStream();
if (ctx->zcstream == NULL) {
zip_error_set(ctx->error, ZIP_ER_MEMORY, 0);
return false;
}
ret = ZSTD_initCStream(ctx->zcstream, ctx->compression_flags);
if (ZSTD_isError(ret)) {
zip_error_set(ctx->error, ZIP_ER_ZLIB, map_error(ret));
return false;
}
}
else {
ctx->zdstream = ZSTD_createDStream();
if (ctx->zdstream == NULL) {
zip_error_set(ctx->error, ZIP_ER_MEMORY, 0);
return false;
}
}
return true;
}
static bool
end(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
size_t ret;
if (ctx->compress) {
ret = ZSTD_freeCStream(ctx->zcstream);
ctx->zcstream = NULL;
}
else {
ret = ZSTD_freeDStream(ctx->zdstream);
ctx->zdstream = NULL;
}
if (ZSTD_isError(ret)) {
zip_error_set(ctx->error, map_error(ret), 0);
return false;
}
return true;
}
static bool
input(void *ud, zip_uint8_t *data, zip_uint64_t length) {
struct ctx *ctx = (struct ctx *)ud;
if (length > SIZE_MAX || ctx->in.pos != ctx->in.size) {
zip_error_set(ctx->error, ZIP_ER_INVAL, 0);
return false;
}
ctx->in.src = (const void *)data;
ctx->in.size = (size_t)length;
ctx->in.pos = 0;
return true;
}
static void
end_of_input(void *ud) {
struct ctx *ctx = (struct ctx *)ud;
ctx->end_of_input = true;
}
static zip_compression_status_t
process(void *ud, zip_uint8_t *data, zip_uint64_t *length) {
struct ctx *ctx = (struct ctx *)ud;
size_t ret;
if (ctx->in.pos == ctx->in.size && !ctx->end_of_input) {
*length = 0;
return ZIP_COMPRESSION_NEED_DATA;
}
ctx->out.dst = data;
ctx->out.pos = 0;
ctx->out.size = ZIP_MIN(SIZE_MAX, *length);
if (ctx->compress) {
if (ctx->in.pos == ctx->in.size && ctx->end_of_input) {
ret = ZSTD_endStream(ctx->zcstream, &ctx->out);
if (ret == 0) {
*length = ctx->out.pos;
return ZIP_COMPRESSION_END;
}
}
else {
ret = ZSTD_compressStream(ctx->zcstream, &ctx->out, &ctx->in);
}
}
else {
ret = ZSTD_decompressStream(ctx->zdstream, &ctx->out, &ctx->in);
}
if (ZSTD_isError(ret)) {
zip_error_set(ctx->error, map_error(ret), 0);
return ZIP_COMPRESSION_ERROR;
}
*length = ctx->out.pos;
if (ctx->in.pos == ctx->in.size) {
return ZIP_COMPRESSION_NEED_DATA;
}
return ZIP_COMPRESSION_OK;
}
/* Version Required should be set to 63 (6.3) because this compression
method was only defined in appnote.txt version 6.3.7, but Winzip
does not unpack it if the value is not 20. */
/* clang-format off */
zip_compression_algorithm_t zip_algorithm_zstd_compress = {
maximum_compressed_size,
compress_allocate,
deallocate,
general_purpose_bit_flags,
20,
start,
end,
input,
end_of_input,
process
};
zip_compression_algorithm_t zip_algorithm_zstd_decompress = {
maximum_compressed_size,
decompress_allocate,
deallocate,
general_purpose_bit_flags,
20,
start,
end,
input,
end_of_input,
process
};
/* clang-format on */

View File

@ -1,9 +1,9 @@
/*
zip_buffer.c -- bounds checked access to memory buffer
Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -45,11 +45,11 @@ _zip_buffer_data(zip_buffer_t *buffer) {
void
_zip_buffer_free(zip_buffer_t *buffer) {
if (buffer == NULL) {
return;
return;
}
if (buffer->free_data) {
free(buffer->data);
free(buffer->data);
}
free(buffer);
@ -69,7 +69,7 @@ _zip_buffer_get(zip_buffer_t *buffer, zip_uint64_t length) {
data = _zip_buffer_peek(buffer, length);
if (data != NULL) {
buffer->offset += length;
buffer->offset += length;
}
return data;
@ -81,7 +81,7 @@ _zip_buffer_get_16(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 2);
if (data == NULL) {
return 0;
return 0;
}
return (zip_uint16_t)(data[0] + (data[1] << 8));
@ -93,7 +93,7 @@ _zip_buffer_get_32(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 4);
if (data == NULL) {
return 0;
return 0;
}
return ((((((zip_uint32_t)data[3] << 8) + data[2]) << 8) + data[1]) << 8) + data[0];
@ -105,7 +105,7 @@ _zip_buffer_get_64(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 8);
if (data == NULL) {
return 0;
return 0;
}
return ((zip_uint64_t)data[7] << 56) + ((zip_uint64_t)data[6] << 48) + ((zip_uint64_t)data[5] << 40) + ((zip_uint64_t)data[4] << 32) + ((zip_uint64_t)data[3] << 24) + ((zip_uint64_t)data[2] << 16) + ((zip_uint64_t)data[1] << 8) + (zip_uint64_t)data[0];
@ -117,7 +117,7 @@ _zip_buffer_get_8(zip_buffer_t *buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, 1);
if (data == NULL) {
return 0;
return 0;
}
return data[0];
@ -133,7 +133,7 @@ _zip_buffer_left(zip_buffer_t *buffer) {
zip_uint64_t
_zip_buffer_read(zip_buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
if (_zip_buffer_left(buffer) < length) {
length = _zip_buffer_left(buffer);
length = _zip_buffer_left(buffer);
}
memcpy(data, _zip_buffer_get(buffer, length), length);
@ -148,16 +148,16 @@ _zip_buffer_new(zip_uint8_t *data, zip_uint64_t size) {
zip_buffer_t *buffer;
if (data == NULL) {
if ((data = (zip_uint8_t *)malloc(size)) == NULL) {
return NULL;
}
if ((data = (zip_uint8_t *)malloc(size)) == NULL) {
return NULL;
}
}
if ((buffer = (zip_buffer_t *)malloc(sizeof(*buffer))) == NULL) {
if (free_data) {
free(data);
}
return NULL;
if (free_data) {
free(data);
}
return NULL;
}
buffer->ok = true;
@ -175,13 +175,13 @@ _zip_buffer_new_from_source(zip_source_t *src, zip_uint64_t size, zip_uint8_t *b
zip_buffer_t *buffer;
if ((buffer = _zip_buffer_new(buf, size)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
if (_zip_read(src, buffer->data, size, error) < 0) {
_zip_buffer_free(buffer);
return NULL;
_zip_buffer_free(buffer);
return NULL;
}
return buffer;
@ -205,8 +205,8 @@ _zip_buffer_peek(zip_buffer_t *buffer, zip_uint64_t length) {
zip_uint8_t *data;
if (!buffer->ok || buffer->offset + length < length || buffer->offset + length > buffer->size) {
buffer->ok = false;
return NULL;
buffer->ok = false;
return NULL;
}
data = buffer->data + buffer->offset;
@ -218,7 +218,7 @@ _zip_buffer_put(zip_buffer_t *buffer, const void *src, size_t length) {
zip_uint8_t *dst = _zip_buffer_get(buffer, length);
if (dst == NULL) {
return -1;
return -1;
}
memcpy(dst, src, length);
@ -231,7 +231,7 @@ _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i) {
zip_uint8_t *data = _zip_buffer_get(buffer, 2);
if (data == NULL) {
return -1;
return -1;
}
data[0] = (zip_uint8_t)(i & 0xff);
@ -246,7 +246,7 @@ _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i) {
zip_uint8_t *data = _zip_buffer_get(buffer, 4);
if (data == NULL) {
return -1;
return -1;
}
data[0] = (zip_uint8_t)(i & 0xff);
@ -263,7 +263,7 @@ _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i) {
zip_uint8_t *data = _zip_buffer_get(buffer, 8);
if (data == NULL) {
return -1;
return -1;
}
data[0] = (zip_uint8_t)(i & 0xff);
@ -284,7 +284,7 @@ _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) {
zip_uint8_t *data = _zip_buffer_get(buffer, 1);
if (data == NULL) {
return -1;
return -1;
}
data[0] = i;
@ -296,8 +296,8 @@ _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i) {
int
_zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) {
if (offset > buffer->size) {
buffer->ok = false;
return -1;
buffer->ok = false;
return -1;
}
buffer->ok = true;
@ -312,8 +312,8 @@ _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) {
zip_uint64_t offset = buffer->offset + length;
if (offset < buffer->offset) {
buffer->ok = false;
return -1;
buffer->ok = false;
return -1;
}
return _zip_buffer_set_offset(buffer, offset);
}

View File

@ -1,9 +1,9 @@
/*
zip_close.c -- close zip archive and update changes
Copyright (C) 1999-2020 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -57,225 +57,225 @@ zip_close(zip_t *za) {
int changed;
if (za == NULL)
return -1;
return -1;
changed = _zip_changed(za, &survivors);
/* don't create zip files with no entries */
if (survivors == 0) {
if ((za->open_flags & ZIP_TRUNCATE) || changed) {
if (zip_source_remove(za->src) < 0) {
if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) {
_zip_error_set_from_source(&za->error, za->src);
return -1;
}
}
}
zip_discard(za);
return 0;
if ((za->open_flags & ZIP_TRUNCATE) || changed) {
if (zip_source_remove(za->src) < 0) {
if (!((zip_error_code_zip(zip_source_error(za->src)) == ZIP_ER_REMOVE) && (zip_error_code_system(zip_source_error(za->src)) == ENOENT))) {
_zip_error_set_from_source(&za->error, za->src);
return -1;
}
}
}
zip_discard(za);
return 0;
}
if (!changed) {
zip_discard(za);
return 0;
zip_discard(za);
return 0;
}
if (survivors > za->nentry) {
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
if ((filelist = (zip_filelist_t *)malloc(sizeof(filelist[0]) * (size_t)survivors)) == NULL)
return -1;
return -1;
unchanged_offset = ZIP_UINT64_MAX;
/* create list of files with index into original archive */
for (i = j = 0; i < za->nentry; i++) {
if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset);
}
if (za->entry[i].deleted) {
continue;
}
if (za->entry[i].orig != NULL && ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
unchanged_offset = ZIP_MIN(unchanged_offset, za->entry[i].orig->offset);
}
if (za->entry[i].deleted) {
continue;
}
if (j >= survivors) {
free(filelist);
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
if (j >= survivors) {
free(filelist);
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
filelist[j].idx = i;
j++;
filelist[j].idx = i;
j++;
}
if (j < survivors) {
free(filelist);
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
free(filelist);
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
if ((zip_source_supports(za->src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_BEGIN_WRITE_CLONING)) == 0) {
unchanged_offset = 0;
unchanged_offset = 0;
}
else {
if (unchanged_offset == ZIP_UINT64_MAX) {
/* we're keeping all file data, find the end of the last one */
zip_uint64_t last_index = ZIP_UINT64_MAX;
unchanged_offset = 0;
if (unchanged_offset == ZIP_UINT64_MAX) {
/* we're keeping all file data, find the end of the last one */
zip_uint64_t last_index = ZIP_UINT64_MAX;
unchanged_offset = 0;
for (i = 0; i < za->nentry; i++) {
if (za->entry[i].orig != NULL) {
if (za->entry[i].orig->offset >= unchanged_offset) {
unchanged_offset = za->entry[i].orig->offset;
last_index = i;
}
}
}
if (last_index != ZIP_UINT64_MAX) {
if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) {
free(filelist);
return -1;
}
}
}
if (unchanged_offset > 0) {
if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) {
/* cloning not supported, need to copy everything */
unchanged_offset = 0;
}
}
for (i = 0; i < za->nentry; i++) {
if (za->entry[i].orig != NULL) {
if (za->entry[i].orig->offset >= unchanged_offset) {
unchanged_offset = za->entry[i].orig->offset;
last_index = i;
}
}
}
if (last_index != ZIP_UINT64_MAX) {
if ((unchanged_offset = _zip_file_get_end(za, last_index, &za->error)) == 0) {
free(filelist);
return -1;
}
}
}
if (unchanged_offset > 0) {
if (zip_source_begin_write_cloning(za->src, unchanged_offset) < 0) {
/* cloning not supported, need to copy everything */
unchanged_offset = 0;
}
}
}
if (unchanged_offset == 0) {
if (zip_source_begin_write(za->src) < 0) {
_zip_error_set_from_source(&za->error, za->src);
free(filelist);
return -1;
}
if (zip_source_begin_write(za->src) < 0) {
_zip_error_set_from_source(&za->error, za->src);
free(filelist);
return -1;
}
}
if (_zip_progress_start(za->progress) != 0) {
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
zip_source_rollback_write(za->src);
free(filelist);
return -1;
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
zip_source_rollback_write(za->src);
free(filelist);
return -1;
}
error = 0;
for (j = 0; j < survivors; j++) {
int new_data;
zip_entry_t *entry;
zip_dirent_t *de;
int new_data;
zip_entry_t *entry;
zip_dirent_t *de;
if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) {
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
error = 1;
break;
}
if (_zip_progress_subrange(za->progress, (double)j / (double)survivors, (double)(j + 1) / (double)survivors) != 0) {
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
error = 1;
break;
}
i = filelist[j].idx;
entry = za->entry + i;
i = filelist[j].idx;
entry = za->entry + i;
if (entry->orig != NULL && entry->orig->offset < unchanged_offset) {
/* already implicitly copied by cloning */
continue;
}
if (entry->orig != NULL && entry->orig->offset < unchanged_offset) {
/* already implicitly copied by cloning */
continue;
}
new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
new_data = (ZIP_ENTRY_DATA_CHANGED(entry) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_COMP_METHOD) || ZIP_ENTRY_CHANGED(entry, ZIP_DIRENT_ENCRYPTION_METHOD));
/* create new local directory entry */
if (entry->changes == NULL) {
if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
error = 1;
break;
}
}
de = entry->changes;
if (_zip_read_local_ef(za, i) < 0) {
error = 1;
break;
}
if ((off = zip_source_tell_write(za->src)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
error = 1;
break;
}
de->offset = (zip_uint64_t)off;
if (new_data) {
zip_source_t *zs;
zs = NULL;
if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
if ((zs = _zip_source_zip_new(za, za, i, ZIP_FL_UNCHANGED, 0, 0, NULL)) == NULL) {
error = 1;
break;
}
}
/* add_data writes dirent */
if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
error = 1;
if (zs)
zip_source_free(zs);
break;
}
if (zs)
zip_source_free(zs);
}
else {
zip_uint64_t offset;
if (de->encryption_method != ZIP_EM_TRAD_PKWARE) {
/* when copying data, all sizes are known -> no data descriptor needed */
/* except for PKWare encryption, where removing the data descriptor breaks password validation */
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
}
if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
error = 1;
break;
}
if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) {
error = 1;
break;
}
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
_zip_error_set_from_source(&za->error, za->src);
/* create new local directory entry */
if (entry->changes == NULL) {
if ((entry->changes = _zip_dirent_clone(entry->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
error = 1;
break;
}
if (copy_data(za, de->comp_size) < 0) {
error = 1;
break;
}
break;
}
}
de = entry->changes;
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) {
error = 1;
break;
}
}
}
if (_zip_read_local_ef(za, i) < 0) {
error = 1;
break;
}
if ((off = zip_source_tell_write(za->src)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
error = 1;
break;
}
de->offset = (zip_uint64_t)off;
if (new_data) {
zip_source_t *zs;
zs = NULL;
if (!ZIP_ENTRY_DATA_CHANGED(entry)) {
if ((zs = _zip_source_zip_new(za, i, ZIP_FL_UNCHANGED, 0, 0, NULL, &za->error)) == NULL) {
error = 1;
break;
}
}
/* add_data writes dirent */
if (add_data(za, zs ? zs : entry->source, de, entry->changes ? entry->changes->changed : 0) < 0) {
error = 1;
if (zs)
zip_source_free(zs);
break;
}
if (zs)
zip_source_free(zs);
}
else {
zip_uint64_t offset;
if (de->encryption_method != ZIP_EM_TRAD_PKWARE) {
/* when copying data, all sizes are known -> no data descriptor needed */
/* except for PKWare encryption, where removing the data descriptor breaks password validation */
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
}
if (_zip_dirent_write(za, de, ZIP_FL_LOCAL) < 0) {
error = 1;
break;
}
if ((offset = _zip_file_get_offset(za, i, &za->error)) == 0) {
error = 1;
break;
}
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
_zip_error_set_from_source(&za->error, za->src);
error = 1;
break;
}
if (copy_data(za, de->comp_size) < 0) {
error = 1;
break;
}
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
if (write_data_descriptor(za, de, _zip_dirent_needs_zip64(de, 0)) < 0) {
error = 1;
break;
}
}
}
}
if (!error) {
if (write_cdir(za, filelist, survivors) < 0)
error = 1;
if (write_cdir(za, filelist, survivors) < 0)
error = 1;
}
free(filelist);
if (!error) {
if (zip_source_commit_write(za->src) != 0) {
_zip_error_set_from_source(&za->error, za->src);
error = 1;
}
_zip_progress_end(za->progress);
if (zip_source_commit_write(za->src) != 0) {
_zip_error_set_from_source(&za->error, za->src);
error = 1;
}
_zip_progress_end(za->progress);
}
if (error) {
zip_source_rollback_write(za->src);
return -1;
zip_source_rollback_write(za->src);
return -1;
}
zip_discard(za);
@ -296,86 +296,83 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
bool needs_recompress, needs_decompress, needs_crc, needs_compress, needs_reencrypt, needs_decrypt, needs_encrypt;
if (zip_source_stat(src, &st) < 0) {
_zip_error_set_from_source(&za->error, src);
return -1;
_zip_error_set_from_source(&za->error, src);
return -1;
}
if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
st.valid |= ZIP_STAT_COMP_METHOD;
st.comp_method = ZIP_CM_STORE;
st.valid |= ZIP_STAT_COMP_METHOD;
st.comp_method = ZIP_CM_STORE;
}
if (ZIP_CM_IS_DEFAULT(de->comp_method) && st.comp_method != ZIP_CM_STORE)
de->comp_method = st.comp_method;
de->comp_method = st.comp_method;
else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
st.valid |= ZIP_STAT_COMP_SIZE;
st.comp_size = st.size;
st.valid |= ZIP_STAT_COMP_SIZE;
st.comp_size = st.size;
}
else {
/* we'll recompress */
st.valid &= ~ZIP_STAT_COMP_SIZE;
/* we'll recompress */
st.valid &= ~ZIP_STAT_COMP_SIZE;
}
if ((st.valid & ZIP_STAT_ENCRYPTION_METHOD) == 0) {
st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
st.encryption_method = ZIP_EM_NONE;
st.valid |= ZIP_STAT_ENCRYPTION_METHOD;
st.encryption_method = ZIP_EM_NONE;
}
flags = ZIP_EF_LOCAL;
if ((st.valid & ZIP_STAT_SIZE) == 0) {
flags |= ZIP_FL_FORCE_ZIP64;
data_length = -1;
flags |= ZIP_FL_FORCE_ZIP64;
data_length = -1;
}
else {
de->uncomp_size = st.size;
/* this is technically incorrect (copy_source counts compressed data), but it's the best we have */
data_length = (zip_int64_t)st.size;
de->uncomp_size = st.size;
/* this is technically incorrect (copy_source counts compressed data), but it's the best we have */
data_length = (zip_int64_t)st.size;
if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
zip_uint64_t max_size;
if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
zip_uint64_t max_compressed_size;
zip_uint16_t compression_method = ZIP_CM_ACTUAL(de->comp_method);
switch (ZIP_CM_ACTUAL(de->comp_method)) {
case ZIP_CM_BZIP2:
/* computed by looking at increase of 10 random files of size 1MB when
* compressed with bzip2, rounded up: 1.006 */
max_size = 4269351188u;
break;
if (compression_method == ZIP_CM_STORE) {
max_compressed_size = st.size;
}
else {
zip_compression_algorithm_t *algorithm = _zip_get_compression_algorithm(compression_method, true);
if (algorithm == NULL) {
max_compressed_size = ZIP_UINT64_MAX;
}
else {
max_compressed_size = algorithm->maximum_compressed_size(st.size);
}
}
case ZIP_CM_DEFLATE:
/* max deflate size increase: size + ceil(size/16k)*5+6 */
max_size = 4293656963u;
break;
case ZIP_CM_STORE:
max_size = 0xffffffffu;
break;
default:
max_size = 0;
}
if (st.size > max_size) {
flags |= ZIP_FL_FORCE_ZIP64;
}
}
else
de->comp_size = st.comp_size;
if (max_compressed_size > 0xffffffffu) {
flags |= ZIP_FL_FORCE_ZIP64;
}
}
else {
de->comp_size = st.comp_size;
data_length = (zip_int64_t)st.comp_size;
}
}
if ((offstart = zip_source_tell_write(za->src)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
return -1;
_zip_error_set_from_source(&za->error, za->src);
return -1;
}
/* as long as we don't support non-seekable output, clear data descriptor bit */
de->bitflags &= (zip_uint16_t)~ZIP_GPBF_DATA_DESCRIPTOR;
if ((is_zip64 = _zip_dirent_write(za, de, flags)) < 0) {
return -1;
return -1;
}
needs_recompress = st.comp_method != ZIP_CM_ACTUAL(de->comp_method);
needs_decompress = needs_recompress && (st.comp_method != ZIP_CM_STORE);
/* in these cases we can compute the CRC ourselves, so we do */
needs_crc = (st.comp_method == ZIP_CM_STORE) || needs_decompress;
needs_compress = needs_recompress && (de->comp_method != ZIP_CM_STORE);
@ -387,127 +384,143 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
zip_source_keep(src_final);
if (needs_decrypt) {
zip_encryption_implementation impl;
zip_encryption_implementation impl;
if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
zip_source_free(src_final);
return -1;
}
if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
/* error set by impl */
zip_source_free(src_final);
return -1;
}
if ((impl = _zip_get_encryption_implementation(st.encryption_method, ZIP_CODEC_DECODE)) == NULL) {
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
zip_source_free(src_final);
return -1;
}
if ((src_tmp = impl(za, src_final, st.encryption_method, ZIP_CODEC_DECODE, za->default_password)) == NULL) {
/* error set by impl */
zip_source_free(src_final);
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
zip_source_free(src_final);
src_final = src_tmp;
}
if (needs_decompress) {
if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
zip_source_free(src_final);
return -1;
}
if ((src_tmp = zip_source_decompress(za, src_final, st.comp_method)) == NULL) {
zip_source_free(src_final);
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
zip_source_free(src_final);
src_final = src_tmp;
}
if (needs_crc) {
if ((src_tmp = zip_source_crc(za, src_final, 0)) == NULL) {
zip_source_free(src_final);
return -1;
}
if ((src_tmp = zip_source_crc_create(src_final, 0, &za->error)) == NULL) {
zip_source_free(src_final);
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
zip_source_free(src_final);
src_final = src_tmp;
}
if (needs_compress) {
if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
zip_source_free(src_final);
return -1;
}
if ((src_tmp = zip_source_compress(za, src_final, de->comp_method, de->compression_level)) == NULL) {
zip_source_free(src_final);
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
zip_source_free(src_final);
src_final = src_tmp;
}
if (needs_encrypt) {
zip_encryption_implementation impl;
const char *password = NULL;
zip_encryption_implementation impl;
const char *password = NULL;
if (de->password) {
password = de->password;
}
else if (za->default_password) {
password = za->default_password;
}
if (de->password) {
password = de->password;
}
else if (za->default_password) {
password = za->default_password;
}
if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) {
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
zip_source_free(src_final);
return -1;
}
if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
/* error set by impl */
zip_source_free(src_final);
return -1;
}
if (de->encryption_method == ZIP_EM_TRAD_PKWARE) {
de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR;
}
if ((impl = _zip_get_encryption_implementation(de->encryption_method, ZIP_CODEC_ENCODE)) == NULL) {
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
zip_source_free(src_final);
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
if (de->encryption_method == ZIP_EM_TRAD_PKWARE) {
de->bitflags |= ZIP_GPBF_DATA_DESCRIPTOR;
/* PKWare encryption uses last_mod, make sure it gets the right value. */
if (de->changed & ZIP_DIRENT_LAST_MOD) {
zip_stat_t st_mtime;
zip_stat_init(&st_mtime);
st_mtime.valid = ZIP_STAT_MTIME;
st_mtime.mtime = de->last_mod;
if ((src_tmp = _zip_source_window_new(src_final, 0, -1, &st_mtime, NULL, NULL, 0, &za->error)) == NULL) {
zip_source_free(src_final);
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
}
}
if ((src_tmp = impl(za, src_final, de->encryption_method, ZIP_CODEC_ENCODE, password)) == NULL) {
/* error set by impl */
zip_source_free(src_final);
return -1;
}
zip_source_free(src_final);
src_final = src_tmp;
}
if ((offdata = zip_source_tell_write(za->src)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
return -1;
_zip_error_set_from_source(&za->error, za->src);
return -1;
}
ret = copy_source(za, src_final, data_length);
if (zip_source_stat(src_final, &st) < 0) {
_zip_error_set_from_source(&za->error, src_final);
ret = -1;
_zip_error_set_from_source(&za->error, src_final);
ret = -1;
}
if (zip_source_get_file_attributes(src_final, &attributes) != 0) {
_zip_error_set_from_source(&za->error, src_final);
ret = -1;
_zip_error_set_from_source(&za->error, src_final);
ret = -1;
}
zip_source_free(src_final);
if (ret < 0) {
return -1;
return -1;
}
if ((offend = zip_source_tell_write(za->src)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
return -1;
_zip_error_set_from_source(&za->error, za->src);
return -1;
}
if (zip_source_seek_write(za->src, offstart, SEEK_SET) < 0) {
_zip_error_set_from_source(&za->error, za->src);
return -1;
_zip_error_set_from_source(&za->error, za->src);
return -1;
}
if ((st.valid & (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD | ZIP_STAT_CRC | ZIP_STAT_SIZE)) {
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
if (st.valid & ZIP_STAT_MTIME)
de->last_mod = st.mtime;
else
time(&de->last_mod);
if (st.valid & ZIP_STAT_MTIME)
de->last_mod = st.mtime;
else
time(&de->last_mod);
}
de->comp_method = st.comp_method;
de->crc = st.crc;
@ -516,23 +529,23 @@ add_data(zip_t *za, zip_source_t *src, zip_dirent_t *de, zip_uint32_t changed) {
_zip_dirent_apply_attributes(de, &attributes, (flags & ZIP_FL_FORCE_ZIP64) != 0, changed);
if ((ret = _zip_dirent_write(za, de, flags)) < 0)
return -1;
return -1;
if (is_zip64 != ret) {
/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
if (zip_source_seek_write(za->src, offend, SEEK_SET) < 0) {
_zip_error_set_from_source(&za->error, za->src);
return -1;
_zip_error_set_from_source(&za->error, za->src);
return -1;
}
if (de->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
if (write_data_descriptor(za, de, is_zip64) < 0) {
return -1;
}
if (write_data_descriptor(za, de, is_zip64) < 0) {
return -1;
}
}
return 0;
@ -546,28 +559,28 @@ copy_data(zip_t *za, zip_uint64_t len) {
double total = (double)len;
if (!byte_array_init(buf, BUFSIZE)) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
while (len > 0) {
n = len > BUFSIZE ? BUFSIZE : len;
if (_zip_read(za->src, buf, n, &za->error) < 0) {
byte_array_fini(buf);
return -1;
}
n = len > BUFSIZE ? BUFSIZE : len;
if (_zip_read(za->src, buf, n, &za->error) < 0) {
byte_array_fini(buf);
return -1;
}
if (_zip_write(za, buf, n) < 0) {
byte_array_fini(buf);
return -1;
}
if (_zip_write(za, buf, n) < 0) {
byte_array_fini(buf);
return -1;
}
len -= n;
len -= n;
if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) {
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
return -1;
}
if (_zip_progress_update(za->progress, (total - (double)len) / total) != 0) {
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
return -1;
}
}
byte_array_fini(buf);
@ -582,35 +595,35 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
int ret;
if (zip_source_open(src) < 0) {
_zip_error_set_from_source(&za->error, src);
return -1;
_zip_error_set_from_source(&za->error, src);
return -1;
}
if (!byte_array_init(buf, BUFSIZE)) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
ret = 0;
current = 0;
while ((n = zip_source_read(src, buf, BUFSIZE)) > 0) {
if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
ret = -1;
break;
}
if (n == BUFSIZE && za->progress && data_length > 0) {
current += n;
if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) {
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
ret = -1;
break;
}
}
if (_zip_write(za, buf, (zip_uint64_t)n) < 0) {
ret = -1;
break;
}
if (n == BUFSIZE && za->progress && data_length > 0) {
current += n;
if (_zip_progress_update(za->progress, (double)current / (double)data_length) != 0) {
zip_error_set(&za->error, ZIP_ER_CANCELLED, 0);
ret = -1;
break;
}
}
}
if (n < 0) {
_zip_error_set_from_source(&za->error, src);
ret = -1;
_zip_error_set_from_source(&za->error, src);
ret = -1;
}
byte_array_fini(buf);
@ -622,18 +635,16 @@ copy_source(zip_t *za, zip_source_t *src, zip_int64_t data_length) {
static int
write_cdir(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivors) {
zip_int64_t cd_start, end, size;
if ((cd_start = zip_source_tell_write(za->src)) < 0) {
return -1;
if (zip_source_tell_write(za->src) < 0) {
return -1;
}
if ((size = _zip_cdir_write(za, filelist, survivors)) < 0) {
return -1;
if (_zip_cdir_write(za, filelist, survivors) < 0) {
return -1;
}
if ((end = zip_source_tell_write(za->src)) < 0) {
return -1;
if (zip_source_tell_write(za->src) < 0) {
return -1;
}
return 0;
@ -649,20 +660,20 @@ _zip_changed(const zip_t *za, zip_uint64_t *survivorsp) {
survivors = 0;
if (za->comment_changed || za->ch_flags != za->flags) {
changed = 1;
changed = 1;
}
for (i = 0; i < za->nentry; i++) {
if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
changed = 1;
}
if (!za->entry[i].deleted) {
survivors++;
}
if (ZIP_ENTRY_HAS_CHANGES(&za->entry[i])) {
changed = 1;
}
if (!za->entry[i].deleted) {
survivors++;
}
}
if (survivorsp) {
*survivorsp = survivors;
*survivorsp = survivors;
}
return changed;
@ -674,27 +685,27 @@ write_data_descriptor(zip_t *za, const zip_dirent_t *de, int is_zip64) {
int ret = 0;
if (buffer == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
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);
_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);
_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;
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
ret = -1;
}
else {
ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer));
ret = _zip_write(za, _zip_buffer_data(buffer), _zip_buffer_offset(buffer));
}
_zip_buffer_free(buffer);

View File

@ -0,0 +1,54 @@
/*
zip_crypto.h -- crypto definitions
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HAD_ZIP_CRYPTO_H
#define HAD_ZIP_CRYPTO_H
#define ZIP_CRYPTO_SHA1_LENGTH 20
#define ZIP_CRYPTO_AES_BLOCK_LENGTH 16
#if defined(HAVE_WINDOWS_CRYPTO)
#include "zip_crypto_win.h"
#elif defined(HAVE_COMMONCRYPTO)
#include "zip_crypto_commoncrypto.h"
#elif defined(HAVE_GNUTLS)
#include "zip_crypto_gnutls.h"
#elif defined(HAVE_OPENSSL)
#include "zip_crypto_openssl.h"
#elif defined(HAVE_MBEDTLS)
#include "zip_crypto_mbedtls.h"
#else
#error "no crypto backend found"
#endif
#endif /* HAD_ZIP_CRYPTO_H */

View File

@ -0,0 +1,110 @@
/*
zip_crypto_commoncrypto.c -- CommonCrypto wrapper.
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include "zipint.h"
#include "zip_crypto.h"
#include <fcntl.h>
#include <unistd.h>
void
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
if (aes == NULL) {
return;
}
CCCryptorRelease(aes);
}
bool
_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
size_t len;
CCCryptorUpdate(aes, in, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, ZIP_CRYPTO_AES_BLOCK_LENGTH, &len);
return true;
}
_zip_crypto_aes_t *
_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
_zip_crypto_aes_t *aes;
CCCryptorStatus ret;
ret = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionECBMode, key, key_size / 8, NULL, &aes);
switch (ret) {
case kCCSuccess:
return aes;
case kCCMemoryFailure:
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
case kCCParamError:
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
default:
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return NULL;
}
}
void
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
if (hmac == NULL) {
return;
}
_zip_crypto_clear(hmac, sizeof(*hmac));
free(hmac);
}
_zip_crypto_hmac_t *
_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
_zip_crypto_hmac_t *hmac;
if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
CCHmacInit(hmac, kCCHmacAlgSHA1, secret, secret_length);
return hmac;
}

View File

@ -0,0 +1,53 @@
/*
zip_crypto_commoncrypto.h -- definitions for CommonCrypto wrapper.
Copyright (C) 2018 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HAD_ZIP_CRYPTO_COMMONCRYPTO_H
#define HAD_ZIP_CRYPTO_COMMONCRYPTO_H
#include <CommonCrypto/CommonCrypto.h>
#define _zip_crypto_aes_t struct _CCCryptor
#define _zip_crypto_hmac_t CCHmacContext
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
#define _zip_crypto_hmac(hmac, data, length) (CCHmacUpdate((hmac), (data), (length)), true)
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
#define _zip_crypto_hmac_output(hmac, data) (CCHmacFinal((hmac), (data)), true)
#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)(key), (key_length), (salt), (salt_length), kCCPRFHmacAlgSHA1, (iterations), (output), (output_length)) == kCCSuccess)
#endif /* HAD_ZIP_CRYPTO_COMMONCRYPTO_H */

View File

@ -0,0 +1,134 @@
/*
zip_crypto_gnutls.c -- GnuTLS wrapper.
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include "zipint.h"
#include "zip_crypto.h"
_zip_crypto_aes_t *
_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
_zip_crypto_aes_t *aes;
if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
aes->key_size = key_size;
switch (aes->key_size) {
case 128:
nettle_aes128_set_encrypt_key(&aes->ctx.ctx_128, key);
break;
case 192:
nettle_aes192_set_encrypt_key(&aes->ctx.ctx_192, key);
break;
case 256:
nettle_aes256_set_encrypt_key(&aes->ctx.ctx_256, key);
break;
default:
zip_error_set(error, ZIP_ER_INVAL, 0);
free(aes);
return NULL;
}
return aes;
}
bool
_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
switch (aes->key_size) {
case 128:
nettle_aes128_encrypt(&aes->ctx.ctx_128, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
break;
case 192:
nettle_aes192_encrypt(&aes->ctx.ctx_192, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
break;
case 256:
nettle_aes256_encrypt(&aes->ctx.ctx_256, ZIP_CRYPTO_AES_BLOCK_LENGTH, out, in);
break;
}
return true;
}
void
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
if (aes == NULL) {
return;
}
_zip_crypto_clear(aes, sizeof(*aes));
free(aes);
}
_zip_crypto_hmac_t *
_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
_zip_crypto_hmac_t *hmac;
if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
if (gnutls_hmac_init(hmac, GNUTLS_MAC_SHA1, secret, secret_length) < 0) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
free(hmac);
return NULL;
}
return hmac;
}
void
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
zip_uint8_t buf[ZIP_CRYPTO_SHA1_LENGTH];
if (hmac == NULL) {
return;
}
gnutls_hmac_deinit(*hmac, buf);
_zip_crypto_clear(hmac, sizeof(*hmac));
free(hmac);
}
ZIP_EXTERN bool
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
return gnutls_rnd(GNUTLS_RND_KEY, buffer, length) == 0;
}

View File

@ -0,0 +1,68 @@
/*
zip_crypto_gnutls.h -- definitions for GnuTLS wrapper.
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HAD_ZIP_CRYPTO_GNUTLS_H
#define HAD_ZIP_CRYPTO_GNUTLS_H
#define HAVE_SECURE_RANDOM
#include <nettle/aes.h>
#include <nettle/pbkdf2.h>
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
typedef struct {
union {
struct aes128_ctx ctx_128;
struct aes192_ctx ctx_192;
struct aes256_ctx ctx_256;
} ctx;
zip_uint16_t key_size;
} _zip_crypto_aes_t;
#define _zip_crypto_hmac_t gnutls_hmac_hd_t
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
#define _zip_crypto_hmac(hmac, data, length) (gnutls_hmac(*(hmac), (data), (length)) == 0)
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
#define _zip_crypto_hmac_output(hmac, data) (gnutls_hmac_output(*(hmac), (data)), true)
#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (pbkdf2_hmac_sha1((key_length), (key), (iterations), (salt_length), (salt), (output_length), (output)), true)
#endif /* HAD_ZIP_CRYPTO_GNUTLS_H */

View File

@ -0,0 +1,162 @@
/*
zip_crypto_mbedtls.c -- mbed TLS wrapper
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include "zipint.h"
#include "zip_crypto.h"
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#include <mbedtls/pkcs5.h>
#include <limits.h>
_zip_crypto_aes_t *
_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
_zip_crypto_aes_t *aes;
if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
mbedtls_aes_init(aes);
mbedtls_aes_setkey_enc(aes, (const unsigned char *)key, (unsigned int)key_size);
return aes;
}
void
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
if (aes == NULL) {
return;
}
mbedtls_aes_free(aes);
free(aes);
}
_zip_crypto_hmac_t *
_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
_zip_crypto_hmac_t *hmac;
if (secret_length > INT_MAX) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
mbedtls_md_init(hmac);
if (mbedtls_md_setup(hmac, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
free(hmac);
return NULL;
}
if (mbedtls_md_hmac_starts(hmac, (const unsigned char *)secret, (size_t)secret_length) != 0) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
free(hmac);
return NULL;
}
return hmac;
}
void
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
if (hmac == NULL) {
return;
}
mbedtls_md_free(hmac);
free(hmac);
}
bool
_zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, int iterations, zip_uint8_t *output, zip_uint64_t output_length) {
mbedtls_md_context_t sha1_ctx;
bool ok = true;
mbedtls_md_init(&sha1_ctx);
if (mbedtls_md_setup(&sha1_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 1) != 0) {
ok = false;
}
if (ok && mbedtls_pkcs5_pbkdf2_hmac(&sha1_ctx, (const unsigned char *)key, (size_t)key_length, (const unsigned char *)salt, (size_t)salt_length, (unsigned int)iterations, (uint32_t)output_length, (unsigned char *)output) != 0) {
ok = false;
}
mbedtls_md_free(&sha1_ctx);
return ok;
}
typedef struct {
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
} zip_random_context_t;
ZIP_EXTERN bool
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
static zip_random_context_t *ctx = NULL;
const unsigned char *pers = "zip_crypto_mbedtls";
if (!ctx) {
ctx = (zip_random_context_t *)malloc(sizeof(zip_random_context_t));
if (!ctx) {
return false;
}
mbedtls_entropy_init(&ctx->entropy);
mbedtls_ctr_drbg_init(&ctx->ctr_drbg);
if (mbedtls_ctr_drbg_seed(&ctx->ctr_drbg, mbedtls_entropy_func, &ctx->entropy, pers, strlen(pers)) != 0) {
mbedtls_ctr_drbg_free(&ctx->ctr_drbg);
mbedtls_entropy_free(&ctx->entropy);
free(ctx);
ctx = NULL;
return false;
}
}
return mbedtls_ctr_drbg_random(&ctx->ctr_drbg, (unsigned char *)buffer, (size_t)length) == 0;
}

View File

@ -0,0 +1,56 @@
/*
zip_crypto_mbedtls.h -- definitions for mbedtls wrapper
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HAD_ZIP_CRYPTO_MBEDTLS_H
#define HAD_ZIP_CRYPTO_MBEDTLS_H
#define HAVE_SECURE_RANDOM
#include <mbedtls/aes.h>
#include <mbedtls/md.h>
#define _zip_crypto_aes_t mbedtls_aes_context
#define _zip_crypto_hmac_t mbedtls_md_context_t
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
#define _zip_crypto_aes_encrypt_block(aes, in, out) (mbedtls_aes_crypt_ecb((aes), MBEDTLS_AES_ENCRYPT, (in), (out)) == 0)
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
#define _zip_crypto_hmac(hmac, data, length) (mbedtls_md_hmac_update((hmac), (data), (length)) == 0)
#define _zip_crypto_hmac_output(hmac, data) (mbedtls_md_hmac_finish((hmac), (data)) == 0)
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
bool _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, int iterations, zip_uint8_t *output, zip_uint64_t output_length);
#endif /* HAD_ZIP_CRYPTO_MBEDTLS_H */

View File

@ -0,0 +1,184 @@
/*
zip_crypto_openssl.c -- OpenSSL wrapper.
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include "zipint.h"
#include "zip_crypto.h"
#include <limits.h>
#include <openssl/rand.h>
#if OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL)
#define USE_OPENSSL_1_0_API
#endif
_zip_crypto_aes_t *
_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
_zip_crypto_aes_t *aes;
const EVP_CIPHER* cipher_type;
switch (key_size) {
case 128:
cipher_type = EVP_aes_128_ecb();
break;
case 192:
cipher_type = EVP_aes_192_ecb();
break;
case 256:
cipher_type = EVP_aes_256_ecb();
break;
default:
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return NULL;
}
#ifdef USE_OPENSSL_1_0_API
if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
memset(aes, 0, sizeof(*aes));
#else
if ((aes = EVP_CIPHER_CTX_new()) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
#endif
if (EVP_EncryptInit_ex(aes, cipher_type, NULL, key, NULL) != 1) {
#ifdef USE_OPENSSL_1_0_API
free(aes);
#else
EVP_CIPHER_CTX_free(aes);
#endif
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return NULL;
}
return aes;
}
void
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
if (aes == NULL) {
return;
}
#ifdef USE_OPENSSL_1_0_API
EVP_CIPHER_CTX_cleanup(aes);
_zip_crypto_clear(aes, sizeof(*aes));
free(aes);
#else
EVP_CIPHER_CTX_free(aes);
#endif
}
bool
_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
int len;
if (EVP_EncryptUpdate(aes, out, &len, in, ZIP_CRYPTO_AES_BLOCK_LENGTH) != 1) {
return false;
}
return true;
}
_zip_crypto_hmac_t *
_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
_zip_crypto_hmac_t *hmac;
if (secret_length > INT_MAX) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
#ifdef USE_OPENSSL_1_0_API
if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
HMAC_CTX_init(hmac);
#else
if ((hmac = HMAC_CTX_new()) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
#endif
if (HMAC_Init_ex(hmac, secret, (int)secret_length, EVP_sha1(), NULL) != 1) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
#ifdef USE_OPENSSL_1_0_API
free(hmac);
#else
HMAC_CTX_free(hmac);
#endif
return NULL;
}
return hmac;
}
void
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
if (hmac == NULL) {
return;
}
#ifdef USE_OPENSSL_1_0_API
HMAC_CTX_cleanup(hmac);
_zip_crypto_clear(hmac, sizeof(*hmac));
free(hmac);
#else
HMAC_CTX_free(hmac);
#endif
}
bool
_zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) {
unsigned int length;
return HMAC_Final(hmac, data, &length) == 1;
}
ZIP_EXTERN bool
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
return RAND_bytes(buffer, length) == 1;
}

View File

@ -0,0 +1,56 @@
/*
zip_crypto_openssl.h -- definitions for OpenSSL wrapper.
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HAD_ZIP_CRYPTO_OPENSSL_H
#define HAD_ZIP_CRYPTO_OPENSSL_H
#define HAVE_SECURE_RANDOM
#include <openssl/evp.h>
#include <openssl/hmac.h>
#define _zip_crypto_aes_t EVP_CIPHER_CTX
#define _zip_crypto_hmac_t HMAC_CTX
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
#define _zip_crypto_hmac(hmac, data, length) (HMAC_Update((hmac), (data), (length)) == 1)
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data);
#define _zip_crypto_pbkdf2(key, key_length, salt, salt_length, iterations, output, output_length) (PKCS5_PBKDF2_HMAC_SHA1((const char *)(key), (key_length), (salt), (salt_length), (iterations), (output_length), (output)))
#endif /* HAD_ZIP_CRYPTO_OPENSSL_H */

View File

@ -0,0 +1,495 @@
/*
zip_crypto_win.c -- Windows Crypto API wrapper.
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdlib.h>
#include <limits.h>
#include "zipint.h"
#include "zip_crypto.h"
#define WIN32_LEAN_AND_MEAN
#define NOCRYPT
#include <windows.h>
#include <bcrypt.h>
#pragma comment(lib, "bcrypt.lib")
/*
This code is using the Cryptography API: Next Generation (CNG)
https://docs.microsoft.com/en-us/windows/desktop/seccng/cng-portal
This API is supported on
- Windows Vista or later (client OS)
- Windows Server 2008 (server OS)
- Windows Embedded Compact 2013 (don't know about Windows Embedded Compact 7)
The code was developed for Windows Embedded Compact 2013 (WEC2013),
but should be working for all of the above mentioned OSes.
There are 2 restrictions for WEC2013, Windows Vista and Windows Server 2008:
1.) The function "BCryptDeriveKeyPBKDF2" is not available
I found some code which is implementing this function using the deprecated Crypto API here:
https://www.idrix.fr/Root/content/view/37/54/
I took this code and converted it to the newer CNG API. The original code was more
flexible, but this is not needed here so i refactored it a bit and just kept what is needed.
The define "HAS_BCRYPTDERIVEKEYPBKDF2" controls whether "BCryptDeriveKeyPBKDF2"
of the CNG API is used or not. This define must not be set if you are compiling for WEC2013 or Windows Vista.
2.) "BCryptCreateHash" can't manage the memory needed for the hash object internally
On Windows 7 or later it is possible to pass NULL for the hash object buffer.
This is not supported on WEC2013, so we have to handle the memory allocation/deallocation ourselves.
There is no #ifdef to control that, because this is working for all supported OSes.
*/
#if !defined(WINCE) && !defined(__MINGW32__)
#define HAS_BCRYPTDERIVEKEYPBKDF2
#endif
#ifdef HAS_BCRYPTDERIVEKEYPBKDF2
bool
_zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length) {
BCRYPT_ALG_HANDLE hAlgorithm = NULL;
bool result;
if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG))) {
return false;
}
result = BCRYPT_SUCCESS(BCryptDeriveKeyPBKDF2(hAlgorithm, (PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length, 0));
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
return result;
}
#else
#include <math.h>
#define DIGEST_SIZE 20
#define BLOCK_SIZE 64
typedef struct {
BCRYPT_ALG_HANDLE hAlgorithm;
BCRYPT_HASH_HANDLE hInnerHash;
BCRYPT_HASH_HANDLE hOuterHash;
ULONG cbHashObject;
PUCHAR pbInnerHash;
PUCHAR pbOuterHash;
} PRF_CTX;
static void
hmacFree(PRF_CTX *pContext) {
if (pContext->hOuterHash)
BCryptDestroyHash(pContext->hOuterHash);
if (pContext->hInnerHash)
BCryptDestroyHash(pContext->hInnerHash);
free(pContext->pbOuterHash);
free(pContext->pbInnerHash);
if (pContext->hAlgorithm)
BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0);
}
static BOOL
hmacPrecomputeDigest(BCRYPT_HASH_HANDLE hHash, PUCHAR pbPassword, DWORD cbPassword, BYTE mask) {
BYTE buffer[BLOCK_SIZE];
DWORD i;
if (cbPassword > BLOCK_SIZE) {
return FALSE;
}
memset(buffer, mask, sizeof(buffer));
for (i = 0; i < cbPassword; ++i) {
buffer[i] = (char)(pbPassword[i] ^ mask);
}
return BCRYPT_SUCCESS(BCryptHashData(hHash, buffer, sizeof(buffer), 0));
}
static BOOL
hmacInit(PRF_CTX *pContext, PUCHAR pbPassword, DWORD cbPassword) {
BOOL bStatus = FALSE;
ULONG cbResult;
BYTE key[DIGEST_SIZE];
if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&pContext->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, 0)) || !BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&pContext->cbHashObject, sizeof(pContext->cbHashObject), &cbResult, 0)) || ((pContext->pbInnerHash = malloc(pContext->cbHashObject)) == NULL) || ((pContext->pbOuterHash = malloc(pContext->cbHashObject)) == NULL) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hInnerHash, pContext->pbInnerHash, pContext->cbHashObject, NULL, 0, 0)) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hOuterHash, pContext->pbOuterHash, pContext->cbHashObject, NULL, 0, 0))) {
goto hmacInit_end;
}
if (cbPassword > BLOCK_SIZE) {
BCRYPT_HASH_HANDLE hHash = NULL;
PUCHAR pbHashObject = malloc(pContext->cbHashObject);
if (pbHashObject == NULL) {
goto hmacInit_end;
}
bStatus = BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &hHash, pbHashObject, pContext->cbHashObject, NULL, 0, 0)) && BCRYPT_SUCCESS(BCryptHashData(hHash, pbPassword, cbPassword, 0)) && BCRYPT_SUCCESS(BCryptGetProperty(hHash, BCRYPT_HASH_LENGTH, (PUCHAR)&cbPassword, sizeof(cbPassword), &cbResult, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, key, cbPassword, 0));
if (hHash)
BCryptDestroyHash(hHash);
free(pbHashObject);
if (!bStatus) {
goto hmacInit_end;
}
pbPassword = key;
}
bStatus = hmacPrecomputeDigest(pContext->hInnerHash, pbPassword, cbPassword, 0x36) && hmacPrecomputeDigest(pContext->hOuterHash, pbPassword, cbPassword, 0x5C);
hmacInit_end:
if (bStatus == FALSE)
hmacFree(pContext);
return bStatus;
}
static BOOL
hmacCalculateInternal(BCRYPT_HASH_HANDLE hHashTemplate, PUCHAR pbData, DWORD cbData, PUCHAR pbOutput, DWORD cbOutput, DWORD cbHashObject) {
BOOL success = FALSE;
BCRYPT_HASH_HANDLE hHash = NULL;
PUCHAR pbHashObject = malloc(cbHashObject);
if (pbHashObject == NULL) {
return FALSE;
}
if (BCRYPT_SUCCESS(BCryptDuplicateHash(hHashTemplate, &hHash, pbHashObject, cbHashObject, 0))) {
success = BCRYPT_SUCCESS(BCryptHashData(hHash, pbData, cbData, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, pbOutput, cbOutput, 0));
BCryptDestroyHash(hHash);
}
free(pbHashObject);
return success;
}
static BOOL
hmacCalculate(PRF_CTX *pContext, PUCHAR pbData, DWORD cbData, PUCHAR pbDigest) {
DWORD cbResult;
DWORD cbHashObject;
return BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&cbHashObject, sizeof(cbHashObject), &cbResult, 0)) && hmacCalculateInternal(pContext->hInnerHash, pbData, cbData, pbDigest, DIGEST_SIZE, cbHashObject) && hmacCalculateInternal(pContext->hOuterHash, pbDigest, DIGEST_SIZE, pbDigest, DIGEST_SIZE, cbHashObject);
}
static void
myxor(LPBYTE ptr1, LPBYTE ptr2, DWORD dwLen) {
while (dwLen--)
*ptr1++ ^= *ptr2++;
}
BOOL
pbkdf2(PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, DWORD cIterations, PUCHAR pbDerivedKey, ULONG cbDerivedKey) {
BOOL bStatus = FALSE;
DWORD l, r, dwULen, i, j;
BYTE Ti[DIGEST_SIZE];
BYTE V[DIGEST_SIZE];
LPBYTE U = malloc(max((cbSalt + 4), DIGEST_SIZE));
PRF_CTX prfCtx = {0};
if (U == NULL) {
return FALSE;
}
if (pbPassword == NULL || cbPassword == 0 || pbSalt == NULL || cbSalt == 0 || cIterations == 0 || pbDerivedKey == NULL || cbDerivedKey == 0) {
free(U);
return FALSE;
}
if (!hmacInit(&prfCtx, pbPassword, cbPassword)) {
goto PBKDF2_end;
}
l = (DWORD)ceil((double)cbDerivedKey / (double)DIGEST_SIZE);
r = cbDerivedKey - (l - 1) * DIGEST_SIZE;
for (i = 1; i <= l; i++) {
ZeroMemory(Ti, DIGEST_SIZE);
for (j = 0; j < cIterations; j++) {
if (j == 0) {
/* construct first input for PRF */
memcpy(U, pbSalt, cbSalt);
U[cbSalt] = (BYTE)((i & 0xFF000000) >> 24);
U[cbSalt + 1] = (BYTE)((i & 0x00FF0000) >> 16);
U[cbSalt + 2] = (BYTE)((i & 0x0000FF00) >> 8);
U[cbSalt + 3] = (BYTE)((i & 0x000000FF));
dwULen = cbSalt + 4;
}
else {
memcpy(U, V, DIGEST_SIZE);
dwULen = DIGEST_SIZE;
}
if (!hmacCalculate(&prfCtx, U, dwULen, V)) {
goto PBKDF2_end;
}
myxor(Ti, V, DIGEST_SIZE);
}
if (i != l) {
memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, DIGEST_SIZE);
}
else {
/* Take only the first r bytes */
memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, r);
}
}
bStatus = TRUE;
PBKDF2_end:
hmacFree(&prfCtx);
free(U);
return bStatus;
}
bool
_zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length) {
return (key_length <= ZIP_UINT32_MAX) && pbkdf2((PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length);
}
#endif
struct _zip_crypto_aes_s {
BCRYPT_ALG_HANDLE hAlgorithm;
BCRYPT_KEY_HANDLE hKey;
ULONG cbKeyObject;
PUCHAR pbKeyObject;
};
_zip_crypto_aes_t *
_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
_zip_crypto_aes_t *aes = (_zip_crypto_aes_t *)calloc(1, sizeof(*aes));
ULONG cbResult;
ULONG key_length = key_size / 8;
if (aes == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&aes->hAlgorithm, BCRYPT_AES_ALGORITHM, NULL, 0))) {
_zip_crypto_aes_free(aes);
return NULL;
}
if (!BCRYPT_SUCCESS(BCryptSetProperty(aes->hAlgorithm, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0))) {
_zip_crypto_aes_free(aes);
return NULL;
}
if (!BCRYPT_SUCCESS(BCryptGetProperty(aes->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&aes->cbKeyObject, sizeof(aes->cbKeyObject), &cbResult, 0))) {
_zip_crypto_aes_free(aes);
return NULL;
}
aes->pbKeyObject = malloc(aes->cbKeyObject);
if (aes->pbKeyObject == NULL) {
_zip_crypto_aes_free(aes);
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
if (!BCRYPT_SUCCESS(BCryptGenerateSymmetricKey(aes->hAlgorithm, &aes->hKey, aes->pbKeyObject, aes->cbKeyObject, (PUCHAR)key, key_length, 0))) {
_zip_crypto_aes_free(aes);
return NULL;
}
return aes;
}
void
_zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
if (aes == NULL) {
return;
}
if (aes->hKey != NULL) {
BCryptDestroyKey(aes->hKey);
}
if (aes->pbKeyObject != NULL) {
free(aes->pbKeyObject);
}
if (aes->hAlgorithm != NULL) {
BCryptCloseAlgorithmProvider(aes->hAlgorithm, 0);
}
free(aes);
}
bool
_zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
ULONG cbResult;
NTSTATUS status = BCryptEncrypt(aes->hKey, (PUCHAR)in, ZIP_CRYPTO_AES_BLOCK_LENGTH, NULL, NULL, 0, (PUCHAR)out, ZIP_CRYPTO_AES_BLOCK_LENGTH, &cbResult, 0);
return BCRYPT_SUCCESS(status);
}
struct _zip_crypto_hmac_s {
BCRYPT_ALG_HANDLE hAlgorithm;
BCRYPT_HASH_HANDLE hHash;
DWORD cbHashObject;
PUCHAR pbHashObject;
DWORD cbHash;
PUCHAR pbHash;
};
/* https://code.msdn.microsoft.com/windowsdesktop/Hmac-Computation-Sample-11fe8ec1/sourcecode?fileId=42820&pathId=283874677 */
_zip_crypto_hmac_t *
_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
NTSTATUS status;
ULONG cbResult;
_zip_crypto_hmac_t *hmac;
if (secret_length > INT_MAX) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
hmac = (_zip_crypto_hmac_t *)calloc(1, sizeof(*hmac));
if (hmac == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
status = BCryptOpenAlgorithmProvider(&hmac->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
if (!BCRYPT_SUCCESS(status)) {
_zip_crypto_hmac_free(hmac);
return NULL;
}
status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hmac->cbHashObject, sizeof(hmac->cbHashObject), &cbResult, 0);
if (!BCRYPT_SUCCESS(status)) {
_zip_crypto_hmac_free(hmac);
return NULL;
}
hmac->pbHashObject = malloc(hmac->cbHashObject);
if (hmac->pbHashObject == NULL) {
_zip_crypto_hmac_free(hmac);
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_HASH_LENGTH, (PUCHAR)&hmac->cbHash, sizeof(hmac->cbHash), &cbResult, 0);
if (!BCRYPT_SUCCESS(status)) {
_zip_crypto_hmac_free(hmac);
return NULL;
}
hmac->pbHash = malloc(hmac->cbHash);
if (hmac->pbHash == NULL) {
_zip_crypto_hmac_free(hmac);
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
status = BCryptCreateHash(hmac->hAlgorithm, &hmac->hHash, hmac->pbHashObject, hmac->cbHashObject, (PUCHAR)secret, (ULONG)secret_length, 0);
if (!BCRYPT_SUCCESS(status)) {
_zip_crypto_hmac_free(hmac);
return NULL;
}
return hmac;
}
void
_zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
if (hmac == NULL) {
return;
}
if (hmac->hHash != NULL) {
BCryptDestroyHash(hmac->hHash);
}
if (hmac->pbHash != NULL) {
free(hmac->pbHash);
}
if (hmac->pbHashObject != NULL) {
free(hmac->pbHashObject);
}
if (hmac->hAlgorithm) {
BCryptCloseAlgorithmProvider(hmac->hAlgorithm, 0);
}
free(hmac);
}
bool
_zip_crypto_hmac(_zip_crypto_hmac_t *hmac, zip_uint8_t *data, zip_uint64_t length) {
if (hmac == NULL || length > ULONG_MAX) {
return false;
}
return BCRYPT_SUCCESS(BCryptHashData(hmac->hHash, data, (ULONG)length, 0));
}
bool
_zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) {
if (hmac == NULL) {
return false;
}
return BCRYPT_SUCCESS(BCryptFinishHash(hmac->hHash, data, hmac->cbHash, 0));
}
ZIP_EXTERN bool
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
return BCRYPT_SUCCESS(BCryptGenRandom(NULL, buffer, length, BCRYPT_USE_SYSTEM_PREFERRED_RNG));
}

View File

@ -0,0 +1,53 @@
/*
zip_crypto_win.h -- Windows Crypto API wrapper.
Copyright (C) 2018-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HAD_ZIP_CRYPTO_WIN_H
#define HAD_ZIP_CRYPTO_WIN_H
#define HAVE_SECURE_RANDOM
typedef struct _zip_crypto_aes_s _zip_crypto_aes_t;
typedef struct _zip_crypto_hmac_s _zip_crypto_hmac_t;
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes);
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error);
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out);
bool _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length);
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error);
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac);
bool _zip_crypto_hmac(_zip_crypto_hmac_t *hmac, zip_uint8_t *data, zip_uint64_t length);
bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data);
#endif /* HAD_ZIP_CRYPTO_WIN_H */

View File

@ -1,9 +1,9 @@
/*
zip_delete.c -- delete file from zip archive
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -40,27 +40,27 @@ zip_delete(zip_t *za, zip_uint64_t idx) {
const char *name;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if ((name = _zip_get_name(za, idx, 0, &za->error)) == NULL) {
return -1;
return -1;
}
if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) {
return -1;
return -1;
}
/* allow duplicate file names, because the file will
* be removed directly afterwards */
if (_zip_unchange(za, idx, 1) != 0)
return -1;
return -1;
za->entry[idx].deleted = 1;

View File

@ -1,9 +1,9 @@
/*
zip_dir_add.c -- add directory
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -48,31 +48,31 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
zip_source_t *source;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (name == NULL) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
s = NULL;
len = strlen(name);
if (name[len - 1] != '/') {
if ((s = (char *)malloc(len + 2)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
strcpy(s, name);
s[len] = '/';
s[len + 1] = '\0';
if ((s = (char *)malloc(len + 2)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
strcpy(s, name);
s[len] = '/';
s[len + 1] = '\0';
}
if ((source = zip_source_buffer(za, NULL, 0, 0)) == NULL) {
free(s);
return -1;
free(s);
return -1;
}
idx = _zip_file_replace(za, ZIP_UINT64_MAX, s ? s : name, source, flags);
@ -80,12 +80,12 @@ zip_dir_add(zip_t *za, const char *name, zip_flags_t flags) {
free(s);
if (idx < 0)
zip_source_free(source);
zip_source_free(source);
else {
if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) {
zip_delete(za, (zip_uint64_t)idx);
return -1;
}
if (zip_file_set_external_attributes(za, (zip_uint64_t)idx, 0, ZIP_OPSYS_DEFAULT, ZIP_EXT_ATTRIB_DEFAULT_DIR) < 0) {
zip_delete(za, (zip_uint64_t)idx);
return -1;
}
}
return idx;

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
/*
zip_discard.c -- discard and free struct zip
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -46,11 +46,11 @@ zip_discard(zip_t *za) {
zip_uint64_t i;
if (za == NULL)
return;
return;
if (za->src) {
zip_source_close(za->src);
zip_source_free(za->src);
zip_source_close(za->src);
zip_source_free(za->src);
}
free(za->default_password);
@ -60,13 +60,13 @@ zip_discard(zip_t *za) {
_zip_hash_free(za->names);
if (za->entry) {
for (i = 0; i < za->nentry; i++)
_zip_entry_finalize(za->entry + i);
free(za->entry);
for (i = 0; i < za->nentry; i++)
_zip_entry_finalize(za->entry + i);
free(za->entry);
}
for (i = 0; i < za->nopen_source; i++) {
_zip_source_invalidate(za->open_source[i]);
_zip_source_invalidate(za->open_source[i]);
}
free(za->open_source);

View File

@ -1,9 +1,9 @@
/*
zip_entry.c -- struct zip_entry helper functions
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -1,9 +1,9 @@
/*
zip_error.c -- zip_error_t helper functions
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -67,30 +67,31 @@ zip_error_init_with_code(zip_error_t *error, int ze) {
zip_error_init(error);
error->zip_err = ze;
switch (zip_error_system_type(error)) {
case ZIP_ET_SYS:
error->sys_err = errno;
break;
default:
error->sys_err = 0;
break;
case ZIP_ET_SYS:
case ZIP_ET_LIBZIP:
error->sys_err = errno;
break;
default:
error->sys_err = 0;
break;
}
}
ZIP_EXTERN int
zip_error_system_type(const zip_error_t *error) {
if (error->zip_err < 0 || error->zip_err >= _zip_nerr_str)
return ZIP_ET_NONE;
if (error->zip_err < 0 || error->zip_err >= _zip_err_str_count)
return ZIP_ET_NONE;
return _zip_err_type[error->zip_err];
return _zip_err_str[error->zip_err].type;
}
void
_zip_error_clear(zip_error_t *err) {
if (err == NULL)
return;
return;
err->zip_err = ZIP_ER_OK;
err->sys_err = 0;
@ -100,7 +101,7 @@ _zip_error_clear(zip_error_t *err) {
void
_zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
if (dst == NULL) {
return;
return;
}
dst->zip_err = src->zip_err;
@ -111,12 +112,12 @@ _zip_error_copy(zip_error_t *dst, const zip_error_t *src) {
void
_zip_error_get(const zip_error_t *err, int *zep, int *sep) {
if (zep)
*zep = err->zip_err;
*zep = err->zip_err;
if (sep) {
if (zip_error_system_type(err) != ZIP_ET_NONE)
*sep = err->sys_err;
else
*sep = 0;
if (zip_error_system_type(err) != ZIP_ET_NONE)
*sep = err->sys_err;
else
*sep = 0;
}
}
@ -124,8 +125,8 @@ _zip_error_get(const zip_error_t *err, int *zep, int *sep) {
void
zip_error_set(zip_error_t *err, int ze, int se) {
if (err) {
err->zip_err = ze;
err->sys_err = se;
err->zip_err = ze;
err->sys_err = se;
}
}
@ -141,7 +142,7 @@ zip_error_to_data(const zip_error_t *error, void *data, zip_uint64_t length) {
int *e = (int *)data;
if (length < sizeof(int) * 2) {
return -1;
return -1;
}
e[0] = zip_error_code_zip(error);

View File

@ -1,9 +1,9 @@
/*
zip_error_clear.c -- clear zip error
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -38,7 +38,7 @@
ZIP_EXTERN void
zip_error_clear(zip_t *za) {
if (za == NULL)
return;
return;
_zip_error_clear(&za->error);
}

View File

@ -1,9 +1,9 @@
/*
zip_error_get.c -- get zip error
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -1,9 +1,9 @@
/*
zip_error_get_sys_type.c -- return type of system error code
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -37,8 +37,9 @@
ZIP_EXTERN int
zip_error_get_sys_type(int ze) {
if (ze < 0 || ze >= _zip_nerr_str)
return 0;
if (ze < 0 || ze >= _zip_err_str_count) {
return 0;
}
return _zip_err_type[ze];
return _zip_err_str[ze].type;
}

View File

@ -1,9 +1,9 @@
/*
zip_error_sterror.c -- get string representation of struct zip_error
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -39,45 +39,70 @@
#include "zipint.h"
ZIP_EXTERN const char *
zip_error_strerror(zip_error_t *err) {
const char *zs, *ss;
const char *zip_error_string, *system_error_string;
char buf[128], *s;
zip_error_fini(err);
if (err->zip_err < 0 || err->zip_err >= _zip_nerr_str) {
sprintf(buf, "Unknown error %d", err->zip_err);
zs = NULL;
ss = buf;
if (err->zip_err < 0 || err->zip_err >= _zip_err_str_count) {
snprintf(buf, sizeof(buf), "Unknown error %d", err->zip_err);
buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */
zip_error_string = NULL;
system_error_string = buf;
}
else {
zs = _zip_err_str[err->zip_err];
zip_error_string = _zip_err_str[err->zip_err].description;
switch (_zip_err_type[err->zip_err]) {
case ZIP_ET_SYS:
ss = strerror(err->sys_err);
break;
case ZIP_ET_ZLIB:
ss = zError(err->sys_err);
break;
default:
ss = NULL;
}
switch (_zip_err_str[err->zip_err].type) {
case ZIP_ET_SYS:
system_error_string = strerror(err->sys_err);
break;
case ZIP_ET_ZLIB:
system_error_string = zError(err->sys_err);
break;
case ZIP_ET_LIBZIP: {
zip_uint8_t error = GET_ERROR_FROM_DETAIL(err->sys_err);
int index = GET_INDEX_FROM_DETAIL(err->sys_err);
if (error == 0) {
system_error_string = NULL;
}
else if (error >= _zip_err_details_count) {
snprintf(buf, sizeof(buf), "invalid detail error %u", error);
buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */
system_error_string = buf;
}
else if (_zip_err_details[error].type == ZIP_DETAIL_ET_ENTRY && index < MAX_DETAIL_INDEX) {
snprintf(buf, sizeof(buf), "entry %d: %s", index, _zip_err_details[error].description);
buf[sizeof(buf) - 1] = '\0'; /* make sure string is NUL-terminated */
system_error_string = buf;
}
else {
system_error_string = _zip_err_details[error].description;
}
break;
}
default:
system_error_string = NULL;
}
}
if (ss == NULL)
return zs;
if (system_error_string == NULL) {
return zip_error_string;
}
else {
if ((s = (char *)malloc(strlen(ss) + (zs ? strlen(zs) + 2 : 0) + 1)) == NULL)
return _zip_err_str[ZIP_ER_MEMORY];
if ((s = (char *)malloc(strlen(system_error_string) + (zip_error_string ? strlen(zip_error_string) + 2 : 0) + 1)) == NULL) {
return _zip_err_str[ZIP_ER_MEMORY].description;
}
sprintf(s, "%s%s%s", (zs ? zs : ""), (zs ? ": " : ""), ss);
err->str = s;
sprintf(s, "%s%s%s", (zip_error_string ? zip_error_string : ""), (zip_error_string ? ": " : ""), system_error_string);
err->str = s;
return s;
return s;
}
}

View File

@ -1,9 +1,9 @@
/*
zip_error_to_str.c -- get string representation of zip error code
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -44,22 +44,23 @@ ZIP_EXTERN int
zip_error_to_str(char *buf, zip_uint64_t len, int ze, int se) {
const char *zs, *ss;
if (ze < 0 || ze >= _zip_nerr_str)
return snprintf(buf, len, "Unknown error %d", ze);
if (ze < 0 || ze >= _zip_err_str_count) {
return snprintf(buf, len, "Unknown error %d", ze);
}
zs = _zip_err_str[ze];
zs = _zip_err_str[ze].description;
switch (_zip_err_type[ze]) {
case ZIP_ET_SYS:
ss = strerror(se);
break;
case ZIP_ET_ZLIB:
ss = zError(se);
break;
default:
ss = NULL;
switch (_zip_err_str[ze].type) {
case ZIP_ET_SYS:
ss = strerror(se);
break;
case ZIP_ET_ZLIB:
ss = zError(se);
break;
default:
ss = NULL;
}
return snprintf(buf, len, "%s%s%s", zs, (ss ? ": " : ""), (ss ? ss : ""));

View File

@ -1,9 +1,9 @@
/*
zip_extra_field.c -- manipulate extra fields
Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -44,19 +44,19 @@ _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) {
head = prev = NULL;
while (ef) {
if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
_zip_ef_free(head);
return NULL;
}
if ((def = _zip_ef_new(ef->id, ef->size, ef->data, ef->flags)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
_zip_ef_free(head);
return NULL;
}
if (head == NULL)
head = def;
if (prev)
prev->next = def;
prev = def;
if (head == NULL)
head = def;
if (prev)
prev->next = def;
prev = def;
ef = ef->next;
ef = ef->next;
}
return head;
@ -72,27 +72,27 @@ _zip_ef_delete_by_id(zip_extra_field_t *ef, zip_uint16_t id, zip_uint16_t id_idx
head = ef;
prev = NULL;
for (; ef; ef = (prev ? prev->next : head)) {
if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) {
if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) {
ef->flags &= ~(flags & ZIP_EF_BOTH);
if ((ef->flags & ZIP_EF_BOTH) == 0) {
if (prev)
prev->next = ef->next;
else
head = ef->next;
ef->next = NULL;
_zip_ef_free(ef);
if ((ef->flags & flags & ZIP_EF_BOTH) && ((ef->id == id) || (id == ZIP_EXTRA_FIELD_ALL))) {
if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) {
ef->flags &= ~(flags & ZIP_EF_BOTH);
if ((ef->flags & ZIP_EF_BOTH) == 0) {
if (prev)
prev->next = ef->next;
else
head = ef->next;
ef->next = NULL;
_zip_ef_free(ef);
if (id_idx == ZIP_EXTRA_FIELD_ALL)
continue;
}
}
if (id_idx == ZIP_EXTRA_FIELD_ALL)
continue;
}
}
i++;
if (i > id_idx)
break;
}
prev = ef;
i++;
if (i > id_idx)
break;
}
prev = ef;
}
return head;
@ -104,10 +104,10 @@ _zip_ef_free(zip_extra_field_t *ef) {
zip_extra_field_t *ef2;
while (ef) {
ef2 = ef->next;
free(ef->data);
free(ef);
ef = ef2;
ef2 = ef->next;
free(ef->data);
free(ef);
ef = ef2;
}
}
@ -120,19 +120,19 @@ _zip_ef_get_by_id(const zip_extra_field_t *ef, zip_uint16_t *lenp, zip_uint16_t
i = 0;
for (; ef; ef = ef->next) {
if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) {
if (i < id_idx) {
i++;
continue;
}
if (ef->id == id && (ef->flags & flags & ZIP_EF_BOTH)) {
if (i < id_idx) {
i++;
continue;
}
if (lenp)
*lenp = ef->size;
if (ef->size > 0)
return ef->data;
else
return empty;
}
if (lenp)
*lenp = ef->size;
if (ef->size > 0)
return ef->data;
else
return empty;
}
}
zip_error_set(error, ZIP_ER_NOENT, 0);
@ -146,28 +146,28 @@ _zip_ef_merge(zip_extra_field_t *to, zip_extra_field_t *from) {
int duplicate;
if (to == NULL)
return from;
return from;
for (tail = to; tail->next; tail = tail->next)
;
;
for (; from; from = ef2) {
ef2 = from->next;
ef2 = from->next;
duplicate = 0;
for (tt = to; tt; tt = tt->next) {
if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) {
tt->flags |= (from->flags & ZIP_EF_BOTH);
duplicate = 1;
break;
}
}
duplicate = 0;
for (tt = to; tt; tt = tt->next) {
if (tt->id == from->id && tt->size == from->size && (tt->size == 0 || memcmp(tt->data, from->data, tt->size) == 0)) {
tt->flags |= (from->flags & ZIP_EF_BOTH);
duplicate = 1;
break;
}
}
from->next = NULL;
if (duplicate)
_zip_ef_free(from);
else
tail = tail->next = from;
from->next = NULL;
if (duplicate)
_zip_ef_free(from);
else
tail = tail->next = from;
}
return to;
@ -179,20 +179,20 @@ _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_fla
zip_extra_field_t *ef;
if ((ef = (zip_extra_field_t *)malloc(sizeof(*ef))) == NULL)
return NULL;
return NULL;
ef->next = NULL;
ef->flags = flags;
ef->id = id;
ef->size = size;
if (size > 0) {
if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
free(ef);
return NULL;
}
if ((ef->data = (zip_uint8_t *)_zip_memdup(data, size, NULL)) == NULL) {
free(ef);
return NULL;
}
}
else
ef->data = NULL;
ef->data = NULL;
return ef;
}
@ -204,63 +204,63 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_
zip_extra_field_t *ef, *ef2, *ef_head;
if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
ef_head = ef = NULL;
while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) {
zip_uint16_t fid, flen;
zip_uint8_t *ef_data;
zip_uint16_t fid, flen;
zip_uint8_t *ef_data;
fid = _zip_buffer_get_16(buffer);
flen = _zip_buffer_get_16(buffer);
ef_data = _zip_buffer_get(buffer, flen);
fid = _zip_buffer_get_16(buffer);
flen = _zip_buffer_get_16(buffer);
ef_data = _zip_buffer_get(buffer, flen);
if (ef_data == NULL) {
zip_error_set(error, ZIP_ER_INCONS, 0);
_zip_buffer_free(buffer);
_zip_ef_free(ef_head);
return false;
}
if (ef_data == NULL) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_INVALID_EF_LENGTH);
_zip_buffer_free(buffer);
_zip_ef_free(ef_head);
return false;
}
if ((ef2 = _zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
_zip_buffer_free(buffer);
_zip_ef_free(ef_head);
return false;
}
if ((ef2 = _zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
_zip_buffer_free(buffer);
_zip_ef_free(ef_head);
return false;
}
if (ef_head) {
ef->next = ef2;
ef = ef2;
}
else
ef_head = ef = ef2;
if (ef_head) {
ef->next = ef2;
ef = ef2;
}
else
ef_head = ef = ef2;
}
if (!_zip_buffer_eof(buffer)) {
/* Android APK files align stored file data with padding in extra fields; ignore. */
/* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */
size_t glen = _zip_buffer_left(buffer);
zip_uint8_t *garbage;
garbage = _zip_buffer_get(buffer, glen);
if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) {
zip_error_set(error, ZIP_ER_INCONS, 0);
_zip_buffer_free(buffer);
_zip_ef_free(ef_head);
return false;
}
/* Android APK files align stored file data with padding in extra fields; ignore. */
/* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */
size_t glen = _zip_buffer_left(buffer);
zip_uint8_t *garbage;
garbage = _zip_buffer_get(buffer, glen);
if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) {
zip_error_set(error, ZIP_ER_INCONS, ZIP_ER_DETAIL_EF_TRAILING_GARBAGE);
_zip_buffer_free(buffer);
_zip_ef_free(ef_head);
return false;
}
}
_zip_buffer_free(buffer);
if (ef_head_p) {
*ef_head_p = ef_head;
*ef_head_p = ef_head;
}
else {
_zip_ef_free(ef_head);
_zip_ef_free(ef_head);
}
return true;
@ -276,20 +276,20 @@ _zip_ef_remove_internal(zip_extra_field_t *ef) {
prev = NULL;
while (ef) {
if (ZIP_EF_IS_INTERNAL(ef->id)) {
next = ef->next;
if (ef_head == ef)
ef_head = next;
ef->next = NULL;
_zip_ef_free(ef);
if (prev)
prev->next = next;
ef = next;
}
else {
prev = ef;
ef = ef->next;
}
if (ZIP_EF_IS_INTERNAL(ef->id)) {
next = ef->next;
if (ef_head == ef)
ef_head = next;
ef->next = NULL;
_zip_ef_free(ef);
if (prev)
prev->next = next;
ef = next;
}
else {
prev = ef;
ef = ef->next;
}
}
return ef_head;
@ -302,8 +302,8 @@ _zip_ef_size(const zip_extra_field_t *ef, zip_flags_t flags) {
size = 0;
for (; ef; ef = ef->next) {
if (ef->flags & flags & ZIP_EF_BOTH)
size = (zip_uint16_t)(size + 4 + ef->size);
if (ef->flags & flags & ZIP_EF_BOTH)
size = (zip_uint16_t)(size + 4 + ef->size);
}
return size;
@ -316,30 +316,30 @@ _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags) {
zip_buffer_t *buffer = _zip_buffer_new(b, sizeof(b));
if (buffer == NULL) {
return -1;
return -1;
}
for (; ef; ef = ef->next) {
if (ef->flags & flags & ZIP_EF_BOTH) {
_zip_buffer_set_offset(buffer, 0);
_zip_buffer_put_16(buffer, ef->id);
_zip_buffer_put_16(buffer, ef->size);
if (!_zip_buffer_ok(buffer)) {
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
_zip_buffer_free(buffer);
return -1;
}
if (_zip_write(za, b, 4) < 0) {
_zip_buffer_free(buffer);
return -1;
}
if (ef->size > 0) {
if (_zip_write(za, ef->data, ef->size) < 0) {
_zip_buffer_free(buffer);
return -1;
}
}
}
if (ef->flags & flags & ZIP_EF_BOTH) {
_zip_buffer_set_offset(buffer, 0);
_zip_buffer_put_16(buffer, ef->id);
_zip_buffer_put_16(buffer, ef->size);
if (!_zip_buffer_ok(buffer)) {
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
_zip_buffer_free(buffer);
return -1;
}
if (_zip_write(za, b, 4) < 0) {
_zip_buffer_free(buffer);
return -1;
}
if (ef->size > 0) {
if (_zip_write(za, ef->data, ef->size) < 0) {
_zip_buffer_free(buffer);
return -1;
}
}
}
}
_zip_buffer_free(buffer);
@ -355,71 +355,71 @@ _zip_read_local_ef(zip_t *za, zip_uint64_t idx) {
zip_uint16_t fname_len, ef_len;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
e = za->entry + idx;
if (e->orig == NULL || e->orig->local_extra_fields_read)
return 0;
return 0;
if (e->orig->offset + 26 > ZIP_INT64_MAX) {
zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG);
return -1;
zip_error_set(&za->error, ZIP_ER_SEEK, EFBIG);
return -1;
}
if (zip_source_seek(za->src, (zip_int64_t)(e->orig->offset + 26), SEEK_SET) < 0) {
_zip_error_set_from_source(&za->error, za->src);
return -1;
_zip_error_set_from_source(&za->error, za->src);
return -1;
}
if ((buffer = _zip_buffer_new_from_source(za->src, sizeof(b), b, &za->error)) == NULL) {
return -1;
return -1;
}
fname_len = _zip_buffer_get_16(buffer);
ef_len = _zip_buffer_get_16(buffer);
if (!_zip_buffer_eof(buffer)) {
_zip_buffer_free(buffer);
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
_zip_buffer_free(buffer);
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
return -1;
}
_zip_buffer_free(buffer);
if (ef_len > 0) {
zip_extra_field_t *ef;
zip_uint8_t *ef_raw;
zip_extra_field_t *ef;
zip_uint8_t *ef_raw;
if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) {
zip_error_set(&za->error, ZIP_ER_SEEK, errno);
return -1;
}
if (zip_source_seek(za->src, fname_len, SEEK_CUR) < 0) {
zip_error_set(&za->error, ZIP_ER_SEEK, errno);
return -1;
}
ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error);
ef_raw = _zip_read_data(NULL, za->src, ef_len, 0, &za->error);
if (ef_raw == NULL)
return -1;
if (ef_raw == NULL)
return -1;
if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) {
free(ef_raw);
return -1;
}
free(ef_raw);
if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) {
free(ef_raw);
return -1;
}
free(ef_raw);
if (ef) {
ef = _zip_ef_remove_internal(ef);
e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
}
if (ef) {
ef = _zip_ef_remove_internal(ef);
e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
}
}
e->orig->local_extra_fields_read = 1;
if (e->changes && e->changes->local_extra_fields_read == 0) {
e->changes->extra_fields = e->orig->extra_fields;
e->changes->local_extra_fields_read = 1;
e->changes->extra_fields = e->orig->extra_fields;
e->changes->local_extra_fields_read = 1;
}
return 0;

View File

@ -1,9 +1,9 @@
/*
zip_extra_field_api.c -- public extra fields API functions
Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -40,25 +40,25 @@ zip_file_extra_field_delete(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zi
zip_dirent_t *de;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
return -1;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
return -1;
return -1;
de = za->entry[idx].changes;
@ -72,25 +72,25 @@ zip_file_extra_field_delete_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
zip_dirent_t *de;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (((flags & ZIP_EF_BOTH) == ZIP_EF_BOTH) && (ef_idx != ZIP_EXTRA_FIELD_ALL)) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
return -1;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
return -1;
return -1;
de = za->entry[idx].changes;
@ -108,34 +108,34 @@ zip_file_extra_field_get(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_idx, zip_u
int i;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return NULL;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return NULL;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
return NULL;
return NULL;
if (flags & ZIP_FL_LOCAL)
if (_zip_read_local_ef(za, idx) < 0)
return NULL;
if (_zip_read_local_ef(za, idx) < 0)
return NULL;
i = 0;
for (ef = de->extra_fields; ef; ef = ef->next) {
if (ef->flags & flags & ZIP_EF_BOTH) {
if (i < ef_idx) {
i++;
continue;
}
if (ef->flags & flags & ZIP_EF_BOTH) {
if (i < ef_idx) {
i++;
continue;
}
if (idp)
*idp = ef->id;
if (lenp)
*lenp = ef->size;
if (ef->size > 0)
return ef->data;
else
return empty;
}
if (idp)
*idp = ef->id;
if (lenp)
*lenp = ef->size;
if (ef->size > 0)
return ef->data;
else
return empty;
}
}
zip_error_set(&za->error, ZIP_ER_NOENT, 0);
@ -148,16 +148,16 @@ zip_file_extra_field_get_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id,
zip_dirent_t *de;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return NULL;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return NULL;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
return NULL;
return NULL;
if (flags & ZIP_FL_LOCAL)
if (_zip_read_local_ef(za, idx) < 0)
return NULL;
if (_zip_read_local_ef(za, idx) < 0)
return NULL;
return _zip_ef_get_by_id(de->extra_fields, lenp, ef_id, ef_idx, flags, &za->error);
}
@ -170,21 +170,21 @@ zip_file_extra_fields_count(zip_t *za, zip_uint64_t idx, zip_flags_t flags) {
zip_uint16_t n;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
return -1;
return -1;
if (flags & ZIP_FL_LOCAL)
if (_zip_read_local_ef(za, idx) < 0)
return -1;
if (_zip_read_local_ef(za, idx) < 0)
return -1;
n = 0;
for (ef = de->extra_fields; ef; ef = ef->next)
if (ef->flags & flags & ZIP_EF_BOTH)
n++;
if (ef->flags & flags & ZIP_EF_BOTH)
n++;
return (zip_int16_t)n;
}
@ -197,21 +197,21 @@ zip_file_extra_fields_count_by_id(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_i
zip_uint16_t n;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if ((de = _zip_get_dirent(za, idx, flags, &za->error)) == NULL)
return -1;
return -1;
if (flags & ZIP_FL_LOCAL)
if (_zip_read_local_ef(za, idx) < 0)
return -1;
if (_zip_read_local_ef(za, idx) < 0)
return -1;
n = 0;
for (ef = de->extra_fields; ef; ef = ef->next)
if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH))
n++;
if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH))
n++;
return (zip_int16_t)n;
}
@ -225,25 +225,25 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
int i, found, new_len;
if ((flags & ZIP_EF_BOTH) == 0) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
return -1;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (ZIP_EF_IS_INTERNAL(ef_id)) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (_zip_file_extra_field_prepare_for_change(za, idx) < 0)
return -1;
return -1;
de = za->entry[idx].changes;
@ -253,67 +253,67 @@ zip_file_extra_field_set(zip_t *za, zip_uint64_t idx, zip_uint16_t ef_id, zip_ui
found = 0;
for (; ef; ef = ef->next) {
if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) {
if (i == ef_idx) {
found = 1;
break;
}
i++;
}
ef_prev = ef;
if (ef->id == ef_id && (ef->flags & flags & ZIP_EF_BOTH)) {
if (i == ef_idx) {
found = 1;
break;
}
i++;
}
ef_prev = ef;
}
if (i < ef_idx && ef_idx != ZIP_EXTRA_FIELD_NEW) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (flags & ZIP_EF_LOCAL)
ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL);
ls = _zip_ef_size(de->extra_fields, ZIP_EF_LOCAL);
else
ls = 0;
ls = 0;
if (flags & ZIP_EF_CENTRAL)
cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
cs = _zip_ef_size(de->extra_fields, ZIP_EF_CENTRAL);
else
cs = 0;
cs = 0;
new_len = ls > cs ? ls : cs;
if (found)
new_len -= ef->size + 4;
new_len -= ef->size + 4;
new_len += len + 4;
if (new_len > ZIP_UINT16_MAX) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if ((ef_new = _zip_ef_new(ef_id, len, data, flags)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
if (found) {
if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) {
ef_new->next = ef->next;
ef->next = NULL;
_zip_ef_free(ef);
if (ef_prev)
ef_prev->next = ef_new;
else
de->extra_fields = ef_new;
}
else {
ef->flags &= ~(flags & ZIP_EF_BOTH);
ef_new->next = ef->next;
ef->next = ef_new;
}
if ((ef->flags & ZIP_EF_BOTH) == (flags & ZIP_EF_BOTH)) {
ef_new->next = ef->next;
ef->next = NULL;
_zip_ef_free(ef);
if (ef_prev)
ef_prev->next = ef_new;
else
de->extra_fields = ef_new;
}
else {
ef->flags &= ~(flags & ZIP_EF_BOTH);
ef_new->next = ef->next;
ef->next = ef_new;
}
}
else if (ef_prev) {
ef_new->next = ef_prev->next;
ef_prev->next = ef_new;
ef_new->next = ef_prev->next;
ef_prev->next = ef_new;
}
else
de->extra_fields = ef_new;
de->extra_fields = ef_new;
return 0;
}
@ -324,30 +324,30 @@ _zip_file_extra_field_prepare_for_change(zip_t *za, zip_uint64_t idx) {
zip_entry_t *e;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
e = za->entry + idx;
if (e->changes && (e->changes->changed & ZIP_DIRENT_EXTRA_FIELD))
return 0;
return 0;
if (e->orig) {
if (_zip_read_local_ef(za, idx) < 0)
return -1;
if (_zip_read_local_ef(za, idx) < 0)
return -1;
}
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
if (e->orig && e->orig->extra_fields) {
if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
return -1;
if ((e->changes->extra_fields = _zip_ef_clone(e->orig->extra_fields, &za->error)) == NULL)
return -1;
}
e->changes->changed |= ZIP_DIRENT_EXTRA_FIELD;

View File

@ -1,9 +1,9 @@
/*
zip_fclose.c -- close file in zip archive
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -42,11 +42,11 @@ zip_fclose(zip_file_t *zf) {
int ret;
if (zf->src)
zip_source_free(zf->src);
zip_source_free(zf->src);
ret = 0;
if (zf->error.zip_err)
ret = zf->error.zip_err;
ret = zf->error.zip_err;
zip_error_fini(&zf->error);
free(zf);

View File

@ -1,9 +1,9 @@
/*
zip_fdopen.c -- open read-only archive from file descriptor
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -47,37 +47,37 @@ zip_fdopen(int fd_orig, int _flags, int *zep) {
struct zip_error error;
if (_flags < 0 || (_flags & ~(ZIP_CHECKCONS | ZIP_RDONLY))) {
_zip_set_open_error(zep, NULL, ZIP_ER_INVAL);
return NULL;
_zip_set_open_error(zep, NULL, ZIP_ER_INVAL);
return NULL;
}
/* We dup() here to avoid messing with the passed in fd.
We could not restore it to the original state in case of error. */
if ((fd = dup(fd_orig)) < 0) {
_zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
return NULL;
_zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
return NULL;
}
if ((fp = fdopen(fd, "rb")) == NULL) {
close(fd);
_zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
return NULL;
close(fd);
_zip_set_open_error(zep, NULL, ZIP_ER_OPEN);
return NULL;
}
zip_error_init(&error);
if ((src = zip_source_filep_create(fp, 0, -1, &error)) == NULL) {
fclose(fp);
_zip_set_open_error(zep, &error, 0);
zip_error_fini(&error);
return NULL;
fclose(fp);
_zip_set_open_error(zep, &error, 0);
zip_error_fini(&error);
return NULL;
}
if ((za = zip_open_from_source(src, _flags, &error)) == NULL) {
zip_source_free(src);
_zip_set_open_error(zep, &error, 0);
zip_error_fini(&error);
return NULL;
zip_source_free(src);
_zip_set_open_error(zep, &error, 0);
zip_error_fini(&error);
return NULL;
}
zip_error_fini(&error);

View File

@ -1,9 +1,9 @@
/*
zip_file_add.c -- add file via callback function
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -36,16 +36,16 @@
/*
NOTE: Return type is signed so we can return -1 on error.
The index can not be larger than ZIP_INT64_MAX since the size
of the central directory cannot be larger than
ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
The index can not be larger than ZIP_INT64_MAX since the size
of the central directory cannot be larger than
ZIP_UINT64_MAX, and each entry is larger than 2 bytes.
*/
ZIP_EXTERN zip_int64_t
zip_file_add(zip_t *za, const char *name, zip_source_t *source, zip_flags_t flags) {
if (name == NULL || source == NULL) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
return _zip_file_replace(za, ZIP_UINT64_MAX, name, source, flags);

View File

@ -1,9 +1,9 @@
/*
zip_file_error_clear.c -- clear zip file error
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -38,7 +38,7 @@
ZIP_EXTERN void
zip_file_error_clear(zip_file_t *zf) {
if (zf == NULL)
return;
return;
_zip_error_clear(&zf->error);
}

View File

@ -1,9 +1,9 @@
/*
zip_file_error_get.c -- get zip file error
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -1,9 +1,9 @@
/*
zip_file_get_comment.c -- get file comment
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -43,13 +43,13 @@ zip_file_get_comment(zip_t *za, zip_uint64_t idx, zip_uint32_t *lenp, zip_flags_
const zip_uint8_t *str;
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
return NULL;
return NULL;
if ((str = _zip_string_get(de->comment, &len, flags, &za->error)) == NULL)
return NULL;
return NULL;
if (lenp)
*lenp = len;
*lenp = len;
return (const char *)str;
}

View File

@ -1,9 +1,9 @@
/*
zip_file_get_external_attributes.c -- get opsys/external attributes
Copyright (C) 2013-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2013-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -38,13 +38,13 @@ zip_file_get_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
zip_dirent_t *de;
if ((de = _zip_get_dirent(za, idx, flags, NULL)) == NULL)
return -1;
return -1;
if (opsys)
*opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff);
*opsys = (zip_uint8_t)((de->version_madeby >> 8) & 0xff);
if (attributes)
*attributes = de->ext_attrib;
*attributes = de->ext_attrib;
return 0;
}

View File

@ -1,9 +1,9 @@
/*
zip_file_get_offset.c -- get offset of file data in archive.
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -50,24 +50,24 @@ _zip_file_get_offset(const zip_t *za, zip_uint64_t idx, zip_error_t *error) {
zip_int32_t size;
if (za->entry[idx].orig == NULL) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return 0;
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return 0;
}
offset = za->entry[idx].orig->offset;
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
_zip_error_set_from_source(error, za->src);
return 0;
_zip_error_set_from_source(error, za->src);
return 0;
}
/* TODO: cache? */
if ((size = _zip_dirent_size(za->src, ZIP_EF_LOCAL, error)) < 0)
return 0;
return 0;
if (offset + (zip_uint32_t)size > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return 0;
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return 0;
}
return offset + (zip_uint32_t)size;
@ -79,38 +79,38 @@ _zip_file_get_end(const zip_t *za, zip_uint64_t index, zip_error_t *error) {
zip_dirent_t *entry;
if ((offset = _zip_file_get_offset(za, index, error)) == 0) {
return 0;
return 0;
}
entry = za->entry[index].orig;
if (offset + entry->comp_size < offset || offset + entry->comp_size > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return 0;
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return 0;
}
offset += entry->comp_size;
if (entry->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) {
zip_uint8_t buf[4];
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
_zip_error_set_from_source(error, za->src);
return 0;
}
if (zip_source_read(za->src, buf, 4) != 4) {
_zip_error_set_from_source(error, za->src);
return 0;
}
if (memcmp(buf, DATADES_MAGIC, 4) == 0) {
offset += 4;
}
offset += 12;
if (_zip_dirent_needs_zip64(entry, 0)) {
offset += 8;
}
if (offset > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return 0;
}
zip_uint8_t buf[4];
if (zip_source_seek(za->src, (zip_int64_t)offset, SEEK_SET) < 0) {
_zip_error_set_from_source(error, za->src);
return 0;
}
if (zip_source_read(za->src, buf, 4) != 4) {
_zip_error_set_from_source(error, za->src);
return 0;
}
if (memcmp(buf, DATADES_MAGIC, 4) == 0) {
offset += 4;
}
offset += 12;
if (_zip_dirent_needs_zip64(entry, 0)) {
offset += 8;
}
if (offset > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return 0;
}
}
return offset;

View File

@ -1,9 +1,9 @@
/*
zip_file_rename.c -- rename file in zip archive
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -43,24 +43,24 @@ zip_file_rename(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags
int old_is_dir, new_is_dir;
if (idx >= za->nentry || (name != NULL && strlen(name) > ZIP_UINT16_MAX)) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if ((old_name = zip_get_name(za, idx, 0)) == NULL)
return -1;
return -1;
new_is_dir = (name != NULL && name[strlen(name) - 1] == '/');
old_is_dir = (old_name[strlen(old_name) - 1] == '/');
if (new_is_dir != old_is_dir) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
return _zip_set_name(za, idx, name, flags);

View File

@ -1,9 +1,9 @@
/*
zip_file_replace.c -- replace file via callback function
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -38,12 +38,12 @@
ZIP_EXTERN int
zip_file_replace(zip_t *za, zip_uint64_t idx, zip_source_t *source, zip_flags_t flags) {
if (idx >= za->nentry || source == NULL) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (_zip_file_replace(za, idx, NULL, source, flags) == -1)
return -1;
return -1;
return 0;
}
@ -56,31 +56,31 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s
zip_uint64_t za_nentry_prev;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
za_nentry_prev = za->nentry;
if (idx == ZIP_UINT64_MAX) {
zip_int64_t i = -1;
zip_int64_t i = -1;
if (flags & ZIP_FL_OVERWRITE)
i = _zip_name_locate(za, name, flags, NULL);
if (flags & ZIP_FL_OVERWRITE)
i = _zip_name_locate(za, name, flags, NULL);
if (i == -1) {
/* create and use new entry, used by zip_add */
if ((i = _zip_add_entry(za)) < 0)
return -1;
}
idx = (zip_uint64_t)i;
if (i == -1) {
/* create and use new entry, used by zip_add */
if ((i = _zip_add_entry(za)) < 0)
return -1;
}
idx = (zip_uint64_t)i;
}
if (name && _zip_set_name(za, idx, name, flags) != 0) {
if (za->nentry != za_nentry_prev) {
_zip_entry_finalize(za->entry + idx);
za->nentry = za_nentry_prev;
}
return -1;
if (za->nentry != za_nentry_prev) {
_zip_entry_finalize(za->entry + idx);
za->nentry = za_nentry_prev;
}
return -1;
}
/* does not change any name related data, so we can do it here;
@ -88,15 +88,15 @@ _zip_file_replace(zip_t *za, zip_uint64_t idx, const char *name, zip_source_t *s
_zip_unchange_data(za->entry + idx);
if (za->entry[idx].orig != NULL && (za->entry[idx].changes == NULL || (za->entry[idx].changes->changed & ZIP_DIRENT_COMP_METHOD) == 0)) {
if (za->entry[idx].changes == NULL) {
if ((za->entry[idx].changes = _zip_dirent_clone(za->entry[idx].orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
if (za->entry[idx].changes == NULL) {
if ((za->entry[idx].changes = _zip_dirent_clone(za->entry[idx].orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT;
za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD;
za->entry[idx].changes->comp_method = ZIP_CM_REPLACED_DEFAULT;
za->entry[idx].changes->changed |= ZIP_DIRENT_COMP_METHOD;
}
za->entry[idx].source = source;

View File

@ -1,9 +1,9 @@
/*
zip_file_set_comment.c -- set comment for file in archive
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -44,57 +44,57 @@ zip_file_set_comment(zip_t *za, zip_uint64_t idx, const char *comment, zip_uint1
int changed;
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
return -1;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (len > 0 && comment == NULL) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (len > 0) {
if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL)
return -1;
if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
cstr->encoding = ZIP_ENCODING_UTF8_KNOWN;
if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, flags, &za->error)) == NULL)
return -1;
if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
cstr->encoding = ZIP_ENCODING_UTF8_KNOWN;
}
else
cstr = NULL;
cstr = NULL;
e = za->entry + idx;
if (e->changes) {
_zip_string_free(e->changes->comment);
e->changes->comment = NULL;
e->changes->changed &= ~ZIP_DIRENT_COMMENT;
_zip_string_free(e->changes->comment);
e->changes->comment = NULL;
e->changes->changed &= ~ZIP_DIRENT_COMMENT;
}
if (e->orig && e->orig->comment)
changed = !_zip_string_equal(e->orig->comment, cstr);
changed = !_zip_string_equal(e->orig->comment, cstr);
else
changed = (cstr != NULL);
changed = (cstr != NULL);
if (changed) {
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
_zip_string_free(cstr);
return -1;
}
}
e->changes->comment = cstr;
e->changes->changed |= ZIP_DIRENT_COMMENT;
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
_zip_string_free(cstr);
return -1;
}
}
e->changes->comment = cstr;
e->changes->changed |= ZIP_DIRENT_COMMENT;
}
else {
_zip_string_free(cstr);
if (e->changes && e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
_zip_string_free(cstr);
if (e->changes && e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
}
return 0;

View File

@ -0,0 +1,116 @@
/*
zip_file_set_encryption.c -- set encryption for file in archive
Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "zipint.h"
#include <stdlib.h>
#include <string.h>
ZIP_EXTERN int
zip_file_set_encryption(zip_t *za, zip_uint64_t idx, zip_uint16_t method, const char *password) {
zip_entry_t *e;
zip_uint16_t old_method;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (method != ZIP_EM_NONE && _zip_get_encryption_implementation(method, ZIP_CODEC_ENCODE) == NULL) {
zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
return -1;
}
e = za->entry + idx;
old_method = (e->orig == NULL ? ZIP_EM_NONE : e->orig->encryption_method);
if (method == old_method && password == NULL) {
if (e->changes) {
if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
_zip_crypto_clear(e->changes->password, strlen(e->changes->password));
free(e->changes->password);
e->changes->password = (e->orig == NULL ? NULL : e->orig->password);
}
e->changes->changed &= ~(ZIP_DIRENT_ENCRYPTION_METHOD | ZIP_DIRENT_PASSWORD);
if (e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
}
}
else {
char *our_password = NULL;
if (password) {
if ((our_password = strdup(password)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
if (our_password) {
_zip_crypto_clear(our_password, strlen(our_password));
}
free(our_password);
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
e->changes->encryption_method = method;
e->changes->changed |= ZIP_DIRENT_ENCRYPTION_METHOD;
if (password) {
e->changes->password = our_password;
e->changes->changed |= ZIP_DIRENT_PASSWORD;
}
else {
if (e->changes->changed & ZIP_DIRENT_PASSWORD) {
_zip_crypto_clear(e->changes->password, strlen(e->changes->password));
free(e->changes->password);
e->changes->password = e->orig ? e->orig->password : NULL;
e->changes->changed &= ~ZIP_DIRENT_PASSWORD;
}
}
}
return 0;
}

View File

@ -1,9 +1,9 @@
/*
zip_file_set_external_attributes.c -- set external attributes for entry
Copyright (C) 2013-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2013-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -41,11 +41,11 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
zip_uint32_t unchanged_attributes;
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
return -1;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
e = za->entry + idx;
@ -56,26 +56,26 @@ zip_file_set_external_attributes(zip_t *za, zip_uint64_t idx, zip_flags_t flags,
changed = (opsys != unchanged_opsys || attributes != unchanged_attributes);
if (changed) {
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
e->changes->version_madeby = (zip_uint16_t)((opsys << 8) | (e->changes->version_madeby & 0xff));
e->changes->ext_attrib = attributes;
e->changes->changed |= ZIP_DIRENT_ATTRIBUTES;
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
e->changes->version_madeby = (zip_uint16_t)((opsys << 8) | (e->changes->version_madeby & 0xff));
e->changes->ext_attrib = attributes;
e->changes->changed |= ZIP_DIRENT_ATTRIBUTES;
}
else if (e->changes) {
e->changes->changed &= ~ZIP_DIRENT_ATTRIBUTES;
if (e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
else {
e->changes->version_madeby = (zip_uint16_t)((unchanged_opsys << 8) | (e->changes->version_madeby & 0xff));
e->changes->ext_attrib = unchanged_attributes;
}
e->changes->changed &= ~ZIP_DIRENT_ATTRIBUTES;
if (e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
else {
e->changes->version_madeby = (zip_uint16_t)((unchanged_opsys << 8) | (e->changes->version_madeby & 0xff));
e->changes->ext_attrib = unchanged_attributes;
}
}
return 0;

View File

@ -1,9 +1,9 @@
/*
zip_file_set_mtime.c -- set modification time of entry.
Copyright (C) 2014-2020 Dieter Baron and Thomas Klausner
Copyright (C) 2014-2022 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -45,20 +45,25 @@ zip_file_set_mtime(zip_t *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags)
zip_entry_t *e;
if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
return -1;
return -1;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
e = za->entry + idx;
if (e->orig != NULL && e->orig->encryption_method == ZIP_EM_TRAD_PKWARE && !ZIP_ENTRY_CHANGED(e, ZIP_DIRENT_ENCRYPTION_METHOD) && !ZIP_ENTRY_DATA_CHANGED(e)) {
zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
e->changes->last_mod = mtime;

View File

@ -1,9 +1,9 @@
/*
zip_file_sterror.c -- get string representation of zip file error
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -1,9 +1,9 @@
/*
zip_fopen.c -- open file in zip archive for reading
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -40,7 +40,7 @@ zip_fopen(zip_t *za, const char *fname, zip_flags_t flags) {
zip_int64_t idx;
if ((idx = zip_name_locate(za, fname, flags)) < 0)
return NULL;
return NULL;
return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, za->default_password);
}

View File

@ -1,9 +1,9 @@
/*
zip_fopen_encrypted.c -- open file for reading with password
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -40,7 +40,7 @@ zip_fopen_encrypted(zip_t *za, const char *fname, zip_flags_t flags, const char
zip_int64_t idx;
if ((idx = zip_name_locate(za, fname, flags)) < 0)
return NULL;
return NULL;
return zip_fopen_index_encrypted(za, (zip_uint64_t)idx, flags, password);
}

View File

@ -1,9 +1,9 @@
/*
zip_fopen_index.c -- open file in zip archive for reading by index
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -1,9 +1,9 @@
/*
zip_fopen_index_encrypted.c -- open file for reading by index w/ password
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -45,18 +45,22 @@ zip_fopen_index_encrypted(zip_t *za, zip_uint64_t index, zip_flags_t flags, cons
zip_file_t *zf;
zip_source_t *src;
if ((src = _zip_source_zip_new(za, za, index, flags, 0, 0, password)) == NULL)
return NULL;
if (password != NULL && password[0] == '\0') {
password = NULL;
}
if ((src = _zip_source_zip_new(za, index, flags, 0, 0, password, &za->error)) == NULL)
return NULL;
if (zip_source_open(src) < 0) {
_zip_error_set_from_source(&za->error, src);
zip_source_free(src);
return NULL;
_zip_error_set_from_source(&za->error, src);
zip_source_free(src);
return NULL;
}
if ((zf = _zip_file_new(za)) == NULL) {
zip_source_free(src);
return NULL;
zip_source_free(src);
return NULL;
}
zf->src = src;
@ -70,8 +74,8 @@ _zip_file_new(zip_t *za) {
zip_file_t *zf;
if ((zf = (zip_file_t *)malloc(sizeof(struct zip_file))) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return NULL;
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return NULL;
}
zf->za = za;

View File

@ -1,9 +1,9 @@
/*
zip_fread.c -- read from file
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -40,22 +40,22 @@ zip_fread(zip_file_t *zf, void *outbuf, zip_uint64_t toread) {
zip_int64_t n;
if (!zf)
return -1;
return -1;
if (zf->error.zip_err != 0)
return -1;
return -1;
if (toread > ZIP_INT64_MAX) {
zip_error_set(&zf->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&zf->error, ZIP_ER_INVAL, 0);
return -1;
}
if ((zf->eof) || (toread == 0))
return 0;
return 0;
if ((n = zip_source_read(zf->src, outbuf, toread)) < 0) {
_zip_error_set_from_source(&zf->error, zf->src);
return -1;
_zip_error_set_from_source(&zf->error, zf->src);
return -1;
}
return n;

View File

@ -0,0 +1,61 @@
/*
zip_fseek.c -- seek in file
Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "zipint.h"
ZIP_EXTERN zip_int8_t
zip_fseek(zip_file_t *zf, zip_int64_t offset, int whence) {
if (!zf)
return -1;
if (zf->error.zip_err != 0)
return -1;
if (zip_source_seek(zf->src, offset, whence) < 0) {
_zip_error_set_from_source(&zf->error, zf->src);
return -1;
}
return 0;
}
ZIP_EXTERN int
zip_file_is_seekable(zip_file_t *zfile) {
if (!zfile) {
return -1;
}
return ZIP_SOURCE_CHECK_SUPPORTED(zip_source_supports(zfile->src), ZIP_SOURCE_SEEK);
}

View File

@ -0,0 +1,54 @@
/*
zip_ftell.c -- tell position in file
Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "zipint.h"
ZIP_EXTERN zip_int64_t
zip_ftell(zip_file_t *zf) {
zip_int64_t res;
if (!zf)
return -1;
if (zf->error.zip_err != 0)
return -1;
res = zip_source_tell(zf->src);
if (res < 0) {
_zip_error_set_from_source(&zf->error, zf->src);
return -1;
}
return res;
}

View File

@ -1,9 +1,9 @@
/*
zip_get_archive_comment.c -- get archive comment
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -44,15 +44,15 @@ zip_get_archive_comment(zip_t *za, int *lenp, zip_flags_t flags) {
const zip_uint8_t *str;
if ((flags & ZIP_FL_UNCHANGED) || (za->comment_changes == NULL))
comment = za->comment_orig;
comment = za->comment_orig;
else
comment = za->comment_changes;
comment = za->comment_changes;
if ((str = _zip_string_get(comment, &len, flags, &za->error)) == NULL)
return NULL;
return NULL;
if (lenp)
*lenp = (int)len;
*lenp = (int)len;
return (const char *)str;
}

View File

@ -1,9 +1,9 @@
/*
zip_get_archive_flag.c -- get archive global flag
Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2008-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -1,9 +1,9 @@
/*
zip_get_encryption_implementation.c -- get encryption implementation
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -39,24 +39,24 @@ zip_encryption_implementation
_zip_get_encryption_implementation(zip_uint16_t em, int operation) {
switch (em) {
case ZIP_EM_TRAD_PKWARE:
return operation == ZIP_CODEC_DECODE ? zip_source_pkware_decode : zip_source_pkware_encode;
return operation == ZIP_CODEC_DECODE ? zip_source_pkware_decode : zip_source_pkware_encode;
#if defined(HAVE_CRYPTO)
case ZIP_EM_AES_128:
case ZIP_EM_AES_192:
case ZIP_EM_AES_256:
return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode;
return operation == ZIP_CODEC_DECODE ? zip_source_winzip_aes_decode : zip_source_winzip_aes_encode;
#endif
default:
return NULL;
return NULL;
}
}
ZIP_EXTERN int
zip_encryption_method_supported(zip_uint16_t method, int encode) {
if (method == ZIP_EM_NONE) {
return 1;
return 1;
}
return _zip_get_encryption_implementation(method, encode ? ZIP_CODEC_ENCODE : ZIP_CODEC_DECODE) != NULL;
}

View File

@ -1,9 +1,9 @@
/*
zip_get_file_comment.c -- get file comment
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -42,8 +42,8 @@ zip_get_file_comment(zip_t *za, zip_uint64_t idx, int *lenp, int flags) {
const char *s;
if ((s = zip_file_get_comment(za, idx, &len, (zip_flags_t)flags)) != NULL) {
if (lenp)
*lenp = (int)len;
if (lenp)
*lenp = (int)len;
}
return s;

View File

@ -1,9 +1,9 @@
/*
zip_get_name.c -- get filename for a file in zip file
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -49,10 +49,10 @@ _zip_get_name(zip_t *za, zip_uint64_t idx, zip_flags_t flags, zip_error_t *error
const zip_uint8_t *str;
if ((de = _zip_get_dirent(za, idx, flags, error)) == NULL)
return NULL;
return NULL;
if ((str = _zip_string_get(de->filename, NULL, flags, error)) == NULL)
return NULL;
return NULL;
return (const char *)str;
}

View File

@ -1,9 +1,9 @@
/*
zip_get_num_entries.c -- get number of entries in archive
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -40,13 +40,13 @@ zip_get_num_entries(zip_t *za, zip_flags_t flags) {
zip_uint64_t n;
if (za == NULL)
return -1;
return -1;
if (flags & ZIP_FL_UNCHANGED) {
n = za->nentry;
while (n > 0 && za->entry[n - 1].orig == NULL)
--n;
return (zip_int64_t)n;
n = za->nentry;
while (n > 0 && za->entry[n - 1].orig == NULL)
--n;
return (zip_int64_t)n;
}
return (zip_int64_t)za->nentry;
}

View File

@ -1,9 +1,9 @@
/*
zip_get_num_files.c -- get number of files in archive
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -40,11 +40,11 @@
ZIP_EXTERN int
zip_get_num_files(zip_t *za) {
if (za == NULL)
return -1;
return -1;
if (za->nentry > INT_MAX) {
zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
return (int)za->nentry;

View File

@ -1,9 +1,9 @@
/*
zip_hash.c -- hash table string -> uint64
Copyright (C) 2015-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2015-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -67,9 +67,9 @@ struct zip_hash {
static void
free_list(zip_hash_entry_t *entry) {
while (entry != NULL) {
zip_hash_entry_t *next = entry->next;
free(entry);
entry = next;
zip_hash_entry_t *next = entry->next;
free(entry);
entry = next;
}
}
@ -80,12 +80,12 @@ hash_string(const zip_uint8_t *name) {
zip_uint64_t value = HASH_START;
if (name == NULL) {
return 0;
return 0;
}
while (*name != 0) {
value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
name++;
value = (zip_uint64_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % 0x100000000ul);
name++;
}
return (zip_uint32_t)value;
@ -98,30 +98,30 @@ hash_resize(zip_hash_t *hash, zip_uint32_t new_size, zip_error_t *error) {
zip_hash_entry_t **new_table;
if (new_size == hash->table_size) {
return true;
return true;
}
if ((new_table = (zip_hash_entry_t **)calloc(new_size, sizeof(zip_hash_entry_t *))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
if (hash->nentries > 0) {
zip_uint32_t i;
zip_uint32_t i;
for (i = 0; i < hash->table_size; i++) {
zip_hash_entry_t *entry = hash->table[i];
while (entry) {
zip_hash_entry_t *next = entry->next;
for (i = 0; i < hash->table_size; i++) {
zip_hash_entry_t *entry = hash->table[i];
while (entry) {
zip_hash_entry_t *next = entry->next;
zip_uint32_t new_index = entry->hash_value % new_size;
zip_uint32_t new_index = entry->hash_value % new_size;
entry->next = new_table[new_index];
new_table[new_index] = entry;
entry->next = new_table[new_index];
new_table[new_index] = entry;
entry = next;
}
}
entry = next;
}
}
}
free(hash->table);
@ -138,14 +138,14 @@ size_for_capacity(zip_uint64_t capacity) {
zip_uint32_t v;
if (needed_size > ZIP_UINT32_MAX) {
v = ZIP_UINT32_MAX;
v = ZIP_UINT32_MAX;
}
else {
v = (zip_uint32_t)needed_size;
v = (zip_uint32_t)needed_size;
}
if (v > HASH_MAX_SIZE) {
return HASH_MAX_SIZE;
return HASH_MAX_SIZE;
}
/* From Bit Twiddling Hacks by Sean Eron Anderson <seander@cs.stanford.edu>
@ -168,8 +168,8 @@ _zip_hash_new(zip_error_t *error) {
zip_hash_t *hash;
if ((hash = (zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
hash->table_size = 0;
@ -185,16 +185,16 @@ _zip_hash_free(zip_hash_t *hash) {
zip_uint32_t i;
if (hash == NULL) {
return;
return;
}
if (hash->table != NULL) {
for (i = 0; i < hash->table_size; i++) {
if (hash->table[i] != NULL) {
free_list(hash->table[i]);
}
}
free(hash->table);
for (i = 0; i < hash->table_size; i++) {
if (hash->table[i] != NULL) {
free_list(hash->table[i]);
}
}
free(hash->table);
}
free(hash);
}
@ -207,51 +207,51 @@ _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip
zip_hash_entry_t *entry;
if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return false;
zip_error_set(error, ZIP_ER_INVAL, 0);
return false;
}
if (hash->table_size == 0) {
if (!hash_resize(hash, HASH_MIN_SIZE, error)) {
return false;
}
if (!hash_resize(hash, HASH_MIN_SIZE, error)) {
return false;
}
}
hash_value = hash_string(name);
table_index = hash_value % hash->table_size;
for (entry = hash->table[table_index]; entry != NULL; entry = entry->next) {
if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
zip_error_set(error, ZIP_ER_EXISTS, 0);
return false;
}
else {
break;
}
}
if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
zip_error_set(error, ZIP_ER_EXISTS, 0);
return false;
}
else {
break;
}
}
}
if (entry == NULL) {
if ((entry = (zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
entry->name = name;
entry->next = hash->table[table_index];
hash->table[table_index] = entry;
entry->hash_value = hash_value;
entry->orig_index = -1;
hash->nentries++;
if (hash->nentries > hash->table_size * HASH_MAX_FILL && hash->table_size < HASH_MAX_SIZE) {
if (!hash_resize(hash, hash->table_size * 2, error)) {
return false;
}
}
if ((entry = (zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
entry->name = name;
entry->next = hash->table[table_index];
hash->table[table_index] = entry;
entry->hash_value = hash_value;
entry->orig_index = -1;
hash->nentries++;
if (hash->nentries > hash->table_size * HASH_MAX_FILL && hash->table_size < HASH_MAX_SIZE) {
if (!hash_resize(hash, hash->table_size * 2, error)) {
return false;
}
}
}
if (flags & ZIP_FL_UNCHANGED) {
entry->orig_index = (zip_int64_t)index;
entry->orig_index = (zip_int64_t)index;
}
entry->current_index = (zip_int64_t)index;
@ -266,40 +266,40 @@ _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
zip_hash_entry_t *entry, *previous;
if (hash == NULL || name == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return false;
zip_error_set(error, ZIP_ER_INVAL, 0);
return false;
}
if (hash->nentries > 0) {
hash_value = hash_string(name);
index = hash_value % hash->table_size;
previous = NULL;
entry = hash->table[index];
while (entry) {
if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
if (entry->orig_index == -1) {
if (previous) {
previous->next = entry->next;
}
else {
hash->table[index] = entry->next;
}
free(entry);
hash->nentries--;
if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
if (!hash_resize(hash, hash->table_size / 2, error)) {
return false;
}
}
}
else {
entry->current_index = -1;
}
return true;
}
previous = entry;
entry = entry->next;
}
hash_value = hash_string(name);
index = hash_value % hash->table_size;
previous = NULL;
entry = hash->table[index];
while (entry) {
if (entry->hash_value == hash_value && strcmp((const char *)name, (const char *)entry->name) == 0) {
if (entry->orig_index == -1) {
if (previous) {
previous->next = entry->next;
}
else {
hash->table[index] = entry->next;
}
free(entry);
hash->nentries--;
if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
if (!hash_resize(hash, hash->table_size / 2, error)) {
return false;
}
}
}
else {
entry->current_index = -1;
}
return true;
}
previous = entry;
entry = entry->next;
}
}
zip_error_set(error, ZIP_ER_NOENT, 0);
@ -314,28 +314,28 @@ _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, z
zip_hash_entry_t *entry;
if (hash == NULL || name == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(error, ZIP_ER_INVAL, 0);
return -1;
}
if (hash->nentries > 0) {
hash_value = hash_string(name);
index = hash_value % hash->table_size;
for (entry = hash->table[index]; entry != NULL; entry = entry->next) {
if (strcmp((const char *)name, (const char *)entry->name) == 0) {
if (flags & ZIP_FL_UNCHANGED) {
if (entry->orig_index != -1) {
return entry->orig_index;
}
}
else {
if (entry->current_index != -1) {
return entry->current_index;
}
}
break;
}
}
hash_value = hash_string(name);
index = hash_value % hash->table_size;
for (entry = hash->table[index]; entry != NULL; entry = entry->next) {
if (strcmp((const char *)name, (const char *)entry->name) == 0) {
if (flags & ZIP_FL_UNCHANGED) {
if (entry->orig_index != -1) {
return entry->orig_index;
}
}
else {
if (entry->current_index != -1) {
return entry->current_index;
}
}
break;
}
}
}
zip_error_set(error, ZIP_ER_NOENT, 0);
@ -348,17 +348,17 @@ _zip_hash_reserve_capacity(zip_hash_t *hash, zip_uint64_t capacity, zip_error_t
zip_uint32_t new_size;
if (capacity == 0) {
return true;
return true;
}
new_size = size_for_capacity(capacity);
if (new_size <= hash->table_size) {
return true;
return true;
}
if (!hash_resize(hash, new_size, error)) {
return false;
return false;
}
return true;
@ -371,39 +371,39 @@ _zip_hash_revert(zip_hash_t *hash, zip_error_t *error) {
zip_hash_entry_t *entry, *previous;
for (i = 0; i < hash->table_size; i++) {
previous = NULL;
entry = hash->table[i];
while (entry) {
if (entry->orig_index == -1) {
zip_hash_entry_t *p;
if (previous) {
previous->next = entry->next;
}
else {
hash->table[i] = entry->next;
}
p = entry;
entry = entry->next;
/* previous does not change */
free(p);
hash->nentries--;
}
else {
entry->current_index = entry->orig_index;
previous = entry;
entry = entry->next;
}
}
previous = NULL;
entry = hash->table[i];
while (entry) {
if (entry->orig_index == -1) {
zip_hash_entry_t *p;
if (previous) {
previous->next = entry->next;
}
else {
hash->table[i] = entry->next;
}
p = entry;
entry = entry->next;
/* previous does not change */
free(p);
hash->nentries--;
}
else {
entry->current_index = entry->orig_index;
previous = entry;
entry = entry->next;
}
}
}
if (hash->nentries < hash->table_size * HASH_MIN_FILL && hash->table_size > HASH_MIN_SIZE) {
zip_uint32_t new_size = hash->table_size / 2;
while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) {
new_size /= 2;
}
if (!hash_resize(hash, new_size, error)) {
return false;
}
zip_uint32_t new_size = hash->table_size / 2;
while (hash->nentries < new_size * HASH_MIN_FILL && new_size > HASH_MIN_SIZE) {
new_size /= 2;
}
if (!hash_resize(hash, new_size, error)) {
return false;
}
}
return true;

View File

@ -1,9 +1,9 @@
/*
zip_io_util.c -- I/O helper functions
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -41,18 +41,18 @@ _zip_read(zip_source_t *src, zip_uint8_t *b, zip_uint64_t length, zip_error_t *e
zip_int64_t n;
if (length > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return -1;
zip_error_set(error, ZIP_ER_INTERNAL, 0);
return -1;
}
if ((n = zip_source_read(src, b, length)) < 0) {
_zip_error_set_from_source(error, src);
return -1;
_zip_error_set_from_source(error, src);
return -1;
}
if (n < (zip_int64_t)length) {
zip_error_set(error, ZIP_ER_EOF, 0);
return -1;
zip_error_set(error, ZIP_ER_EOF, 0);
return -1;
}
return 0;
@ -64,39 +64,39 @@ _zip_read_data(zip_buffer_t *buffer, zip_source_t *src, size_t length, bool nulp
zip_uint8_t *r;
if (length == 0 && !nulp) {
return NULL;
return NULL;
}
r = (zip_uint8_t *)malloc(length + (nulp ? 1 : 0));
if (!r) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
if (buffer) {
zip_uint8_t *data = _zip_buffer_get(buffer, length);
zip_uint8_t *data = _zip_buffer_get(buffer, length);
if (data == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
free(r);
return NULL;
}
memcpy(r, data, length);
if (data == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
free(r);
return NULL;
}
memcpy(r, data, length);
}
else {
if (_zip_read(src, r, length, error) < 0) {
free(r);
return NULL;
}
if (_zip_read(src, r, length, error) < 0) {
free(r);
return NULL;
}
}
if (nulp) {
zip_uint8_t *o;
/* replace any in-string NUL characters with spaces */
r[length] = 0;
for (o = r; o < r + length; o++)
if (*o == '\0')
*o = ' ';
zip_uint8_t *o;
/* replace any in-string NUL characters with spaces */
r[length] = 0;
for (o = r; o < r + length; o++)
if (*o == '\0')
*o = ' ';
}
return r;
@ -109,7 +109,7 @@ _zip_read_string(zip_buffer_t *buffer, zip_source_t *src, zip_uint16_t len, bool
zip_string_t *s;
if ((raw = _zip_read_data(buffer, src, len, nulp, error)) == NULL)
return NULL;
return NULL;
s = _zip_string_new(raw, len, ZIP_FL_ENC_GUESS, error);
free(raw);
@ -122,12 +122,12 @@ _zip_write(zip_t *za, const void *data, zip_uint64_t length) {
zip_int64_t n;
if ((n = zip_source_write(za->src, data, length)) < 0) {
_zip_error_set_from_source(&za->error, za->src);
return -1;
_zip_error_set_from_source(&za->error, za->src);
return -1;
}
if ((zip_uint64_t)n != length) {
zip_error_set(&za->error, ZIP_ER_WRITE, EINTR);
return -1;
zip_error_set(&za->error, ZIP_ER_WRITE, EINTR);
return -1;
}
return 0;

View File

@ -0,0 +1,41 @@
/*
zip_libzip_version.c -- return run-time version of library
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "zipint.h"
ZIP_EXTERN const char *
zip_libzip_version(void) {
return LIBZIP_VERSION;
}

View File

@ -1,9 +1,9 @@
/*
zip_memdup.c -- internal zip function, "strdup" with len
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -42,12 +42,12 @@ _zip_memdup(const void *mem, size_t len, zip_error_t *error) {
void *ret;
if (len == 0)
return NULL;
return NULL;
ret = malloc(len);
if (!ret) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
memcpy(ret, mem, len);

View File

@ -1,9 +1,9 @@
/*
zip_name_locate.c -- get index by name
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -49,44 +49,59 @@ zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags) {
zip_int64_t
_zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *error) {
int (*cmp)(const char *, const char *);
zip_string_t *str = NULL;
const char *fn, *p;
zip_uint64_t i;
if (za == NULL)
return -1;
return -1;
if (fname == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(error, ZIP_ER_INVAL, 0);
return -1;
}
if (flags & (ZIP_FL_NOCASE | ZIP_FL_NODIR | ZIP_FL_ENC_CP437)) {
/* can't use hash table */
cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
if ((flags & (ZIP_FL_ENC_UTF_8 | ZIP_FL_ENC_RAW)) == 0 && fname[0] != '\0') {
if ((str = _zip_string_new((const zip_uint8_t *)fname, strlen(fname), flags, error)) == NULL) {
return -1;
}
if ((fname = (const char *)_zip_string_get(str, NULL, 0, error)) == NULL) {
_zip_string_free(str);
return -1;
}
}
for (i = 0; i < za->nentry; i++) {
fn = _zip_get_name(za, i, flags, error);
if (flags & (ZIP_FL_NOCASE | ZIP_FL_NODIR | ZIP_FL_ENC_RAW | ZIP_FL_ENC_STRICT)) {
/* can't use hash table */
cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
/* newly added (partially filled) entry or error */
if (fn == NULL)
continue;
for (i = 0; i < za->nentry; i++) {
fn = _zip_get_name(za, i, flags, error);
if (flags & ZIP_FL_NODIR) {
p = strrchr(fn, '/');
if (p)
fn = p + 1;
}
/* newly added (partially filled) entry or error */
if (fn == NULL)
continue;
if (cmp(fname, fn) == 0) {
_zip_error_clear(error);
return (zip_int64_t)i;
}
}
if (flags & ZIP_FL_NODIR) {
p = strrchr(fn, '/');
if (p)
fn = p + 1;
}
zip_error_set(error, ZIP_ER_NOENT, 0);
return -1;
if (cmp(fname, fn) == 0) {
_zip_error_clear(error);
_zip_string_free(str);
return (zip_int64_t)i;
}
}
zip_error_set(error, ZIP_ER_NOENT, 0);
_zip_string_free(str);
return -1;
}
else {
return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
zip_int64_t ret = _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
_zip_string_free(str);
return ret;
}
}

View File

@ -1,9 +1,9 @@
/*
zip_new.c -- create and init struct zip
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -47,13 +47,13 @@ _zip_new(zip_error_t *error) {
za = (zip_t *)malloc(sizeof(struct zip));
if (!za) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
if ((za->names = _zip_hash_new(error)) == NULL) {
free(za);
return NULL;
free(za);
return NULL;
}
za->src = NULL;

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
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>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -75,18 +75,18 @@ _zip_pkware_encrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t
zip_uint8_t tmp;
for (i = 0; i < len; i++) {
b = in[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);
}
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);
}
}
}
@ -98,15 +98,15 @@ _zip_pkware_decrypt(zip_pkware_keys_t *keys, zip_uint8_t *out, const zip_uint8_t
zip_uint8_t tmp;
for (i = 0; i < len; i++) {
b = in[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;
}
/* 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);
update_keys(keys, b);
}
}

View File

@ -3,7 +3,7 @@
Copyright (C) 2017-2020 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -73,7 +73,7 @@ _zip_progress_end(zip_progress_t *progress) {
void
_zip_progress_free(zip_progress_t *progress) {
if (progress == NULL) {
return;
return;
}
_zip_progress_free_progress_callback(progress);
@ -88,8 +88,8 @@ _zip_progress_new(zip_t *za) {
zip_progress_t *progress = (zip_progress_t *)malloc(sizeof(*progress));
if (progress == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return NULL;
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return NULL;
}
progress->za = za;
@ -109,7 +109,7 @@ _zip_progress_new(zip_t *za) {
static void
_zip_progress_free_progress_callback(zip_progress_t *progress) {
if (progress->ud_progress_free) {
progress->ud_progress_free(progress->ud_progress);
progress->ud_progress_free(progress->ud_progress);
}
progress->callback_progress = NULL;
@ -120,7 +120,7 @@ _zip_progress_free_progress_callback(zip_progress_t *progress) {
static void
_zip_progress_free_cancel_callback(zip_progress_t *progress) {
if (progress->ud_cancel_free) {
progress->ud_cancel_free(progress->ud_cancel);
progress->ud_cancel_free(progress->ud_cancel);
}
progress->callback_cancel = NULL;
@ -150,18 +150,18 @@ _zip_progress_set_cancel_callback(zip_progress_t *progress, zip_cancel_callback
int
_zip_progress_start(zip_progress_t *progress) {
if (progress == NULL) {
return 0;
return 0;
}
if (progress->callback_progress != NULL) {
progress->last_update = 0.0;
progress->callback_progress(progress->za, 0.0, progress->ud_progress);
progress->last_update = 0.0;
progress->callback_progress(progress->za, 0.0, progress->ud_progress);
}
if (progress->callback_cancel != NULL) {
if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
return -1;
}
if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
return -1;
}
}
return 0;
@ -171,7 +171,7 @@ _zip_progress_start(zip_progress_t *progress) {
int
_zip_progress_subrange(zip_progress_t *progress, double start, double end) {
if (progress == NULL) {
return 0;
return 0;
}
progress->start = start;
@ -185,22 +185,22 @@ _zip_progress_update(zip_progress_t *progress, double sub_current) {
double current;
if (progress == NULL) {
return 0;
return 0;
}
if (progress->callback_progress != NULL) {
current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
current = ZIP_MIN(ZIP_MAX(sub_current, 0.0), 1.0) * (progress->end - progress->start) + progress->start;
if (current - progress->last_update > progress->precision) {
progress->callback_progress(progress->za, current, progress->ud_progress);
progress->last_update = current;
}
if (current - progress->last_update > progress->precision) {
progress->callback_progress(progress->za, current, progress->ud_progress);
progress->last_update = current;
}
}
if (progress->callback_cancel != NULL) {
if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
return -1;
}
if (progress->callback_cancel(progress->za, progress->ud_cancel)) {
return -1;
}
}
return 0;
@ -210,24 +210,24 @@ _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) {
if (callback != NULL) {
if (za->progress == NULL) {
if ((za->progress = _zip_progress_new(za)) == NULL) {
return -1;
}
}
if (za->progress == NULL) {
if ((za->progress = _zip_progress_new(za)) == NULL) {
return -1;
}
}
_zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud);
_zip_progress_set_progress_callback(za->progress, precision, callback, ud_free, ud);
}
else {
if (za->progress != NULL) {
if (za->progress->callback_cancel == NULL) {
_zip_progress_free(za->progress);
za->progress = NULL;
}
else {
_zip_progress_free_progress_callback(za->progress);
}
}
if (za->progress != NULL) {
if (za->progress->callback_cancel == NULL) {
_zip_progress_free(za->progress);
za->progress = NULL;
}
else {
_zip_progress_free_progress_callback(za->progress);
}
}
}
return 0;
@ -237,24 +237,24 @@ 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) {
if (callback != NULL) {
if (za->progress == NULL) {
if ((za->progress = _zip_progress_new(za)) == NULL) {
return -1;
}
}
if (za->progress == NULL) {
if ((za->progress = _zip_progress_new(za)) == NULL) {
return -1;
}
}
_zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud);
_zip_progress_set_cancel_callback(za->progress, callback, ud_free, ud);
}
else {
if (za->progress != NULL) {
if (za->progress->callback_progress == NULL) {
_zip_progress_free(za->progress);
za->progress = NULL;
}
else {
_zip_progress_free_cancel_callback(za->progress);
}
}
if (za->progress != NULL) {
if (za->progress->callback_progress == NULL) {
_zip_progress_free(za->progress);
za->progress = NULL;
}
else {
_zip_progress_free_cancel_callback(za->progress);
}
}
}
return 0;
@ -278,16 +278,16 @@ zip_register_progress_callback(zip_t *za, zip_progress_callback_t progress_callb
struct legacy_ud *ud;
if (progress_callback == NULL) {
zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
zip_register_progress_callback_with_state(za, 0, NULL, NULL, NULL);
}
if ((ud = (struct legacy_ud *)malloc(sizeof(*ud))) == NULL) {
return;
return;
}
ud->callback = progress_callback;
if (zip_register_progress_callback_with_state(za, 0.001, _zip_legacy_progress_callback, free, ud) < 0) {
free(ud);
free(ud);
}
}

View File

@ -0,0 +1,104 @@
/*
zip_random_unix.c -- fill the user's buffer with random stuff (Unix version)
Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "zipint.h"
#ifdef HAVE_CRYPTO
#include "zip_crypto.h"
#endif
#ifdef HAVE_ARC4RANDOM
#include <stdlib.h>
#ifndef HAVE_SECURE_RANDOM
ZIP_EXTERN bool
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
arc4random_buf(buffer, length);
return true;
}
#endif
#ifndef HAVE_RANDOM_UINT32
zip_uint32_t
zip_random_uint32(void) {
return arc4random();
}
#endif
#else /* HAVE_ARC4RANDOM */
#ifndef HAVE_SECURE_RANDOM
#include <fcntl.h>
#include <unistd.h>
ZIP_EXTERN bool
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
int fd;
if ((fd = open("/dev/urandom", O_RDONLY)) < 0) {
return false;
}
if (read(fd, buffer, length) != length) {
close(fd);
return false;
}
close(fd);
return true;
}
#endif
#ifndef HAVE_RANDOM_UINT32
#include <stdlib.h>
zip_uint32_t
zip_random_uint32(void) {
static bool seeded = false;
zip_uint32_t value;
if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
return value;
}
if (!seeded) {
srandom((unsigned int)time(NULL));
}
return (zip_uint32_t)random();
}
#endif
#endif /* HAVE_ARC4RANDOM */

View File

@ -1,9 +1,9 @@
/*
zip_filerange_crc.c -- compute CRC32 for a range of a file
Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner
zip_random_uwp.c -- fill the user's buffer with random stuff (UWP version)
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -31,54 +31,51 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "zipint.h"
#ifdef HAVE_CRYPTO
#include "zip_crypto.h"
#endif
int
_zip_filerange_crc(zip_source_t *src, zip_uint64_t start, zip_uint64_t len, uLong *crcp, zip_error_t *error) {
DEFINE_BYTE_ARRAY(buf, BUFSIZE);
#ifndef HAVE_SECURE_RANDOM
zip_int64_t n;
#include <windows.h>
#include <bcrypt.h>
*crcp = crc32(0L, Z_NULL, 0);
if (start > ZIP_INT64_MAX) {
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return -1;
ZIP_EXTERN bool
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
BCRYPT_ALG_HANDLE hAlg = NULL;
NTSTATUS hr = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
if (!BCRYPT_SUCCESS(hr) || hAlg == NULL) {
return false;
}
if (zip_source_seek(src, (zip_int64_t)start, SEEK_SET) != 0) {
_zip_error_set_from_source(error, src);
return -1;
hr = BCryptGenRandom(&hAlg, buffer, length, 0);
BCryptCloseAlgorithmProvider(&hAlg, 0);
if (!BCRYPT_SUCCESS(hr)) {
return false;
}
if (!byte_array_init(buf, BUFSIZE)) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return -1;
}
while (len > 0) {
n = (zip_int64_t)(len > BUFSIZE ? BUFSIZE : len);
if ((n = zip_source_read(src, buf, (zip_uint64_t)n)) < 0) {
_zip_error_set_from_source(error, src);
byte_array_fini(buf);
return -1;
}
if (n == 0) {
zip_error_set(error, ZIP_ER_EOF, 0);
byte_array_fini(buf);
return -1;
}
*crcp = crc32(*crcp, buf, (uInt)n);
len -= (zip_uint64_t)n;
}
byte_array_fini(buf);
return 0;
return true;
}
#endif
#ifndef HAVE_RANDOM_UINT32
#include <stdlib.h>
zip_uint32_t
zip_random_uint32(void) {
static bool seeded = false;
zip_uint32_t value;
if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
return value;
}
if (!seeded) {
srand((unsigned int)time(NULL));
}
return (zip_uint32_t)rand();
}
#endif

View File

@ -0,0 +1,81 @@
/*
zip_random_win32.c -- fill the user's buffer with random stuff (Windows version)
Copyright (C) 2016-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "zipint.h"
#ifdef HAVE_CRYPTO
#include "zip_crypto.h"
#endif
#include <windows.h>
#ifndef HAVE_SECURE_RANDOM
#include <wincrypt.h>
ZIP_EXTERN bool
zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
HCRYPTPROV hprov;
if (!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
return false;
}
if (!CryptGenRandom(hprov, length, buffer)) {
return false;
}
if (!CryptReleaseContext(hprov, 0)) {
return false;
}
return true;
}
#endif
#ifndef HAVE_RANDOM_UINT32
#include <stdlib.h>
zip_uint32_t
zip_random_uint32(void) {
static bool seeded = false;
zip_uint32_t value;
if (zip_secure_random((zip_uint8_t *)&value, sizeof(value))) {
return value;
}
if (!seeded) {
srand((unsigned int)time(NULL));
}
return (zip_uint32_t)rand();
}
#endif

View File

@ -1,9 +1,9 @@
/*
zip_rename.c -- rename file in zip archive
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -1,9 +1,9 @@
/*
zip_replace.c -- replace file via callback function
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -1,9 +1,9 @@
/*
zip_set_archive_comment.c -- set archive comment
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -42,38 +42,38 @@ zip_set_archive_comment(zip_t *za, const char *comment, zip_uint16_t len) {
zip_string_t *cstr;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (len > 0 && comment == NULL) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (len > 0) {
if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL)
return -1;
if ((cstr = _zip_string_new((const zip_uint8_t *)comment, len, ZIP_FL_ENC_GUESS, &za->error)) == NULL)
return -1;
if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) {
_zip_string_free(cstr);
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (_zip_guess_encoding(cstr, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_CP437) {
_zip_string_free(cstr);
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
}
else
cstr = NULL;
cstr = NULL;
_zip_string_free(za->comment_changes);
za->comment_changes = NULL;
if (((za->comment_orig && _zip_string_equal(za->comment_orig, cstr)) || (za->comment_orig == NULL && cstr == NULL))) {
_zip_string_free(cstr);
za->comment_changed = 0;
_zip_string_free(cstr);
za->comment_changed = 0;
}
else {
za->comment_changes = cstr;
za->comment_changed = 1;
za->comment_changes = cstr;
za->comment_changed = 1;
}
return 0;

View File

@ -1,9 +1,9 @@
/*
zip_get_archive_flag.c -- set archive global flag
Copyright (C) 2008-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2008-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -40,23 +40,23 @@ zip_set_archive_flag(zip_t *za, zip_flags_t flag, int value) {
unsigned int new_flags;
if (value)
new_flags = za->ch_flags | flag;
new_flags = za->ch_flags | flag;
else
new_flags = za->ch_flags & ~flag;
new_flags = za->ch_flags & ~flag;
if (new_flags == za->ch_flags)
return 0;
return 0;
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if ((flag & ZIP_AFL_RDONLY) && value && (za->ch_flags & ZIP_AFL_RDONLY) == 0) {
if (_zip_changed(za, NULL)) {
zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
return -1;
}
if (_zip_changed(za, NULL)) {
zip_error_set(&za->error, ZIP_ER_CHANGED, 0);
return -1;
}
}
za->ch_flags = new_flags;

View File

@ -1,9 +1,9 @@
/*
zip_set_default_password.c -- set default password for decryption
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -41,18 +41,18 @@
ZIP_EXTERN int
zip_set_default_password(zip_t *za, const char *passwd) {
if (za == NULL)
return -1;
return -1;
free(za->default_password);
if (passwd) {
if ((za->default_password = strdup(passwd)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
if (passwd && passwd[0] != '\0') {
if ((za->default_password = strdup(passwd)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
else
za->default_password = NULL;
za->default_password = NULL;
return 0;
}

View File

@ -1,9 +1,9 @@
/*
zip_set_file_comment.c -- set comment for file in archive
Copyright (C) 2006-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2006-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -39,8 +39,8 @@
ZIP_EXTERN int
zip_set_file_comment(zip_t *za, zip_uint64_t idx, const char *comment, int len) {
if (len < 0 || len > ZIP_UINT16_MAX) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
return zip_file_set_comment(za, idx, comment, (zip_uint16_t)len, 0);
}

View File

@ -1,9 +1,9 @@
/*
zip_set_file_compression.c -- set compression for file in archive
Copyright (C) 2012-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2012-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -40,19 +40,19 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
zip_entry_t *e;
zip_int32_t old_method;
if (idx >= za->nentry || flags > 9) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (!zip_compression_method_supported(method, true)) {
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
return -1;
}
e = za->entry + idx;
@ -65,26 +65,26 @@ zip_set_file_compression(zip_t *za, zip_uint64_t idx, zip_int32_t method, zip_ui
* to levels */
if (method == old_method) {
if (e->changes) {
e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
e->changes->compression_level = 0;
if (e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
}
if (e->changes) {
e->changes->changed &= ~ZIP_DIRENT_COMP_METHOD;
e->changes->compression_level = 0;
if (e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
}
}
else {
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
if (e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
}
e->changes->comp_method = method;
e->changes->compression_level = (zip_uint16_t)flags;
e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
e->changes->comp_method = method;
e->changes->compression_level = (zip_uint16_t)flags;
e->changes->changed |= ZIP_DIRENT_COMP_METHOD;
}
return 0;

View File

@ -1,9 +1,9 @@
/*
zip_set_name.c -- rename helper function
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -48,109 +48,109 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
zip_string_t *old_str;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
}
if (ZIP_IS_RDONLY(za)) {
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
return -1;
}
if (name && name[0] != '\0') {
/* TODO: check for string too long */
if ((str = _zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL)
return -1;
if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
str->encoding = ZIP_ENCODING_UTF8_KNOWN;
/* TODO: check for string too long */
if ((str = _zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL)
return -1;
if ((flags & ZIP_FL_ENCODING_ALL) == ZIP_FL_ENC_GUESS && _zip_guess_encoding(str, ZIP_ENCODING_UNKNOWN) == ZIP_ENCODING_UTF8_GUESSED)
str->encoding = ZIP_ENCODING_UTF8_KNOWN;
}
else
str = NULL;
str = NULL;
/* TODO: encoding flags needed for CP437? */
if ((i = _zip_name_locate(za, name, 0, NULL)) >= 0 && (zip_uint64_t)i != idx) {
_zip_string_free(str);
zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
return -1;
_zip_string_free(str);
zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
return -1;
}
/* no effective name change */
if (i >= 0 && (zip_uint64_t)i == idx) {
_zip_string_free(str);
return 0;
_zip_string_free(str);
return 0;
}
e = za->entry + idx;
if (e->orig)
same_as_orig = _zip_string_equal(e->orig->filename, str);
same_as_orig = _zip_string_equal(e->orig->filename, str);
else
same_as_orig = false;
same_as_orig = false;
if (!same_as_orig && e->changes == NULL) {
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
_zip_string_free(str);
return -1;
}
if ((e->changes = _zip_dirent_clone(e->orig)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
_zip_string_free(str);
return -1;
}
}
if ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) {
_zip_string_free(str);
return -1;
_zip_string_free(str);
return -1;
}
if (e->changes) {
old_str = e->changes->filename;
old_str = e->changes->filename;
}
else if (e->orig) {
old_str = e->orig->filename;
old_str = e->orig->filename;
}
else {
old_str = NULL;
old_str = NULL;
}
if (old_str) {
if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) {
_zip_string_free(str);
return -1;
}
if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) {
_zip_string_free(str);
return -1;
}
}
else {
old_name = NULL;
old_name = NULL;
}
if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) {
_zip_string_free(str);
return -1;
_zip_string_free(str);
return -1;
}
if (old_name) {
_zip_hash_delete(za->names, old_name, NULL);
_zip_hash_delete(za->names, old_name, NULL);
}
if (same_as_orig) {
if (e->changes) {
if (e->changes->changed & ZIP_DIRENT_FILENAME) {
_zip_string_free(e->changes->filename);
e->changes->changed &= ~ZIP_DIRENT_FILENAME;
if (e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
else {
/* TODO: what if not cloned? can that happen? */
e->changes->filename = e->orig->filename;
}
}
}
_zip_string_free(str);
if (e->changes) {
if (e->changes->changed & ZIP_DIRENT_FILENAME) {
_zip_string_free(e->changes->filename);
e->changes->changed &= ~ZIP_DIRENT_FILENAME;
if (e->changes->changed == 0) {
_zip_dirent_free(e->changes);
e->changes = NULL;
}
else {
/* TODO: what if not cloned? can that happen? */
e->changes->filename = e->orig->filename;
}
}
}
_zip_string_free(str);
}
else {
if (e->changes->changed & ZIP_DIRENT_FILENAME) {
_zip_string_free(e->changes->filename);
}
e->changes->changed |= ZIP_DIRENT_FILENAME;
e->changes->filename = str;
if (e->changes->changed & ZIP_DIRENT_FILENAME) {
_zip_string_free(e->changes->filename);
}
e->changes->changed |= ZIP_DIRENT_FILENAME;
e->changes->filename = str;
}
return 0;

View File

@ -1,9 +1,9 @@
/*
zip_source_accept_empty.c -- if empty source is a valid archive
Copyright (C) 2019 Dieter Baron and Thomas Klausner
Copyright (C) 2019-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -40,10 +40,10 @@ zip_source_accept_empty(zip_source_t *src) {
int ret;
if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_ACCEPT_EMPTY)) == 0) {
if (ZIP_SOURCE_IS_LAYERED(src)) {
return zip_source_accept_empty(src->src);
}
return true;
if (ZIP_SOURCE_IS_LAYERED(src)) {
return zip_source_accept_empty(src->src);
}
return true;
}
ret = (int)_zip_source_call(src, NULL, 0, ZIP_SOURCE_ACCEPT_EMPTY);

View File

@ -1,9 +1,9 @@
/*
zip_source_begin_write.c -- start a new file for writing
Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -38,12 +38,12 @@
ZIP_EXTERN int
zip_source_begin_write(zip_source_t *src) {
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;
}
if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_BEGIN_WRITE) < 0) {
return -1;
return -1;
}
src->write_state = ZIP_SOURCE_WRITE_OPEN;

View File

@ -1,9 +1,9 @@
/*
zip_source_begin_write_cloning.c -- clone part of file for writing
Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -38,12 +38,12 @@
ZIP_EXTERN int
zip_source_begin_write_cloning(zip_source_t *src, zip_uint64_t offset) {
if (ZIP_SOURCE_IS_OPEN_WRITING(src)) {
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;
}
if (_zip_source_call(src, NULL, offset, ZIP_SOURCE_BEGIN_WRITE_CLONING) < 0) {
return -1;
return -1;
}
src->write_state = ZIP_SOURCE_WRITE_OPEN;

View File

@ -1,9 +1,9 @@
/*
zip_source_buffer.c -- create zip data source from buffer
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2022 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -87,7 +87,7 @@ zip_source_t *zip_source_buffer_fragment_with_attributes_create(const zip_buffer
ZIP_EXTERN zip_source_t *
zip_source_buffer(zip_t *za, const void *data, zip_uint64_t len, int freep) {
if (za == NULL)
return NULL;
return NULL;
return zip_source_buffer_with_attributes_create(data, len, freep, NULL, &za->error);
}
@ -104,12 +104,12 @@ zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int
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_with_attributes_create(NULL, 0, freep, attributes, error);
return zip_source_buffer_fragment_with_attributes_create(NULL, 0, freep, attributes, error);
}
fragment.data = (zip_uint8_t *)data;
@ -122,7 +122,7 @@ zip_source_buffer_with_attributes_create(const void *data, zip_uint64_t len, int
ZIP_EXTERN zip_source_t *
zip_source_buffer_fragment(zip_t *za, const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int freep) {
if (za == NULL) {
return NULL;
return NULL;
}
return zip_source_buffer_fragment_with_attributes_create(fragments, nfragments, freep, NULL, &za->error);
@ -141,35 +141,35 @@ zip_source_buffer_fragment_with_attributes_create(const zip_buffer_fragment_t *f
buffer_t *buffer;
if (fragments == NULL && nfragments > 0) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
if ((buffer = buffer_new(fragments, nfragments, freep, error)) == NULL) {
return NULL;
return NULL;
}
if ((ctx = (struct read_data *)malloc(sizeof(*ctx))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
buffer_free(buffer);
return NULL;
zip_error_set(error, ZIP_ER_MEMORY, 0);
buffer_free(buffer);
return NULL;
}
ctx->in = buffer;
ctx->out = NULL;
ctx->mtime = time(NULL);
if (attributes) {
memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
memcpy(&ctx->attributes, attributes, sizeof(ctx->attributes));
}
else {
zip_file_attributes_init(&ctx->attributes);
zip_file_attributes_init(&ctx->attributes);
}
zip_error_init(&ctx->error);
if ((zs = zip_source_function_create(read_data, ctx, error)) == NULL) {
buffer_free(ctx->in);
free(ctx);
return NULL;
buffer_free(ctx->in);
free(ctx);
return NULL;
}
return zs;
@ -187,133 +187,133 @@ read_data(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
switch (cmd) {
case ZIP_SOURCE_BEGIN_WRITE:
if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) {
return -1;
}
ctx->out->offset = 0;
ctx->out->current_fragment = 0;
return 0;
if ((ctx->out = buffer_new(NULL, 0, 0, &ctx->error)) == NULL) {
return -1;
}
ctx->out->offset = 0;
ctx->out->current_fragment = 0;
return 0;
case ZIP_SOURCE_BEGIN_WRITE_CLONING:
if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) {
return -1;
}
ctx->out->offset = len;
ctx->out->current_fragment = ctx->out->nfragments;
return 0;
if ((ctx->out = buffer_clone(ctx->in, len, &ctx->error)) == NULL) {
return -1;
}
ctx->out->offset = len;
ctx->out->current_fragment = ctx->out->nfragments;
return 0;
case ZIP_SOURCE_CLOSE:
return 0;
return 0;
case ZIP_SOURCE_COMMIT_WRITE:
buffer_free(ctx->in);
ctx->in = ctx->out;
ctx->out = NULL;
return 0;
buffer_free(ctx->in);
ctx->in = ctx->out;
ctx->out = NULL;
return 0;
case ZIP_SOURCE_ERROR:
return zip_error_to_data(&ctx->error, data, len);
return zip_error_to_data(&ctx->error, data, len);
case ZIP_SOURCE_FREE:
buffer_free(ctx->in);
buffer_free(ctx->out);
free(ctx);
return 0;
buffer_free(ctx->in);
buffer_free(ctx->out);
free(ctx);
return 0;
case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
if (len < sizeof(ctx->attributes)) {
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
if (len < sizeof(ctx->attributes)) {
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
memcpy(data, &ctx->attributes, sizeof(ctx->attributes));
return sizeof(ctx->attributes);
return sizeof(ctx->attributes);
}
case ZIP_SOURCE_OPEN:
ctx->in->offset = 0;
ctx->in->current_fragment = 0;
return 0;
ctx->in->offset = 0;
ctx->in->current_fragment = 0;
return 0;
case ZIP_SOURCE_READ:
if (len > ZIP_INT64_MAX) {
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
return buffer_read(ctx->in, data, len);
if (len > ZIP_INT64_MAX) {
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
return buffer_read(ctx->in, data, len);
case ZIP_SOURCE_REMOVE: {
buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error);
if (empty == NULL) {
return -1;
}
buffer_t *empty = buffer_new(NULL, 0, 0, &ctx->error);
if (empty == NULL) {
return -1;
}
buffer_free(ctx->in);
ctx->in = empty;
return 0;
buffer_free(ctx->in);
ctx->in = empty;
return 0;
}
case ZIP_SOURCE_ROLLBACK_WRITE:
buffer_free(ctx->out);
ctx->out = NULL;
return 0;
buffer_free(ctx->out);
ctx->out = NULL;
return 0;
case ZIP_SOURCE_SEEK:
return buffer_seek(ctx->in, data, len, &ctx->error);
return buffer_seek(ctx->in, data, len, &ctx->error);
case ZIP_SOURCE_SEEK_WRITE:
return buffer_seek(ctx->out, data, len, &ctx->error);
return buffer_seek(ctx->out, data, len, &ctx->error);
case ZIP_SOURCE_STAT: {
zip_stat_t *st;
zip_stat_t *st;
if (len < sizeof(*st)) {
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
if (len < sizeof(*st)) {
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
st = (zip_stat_t *)data;
st = (zip_stat_t *)data;
zip_stat_init(st);
st->mtime = ctx->mtime;
st->size = ctx->in->size;
st->comp_size = st->size;
st->comp_method = ZIP_CM_STORE;
st->encryption_method = ZIP_EM_NONE;
st->valid = ZIP_STAT_MTIME | ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
zip_stat_init(st);
st->mtime = ctx->mtime;
st->size = ctx->in->size;
st->comp_size = st->size;
st->comp_method = ZIP_CM_STORE;
st->encryption_method = ZIP_EM_NONE;
st->valid = ZIP_STAT_MTIME | ZIP_STAT_SIZE | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
return sizeof(*st);
return sizeof(*st);
}
case ZIP_SOURCE_SUPPORTS:
return zip_source_make_command_bitmap(ZIP_SOURCE_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);
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) {
zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
return -1;
}
return (zip_int64_t)ctx->in->offset;
if (ctx->in->offset > ZIP_INT64_MAX) {
zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
return -1;
}
return (zip_int64_t)ctx->in->offset;
case ZIP_SOURCE_TELL_WRITE:
if (ctx->out->offset > ZIP_INT64_MAX) {
zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
return -1;
}
return (zip_int64_t)ctx->out->offset;
if (ctx->out->offset > ZIP_INT64_MAX) {
zip_error_set(&ctx->error, ZIP_ER_TELL, EOVERFLOW);
return -1;
}
return (zip_int64_t)ctx->out->offset;
case ZIP_SOURCE_WRITE:
if (len > ZIP_INT64_MAX) {
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
return buffer_write(ctx->out, data, len, &ctx->error);
if (len > ZIP_INT64_MAX) {
zip_error_set(&ctx->error, ZIP_ER_INVAL, 0);
return -1;
}
return buffer_write(ctx->out, data, len, &ctx->error);
default:
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
}
@ -324,34 +324,34 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
buffer_t *clone;
if (offset == 0) {
return buffer_new(NULL, 0, 1, error);
return buffer_new(NULL, 0, 1, error);
}
if (offset > buffer->size) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
if (buffer->shared_buffer != NULL) {
zip_error_set(error, ZIP_ER_INUSE, 0);
return NULL;
zip_error_set(error, ZIP_ER_INUSE, 0);
return NULL;
}
fragment = buffer_find_fragment(buffer, offset);
fragment_offset = offset - buffer->fragment_offsets[fragment];
if (fragment_offset == 0) {
fragment--;
fragment_offset = buffer->fragments[fragment].length;
fragment--;
fragment_offset = buffer->fragments[fragment].length;
}
waste = buffer->fragments[fragment].length - fragment_offset;
if (waste > offset) {
zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
return NULL;
zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
return NULL;
}
if ((clone = buffer_new(buffer->fragments, fragment + 1, 0, error)) == NULL) {
return NULL;
return NULL;
}
#ifndef __clang_analyzer__
@ -361,13 +361,13 @@ buffer_clone(buffer_t *buffer, zip_uint64_t offset, zip_error_t *error) {
clone->fragment_offsets[clone->nfragments] = offset;
clone->size = offset;
clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments - 1);
clone->first_owned_fragment = ZIP_MIN(buffer->first_owned_fragment, clone->nfragments);
buffer->shared_buffer = clone;
clone->shared_buffer = buffer;
buffer->shared_fragments = clone->nfragments;
clone->shared_fragments = fragment + 1;
return clone;
}
@ -376,20 +376,24 @@ static zip_uint64_t
buffer_find_fragment(const buffer_t *buffer, zip_uint64_t offset) {
zip_uint64_t low, high, mid;
if (buffer->nfragments == 0) {
return 0;
}
low = 0;
high = buffer->nfragments - 1;
while (low < high) {
mid = (high - low) / 2 + low;
if (buffer->fragment_offsets[mid] > offset) {
high = mid - 1;
}
else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) {
return mid;
}
else {
low = mid + 1;
}
mid = (high - low) / 2 + low;
if (buffer->fragment_offsets[mid] > offset) {
high = mid - 1;
}
else if (mid == buffer->nfragments || buffer->fragment_offsets[mid + 1] > offset) {
return mid;
}
else {
low = mid + 1;
}
}
return low;
@ -401,18 +405,18 @@ buffer_free(buffer_t *buffer) {
zip_uint64_t i;
if (buffer == NULL) {
return;
return;
}
if (buffer->shared_buffer != NULL) {
buffer->shared_buffer->shared_buffer = NULL;
buffer->shared_buffer->shared_fragments = 0;
buffer->shared_buffer->shared_buffer = NULL;
buffer->shared_buffer->shared_fragments = 0;
buffer->first_owned_fragment = ZIP_MAX(buffer->first_owned_fragment, buffer->shared_fragments);
buffer->first_owned_fragment = ZIP_MAX(buffer->first_owned_fragment, buffer->shared_fragments);
}
for (i = buffer->first_owned_fragment; i < buffer->nfragments; i++) {
free(buffer->fragments[i].data);
free(buffer->fragments[i].data);
}
free(buffer->fragments);
free(buffer->fragment_offsets);
@ -426,17 +430,17 @@ buffer_grow_fragments(buffer_t *buffer, zip_uint64_t capacity, zip_error_t *erro
zip_uint64_t *offsets;
if (capacity < buffer->fragments_capacity) {
return true;
return true;
}
if ((fragments = realloc(buffer->fragments, sizeof(buffer->fragments[0]) * capacity)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
buffer->fragments = fragments;
if ((offsets = realloc(buffer->fragment_offsets, sizeof(buffer->fragment_offsets[0]) * (capacity + 1))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
zip_error_set(error, ZIP_ER_MEMORY, 0);
return false;
}
buffer->fragment_offsets = offsets;
buffer->fragments_capacity = capacity;
@ -450,7 +454,7 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int
buffer_t *buffer;
if ((buffer = malloc(sizeof(*buffer))) == NULL) {
return NULL;
return NULL;
}
buffer->offset = 0;
@ -464,42 +468,42 @@ buffer_new(const zip_buffer_fragment_t *fragments, zip_uint64_t nfragments, int
buffer->shared_fragments = 0;
if (nfragments == 0) {
if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) {
free(buffer);
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
buffer->fragment_offsets[0] = 0;
if ((buffer->fragment_offsets = malloc(sizeof(buffer->fragment_offsets[0]))) == NULL) {
free(buffer);
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
buffer->fragment_offsets[0] = 0;
}
else {
zip_uint64_t i, j, offset;
zip_uint64_t i, j, offset;
if (!buffer_grow_fragments(buffer, nfragments, NULL)) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
buffer_free(buffer);
return NULL;
}
if (!buffer_grow_fragments(buffer, nfragments, NULL)) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
buffer_free(buffer);
return NULL;
}
offset = 0;
for (i = 0, j = 0; i < nfragments; i++) {
if (fragments[i].length == 0) {
continue;
}
if (fragments[i].data == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
buffer_free(buffer);
return NULL;
}
buffer->fragments[j].data = fragments[i].data;
buffer->fragments[j].length = fragments[i].length;
buffer->fragment_offsets[i] = offset;
offset += fragments[i].length;
j++;
}
buffer->nfragments = j;
buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments;
buffer->fragment_offsets[buffer->nfragments] = offset;
buffer->size = offset;
offset = 0;
for (i = 0, j = 0; i < nfragments; i++) {
if (fragments[i].length == 0) {
continue;
}
if (fragments[i].data == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
buffer_free(buffer);
return NULL;
}
buffer->fragments[j].data = fragments[i].data;
buffer->fragments[j].length = fragments[i].length;
buffer->fragment_offsets[i] = offset;
offset += fragments[i].length;
j++;
}
buffer->nfragments = j;
buffer->first_owned_fragment = free_data ? 0 : buffer->nfragments;
buffer->fragment_offsets[buffer->nfragments] = offset;
buffer->size = offset;
}
return buffer;
@ -512,25 +516,25 @@ buffer_read(buffer_t *buffer, zip_uint8_t *data, zip_uint64_t length) {
length = ZIP_MIN(length, buffer->size - buffer->offset);
if (length == 0) {
return 0;
return 0;
}
if (length > ZIP_INT64_MAX) {
return -1;
return -1;
}
i = buffer->current_fragment;
fragment_offset = buffer->offset - buffer->fragment_offsets[i];
n = 0;
while (n < length) {
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
memcpy(data + n, buffer->fragments[i].data + fragment_offset, left);
memcpy(data + n, buffer->fragments[i].data + fragment_offset, left);
if (left == buffer->fragments[i].length - fragment_offset) {
i++;
}
n += left;
fragment_offset = 0;
if (left == buffer->fragments[i].length - fragment_offset) {
i++;
}
n += left;
fragment_offset = 0;
}
buffer->offset += n;
@ -544,7 +548,7 @@ buffer_seek(buffer_t *buffer, void *data, zip_uint64_t len, zip_error_t *error)
zip_int64_t new_offset = zip_source_seek_compute_offset(buffer->offset, buffer->size, data, len, error);
if (new_offset < 0) {
return -1;
return -1;
}
buffer->offset = (zip_uint64_t)new_offset;
@ -558,62 +562,62 @@ buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip
zip_uint64_t n, i, fragment_offset, capacity;
if (buffer->offset + length + WRITE_FRAGMENT_SIZE - 1 < length) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(error, ZIP_ER_INVAL, 0);
return -1;
}
/* grow buffer if needed */
capacity = buffer_capacity(buffer);
if (buffer->offset + length > capacity) {
zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE;
zip_uint64_t needed_fragments = buffer->nfragments + (length - (capacity - buffer->offset) + WRITE_FRAGMENT_SIZE - 1) / WRITE_FRAGMENT_SIZE;
if (needed_fragments > buffer->fragments_capacity) {
zip_uint64_t new_capacity = buffer->fragments_capacity;
if (needed_fragments > buffer->fragments_capacity) {
zip_uint64_t new_capacity = buffer->fragments_capacity;
if (new_capacity == 0) {
new_capacity = 16;
}
while (new_capacity < needed_fragments) {
new_capacity *= 2;
}
if (new_capacity == 0) {
new_capacity = 16;
}
while (new_capacity < needed_fragments) {
new_capacity *= 2;
}
if (!buffer_grow_fragments(buffer, new_capacity, error)) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return -1;
}
}
if (!buffer_grow_fragments(buffer, new_capacity, error)) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return -1;
}
}
while (buffer->nfragments < needed_fragments) {
if ((buffer->fragments[buffer->nfragments].data = malloc(WRITE_FRAGMENT_SIZE)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return -1;
}
buffer->fragments[buffer->nfragments].length = WRITE_FRAGMENT_SIZE;
buffer->nfragments++;
capacity += WRITE_FRAGMENT_SIZE;
buffer->fragment_offsets[buffer->nfragments] = capacity;
}
while (buffer->nfragments < needed_fragments) {
if ((buffer->fragments[buffer->nfragments].data = malloc(WRITE_FRAGMENT_SIZE)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return -1;
}
buffer->fragments[buffer->nfragments].length = WRITE_FRAGMENT_SIZE;
buffer->nfragments++;
capacity += WRITE_FRAGMENT_SIZE;
buffer->fragment_offsets[buffer->nfragments] = capacity;
}
}
i = buffer->current_fragment;
fragment_offset = buffer->offset - buffer->fragment_offsets[i];
n = 0;
while (n < length) {
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
zip_uint64_t left = ZIP_MIN(length - n, buffer->fragments[i].length - fragment_offset);
memcpy(buffer->fragments[i].data + fragment_offset, data + n, left);
memcpy(buffer->fragments[i].data + fragment_offset, data + n, left);
if (left == buffer->fragments[i].length - fragment_offset) {
i++;
}
n += left;
fragment_offset = 0;
if (left == buffer->fragments[i].length - fragment_offset) {
i++;
}
n += left;
fragment_offset = 0;
}
buffer->offset += n;
buffer->current_fragment = i;
if (buffer->offset > buffer->size) {
buffer->size = buffer->offset;
buffer->size = buffer->offset;
}
return (zip_int64_t)n;

View File

@ -1,9 +1,9 @@
/*
zip_source_call.c -- invoke callback command on zip_source
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -40,28 +40,28 @@ _zip_source_call(zip_source_t *src, void *data, zip_uint64_t length, zip_source_
zip_int64_t ret;
if ((src->supports & ZIP_SOURCE_MAKE_COMMAND_BITMASK(command)) == 0) {
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
zip_error_set(&src->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
if (src->src == NULL) {
ret = src->cb.f(src->ud, data, length, command);
ret = src->cb.f(src->ud, data, length, command);
}
else {
ret = src->cb.l(src->src, src->ud, data, length, command);
ret = src->cb.l(src->src, src->ud, data, length, command);
}
if (ret < 0) {
if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) {
int e[2];
if (command != ZIP_SOURCE_ERROR && command != ZIP_SOURCE_SUPPORTS) {
int e[2];
if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) {
zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
}
else {
zip_error_set(&src->error, e[0], e[1]);
}
}
if (_zip_source_call(src, e, sizeof(e), ZIP_SOURCE_ERROR) < 0) {
zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
}
else {
zip_error_set(&src->error, e[0], e[1]);
}
}
}
return ret;

View File

@ -1,9 +1,9 @@
/*
zip_source_close.c -- close zip_source (stop reading)
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -38,19 +38,19 @@
int
zip_source_close(zip_source_t *src) {
if (!ZIP_SOURCE_IS_OPEN_READING(src)) {
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;
}
src->open_count--;
if (src->open_count == 0) {
_zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE);
_zip_source_call(src, NULL, 0, ZIP_SOURCE_CLOSE);
if (ZIP_SOURCE_IS_LAYERED(src)) {
if (zip_source_close(src->src) < 0) {
zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
}
}
if (ZIP_SOURCE_IS_LAYERED(src)) {
if (zip_source_close(src->src) < 0) {
zip_error_set(&src->error, ZIP_ER_INTERNAL, 0);
}
}
}
return 0;

View File

@ -1,9 +1,9 @@
/*
zip_source_commit_write.c -- commit changes to file
Copyright (C) 2014-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2014-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -38,23 +38,23 @@
ZIP_EXTERN int
zip_source_commit_write(zip_source_t *src) {
if (!ZIP_SOURCE_IS_OPEN_WRITING(src)) {
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;
zip_error_set(&src->error, ZIP_ER_INVAL, 0);
return -1;
}
if (src->open_count > 1) {
zip_error_set(&src->error, ZIP_ER_INUSE, 0);
return -1;
zip_error_set(&src->error, ZIP_ER_INUSE, 0);
return -1;
}
else if (ZIP_SOURCE_IS_OPEN_READING(src)) {
if (zip_source_close(src) < 0) {
return -1;
}
if (zip_source_close(src) < 0) {
return -1;
}
}
if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_COMMIT_WRITE) < 0) {
src->write_state = ZIP_SOURCE_WRITE_FAILED;
return -1;
src->write_state = ZIP_SOURCE_WRITE_FAILED;
return -1;
}
src->write_state = ZIP_SOURCE_WRITE_CLOSED;

View File

@ -1,9 +1,9 @@
/*
zip_source_compress.c -- (de)compression routines
Copyright (C) 2017-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2017-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -67,14 +67,17 @@ static struct implementation implementations[] = {
{ZIP_CM_BZIP2, &zip_algorithm_bzip2_compress, &zip_algorithm_bzip2_decompress},
#endif
#if defined(HAVE_LIBLZMA)
/* Disabled - because 7z isn't able to unpack ZIP+LZMA ZIP+LZMA2
archives made this way - and vice versa.
{ZIP_CM_LZMA, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
/* Disabled - because 7z isn't able to unpack 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_LZMA2, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
*/
{ZIP_CM_XZ, &zip_algorithm_xz_compress, &zip_algorithm_xz_decompress},
#endif
#if defined(HAVE_LIBZSTD)
{ZIP_CM_ZSTD, &zip_algorithm_zstd_compress, &zip_algorithm_zstd_decompress},
#endif
};
@ -86,20 +89,20 @@ static void context_free(struct context *ctx);
static struct context *context_new(zip_int32_t method, bool compress, int compression_flags, zip_compression_algorithm_t *algorithm);
static zip_int64_t compress_read(zip_source_t *, struct context *, void *, zip_uint64_t);
static zip_compression_algorithm_t *
get_algorithm(zip_int32_t method, bool compress) {
zip_compression_algorithm_t *
_zip_get_compression_algorithm(zip_int32_t method, bool compress) {
size_t i;
zip_uint16_t real_method = ZIP_CM_ACTUAL(method);
for (i = 0; i < implementations_size; i++) {
if (implementations[i].method == real_method) {
if (compress) {
return implementations[i].compress;
}
else {
return implementations[i].decompress;
}
}
if (implementations[i].method == real_method) {
if (compress) {
return implementations[i].compress;
}
else {
return implementations[i].decompress;
}
}
}
return NULL;
@ -108,9 +111,9 @@ get_algorithm(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 1;
return 1;
}
return get_algorithm(method, compress) != NULL;
return _zip_get_compression_algorithm(method, compress) != NULL;
}
zip_source_t *
@ -131,23 +134,23 @@ compression_source_new(zip_t *za, zip_source_t *src, zip_int32_t method, bool co
zip_compression_algorithm_t *algorithm = NULL;
if (src == NULL) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return NULL;
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return NULL;
}
if ((algorithm = get_algorithm(method, compress)) == NULL) {
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
return NULL;
if ((algorithm = _zip_get_compression_algorithm(method, compress)) == NULL) {
zip_error_set(&za->error, ZIP_ER_COMPNOTSUPP, 0);
return NULL;
}
if ((ctx = context_new(method, compress, compression_flags, algorithm)) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return NULL;
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return NULL;
}
if ((s2 = zip_source_layered(za, src, compress_callback, ctx)) == NULL) {
context_free(ctx);
return NULL;
context_free(ctx);
return NULL;
}
return s2;
@ -159,7 +162,7 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre
struct context *ctx;
if ((ctx = (struct context *)malloc(sizeof(*ctx))) == NULL) {
return NULL;
return NULL;
}
zip_error_init(&ctx->error);
ctx->can_store = compress ? ZIP_CM_IS_DEFAULT(method) : false;
@ -171,9 +174,9 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre
ctx->is_stored = false;
if ((ctx->ud = ctx->algorithm->allocate(ZIP_CM_ACTUAL(method), compression_flags, &ctx->error)) == NULL) {
zip_error_fini(&ctx->error);
free(ctx);
return NULL;
zip_error_fini(&ctx->error);
free(ctx);
return NULL;
}
return ctx;
@ -183,7 +186,7 @@ context_new(zip_int32_t method, bool compress, int compression_flags, zip_compre
static void
context_free(struct context *ctx) {
if (ctx == NULL) {
return;
return;
}
ctx->algorithm->deallocate(ctx->ud);
@ -202,96 +205,96 @@ compress_read(zip_source_t *src, struct context *ctx, void *data, zip_uint64_t l
zip_uint64_t out_len;
if (zip_error_code_zip(&ctx->error) != ZIP_ER_OK) {
return -1;
return -1;
}
if (len == 0 || ctx->end_of_stream) {
return 0;
return 0;
}
out_offset = 0;
end = false;
while (!end && out_offset < len) {
out_len = len - out_offset;
ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len);
out_len = len - out_offset;
ret = ctx->algorithm->process(ctx->ud, (zip_uint8_t *)data + out_offset, &out_len);
if (ret != ZIP_COMPRESSION_ERROR) {
out_offset += out_len;
}
if (ret != ZIP_COMPRESSION_ERROR) {
out_offset += out_len;
}
switch (ret) {
case ZIP_COMPRESSION_END:
ctx->end_of_stream = true;
switch (ret) {
case ZIP_COMPRESSION_END:
ctx->end_of_stream = true;
if (!ctx->end_of_input) {
/* TODO: garbage after stream, or compression ended before all data read */
}
if (!ctx->end_of_input) {
/* TODO: garbage after stream, or compression ended before all data read */
}
if (ctx->first_read < 0) {
/* we got end of processed stream before reading any input data */
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
end = true;
break;
}
if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) {
ctx->is_stored = true;
ctx->size = (zip_uint64_t)ctx->first_read;
memcpy(data, ctx->buffer, ctx->size);
return (zip_int64_t)ctx->size;
}
end = true;
break;
if (ctx->first_read < 0) {
/* we got end of processed stream before reading any input data */
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
end = true;
break;
}
if (ctx->can_store && (zip_uint64_t)ctx->first_read <= out_offset) {
ctx->is_stored = true;
ctx->size = (zip_uint64_t)ctx->first_read;
memcpy(data, ctx->buffer, ctx->size);
return (zip_int64_t)ctx->size;
}
end = true;
break;
case ZIP_COMPRESSION_OK:
break;
case ZIP_COMPRESSION_OK:
break;
case ZIP_COMPRESSION_NEED_DATA:
if (ctx->end_of_input) {
/* TODO: error: stream not ended, but no more input */
end = true;
break;
}
case ZIP_COMPRESSION_NEED_DATA:
if (ctx->end_of_input) {
/* TODO: error: stream not ended, but no more input */
end = true;
break;
}
if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
_zip_error_set_from_source(&ctx->error, src);
end = true;
break;
}
else if (n == 0) {
ctx->end_of_input = true;
ctx->algorithm->end_of_input(ctx->ud);
if (ctx->first_read < 0) {
ctx->first_read = 0;
}
}
else {
if (ctx->first_read >= 0) {
/* we overwrote a previously filled ctx->buffer */
ctx->can_store = false;
}
else {
ctx->first_read = n;
}
if ((n = zip_source_read(src, ctx->buffer, sizeof(ctx->buffer))) < 0) {
_zip_error_set_from_source(&ctx->error, src);
end = true;
break;
}
else if (n == 0) {
ctx->end_of_input = true;
ctx->algorithm->end_of_input(ctx->ud);
if (ctx->first_read < 0) {
ctx->first_read = 0;
}
}
else {
if (ctx->first_read >= 0) {
/* we overwrote a previously filled ctx->buffer */
ctx->can_store = false;
}
else {
ctx->first_read = n;
}
ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n);
}
break;
ctx->algorithm->input(ctx->ud, ctx->buffer, (zip_uint64_t)n);
}
break;
case ZIP_COMPRESSION_ERROR:
/* error set by algorithm */
if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) {
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
}
end = true;
break;
}
case ZIP_COMPRESSION_ERROR:
/* error set by algorithm */
if (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) {
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
}
end = true;
break;
}
}
if (out_offset > 0) {
ctx->can_store = false;
ctx->size += out_offset;
return (zip_int64_t)out_offset;
ctx->can_store = false;
ctx->size += out_offset;
return (zip_int64_t)out_offset;
}
return (zip_error_code_zip(&ctx->error) == ZIP_ER_OK) ? 0 : -1;
@ -305,85 +308,91 @@ compress_callback(zip_source_t *src, void *ud, void *data, zip_uint64_t len, zip
ctx = (struct context *)ud;
switch (cmd) {
case ZIP_SOURCE_OPEN:
ctx->size = 0;
ctx->end_of_input = false;
ctx->end_of_stream = false;
ctx->is_stored = false;
ctx->first_read = -1;
case ZIP_SOURCE_OPEN: {
zip_stat_t st;
zip_file_attributes_t attributes;
ctx->size = 0;
ctx->end_of_input = false;
ctx->end_of_stream = false;
ctx->is_stored = false;
ctx->first_read = -1;
if (zip_source_stat(src, &st) < 0 || zip_source_get_file_attributes(src, &attributes) < 0) {
_zip_error_set_from_source(&ctx->error, src);
return -1;
}
if (!ctx->algorithm->start(ctx->ud)) {
return -1;
}
if (!ctx->algorithm->start(ctx->ud, &st, &attributes)) {
return -1;
}
return 0;
return 0;
}
case ZIP_SOURCE_READ:
return compress_read(src, ctx, data, len);
return compress_read(src, ctx, data, len);
case ZIP_SOURCE_CLOSE:
if (!ctx->algorithm->end(ctx->ud)) {
return -1;
}
return 0;
if (!ctx->algorithm->end(ctx->ud)) {
return -1;
}
return 0;
case ZIP_SOURCE_STAT: {
zip_stat_t *st;
zip_stat_t *st;
st = (zip_stat_t *)data;
st = (zip_stat_t *)data;
if (ctx->compress) {
if (ctx->end_of_stream) {
st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method);
st->comp_size = ctx->size;
st->valid |= ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD;
}
else {
st->valid &= ~(ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD);
}
}
else {
st->comp_method = ZIP_CM_STORE;
st->valid |= ZIP_STAT_COMP_METHOD;
if (ctx->end_of_stream) {
st->size = ctx->size;
st->valid |= ZIP_STAT_SIZE;
}
else {
st->valid &= ~ZIP_STAT_SIZE;
}
}
if (ctx->compress) {
if (ctx->end_of_stream) {
st->comp_method = ctx->is_stored ? ZIP_CM_STORE : ZIP_CM_ACTUAL(ctx->method);
st->comp_size = ctx->size;
st->valid |= ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD;
}
else {
st->valid &= ~(ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD);
}
}
else {
st->comp_method = ZIP_CM_STORE;
st->valid |= ZIP_STAT_COMP_METHOD;
if (ctx->end_of_stream) {
st->size = ctx->size;
st->valid |= ZIP_STAT_SIZE;
}
}
}
return 0;
return 0;
case ZIP_SOURCE_ERROR:
return zip_error_to_data(&ctx->error, data, len);
return zip_error_to_data(&ctx->error, data, len);
case ZIP_SOURCE_FREE:
context_free(ctx);
return 0;
context_free(ctx);
return 0;
case ZIP_SOURCE_GET_FILE_ATTRIBUTES: {
zip_file_attributes_t *attributes = (zip_file_attributes_t *)data;
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;
}
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));
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);
return sizeof(*attributes);
}
case ZIP_SOURCE_SUPPORTS:
return ZIP_SOURCE_SUPPORTS_READABLE | zip_source_make_command_bitmap(ZIP_SOURCE_GET_FILE_ATTRIBUTES, -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);
return -1;
zip_error_set(&ctx->error, ZIP_ER_INTERNAL, 0);
return -1;
}
}

View File

@ -1,9 +1,9 @@
/*
zip_source_crc.c -- pass-through source that calculates CRC32 and size
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -52,17 +52,17 @@ static zip_int64_t crc_read(zip_source_t *, void *, void *, zip_uint64_t, zip_so
zip_source_t *
zip_source_crc(zip_t *za, zip_source_t *src, int validate) {
zip_source_crc_create(zip_source_t *src, int validate, zip_error_t *error) {
struct crc_context *ctx;
if (src == NULL) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return NULL;
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
if ((ctx = (struct crc_context *)malloc(sizeof(*ctx))) == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return NULL;
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
}
zip_error_init(&ctx->error);
@ -72,7 +72,7 @@ zip_source_crc(zip_t *za, zip_source_t *src, int validate) {
ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
ctx->size = 0;
return zip_source_layered(za, src, crc_read, ctx);
return zip_source_layered_create(src, crc_read, ctx, error);
}
@ -85,113 +85,114 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
switch (cmd) {
case ZIP_SOURCE_OPEN:
ctx->position = 0;
return 0;
ctx->position = 0;
return 0;
case ZIP_SOURCE_READ:
if ((n = zip_source_read(src, data, len)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
return -1;
}
if ((n = zip_source_read(src, data, len)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
return -1;
}
if (n == 0) {
if (ctx->crc_position == ctx->position) {
ctx->crc_complete = 1;
ctx->size = ctx->position;
if (n == 0) {
if (ctx->crc_position == ctx->position) {
ctx->crc_complete = 1;
ctx->size = ctx->position;
if (ctx->validate) {
struct zip_stat st;
if (ctx->validate) {
struct zip_stat st;
if (zip_source_stat(src, &st) < 0) {
_zip_error_set_from_source(&ctx->error, src);
return -1;
}
if (zip_source_stat(src, &st) < 0) {
_zip_error_set_from_source(&ctx->error, src);
return -1;
}
if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
return -1;
}
if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
return -1;
}
}
}
}
else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) {
zip_uint64_t i, nn;
if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
return -1;
}
if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
/* We don't have the index here, but the caller should know which file they are reading from. */
zip_error_set(&ctx->error, ZIP_ER_INCONS, MAKE_DETAIL_WITH_INDEX(ZIP_ER_DETAIL_INVALID_FILE_LENGTH, MAX_DETAIL_INDEX));
return -1;
}
}
}
}
else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) {
zip_uint64_t i, nn;
for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n - i);
for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n - i);
ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data + i, (uInt)nn);
ctx->crc_position += nn;
}
}
ctx->position += (zip_uint64_t)n;
return n;
ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data + i, (uInt)nn);
ctx->crc_position += nn;
}
}
ctx->position += (zip_uint64_t)n;
return n;
case ZIP_SOURCE_CLOSE:
return 0;
return 0;
case ZIP_SOURCE_STAT: {
zip_stat_t *st;
zip_stat_t *st;
st = (zip_stat_t *)data;
st = (zip_stat_t *)data;
if (ctx->crc_complete) {
/* TODO: Set comp_size, comp_method, encryption_method?
After all, this only works for uncompressed data. */
st->size = ctx->size;
st->crc = ctx->crc;
st->comp_size = ctx->size;
st->comp_method = ZIP_CM_STORE;
st->encryption_method = ZIP_EM_NONE;
st->valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
}
return 0;
if (ctx->crc_complete) {
/* TODO: Set comp_size, comp_method, encryption_method?
After all, this only works for uncompressed data. */
st->size = ctx->size;
st->crc = ctx->crc;
st->comp_size = ctx->size;
st->comp_method = ZIP_CM_STORE;
st->encryption_method = ZIP_EM_NONE;
st->valid |= ZIP_STAT_SIZE | ZIP_STAT_CRC | ZIP_STAT_COMP_SIZE | ZIP_STAT_COMP_METHOD | ZIP_STAT_ENCRYPTION_METHOD;
}
return 0;
}
case ZIP_SOURCE_ERROR:
return zip_error_to_data(&ctx->error, data, len);
return zip_error_to_data(&ctx->error, data, len);
case ZIP_SOURCE_FREE:
free(ctx);
return 0;
free(ctx);
return 0;
case ZIP_SOURCE_SUPPORTS: {
zip_int64_t mask = zip_source_supports(src);
zip_int64_t mask = zip_source_supports(src);
if (mask < 0) {
_zip_error_set_from_source(&ctx->error, src);
return -1;
}
if (mask < 0) {
_zip_error_set_from_source(&ctx->error, src);
return -1;
}
return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, ZIP_SOURCE_GET_FILE_ATTRIBUTES, -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: {
zip_int64_t new_position;
zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
zip_int64_t new_position;
zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
if (args == NULL) {
return -1;
}
if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
return -1;
}
if (args == NULL) {
return -1;
}
if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
return -1;
}
ctx->position = (zip_uint64_t)new_position;
ctx->position = (zip_uint64_t)new_position;
return 0;
return 0;
}
case ZIP_SOURCE_TELL:
return (zip_int64_t)ctx->position;
return (zip_int64_t)ctx->position;
default:
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
}

View File

@ -1,9 +1,9 @@
/*
zip_source_error.c -- get last error from zip_source
Copyright (C) 2009-2019 Dieter Baron and Thomas Klausner
Copyright (C) 2009-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@ -1,9 +1,9 @@
/*
zip_source_file.h -- header for common file operations
Copyright (C) 2020 Dieter Baron and Thomas Klausner
Copyright (C) 2020-2022 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -34,7 +34,7 @@
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 exists; /* must always be valid */
bool regular_file; /* must always be valid */
};

View File

@ -1,9 +1,9 @@
/*
zip_source_file_common.c -- create data source from file
Copyright (C) 1999-2019 Dieter Baron and Thomas Klausner
Copyright (C) 1999-2021 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
The authors can be contacted at <info@libzip.org>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -56,70 +56,70 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi
zip_source_file_stat_t sb;
if (ops == NULL) {
zip_error_set(error, ZIP_ER_INVAL, 0);
return 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;
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;
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;
}
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;
zip_error_set(error, ZIP_ER_INVAL, 0);
return NULL;
}
if (len < 0) {
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;
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;
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;
}
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;
memcpy(&ctx->st, st, sizeof(ctx->st));
ctx->st.name = NULL;
ctx->st.valid &= ~ZIP_STAT_NAME;
}
else {
zip_stat_init(&ctx->st);
zip_stat_init(&ctx->st);
}
if (ctx->len > 0) {
ctx->st.size = ctx->len;
ctx->st.valid |= ZIP_STAT_SIZE;
ctx->st.size = ctx->len;
ctx->st.valid |= ZIP_STAT_SIZE;
}
zip_error_init(&ctx->stat_error);
@ -154,46 +154,46 @@ zip_source_file_common_new(const char *fname, void *file, zip_uint64_t start, zi
}
}
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->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->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;
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;
}
}
}
/* 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_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 (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;
free(ctx->fname);
free(ctx);
return NULL;
}
return zs;
@ -210,169 +210,169 @@ read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd) {
switch (cmd) {
case ZIP_SOURCE_ACCEPT_EMPTY:
return 0;
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);
/* 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);
/* 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;
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;
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);
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;
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);
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->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;
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;
zip_int64_t i;
zip_uint64_t n;
if (ctx->len > 0) {
n = ZIP_MIN(ctx->len - ctx->offset, len);
}
else {
n = len;
}
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;
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;
return i;
}
case ZIP_SOURCE_REMOVE:
return ctx->ops->remove(ctx);
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;
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);
zip_int64_t new_offset = zip_source_seek_compute_offset(ctx->offset, ctx->len, data, len, &ctx->error);
if (new_offset < 0) {
return -1;
}
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;
}
/* 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;
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;
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;
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;
}
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;
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 (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;
}
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);
memcpy(data, &ctx->st, sizeof(ctx->st));
return sizeof(ctx->st);
}
case ZIP_SOURCE_SUPPORTS:
return ctx->supports;
return ctx->supports;
case ZIP_SOURCE_TELL:
return (zip_int64_t)ctx->offset;
return (zip_int64_t)ctx->offset;
case ZIP_SOURCE_TELL_WRITE:
return ctx->ops->tell(ctx, ctx->fout);
return ctx->ops->tell(ctx, ctx->fout);
case ZIP_SOURCE_WRITE:
return ctx->ops->write(ctx, data, len);
return ctx->ops->write(ctx, data, len);
default:
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
return -1;
}
}

Some files were not shown because too many files have changed in this diff Show More