Mercurial > hg > orthanc
changeset 6596:de1b2b661ec3
upgrade to minizip 1.3.2
| author | Sebastien Jodogne <s.jodogne@gmail.com> |
|---|---|
| date | Fri, 20 Feb 2026 16:03:16 +0100 |
| parents | c23bb535bade |
| children | 81746b9484c4 |
| files | NEWS OrthancFramework/Resources/ThirdParty/minizip/NOTES OrthancFramework/Resources/ThirdParty/minizip/SyncMinizip.py OrthancFramework/Resources/ThirdParty/minizip/crypt.h OrthancFramework/Resources/ThirdParty/minizip/ints.h OrthancFramework/Resources/ThirdParty/minizip/ioapi.c OrthancFramework/Resources/ThirdParty/minizip/ioapi.h OrthancFramework/Resources/ThirdParty/minizip/skipset.h OrthancFramework/Resources/ThirdParty/minizip/unzip.c OrthancFramework/Resources/ThirdParty/minizip/unzip.h OrthancFramework/Resources/ThirdParty/minizip/zip.c OrthancFramework/Resources/ThirdParty/minizip/zip.h |
| diffstat | 12 files changed, 865 insertions(+), 146 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Fri Feb 20 15:41:05 2026 +0100 +++ b/NEWS Fri Feb 20 16:03:16 2026 +0100 @@ -48,6 +48,7 @@ * Upgraded dependencies for static builds: - boost 1.89.0 - dcmtk 3.7.0 + - minizip 1.3.2 NB: To maintain compatibility with Windows XP, which is not supported by DCMTK 3.7.0, Windows 32-bit builds must use
--- a/OrthancFramework/Resources/ThirdParty/minizip/NOTES Fri Feb 20 15:41:05 2026 +0100 +++ b/OrthancFramework/Resources/ThirdParty/minizip/NOTES Fri Feb 20 16:03:16 2026 +0100 @@ -1,2 +1,2 @@ -These files come from the "contrib/minizip" directory in zlib 1.3+. -It was last synced on this commit: https://github.com/madler/zlib/commit/73331a6a0481067628f065ffe87bb1d8f787d10c. +These files come from the "contrib/minizip" directory in zlib. +The Python script "./SyncMinizip.py" can be used to update the version of minizip.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancFramework/Resources/ThirdParty/minizip/SyncMinizip.py Fri Feb 20 16:03:16 2026 +0100 @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 + +import os +import requests + +ZLIB_VERSION = '1.3.2' +URL = 'https://raw.githubusercontent.com/madler/zlib/refs/tags/v%s/contrib/minizip' % ZLIB_VERSION +TARGET = os.path.join(os.path.dirname(__file__)) + +for f in [ + 'crypt.h', + 'ints.h', + 'ioapi.c', + 'ioapi.h', + 'skipset.h', + 'unzip.c', + 'unzip.h', + 'zip.c', + 'zip.h', +]: + r = requests.get('%s/%s' % (URL, f)) + r.raise_for_status() + with open(os.path.join(TARGET, f), 'wb') as f: + f.write(r.content)
--- a/OrthancFramework/Resources/ThirdParty/minizip/crypt.h Fri Feb 20 15:41:05 2026 +0100 +++ b/OrthancFramework/Resources/ThirdParty/minizip/crypt.h Fri Feb 20 16:03:16 2026 +0100 @@ -1,9 +1,6 @@ /* crypt.h -- base code for crypt/uncrypt ZIPfile - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant + Copyright (C) 1998-2026 Gilles Vollant This code is a modified version of crypting code in Infozip distribution @@ -23,7 +20,7 @@ This code support the "Traditional PKWARE Encryption". The new AES encryption added on Zip format by Winzip (see the page - http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + https://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong Encryption is not supported. */ @@ -50,7 +47,7 @@ (*(pkeys+1)) += (*(pkeys+0)) & 0xff; (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; { - register int keyshift = (int)((*(pkeys+1)) >> 24); + int keyshift = (int)((*(pkeys+1)) >> 24); (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); } return c; @@ -106,7 +103,7 @@ */ if (++calls == 1) { - srand((unsigned)(time(NULL) ^ ZCR_SEED2)); + srand((unsigned)time(NULL) ^ ZCR_SEED2); } init_keys(passwd, pkeys, pcrc_32_tab); for (n = 0; n < RAND_HEAD_LEN-2; n++)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancFramework/Resources/ThirdParty/minizip/ints.h Fri Feb 20 16:03:16 2026 +0100 @@ -0,0 +1,57 @@ +/* ints.h -- create integer types for 8, 16, 32, and 64 bits + * Copyright (C) 2024 Mark Adler + * For conditions of distribution and use, see the copyright notice in zlib.h + * + * There exist compilers with limits.h, but not stdint.h or inttypes.h. + */ + +#ifndef INTS_H +#define INTS_H +#include <limits.h> +#if defined(UCHAR_MAX) && UCHAR_MAX == 0xff + typedef signed char i8_t; + typedef unsigned char ui8_t; +#else +# error "no 8-bit integer" +#endif +#if defined(USHRT_MAX) && USHRT_MAX == 0xffff + typedef short i16_t; + typedef unsigned short ui16_t; +#elif defined(UINT_MAX) && UINT_MAX == 0xffff + typedef int i16_t; + typedef unsigned ui16_t; +#else +# error "no 16-bit integer" +#endif +#if defined(UINT_MAX) && UINT_MAX == 0xffffffff + typedef int i32_t; + typedef unsigned ui32_t; +# define PI32 "d" +# define PUI32 "u" +#elif defined(ULONG_MAX) && ULONG_MAX == 0xffffffff + typedef long i32_t; + typedef unsigned long ui32_t; +# define PI32 "ld" +# define PUI32 "lu" +#else +# error "no 32-bit integer" +#endif +#if defined(ULONG_MAX) && ULONG_MAX == 0xffffffffffffffff + typedef long i64_t; + typedef unsigned long ui64_t; +# define PI64 "ld" +# define PUI64 "lu" +#elif defined(ULLONG_MAX) && ULLONG_MAX == 0xffffffffffffffff + typedef long long i64_t; + typedef unsigned long long ui64_t; +# define PI64 "lld" +# define PUI64 "llu" +#elif defined(ULONG_LONG_MAX) && ULONG_LONG_MAX == 0xffffffffffffffff + typedef long long i64_t; + typedef unsigned long long ui64_t; +# define PI64 "lld" +# define PUI64 "llu" +#else +# error "no 64-bit integer" +#endif +#endif
--- a/OrthancFramework/Resources/ThirdParty/minizip/ioapi.c Fri Feb 20 15:41:05 2026 +0100 +++ b/OrthancFramework/Resources/ThirdParty/minizip/ioapi.c Fri Feb 20 16:03:16 2026 +0100 @@ -1,10 +1,10 @@ /* ioapi.h -- IO base function header for compress/uncompress .zip - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + part of the MiniZip project - ( https://www.winimage.com/zLibDll/minizip.html ) - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + Copyright (C) 1998-2026 Gilles Vollant (minizip) ( https://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + Copyright (C) 2009-2010 Mathias Svensson ( https://result42.com ) For more info read MiniZip_info.txt @@ -14,8 +14,8 @@ #define _CRT_SECURE_NO_WARNINGS #endif -#if defined(__APPLE__) || defined(IOAPI_NO_64) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64) -// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#if defined(__APPLE__) || defined(IOAPI_NO_64) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64) || (defined(__ANDROID_API__) && __ANDROID_API__ < 24) +/* In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions */ #define FOPEN_FUNC(filename, mode) fopen(filename, mode) #define FTELLO_FUNC(stream) ftello(stream) #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
--- a/OrthancFramework/Resources/ThirdParty/minizip/ioapi.h Fri Feb 20 15:41:05 2026 +0100 +++ b/OrthancFramework/Resources/ThirdParty/minizip/ioapi.h Fri Feb 20 16:03:16 2026 +0100 @@ -1,10 +1,10 @@ /* ioapi.h -- IO base function header for compress/uncompress .zip - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + part of the MiniZip project - ( https://www.winimage.com/zLibDll/minizip.html ) - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + Copyright (C) 1998-2026 Gilles Vollant (minizip) ( https://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + Copyright (C) 2009-2010 Mathias Svensson ( https://result42.com ) For more info read MiniZip_info.txt @@ -18,13 +18,13 @@ */ -#ifndef _ZLIBIOAPI64_H -#define _ZLIBIOAPI64_H +#ifndef ZLIBIOAPI64_H +#define ZLIBIOAPI64_H -#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) && (!(defined(__ANDROID_API__) || __ANDROID_API__ >= 24)) - // Linux needs this to support file operation on files larger then 4+GB - // But might need better if/def to select just the platforms that needs them. + /* Linux needs this to support file operation on files larger then 4+GB */ + /* But might need better if/def to select just the platforms that needs them.*/ #ifndef __USE_FILE_OFFSET64 #define __USE_FILE_OFFSET64 @@ -67,39 +67,12 @@ #endif #endif -/* -#ifndef ZPOS64_T - #ifdef _WIN32 - #define ZPOS64_T fpos_t - #else - #include <stdint.h> - #define ZPOS64_T uint64_t - #endif -#endif -*/ - #ifdef HAVE_MINIZIP64_CONF_H #include "mz64conf.h" #endif -/* a type chosen by DEFINE */ -#ifdef HAVE_64BIT_INT_CUSTOM -typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; -#else -#ifdef HAS_STDINT_H -#include "stdint.h" -typedef uint64_t ZPOS64_T; -#else - - - -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef unsigned __int64 ZPOS64_T; -#else -typedef unsigned long long int ZPOS64_T; -#endif -#endif -#endif +#include "ints.h" +typedef ui64_t ZPOS64_T; /* Maximum unsigned 32-bit value used as placeholder for zip64 */ #ifndef MAXU32 @@ -188,8 +161,8 @@ #define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) #define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) -//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) -//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) +/*#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) */ +/*#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) */ #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancFramework/Resources/ThirdParty/minizip/skipset.h Fri Feb 20 16:03:16 2026 +0100 @@ -0,0 +1,366 @@ +/* skipset.h -- set operations using a skiplist +// Copyright (C) 2024-2026 Mark Adler +// See MiniZip_info.txt for the license. + +// This implements a skiplist set, i.e. just keys, no data, with ~O(log n) time +// insert and search operations. The application defines the type of a key, and +// provides a function to compare two keys. + +// This header is not definitions of functions found in another source file -- +// it creates the set functions, with the application's key type, right where +// the #include is. Before this header is #included, these must be defined: +// +// 1. A macro or typedef for set_key_t, the type of a key. +// 2. A macro or function set_cmp(a, b) to compare two keys. The return values +// are < 0 for a < b, 0 for a == b, and > 0 for a > b. +// 3. A macro or function set_drop(s, k) to release the key k's resources, if +// any, when doing a set_end() or set_clear(). s is a pointer to the set +// that key is in, for use with set_free() if desired. +// +// Example usage: +// +// typedef int set_key_t; +// #define set_cmp(a, b) ((a) < (b) ? -1 : (a) == (b) ? 0 : 1) +// #define set_drop(s, k) +// #include "skipset.h" +// +// int test(void) { // return 0: good, 1: bad, -1: out of memory +// set_t set; +// if (setjmp(set.env)) +// return -1; +// set_start(&set); +// set_insert(&set, 2); +// set_insert(&set, 1); +// set_insert(&set, 7); +// int bad = !set_found(&set, 2); +// bad = bad || set_found(&set, 5); +// set_end(&set); +// return bad; +// } +// +// Interface summary (see more details below): +// - set_t is the type of the set being operated on (a set_t pointer is passed) +// - set_start() initializes a new, empty set (initialize set.env first) +// - set_insert() inserts a new key into the set, or not if it's already there +// - set_found() determines whether or not a key is in the set +// - set_end() ends the use of the set, freeing all memory +// - set_clear() empties the set, equivalent to set_end() and then set_start() +// - set_ok() checks if set appears to be usable, i.e. started and not ended +// +// Auxiliary functions available to the application: +// - set_alloc() allocates memory with optional tracking (#define SET_TRACK) +// - set_free() deallocates memory allocated by set_alloc() +// - set_rand() returns 32 random bits (seeded by set_start()) */ + +#ifndef SKIPSET_H +#define SKIPSET_H + +#include <stdlib.h> /* realloc(), free(), NULL, size_t */ +#include <stddef.h> /* ptrdiff_t */ +#include <setjmp.h> /* jmp_buf, longjmp() */ +#include <errno.h> /* ENOMEM */ +#include <time.h> /* time(), clock() */ +#include <assert.h> /* assert.h */ +#include "ints.h" /* i16_t, ui32_t, ui64_t */ + +/* Structures and functions below noted as "--private--" should not be used by +// the application. set_t is partially private and partially public -- see the +// comments there. + +// There is no POSIX random() in MSVC, and rand() is awful. For portability, we +// cannot rely on a library function for random numbers. Instead we use the +// fast and effective algorithm below, invented by Melissa O'Neill. + +// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / www.pcg-random.org +// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website) +// --private-- Random number generator state. */ +typedef struct { + ui64_t state; /* 64-bit generator state */ + ui64_t inc; /* 63-bit sequence id */ +} set_rand_t; +/* --private-- Initialize the state *gen using seed and seq. seed seeds the +// advancing 64-bit state. seq is a sequence selection constant. */ +void set_seed(set_rand_t *gen, ui64_t seed, ui64_t seq) { + gen->inc = (seq << 1) | 1; + gen->state = (seed + gen->inc) * 6364136223846793005ULL + gen->inc; +} +/* Start a unique random number sequence using bits from noise sources. */ +void set_uniq(set_rand_t *gen, const void *ptr) { + set_seed(gen, ((ui64_t)(ptrdiff_t)ptr << 32) ^ + ((ui64_t)time(NULL) << 12) ^ clock(), 0); +} +/* Return 32 random bits, advancing the state *gen. */ +ui32_t set_rand(set_rand_t *gen) { + ui64_t state = gen->state; + gen->state = state * 6364136223846793005ULL + gen->inc; + ui32_t mix = (ui32_t)(((state >> 18) ^ state) >> 27); + int rot = state >> 59; + return (mix >> rot) | (mix << ((-rot) & 31)); +} +/* End of PCG32 code. */ + +/* --private-- Linked-list node. */ +typedef struct set_node_s set_node_t; +struct set_node_s { + set_key_t key; /* the key (not used for head or path) */ + i16_t size; /* number of allocated pointers in right[] */ + i16_t fill; /* number of pointers in right[] filled in */ + set_node_t **right; /* pointer for each level, each to the right */ +}; + +/* A set. The application sets env, may use gen with set_rand(), and may read +// allocs and memory. The remaining variables are --private-- . */ +typedef struct set_s { + set_node_t *head; /* skiplist head -- no key, just links */ + set_node_t *path; /* right[] is path to key from set_found() */ + set_node_t *node; /* node under construction, in case of longjmp() */ + i16_t depth; /* maximum depth of the skiplist */ + ui64_t ran; /* a precious trove of random bits */ + set_rand_t gen; /* random number generator state */ + jmp_buf env; /* setjmp() environment for allocation errors */ +#ifdef SET_TRACK + size_t allocs; /* number of allocations */ + size_t memory; /* total amount of allocated memory (>= requests) */ +#endif +} set_t; + +/* Memory allocation and deallocation. set_alloc(set, ptr, size) returns a +// pointer to an allocation of size bytes if ptr is NULL, or the previous +// allocation ptr resized to size bytes. set_alloc() will never return NULL. +// set_free(set, ptr) frees an allocation created by set_alloc(). These may be +// used by the application. e.g. if allocation tracking is desired. */ +#ifdef SET_TRACK +/* Track the number of allocations and the total backing memory size. */ +# if defined(_WIN32) +# include <malloc.h> +# define SET_ALLOC_SIZE(ptr) _msize(ptr) +# elif defined(__MACH__) +# include <malloc/malloc.h> +# define SET_ALLOC_SIZE(ptr) malloc_size(ptr) +# elif defined(__linux__) +# include <malloc.h> +# define SET_ALLOC_SIZE(ptr) malloc_usable_size(ptr) +# elif defined(__FreeBSD__) +# include <malloc_np.h> +# define SET_ALLOC_SIZE(ptr) malloc_usable_size(ptr) +# elif defined(__NetBSD__) +# include <jemalloc/jemalloc.h> +# define SET_ALLOC_SIZE(ptr) malloc_usable_size(ptr) +# else // e.g. OpenBSD +# define SET_ALLOC_SIZE(ptr) 0 +# endif +// With tracking. +void *set_alloc(set_t *set, void *ptr, size_t size) { + size_t had = ptr == NULL ? 0 : SET_ALLOC_SIZE(ptr); + void *mem = realloc(ptr, size); + if (mem == NULL) + longjmp(set->env, ENOMEM); + set->allocs += ptr == NULL; + set->memory += SET_ALLOC_SIZE(mem) - had; + return mem; +} +void set_free(set_t *set, void *ptr) { + if (ptr != NULL) { + set->allocs--; + set->memory -= SET_ALLOC_SIZE(ptr); + free(ptr); + } +} +#else +/* Without tracking. */ +void *set_alloc(set_t *set, void *ptr, size_t size) { + void *mem = realloc(ptr, size); + if (mem == NULL) + longjmp(set->env, ENOMEM); + return mem; +} +void set_free(set_t *set, void *ptr) { + (void)set; + free(ptr); +} +#endif + +/* --private-- Grow node's array right[] as needed to be able to hold at least +// want links. If fill is true, assure that the first want links are filled in, +// setting them to set->head if not previously filled in. Otherwise it is +// assumed that the first want links are about to be filled in. */ +void set_grow(set_t *set, set_node_t *node, int want, int fill) { + if (node->size < want) { + int more = node->size ? node->size : 1; + while (more < want) + more <<= 1; + node->right = set_alloc(set, node->right, + (size_t)more * sizeof(set_node_t *)); + node->size = (i16_t)more; + } + int i; + if (fill) + for (i = node->fill; i < want; i++) + node->right[i] = set->head; + node->fill = (i16_t)want; +} + +/* --private-- Return a new node. key is left uninitialized. */ +set_node_t *set_node(set_t *set) { + set_node_t *node = set_alloc(set, NULL, sizeof(set_node_t)); + node->size = 0; + node->fill = 0; + node->right = NULL; + return node; +} + +/* --private-- Free the list linked from head, along with the keys. */ +void set_sweep(set_t *set) { + set_node_t *step = set->head->right[0]; + while (step != set->head) { + set_node_t *next = step->right[0]; /* save link to next node */ + set_drop(set, step->key); + set_free(set, step->right); + set_free(set, step); + step = next; + } +} + +/* Initialize a new set. set->env must be initialized using setjmp() before +// set_start() is called. A longjmp(set->env, ENOMEM) will be used to handle a +// memory allocation failure during any of the operations. (See setjmp.h and +// errno.h.) The set can still be used if this happens, assuming that it didn't +// happen during set_start(). Whether set_start() completed or not, set_end() +// can be used to free the set's memory after a longjmp(). */ +void set_start(set_t *set) { +#ifdef SET_TRACK + set->allocs = 0; + set->memory = 0; +#endif + set->head = set->path = set->node = NULL; /* in case set_node() fails */ + set->path = set_node(set); + set->head = set_node(set); + set_grow(set, set->head, 1, 1); /* one link back to head for an empty set */ + *(unsigned char *)&set->head->key = 137; /* set id */ + set->depth = 0; + set_uniq(&set->gen, set); + set->ran = 1; +} + +/* Return true if *set appears to be in a usable state. If *set has been zeroed +// out, then set_ok(set) will be false and set_end(set) will be safe. */ +int set_ok(set_t *set) { + return set->head != NULL && + set->head->right != NULL && + *(unsigned char *)&set->head->key == 137; +} + +/* Empty the set. This frees the memory used for the previous set contents. +// After set_clear(), *set is ready for use, as if after a set_start(). */ +void set_clear(set_t *set) { + assert(set_ok(set) && "improper use"); + + /* Free all the keys and their nodes. */ + set_sweep(set); + + /* Leave the head and path allocations as is. Clear their contents, with + // head pointing to itself and setting depth to zero, for an empty set. */ + set->head->right[0] = set->head; + set->head->fill = 1; + set->path->fill = 0; + set->depth = 0; +} + +/* Done using the set -- free all allocations. The only operation on *set +// permitted after this is set_start(). Though another set_end() would do no +// harm. This can be done at any time after a set_start(), or after a longjmp() +// on any allocation failure, including during a set_start(). */ +void set_end(set_t *set) { + if (set->head != NULL) { + /* Empty the set and free the head node. */ + if (set->head->right != NULL) { + set_sweep(set); + set_free(set, set->head->right); + } + set_free(set, set->head); + set->head = NULL; + } + if (set->path != NULL) { + /* Free the path work area. */ + set_free(set, set->path->right); + set_free(set, set->path); + set->path = NULL; + } + if (set->node != NULL) { + /* Free the node that was under construction when longjmp() hit. */ + set_drop(set, set->node->key); + set_free(set, set->node->right); + set_free(set, set->node); + set->node = NULL; + } +} + +/* Look for key. Return 1 if found or 0 if not. This also puts the path to get +// there in set->path, for use by set_insert(). */ +int set_found(set_t *set, set_key_t key) { + assert(set_ok(set) && "improper use"); + + /* Start at depth and work down and right as determined by key comparisons. */ + set_node_t *head = set->head, *here = head; + int i = set->depth; + set_grow(set, set->path, i + 1, 0); + do { + while (here->right[i] != head && + set_cmp(here->right[i]->key, key) < 0) + here = here->right[i]; + set->path->right[i] = here; + } while (i--); + + /* See if the key matches. */ + here = here->right[0]; + return here != head && set_cmp(here->key, key) == 0; +} + +/* Insert the key key. Return 0 on success, or 1 if key is already in the set. */ +int set_insert(set_t *set, set_key_t key) { + assert(set_ok(set) && "improper use"); + + if (set_found(set, key)) + /* That key is already in the set. */ + return 1; + + /* Randomly generate a new level-- level 0 with probability 1/2, 1 with + // probability 1/4, 2 with probability 1/8, etc. */ + int level = 0; + for (;;) { + if (set->ran == 1) + /* Ran out. Get another 32 random bits. */ + set->ran = set_rand(&set->gen) | (1ULL << 32); + int bit = set->ran & 1; + set->ran >>= 1; + if (bit) + break; + assert(level < 32767 && + "Overhead, without any fuss, the stars were going out."); + level++; + } + if (level > set->depth) { + /* The maximum depth is now deeper. Update the structures. */ + set_grow(set, set->path, level + 1, 1); + set_grow(set, set->head, level + 1, 1); + set->depth = (i16_t)level; + } + + /* Make a new node for the provided key, and insert it in the lists up to + // and including level. */ + set->node = set_node(set); + set->node->key = key; + set_grow(set, set->node, level + 1, 0); + int i; + for (i = 0; i <= level; i++) { + set->node->right[i] = set->path->right[i]->right[i]; + set->path->right[i]->right[i] = set->node; + } + set->node = NULL; + return 0; +} + +#else +#error ** another skiplist set already created here +/* Would need to implement a prefix in order to support multiple sets. */ +#endif
--- a/OrthancFramework/Resources/ThirdParty/minizip/unzip.c Fri Feb 20 15:41:05 2026 +0100 +++ b/OrthancFramework/Resources/ThirdParty/minizip/unzip.c Fri Feb 20 16:03:16 2026 +0100 @@ -1,14 +1,13 @@ /* unzip.c -- IO for uncompress .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + part of the MiniZip project - ( https://www.winimage.com/zLibDll/minizip.html ) - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + Copyright (C) 1998-2026 Gilles Vollant (minizip) ( https://www.winimage.com/zLibDll/minizip.html ) Modifications of Unzip for Zip64 Copyright (C) 2007-2008 Even Rouault Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + Copyright (C) 2009-2010 Mathias Svensson ( https://result42.com ) For more info read MiniZip_info.txt @@ -68,10 +67,9 @@ #include <stdlib.h> #include <string.h> -#ifndef NOUNCRYPT - #define NOUNCRYPT +#ifdef ZLIB_DLL +# undef ZLIB_DLL #endif - #include "zlib.h" #include "unzip.h" @@ -92,7 +90,7 @@ #ifndef CASESENSITIVITYDEFAULT_NO -# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# if (!defined(__unix__) && !defined(__unix) || defined(__CYGWIN__)) && !defined(CASESENSITIVITYDEFAULT_YES) # define CASESENSITIVITYDEFAULT_NO # endif #endif @@ -115,9 +113,9 @@ const char unz_copyright[] = - " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - https://www.winimage.com/zLibDll/minizip.html"; -/* unz_file_info_interntal contain internal info about a file in zipfile*/ +/* unz_file_info64_internal contain internal info about a file in zipfile*/ typedef struct unz_file_info64_internal_s { ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ @@ -450,7 +448,7 @@ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return CENTRALDIRINVALID; - /* number of the disk with the start of the zip64 end of central directory */ + /* number of the disk with the start of the zip64 end of central directory */ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) return CENTRALDIRINVALID; if (uL != 0) @@ -497,9 +495,9 @@ ZPOS64_T central_pos; uLong uL; - uLong number_disk; /* number of the current dist, used for + uLong number_disk; /* number of the current disk, used for spanning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used + uLong number_disk_with_CD; /* number the disk with central dir, used for spanning ZIP, unsupported, always 0*/ ZPOS64_T number_entry_CD; /* total number of entries in the central dir @@ -687,6 +685,7 @@ { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.zopen32_file = NULL; zlib_filefunc64_32_def_fill.ztell32_file = NULL; zlib_filefunc64_32_def_fill.zseek32_file = NULL; return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1); @@ -846,7 +845,7 @@ if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) err=UNZ_ERRNO; - // relative offset of local header + /* relative offset of local header */ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) err=UNZ_ERRNO; file_info_internal.offset_curfile = uL; @@ -869,7 +868,7 @@ lSeek -= uSizeRead; } - // Read extrafield + /* Read extrafield */ if ((err==UNZ_OK) && (extraField!=NULL)) { ZPOS64_T uSizeRead ; @@ -900,7 +899,7 @@ { uLong acc = 0; - // since lSeek now points to after the extra field we need to move back + /* since lSeek now points to after the extra field we need to move back */ lSeek -= file_info.size_file_extra; if (lSeek!=0) @@ -1529,10 +1528,10 @@ file_in_zip64_read_info_s* pfile_in_zip_read_info; s=(unz64_s*)file; if (file==NULL) - return 0; //UNZ_PARAMERROR; + return 0; /* UNZ_PARAMERROR; */ pfile_in_zip_read_info=s->pfile_in_zip_read; if (pfile_in_zip_read_info==NULL) - return 0; //UNZ_PARAMERROR; + return 0; /* UNZ_PARAMERROR; */ return pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile; } @@ -1613,7 +1612,7 @@ uInt i; for(i=0;i<uReadThis;i++) pfile_in_zip_read_info->read_buffer[i] = - zdecode(s->keys,s->pcrc_32_tab, + (char)zdecode(s->keys,s->pcrc_32_tab, pfile_in_zip_read_info->read_buffer[i]); } # endif @@ -1701,7 +1700,7 @@ if (err!=BZ_OK) break; #endif - } // end Z_BZIP2ED + } /* end Z_BZIP2ED */ else { ZPOS64_T uTotalOutBefore,uTotalOutAfter; @@ -1944,7 +1943,7 @@ unz64_s* s; if (file==NULL) - return 0; //UNZ_PARAMERROR; + return 0; /* UNZ_PARAMERROR; */ s=(unz64_s*)file; if (!s->current_file_ok) return 0; @@ -1958,7 +1957,7 @@ ZPOS64_T offset64; if (file==NULL) - return 0; //UNZ_PARAMERROR; + return 0; /* UNZ_PARAMERROR; */ offset64 = unzGetOffset64(file); return (uLong)offset64; }
--- a/OrthancFramework/Resources/ThirdParty/minizip/unzip.h Fri Feb 20 15:41:05 2026 +0100 +++ b/OrthancFramework/Resources/ThirdParty/minizip/unzip.h Fri Feb 20 16:03:16 2026 +0100 @@ -1,14 +1,13 @@ /* unzip.h -- IO for uncompress .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + part of the MiniZip project - ( https://www.winimage.com/zLibDll/minizip.html ) - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + Copyright (C) 1998-2026 Gilles Vollant (minizip) ( https://www.winimage.com/zLibDll/minizip.html ) Modifications of Unzip for Zip64 Copyright (C) 2007-2008 Even Rouault Modifications for Zip64 support on both zip and unzip - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + Copyright (C) 2009-2010 Mathias Svensson ( https://result42.com ) For more info read MiniZip_info.txt @@ -70,6 +69,8 @@ typedef voidp unzFile; #endif +extern const char unz_copyright[]; + #define UNZ_OK (0) #define UNZ_END_OF_LIST_OF_FILE (-100) @@ -306,13 +307,17 @@ Get Info about the current file if pfile_info!=NULL, the *pfile_info structure will contain some info about the current file - if szFileName!=NULL, the filemane string will be copied in szFileName + if szFileName!=NULL, the filename string will be copied in szFileName (fileNameBufferSize is the size of the buffer) if extraField!=NULL, the extra field information will be copied in extraField (extraFieldBufferSize is the size of the buffer). This is the Central-header version of the extra field if szComment!=NULL, the comment string of the file will be copied in szComment (commentBufferSize is the size of the buffer) + The file name and comment will be zero-terminated if there is room in the + provided buffer. Otherwise the buffer will contain as much as will fit. If at + least 65537 bytes of room is provided, then the result will always be + complete and zero-terminated. */
--- a/OrthancFramework/Resources/ThirdParty/minizip/zip.c Fri Feb 20 15:41:05 2026 +0100 +++ b/OrthancFramework/Resources/ThirdParty/minizip/zip.c Fri Feb 20 16:03:16 2026 +0100 @@ -1,11 +1,10 @@ /* zip.c -- IO on .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + part of the MiniZip project - ( https://www.winimage.com/zLibDll/minizip.html ) - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + Copyright (C) 1998-2026 Gilles Vollant (minizip) ( https://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + Copyright (C) 2009-2010 Mathias Svensson ( https://result42.com ) For more info read MiniZip_info.txt @@ -25,8 +24,13 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <stdint.h> #include <time.h> +#ifndef ZLIB_CONST +# define ZLIB_CONST +#endif +#ifdef ZLIB_DLL +# undef ZLIB_DLL +#endif #include "zlib.h" #include "zip.h" @@ -50,7 +54,7 @@ #endif #ifndef Z_BUFSIZE -#define Z_BUFSIZE (64*1024) //(16384) +#define Z_BUFSIZE (64*1024) /* (16384) */ #endif #ifndef Z_MAXFILENAMEINZIP @@ -69,7 +73,7 @@ /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ -// NOT sure that this work on ALL platform +/* NOT sure that this work on ALL platform */ #define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) #ifndef SEEK_CUR @@ -91,7 +95,7 @@ # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif #endif -const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; +const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - https://www.winimage.com/zLibDll/minizip.html"; #define SIZEDATA_INDATABLOCK (4096-(4*4)) @@ -123,6 +127,19 @@ } linkedlist_data; +/* zipAlreadyThere() set functions for a set of zero-terminated strings, and +// a block_t type for reading the central directory datablocks. */ +typedef char *set_key_t; +#define set_cmp(a, b) strcmp(a, b) +#define set_drop(s, k) set_free(s, k) +#include "skipset.h" +typedef struct { + unsigned char *next; /* next byte in datablock data */ + size_t left; /* number of bytes left in data (at least) */ + linkedlist_datablock_internal *node; /* current datablock */ +} block_t; + + typedef struct { z_stream stream; /* zLib stream structure for inflate */ @@ -174,6 +191,10 @@ char *globalcomment; #endif + /* Support for zipAlreadyThere(). */ + set_t set; /* set for detecting name collisions */ + block_t block; /* block for reading the central directory */ + } zip64_internal; @@ -264,6 +285,229 @@ return ZIP_OK; } +/* zipAlreadyThere() operations. "set" in the zip internal structure keeps the +// set of names that are in the under-construction central directory so far. A +// skipset provides ~O(log n) time insertion and searching. Central directory +// records, stored in a linked list of allocated memory datablocks, is read +// through "block" in the zip internal structure. + +// The block_*() functions support extracting the central directory file names +// from the datablocks. They are designed to support a growing directory by +// automatically continuing once more data has been appended to the linked +// datablocks. + +// Initialize *block to the head of list. This should only be called once the +// list has at least some data in it, i.e. list->first_block is not NULL. */ +local void block_init(block_t *block, linkedlist_data *list) { + block->node = list->first_block; + block->next = block->node->data; + block->left = block->node->filled_in_this_block; +} + +/* Mark *block as bad, with all subsequent reads returning end, even if more +// data is added to the datablocks. This is invoked if the central directory is +// invalid, so there is no longer any point in attempting to interpret it. */ +local void block_stop(block_t *block) { + block->left = 0; + block->next = NULL; +} + +/* Return true if *block has reached the end of the data in the datablocks. */ +local int block_end(block_t *block) { + linkedlist_datablock_internal *node = block->node; + if (node == NULL) + /* This block was previously terminated with extreme prejudice. */ + return 1; + if (block->next < node->data + node->filled_in_this_block) + /* There are more bytes to read in the current datablock. */ + return 0; + while (node->next_datablock != NULL) { + if (node->filled_in_this_block != 0) + /* There are some bytes in a later datablock. */ + return 0; + node = node->next_datablock; + } + /* Reached the end of the list of datablocks. There's nothing. */ + return 1; +} + +/* Return one byte from *block, or -1 if the end is reached. */ +local int block_get(block_t *block) { + while (block->left == 0) { + if (block->node == NULL) + /* We've been marked bad. Return end. */ + return -1; + /* Update left in case more was filled in since we were last here. */ + block->left = block->node->filled_in_this_block - + (size_t)(block->next - block->node->data); + if (block->left != 0) + /* There was indeed more data appended in the current datablock. */ + break; + if (block->node->next_datablock == NULL) + /* No more data here, and there is no next datablock. At the end. */ + return -1; + /* Try the next datablock for more data. */ + block->node = block->node->next_datablock; + block->next = block->node->data; + block->left = block->node->filled_in_this_block; + } + /* We have a byte to return. */ + block->left--; + return *block->next++; +} + +/* Return a 16-bit unsigned little-endian value from block, or a negative value +// if the end is reached. */ +local long block_get2(block_t *block) { + int low = block_get(block); + int high = block_get(block); + return low < 0 || high < 0 ? -1 : low | ((long)high << 8); +} + +/* Read up to len bytes from block into buf. Return the number of bytes read. */ +local size_t block_read(block_t *block, unsigned char *buf, size_t len) { + size_t need = len; + while (need) { + if (block->left == 0) { + /* Get a byte to update and step through the linked list as needed. */ + int got = block_get(block); + if (got == -1) + /* Reached the end. */ + break; + *buf++ = (unsigned char)got; + need--; + continue; + } + size_t take = need > block->left ? block->left : need; + memcpy(buf, block->next, take); + block->next += take; + block->left -= take; + buf += take; + need -= take; + } + return len - need; /* return the number of bytes copied */ +} + +/* Skip n bytes in block. Return 0 on success or -1 if there are less than n +// bytes to the end. */ +local int block_skip(block_t *block, size_t n) { + while (n > block->left) { + n -= block->left; + block->next += block->left; + block->left = 0; + if (block_get(block) == -1) + return -1; + n--; + } + block->next += n; + block->left -= n; + return 0; +} + +/* Process the next central directory record at *block. Return the allocated, +// zero-terminated file name, or NULL for end of input or invalid data. If +// invalid, *block is marked bad. This uses *set for the allocation of memory. */ +local char *block_central_name(block_t *block, set_t *set) { + char *name = NULL; + for (;;) { + if (block_end(block)) + /* At the end of the central directory (so far). */ + return NULL; + + /* Check for a central directory record signature. */ + if (block_get2(block) != (CENTRALHEADERMAGIC & 0xffff) || + block_get2(block) != (CENTRALHEADERMAGIC >> 16)) + /* Incorrect signature. */ + break; + + /* Go through the remaining fixed-length portion of the record, + // extracting the lengths of the three variable-length fields. */ + block_skip(block, 24); + unsigned flen = (unsigned)block_get2(block); /* file name length */ + unsigned xlen = (unsigned)block_get2(block); /* extra length */ + unsigned clen = (unsigned)block_get2(block); /* comment length */ + if (block_skip(block, 12) == -1) + /* Premature end of the record. */ + break; + + /* Extract the name and skip over the extra and comment fields. */ + name = set_alloc(set, NULL, flen + 1); + if (block_read(block, (unsigned char *)name, flen) < flen || + block_skip(block, xlen + clen) == -1) + /* Premature end of the record. */ + break; + + /* Check for embedded nuls in the name. */ + if (memchr(name, 0, flen) != NULL) { + /* This name can never match the zero-terminated name provided to + // zipAlreadyThere(), so we discard it and go back to get another + // name. (Who the heck is putting nuls inside their zip file entry + // names anyway?) */ + set_free(set, name); + continue; + } + + /* All good. Return the zero-terminated file name. */ + name[flen] = 0; + return name; + } + + /* Invalid signature or premature end of the central directory record. + // Abandon trying to process the central directory. */ + set_free(set, name); + block_stop(block); + return NULL; +} + +/* Return 0 if name is not in the central directory so far, 1 if it is, -1 if +// the central directory is invalid, -2 if out of memory, or ZIP_PARAMERROR if +// file is NULL. */ +extern int ZEXPORT zipAlreadyThere(zipFile file, char const *name) { + zip64_internal *zip = file; + if (zip == NULL) + return ZIP_PARAMERROR; + if (zip->central_dir.first_block == NULL) + /* No central directory yet, so no, name isn't there. */ + return 0; + if (setjmp(zip->set.env)) { + /* Memory allocation failure. */ + set_end(&zip->set); + return -2; + } + if (!set_ok(&zip->set)) { + /* This is the first time here with some central directory content. We + // construct this set of names only on demand. Prepare set and block. */ + set_start(&zip->set); + block_init(&zip->block, &zip->central_dir); + } + + /* Update the set of names from the current central directory contents. + // This reads any new central directory records since the last time we were + // here. */ + for (;;) { + char *there = block_central_name(&zip->block, &zip->set); + if (there == NULL) { + if (zip->block.next == NULL) + /* The central directory is invalid. */ + return -1; + break; + } + + /* Add there to the set. */ + if (set_insert(&zip->set, there)) + /* There's already a duplicate in the central directory! We'll just + // let this be and carry on. */ + set_free(&zip->set, there); + } + + /* Return true if name is in the central directory. */ + size_t len = strlen(name); + char *copy = set_alloc(&zip->set, NULL, len + 1); + memcpy(copy, name, len + 1); + int found = set_found(&zip->set, copy); + set_free(&zip->set, copy); + return found; +} /****************************************************************************/ @@ -551,7 +795,7 @@ for (i=(int)uReadSize-3; (i--)>0;) { - // Signature "0x07064b50" Zip64 end of central directory locater + /* Signature "0x07064b50" Zip64 end of central directory locator */ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) { uPosFound = uReadPos+(unsigned)i; @@ -575,7 +819,7 @@ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return 0; - /* number of the disk with the start of the zip64 end of central directory */ + /* number of the disk with the start of the zip64 end of central directory */ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return 0; if (uL != 0) @@ -599,7 +843,7 @@ if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) return 0; - if (uL != 0x06064b50) // signature of 'Zip64 end of central directory' + if (uL != 0x06064b50) /* signature of 'Zip64 end of central directory' */ return 0; return relativeOffset; @@ -628,7 +872,7 @@ int hasZIP64Record = 0; - // check first if we find a ZIP64 record + /* check first if we find a ZIP64 record */ central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); if(central_pos > 0) { @@ -694,13 +938,13 @@ if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) err=ZIP_ERRNO; - // TODO.. - // read the comment from the standard central header. + /* TODO.. + // read the comment from the standard central header. */ size_comment = 0; } else { - // Read End of central Directory info + /* Read End of central Directory info */ if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) err=ZIP_ERRNO; @@ -843,6 +1087,7 @@ ziinit.number_entry = 0; ziinit.add_position_when_writing_offset = 0; init_linkedlist(&(ziinit.central_dir)); + memset(&ziinit.set, 0, sizeof(set_t)); /* make sure set appears dormant */ @@ -858,7 +1103,7 @@ ziinit.globalcomment = NULL; if (append == APPEND_STATUS_ADDINZIP) { - // Read and Cache Central Directory Records + /* Read and Cache Central Directory Records */ err = LoadCentralDirectoryRecord(&ziinit); } @@ -899,6 +1144,7 @@ { zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.zopen32_file = NULL; zlib_filefunc64_32_def_fill.ztell32_file = NULL; zlib_filefunc64_32_def_fill.zseek32_file = NULL; return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); @@ -942,7 +1188,7 @@ if (err==ZIP_OK) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); - // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later + /* CRC / Compressed size / Uncompressed size will be filled in later and rewritten later */ if (err==ZIP_OK) err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ if (err==ZIP_OK) @@ -986,13 +1232,13 @@ if ((err==ZIP_OK) && (zi->ci.zip64)) { - // write the Zip64 extended info + /* write the Zip64 extended info */ short HeaderID = 1; short DataSize = 16; ZPOS64_T CompressedSize = 0; ZPOS64_T UncompressedSize = 0; - // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) + /* Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) */ zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID,2); @@ -1005,6 +1251,46 @@ return err; } +/* Return the length of the UTF-8 code at str[0..len-1] in [1..4], or negative + if there is no valid UTF-8 code there. If negative, it is minus the number + of bytes examined in order to determine it was bad. Or if minus the return + code is one less than len, then at least one more byte than provided would + be needed to complete the code. */ +local int utf8len(unsigned char const *str, size_t len) { + return + len == 0 ? -1 : /* empty input */ + str[0] < 0x80 ? 1 : /* good one-byte */ + str[0] < 0xc0 ? -1 : /* bad first byte */ + len < 2 || (str[1] >> 6) != 2 ? -2 : /* missing or bad 2nd byte */ + str[0] < 0xc2 ? -2 : /* overlong code */ + str[0] < 0xe0 ? 2 : /* good two-byte */ + len < 3 || (str[2] >> 6) != 2 ? -3 : /* missing or bad 3rd byte */ + str[0] == 0xe0 && str[1] < 0xa0 ? -3 : /* overlong code */ + str[0] < 0xf0 ? 3 : /* good three-byte */ + len < 4 || (str[3] >> 6) != 2 ? -4 : /* missing or bad 4th byte */ + str[0] == 0xf0 && str[1] < 0x90 ? -4 : /* overlong code */ + str[0] < 0xf4 || + (str[0] == 0xf4 && str[1] < 0x90) ? 4 : /* good four-byte */ + -4; /* code > 0x10ffff */ +} + +/* Return true if str[0..len-1] is valid UTF-8 *and* it contains at least one + code of two or more bytes. This is used to determine whether or not to set + bit 11 in the zip header flags. */ +local int isutf8(char const *str, size_t len) { + int utf8 = 0; + while (len) { + int code = utf8len((unsigned char const *)str, len); + if (code < 0) + return 0; + if (code > 1) + utf8 = 1; + str += code; + len -= (unsigned)code; + } + return utf8; +} + /* NOTE. When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped @@ -1027,7 +1313,6 @@ int err = ZIP_OK; # ifdef NOCRYPT - (crcForCrypting); if (password != NULL) return ZIP_PARAMERROR; # endif @@ -1043,14 +1328,14 @@ return ZIP_PARAMERROR; #endif - // The filename and comment length must fit in 16 bits. + /* The filename and comment length must fit in 16 bits. */ if ((filename!=NULL) && (strlen(filename)>0xffff)) return ZIP_PARAMERROR; if ((comment!=NULL) && (strlen(comment)>0xffff)) return ZIP_PARAMERROR; - // The extra field length must fit in 16 bits. If the member also requires + /* The extra field length must fit in 16 bits. If the member also requires // a Zip64 extra block, that will also need to fit within that 16-bit - // length, but that will be checked for later. + // length, but that will be checked for later. */ if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff)) return ZIP_PARAMERROR; @@ -1092,6 +1377,9 @@ zi->ci.flag |= 6; if (password != NULL) zi->ci.flag |= 1; + if (isutf8(filename, size_filename) && + (size_comment == 0 || isutf8(comment, size_comment))) + zi->ci.flag |= (1 << 11); zi->ci.crc32 = 0; zi->ci.method = method; @@ -1102,7 +1390,7 @@ zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; - zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data + zi->ci.size_centralExtraFree = 32; /* Extra space we have reserved in case we need to add ZIP64 extra info data */ zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); @@ -1197,7 +1485,7 @@ else if(zi->ci.method == Z_BZIP2ED) { #ifdef HAVE_BZIP2 - // Init BZip stuff here + /* Init BZip stuff here */ zi->ci.bstream.bzalloc = 0; zi->ci.bstream.bzfree = 0; zi->ci.bstream.opaque = (voidpf)0; @@ -1399,7 +1687,7 @@ if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) { uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; -// uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; +/* uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; */ err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN); zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ; @@ -1412,7 +1700,7 @@ else #endif { - zi->ci.stream.next_in = (Bytef*)(uintptr_t)buf; + zi->ci.stream.next_in = buf; zi->ci.stream.avail_in = len; while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) @@ -1457,7 +1745,7 @@ zi->ci.pos_in_buffered_data += copy_this; } } - }// while(...) + }/* while(...) */ } return err; @@ -1563,7 +1851,7 @@ compressed_size += zi->ci.crypt_header_size; # endif - // update Current Item crc and sizes, + /* update Current Item crc and sizes, */ if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) { /*version Made by*/ @@ -1581,7 +1869,7 @@ else zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ - /// set internal file attributes field + /* set internal file attributes field */ if (zi->ci.stream.data_type == Z_ASCII) zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); @@ -1590,15 +1878,15 @@ else zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ - // Add ZIP64 extra info field for uncompressed size + /* Add ZIP64 extra info field for uncompressed size */ if(uncompressed_size >= 0xffffffff) datasize += 8; - // Add ZIP64 extra info field for compressed size + /* Add ZIP64 extra info field for compressed size */ if(compressed_size >= 0xffffffff) datasize += 8; - // Add ZIP64 extra info field for relative offset to local file header of current file + /* Add ZIP64 extra info field for relative offset to local file header of current file */ if(zi->ci.pos_local_header >= 0xffffffff) datasize += 8; @@ -1608,16 +1896,16 @@ if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) { - // we can not write more data to the buffer that we have room for. + /* we cannot write more data to the buffer that we have room for. */ return ZIP_BADZIPFILE; } p = zi->ci.central_header + zi->ci.size_centralheader; - // Add Extra Information Header for 'ZIP64 information' - zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID + /* Add Extra Information Header for 'ZIP64 information' */ + zip64local_putValue_inmemory(p, 0x0001, 2); /* HeaderID */ p += 2; - zip64local_putValue_inmemory(p, datasize, 2); // DataSize + zip64local_putValue_inmemory(p, datasize, 2); /* DataSize */ p += 2; if(uncompressed_size >= 0xffffffff) @@ -1638,13 +1926,13 @@ p += 8; } - // Update how much extra free space we got in the memory buffer + /* Update how much extra free space we got in the memory buffer // and increase the centralheader size so the new ZIP64 fields are included - // ( 4 below is the size of HeaderID and DataSize field ) + // ( 4 below is the size of HeaderID and DataSize field ) */ zi->ci.size_centralExtraFree -= datasize + 4; zi->ci.size_centralheader += datasize + 4; - // Update the extra info size field + /* Update the extra info size field */ zi->ci.size_centralExtra += datasize + 4; zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2); } @@ -1656,7 +1944,7 @@ if (err==ZIP_OK) { - // Update the LocalFileHeader with the new values. + /* Update the LocalFileHeader with the new values. */ ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); @@ -1670,7 +1958,7 @@ { if(zi->ci.pos_zip64extrainfo > 0) { - // Update the size in the ZIP64 extended field. + /* Update the size in the ZIP64 extended field. */ if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0) err = ZIP_ERRNO; @@ -1681,7 +1969,7 @@ err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); } else - err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal + err = ZIP_BADZIPFILE; /* Caller passed zip64 = 0, so no room for zip64 info -> fatal */ } else { @@ -1735,7 +2023,7 @@ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */ - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ? + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); /* why ZPOS64_T of this ? */ if (err==ZIP_OK) /* version made by */ err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); @@ -1782,7 +2070,7 @@ { { if(zi->number_entry >= 0xFFFF) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); /* use value in ZIP64 record */ else err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); } @@ -1791,7 +2079,7 @@ if (err==ZIP_OK) /* total number of entries in the central dir */ { if(zi->number_entry >= 0xFFFF) - err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); /* use value in ZIP64 record */ else err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); } @@ -1871,6 +2159,8 @@ } free_linkedlist(&(zi->central_dir)); + set_end(&zi->set); /* set was zeroed, so this is safe */ + pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF) { @@ -1919,13 +2209,13 @@ header = *(short*)p; dataSize = *(((short*)p)+1); - if( header == sHeader ) // Header found. + if( header == sHeader ) /* Header found. */ { - p += dataSize + 4; // skip it. do not copy to temp buffer + p += dataSize + 4; /* skip it. do not copy to temp buffer */ } else { - // Extra Info block should not be removed, So copy it to the temp buffer. + /* Extra Info block should not be removed, So copy it to the temp buffer. */ memcpy(pTmp, p, dataSize + 4); p += dataSize + 4; size += dataSize + 4; @@ -1935,14 +2225,14 @@ if(size < *dataLen) { - // clean old extra info block. + /* clean old extra info block. */ memset(pData,0, *dataLen); - // copy the new extra info block over the old + /* copy the new extra info block over the old */ if(size > 0) memcpy(pData, pNewHeader, size); - // set the new extra info size + /* set the new extra info size */ *dataLen = size; retVal = ZIP_OK;
--- a/OrthancFramework/Resources/ThirdParty/minizip/zip.h Fri Feb 20 15:41:05 2026 +0100 +++ b/OrthancFramework/Resources/ThirdParty/minizip/zip.h Fri Feb 20 16:03:16 2026 +0100 @@ -1,11 +1,10 @@ /* zip.h -- IO on .zip files using zlib - Version 1.1, February 14h, 2010 - part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + part of the MiniZip project - ( https://www.winimage.com/zLibDll/minizip.html ) - Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + Copyright (C) 1998-2026 Gilles Vollant (minizip) ( https://www.winimage.com/zLibDll/minizip.html ) Modifications for Zip64 support - Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + Copyright (C) 2009-2010 Mathias Svensson ( https://result42.com ) For more info read MiniZip_info.txt @@ -35,7 +34,7 @@ See header of zip.h -*/ + */ #ifndef _zip12_H #define _zip12_H @@ -44,7 +43,7 @@ extern "C" { #endif -//#define HAVE_BZIP2 +/* #define HAVE_BZIP2 */ #ifndef _ZLIB_H #include "zlib.h" @@ -69,6 +68,8 @@ typedef voidp zipFile; #endif +extern const char zip_copyright[]; + #define ZIP_OK (0) #define ZIP_EOF (0) #define ZIP_ERRNO (Z_ERRNO) @@ -127,12 +128,12 @@ If the zipfile cannot be opened, the return value is NULL. Else, the return value is a zipFile Handle, usable with other function of this zip package. -*/ + */ /* Note : there is no delete function into a zipfile. If you want delete file into a zipfile, you must open a zipfile, and create another Of course, you can use RAW reading and writing to copy the file you did not want delete -*/ + */ extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, @@ -186,7 +187,7 @@ zip64 is set to 1 if a zip64 extended information block should be added to the local file header. this MUST be '1' if the uncompressed size is >= 0xffffffff. -*/ + */ extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, @@ -311,12 +312,12 @@ unsigned len); /* Write data in the zipfile -*/ + */ extern int ZEXPORT zipCloseFileInZip(zipFile file); /* Close the current file in the zipfile -*/ + */ extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, @@ -326,17 +327,23 @@ ZPOS64_T uncompressed_size, uLong crc32); +extern int ZEXPORT zipAlreadyThere(zipFile file, + char const* name); +/* + See if name is already in file's central directory. + */ + /* Close the current file in the zipfile, for file opened with parameter raw=1 in zipOpenNewFileInZip2 uncompressed_size and crc32 are value for the uncompressed size -*/ + */ extern int ZEXPORT zipClose(zipFile file, const char* global_comment); /* Close the zipfile -*/ + */ extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader); @@ -355,7 +362,7 @@ Remove ZIP64 Extra information from a Local File Header extra field data zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001); -*/ + */ #ifdef __cplusplus }
