Coverage Report

Created: 2024-07-23 06:45

/src/ogre/OgreMain/src/zip/miniz.h
Line
Count
Source (jump to first uncovered line)
1
#define MINIZ_EXPORT
2
/* miniz.c 2.2.0 - public domain deflate/inflate, zlib-subset, ZIP
3
   reading/writing/appending, PNG writing See "unlicense" statement at the end
4
   of this file. Rich Geldreich <richgel99@gmail.com>, last updated Oct. 13,
5
   2013 Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951:
6
   http://www.ietf.org/rfc/rfc1951.txt
7
8
   Most API's defined in miniz.c are optional. For example, to disable the
9
   archive related functions just define MINIZ_NO_ARCHIVE_APIS, or to get rid of
10
   all stdio usage define MINIZ_NO_STDIO (see the list below for more macros).
11
12
   * Low-level Deflate/Inflate implementation notes:
13
14
     Compression: Use the "tdefl" API's. The compressor supports raw, static,
15
   and dynamic blocks, lazy or greedy parsing, match length filtering, RLE-only,
16
   and Huffman-only streams. It performs and compresses approximately as well as
17
   zlib.
18
19
     Decompression: Use the "tinfl" API's. The entire decompressor is
20
   implemented as a single function coroutine: see tinfl_decompress(). It
21
   supports decompression into a 32KB (or larger power of 2) wrapping buffer, or
22
   into a memory block large enough to hold the entire file.
23
24
     The low-level tdefl/tinfl API's do not make any use of dynamic memory
25
   allocation.
26
27
   * zlib-style API notes:
28
29
     miniz.c implements a fairly large subset of zlib. There's enough
30
   functionality present for it to be a drop-in zlib replacement in many apps:
31
        The z_stream struct, optional memory allocation callbacks
32
        deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
33
        inflateInit/inflateInit2/inflate/inflateReset/inflateEnd
34
        compress, compress2, compressBound, uncompress
35
        CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly
36
   routines. Supports raw deflate streams or standard zlib streams with adler-32
37
   checking.
38
39
     Limitations:
40
      The callback API's are not implemented yet. No support for gzip headers or
41
   zlib static dictionaries. I've tried to closely emulate zlib's various
42
   flavors of stream flushing and return status codes, but there are no
43
   guarantees that miniz.c pulls this off perfectly.
44
45
   * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function,
46
   originally written by Alex Evans. Supports 1-4 bytes/pixel images.
47
48
   * ZIP archive API notes:
49
50
     The ZIP archive API's where designed with simplicity and efficiency in
51
   mind, with just enough abstraction to get the job done with minimal fuss.
52
   There are simple API's to retrieve file information, read files from existing
53
   archives, create new archives, append new files to existing archives, or
54
   clone archive data from one archive to another. It supports archives located
55
   in memory or the heap, on disk (using stdio.h), or you can specify custom
56
   file read/write callbacks.
57
58
     - Archive reading: Just call this function to read a single file from a
59
   disk archive:
60
61
      void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const
62
   char *pArchive_name, size_t *pSize, mz_uint zip_flags);
63
64
     For more complex cases, use the "mz_zip_reader" functions. Upon opening an
65
   archive, the entire central directory is located and read as-is into memory,
66
   and subsequent file access only occurs when reading individual files.
67
68
     - Archives file scanning: The simple way is to use this function to scan a
69
   loaded archive for a specific file:
70
71
     int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
72
   const char *pComment, mz_uint flags);
73
74
     The locate operation can optionally check file comments too, which (as one
75
   example) can be used to identify multiple versions of the same file in an
76
   archive. This function uses a simple linear search through the central
77
     directory, so it's not very fast.
78
79
     Alternately, you can iterate through all the files in an archive (using
80
   mz_zip_reader_get_num_files()) and retrieve detailed info on each file by
81
   calling mz_zip_reader_file_stat().
82
83
     - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer
84
   immediately writes compressed file data to disk and builds an exact image of
85
   the central directory in memory. The central directory image is written all
86
   at once at the end of the archive file when the archive is finalized.
87
88
     The archive writer can optionally align each file's local header and file
89
   data to any power of 2 alignment, which can be useful when the archive will
90
   be read from optical media. Also, the writer supports placing arbitrary data
91
   blobs at the very beginning of ZIP archives. Archives written using either
92
   feature are still readable by any ZIP tool.
93
94
     - Archive appending: The simple way to add a single file to an archive is
95
   to call this function:
96
97
      mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename,
98
   const char *pArchive_name, const void *pBuf, size_t buf_size, const void
99
   *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
100
101
     The archive will be created if it doesn't already exist, otherwise it'll be
102
   appended to. Note the appending is done in-place and is not an atomic
103
   operation, so if something goes wrong during the operation it's possible the
104
   archive could be left without a central directory (although the local file
105
   headers and file data will be fine, so the archive will be recoverable).
106
107
     For more complex archive modification scenarios:
108
     1. The safest way is to use a mz_zip_reader to read the existing archive,
109
   cloning only those bits you want to preserve into a new archive using using
110
   the mz_zip_writer_add_from_zip_reader() function (which compiles the
111
     compressed file data as-is). When you're done, delete the old archive and
112
   rename the newly written archive, and you're done. This is safe but requires
113
   a bunch of temporary disk space or heap memory.
114
115
     2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using
116
   mz_zip_writer_init_from_reader(), append new files as needed, then finalize
117
   the archive which will write an updated central directory to the original
118
   archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place()
119
   does.) There's a possibility that the archive's central directory could be
120
   lost with this method if anything goes wrong, though.
121
122
     - ZIP archive support limitations:
123
     No spanning support. Extraction functions can only handle unencrypted,
124
   stored or deflated files. Requires streams capable of seeking.
125
126
   * This is a header file library, like stb_image.c. To get only a header file,
127
   either cut and paste the below header, or create miniz.h, #define
128
   MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it.
129
130
   * Important: For best perf. be sure to customize the below macros for your
131
   target platform: #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 #define
132
   MINIZ_LITTLE_ENDIAN 1 #define MINIZ_HAS_64BIT_REGISTERS 1
133
134
   * On platforms using glibc, Be sure to "#define _LARGEFILE64_SOURCE 1" before
135
   including miniz.c to ensure miniz uses the 64-bit variants: fopen64(),
136
   stat64(), etc. Otherwise you won't be able to process large files (i.e.
137
   32-bit stat() fails for me on files > 0x7FFFFFFF bytes).
138
*/
139
#pragma once
140
141
/* Defines to completely disable specific portions of miniz.c:
142
   If all macros here are defined the only functionality remaining will be
143
   CRC-32, adler-32, tinfl, and tdefl. */
144
145
/* Define MINIZ_NO_STDIO to disable all usage and any functions which rely on
146
 * stdio for file I/O. */
147
/*#define MINIZ_NO_STDIO */
148
149
/* If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able
150
 * to get the current time, or */
151
/* get/set file times, and the C run-time funcs that get/set times won't be
152
 * called. */
153
/* The current downside is the times written to your archives will be from 1979.
154
 */
155
/*#define MINIZ_NO_TIME */
156
157
/* Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. */
158
/*#define MINIZ_NO_ARCHIVE_APIS */
159
160
/* Define MINIZ_NO_ARCHIVE_WRITING_APIS to disable all writing related ZIP
161
 * archive API's. */
162
/*#define MINIZ_NO_ARCHIVE_WRITING_APIS */
163
164
/* Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression
165
 * API's. */
166
/*#define MINIZ_NO_ZLIB_APIS */
167
168
/* Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent
169
 * conflicts against stock zlib. */
170
/*#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES */
171
172
/* Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc.
173
   Note if MINIZ_NO_MALLOC is defined then the user must always provide custom
174
   user alloc/free/realloc callbacks to the zlib and archive API's, and a few
175
   stand-alone helper API's which don't provide custom user functions (such as
176
   tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work.
177
 */
178
/*#define MINIZ_NO_MALLOC */
179
180
#if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
181
/* TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc
182
 * on Linux */
183
#define MINIZ_NO_TIME
184
#endif
185
186
#include <stddef.h>
187
188
#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS)
189
#include <time.h>
190
#endif
191
192
#if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) ||                \
193
    defined(__i386) || defined(__i486__) || defined(__i486) ||                 \
194
    defined(i386) || defined(__ia64__) || defined(__x86_64__)
195
/* MINIZ_X86_OR_X64_CPU is only used to help set the below macros. */
196
#define MINIZ_X86_OR_X64_CPU 1
197
#else
198
#define MINIZ_X86_OR_X64_CPU 0
199
#endif
200
201
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
202
/* Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. */
203
#define MINIZ_LITTLE_ENDIAN 1
204
#else
205
#define MINIZ_LITTLE_ENDIAN 0
206
#endif
207
208
/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */
209
#if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES)
210
#if MINIZ_X86_OR_X64_CPU
211
/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient
212
 * integer loads and stores from unaligned addresses. */
213
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
214
#define MINIZ_UNALIGNED_USE_MEMCPY
215
#else
216
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0
217
#endif
218
#endif
219
220
#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) ||              \
221
    defined(_LP64) || defined(__LP64__) || defined(__ia64__) ||                \
222
    defined(__x86_64__)
223
/* Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are
224
 * reasonably fast (and don't involve compiler generated calls to helper
225
 * functions). */
226
#define MINIZ_HAS_64BIT_REGISTERS 1
227
#else
228
#define MINIZ_HAS_64BIT_REGISTERS 0
229
#endif
230
231
#ifdef __cplusplus
232
extern "C" {
233
#endif
234
235
/* ------------------- zlib-style API Definitions. */
236
237
/* For more compatibility with zlib, miniz.c uses unsigned long for some
238
 * parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! */
239
typedef unsigned long mz_ulong;
240
241
/* mz_free() internally uses the MZ_FREE() macro (which by default calls free()
242
 * unless you've modified the MZ_MALLOC macro) to release a block allocated from
243
 * the heap. */
244
MINIZ_EXPORT void mz_free(void *p);
245
246
0
#define MZ_ADLER32_INIT (1)
247
/* mz_adler32() returns the initial adler-32 value to use when called with
248
 * ptr==NULL. */
249
MINIZ_EXPORT mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr,
250
                                 size_t buf_len);
251
252
0
#define MZ_CRC32_INIT (0)
253
/* mz_crc32() returns the initial CRC-32 value to use when called with
254
 * ptr==NULL. */
255
MINIZ_EXPORT mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr,
256
                               size_t buf_len);
257
258
/* Compression strategies. */
259
enum {
260
  MZ_DEFAULT_STRATEGY = 0,
261
  MZ_FILTERED = 1,
262
  MZ_HUFFMAN_ONLY = 2,
263
  MZ_RLE = 3,
264
  MZ_FIXED = 4
265
};
266
267
/* Method */
268
0
#define MZ_DEFLATED 8
269
270
/* Heap allocation callbacks.
271
Note that mz_alloc_func parameter types purposely differ from zlib's: items/size
272
is size_t, not unsigned long. */
273
typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
274
typedef void (*mz_free_func)(void *opaque, void *address);
275
typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items,
276
                                 size_t size);
277
278
/* Compression levels: 0-9 are the standard zlib-style levels, 10 is best
279
 * possible compression (not zlib compatible, and may be very slow),
280
 * MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. */
281
enum {
282
  MZ_NO_COMPRESSION = 0,
283
  MZ_BEST_SPEED = 1,
284
  MZ_BEST_COMPRESSION = 9,
285
  MZ_UBER_COMPRESSION = 10,
286
  MZ_DEFAULT_LEVEL = 6,
287
  MZ_DEFAULT_COMPRESSION = -1
288
};
289
290
0
#define MZ_VERSION "10.2.0"
291
#define MZ_VERNUM 0xA100
292
#define MZ_VER_MAJOR 10
293
#define MZ_VER_MINOR 2
294
#define MZ_VER_REVISION 0
295
#define MZ_VER_SUBREVISION 0
296
297
#ifndef MINIZ_NO_ZLIB_APIS
298
299
/* Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The
300
 * other values are for advanced use (refer to the zlib docs). */
301
enum {
302
  MZ_NO_FLUSH = 0,
303
  MZ_PARTIAL_FLUSH = 1,
304
  MZ_SYNC_FLUSH = 2,
305
  MZ_FULL_FLUSH = 3,
306
  MZ_FINISH = 4,
307
  MZ_BLOCK = 5
308
};
309
310
/* Return status codes. MZ_PARAM_ERROR is non-standard. */
311
enum {
312
  MZ_OK = 0,
313
  MZ_STREAM_END = 1,
314
  MZ_NEED_DICT = 2,
315
  MZ_ERRNO = -1,
316
  MZ_STREAM_ERROR = -2,
317
  MZ_DATA_ERROR = -3,
318
  MZ_MEM_ERROR = -4,
319
  MZ_BUF_ERROR = -5,
320
  MZ_VERSION_ERROR = -6,
321
  MZ_PARAM_ERROR = -10000
322
};
323
324
/* Window bits */
325
0
#define MZ_DEFAULT_WINDOW_BITS 15
326
327
struct mz_internal_state;
328
329
/* Compression/decompression stream struct. */
330
typedef struct mz_stream_s {
331
  const unsigned char *next_in; /* pointer to next byte to read */
332
  unsigned int avail_in;        /* number of bytes available at next_in */
333
  mz_ulong total_in;            /* total number of bytes consumed so far */
334
335
  unsigned char *next_out; /* pointer to next byte to write */
336
  unsigned int avail_out;  /* number of bytes that can be written to next_out */
337
  mz_ulong total_out;      /* total number of bytes produced so far */
338
339
  char *msg; /* error msg (unused) */
340
  struct mz_internal_state
341
      *state; /* internal state, allocated by zalloc/zfree */
342
343
  mz_alloc_func
344
      zalloc; /* optional heap allocation function (defaults to malloc) */
345
  mz_free_func zfree; /* optional heap free function (defaults to free) */
346
  void *opaque;       /* heap alloc function user pointer */
347
348
  int data_type;     /* data_type (unused) */
349
  mz_ulong adler;    /* adler32 of the source or uncompressed data */
350
  mz_ulong reserved; /* not used */
351
} mz_stream;
352
353
typedef mz_stream *mz_streamp;
354
355
/* Returns the version string of miniz.c. */
356
MINIZ_EXPORT const char *mz_version(void);
357
358
/* mz_deflateInit() initializes a compressor with default options: */
359
/* Parameters: */
360
/*  pStream must point to an initialized mz_stream struct. */
361
/*  level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. */
362
/*  level 1 enables a specially optimized compression function that's been
363
 * optimized purely for performance, not ratio. */
364
/*  (This special func. is currently only enabled when
365
 * MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) */
366
/* Return values: */
367
/*  MZ_OK on success. */
368
/*  MZ_STREAM_ERROR if the stream is bogus. */
369
/*  MZ_PARAM_ERROR if the input parameters are bogus. */
370
/*  MZ_MEM_ERROR on out of memory. */
371
MINIZ_EXPORT int mz_deflateInit(mz_streamp pStream, int level);
372
373
/* mz_deflateInit2() is like mz_deflate(), except with more control: */
374
/* Additional parameters: */
375
/*   method must be MZ_DEFLATED */
376
/*   window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with
377
 * zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no
378
 * header or footer) */
379
/*   mem_level must be between [1, 9] (it's checked but ignored by miniz.c) */
380
MINIZ_EXPORT int mz_deflateInit2(mz_streamp pStream, int level, int method,
381
                                 int window_bits, int mem_level, int strategy);
382
383
/* Quickly resets a compressor without having to reallocate anything. Same as
384
 * calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). */
385
MINIZ_EXPORT int mz_deflateReset(mz_streamp pStream);
386
387
/* mz_deflate() compresses the input to output, consuming as much of the input
388
 * and producing as much output as possible. */
389
/* Parameters: */
390
/*   pStream is the stream to read from and write to. You must initialize/update
391
 * the next_in, avail_in, next_out, and avail_out members. */
392
/*   flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or
393
 * MZ_FINISH. */
394
/* Return values: */
395
/*   MZ_OK on success (when flushing, or if more input is needed but not
396
 * available, and/or there's more output to be written but the output buffer is
397
 * full). */
398
/*   MZ_STREAM_END if all input has been consumed and all output bytes have been
399
 * written. Don't call mz_deflate() on the stream anymore. */
400
/*   MZ_STREAM_ERROR if the stream is bogus. */
401
/*   MZ_PARAM_ERROR if one of the parameters is invalid. */
402
/*   MZ_BUF_ERROR if no forward progress is possible because the input and/or
403
 * output buffers are empty. (Fill up the input buffer or free up some output
404
 * space and try again.) */
405
MINIZ_EXPORT int mz_deflate(mz_streamp pStream, int flush);
406
407
/* mz_deflateEnd() deinitializes a compressor: */
408
/* Return values: */
409
/*  MZ_OK on success. */
410
/*  MZ_STREAM_ERROR if the stream is bogus. */
411
MINIZ_EXPORT int mz_deflateEnd(mz_streamp pStream);
412
413
/* mz_deflateBound() returns a (very) conservative upper bound on the amount of
414
 * data that could be generated by deflate(), assuming flush is set to only
415
 * MZ_NO_FLUSH or MZ_FINISH. */
416
MINIZ_EXPORT mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
417
418
/* Single-call compression functions mz_compress() and mz_compress2(): */
419
/* Returns MZ_OK on success, or one of the error codes from mz_deflate() on
420
 * failure. */
421
MINIZ_EXPORT int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
422
                             const unsigned char *pSource, mz_ulong source_len);
423
MINIZ_EXPORT int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len,
424
                              const unsigned char *pSource, mz_ulong source_len,
425
                              int level);
426
427
/* mz_compressBound() returns a (very) conservative upper bound on the amount of
428
 * data that could be generated by calling mz_compress(). */
429
MINIZ_EXPORT mz_ulong mz_compressBound(mz_ulong source_len);
430
431
/* Initializes a decompressor. */
432
MINIZ_EXPORT int mz_inflateInit(mz_streamp pStream);
433
434
/* mz_inflateInit2() is like mz_inflateInit() with an additional option that
435
 * controls the window size and whether or not the stream has been wrapped with
436
 * a zlib header/footer: */
437
/* window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or
438
 * -MZ_DEFAULT_WINDOW_BITS (raw deflate). */
439
MINIZ_EXPORT int mz_inflateInit2(mz_streamp pStream, int window_bits);
440
441
/* Quickly resets a compressor without having to reallocate anything. Same as
442
 * calling mz_inflateEnd() followed by mz_inflateInit()/mz_inflateInit2(). */
443
MINIZ_EXPORT int mz_inflateReset(mz_streamp pStream);
444
445
/* Decompresses the input stream to the output, consuming only as much of the
446
 * input as needed, and writing as much to the output as possible. */
447
/* Parameters: */
448
/*   pStream is the stream to read from and write to. You must initialize/update
449
 * the next_in, avail_in, next_out, and avail_out members. */
450
/*   flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. */
451
/*   On the first call, if flush is MZ_FINISH it's assumed the input and output
452
 * buffers are both sized large enough to decompress the entire stream in a
453
 * single call (this is slightly faster). */
454
/*   MZ_FINISH implies that there are no more source bytes available beside
455
 * what's already in the input buffer, and that the output buffer is large
456
 * enough to hold the rest of the decompressed data. */
457
/* Return values: */
458
/*   MZ_OK on success. Either more input is needed but not available, and/or
459
 * there's more output to be written but the output buffer is full. */
460
/*   MZ_STREAM_END if all needed input has been consumed and all output bytes
461
 * have been written. For zlib streams, the adler-32 of the decompressed data
462
 * has also been verified. */
463
/*   MZ_STREAM_ERROR if the stream is bogus. */
464
/*   MZ_DATA_ERROR if the deflate stream is invalid. */
465
/*   MZ_PARAM_ERROR if one of the parameters is invalid. */
466
/*   MZ_BUF_ERROR if no forward progress is possible because the input buffer is
467
 * empty but the inflater needs more input to continue, or if the output buffer
468
 * is not large enough. Call mz_inflate() again */
469
/*   with more input data, or with more room in the output buffer (except when
470
 * using single call decompression, described above). */
471
MINIZ_EXPORT int mz_inflate(mz_streamp pStream, int flush);
472
473
/* Deinitializes a decompressor. */
474
MINIZ_EXPORT int mz_inflateEnd(mz_streamp pStream);
475
476
/* Single-call decompression. */
477
/* Returns MZ_OK on success, or one of the error codes from mz_inflate() on
478
 * failure. */
479
MINIZ_EXPORT int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len,
480
                               const unsigned char *pSource,
481
                               mz_ulong source_len);
482
MINIZ_EXPORT int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len,
483
                                const unsigned char *pSource,
484
                                mz_ulong *pSource_len);
485
486
/* Returns a string description of the specified error code, or NULL if the
487
 * error code is invalid. */
488
MINIZ_EXPORT const char *mz_error(int err);
489
490
/* Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used
491
 * as a drop-in replacement for the subset of zlib that miniz.c supports. */
492
/* Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you
493
 * use zlib in the same project. */
494
#ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES
495
typedef unsigned char Byte;
496
typedef unsigned int uInt;
497
typedef mz_ulong uLong;
498
typedef Byte Bytef;
499
typedef uInt uIntf;
500
typedef char charf;
501
typedef int intf;
502
typedef void *voidpf;
503
typedef uLong uLongf;
504
typedef void *voidp;
505
typedef void *const voidpc;
506
#define Z_NULL 0
507
0
#define Z_NO_FLUSH MZ_NO_FLUSH
508
#define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH
509
0
#define Z_SYNC_FLUSH MZ_SYNC_FLUSH
510
#define Z_FULL_FLUSH MZ_FULL_FLUSH
511
0
#define Z_FINISH MZ_FINISH
512
#define Z_BLOCK MZ_BLOCK
513
0
#define Z_OK MZ_OK
514
0
#define Z_STREAM_END MZ_STREAM_END
515
#define Z_NEED_DICT MZ_NEED_DICT
516
#define Z_ERRNO MZ_ERRNO
517
#define Z_STREAM_ERROR MZ_STREAM_ERROR
518
#define Z_DATA_ERROR MZ_DATA_ERROR
519
#define Z_MEM_ERROR MZ_MEM_ERROR
520
#define Z_BUF_ERROR MZ_BUF_ERROR
521
#define Z_VERSION_ERROR MZ_VERSION_ERROR
522
#define Z_PARAM_ERROR MZ_PARAM_ERROR
523
#define Z_NO_COMPRESSION MZ_NO_COMPRESSION
524
#define Z_BEST_SPEED MZ_BEST_SPEED
525
#define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION
526
0
#define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION
527
0
#define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY
528
#define Z_FILTERED MZ_FILTERED
529
#define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY
530
#define Z_RLE MZ_RLE
531
#define Z_FIXED MZ_FIXED
532
0
#define Z_DEFLATED MZ_DEFLATED
533
#define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS
534
#define alloc_func mz_alloc_func
535
#define free_func mz_free_func
536
#define internal_state mz_internal_state
537
#define z_stream mz_stream
538
#define deflateInit mz_deflateInit
539
0
#define deflateInit2 mz_deflateInit2
540
#define deflateReset mz_deflateReset
541
0
#define deflate mz_deflate
542
0
#define deflateEnd mz_deflateEnd
543
#define deflateBound mz_deflateBound
544
#define compress mz_compress
545
#define compress2 mz_compress2
546
#define compressBound mz_compressBound
547
#define inflateInit mz_inflateInit
548
0
#define inflateInit2 mz_inflateInit2
549
0
#define inflateReset mz_inflateReset
550
0
#define inflate mz_inflate
551
0
#define inflateEnd mz_inflateEnd
552
#define uncompress mz_uncompress
553
#define uncompress2 mz_uncompress2
554
0
#define crc32 mz_crc32
555
#define adler32 mz_adler32
556
0
#define MAX_WBITS 15
557
#define MAX_MEM_LEVEL 9
558
#define zError mz_error
559
#define ZLIB_VERSION MZ_VERSION
560
#define ZLIB_VERNUM MZ_VERNUM
561
#define ZLIB_VER_MAJOR MZ_VER_MAJOR
562
#define ZLIB_VER_MINOR MZ_VER_MINOR
563
#define ZLIB_VER_REVISION MZ_VER_REVISION
564
#define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION
565
#define zlibVersion mz_version
566
#define zlib_version mz_version()
567
#endif /* #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES */
568
569
#endif /* MINIZ_NO_ZLIB_APIS */
570
571
#ifdef __cplusplus
572
}
573
#endif
574
575
#pragma once
576
#include <assert.h>
577
#include <stdint.h>
578
#include <stdlib.h>
579
#include <string.h>
580
581
/* ------------------- Types and macros */
582
typedef unsigned char mz_uint8;
583
typedef signed short mz_int16;
584
typedef unsigned short mz_uint16;
585
typedef unsigned int mz_uint32;
586
typedef unsigned int mz_uint;
587
typedef int64_t mz_int64;
588
typedef uint64_t mz_uint64;
589
typedef int mz_bool;
590
591
0
#define MZ_FALSE (0)
592
0
#define MZ_TRUE (1)
593
594
/* Works around MSVC's spammy "warning C4127: conditional expression is
595
 * constant" message. */
596
#ifdef _MSC_VER
597
#define MZ_MACRO_END while (0, 0)
598
#else
599
0
#define MZ_MACRO_END while (0)
600
#endif
601
602
#ifdef MINIZ_NO_STDIO
603
#define MZ_FILE void *
604
#else
605
#include <stdio.h>
606
0
#define MZ_FILE FILE
607
#endif /* #ifdef MINIZ_NO_STDIO */
608
609
#ifdef MINIZ_NO_TIME
610
typedef struct mz_dummy_time_t_tag {
611
  int m_dummy;
612
} mz_dummy_time_t;
613
#define MZ_TIME_T mz_dummy_time_t
614
#else
615
0
#define MZ_TIME_T time_t
616
#endif
617
618
0
#define MZ_ASSERT(x) assert(x)
619
620
#ifdef MINIZ_NO_MALLOC
621
#define MZ_MALLOC(x) NULL
622
#define MZ_FREE(x) (void)x, ((void)0)
623
#define MZ_REALLOC(p, x) NULL
624
#else
625
0
#define MZ_MALLOC(x) malloc(x)
626
0
#define MZ_FREE(x) free(x)
627
0
#define MZ_REALLOC(p, x) realloc(p, x)
628
#endif
629
630
0
#define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b))
631
0
#define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b))
632
0
#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
633
634
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
635
0
#define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
636
0
#define MZ_READ_LE32(p) *((const mz_uint32 *)(p))
637
#else
638
#define MZ_READ_LE16(p)                                                        \
639
  ((mz_uint32)(((const mz_uint8 *)(p))[0]) |                                   \
640
   ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U))
641
#define MZ_READ_LE32(p)                                                        \
642
  ((mz_uint32)(((const mz_uint8 *)(p))[0]) |                                   \
643
   ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) |                           \
644
   ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) |                          \
645
   ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U))
646
#endif
647
648
#define MZ_READ_LE64(p)                                                        \
649
0
  (((mz_uint64)MZ_READ_LE32(p)) |                                              \
650
0
   (((mz_uint64)MZ_READ_LE32((const mz_uint8 *)(p) + sizeof(mz_uint32)))       \
651
0
    << 32U))
652
653
#ifdef _MSC_VER
654
#define MZ_FORCEINLINE __forceinline
655
#elif defined(__GNUC__)
656
#define MZ_FORCEINLINE __inline__ __attribute__((__always_inline__))
657
#else
658
#define MZ_FORCEINLINE inline
659
#endif
660
661
#ifdef __cplusplus
662
extern "C" {
663
#endif
664
665
extern MINIZ_EXPORT void *miniz_def_alloc_func(void *opaque, size_t items,
666
                                               size_t size);
667
extern MINIZ_EXPORT void miniz_def_free_func(void *opaque, void *address);
668
extern MINIZ_EXPORT void *miniz_def_realloc_func(void *opaque, void *address,
669
                                                 size_t items, size_t size);
670
671
0
#define MZ_UINT16_MAX (0xFFFFU)
672
0
#define MZ_UINT32_MAX (0xFFFFFFFFU)
673
674
#ifdef __cplusplus
675
}
676
#endif
677
#pragma once
678
679
#ifdef __cplusplus
680
extern "C" {
681
#endif
682
/* ------------------- Low-level Compression API Definitions */
683
684
/* Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly
685
 * slower, and raw/dynamic blocks will be output more frequently). */
686
#define TDEFL_LESS_MEMORY 0
687
688
/* tdefl_init() compression flags logically OR'd together (low 12 bits contain
689
 * the max. number of probes per dictionary search): */
690
/* TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes
691
 * per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap
692
 * compression), 4095=Huffman+LZ (slowest/best compression). */
693
enum {
694
  TDEFL_HUFFMAN_ONLY = 0,
695
  TDEFL_DEFAULT_MAX_PROBES = 128,
696
  TDEFL_MAX_PROBES_MASK = 0xFFF
697
};
698
699
/* TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before
700
 * the deflate data, and the Adler-32 of the source data at the end. Otherwise,
701
 * you'll get raw deflate data. */
702
/* TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even
703
 * when not writing zlib headers). */
704
/* TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more
705
 * efficient lazy parsing. */
706
/* TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's
707
 * initialization time to the minimum, but the output may vary from run to run
708
 * given the same input (depending on the contents of memory). */
709
/* TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1)
710
 */
711
/* TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. */
712
/* TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. */
713
/* TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. */
714
/* The low 12 bits are reserved to control the max # of hash probes per
715
 * dictionary lookup (see TDEFL_MAX_PROBES_MASK). */
716
enum {
717
  TDEFL_WRITE_ZLIB_HEADER = 0x01000,
718
  TDEFL_COMPUTE_ADLER32 = 0x02000,
719
  TDEFL_GREEDY_PARSING_FLAG = 0x04000,
720
  TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000,
721
  TDEFL_RLE_MATCHES = 0x10000,
722
  TDEFL_FILTER_MATCHES = 0x20000,
723
  TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000,
724
  TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000
725
};
726
727
/* High level compression functions: */
728
/* tdefl_compress_mem_to_heap() compresses a block in memory to a heap block
729
 * allocated via malloc(). */
730
/* On entry: */
731
/*  pSrc_buf, src_buf_len: Pointer and size of source block to compress. */
732
/*  flags: The max match finder probes (default is 128) logically OR'd against
733
 * the above flags. Higher probes are slower but improve compression. */
734
/* On return: */
735
/*  Function returns a pointer to the compressed data, or NULL on failure. */
736
/*  *pOut_len will be set to the compressed data's size, which could be larger
737
 * than src_buf_len on uncompressible data. */
738
/*  The caller must free() the returned block when it's no longer needed. */
739
MINIZ_EXPORT void *tdefl_compress_mem_to_heap(const void *pSrc_buf,
740
                                              size_t src_buf_len,
741
                                              size_t *pOut_len, int flags);
742
743
/* tdefl_compress_mem_to_mem() compresses a block in memory to another block in
744
 * memory. */
745
/* Returns 0 on failure. */
746
MINIZ_EXPORT size_t tdefl_compress_mem_to_mem(void *pOut_buf,
747
                                              size_t out_buf_len,
748
                                              const void *pSrc_buf,
749
                                              size_t src_buf_len, int flags);
750
751
/* Compresses an image to a compressed PNG file in memory. */
752
/* On entry: */
753
/*  pImage, w, h, and num_chans describe the image to compress. num_chans may be
754
 * 1, 2, 3, or 4. */
755
/*  The image pitch in bytes per scanline will be w*num_chans. The leftmost
756
 * pixel on the top scanline is stored first in memory. */
757
/*  level may range from [0,10], use MZ_NO_COMPRESSION, MZ_BEST_SPEED,
758
 * MZ_BEST_COMPRESSION, etc. or a decent default is MZ_DEFAULT_LEVEL */
759
/*  If flip is true, the image will be flipped on the Y axis (useful for OpenGL
760
 * apps). */
761
/* On return: */
762
/*  Function returns a pointer to the compressed data, or NULL on failure. */
763
/*  *pLen_out will be set to the size of the PNG image file. */
764
/*  The caller must mz_free() the returned heap block (which will typically be
765
 * larger than *pLen_out) when it's no longer needed. */
766
MINIZ_EXPORT void *
767
tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h,
768
                                           int num_chans, size_t *pLen_out,
769
                                           mz_uint level, mz_bool flip);
770
MINIZ_EXPORT void *tdefl_write_image_to_png_file_in_memory(const void *pImage,
771
                                                           int w, int h,
772
                                                           int num_chans,
773
                                                           size_t *pLen_out);
774
775
/* Output stream interface. The compressor uses this interface to write
776
 * compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. */
777
typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len,
778
                                          void *pUser);
779
780
/* tdefl_compress_mem_to_output() compresses a block to an output stream. The
781
 * above helpers use this function internally. */
782
MINIZ_EXPORT mz_bool tdefl_compress_mem_to_output(
783
    const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func,
784
    void *pPut_buf_user, int flags);
785
786
enum {
787
  TDEFL_MAX_HUFF_TABLES = 3,
788
  TDEFL_MAX_HUFF_SYMBOLS_0 = 288,
789
  TDEFL_MAX_HUFF_SYMBOLS_1 = 32,
790
  TDEFL_MAX_HUFF_SYMBOLS_2 = 19,
791
  TDEFL_LZ_DICT_SIZE = 32768,
792
  TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1,
793
  TDEFL_MIN_MATCH_LEN = 3,
794
  TDEFL_MAX_MATCH_LEN = 258
795
};
796
797
/* TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed
798
 * output block (using static/fixed Huffman codes). */
799
#if TDEFL_LESS_MEMORY
800
enum {
801
  TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024,
802
  TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
803
  TDEFL_MAX_HUFF_SYMBOLS = 288,
804
  TDEFL_LZ_HASH_BITS = 12,
805
  TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
806
  TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
807
  TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
808
};
809
#else
810
enum {
811
  TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024,
812
  TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10,
813
  TDEFL_MAX_HUFF_SYMBOLS = 288,
814
  TDEFL_LZ_HASH_BITS = 15,
815
  TDEFL_LEVEL1_HASH_SIZE_MASK = 4095,
816
  TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3,
817
  TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS
818
};
819
#endif
820
821
/* The low-level tdefl functions below may be used directly if the above helper
822
 * functions aren't flexible enough. The low-level functions don't make any heap
823
 * allocations, unlike the above helper functions. */
824
typedef enum {
825
  TDEFL_STATUS_BAD_PARAM = -2,
826
  TDEFL_STATUS_PUT_BUF_FAILED = -1,
827
  TDEFL_STATUS_OKAY = 0,
828
  TDEFL_STATUS_DONE = 1
829
} tdefl_status;
830
831
/* Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums */
832
typedef enum {
833
  TDEFL_NO_FLUSH = 0,
834
  TDEFL_SYNC_FLUSH = 2,
835
  TDEFL_FULL_FLUSH = 3,
836
  TDEFL_FINISH = 4
837
} tdefl_flush;
838
839
/* tdefl's compression state structure. */
840
typedef struct {
841
  tdefl_put_buf_func_ptr m_pPut_buf_func;
842
  void *m_pPut_buf_user;
843
  mz_uint m_flags, m_max_probes[2];
844
  int m_greedy_parsing;
845
  mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size;
846
  mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end;
847
  mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in,
848
      m_bit_buffer;
849
  mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit,
850
      m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index,
851
      m_wants_to_finish;
852
  tdefl_status m_prev_return_status;
853
  const void *m_pIn_buf;
854
  void *m_pOut_buf;
855
  size_t *m_pIn_buf_size, *m_pOut_buf_size;
856
  tdefl_flush m_flush;
857
  const mz_uint8 *m_pSrc;
858
  size_t m_src_buf_left, m_out_buf_ofs;
859
  mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1];
860
  mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
861
  mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
862
  mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS];
863
  mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE];
864
  mz_uint16 m_next[TDEFL_LZ_DICT_SIZE];
865
  mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE];
866
  mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE];
867
} tdefl_compressor;
868
869
/* Initializes the compressor. */
870
/* There is no corresponding deinit() function because the tdefl API's do not
871
 * dynamically allocate memory. */
872
/* pBut_buf_func: If NULL, output data will be supplied to the specified
873
 * callback. In this case, the user should call the tdefl_compress_buffer() API
874
 * for compression. */
875
/* If pBut_buf_func is NULL the user should always call the tdefl_compress()
876
 * API. */
877
/* flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER,
878
 * etc.) */
879
MINIZ_EXPORT tdefl_status tdefl_init(tdefl_compressor *d,
880
                                     tdefl_put_buf_func_ptr pPut_buf_func,
881
                                     void *pPut_buf_user, int flags);
882
883
/* Compresses a block of data, consuming as much of the specified input buffer
884
 * as possible, and writing as much compressed data to the specified output
885
 * buffer as possible. */
886
MINIZ_EXPORT tdefl_status tdefl_compress(tdefl_compressor *d,
887
                                         const void *pIn_buf,
888
                                         size_t *pIn_buf_size, void *pOut_buf,
889
                                         size_t *pOut_buf_size,
890
                                         tdefl_flush flush);
891
892
/* tdefl_compress_buffer() is only usable when the tdefl_init() is called with a
893
 * non-NULL tdefl_put_buf_func_ptr. */
894
/* tdefl_compress_buffer() always consumes the entire input buffer. */
895
MINIZ_EXPORT tdefl_status tdefl_compress_buffer(tdefl_compressor *d,
896
                                                const void *pIn_buf,
897
                                                size_t in_buf_size,
898
                                                tdefl_flush flush);
899
900
MINIZ_EXPORT tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
901
MINIZ_EXPORT mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
902
903
/* Create tdefl_compress() flags given zlib-style compression parameters. */
904
/* level may range from [0,10] (where 10 is absolute max compression, but may be
905
 * much slower on some files) */
906
/* window_bits may be -15 (raw deflate) or 15 (zlib) */
907
/* strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY,
908
 * MZ_RLE, or MZ_FIXED */
909
MINIZ_EXPORT mz_uint tdefl_create_comp_flags_from_zip_params(int level,
910
                                                             int window_bits,
911
                                                             int strategy);
912
913
#ifndef MINIZ_NO_MALLOC
914
/* Allocate the tdefl_compressor structure in C so that */
915
/* non-C language bindings to tdefl_ API don't need to worry about */
916
/* structure size and allocation mechanism. */
917
MINIZ_EXPORT tdefl_compressor *tdefl_compressor_alloc(void);
918
MINIZ_EXPORT void tdefl_compressor_free(tdefl_compressor *pComp);
919
#endif
920
921
#ifdef __cplusplus
922
}
923
#endif
924
#pragma once
925
926
/* ------------------- Low-level Decompression API Definitions */
927
928
#ifdef __cplusplus
929
extern "C" {
930
#endif
931
/* Decompression flags used by tinfl_decompress(). */
932
/* TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and
933
 * ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the
934
 * input is a raw deflate stream. */
935
/* TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available
936
 * beyond the end of the supplied input buffer. If clear, the input buffer
937
 * contains all remaining input. */
938
/* TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large
939
 * enough to hold the entire decompressed stream. If clear, the output buffer is
940
 * at least the size of the dictionary (typically 32KB). */
941
/* TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the
942
 * decompressed bytes. */
943
enum {
944
  TINFL_FLAG_PARSE_ZLIB_HEADER = 1,
945
  TINFL_FLAG_HAS_MORE_INPUT = 2,
946
  TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4,
947
  TINFL_FLAG_COMPUTE_ADLER32 = 8
948
};
949
950
/* High level decompression functions: */
951
/* tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block
952
 * allocated via malloc(). */
953
/* On entry: */
954
/*  pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data
955
 * to decompress. */
956
/* On return: */
957
/*  Function returns a pointer to the decompressed data, or NULL on failure. */
958
/*  *pOut_len will be set to the decompressed data's size, which could be larger
959
 * than src_buf_len on uncompressible data. */
960
/*  The caller must call mz_free() on the returned block when it's no longer
961
 * needed. */
962
MINIZ_EXPORT void *tinfl_decompress_mem_to_heap(const void *pSrc_buf,
963
                                                size_t src_buf_len,
964
                                                size_t *pOut_len, int flags);
965
966
/* tinfl_decompress_mem_to_mem() decompresses a block in memory to another block
967
 * in memory. */
968
/* Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes
969
 * written on success. */
970
0
#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
971
MINIZ_EXPORT size_t tinfl_decompress_mem_to_mem(void *pOut_buf,
972
                                                size_t out_buf_len,
973
                                                const void *pSrc_buf,
974
                                                size_t src_buf_len, int flags);
975
976
/* tinfl_decompress_mem_to_callback() decompresses a block in memory to an
977
 * internal 32KB buffer, and a user provided callback function will be called to
978
 * flush the buffer. */
979
/* Returns 1 on success or 0 on failure. */
980
typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);
981
MINIZ_EXPORT int
982
tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
983
                                 tinfl_put_buf_func_ptr pPut_buf_func,
984
                                 void *pPut_buf_user, int flags);
985
986
struct tinfl_decompressor_tag;
987
typedef struct tinfl_decompressor_tag tinfl_decompressor;
988
989
#ifndef MINIZ_NO_MALLOC
990
/* Allocate the tinfl_decompressor structure in C so that */
991
/* non-C language bindings to tinfl_ API don't need to worry about */
992
/* structure size and allocation mechanism. */
993
MINIZ_EXPORT tinfl_decompressor *tinfl_decompressor_alloc(void);
994
MINIZ_EXPORT void tinfl_decompressor_free(tinfl_decompressor *pDecomp);
995
#endif
996
997
/* Max size of LZ dictionary. */
998
0
#define TINFL_LZ_DICT_SIZE 32768
999
1000
/* Return status. */
1001
typedef enum {
1002
  /* This flags indicates the inflator needs 1 or more input bytes to make
1003
     forward progress, but the caller is indicating that no more are available.
1004
     The compressed data */
1005
  /* is probably corrupted. If you call the inflator again with more bytes it'll
1006
     try to continue processing the input but this is a BAD sign (either the
1007
     data is corrupted or you called it incorrectly). */
1008
  /* If you call it again with no input you'll just get
1009
     TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS again. */
1010
  TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS = -4,
1011
1012
  /* This flag indicates that one or more of the input parameters was obviously
1013
     bogus. (You can try calling it again, but if you get this error the calling
1014
     code is wrong.) */
1015
  TINFL_STATUS_BAD_PARAM = -3,
1016
1017
  /* This flags indicate the inflator is finished but the adler32 check of the
1018
     uncompressed data didn't match. If you call it again it'll return
1019
     TINFL_STATUS_DONE. */
1020
  TINFL_STATUS_ADLER32_MISMATCH = -2,
1021
1022
  /* This flags indicate the inflator has somehow failed (bad code, corrupted
1023
     input, etc.). If you call it again without resetting via tinfl_init() it
1024
     it'll just keep on returning the same status failure code. */
1025
  TINFL_STATUS_FAILED = -1,
1026
1027
  /* Any status code less than TINFL_STATUS_DONE must indicate a failure. */
1028
1029
  /* This flag indicates the inflator has returned every byte of uncompressed
1030
     data that it can, has consumed every byte that it needed, has successfully
1031
     reached the end of the deflate stream, and */
1032
  /* if zlib headers and adler32 checking enabled that it has successfully
1033
     checked the uncompressed data's adler32. If you call it again you'll just
1034
     get TINFL_STATUS_DONE over and over again. */
1035
  TINFL_STATUS_DONE = 0,
1036
1037
  /* This flag indicates the inflator MUST have more input data (even 1 byte)
1038
     before it can make any more forward progress, or you need to clear the
1039
     TINFL_FLAG_HAS_MORE_INPUT */
1040
  /* flag on the next call if you don't have any more source data. If the source
1041
     data was somehow corrupted it's also possible (but unlikely) for the
1042
     inflator to keep on demanding input to */
1043
  /* proceed, so be sure to properly set the TINFL_FLAG_HAS_MORE_INPUT flag. */
1044
  TINFL_STATUS_NEEDS_MORE_INPUT = 1,
1045
1046
  /* This flag indicates the inflator definitely has 1 or more bytes of
1047
     uncompressed data available, but it cannot write this data into the output
1048
     buffer. */
1049
  /* Note if the source compressed data was corrupted it's possible for the
1050
     inflator to return a lot of uncompressed data to the caller. I've been
1051
     assuming you know how much uncompressed data to expect */
1052
  /* (either exact or worst case) and will stop calling the inflator and fail
1053
     after receiving too much. In pure streaming scenarios where you have no
1054
     idea how many bytes to expect this may not be possible */
1055
  /* so I may need to add some code to address this. */
1056
  TINFL_STATUS_HAS_MORE_OUTPUT = 2
1057
} tinfl_status;
1058
1059
/* Initializes the decompressor to its initial state. */
1060
#define tinfl_init(r)                                                          \
1061
0
  do {                                                                         \
1062
0
    (r)->m_state = 0;                                                          \
1063
0
  }                                                                            \
1064
0
  MZ_MACRO_END
1065
0
#define tinfl_get_adler32(r) (r)->m_check_adler32
1066
1067
/* Main low-level decompressor coroutine function. This is the only function
1068
 * actually needed for decompression. All the other functions are just
1069
 * high-level helpers for improved usability. */
1070
/* This is a universal API, i.e. it can be used as a building block to build any
1071
 * desired higher level decompression API. In the limit case, it can be called
1072
 * once per every byte input or output. */
1073
MINIZ_EXPORT tinfl_status tinfl_decompress(
1074
    tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size,
1075
    mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size,
1076
    const mz_uint32 decomp_flags);
1077
1078
/* Internal/private bits follow. */
1079
enum {
1080
  TINFL_MAX_HUFF_TABLES = 3,
1081
  TINFL_MAX_HUFF_SYMBOLS_0 = 288,
1082
  TINFL_MAX_HUFF_SYMBOLS_1 = 32,
1083
  TINFL_MAX_HUFF_SYMBOLS_2 = 19,
1084
  TINFL_FAST_LOOKUP_BITS = 10,
1085
  TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
1086
};
1087
1088
typedef struct {
1089
  mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
1090
  mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE],
1091
      m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
1092
} tinfl_huff_table;
1093
1094
#if MINIZ_HAS_64BIT_REGISTERS
1095
#define TINFL_USE_64BIT_BITBUF 1
1096
#else
1097
#define TINFL_USE_64BIT_BITBUF 0
1098
#endif
1099
1100
#if TINFL_USE_64BIT_BITBUF
1101
typedef mz_uint64 tinfl_bit_buf_t;
1102
#define TINFL_BITBUF_SIZE (64)
1103
#else
1104
typedef mz_uint32 tinfl_bit_buf_t;
1105
#define TINFL_BITBUF_SIZE (32)
1106
#endif
1107
1108
struct tinfl_decompressor_tag {
1109
  mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type,
1110
      m_check_adler32, m_dist, m_counter, m_num_extra,
1111
      m_table_sizes[TINFL_MAX_HUFF_TABLES];
1112
  tinfl_bit_buf_t m_bit_buf;
1113
  size_t m_dist_from_out_buf_start;
1114
  tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
1115
  mz_uint8 m_raw_header[4],
1116
      m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
1117
};
1118
1119
#ifdef __cplusplus
1120
}
1121
#endif
1122
1123
#pragma once
1124
1125
/* ------------------- ZIP archive reading/writing */
1126
1127
#ifndef MINIZ_NO_ARCHIVE_APIS
1128
1129
#ifdef __cplusplus
1130
extern "C" {
1131
#endif
1132
1133
enum {
1134
  /* Note: These enums can be reduced as needed to save memory or stack space -
1135
     they are pretty conservative. */
1136
  MZ_ZIP_MAX_IO_BUF_SIZE = 64 * 1024,
1137
  MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 512,
1138
  MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 512
1139
};
1140
1141
typedef struct {
1142
  /* Central directory file index. */
1143
  mz_uint32 m_file_index;
1144
1145
  /* Byte offset of this entry in the archive's central directory. Note we
1146
   * currently only support up to UINT_MAX or less bytes in the central dir. */
1147
  mz_uint64 m_central_dir_ofs;
1148
1149
  /* These fields are copied directly from the zip's central dir. */
1150
  mz_uint16 m_version_made_by;
1151
  mz_uint16 m_version_needed;
1152
  mz_uint16 m_bit_flag;
1153
  mz_uint16 m_method;
1154
1155
#ifndef MINIZ_NO_TIME
1156
  MZ_TIME_T m_time;
1157
#endif
1158
1159
  /* CRC-32 of uncompressed data. */
1160
  mz_uint32 m_crc32;
1161
1162
  /* File's compressed size. */
1163
  mz_uint64 m_comp_size;
1164
1165
  /* File's uncompressed size. Note, I've seen some old archives where directory
1166
   * entries had 512 bytes for their uncompressed sizes, but when you try to
1167
   * unpack them you actually get 0 bytes. */
1168
  mz_uint64 m_uncomp_size;
1169
1170
  /* Zip internal and external file attributes. */
1171
  mz_uint16 m_internal_attr;
1172
  mz_uint32 m_external_attr;
1173
1174
  /* Entry's local header file offset in bytes. */
1175
  mz_uint64 m_local_header_ofs;
1176
1177
  /* Size of comment in bytes. */
1178
  mz_uint32 m_comment_size;
1179
1180
  /* MZ_TRUE if the entry appears to be a directory. */
1181
  mz_bool m_is_directory;
1182
1183
  /* MZ_TRUE if the entry uses encryption/strong encryption (which miniz_zip
1184
   * doesn't support) */
1185
  mz_bool m_is_encrypted;
1186
1187
  /* MZ_TRUE if the file is not encrypted, a patch file, and if it uses a
1188
   * compression method we support. */
1189
  mz_bool m_is_supported;
1190
1191
  /* Filename. If string ends in '/' it's a subdirectory entry. */
1192
  /* Guaranteed to be zero terminated, may be truncated to fit. */
1193
  char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE];
1194
1195
  /* Comment field. */
1196
  /* Guaranteed to be zero terminated, may be truncated to fit. */
1197
  char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
1198
1199
} mz_zip_archive_file_stat;
1200
1201
typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs,
1202
                                    void *pBuf, size_t n);
1203
typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs,
1204
                                     const void *pBuf, size_t n);
1205
typedef mz_bool (*mz_file_needs_keepalive)(void *pOpaque);
1206
1207
struct mz_zip_internal_state_tag;
1208
typedef struct mz_zip_internal_state_tag mz_zip_internal_state;
1209
1210
typedef enum {
1211
  MZ_ZIP_MODE_INVALID = 0,
1212
  MZ_ZIP_MODE_READING = 1,
1213
  MZ_ZIP_MODE_WRITING = 2,
1214
  MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3
1215
} mz_zip_mode;
1216
1217
typedef enum {
1218
  MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,
1219
  MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,
1220
  MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,
1221
  MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800,
1222
  MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG =
1223
      0x1000, /* if enabled, mz_zip_reader_locate_file() will be called on each
1224
                 file as its validated to ensure the func finds the file in the
1225
                 central dir (intended for testing) */
1226
  MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY =
1227
      0x2000, /* validate the local headers, but don't decompress the entire
1228
                 file and check the crc32 */
1229
  MZ_ZIP_FLAG_WRITE_ZIP64 =
1230
      0x4000, /* always use the zip64 file format, instead of the original zip
1231
                 file format with automatic switch to zip64. Use as flags
1232
                 parameter with mz_zip_writer_init*_v2 */
1233
  MZ_ZIP_FLAG_WRITE_ALLOW_READING = 0x8000,
1234
  MZ_ZIP_FLAG_ASCII_FILENAME = 0x10000,
1235
  /*After adding a compressed file, seek back
1236
  to local file header and set the correct sizes*/
1237
  MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE = 0x20000
1238
} mz_zip_flags;
1239
1240
typedef enum {
1241
  MZ_ZIP_TYPE_INVALID = 0,
1242
  MZ_ZIP_TYPE_USER,
1243
  MZ_ZIP_TYPE_MEMORY,
1244
  MZ_ZIP_TYPE_HEAP,
1245
  MZ_ZIP_TYPE_FILE,
1246
  MZ_ZIP_TYPE_CFILE,
1247
  MZ_ZIP_TOTAL_TYPES
1248
} mz_zip_type;
1249
1250
/* miniz error codes. Be sure to update mz_zip_get_error_string() if you add or
1251
 * modify this enum. */
1252
typedef enum {
1253
  MZ_ZIP_NO_ERROR = 0,
1254
  MZ_ZIP_UNDEFINED_ERROR,
1255
  MZ_ZIP_TOO_MANY_FILES,
1256
  MZ_ZIP_FILE_TOO_LARGE,
1257
  MZ_ZIP_UNSUPPORTED_METHOD,
1258
  MZ_ZIP_UNSUPPORTED_ENCRYPTION,
1259
  MZ_ZIP_UNSUPPORTED_FEATURE,
1260
  MZ_ZIP_FAILED_FINDING_CENTRAL_DIR,
1261
  MZ_ZIP_NOT_AN_ARCHIVE,
1262
  MZ_ZIP_INVALID_HEADER_OR_CORRUPTED,
1263
  MZ_ZIP_UNSUPPORTED_MULTIDISK,
1264
  MZ_ZIP_DECOMPRESSION_FAILED,
1265
  MZ_ZIP_COMPRESSION_FAILED,
1266
  MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE,
1267
  MZ_ZIP_CRC_CHECK_FAILED,
1268
  MZ_ZIP_UNSUPPORTED_CDIR_SIZE,
1269
  MZ_ZIP_ALLOC_FAILED,
1270
  MZ_ZIP_FILE_OPEN_FAILED,
1271
  MZ_ZIP_FILE_CREATE_FAILED,
1272
  MZ_ZIP_FILE_WRITE_FAILED,
1273
  MZ_ZIP_FILE_READ_FAILED,
1274
  MZ_ZIP_FILE_CLOSE_FAILED,
1275
  MZ_ZIP_FILE_SEEK_FAILED,
1276
  MZ_ZIP_FILE_STAT_FAILED,
1277
  MZ_ZIP_INVALID_PARAMETER,
1278
  MZ_ZIP_INVALID_FILENAME,
1279
  MZ_ZIP_BUF_TOO_SMALL,
1280
  MZ_ZIP_INTERNAL_ERROR,
1281
  MZ_ZIP_FILE_NOT_FOUND,
1282
  MZ_ZIP_ARCHIVE_TOO_LARGE,
1283
  MZ_ZIP_VALIDATION_FAILED,
1284
  MZ_ZIP_WRITE_CALLBACK_FAILED,
1285
  MZ_ZIP_TOTAL_ERRORS
1286
} mz_zip_error;
1287
1288
typedef struct {
1289
  mz_uint64 m_archive_size;
1290
  mz_uint64 m_central_directory_file_ofs;
1291
1292
  /* We only support up to UINT32_MAX files in zip64 mode. */
1293
  mz_uint32 m_total_files;
1294
  mz_zip_mode m_zip_mode;
1295
  mz_zip_type m_zip_type;
1296
  mz_zip_error m_last_error;
1297
1298
  mz_uint64 m_file_offset_alignment;
1299
1300
  mz_alloc_func m_pAlloc;
1301
  mz_free_func m_pFree;
1302
  mz_realloc_func m_pRealloc;
1303
  void *m_pAlloc_opaque;
1304
1305
  mz_file_read_func m_pRead;
1306
  mz_file_write_func m_pWrite;
1307
  mz_file_needs_keepalive m_pNeeds_keepalive;
1308
  void *m_pIO_opaque;
1309
1310
  mz_zip_internal_state *m_pState;
1311
1312
} mz_zip_archive;
1313
1314
typedef struct {
1315
  mz_zip_archive *pZip;
1316
  mz_uint flags;
1317
1318
  int status;
1319
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
1320
  mz_uint file_crc32;
1321
#endif
1322
  mz_uint64 read_buf_size, read_buf_ofs, read_buf_avail, comp_remaining,
1323
      out_buf_ofs, cur_file_ofs;
1324
  mz_zip_archive_file_stat file_stat;
1325
  void *pRead_buf;
1326
  void *pWrite_buf;
1327
1328
  size_t out_blk_remain;
1329
1330
  tinfl_decompressor inflator;
1331
1332
} mz_zip_reader_extract_iter_state;
1333
1334
/* -------- ZIP reading */
1335
1336
/* Inits a ZIP archive reader. */
1337
/* These functions read and validate the archive's central directory. */
1338
MINIZ_EXPORT mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
1339
                                        mz_uint flags);
1340
1341
MINIZ_EXPORT mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip,
1342
                                            const void *pMem, size_t size,
1343
                                            mz_uint flags);
1344
1345
#ifndef MINIZ_NO_STDIO
1346
/* Read a archive from a disk file. */
1347
/* file_start_ofs is the file offset where the archive actually begins, or 0. */
1348
/* actual_archive_size is the true total size of the archive, which may be
1349
 * smaller than the file's actual size on disk. If zero the entire file is
1350
 * treated as the archive. */
1351
MINIZ_EXPORT mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip,
1352
                                             const char *pFilename,
1353
                                             mz_uint32 flags);
1354
MINIZ_EXPORT mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip,
1355
                                                const char *pFilename,
1356
                                                mz_uint flags,
1357
                                                mz_uint64 file_start_ofs,
1358
                                                mz_uint64 archive_size);
1359
1360
/* Read an archive from an already opened FILE, beginning at the current file
1361
 * position. */
1362
/* The archive is assumed to be archive_size bytes long. If archive_size is 0,
1363
 * then the entire rest of the file is assumed to contain the archive. */
1364
/* The FILE will NOT be closed when mz_zip_reader_end() is called. */
1365
MINIZ_EXPORT mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip,
1366
                                              MZ_FILE *pFile,
1367
                                              mz_uint64 archive_size,
1368
                                              mz_uint flags);
1369
#endif
1370
1371
/* Ends archive reading, freeing all allocations, and closing the input archive
1372
 * file if mz_zip_reader_init_file() was used. */
1373
MINIZ_EXPORT mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
1374
1375
/* -------- ZIP reading or writing */
1376
1377
/* Clears a mz_zip_archive struct to all zeros. */
1378
/* Important: This must be done before passing the struct to any mz_zip
1379
 * functions. */
1380
MINIZ_EXPORT void mz_zip_zero_struct(mz_zip_archive *pZip);
1381
1382
MINIZ_EXPORT mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip);
1383
MINIZ_EXPORT mz_zip_type mz_zip_get_type(mz_zip_archive *pZip);
1384
1385
/* Returns the total number of files in the archive. */
1386
MINIZ_EXPORT mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
1387
1388
MINIZ_EXPORT mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip);
1389
MINIZ_EXPORT mz_uint64
1390
mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip);
1391
MINIZ_EXPORT MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip);
1392
1393
/* Reads n bytes of raw archive data, starting at file offset file_ofs, to pBuf.
1394
 */
1395
MINIZ_EXPORT size_t mz_zip_read_archive_data(mz_zip_archive *pZip,
1396
                                             mz_uint64 file_ofs, void *pBuf,
1397
                                             size_t n);
1398
1399
/* All mz_zip funcs set the m_last_error field in the mz_zip_archive struct.
1400
 * These functions retrieve/manipulate this field. */
1401
/* Note that the m_last_error functionality is not thread safe. */
1402
MINIZ_EXPORT mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip,
1403
                                                mz_zip_error err_num);
1404
MINIZ_EXPORT mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip);
1405
MINIZ_EXPORT mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip);
1406
MINIZ_EXPORT mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip);
1407
MINIZ_EXPORT const char *mz_zip_get_error_string(mz_zip_error mz_err);
1408
1409
/* MZ_TRUE if the archive file entry is a directory entry. */
1410
MINIZ_EXPORT mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
1411
                                                       mz_uint file_index);
1412
1413
/* MZ_TRUE if the file is encrypted/strong encrypted. */
1414
MINIZ_EXPORT mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
1415
                                                     mz_uint file_index);
1416
1417
/* MZ_TRUE if the compression method is supported, and the file is not
1418
 * encrypted, and the file is not a compressed patch file. */
1419
MINIZ_EXPORT mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip,
1420
                                                     mz_uint file_index);
1421
1422
/* Retrieves the filename of an archive file entry. */
1423
/* Returns the number of bytes written to pFilename, or if filename_buf_size is
1424
 * 0 this function returns the number of bytes needed to fully store the
1425
 * filename. */
1426
MINIZ_EXPORT mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip,
1427
                                                mz_uint file_index,
1428
                                                char *pFilename,
1429
                                                mz_uint filename_buf_size);
1430
1431
/* Attempts to locates a file in the archive's central directory. */
1432
/* Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH */
1433
/* Returns -1 if the file cannot be found. */
1434
MINIZ_EXPORT int mz_zip_reader_locate_file(mz_zip_archive *pZip,
1435
                                           const char *pName,
1436
                                           const char *pComment, mz_uint flags);
1437
MINIZ_EXPORT mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip,
1438
                                                  const char *pName,
1439
                                                  const char *pComment,
1440
                                                  mz_uint flags,
1441
                                                  mz_uint32 *file_index);
1442
1443
/* Returns detailed information about an archive file entry. */
1444
MINIZ_EXPORT mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip,
1445
                                             mz_uint file_index,
1446
                                             mz_zip_archive_file_stat *pStat);
1447
1448
/* MZ_TRUE if the file is in zip64 format. */
1449
/* A file is considered zip64 if it contained a zip64 end of central directory
1450
 * marker, or if it contained any zip64 extended file information fields in the
1451
 * central directory. */
1452
MINIZ_EXPORT mz_bool mz_zip_is_zip64(mz_zip_archive *pZip);
1453
1454
/* Returns the total central directory size in bytes. */
1455
/* The current max supported size is <= MZ_UINT32_MAX. */
1456
MINIZ_EXPORT size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip);
1457
1458
/* Extracts a archive file to a memory buffer using no memory allocation. */
1459
/* There must be at least enough room on the stack to store the inflator's state
1460
 * (~34KB or so). */
1461
MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_mem_no_alloc(
1462
    mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size,
1463
    mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
1464
MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
1465
    mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
1466
    mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
1467
1468
/* Extracts a archive file to a memory buffer. */
1469
MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip,
1470
                                                  mz_uint file_index,
1471
                                                  void *pBuf, size_t buf_size,
1472
                                                  mz_uint flags);
1473
MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
1474
                                                       const char *pFilename,
1475
                                                       void *pBuf,
1476
                                                       size_t buf_size,
1477
                                                       mz_uint flags);
1478
1479
/* Extracts a archive file to a dynamically allocated heap buffer. */
1480
/* The memory will be allocated via the mz_zip_archive's alloc/realloc
1481
 * functions. */
1482
/* Returns NULL and sets the last error on failure. */
1483
MINIZ_EXPORT void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip,
1484
                                                 mz_uint file_index,
1485
                                                 size_t *pSize, mz_uint flags);
1486
MINIZ_EXPORT void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
1487
                                                      const char *pFilename,
1488
                                                      size_t *pSize,
1489
                                                      mz_uint flags);
1490
1491
/* Extracts a archive file using a callback function to output the file's data.
1492
 */
1493
MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_callback(
1494
    mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback,
1495
    void *pOpaque, mz_uint flags);
1496
MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_callback(
1497
    mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback,
1498
    void *pOpaque, mz_uint flags);
1499
1500
/* Extract a file iteratively */
1501
MINIZ_EXPORT mz_zip_reader_extract_iter_state *
1502
mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index,
1503
                               mz_uint flags);
1504
MINIZ_EXPORT mz_zip_reader_extract_iter_state *
1505
mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename,
1506
                                    mz_uint flags);
1507
MINIZ_EXPORT size_t mz_zip_reader_extract_iter_read(
1508
    mz_zip_reader_extract_iter_state *pState, void *pvBuf, size_t buf_size);
1509
MINIZ_EXPORT mz_bool
1510
mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state *pState);
1511
1512
#ifndef MINIZ_NO_STDIO
1513
/* Extracts a archive file to a disk file and sets its last accessed and
1514
 * modified times. */
1515
/* This function only extracts files, not archive directory records. */
1516
MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip,
1517
                                                   mz_uint file_index,
1518
                                                   const char *pDst_filename,
1519
                                                   mz_uint flags);
1520
MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_file(
1521
    mz_zip_archive *pZip, const char *pArchive_filename,
1522
    const char *pDst_filename, mz_uint flags);
1523
1524
/* Extracts a archive file starting at the current position in the destination
1525
 * FILE stream. */
1526
MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip,
1527
                                                    mz_uint file_index,
1528
                                                    MZ_FILE *File,
1529
                                                    mz_uint flags);
1530
MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_cfile(
1531
    mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile,
1532
    mz_uint flags);
1533
#endif
1534
1535
#if 0
1536
/* TODO */
1537
  typedef void *mz_zip_streaming_extract_state_ptr;
1538
  mz_zip_streaming_extract_state_ptr mz_zip_streaming_extract_begin(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags);
1539
  uint64_t mz_zip_streaming_extract_get_size(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState);
1540
  uint64_t mz_zip_streaming_extract_get_cur_ofs(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState);
1541
  mz_bool mz_zip_streaming_extract_seek(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, uint64_t new_ofs);
1542
  size_t mz_zip_streaming_extract_read(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, void *pBuf, size_t buf_size);
1543
  mz_bool mz_zip_streaming_extract_end(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState);
1544
#endif
1545
1546
/* This function compares the archive's local headers, the optional local zip64
1547
 * extended information block, and the optional descriptor following the
1548
 * compressed data vs. the data in the central directory. */
1549
/* It also validates that each file can be successfully uncompressed unless the
1550
 * MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY is specified. */
1551
MINIZ_EXPORT mz_bool mz_zip_validate_file(mz_zip_archive *pZip,
1552
                                          mz_uint file_index, mz_uint flags);
1553
1554
/* Validates an entire archive by calling mz_zip_validate_file() on each file.
1555
 */
1556
MINIZ_EXPORT mz_bool mz_zip_validate_archive(mz_zip_archive *pZip,
1557
                                             mz_uint flags);
1558
1559
/* Misc utils/helpers, valid for ZIP reading or writing */
1560
MINIZ_EXPORT mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size,
1561
                                                 mz_uint flags,
1562
                                                 mz_zip_error *pErr);
1563
MINIZ_EXPORT mz_bool mz_zip_validate_file_archive(const char *pFilename,
1564
                                                  mz_uint flags,
1565
                                                  mz_zip_error *pErr);
1566
1567
/* Universal end function - calls either mz_zip_reader_end() or
1568
 * mz_zip_writer_end(). */
1569
MINIZ_EXPORT mz_bool mz_zip_end(mz_zip_archive *pZip);
1570
1571
/* -------- ZIP writing */
1572
1573
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
1574
1575
/* Inits a ZIP archive writer. */
1576
/*Set pZip->m_pWrite (and pZip->m_pIO_opaque) before calling mz_zip_writer_init
1577
 * or mz_zip_writer_init_v2*/
1578
/*The output is streamable, i.e. file_ofs in mz_file_write_func always increases
1579
 * only by n*/
1580
MINIZ_EXPORT mz_bool mz_zip_writer_init(mz_zip_archive *pZip,
1581
                                        mz_uint64 existing_size);
1582
MINIZ_EXPORT mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip,
1583
                                           mz_uint64 existing_size,
1584
                                           mz_uint flags);
1585
1586
MINIZ_EXPORT mz_bool mz_zip_writer_init_heap(
1587
    mz_zip_archive *pZip, size_t size_to_reserve_at_beginning,
1588
    size_t initial_allocation_size);
1589
MINIZ_EXPORT mz_bool mz_zip_writer_init_heap_v2(
1590
    mz_zip_archive *pZip, size_t size_to_reserve_at_beginning,
1591
    size_t initial_allocation_size, mz_uint flags);
1592
1593
#ifndef MINIZ_NO_STDIO
1594
MINIZ_EXPORT mz_bool
1595
mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
1596
                        mz_uint64 size_to_reserve_at_beginning);
1597
MINIZ_EXPORT mz_bool mz_zip_writer_init_file_v2(
1598
    mz_zip_archive *pZip, const char *pFilename,
1599
    mz_uint64 size_to_reserve_at_beginning, mz_uint flags);
1600
MINIZ_EXPORT mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip,
1601
                                              MZ_FILE *pFile, mz_uint flags);
1602
#endif
1603
1604
/* Converts a ZIP archive reader object into a writer object, to allow efficient
1605
 * in-place file appends to occur on an existing archive. */
1606
/* For archives opened using mz_zip_reader_init_file, pFilename must be the
1607
 * archive's filename so it can be reopened for writing. If the file can't be
1608
 * reopened, mz_zip_reader_end() will be called. */
1609
/* For archives opened using mz_zip_reader_init_mem, the memory block must be
1610
 * growable using the realloc callback (which defaults to realloc unless you've
1611
 * overridden it). */
1612
/* Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's
1613
 * user provided m_pWrite function cannot be NULL. */
1614
/* Note: In-place archive modification is not recommended unless you know what
1615
 * you're doing, because if execution stops or something goes wrong before */
1616
/* the archive is finalized the file's central directory will be hosed. */
1617
MINIZ_EXPORT mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
1618
                                                    const char *pFilename);
1619
MINIZ_EXPORT mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip,
1620
                                                       const char *pFilename,
1621
                                                       mz_uint flags);
1622
1623
/* Adds the contents of a memory buffer to an archive. These functions record
1624
 * the current local time into the archive. */
1625
/* To add a directory entry, call this method with an archive name ending in a
1626
 * forwardslash with an empty buffer. */
1627
/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED,
1628
 * MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or
1629
 * just set to MZ_DEFAULT_COMPRESSION. */
1630
MINIZ_EXPORT mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip,
1631
                                           const char *pArchive_name,
1632
                                           const void *pBuf, size_t buf_size,
1633
                                           mz_uint level_and_flags);
1634
1635
/* Like mz_zip_writer_add_mem(), except you can specify a file comment field,
1636
 * and optionally supply the function with already compressed data. */
1637
/* uncomp_size/uncomp_crc32 are only used if the MZ_ZIP_FLAG_COMPRESSED_DATA
1638
 * flag is specified. */
1639
MINIZ_EXPORT mz_bool mz_zip_writer_add_mem_ex(
1640
    mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf,
1641
    size_t buf_size, const void *pComment, mz_uint16 comment_size,
1642
    mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);
1643
1644
MINIZ_EXPORT mz_bool mz_zip_writer_add_mem_ex_v2(
1645
    mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf,
1646
    size_t buf_size, const void *pComment, mz_uint16 comment_size,
1647
    mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32,
1648
    MZ_TIME_T *last_modified, const char *user_extra_data_local,
1649
    mz_uint user_extra_data_local_len, const char *user_extra_data_central,
1650
    mz_uint user_extra_data_central_len);
1651
1652
/* Adds the contents of a file to an archive. This function also records the
1653
 * disk file's modified time into the archive. */
1654
/* File data is supplied via a read callback function. User
1655
 * mz_zip_writer_add_(c)file to add a file directly.*/
1656
MINIZ_EXPORT mz_bool mz_zip_writer_add_read_buf_callback(
1657
    mz_zip_archive *pZip, const char *pArchive_name,
1658
    mz_file_read_func read_callback, void *callback_opaque, mz_uint64 max_size,
1659
    const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size,
1660
    mz_uint level_and_flags, mz_uint32 ext_attributes,
1661
    const char *user_extra_data_local, mz_uint user_extra_data_local_len,
1662
    const char *user_extra_data_central, mz_uint user_extra_data_central_len);
1663
1664
#ifndef MINIZ_NO_STDIO
1665
/* Adds the contents of a disk file to an archive. This function also records
1666
 * the disk file's modified time into the archive. */
1667
/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED,
1668
 * MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or
1669
 * just set to MZ_DEFAULT_COMPRESSION. */
1670
MINIZ_EXPORT mz_bool mz_zip_writer_add_file(
1671
    mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename,
1672
    const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
1673
    mz_uint32 ext_attributes);
1674
1675
/* Like mz_zip_writer_add_file(), except the file data is read from the
1676
 * specified FILE stream. */
1677
MINIZ_EXPORT mz_bool mz_zip_writer_add_cfile(
1678
    mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file,
1679
    mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment,
1680
    mz_uint16 comment_size, mz_uint level_and_flags, mz_uint32 ext_attributes,
1681
    const char *user_extra_data_local, mz_uint user_extra_data_local_len,
1682
    const char *user_extra_data_central, mz_uint user_extra_data_central_len);
1683
#endif
1684
1685
/* Adds a file to an archive by fully cloning the data from another archive. */
1686
/* This function fully clones the source file's compressed data (no
1687
 * recompression), along with its full filename, extra data (it may add or
1688
 * modify the zip64 local header extra data field), and the optional descriptor
1689
 * following the compressed data. */
1690
MINIZ_EXPORT mz_bool mz_zip_writer_add_from_zip_reader(
1691
    mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index);
1692
1693
/* Finalizes the archive by writing the central directory records followed by
1694
 * the end of central directory record. */
1695
/* After an archive is finalized, the only valid call on the mz_zip_archive
1696
 * struct is mz_zip_writer_end(). */
1697
/* An archive must be manually finalized by calling this function for it to be
1698
 * valid. */
1699
MINIZ_EXPORT mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
1700
1701
/* Finalizes a heap archive, returning a poiner to the heap block and its size.
1702
 */
1703
/* The heap block will be allocated using the mz_zip_archive's alloc/realloc
1704
 * callbacks. */
1705
MINIZ_EXPORT mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip,
1706
                                                         void **ppBuf,
1707
                                                         size_t *pSize);
1708
1709
/* Ends archive writing, freeing all allocations, and closing the output file if
1710
 * mz_zip_writer_init_file() was used. */
1711
/* Note for the archive to be valid, it *must* have been finalized before ending
1712
 * (this function will not do it for you). */
1713
MINIZ_EXPORT mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
1714
1715
/* -------- Misc. high-level helper functions: */
1716
1717
/* mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically)
1718
 * appends a memory blob to a ZIP archive. */
1719
/* Note this is NOT a fully safe operation. If it crashes or dies in some way
1720
 * your archive can be left in a screwed up state (without a central directory).
1721
 */
1722
/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED,
1723
 * MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or
1724
 * just set to MZ_DEFAULT_COMPRESSION. */
1725
/* TODO: Perhaps add an option to leave the existing central dir in place in
1726
 * case the add dies? We could then truncate the file (so the old central dir
1727
 * would be at the end) if something goes wrong. */
1728
MINIZ_EXPORT mz_bool mz_zip_add_mem_to_archive_file_in_place(
1729
    const char *pZip_filename, const char *pArchive_name, const void *pBuf,
1730
    size_t buf_size, const void *pComment, mz_uint16 comment_size,
1731
    mz_uint level_and_flags);
1732
MINIZ_EXPORT mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(
1733
    const char *pZip_filename, const char *pArchive_name, const void *pBuf,
1734
    size_t buf_size, const void *pComment, mz_uint16 comment_size,
1735
    mz_uint level_and_flags, mz_zip_error *pErr);
1736
1737
/* Reads a single file from an archive into a heap block. */
1738
/* If pComment is not NULL, only the file with the specified comment will be
1739
 * extracted. */
1740
/* Returns NULL on failure. */
1741
MINIZ_EXPORT void *
1742
mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
1743
                                    const char *pArchive_name, size_t *pSize,
1744
                                    mz_uint flags);
1745
MINIZ_EXPORT void *mz_zip_extract_archive_file_to_heap_v2(
1746
    const char *pZip_filename, const char *pArchive_name, const char *pComment,
1747
    size_t *pSize, mz_uint flags, mz_zip_error *pErr);
1748
1749
#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */
1750
1751
#ifdef __cplusplus
1752
}
1753
#endif
1754
1755
#endif /* MINIZ_NO_ARCHIVE_APIS */
1756
1757
#ifndef MINIZ_HEADER_FILE_ONLY
1758
/**************************************************************************
1759
 *
1760
 * Copyright 2013-2014 RAD Game Tools and Valve Software
1761
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
1762
 * All Rights Reserved.
1763
 *
1764
 * Permission is hereby granted, free of charge, to any person obtaining a copy
1765
 * of this software and associated documentation files (the "Software"), to deal
1766
 * in the Software without restriction, including without limitation the rights
1767
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1768
 * copies of the Software, and to permit persons to whom the Software is
1769
 * furnished to do so, subject to the following conditions:
1770
 *
1771
 * The above copyright notice and this permission notice shall be included in
1772
 * all copies or substantial portions of the Software.
1773
 *
1774
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1775
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1776
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1777
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1778
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1779
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1780
 * THE SOFTWARE.
1781
 *
1782
 **************************************************************************/
1783
1784
typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
1785
typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
1786
typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
1787
1788
#ifdef __cplusplus
1789
extern "C" {
1790
#endif
1791
1792
/* ------------------- zlib-style API's */
1793
1794
0
mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) {
1795
0
  mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
1796
0
  size_t block_len = buf_len % 5552;
1797
0
  if (!ptr)
1798
0
    return MZ_ADLER32_INIT;
1799
0
  while (buf_len) {
1800
0
    for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
1801
0
      s1 += ptr[0], s2 += s1;
1802
0
      s1 += ptr[1], s2 += s1;
1803
0
      s1 += ptr[2], s2 += s1;
1804
0
      s1 += ptr[3], s2 += s1;
1805
0
      s1 += ptr[4], s2 += s1;
1806
0
      s1 += ptr[5], s2 += s1;
1807
0
      s1 += ptr[6], s2 += s1;
1808
0
      s1 += ptr[7], s2 += s1;
1809
0
    }
1810
0
    for (; i < block_len; ++i)
1811
0
      s1 += *ptr++, s2 += s1;
1812
0
    s1 %= 65521U, s2 %= 65521U;
1813
0
    buf_len -= block_len;
1814
0
    block_len = 5552;
1815
0
  }
1816
0
  return (s2 << 16) + s1;
1817
0
}
1818
1819
/* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C
1820
 * implementation that balances processor cache usage against speed":
1821
 * http://www.geocities.com/malbrain/ */
1822
#if 0
1823
    mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
1824
    {
1825
        static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1826
                                               0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
1827
        mz_uint32 crcu32 = (mz_uint32)crc;
1828
        if (!ptr)
1829
            return MZ_CRC32_INIT;
1830
        crcu32 = ~crcu32;
1831
        while (buf_len--)
1832
        {
1833
            mz_uint8 b = *ptr++;
1834
            crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
1835
            crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
1836
        }
1837
        return ~crcu32;
1838
    }
1839
#elif defined(USE_EXTERNAL_MZCRC)
1840
/* If USE_EXTERNAL_CRC is defined, an external module will export the
1841
 * mz_crc32() symbol for us to use, e.g. an SSE-accelerated version.
1842
 * Depending on the impl, it may be necessary to ~ the input/output crc values.
1843
 */
1844
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len);
1845
#else
1846
/* Faster, but larger CPU cache footprint.
1847
 */
1848
0
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) {
1849
0
  static const mz_uint32 s_crc_table[256] = {
1850
0
      0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
1851
0
      0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
1852
0
      0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
1853
0
      0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
1854
0
      0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
1855
0
      0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
1856
0
      0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
1857
0
      0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
1858
0
      0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
1859
0
      0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
1860
0
      0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
1861
0
      0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
1862
0
      0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
1863
0
      0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
1864
0
      0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
1865
0
      0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
1866
0
      0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
1867
0
      0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
1868
0
      0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
1869
0
      0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
1870
0
      0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
1871
0
      0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
1872
0
      0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
1873
0
      0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
1874
0
      0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
1875
0
      0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
1876
0
      0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
1877
0
      0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
1878
0
      0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
1879
0
      0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
1880
0
      0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
1881
0
      0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1882
0
      0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
1883
0
      0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
1884
0
      0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
1885
0
      0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1886
0
      0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
1887
0
      0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
1888
0
      0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
1889
0
      0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1890
0
      0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
1891
0
      0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
1892
0
      0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D};
1893
1894
0
  mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
1895
0
  const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
1896
1897
0
  while (buf_len >= 4) {
1898
0
    crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
1899
0
    crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
1900
0
    crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
1901
0
    crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
1902
0
    pByte_buf += 4;
1903
0
    buf_len -= 4;
1904
0
  }
1905
1906
0
  while (buf_len) {
1907
0
    crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
1908
0
    ++pByte_buf;
1909
0
    --buf_len;
1910
0
  }
1911
1912
0
  return ~crc32;
1913
0
}
1914
#endif
1915
1916
0
void mz_free(void *p) { MZ_FREE(p); }
1917
1918
MINIZ_EXPORT void *miniz_def_alloc_func(void *opaque, size_t items,
1919
0
                                        size_t size) {
1920
0
  (void)opaque, (void)items, (void)size;
1921
0
  return MZ_MALLOC(items * size);
1922
0
}
1923
0
MINIZ_EXPORT void miniz_def_free_func(void *opaque, void *address) {
1924
0
  (void)opaque, (void)address;
1925
0
  MZ_FREE(address);
1926
0
}
1927
MINIZ_EXPORT void *miniz_def_realloc_func(void *opaque, void *address,
1928
0
                                          size_t items, size_t size) {
1929
0
  (void)opaque, (void)address, (void)items, (void)size;
1930
0
  return MZ_REALLOC(address, items * size);
1931
0
}
1932
1933
0
const char *mz_version(void) { return MZ_VERSION; }
1934
1935
#ifndef MINIZ_NO_ZLIB_APIS
1936
1937
0
int mz_deflateInit(mz_streamp pStream, int level) {
1938
0
  return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9,
1939
0
                         MZ_DEFAULT_STRATEGY);
1940
0
}
1941
1942
int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits,
1943
0
                    int mem_level, int strategy) {
1944
0
  tdefl_compressor *pComp;
1945
0
  mz_uint comp_flags =
1946
0
      TDEFL_COMPUTE_ADLER32 |
1947
0
      tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
1948
1949
0
  if (!pStream)
1950
0
    return MZ_STREAM_ERROR;
1951
0
  if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) ||
1952
0
      ((window_bits != MZ_DEFAULT_WINDOW_BITS) &&
1953
0
       (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
1954
0
    return MZ_PARAM_ERROR;
1955
1956
0
  pStream->data_type = 0;
1957
0
  pStream->adler = MZ_ADLER32_INIT;
1958
0
  pStream->msg = NULL;
1959
0
  pStream->reserved = 0;
1960
0
  pStream->total_in = 0;
1961
0
  pStream->total_out = 0;
1962
0
  if (!pStream->zalloc)
1963
0
    pStream->zalloc = miniz_def_alloc_func;
1964
0
  if (!pStream->zfree)
1965
0
    pStream->zfree = miniz_def_free_func;
1966
1967
0
  pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1,
1968
0
                                              sizeof(tdefl_compressor));
1969
0
  if (!pComp)
1970
0
    return MZ_MEM_ERROR;
1971
1972
0
  pStream->state = (struct mz_internal_state *)pComp;
1973
1974
0
  if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) {
1975
0
    mz_deflateEnd(pStream);
1976
0
    return MZ_PARAM_ERROR;
1977
0
  }
1978
1979
0
  return MZ_OK;
1980
0
}
1981
1982
0
int mz_deflateReset(mz_streamp pStream) {
1983
0
  if ((!pStream) || (!pStream->state) || (!pStream->zalloc) ||
1984
0
      (!pStream->zfree))
1985
0
    return MZ_STREAM_ERROR;
1986
0
  pStream->total_in = pStream->total_out = 0;
1987
0
  tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL,
1988
0
             ((tdefl_compressor *)pStream->state)->m_flags);
1989
0
  return MZ_OK;
1990
0
}
1991
1992
0
int mz_deflate(mz_streamp pStream, int flush) {
1993
0
  size_t in_bytes, out_bytes;
1994
0
  mz_ulong orig_total_in, orig_total_out;
1995
0
  int mz_status = MZ_OK;
1996
1997
0
  if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) ||
1998
0
      (!pStream->next_out))
1999
0
    return MZ_STREAM_ERROR;
2000
0
  if (!pStream->avail_out)
2001
0
    return MZ_BUF_ERROR;
2002
2003
0
  if (flush == MZ_PARTIAL_FLUSH)
2004
0
    flush = MZ_SYNC_FLUSH;
2005
2006
0
  if (((tdefl_compressor *)pStream->state)->m_prev_return_status ==
2007
0
      TDEFL_STATUS_DONE)
2008
0
    return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
2009
2010
0
  orig_total_in = pStream->total_in;
2011
0
  orig_total_out = pStream->total_out;
2012
0
  for (;;) {
2013
0
    tdefl_status defl_status;
2014
0
    in_bytes = pStream->avail_in;
2015
0
    out_bytes = pStream->avail_out;
2016
2017
0
    defl_status = tdefl_compress((tdefl_compressor *)pStream->state,
2018
0
                                 pStream->next_in, &in_bytes, pStream->next_out,
2019
0
                                 &out_bytes, (tdefl_flush)flush);
2020
0
    pStream->next_in += (mz_uint)in_bytes;
2021
0
    pStream->avail_in -= (mz_uint)in_bytes;
2022
0
    pStream->total_in += (mz_uint)in_bytes;
2023
0
    pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
2024
2025
0
    pStream->next_out += (mz_uint)out_bytes;
2026
0
    pStream->avail_out -= (mz_uint)out_bytes;
2027
0
    pStream->total_out += (mz_uint)out_bytes;
2028
2029
0
    if (defl_status < 0) {
2030
0
      mz_status = MZ_STREAM_ERROR;
2031
0
      break;
2032
0
    } else if (defl_status == TDEFL_STATUS_DONE) {
2033
0
      mz_status = MZ_STREAM_END;
2034
0
      break;
2035
0
    } else if (!pStream->avail_out)
2036
0
      break;
2037
0
    else if ((!pStream->avail_in) && (flush != MZ_FINISH)) {
2038
0
      if ((flush) || (pStream->total_in != orig_total_in) ||
2039
0
          (pStream->total_out != orig_total_out))
2040
0
        break;
2041
0
      return MZ_BUF_ERROR; /* Can't make forward progress without some input.
2042
                            */
2043
0
    }
2044
0
  }
2045
0
  return mz_status;
2046
0
}
2047
2048
0
int mz_deflateEnd(mz_streamp pStream) {
2049
0
  if (!pStream)
2050
0
    return MZ_STREAM_ERROR;
2051
0
  if (pStream->state) {
2052
0
    pStream->zfree(pStream->opaque, pStream->state);
2053
0
    pStream->state = NULL;
2054
0
  }
2055
0
  return MZ_OK;
2056
0
}
2057
2058
0
mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) {
2059
0
  (void)pStream;
2060
  /* This is really over conservative. (And lame, but it's actually pretty
2061
   * tricky to compute a true upper bound given the way tdefl's blocking works.)
2062
   */
2063
0
  return MZ_MAX(128 + (source_len * 110) / 100,
2064
0
                128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
2065
0
}
2066
2067
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len,
2068
0
                 const unsigned char *pSource, mz_ulong source_len, int level) {
2069
0
  int status;
2070
0
  mz_stream stream;
2071
0
  memset(&stream, 0, sizeof(stream));
2072
2073
  /* In case mz_ulong is 64-bits (argh I hate longs). */
2074
0
  if ((source_len | *pDest_len) > 0xFFFFFFFFU)
2075
0
    return MZ_PARAM_ERROR;
2076
2077
0
  stream.next_in = pSource;
2078
0
  stream.avail_in = (mz_uint32)source_len;
2079
0
  stream.next_out = pDest;
2080
0
  stream.avail_out = (mz_uint32)*pDest_len;
2081
2082
0
  status = mz_deflateInit(&stream, level);
2083
0
  if (status != MZ_OK)
2084
0
    return status;
2085
2086
0
  status = mz_deflate(&stream, MZ_FINISH);
2087
0
  if (status != MZ_STREAM_END) {
2088
0
    mz_deflateEnd(&stream);
2089
0
    return (status == MZ_OK) ? MZ_BUF_ERROR : status;
2090
0
  }
2091
2092
0
  *pDest_len = stream.total_out;
2093
0
  return mz_deflateEnd(&stream);
2094
0
}
2095
2096
int mz_compress(unsigned char *pDest, mz_ulong *pDest_len,
2097
0
                const unsigned char *pSource, mz_ulong source_len) {
2098
0
  return mz_compress2(pDest, pDest_len, pSource, source_len,
2099
0
                      MZ_DEFAULT_COMPRESSION);
2100
0
}
2101
2102
0
mz_ulong mz_compressBound(mz_ulong source_len) {
2103
0
  return mz_deflateBound(NULL, source_len);
2104
0
}
2105
2106
typedef struct {
2107
  tinfl_decompressor m_decomp;
2108
  mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
2109
  int m_window_bits;
2110
  mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
2111
  tinfl_status m_last_status;
2112
} inflate_state;
2113
2114
0
int mz_inflateInit2(mz_streamp pStream, int window_bits) {
2115
0
  inflate_state *pDecomp;
2116
0
  if (!pStream)
2117
0
    return MZ_STREAM_ERROR;
2118
0
  if ((window_bits != MZ_DEFAULT_WINDOW_BITS) &&
2119
0
      (-window_bits != MZ_DEFAULT_WINDOW_BITS))
2120
0
    return MZ_PARAM_ERROR;
2121
2122
0
  pStream->data_type = 0;
2123
0
  pStream->adler = 0;
2124
0
  pStream->msg = NULL;
2125
0
  pStream->total_in = 0;
2126
0
  pStream->total_out = 0;
2127
0
  pStream->reserved = 0;
2128
0
  if (!pStream->zalloc)
2129
0
    pStream->zalloc = miniz_def_alloc_func;
2130
0
  if (!pStream->zfree)
2131
0
    pStream->zfree = miniz_def_free_func;
2132
2133
0
  pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1,
2134
0
                                             sizeof(inflate_state));
2135
0
  if (!pDecomp)
2136
0
    return MZ_MEM_ERROR;
2137
2138
0
  pStream->state = (struct mz_internal_state *)pDecomp;
2139
2140
0
  tinfl_init(&pDecomp->m_decomp);
2141
0
  pDecomp->m_dict_ofs = 0;
2142
0
  pDecomp->m_dict_avail = 0;
2143
0
  pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
2144
0
  pDecomp->m_first_call = 1;
2145
0
  pDecomp->m_has_flushed = 0;
2146
0
  pDecomp->m_window_bits = window_bits;
2147
2148
0
  return MZ_OK;
2149
0
}
2150
2151
0
int mz_inflateInit(mz_streamp pStream) {
2152
0
  return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
2153
0
}
2154
2155
0
int mz_inflateReset(mz_streamp pStream) {
2156
0
  inflate_state *pDecomp;
2157
0
  if (!pStream)
2158
0
    return MZ_STREAM_ERROR;
2159
2160
0
  pStream->data_type = 0;
2161
0
  pStream->adler = 0;
2162
0
  pStream->msg = NULL;
2163
0
  pStream->total_in = 0;
2164
0
  pStream->total_out = 0;
2165
0
  pStream->reserved = 0;
2166
2167
0
  pDecomp = (inflate_state *)pStream->state;
2168
2169
0
  tinfl_init(&pDecomp->m_decomp);
2170
0
  pDecomp->m_dict_ofs = 0;
2171
0
  pDecomp->m_dict_avail = 0;
2172
0
  pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
2173
0
  pDecomp->m_first_call = 1;
2174
0
  pDecomp->m_has_flushed = 0;
2175
0
  /* pDecomp->m_window_bits = window_bits */;
2176
2177
0
  return MZ_OK;
2178
0
}
2179
2180
0
int mz_inflate(mz_streamp pStream, int flush) {
2181
0
  inflate_state *pState;
2182
0
  mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
2183
0
  size_t in_bytes, out_bytes, orig_avail_in;
2184
0
  tinfl_status status;
2185
2186
0
  if ((!pStream) || (!pStream->state))
2187
0
    return MZ_STREAM_ERROR;
2188
0
  if (flush == MZ_PARTIAL_FLUSH)
2189
0
    flush = MZ_SYNC_FLUSH;
2190
0
  if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
2191
0
    return MZ_STREAM_ERROR;
2192
2193
0
  pState = (inflate_state *)pStream->state;
2194
0
  if (pState->m_window_bits > 0)
2195
0
    decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
2196
0
  orig_avail_in = pStream->avail_in;
2197
2198
0
  first_call = pState->m_first_call;
2199
0
  pState->m_first_call = 0;
2200
0
  if (pState->m_last_status < 0)
2201
0
    return MZ_DATA_ERROR;
2202
2203
0
  if (pState->m_has_flushed && (flush != MZ_FINISH))
2204
0
    return MZ_STREAM_ERROR;
2205
0
  pState->m_has_flushed |= (flush == MZ_FINISH);
2206
2207
0
  if ((flush == MZ_FINISH) && (first_call)) {
2208
    /* MZ_FINISH on the first call implies that the input and output buffers are
2209
     * large enough to hold the entire compressed/decompressed file. */
2210
0
    decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
2211
0
    in_bytes = pStream->avail_in;
2212
0
    out_bytes = pStream->avail_out;
2213
0
    status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes,
2214
0
                              pStream->next_out, pStream->next_out, &out_bytes,
2215
0
                              decomp_flags);
2216
0
    pState->m_last_status = status;
2217
0
    pStream->next_in += (mz_uint)in_bytes;
2218
0
    pStream->avail_in -= (mz_uint)in_bytes;
2219
0
    pStream->total_in += (mz_uint)in_bytes;
2220
0
    pStream->adler = tinfl_get_adler32(&pState->m_decomp);
2221
0
    pStream->next_out += (mz_uint)out_bytes;
2222
0
    pStream->avail_out -= (mz_uint)out_bytes;
2223
0
    pStream->total_out += (mz_uint)out_bytes;
2224
2225
0
    if (status < 0)
2226
0
      return MZ_DATA_ERROR;
2227
0
    else if (status != TINFL_STATUS_DONE) {
2228
0
      pState->m_last_status = TINFL_STATUS_FAILED;
2229
0
      return MZ_BUF_ERROR;
2230
0
    }
2231
0
    return MZ_STREAM_END;
2232
0
  }
2233
  /* flush != MZ_FINISH then we must assume there's more input. */
2234
0
  if (flush != MZ_FINISH)
2235
0
    decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
2236
2237
0
  if (pState->m_dict_avail) {
2238
0
    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
2239
0
    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
2240
0
    pStream->next_out += n;
2241
0
    pStream->avail_out -= n;
2242
0
    pStream->total_out += n;
2243
0
    pState->m_dict_avail -= n;
2244
0
    pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
2245
0
    return ((pState->m_last_status == TINFL_STATUS_DONE) &&
2246
0
            (!pState->m_dict_avail))
2247
0
               ? MZ_STREAM_END
2248
0
               : MZ_OK;
2249
0
  }
2250
2251
0
  for (;;) {
2252
0
    in_bytes = pStream->avail_in;
2253
0
    out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
2254
2255
0
    status = tinfl_decompress(
2256
0
        &pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict,
2257
0
        pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
2258
0
    pState->m_last_status = status;
2259
2260
0
    pStream->next_in += (mz_uint)in_bytes;
2261
0
    pStream->avail_in -= (mz_uint)in_bytes;
2262
0
    pStream->total_in += (mz_uint)in_bytes;
2263
0
    pStream->adler = tinfl_get_adler32(&pState->m_decomp);
2264
2265
0
    pState->m_dict_avail = (mz_uint)out_bytes;
2266
2267
0
    n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
2268
0
    memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
2269
0
    pStream->next_out += n;
2270
0
    pStream->avail_out -= n;
2271
0
    pStream->total_out += n;
2272
0
    pState->m_dict_avail -= n;
2273
0
    pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
2274
2275
0
    if (status < 0)
2276
0
      return MZ_DATA_ERROR; /* Stream is corrupted (there could be some
2277
                               uncompressed data left in the output dictionary -
2278
                               oh well). */
2279
0
    else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
2280
0
      return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress
2281
                              without supplying more input or by setting flush
2282
                              to MZ_FINISH. */
2283
0
    else if (flush == MZ_FINISH) {
2284
      /* The output buffer MUST be large to hold the remaining uncompressed data
2285
       * when flush==MZ_FINISH. */
2286
0
      if (status == TINFL_STATUS_DONE)
2287
0
        return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
2288
      /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's
2289
       * at least 1 more byte on the way. If there's no more room left in the
2290
       * output buffer then something is wrong. */
2291
0
      else if (!pStream->avail_out)
2292
0
        return MZ_BUF_ERROR;
2293
0
    } else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) ||
2294
0
               (!pStream->avail_out) || (pState->m_dict_avail))
2295
0
      break;
2296
0
  }
2297
2298
0
  return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail))
2299
0
             ? MZ_STREAM_END
2300
0
             : MZ_OK;
2301
0
}
2302
2303
0
int mz_inflateEnd(mz_streamp pStream) {
2304
0
  if (!pStream)
2305
0
    return MZ_STREAM_ERROR;
2306
0
  if (pStream->state) {
2307
0
    pStream->zfree(pStream->opaque, pStream->state);
2308
0
    pStream->state = NULL;
2309
0
  }
2310
0
  return MZ_OK;
2311
0
}
2312
int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len,
2313
0
                   const unsigned char *pSource, mz_ulong *pSource_len) {
2314
0
  mz_stream stream;
2315
0
  int status;
2316
0
  memset(&stream, 0, sizeof(stream));
2317
2318
  /* In case mz_ulong is 64-bits (argh I hate longs). */
2319
0
  if ((*pSource_len | *pDest_len) > 0xFFFFFFFFU)
2320
0
    return MZ_PARAM_ERROR;
2321
2322
0
  stream.next_in = pSource;
2323
0
  stream.avail_in = (mz_uint32)*pSource_len;
2324
0
  stream.next_out = pDest;
2325
0
  stream.avail_out = (mz_uint32)*pDest_len;
2326
2327
0
  status = mz_inflateInit(&stream);
2328
0
  if (status != MZ_OK)
2329
0
    return status;
2330
2331
0
  status = mz_inflate(&stream, MZ_FINISH);
2332
0
  *pSource_len = *pSource_len - stream.avail_in;
2333
0
  if (status != MZ_STREAM_END) {
2334
0
    mz_inflateEnd(&stream);
2335
0
    return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR
2336
0
                                                            : status;
2337
0
  }
2338
0
  *pDest_len = stream.total_out;
2339
2340
0
  return mz_inflateEnd(&stream);
2341
0
}
2342
2343
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len,
2344
0
                  const unsigned char *pSource, mz_ulong source_len) {
2345
0
  return mz_uncompress2(pDest, pDest_len, pSource, &source_len);
2346
0
}
2347
2348
0
const char *mz_error(int err) {
2349
0
  static struct {
2350
0
    int m_err;
2351
0
    const char *m_pDesc;
2352
0
  } s_error_descs[] = {{MZ_OK, ""},
2353
0
                       {MZ_STREAM_END, "stream end"},
2354
0
                       {MZ_NEED_DICT, "need dictionary"},
2355
0
                       {MZ_ERRNO, "file error"},
2356
0
                       {MZ_STREAM_ERROR, "stream error"},
2357
0
                       {MZ_DATA_ERROR, "data error"},
2358
0
                       {MZ_MEM_ERROR, "out of memory"},
2359
0
                       {MZ_BUF_ERROR, "buf error"},
2360
0
                       {MZ_VERSION_ERROR, "version error"},
2361
0
                       {MZ_PARAM_ERROR, "parameter error"}};
2362
0
  mz_uint i;
2363
0
  for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
2364
0
    if (s_error_descs[i].m_err == err)
2365
0
      return s_error_descs[i].m_pDesc;
2366
0
  return NULL;
2367
0
}
2368
2369
#endif /*MINIZ_NO_ZLIB_APIS */
2370
2371
#ifdef __cplusplus
2372
}
2373
#endif
2374
2375
/*
2376
  This is free and unencumbered software released into the public domain.
2377
2378
  Anyone is free to copy, modify, publish, use, compile, sell, or
2379
  distribute this software, either in source code form or as a compiled
2380
  binary, for any purpose, commercial or non-commercial, and by any
2381
  means.
2382
2383
  In jurisdictions that recognize copyright laws, the author or authors
2384
  of this software dedicate any and all copyright interest in the
2385
  software to the public domain. We make this dedication for the benefit
2386
  of the public at large and to the detriment of our heirs and
2387
  successors. We intend this dedication to be an overt act of
2388
  relinquishment in perpetuity of all present and future rights to this
2389
  software under copyright law.
2390
2391
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2392
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2393
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2394
  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
2395
  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2396
  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2397
  OTHER DEALINGS IN THE SOFTWARE.
2398
2399
  For more information, please refer to <http://unlicense.org/>
2400
*/
2401
/**************************************************************************
2402
 *
2403
 * Copyright 2013-2014 RAD Game Tools and Valve Software
2404
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
2405
 * All Rights Reserved.
2406
 *
2407
 * Permission is hereby granted, free of charge, to any person obtaining a copy
2408
 * of this software and associated documentation files (the "Software"), to deal
2409
 * in the Software without restriction, including without limitation the rights
2410
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2411
 * copies of the Software, and to permit persons to whom the Software is
2412
 * furnished to do so, subject to the following conditions:
2413
 *
2414
 * The above copyright notice and this permission notice shall be included in
2415
 * all copies or substantial portions of the Software.
2416
 *
2417
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2418
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2419
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2420
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2421
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2422
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2423
 * THE SOFTWARE.
2424
 *
2425
 **************************************************************************/
2426
2427
#ifdef __cplusplus
2428
extern "C" {
2429
#endif
2430
2431
/* ------------------- Low-level Compression (independent from all decompression
2432
 * API's) */
2433
2434
/* Purposely making these tables static for faster init and thread safety. */
2435
static const mz_uint16 s_tdefl_len_sym[256] = {
2436
    257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268,
2437
    268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272,
2438
    272, 272, 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274,
2439
    274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276,
2440
    276, 276, 276, 276, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
2441
    277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
2442
    278, 278, 278, 278, 278, 278, 279, 279, 279, 279, 279, 279, 279, 279, 279,
2443
    279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280,
2444
    280, 280, 280, 280, 280, 280, 280, 280, 281, 281, 281, 281, 281, 281, 281,
2445
    281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
2446
    281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 282, 282, 282, 282, 282,
2447
    282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
2448
    282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 283, 283, 283,
2449
    283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
2450
    283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 284,
2451
    284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
2452
    284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
2453
    285};
2454
2455
static const mz_uint8 s_tdefl_len_extra[256] = {
2456
    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
2457
    2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2458
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
2459
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2460
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2461
    4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2462
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2463
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2464
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2465
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2466
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0};
2467
2468
static const mz_uint8 s_tdefl_small_dist_sym[512] = {
2469
    0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,
2470
    8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  10, 10, 10, 10, 10, 10,
2471
    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
2472
    11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2473
    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2474
    12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2475
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14,
2476
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2477
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2478
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
2479
    14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
2480
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
2481
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
2482
    15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2483
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2484
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2485
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2486
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2487
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2488
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
2489
    16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2490
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2491
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2492
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2493
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2494
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
2495
    17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17};
2496
2497
static const mz_uint8 s_tdefl_small_dist_extra[512] = {
2498
    0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2499
    3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
2500
    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2501
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2502
    5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
2503
    5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2504
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2505
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2506
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2507
    6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
2508
    6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2509
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2510
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2511
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2512
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2513
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2514
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2515
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2516
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2517
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
2518
    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
2519
2520
static const mz_uint8 s_tdefl_large_dist_sym[128] = {
2521
    0,  0,  18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24,
2522
    24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26,
2523
    26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27,
2524
    27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
2525
    28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
2526
    28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
2527
    29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29};
2528
2529
static const mz_uint8 s_tdefl_large_dist_extra[128] = {
2530
    0,  0,  8,  8,  9,  9,  9,  9,  10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
2531
    11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12,
2532
    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
2533
    12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2534
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2535
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
2536
    13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13};
2537
2538
/* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted
2539
 * values. */
2540
typedef struct {
2541
  mz_uint16 m_key, m_sym_index;
2542
} tdefl_sym_freq;
2543
static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms,
2544
                                             tdefl_sym_freq *pSyms0,
2545
0
                                             tdefl_sym_freq *pSyms1) {
2546
0
  mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
2547
0
  tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
2548
0
  MZ_CLEAR_OBJ(hist);
2549
0
  for (i = 0; i < num_syms; i++) {
2550
0
    mz_uint freq = pSyms0[i].m_key;
2551
0
    hist[freq & 0xFF]++;
2552
0
    hist[256 + ((freq >> 8) & 0xFF)]++;
2553
0
  }
2554
0
  while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
2555
0
    total_passes--;
2556
0
  for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) {
2557
0
    const mz_uint32 *pHist = &hist[pass << 8];
2558
0
    mz_uint offsets[256], cur_ofs = 0;
2559
0
    for (i = 0; i < 256; i++) {
2560
0
      offsets[i] = cur_ofs;
2561
0
      cur_ofs += pHist[i];
2562
0
    }
2563
0
    for (i = 0; i < num_syms; i++)
2564
0
      pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] =
2565
0
          pCur_syms[i];
2566
0
    {
2567
0
      tdefl_sym_freq *t = pCur_syms;
2568
0
      pCur_syms = pNew_syms;
2569
0
      pNew_syms = t;
2570
0
    }
2571
0
  }
2572
0
  return pCur_syms;
2573
0
}
2574
2575
/* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat,
2576
 * alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */
2577
0
static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) {
2578
0
  int root, leaf, next, avbl, used, dpth;
2579
0
  if (n == 0)
2580
0
    return;
2581
0
  else if (n == 1) {
2582
0
    A[0].m_key = 1;
2583
0
    return;
2584
0
  }
2585
0
  A[0].m_key += A[1].m_key;
2586
0
  root = 0;
2587
0
  leaf = 2;
2588
0
  for (next = 1; next < n - 1; next++) {
2589
0
    if (leaf >= n || A[root].m_key < A[leaf].m_key) {
2590
0
      A[next].m_key = A[root].m_key;
2591
0
      A[root++].m_key = (mz_uint16)next;
2592
0
    } else
2593
0
      A[next].m_key = A[leaf++].m_key;
2594
0
    if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) {
2595
0
      A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
2596
0
      A[root++].m_key = (mz_uint16)next;
2597
0
    } else
2598
0
      A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
2599
0
  }
2600
0
  A[n - 2].m_key = 0;
2601
0
  for (next = n - 3; next >= 0; next--)
2602
0
    A[next].m_key = A[A[next].m_key].m_key + 1;
2603
0
  avbl = 1;
2604
0
  used = dpth = 0;
2605
0
  root = n - 2;
2606
0
  next = n - 1;
2607
0
  while (avbl > 0) {
2608
0
    while (root >= 0 && (int)A[root].m_key == dpth) {
2609
0
      used++;
2610
0
      root--;
2611
0
    }
2612
0
    while (avbl > used) {
2613
0
      A[next--].m_key = (mz_uint16)(dpth);
2614
0
      avbl--;
2615
0
    }
2616
0
    avbl = 2 * used;
2617
0
    dpth++;
2618
0
    used = 0;
2619
0
  }
2620
0
}
2621
2622
/* Limits canonical Huffman code table's max code size. */
2623
enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 };
2624
static void tdefl_huffman_enforce_max_code_size(int *pNum_codes,
2625
                                                int code_list_len,
2626
0
                                                int max_code_size) {
2627
0
  int i;
2628
0
  mz_uint32 total = 0;
2629
0
  if (code_list_len <= 1)
2630
0
    return;
2631
0
  for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
2632
0
    pNum_codes[max_code_size] += pNum_codes[i];
2633
0
  for (i = max_code_size; i > 0; i--)
2634
0
    total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
2635
0
  while (total != (1UL << max_code_size)) {
2636
0
    pNum_codes[max_code_size]--;
2637
0
    for (i = max_code_size - 1; i > 0; i--)
2638
0
      if (pNum_codes[i]) {
2639
0
        pNum_codes[i]--;
2640
0
        pNum_codes[i + 1] += 2;
2641
0
        break;
2642
0
      }
2643
0
    total--;
2644
0
  }
2645
0
}
2646
2647
static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num,
2648
                                         int table_len, int code_size_limit,
2649
0
                                         int static_table) {
2650
0
  int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
2651
0
  mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
2652
0
  MZ_CLEAR_OBJ(num_codes);
2653
0
  if (static_table) {
2654
0
    for (i = 0; i < table_len; i++)
2655
0
      num_codes[d->m_huff_code_sizes[table_num][i]]++;
2656
0
  } else {
2657
0
    tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS],
2658
0
        *pSyms;
2659
0
    int num_used_syms = 0;
2660
0
    const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
2661
0
    for (i = 0; i < table_len; i++)
2662
0
      if (pSym_count[i]) {
2663
0
        syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
2664
0
        syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
2665
0
      }
2666
2667
0
    pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
2668
0
    tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
2669
2670
0
    for (i = 0; i < num_used_syms; i++)
2671
0
      num_codes[pSyms[i].m_key]++;
2672
2673
0
    tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms,
2674
0
                                        code_size_limit);
2675
2676
0
    MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
2677
0
    MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
2678
0
    for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
2679
0
      for (l = num_codes[i]; l > 0; l--)
2680
0
        d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
2681
0
  }
2682
2683
0
  next_code[1] = 0;
2684
0
  for (j = 0, i = 2; i <= code_size_limit; i++)
2685
0
    next_code[i] = j = ((j + num_codes[i - 1]) << 1);
2686
2687
0
  for (i = 0; i < table_len; i++) {
2688
0
    mz_uint rev_code = 0, code, code_size;
2689
0
    if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
2690
0
      continue;
2691
0
    code = next_code[code_size]++;
2692
0
    for (l = code_size; l > 0; l--, code >>= 1)
2693
0
      rev_code = (rev_code << 1) | (code & 1);
2694
0
    d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
2695
0
  }
2696
0
}
2697
2698
#define TDEFL_PUT_BITS(b, l)                                                   \
2699
0
  do {                                                                         \
2700
0
    mz_uint bits = b;                                                          \
2701
0
    mz_uint len = l;                                                           \
2702
0
    MZ_ASSERT(bits <= ((1U << len) - 1U));                                     \
2703
0
    d->m_bit_buffer |= (bits << d->m_bits_in);                                 \
2704
0
    d->m_bits_in += len;                                                       \
2705
0
    while (d->m_bits_in >= 8) {                                                \
2706
0
      if (d->m_pOutput_buf < d->m_pOutput_buf_end)                             \
2707
0
        *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer);                     \
2708
0
      d->m_bit_buffer >>= 8;                                                   \
2709
0
      d->m_bits_in -= 8;                                                       \
2710
0
    }                                                                          \
2711
0
  }                                                                            \
2712
0
  MZ_MACRO_END
2713
2714
#define TDEFL_RLE_PREV_CODE_SIZE()                                             \
2715
0
  {                                                                            \
2716
0
    if (rle_repeat_count) {                                                    \
2717
0
      if (rle_repeat_count < 3) {                                              \
2718
0
        d->m_huff_count[2][prev_code_size] =                                   \
2719
0
            (mz_uint16)(d->m_huff_count[2][prev_code_size] +                   \
2720
0
                        rle_repeat_count);                                     \
2721
0
        while (rle_repeat_count--)                                             \
2722
0
          packed_code_sizes[num_packed_code_sizes++] = prev_code_size;         \
2723
0
      } else {                                                                 \
2724
0
        d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1);      \
2725
0
        packed_code_sizes[num_packed_code_sizes++] = 16;                       \
2726
0
        packed_code_sizes[num_packed_code_sizes++] =                           \
2727
0
            (mz_uint8)(rle_repeat_count - 3);                                  \
2728
0
      }                                                                        \
2729
0
      rle_repeat_count = 0;                                                    \
2730
0
    }                                                                          \
2731
0
  }
2732
2733
#define TDEFL_RLE_ZERO_CODE_SIZE()                                             \
2734
0
  {                                                                            \
2735
0
    if (rle_z_count) {                                                         \
2736
0
      if (rle_z_count < 3) {                                                   \
2737
0
        d->m_huff_count[2][0] =                                                \
2738
0
            (mz_uint16)(d->m_huff_count[2][0] + rle_z_count);                  \
2739
0
        while (rle_z_count--)                                                  \
2740
0
          packed_code_sizes[num_packed_code_sizes++] = 0;                      \
2741
0
      } else if (rle_z_count <= 10) {                                          \
2742
0
        d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1);      \
2743
0
        packed_code_sizes[num_packed_code_sizes++] = 17;                       \
2744
0
        packed_code_sizes[num_packed_code_sizes++] =                           \
2745
0
            (mz_uint8)(rle_z_count - 3);                                       \
2746
0
      } else {                                                                 \
2747
0
        d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1);      \
2748
0
        packed_code_sizes[num_packed_code_sizes++] = 18;                       \
2749
0
        packed_code_sizes[num_packed_code_sizes++] =                           \
2750
0
            (mz_uint8)(rle_z_count - 11);                                      \
2751
0
      }                                                                        \
2752
0
      rle_z_count = 0;                                                         \
2753
0
    }                                                                          \
2754
0
  }
2755
2756
static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = {
2757
    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
2758
2759
0
static void tdefl_start_dynamic_block(tdefl_compressor *d) {
2760
0
  int num_lit_codes, num_dist_codes, num_bit_lengths;
2761
0
  mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count,
2762
0
      rle_repeat_count, packed_code_sizes_index;
2763
0
  mz_uint8
2764
0
      code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
2765
0
      packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1],
2766
0
      prev_code_size = 0xFF;
2767
2768
0
  d->m_huff_count[0][256] = 1;
2769
2770
0
  tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
2771
0
  tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
2772
2773
0
  for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
2774
0
    if (d->m_huff_code_sizes[0][num_lit_codes - 1])
2775
0
      break;
2776
0
  for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
2777
0
    if (d->m_huff_code_sizes[1][num_dist_codes - 1])
2778
0
      break;
2779
2780
0
  memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
2781
0
  memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0],
2782
0
         num_dist_codes);
2783
0
  total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
2784
0
  num_packed_code_sizes = 0;
2785
0
  rle_z_count = 0;
2786
0
  rle_repeat_count = 0;
2787
2788
0
  memset(&d->m_huff_count[2][0], 0,
2789
0
         sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
2790
0
  for (i = 0; i < total_code_sizes_to_pack; i++) {
2791
0
    mz_uint8 code_size = code_sizes_to_pack[i];
2792
0
    if (!code_size) {
2793
0
      TDEFL_RLE_PREV_CODE_SIZE();
2794
0
      if (++rle_z_count == 138) {
2795
0
        TDEFL_RLE_ZERO_CODE_SIZE();
2796
0
      }
2797
0
    } else {
2798
0
      TDEFL_RLE_ZERO_CODE_SIZE();
2799
0
      if (code_size != prev_code_size) {
2800
0
        TDEFL_RLE_PREV_CODE_SIZE();
2801
0
        d->m_huff_count[2][code_size] =
2802
0
            (mz_uint16)(d->m_huff_count[2][code_size] + 1);
2803
0
        packed_code_sizes[num_packed_code_sizes++] = code_size;
2804
0
      } else if (++rle_repeat_count == 6) {
2805
0
        TDEFL_RLE_PREV_CODE_SIZE();
2806
0
      }
2807
0
    }
2808
0
    prev_code_size = code_size;
2809
0
  }
2810
0
  if (rle_repeat_count) {
2811
0
    TDEFL_RLE_PREV_CODE_SIZE();
2812
0
  } else {
2813
0
    TDEFL_RLE_ZERO_CODE_SIZE();
2814
0
  }
2815
2816
0
  tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
2817
2818
0
  TDEFL_PUT_BITS(2, 2);
2819
2820
0
  TDEFL_PUT_BITS(num_lit_codes - 257, 5);
2821
0
  TDEFL_PUT_BITS(num_dist_codes - 1, 5);
2822
2823
0
  for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
2824
0
    if (d->m_huff_code_sizes
2825
0
            [2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
2826
0
      break;
2827
0
  num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
2828
0
  TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
2829
0
  for (i = 0; (int)i < num_bit_lengths; i++)
2830
0
    TDEFL_PUT_BITS(
2831
0
        d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
2832
2833
0
  for (packed_code_sizes_index = 0;
2834
0
       packed_code_sizes_index < num_packed_code_sizes;) {
2835
0
    mz_uint code = packed_code_sizes[packed_code_sizes_index++];
2836
0
    MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
2837
0
    TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
2838
0
    if (code >= 16)
2839
0
      TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++],
2840
0
                     "\02\03\07"[code - 16]);
2841
0
  }
2842
0
}
2843
2844
0
static void tdefl_start_static_block(tdefl_compressor *d) {
2845
0
  mz_uint i;
2846
0
  mz_uint8 *p = &d->m_huff_code_sizes[0][0];
2847
2848
0
  for (i = 0; i <= 143; ++i)
2849
0
    *p++ = 8;
2850
0
  for (; i <= 255; ++i)
2851
0
    *p++ = 9;
2852
0
  for (; i <= 279; ++i)
2853
0
    *p++ = 7;
2854
0
  for (; i <= 287; ++i)
2855
0
    *p++ = 8;
2856
2857
0
  memset(d->m_huff_code_sizes[1], 5, 32);
2858
2859
0
  tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
2860
0
  tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
2861
2862
0
  TDEFL_PUT_BITS(1, 2);
2863
0
}
2864
2865
static const mz_uint mz_bitmasks[17] = {
2866
    0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
2867
    0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF};
2868
2869
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN &&             \
2870
    MINIZ_HAS_64BIT_REGISTERS
2871
0
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
2872
0
  mz_uint flags;
2873
0
  mz_uint8 *pLZ_codes;
2874
0
  mz_uint8 *pOutput_buf = d->m_pOutput_buf;
2875
0
  mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
2876
0
  mz_uint64 bit_buffer = d->m_bit_buffer;
2877
0
  mz_uint bits_in = d->m_bits_in;
2878
2879
0
#define TDEFL_PUT_BITS_FAST(b, l)                                              \
2880
0
  {                                                                            \
2881
0
    bit_buffer |= (((mz_uint64)(b)) << bits_in);                               \
2882
0
    bits_in += (l);                                                            \
2883
0
  }
2884
2885
0
  flags = 1;
2886
0
  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end;
2887
0
       flags >>= 1) {
2888
0
    if (flags == 1)
2889
0
      flags = *pLZ_codes++ | 0x100;
2890
2891
0
    if (flags & 1) {
2892
0
      mz_uint s0, s1, n0, n1, sym, num_extra_bits;
2893
0
      mz_uint match_len = pLZ_codes[0],
2894
0
              match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
2895
0
      pLZ_codes += 3;
2896
2897
0
      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2898
0
      TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
2899
0
                          d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2900
0
      TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
2901
0
                          s_tdefl_len_extra[match_len]);
2902
2903
      /* This sequence coaxes MSVC into using cmov's vs. jmp's. */
2904
0
      s0 = s_tdefl_small_dist_sym[match_dist & 511];
2905
0
      n0 = s_tdefl_small_dist_extra[match_dist & 511];
2906
0
      s1 = s_tdefl_large_dist_sym[match_dist >> 8];
2907
0
      n1 = s_tdefl_large_dist_extra[match_dist >> 8];
2908
0
      sym = (match_dist < 512) ? s0 : s1;
2909
0
      num_extra_bits = (match_dist < 512) ? n0 : n1;
2910
2911
0
      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
2912
0
      TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym],
2913
0
                          d->m_huff_code_sizes[1][sym]);
2914
0
      TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits],
2915
0
                          num_extra_bits);
2916
0
    } else {
2917
0
      mz_uint lit = *pLZ_codes++;
2918
0
      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
2919
0
      TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
2920
0
                          d->m_huff_code_sizes[0][lit]);
2921
2922
0
      if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
2923
0
        flags >>= 1;
2924
0
        lit = *pLZ_codes++;
2925
0
        MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
2926
0
        TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
2927
0
                            d->m_huff_code_sizes[0][lit]);
2928
2929
0
        if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) {
2930
0
          flags >>= 1;
2931
0
          lit = *pLZ_codes++;
2932
0
          MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
2933
0
          TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit],
2934
0
                              d->m_huff_code_sizes[0][lit]);
2935
0
        }
2936
0
      }
2937
0
    }
2938
2939
0
    if (pOutput_buf >= d->m_pOutput_buf_end)
2940
0
      return MZ_FALSE;
2941
2942
0
    *(mz_uint64 *)pOutput_buf = bit_buffer;
2943
0
    pOutput_buf += (bits_in >> 3);
2944
0
    bit_buffer >>= (bits_in & ~7);
2945
0
    bits_in &= 7;
2946
0
  }
2947
2948
0
#undef TDEFL_PUT_BITS_FAST
2949
2950
0
  d->m_pOutput_buf = pOutput_buf;
2951
0
  d->m_bits_in = 0;
2952
0
  d->m_bit_buffer = 0;
2953
2954
0
  while (bits_in) {
2955
0
    mz_uint32 n = MZ_MIN(bits_in, 16);
2956
0
    TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
2957
0
    bit_buffer >>= n;
2958
0
    bits_in -= n;
2959
0
  }
2960
2961
0
  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
2962
2963
0
  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
2964
0
}
2965
#else
2966
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) {
2967
  mz_uint flags;
2968
  mz_uint8 *pLZ_codes;
2969
2970
  flags = 1;
2971
  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf;
2972
       flags >>= 1) {
2973
    if (flags == 1)
2974
      flags = *pLZ_codes++ | 0x100;
2975
    if (flags & 1) {
2976
      mz_uint sym, num_extra_bits;
2977
      mz_uint match_len = pLZ_codes[0],
2978
              match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
2979
      pLZ_codes += 3;
2980
2981
      MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2982
      TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]],
2983
                     d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
2984
      TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]],
2985
                     s_tdefl_len_extra[match_len]);
2986
2987
      if (match_dist < 512) {
2988
        sym = s_tdefl_small_dist_sym[match_dist];
2989
        num_extra_bits = s_tdefl_small_dist_extra[match_dist];
2990
      } else {
2991
        sym = s_tdefl_large_dist_sym[match_dist >> 8];
2992
        num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
2993
      }
2994
      MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
2995
      TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
2996
      TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
2997
    } else {
2998
      mz_uint lit = *pLZ_codes++;
2999
      MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
3000
      TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
3001
    }
3002
  }
3003
3004
  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
3005
3006
  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
3007
}
3008
#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN &&       \
3009
          MINIZ_HAS_64BIT_REGISTERS */
3010
3011
0
static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) {
3012
0
  if (static_block)
3013
0
    tdefl_start_static_block(d);
3014
0
  else
3015
0
    tdefl_start_dynamic_block(d);
3016
0
  return tdefl_compress_lz_codes(d);
3017
0
}
3018
3019
0
static int tdefl_flush_block(tdefl_compressor *d, int flush) {
3020
0
  mz_uint saved_bit_buf, saved_bits_in;
3021
0
  mz_uint8 *pSaved_output_buf;
3022
0
  mz_bool comp_block_succeeded = MZ_FALSE;
3023
0
  int n, use_raw_block =
3024
0
             ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) &&
3025
0
             (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
3026
0
  mz_uint8 *pOutput_buf_start =
3027
0
      ((d->m_pPut_buf_func == NULL) &&
3028
0
       ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE))
3029
0
          ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs)
3030
0
          : d->m_output_buf;
3031
3032
0
  d->m_pOutput_buf = pOutput_buf_start;
3033
0
  d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
3034
3035
0
  MZ_ASSERT(!d->m_output_flush_remaining);
3036
0
  d->m_output_flush_ofs = 0;
3037
0
  d->m_output_flush_remaining = 0;
3038
3039
0
  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
3040
0
  d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
3041
3042
0
  if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) {
3043
0
    TDEFL_PUT_BITS(0x78, 8);
3044
0
    TDEFL_PUT_BITS(0x01, 8);
3045
0
  }
3046
3047
0
  TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
3048
3049
0
  pSaved_output_buf = d->m_pOutput_buf;
3050
0
  saved_bit_buf = d->m_bit_buffer;
3051
0
  saved_bits_in = d->m_bits_in;
3052
3053
0
  if (!use_raw_block)
3054
0
    comp_block_succeeded =
3055
0
        tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) ||
3056
0
                                    (d->m_total_lz_bytes < 48));
3057
3058
  /* If the block gets expanded, forget the current contents of the output
3059
   * buffer and send a raw block instead. */
3060
0
  if (((use_raw_block) ||
3061
0
       ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >=
3062
0
                                  d->m_total_lz_bytes))) &&
3063
0
      ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) {
3064
0
    mz_uint i;
3065
0
    d->m_pOutput_buf = pSaved_output_buf;
3066
0
    d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3067
0
    TDEFL_PUT_BITS(0, 2);
3068
0
    if (d->m_bits_in) {
3069
0
      TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3070
0
    }
3071
0
    for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) {
3072
0
      TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
3073
0
    }
3074
0
    for (i = 0; i < d->m_total_lz_bytes; ++i) {
3075
0
      TDEFL_PUT_BITS(
3076
0
          d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK],
3077
0
          8);
3078
0
    }
3079
0
  }
3080
  /* Check for the extremely unlikely (if not impossible) case of the compressed
3081
     block not fitting into the output buffer when using dynamic codes. */
3082
0
  else if (!comp_block_succeeded) {
3083
0
    d->m_pOutput_buf = pSaved_output_buf;
3084
0
    d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
3085
0
    tdefl_compress_block(d, MZ_TRUE);
3086
0
  }
3087
3088
0
  if (flush) {
3089
0
    if (flush == TDEFL_FINISH) {
3090
0
      if (d->m_bits_in) {
3091
0
        TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3092
0
      }
3093
0
      if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) {
3094
0
        mz_uint i, a = d->m_adler32;
3095
0
        for (i = 0; i < 4; i++) {
3096
0
          TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
3097
0
          a <<= 8;
3098
0
        }
3099
0
      }
3100
0
    } else {
3101
0
      mz_uint i, z = 0;
3102
0
      TDEFL_PUT_BITS(0, 3);
3103
0
      if (d->m_bits_in) {
3104
0
        TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
3105
0
      }
3106
0
      for (i = 2; i; --i, z ^= 0xFFFF) {
3107
0
        TDEFL_PUT_BITS(z & 0xFFFF, 16);
3108
0
      }
3109
0
    }
3110
0
  }
3111
3112
0
  MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
3113
3114
0
  memset(&d->m_huff_count[0][0], 0,
3115
0
         sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
3116
0
  memset(&d->m_huff_count[1][0], 0,
3117
0
         sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
3118
3119
0
  d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
3120
0
  d->m_pLZ_flags = d->m_lz_code_buf;
3121
0
  d->m_num_flags_left = 8;
3122
0
  d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
3123
0
  d->m_total_lz_bytes = 0;
3124
0
  d->m_block_index++;
3125
3126
0
  if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) {
3127
0
    if (d->m_pPut_buf_func) {
3128
0
      *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
3129
0
      if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
3130
0
        return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
3131
0
    } else if (pOutput_buf_start == d->m_output_buf) {
3132
0
      int bytes_to_copy = (int)MZ_MIN(
3133
0
          (size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
3134
0
      memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf,
3135
0
             bytes_to_copy);
3136
0
      d->m_out_buf_ofs += bytes_to_copy;
3137
0
      if ((n -= bytes_to_copy) != 0) {
3138
0
        d->m_output_flush_ofs = bytes_to_copy;
3139
0
        d->m_output_flush_remaining = n;
3140
0
      }
3141
0
    } else {
3142
0
      d->m_out_buf_ofs += n;
3143
0
    }
3144
0
  }
3145
3146
0
  return d->m_output_flush_remaining;
3147
0
}
3148
3149
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
3150
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
3151
0
static mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8 *p) {
3152
0
  mz_uint16 ret;
3153
0
  memcpy(&ret, p, sizeof(mz_uint16));
3154
0
  return ret;
3155
0
}
3156
0
static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16 *p) {
3157
0
  mz_uint16 ret;
3158
0
  memcpy(&ret, p, sizeof(mz_uint16));
3159
0
  return ret;
3160
0
}
3161
#else
3162
#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
3163
#define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p)
3164
#endif
3165
static MZ_FORCEINLINE void
3166
tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3167
                 mz_uint max_match_len, mz_uint *pMatch_dist,
3168
0
                 mz_uint *pMatch_len) {
3169
0
  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3170
0
                match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3171
0
                probe_len;
3172
0
  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3173
0
  const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
3174
0
  mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]),
3175
0
            s01 = TDEFL_READ_UNALIGNED_WORD2(s);
3176
0
  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3177
0
  if (max_match_len <= match_len)
3178
0
    return;
3179
0
  for (;;) {
3180
0
    for (;;) {
3181
0
      if (--num_probes_left == 0)
3182
0
        return;
3183
0
#define TDEFL_PROBE                                                            \
3184
0
  next_probe_pos = d->m_next[probe_pos];                                       \
3185
0
  if ((!next_probe_pos) ||                                                     \
3186
0
      ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))       \
3187
0
    return;                                                                    \
3188
0
  probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                        \
3189
0
  if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \
3190
0
    break;
3191
0
      TDEFL_PROBE;
3192
0
      TDEFL_PROBE;
3193
0
      TDEFL_PROBE;
3194
0
    }
3195
0
    if (!dist)
3196
0
      break;
3197
0
    q = (const mz_uint16 *)(d->m_dict + probe_pos);
3198
0
    if (TDEFL_READ_UNALIGNED_WORD2(q) != s01)
3199
0
      continue;
3200
0
    p = s;
3201
0
    probe_len = 32;
3202
0
    do {
3203
0
    } while (
3204
0
        (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
3205
0
        (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
3206
0
        (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
3207
0
        (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
3208
0
        (--probe_len > 0));
3209
0
    if (!probe_len) {
3210
0
      *pMatch_dist = dist;
3211
0
      *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN);
3212
0
      break;
3213
0
    } else if ((probe_len = ((mz_uint)(p - s) * 2) +
3214
0
                            (mz_uint)(*(const mz_uint8 *)p ==
3215
0
                                      *(const mz_uint8 *)q)) > match_len) {
3216
0
      *pMatch_dist = dist;
3217
0
      if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) ==
3218
0
          max_match_len)
3219
0
        break;
3220
0
      c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
3221
0
    }
3222
0
  }
3223
0
}
3224
#else
3225
static MZ_FORCEINLINE void
3226
tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist,
3227
                 mz_uint max_match_len, mz_uint *pMatch_dist,
3228
                 mz_uint *pMatch_len) {
3229
  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK,
3230
                match_len = *pMatch_len, probe_pos = pos, next_probe_pos,
3231
                probe_len;
3232
  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
3233
  const mz_uint8 *s = d->m_dict + pos, *p, *q;
3234
  mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
3235
  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
3236
  if (max_match_len <= match_len)
3237
    return;
3238
  for (;;) {
3239
    for (;;) {
3240
      if (--num_probes_left == 0)
3241
        return;
3242
#define TDEFL_PROBE                                                            \
3243
  next_probe_pos = d->m_next[probe_pos];                                       \
3244
  if ((!next_probe_pos) ||                                                     \
3245
      ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))       \
3246
    return;                                                                    \
3247
  probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                        \
3248
  if ((d->m_dict[probe_pos + match_len] == c0) &&                              \
3249
      (d->m_dict[probe_pos + match_len - 1] == c1))                            \
3250
    break;
3251
      TDEFL_PROBE;
3252
      TDEFL_PROBE;
3253
      TDEFL_PROBE;
3254
    }
3255
    if (!dist)
3256
      break;
3257
    p = s;
3258
    q = d->m_dict + probe_pos;
3259
    for (probe_len = 0; probe_len < max_match_len; probe_len++)
3260
      if (*p++ != *q++)
3261
        break;
3262
    if (probe_len > match_len) {
3263
      *pMatch_dist = dist;
3264
      if ((*pMatch_len = match_len = probe_len) == max_match_len)
3265
        return;
3266
      c0 = d->m_dict[pos + match_len];
3267
      c1 = d->m_dict[pos + match_len - 1];
3268
    }
3269
  }
3270
}
3271
#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */
3272
3273
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3274
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
3275
0
static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(const mz_uint8 *p) {
3276
0
  mz_uint32 ret;
3277
0
  memcpy(&ret, p, sizeof(mz_uint32));
3278
0
  return ret;
3279
0
}
3280
#else
3281
#define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p)
3282
#endif
3283
0
static mz_bool tdefl_compress_fast(tdefl_compressor *d) {
3284
  /* Faster, minimally featured LZRW1-style match+parse loop with better
3285
   * register utilization. Intended for applications where raw throughput is
3286
   * valued more highly than ratio. */
3287
0
  mz_uint lookahead_pos = d->m_lookahead_pos,
3288
0
          lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size,
3289
0
          total_lz_bytes = d->m_total_lz_bytes,
3290
0
          num_flags_left = d->m_num_flags_left;
3291
0
  mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
3292
0
  mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
3293
3294
0
  while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) {
3295
0
    const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
3296
0
    mz_uint dst_pos =
3297
0
        (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
3298
0
    mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
3299
0
        d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
3300
0
    d->m_src_buf_left -= num_bytes_to_process;
3301
0
    lookahead_size += num_bytes_to_process;
3302
3303
0
    while (num_bytes_to_process) {
3304
0
      mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
3305
0
      memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
3306
0
      if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3307
0
        memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc,
3308
0
               MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
3309
0
      d->m_pSrc += n;
3310
0
      dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
3311
0
      num_bytes_to_process -= n;
3312
0
    }
3313
3314
0
    dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
3315
0
    if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
3316
0
      break;
3317
3318
0
    while (lookahead_size >= 4) {
3319
0
      mz_uint cur_match_dist, cur_match_len = 1;
3320
0
      mz_uint8 *pCur_dict = d->m_dict + cur_pos;
3321
0
      mz_uint first_trigram = TDEFL_READ_UNALIGNED_WORD32(pCur_dict) & 0xFFFFFF;
3322
0
      mz_uint hash =
3323
0
          (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) &
3324
0
          TDEFL_LEVEL1_HASH_SIZE_MASK;
3325
0
      mz_uint probe_pos = d->m_hash[hash];
3326
0
      d->m_hash[hash] = (mz_uint16)lookahead_pos;
3327
3328
0
      if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <=
3329
0
           dict_size) &&
3330
0
          ((TDEFL_READ_UNALIGNED_WORD32(
3331
0
                d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) &
3332
0
            0xFFFFFF) == first_trigram)) {
3333
0
        const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
3334
0
        const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
3335
0
        mz_uint32 probe_len = 32;
3336
0
        do {
3337
0
        } while ((TDEFL_READ_UNALIGNED_WORD2(++p) ==
3338
0
                  TDEFL_READ_UNALIGNED_WORD2(++q)) &&
3339
0
                 (TDEFL_READ_UNALIGNED_WORD2(++p) ==
3340
0
                  TDEFL_READ_UNALIGNED_WORD2(++q)) &&
3341
0
                 (TDEFL_READ_UNALIGNED_WORD2(++p) ==
3342
0
                  TDEFL_READ_UNALIGNED_WORD2(++q)) &&
3343
0
                 (TDEFL_READ_UNALIGNED_WORD2(++p) ==
3344
0
                  TDEFL_READ_UNALIGNED_WORD2(++q)) &&
3345
0
                 (--probe_len > 0));
3346
0
        cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) +
3347
0
                        (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
3348
0
        if (!probe_len)
3349
0
          cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
3350
3351
0
        if ((cur_match_len < TDEFL_MIN_MATCH_LEN) ||
3352
0
            ((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
3353
0
             (cur_match_dist >= 8U * 1024U))) {
3354
0
          cur_match_len = 1;
3355
0
          *pLZ_code_buf++ = (mz_uint8)first_trigram;
3356
0
          *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3357
0
          d->m_huff_count[0][(mz_uint8)first_trigram]++;
3358
0
        } else {
3359
0
          mz_uint32 s0, s1;
3360
0
          cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
3361
3362
0
          MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) &&
3363
0
                    (cur_match_dist >= 1) &&
3364
0
                    (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
3365
3366
0
          cur_match_dist--;
3367
3368
0
          pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
3369
0
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
3370
0
          memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist));
3371
#else
3372
          *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
3373
#endif
3374
0
          pLZ_code_buf += 3;
3375
0
          *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
3376
3377
0
          s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
3378
0
          s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
3379
0
          d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
3380
3381
0
          d->m_huff_count[0][s_tdefl_len_sym[cur_match_len -
3382
0
                                             TDEFL_MIN_MATCH_LEN]]++;
3383
0
        }
3384
0
      } else {
3385
0
        *pLZ_code_buf++ = (mz_uint8)first_trigram;
3386
0
        *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3387
0
        d->m_huff_count[0][(mz_uint8)first_trigram]++;
3388
0
      }
3389
3390
0
      if (--num_flags_left == 0) {
3391
0
        num_flags_left = 8;
3392
0
        pLZ_flags = pLZ_code_buf++;
3393
0
      }
3394
3395
0
      total_lz_bytes += cur_match_len;
3396
0
      lookahead_pos += cur_match_len;
3397
0
      dict_size =
3398
0
          MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE);
3399
0
      cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
3400
0
      MZ_ASSERT(lookahead_size >= cur_match_len);
3401
0
      lookahead_size -= cur_match_len;
3402
3403
0
      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
3404
0
        int n;
3405
0
        d->m_lookahead_pos = lookahead_pos;
3406
0
        d->m_lookahead_size = lookahead_size;
3407
0
        d->m_dict_size = dict_size;
3408
0
        d->m_total_lz_bytes = total_lz_bytes;
3409
0
        d->m_pLZ_code_buf = pLZ_code_buf;
3410
0
        d->m_pLZ_flags = pLZ_flags;
3411
0
        d->m_num_flags_left = num_flags_left;
3412
0
        if ((n = tdefl_flush_block(d, 0)) != 0)
3413
0
          return (n < 0) ? MZ_FALSE : MZ_TRUE;
3414
0
        total_lz_bytes = d->m_total_lz_bytes;
3415
0
        pLZ_code_buf = d->m_pLZ_code_buf;
3416
0
        pLZ_flags = d->m_pLZ_flags;
3417
0
        num_flags_left = d->m_num_flags_left;
3418
0
      }
3419
0
    }
3420
3421
0
    while (lookahead_size) {
3422
0
      mz_uint8 lit = d->m_dict[cur_pos];
3423
3424
0
      total_lz_bytes++;
3425
0
      *pLZ_code_buf++ = lit;
3426
0
      *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
3427
0
      if (--num_flags_left == 0) {
3428
0
        num_flags_left = 8;
3429
0
        pLZ_flags = pLZ_code_buf++;
3430
0
      }
3431
3432
0
      d->m_huff_count[0][lit]++;
3433
3434
0
      lookahead_pos++;
3435
0
      dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE);
3436
0
      cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
3437
0
      lookahead_size--;
3438
3439
0
      if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) {
3440
0
        int n;
3441
0
        d->m_lookahead_pos = lookahead_pos;
3442
0
        d->m_lookahead_size = lookahead_size;
3443
0
        d->m_dict_size = dict_size;
3444
0
        d->m_total_lz_bytes = total_lz_bytes;
3445
0
        d->m_pLZ_code_buf = pLZ_code_buf;
3446
0
        d->m_pLZ_flags = pLZ_flags;
3447
0
        d->m_num_flags_left = num_flags_left;
3448
0
        if ((n = tdefl_flush_block(d, 0)) != 0)
3449
0
          return (n < 0) ? MZ_FALSE : MZ_TRUE;
3450
0
        total_lz_bytes = d->m_total_lz_bytes;
3451
0
        pLZ_code_buf = d->m_pLZ_code_buf;
3452
0
        pLZ_flags = d->m_pLZ_flags;
3453
0
        num_flags_left = d->m_num_flags_left;
3454
0
      }
3455
0
    }
3456
0
  }
3457
3458
0
  d->m_lookahead_pos = lookahead_pos;
3459
0
  d->m_lookahead_size = lookahead_size;
3460
0
  d->m_dict_size = dict_size;
3461
0
  d->m_total_lz_bytes = total_lz_bytes;
3462
0
  d->m_pLZ_code_buf = pLZ_code_buf;
3463
0
  d->m_pLZ_flags = pLZ_flags;
3464
0
  d->m_num_flags_left = num_flags_left;
3465
0
  return MZ_TRUE;
3466
0
}
3467
#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
3468
3469
static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d,
3470
0
                                                mz_uint8 lit) {
3471
0
  d->m_total_lz_bytes++;
3472
0
  *d->m_pLZ_code_buf++ = lit;
3473
0
  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
3474
0
  if (--d->m_num_flags_left == 0) {
3475
0
    d->m_num_flags_left = 8;
3476
0
    d->m_pLZ_flags = d->m_pLZ_code_buf++;
3477
0
  }
3478
0
  d->m_huff_count[0][lit]++;
3479
0
}
3480
3481
static MZ_FORCEINLINE void
3482
0
tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) {
3483
0
  mz_uint32 s0, s1;
3484
3485
0
  MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) &&
3486
0
            (match_dist <= TDEFL_LZ_DICT_SIZE));
3487
3488
0
  d->m_total_lz_bytes += match_len;
3489
3490
0
  d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
3491
3492
0
  match_dist -= 1;
3493
0
  d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
3494
0
  d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
3495
0
  d->m_pLZ_code_buf += 3;
3496
3497
0
  *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
3498
0
  if (--d->m_num_flags_left == 0) {
3499
0
    d->m_num_flags_left = 8;
3500
0
    d->m_pLZ_flags = d->m_pLZ_code_buf++;
3501
0
  }
3502
3503
0
  s0 = s_tdefl_small_dist_sym[match_dist & 511];
3504
0
  s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
3505
0
  d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
3506
0
  d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
3507
0
}
3508
3509
0
static mz_bool tdefl_compress_normal(tdefl_compressor *d) {
3510
0
  const mz_uint8 *pSrc = d->m_pSrc;
3511
0
  size_t src_buf_left = d->m_src_buf_left;
3512
0
  tdefl_flush flush = d->m_flush;
3513
3514
0
  while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) {
3515
0
    mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
3516
    /* Update dictionary and hash chains. Keeps the lookahead size equal to
3517
     * TDEFL_MAX_MATCH_LEN. */
3518
0
    if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) {
3519
0
      mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
3520
0
                        TDEFL_LZ_DICT_SIZE_MASK,
3521
0
              ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
3522
0
      mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
3523
0
                      << TDEFL_LZ_HASH_SHIFT) ^
3524
0
                     d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
3525
0
      mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(
3526
0
          src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
3527
0
      const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
3528
0
      src_buf_left -= num_bytes_to_process;
3529
0
      d->m_lookahead_size += num_bytes_to_process;
3530
0
      while (pSrc != pSrc_end) {
3531
0
        mz_uint8 c = *pSrc++;
3532
0
        d->m_dict[dst_pos] = c;
3533
0
        if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3534
0
          d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
3535
0
        hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
3536
0
        d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
3537
0
        d->m_hash[hash] = (mz_uint16)(ins_pos);
3538
0
        dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
3539
0
        ins_pos++;
3540
0
      }
3541
0
    } else {
3542
0
      while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) {
3543
0
        mz_uint8 c = *pSrc++;
3544
0
        mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) &
3545
0
                          TDEFL_LZ_DICT_SIZE_MASK;
3546
0
        src_buf_left--;
3547
0
        d->m_dict[dst_pos] = c;
3548
0
        if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
3549
0
          d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
3550
0
        if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) {
3551
0
          mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
3552
0
          mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK]
3553
0
                           << (TDEFL_LZ_HASH_SHIFT * 2)) ^
3554
0
                          (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]
3555
0
                           << TDEFL_LZ_HASH_SHIFT) ^
3556
0
                          c) &
3557
0
                         (TDEFL_LZ_HASH_SIZE - 1);
3558
0
          d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
3559
0
          d->m_hash[hash] = (mz_uint16)(ins_pos);
3560
0
        }
3561
0
      }
3562
0
    }
3563
0
    d->m_dict_size =
3564
0
        MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
3565
0
    if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
3566
0
      break;
3567
3568
    /* Simple lazy/greedy parsing state machine. */
3569
0
    len_to_move = 1;
3570
0
    cur_match_dist = 0;
3571
0
    cur_match_len =
3572
0
        d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
3573
0
    cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
3574
0
    if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) {
3575
0
      if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) {
3576
0
        mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
3577
0
        cur_match_len = 0;
3578
0
        while (cur_match_len < d->m_lookahead_size) {
3579
0
          if (d->m_dict[cur_pos + cur_match_len] != c)
3580
0
            break;
3581
0
          cur_match_len++;
3582
0
        }
3583
0
        if (cur_match_len < TDEFL_MIN_MATCH_LEN)
3584
0
          cur_match_len = 0;
3585
0
        else
3586
0
          cur_match_dist = 1;
3587
0
      }
3588
0
    } else {
3589
0
      tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size,
3590
0
                       d->m_lookahead_size, &cur_match_dist, &cur_match_len);
3591
0
    }
3592
0
    if (((cur_match_len == TDEFL_MIN_MATCH_LEN) &&
3593
0
         (cur_match_dist >= 8U * 1024U)) ||
3594
0
        (cur_pos == cur_match_dist) ||
3595
0
        ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) {
3596
0
      cur_match_dist = cur_match_len = 0;
3597
0
    }
3598
0
    if (d->m_saved_match_len) {
3599
0
      if (cur_match_len > d->m_saved_match_len) {
3600
0
        tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
3601
0
        if (cur_match_len >= 128) {
3602
0
          tdefl_record_match(d, cur_match_len, cur_match_dist);
3603
0
          d->m_saved_match_len = 0;
3604
0
          len_to_move = cur_match_len;
3605
0
        } else {
3606
0
          d->m_saved_lit = d->m_dict[cur_pos];
3607
0
          d->m_saved_match_dist = cur_match_dist;
3608
0
          d->m_saved_match_len = cur_match_len;
3609
0
        }
3610
0
      } else {
3611
0
        tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
3612
0
        len_to_move = d->m_saved_match_len - 1;
3613
0
        d->m_saved_match_len = 0;
3614
0
      }
3615
0
    } else if (!cur_match_dist)
3616
0
      tdefl_record_literal(d,
3617
0
                           d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
3618
0
    else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) ||
3619
0
             (cur_match_len >= 128)) {
3620
0
      tdefl_record_match(d, cur_match_len, cur_match_dist);
3621
0
      len_to_move = cur_match_len;
3622
0
    } else {
3623
0
      d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
3624
0
      d->m_saved_match_dist = cur_match_dist;
3625
0
      d->m_saved_match_len = cur_match_len;
3626
0
    }
3627
    /* Move the lookahead forward by len_to_move bytes. */
3628
0
    d->m_lookahead_pos += len_to_move;
3629
0
    MZ_ASSERT(d->m_lookahead_size >= len_to_move);
3630
0
    d->m_lookahead_size -= len_to_move;
3631
0
    d->m_dict_size =
3632
0
        MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
3633
    /* Check if it's time to flush the current LZ codes to the internal output
3634
     * buffer. */
3635
0
    if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
3636
0
        ((d->m_total_lz_bytes > 31 * 1024) &&
3637
0
         (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >=
3638
0
           d->m_total_lz_bytes) ||
3639
0
          (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) {
3640
0
      int n;
3641
0
      d->m_pSrc = pSrc;
3642
0
      d->m_src_buf_left = src_buf_left;
3643
0
      if ((n = tdefl_flush_block(d, 0)) != 0)
3644
0
        return (n < 0) ? MZ_FALSE : MZ_TRUE;
3645
0
    }
3646
0
  }
3647
3648
0
  d->m_pSrc = pSrc;
3649
0
  d->m_src_buf_left = src_buf_left;
3650
0
  return MZ_TRUE;
3651
0
}
3652
3653
0
static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) {
3654
0
  if (d->m_pIn_buf_size) {
3655
0
    *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
3656
0
  }
3657
3658
0
  if (d->m_pOut_buf_size) {
3659
0
    size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs,
3660
0
                      d->m_output_flush_remaining);
3661
0
    memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs,
3662
0
           d->m_output_buf + d->m_output_flush_ofs, n);
3663
0
    d->m_output_flush_ofs += (mz_uint)n;
3664
0
    d->m_output_flush_remaining -= (mz_uint)n;
3665
0
    d->m_out_buf_ofs += n;
3666
3667
0
    *d->m_pOut_buf_size = d->m_out_buf_ofs;
3668
0
  }
3669
3670
0
  return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE
3671
0
                                                         : TDEFL_STATUS_OKAY;
3672
0
}
3673
3674
tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf,
3675
                            size_t *pIn_buf_size, void *pOut_buf,
3676
0
                            size_t *pOut_buf_size, tdefl_flush flush) {
3677
0
  if (!d) {
3678
0
    if (pIn_buf_size)
3679
0
      *pIn_buf_size = 0;
3680
0
    if (pOut_buf_size)
3681
0
      *pOut_buf_size = 0;
3682
0
    return TDEFL_STATUS_BAD_PARAM;
3683
0
  }
3684
3685
0
  d->m_pIn_buf = pIn_buf;
3686
0
  d->m_pIn_buf_size = pIn_buf_size;
3687
0
  d->m_pOut_buf = pOut_buf;
3688
0
  d->m_pOut_buf_size = pOut_buf_size;
3689
0
  d->m_pSrc = (const mz_uint8 *)(pIn_buf);
3690
0
  d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
3691
0
  d->m_out_buf_ofs = 0;
3692
0
  d->m_flush = flush;
3693
3694
0
  if (((d->m_pPut_buf_func != NULL) ==
3695
0
       ((pOut_buf != NULL) || (pOut_buf_size != NULL))) ||
3696
0
      (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
3697
0
      (d->m_wants_to_finish && (flush != TDEFL_FINISH)) ||
3698
0
      (pIn_buf_size && *pIn_buf_size && !pIn_buf) ||
3699
0
      (pOut_buf_size && *pOut_buf_size && !pOut_buf)) {
3700
0
    if (pIn_buf_size)
3701
0
      *pIn_buf_size = 0;
3702
0
    if (pOut_buf_size)
3703
0
      *pOut_buf_size = 0;
3704
0
    return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
3705
0
  }
3706
0
  d->m_wants_to_finish |= (flush == TDEFL_FINISH);
3707
3708
0
  if ((d->m_output_flush_remaining) || (d->m_finished))
3709
0
    return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
3710
3711
0
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
3712
0
  if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
3713
0
      ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
3714
0
      ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS |
3715
0
                      TDEFL_RLE_MATCHES)) == 0)) {
3716
0
    if (!tdefl_compress_fast(d))
3717
0
      return d->m_prev_return_status;
3718
0
  } else
3719
0
#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
3720
0
  {
3721
0
    if (!tdefl_compress_normal(d))
3722
0
      return d->m_prev_return_status;
3723
0
  }
3724
3725
0
  if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) &&
3726
0
      (pIn_buf))
3727
0
    d->m_adler32 =
3728
0
        (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf,
3729
0
                              d->m_pSrc - (const mz_uint8 *)pIn_buf);
3730
3731
0
  if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) &&
3732
0
      (!d->m_output_flush_remaining)) {
3733
0
    if (tdefl_flush_block(d, flush) < 0)
3734
0
      return d->m_prev_return_status;
3735
0
    d->m_finished = (flush == TDEFL_FINISH);
3736
0
    if (flush == TDEFL_FULL_FLUSH) {
3737
0
      MZ_CLEAR_OBJ(d->m_hash);
3738
0
      MZ_CLEAR_OBJ(d->m_next);
3739
0
      d->m_dict_size = 0;
3740
0
    }
3741
0
  }
3742
3743
0
  return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
3744
0
}
3745
3746
tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf,
3747
0
                                   size_t in_buf_size, tdefl_flush flush) {
3748
0
  MZ_ASSERT(d->m_pPut_buf_func);
3749
0
  return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
3750
0
}
3751
3752
tdefl_status tdefl_init(tdefl_compressor *d,
3753
                        tdefl_put_buf_func_ptr pPut_buf_func,
3754
0
                        void *pPut_buf_user, int flags) {
3755
0
  d->m_pPut_buf_func = pPut_buf_func;
3756
0
  d->m_pPut_buf_user = pPut_buf_user;
3757
0
  d->m_flags = (mz_uint)(flags);
3758
0
  d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
3759
0
  d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
3760
0
  d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
3761
0
  if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
3762
0
    MZ_CLEAR_OBJ(d->m_hash);
3763
0
  d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size =
3764
0
      d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
3765
0
  d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished =
3766
0
      d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
3767
0
  d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
3768
0
  d->m_pLZ_flags = d->m_lz_code_buf;
3769
0
  *d->m_pLZ_flags = 0;
3770
0
  d->m_num_flags_left = 8;
3771
0
  d->m_pOutput_buf = d->m_output_buf;
3772
0
  d->m_pOutput_buf_end = d->m_output_buf;
3773
0
  d->m_prev_return_status = TDEFL_STATUS_OKAY;
3774
0
  d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
3775
0
  d->m_adler32 = 1;
3776
0
  d->m_pIn_buf = NULL;
3777
0
  d->m_pOut_buf = NULL;
3778
0
  d->m_pIn_buf_size = NULL;
3779
0
  d->m_pOut_buf_size = NULL;
3780
0
  d->m_flush = TDEFL_NO_FLUSH;
3781
0
  d->m_pSrc = NULL;
3782
0
  d->m_src_buf_left = 0;
3783
0
  d->m_out_buf_ofs = 0;
3784
0
  if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
3785
0
    MZ_CLEAR_OBJ(d->m_dict);
3786
0
  memset(&d->m_huff_count[0][0], 0,
3787
0
         sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
3788
0
  memset(&d->m_huff_count[1][0], 0,
3789
0
         sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
3790
0
  return TDEFL_STATUS_OKAY;
3791
0
}
3792
3793
0
tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) {
3794
0
  return d->m_prev_return_status;
3795
0
}
3796
3797
0
mz_uint32 tdefl_get_adler32(tdefl_compressor *d) { return d->m_adler32; }
3798
3799
mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len,
3800
                                     tdefl_put_buf_func_ptr pPut_buf_func,
3801
0
                                     void *pPut_buf_user, int flags) {
3802
0
  tdefl_compressor *pComp;
3803
0
  mz_bool succeeded;
3804
0
  if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
3805
0
    return MZ_FALSE;
3806
0
  pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
3807
0
  if (!pComp)
3808
0
    return MZ_FALSE;
3809
0
  succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) ==
3810
0
               TDEFL_STATUS_OKAY);
3811
0
  succeeded =
3812
0
      succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) ==
3813
0
                    TDEFL_STATUS_DONE);
3814
0
  MZ_FREE(pComp);
3815
0
  return succeeded;
3816
0
}
3817
3818
typedef struct {
3819
  size_t m_size, m_capacity;
3820
  mz_uint8 *m_pBuf;
3821
  mz_bool m_expandable;
3822
} tdefl_output_buffer;
3823
3824
static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len,
3825
0
                                          void *pUser) {
3826
0
  tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
3827
0
  size_t new_size = p->m_size + len;
3828
0
  if (new_size > p->m_capacity) {
3829
0
    size_t new_capacity = p->m_capacity;
3830
0
    mz_uint8 *pNew_buf;
3831
0
    if (!p->m_expandable)
3832
0
      return MZ_FALSE;
3833
0
    do {
3834
0
      new_capacity = MZ_MAX(128U, new_capacity << 1U);
3835
0
    } while (new_size > new_capacity);
3836
0
    pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
3837
0
    if (!pNew_buf)
3838
0
      return MZ_FALSE;
3839
0
    p->m_pBuf = pNew_buf;
3840
0
    p->m_capacity = new_capacity;
3841
0
  }
3842
0
  memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
3843
0
  p->m_size = new_size;
3844
0
  return MZ_TRUE;
3845
0
}
3846
3847
void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
3848
0
                                 size_t *pOut_len, int flags) {
3849
0
  tdefl_output_buffer out_buf;
3850
0
  MZ_CLEAR_OBJ(out_buf);
3851
0
  if (!pOut_len)
3852
0
    return MZ_FALSE;
3853
0
  else
3854
0
    *pOut_len = 0;
3855
0
  out_buf.m_expandable = MZ_TRUE;
3856
0
  if (!tdefl_compress_mem_to_output(
3857
0
          pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
3858
0
    return NULL;
3859
0
  *pOut_len = out_buf.m_size;
3860
0
  return out_buf.m_pBuf;
3861
0
}
3862
3863
size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
3864
                                 const void *pSrc_buf, size_t src_buf_len,
3865
0
                                 int flags) {
3866
0
  tdefl_output_buffer out_buf;
3867
0
  MZ_CLEAR_OBJ(out_buf);
3868
0
  if (!pOut_buf)
3869
0
    return 0;
3870
0
  out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
3871
0
  out_buf.m_capacity = out_buf_len;
3872
0
  if (!tdefl_compress_mem_to_output(
3873
0
          pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
3874
0
    return 0;
3875
0
  return out_buf.m_size;
3876
0
}
3877
3878
static const mz_uint s_tdefl_num_probes[11] = {0,   1,   6,   32,  16,  32,
3879
                                               128, 256, 512, 768, 1500};
3880
3881
/* level may actually range from [0,10] (10 is a "hidden" max level, where we
3882
 * want a bit more compression and it's fine if throughput to fall off a cliff
3883
 * on some files). */
3884
mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits,
3885
0
                                                int strategy) {
3886
0
  mz_uint comp_flags =
3887
0
      s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] |
3888
0
      ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
3889
0
  if (window_bits > 0)
3890
0
    comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
3891
3892
0
  if (!level)
3893
0
    comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
3894
0
  else if (strategy == MZ_FILTERED)
3895
0
    comp_flags |= TDEFL_FILTER_MATCHES;
3896
0
  else if (strategy == MZ_HUFFMAN_ONLY)
3897
0
    comp_flags &= ~TDEFL_MAX_PROBES_MASK;
3898
0
  else if (strategy == MZ_FIXED)
3899
0
    comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
3900
0
  else if (strategy == MZ_RLE)
3901
0
    comp_flags |= TDEFL_RLE_MATCHES;
3902
3903
0
  return comp_flags;
3904
0
}
3905
3906
#ifdef _MSC_VER
3907
#pragma warning(push)
3908
#pragma warning(disable : 4204) /* nonstandard extension used : non-constant   \
3909
                                   aggregate initializer (also supported by    \
3910
                                   GNU C and C99, so no big deal) */
3911
#endif
3912
3913
/* Simple PNG writer function by Alex Evans, 2011. Released into the public
3914
 domain: https://gist.github.com/908299, more context at
3915
 http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
3916
 This is actually a modification of Alex's original code so PNG files generated
3917
 by this function pass pngcheck. */
3918
void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w,
3919
                                                 int h, int num_chans,
3920
                                                 size_t *pLen_out,
3921
0
                                                 mz_uint level, mz_bool flip) {
3922
  /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was
3923
   * defined. */
3924
0
  static const mz_uint s_tdefl_png_num_probes[11] = {
3925
0
      0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500};
3926
0
  tdefl_compressor *pComp =
3927
0
      (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
3928
0
  tdefl_output_buffer out_buf;
3929
0
  int i, bpl = w * num_chans, y, z;
3930
0
  mz_uint32 c;
3931
0
  *pLen_out = 0;
3932
0
  if (!pComp)
3933
0
    return NULL;
3934
0
  MZ_CLEAR_OBJ(out_buf);
3935
0
  out_buf.m_expandable = MZ_TRUE;
3936
0
  out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
3937
0
  if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity))) {
3938
0
    MZ_FREE(pComp);
3939
0
    return NULL;
3940
0
  }
3941
  /* write dummy header */
3942
0
  for (z = 41; z; --z)
3943
0
    tdefl_output_buffer_putter(&z, 1, &out_buf);
3944
  /* compress image data */
3945
0
  tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf,
3946
0
             s_tdefl_png_num_probes[MZ_MIN(10, level)] |
3947
0
                 TDEFL_WRITE_ZLIB_HEADER);
3948
0
  for (y = 0; y < h; ++y) {
3949
0
    tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
3950
0
    tdefl_compress_buffer(pComp,
3951
0
                          (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl,
3952
0
                          bpl, TDEFL_NO_FLUSH);
3953
0
  }
3954
0
  if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) !=
3955
0
      TDEFL_STATUS_DONE) {
3956
0
    MZ_FREE(pComp);
3957
0
    MZ_FREE(out_buf.m_pBuf);
3958
0
    return NULL;
3959
0
  }
3960
  /* write real header */
3961
0
  *pLen_out = out_buf.m_size - 41;
3962
0
  {
3963
0
    static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
3964
0
    mz_uint8 pnghdr[41] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00,
3965
0
                           0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00,
3966
0
                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
3967
0
                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
3968
0
                           0x00, 0x49, 0x44, 0x41, 0x54};
3969
0
    pnghdr[18] = (mz_uint8)(w >> 8);
3970
0
    pnghdr[19] = (mz_uint8)w;
3971
0
    pnghdr[22] = (mz_uint8)(h >> 8);
3972
0
    pnghdr[23] = (mz_uint8)h;
3973
0
    pnghdr[25] = chans[num_chans];
3974
0
    pnghdr[33] = (mz_uint8)(*pLen_out >> 24);
3975
0
    pnghdr[34] = (mz_uint8)(*pLen_out >> 16);
3976
0
    pnghdr[35] = (mz_uint8)(*pLen_out >> 8);
3977
0
    pnghdr[36] = (mz_uint8)*pLen_out;
3978
0
    c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
3979
0
    for (i = 0; i < 4; ++i, c <<= 8)
3980
0
      ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
3981
0
    memcpy(out_buf.m_pBuf, pnghdr, 41);
3982
0
  }
3983
  /* write footer (IDAT CRC-32, followed by IEND chunk) */
3984
0
  if (!tdefl_output_buffer_putter(
3985
0
          "\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) {
3986
0
    *pLen_out = 0;
3987
0
    MZ_FREE(pComp);
3988
0
    MZ_FREE(out_buf.m_pBuf);
3989
0
    return NULL;
3990
0
  }
3991
0
  c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4,
3992
0
                          *pLen_out + 4);
3993
0
  for (i = 0; i < 4; ++i, c <<= 8)
3994
0
    (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
3995
  /* compute final size of file, grab compressed data buffer and return */
3996
0
  *pLen_out += 57;
3997
0
  MZ_FREE(pComp);
3998
0
  return out_buf.m_pBuf;
3999
0
}
4000
void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h,
4001
0
                                              int num_chans, size_t *pLen_out) {
4002
  /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we
4003
   * can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's
4004
   * where #defined out) */
4005
0
  return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans,
4006
0
                                                    pLen_out, 6, MZ_FALSE);
4007
0
}
4008
4009
#ifndef MINIZ_NO_MALLOC
4010
/* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that
4011
 */
4012
/* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */
4013
/* structure size and allocation mechanism. */
4014
0
tdefl_compressor *tdefl_compressor_alloc() {
4015
0
  return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
4016
0
}
4017
4018
0
void tdefl_compressor_free(tdefl_compressor *pComp) { MZ_FREE(pComp); }
4019
#endif
4020
4021
#ifdef _MSC_VER
4022
#pragma warning(pop)
4023
#endif
4024
4025
#ifdef __cplusplus
4026
}
4027
#endif
4028
/**************************************************************************
4029
 *
4030
 * Copyright 2013-2014 RAD Game Tools and Valve Software
4031
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
4032
 * All Rights Reserved.
4033
 *
4034
 * Permission is hereby granted, free of charge, to any person obtaining a copy
4035
 * of this software and associated documentation files (the "Software"), to deal
4036
 * in the Software without restriction, including without limitation the rights
4037
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4038
 * copies of the Software, and to permit persons to whom the Software is
4039
 * furnished to do so, subject to the following conditions:
4040
 *
4041
 * The above copyright notice and this permission notice shall be included in
4042
 * all copies or substantial portions of the Software.
4043
 *
4044
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4045
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4046
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4047
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4048
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4049
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4050
 * THE SOFTWARE.
4051
 *
4052
 **************************************************************************/
4053
4054
#ifdef __cplusplus
4055
extern "C" {
4056
#endif
4057
4058
/* ------------------- Low-level Decompression (completely independent from all
4059
 * compression API's) */
4060
4061
0
#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
4062
0
#define TINFL_MEMSET(p, c, l) memset(p, c, l)
4063
4064
#define TINFL_CR_BEGIN                                                         \
4065
0
  switch (r->m_state) {                                                        \
4066
0
  case 0:
4067
#define TINFL_CR_RETURN(state_index, result)                                   \
4068
0
  do {                                                                         \
4069
0
    status = result;                                                           \
4070
0
    r->m_state = state_index;                                                  \
4071
0
    goto common_exit;                                                          \
4072
0
  case state_index:;                                                           \
4073
0
  }                                                                            \
4074
0
  MZ_MACRO_END
4075
#define TINFL_CR_RETURN_FOREVER(state_index, result)                           \
4076
0
  do {                                                                         \
4077
0
    for (;;) {                                                                 \
4078
0
      TINFL_CR_RETURN(state_index, result);                                    \
4079
0
    }                                                                          \
4080
0
  }                                                                            \
4081
0
  MZ_MACRO_END
4082
0
#define TINFL_CR_FINISH }
4083
4084
#define TINFL_GET_BYTE(state_index, c)                                         \
4085
0
  do {                                                                         \
4086
0
    while (pIn_buf_cur >= pIn_buf_end) {                                       \
4087
0
      TINFL_CR_RETURN(state_index,                                             \
4088
0
                      (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)               \
4089
0
                          ? TINFL_STATUS_NEEDS_MORE_INPUT                      \
4090
0
                          : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);         \
4091
0
    }                                                                          \
4092
0
    c = *pIn_buf_cur++;                                                        \
4093
0
  }                                                                            \
4094
0
  MZ_MACRO_END
4095
4096
#define TINFL_NEED_BITS(state_index, n)                                        \
4097
0
  do {                                                                         \
4098
0
    mz_uint c;                                                                 \
4099
0
    TINFL_GET_BYTE(state_index, c);                                            \
4100
0
    bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                             \
4101
0
    num_bits += 8;                                                             \
4102
0
  } while (num_bits < (mz_uint)(n))
4103
#define TINFL_SKIP_BITS(state_index, n)                                        \
4104
0
  do {                                                                         \
4105
0
    if (num_bits < (mz_uint)(n)) {                                             \
4106
0
      TINFL_NEED_BITS(state_index, n);                                         \
4107
0
    }                                                                          \
4108
0
    bit_buf >>= (n);                                                           \
4109
0
    num_bits -= (n);                                                           \
4110
0
  }                                                                            \
4111
0
  MZ_MACRO_END
4112
#define TINFL_GET_BITS(state_index, b, n)                                      \
4113
0
  do {                                                                         \
4114
0
    if (num_bits < (mz_uint)(n)) {                                             \
4115
0
      TINFL_NEED_BITS(state_index, n);                                         \
4116
0
    }                                                                          \
4117
0
    b = bit_buf & ((1 << (n)) - 1);                                            \
4118
0
    bit_buf >>= (n);                                                           \
4119
0
    num_bits -= (n);                                                           \
4120
0
  }                                                                            \
4121
0
  MZ_MACRO_END
4122
4123
/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes
4124
 * remaining in the input buffer falls below 2. */
4125
/* It reads just enough bytes from the input stream that are needed to decode
4126
 * the next Huffman code (and absolutely no more). It works by trying to fully
4127
 * decode a */
4128
/* Huffman code by using whatever bits are currently present in the bit buffer.
4129
 * If this fails, it reads another byte, and tries again until it succeeds or
4130
 * until the */
4131
/* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
4132
#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff)                             \
4133
0
  do {                                                                         \
4134
0
    temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)];         \
4135
0
    if (temp >= 0) {                                                           \
4136
0
      code_len = temp >> 9;                                                    \
4137
0
      if ((code_len) && (num_bits >= code_len))                                \
4138
0
        break;                                                                 \
4139
0
    } else if (num_bits > TINFL_FAST_LOOKUP_BITS) {                            \
4140
0
      code_len = TINFL_FAST_LOOKUP_BITS;                                       \
4141
0
      do {                                                                     \
4142
0
        temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];         \
4143
0
      } while ((temp < 0) && (num_bits >= (code_len + 1)));                    \
4144
0
      if (temp >= 0)                                                           \
4145
0
        break;                                                                 \
4146
0
    }                                                                          \
4147
0
    TINFL_GET_BYTE(state_index, c);                                            \
4148
0
    bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                             \
4149
0
    num_bits += 8;                                                             \
4150
0
  } while (num_bits < 15);
4151
4152
/* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex
4153
 * than you would initially expect because the zlib API expects the decompressor
4154
 * to never read */
4155
/* beyond the final byte of the deflate stream. (In other words, when this macro
4156
 * wants to read another byte from the input, it REALLY needs another byte in
4157
 * order to fully */
4158
/* decode the next Huffman code.) Handling this properly is particularly
4159
 * important on raw deflate (non-zlib) streams, which aren't followed by a byte
4160
 * aligned adler-32. */
4161
/* The slow path is only executed at the very end of the input buffer. */
4162
/* v1.16: The original macro handled the case at the very end of the passed-in
4163
 * input buffer, but we also need to handle the case where the user passes in
4164
 * 1+zillion bytes */
4165
/* following the deflate data and our non-conservative read-ahead path won't
4166
 * kick in here on this code. This is much trickier. */
4167
#define TINFL_HUFF_DECODE(state_index, sym, pHuff)                             \
4168
0
  do {                                                                         \
4169
0
    int temp;                                                                  \
4170
0
    mz_uint code_len, c;                                                       \
4171
0
    if (num_bits < 15) {                                                       \
4172
0
      if ((pIn_buf_end - pIn_buf_cur) < 2) {                                   \
4173
0
        TINFL_HUFF_BITBUF_FILL(state_index, pHuff);                            \
4174
0
      } else {                                                                 \
4175
0
        bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) |           \
4176
0
                   (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8));      \
4177
0
        pIn_buf_cur += 2;                                                      \
4178
0
        num_bits += 16;                                                        \
4179
0
      }                                                                        \
4180
0
    }                                                                          \
4181
0
    if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= \
4182
0
        0)                                                                     \
4183
0
      code_len = temp >> 9, temp &= 511;                                       \
4184
0
    else {                                                                     \
4185
0
      code_len = TINFL_FAST_LOOKUP_BITS;                                       \
4186
0
      do {                                                                     \
4187
0
        temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];         \
4188
0
      } while (temp < 0);                                                      \
4189
0
    }                                                                          \
4190
0
    sym = temp;                                                                \
4191
0
    bit_buf >>= code_len;                                                      \
4192
0
    num_bits -= code_len;                                                      \
4193
0
  }                                                                            \
4194
0
  MZ_MACRO_END
4195
4196
tinfl_status tinfl_decompress(tinfl_decompressor *r,
4197
                              const mz_uint8 *pIn_buf_next,
4198
                              size_t *pIn_buf_size, mz_uint8 *pOut_buf_start,
4199
                              mz_uint8 *pOut_buf_next, size_t *pOut_buf_size,
4200
0
                              const mz_uint32 decomp_flags) {
4201
0
  static const int s_length_base[31] = {
4202
0
      3,  4,  5,  6,  7,  8,  9,  10,  11,  13,  15,  17,  19,  23, 27, 31,
4203
0
      35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0,  0};
4204
0
  static const int s_length_extra[31] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
4205
0
                                         1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4,
4206
0
                                         4, 4, 5, 5, 5, 5, 0, 0, 0};
4207
0
  static const int s_dist_base[32] = {
4208
0
      1,    2,    3,    4,    5,    7,     9,     13,    17,  25,   33,
4209
0
      49,   65,   97,   129,  193,  257,   385,   513,   769, 1025, 1537,
4210
0
      2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0,   0};
4211
0
  static const int s_dist_extra[32] = {0, 0, 0,  0,  1,  1,  2,  2,  3,  3,
4212
0
                                       4, 4, 5,  5,  6,  6,  7,  7,  8,  8,
4213
0
                                       9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
4214
0
  static const mz_uint8 s_length_dezigzag[19] = {
4215
0
      16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
4216
0
  static const int s_min_table_sizes[3] = {257, 1, 4};
4217
4218
0
  tinfl_status status = TINFL_STATUS_FAILED;
4219
0
  mz_uint32 num_bits, dist, counter, num_extra;
4220
0
  tinfl_bit_buf_t bit_buf;
4221
0
  const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end =
4222
0
                                                  pIn_buf_next + *pIn_buf_size;
4223
0
  mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end =
4224
0
                                              pOut_buf_next + *pOut_buf_size;
4225
0
  size_t out_buf_size_mask =
4226
0
             (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)
4227
0
                 ? (size_t)-1
4228
0
                 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1,
4229
0
         dist_from_out_buf_start;
4230
4231
  /* Ensure the output buffer's size is a power of 2, unless the output buffer
4232
   * is large enough to hold the entire output file (in which case it doesn't
4233
   * matter). */
4234
0
  if (((out_buf_size_mask + 1) & out_buf_size_mask) ||
4235
0
      (pOut_buf_next < pOut_buf_start)) {
4236
0
    *pIn_buf_size = *pOut_buf_size = 0;
4237
0
    return TINFL_STATUS_BAD_PARAM;
4238
0
  }
4239
4240
0
  num_bits = r->m_num_bits;
4241
0
  bit_buf = r->m_bit_buf;
4242
0
  dist = r->m_dist;
4243
0
  counter = r->m_counter;
4244
0
  num_extra = r->m_num_extra;
4245
0
  dist_from_out_buf_start = r->m_dist_from_out_buf_start;
4246
0
  TINFL_CR_BEGIN
4247
4248
0
  bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
4249
0
  r->m_z_adler32 = r->m_check_adler32 = 1;
4250
0
  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) {
4251
0
    TINFL_GET_BYTE(1, r->m_zhdr0);
4252
0
    TINFL_GET_BYTE(2, r->m_zhdr1);
4253
0
    counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) ||
4254
0
               (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
4255
0
    if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
4256
0
      counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) ||
4257
0
                  ((out_buf_size_mask + 1) <
4258
0
                   (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
4259
0
    if (counter) {
4260
0
      TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
4261
0
    }
4262
0
  }
4263
4264
0
  do {
4265
0
    TINFL_GET_BITS(3, r->m_final, 3);
4266
0
    r->m_type = r->m_final >> 1;
4267
0
    if (r->m_type == 0) {
4268
0
      TINFL_SKIP_BITS(5, num_bits & 7);
4269
0
      for (counter = 0; counter < 4; ++counter) {
4270
0
        if (num_bits)
4271
0
          TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
4272
0
        else
4273
0
          TINFL_GET_BYTE(7, r->m_raw_header[counter]);
4274
0
      }
4275
0
      if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) !=
4276
0
          (mz_uint)(0xFFFF ^
4277
0
                    (r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) {
4278
0
        TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
4279
0
      }
4280
0
      while ((counter) && (num_bits)) {
4281
0
        TINFL_GET_BITS(51, dist, 8);
4282
0
        while (pOut_buf_cur >= pOut_buf_end) {
4283
0
          TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
4284
0
        }
4285
0
        *pOut_buf_cur++ = (mz_uint8)dist;
4286
0
        counter--;
4287
0
      }
4288
0
      while (counter) {
4289
0
        size_t n;
4290
0
        while (pOut_buf_cur >= pOut_buf_end) {
4291
0
          TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
4292
0
        }
4293
0
        while (pIn_buf_cur >= pIn_buf_end) {
4294
0
          TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT)
4295
0
                                  ? TINFL_STATUS_NEEDS_MORE_INPUT
4296
0
                                  : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);
4297
0
        }
4298
0
        n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur),
4299
0
                          (size_t)(pIn_buf_end - pIn_buf_cur)),
4300
0
                   counter);
4301
0
        TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
4302
0
        pIn_buf_cur += n;
4303
0
        pOut_buf_cur += n;
4304
0
        counter -= (mz_uint)n;
4305
0
      }
4306
0
    } else if (r->m_type == 3) {
4307
0
      TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
4308
0
    } else {
4309
0
      if (r->m_type == 1) {
4310
0
        mz_uint8 *p = r->m_tables[0].m_code_size;
4311
0
        mz_uint i;
4312
0
        r->m_table_sizes[0] = 288;
4313
0
        r->m_table_sizes[1] = 32;
4314
0
        TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
4315
0
        for (i = 0; i <= 143; ++i)
4316
0
          *p++ = 8;
4317
0
        for (; i <= 255; ++i)
4318
0
          *p++ = 9;
4319
0
        for (; i <= 279; ++i)
4320
0
          *p++ = 7;
4321
0
        for (; i <= 287; ++i)
4322
0
          *p++ = 8;
4323
0
      } else {
4324
0
        for (counter = 0; counter < 3; counter++) {
4325
0
          TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
4326
0
          r->m_table_sizes[counter] += s_min_table_sizes[counter];
4327
0
        }
4328
0
        MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
4329
0
        for (counter = 0; counter < r->m_table_sizes[2]; counter++) {
4330
0
          mz_uint s;
4331
0
          TINFL_GET_BITS(14, s, 3);
4332
0
          r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
4333
0
        }
4334
0
        r->m_table_sizes[2] = 19;
4335
0
      }
4336
0
      for (; (int)r->m_type >= 0; r->m_type--) {
4337
0
        int tree_next, tree_cur;
4338
0
        tinfl_huff_table *pTable;
4339
0
        mz_uint i, j, used_syms, total, sym_index, next_code[17],
4340
0
            total_syms[16];
4341
0
        pTable = &r->m_tables[r->m_type];
4342
0
        MZ_CLEAR_OBJ(total_syms);
4343
0
        MZ_CLEAR_OBJ(pTable->m_look_up);
4344
0
        MZ_CLEAR_OBJ(pTable->m_tree);
4345
0
        for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
4346
0
          total_syms[pTable->m_code_size[i]]++;
4347
0
        used_syms = 0, total = 0;
4348
0
        next_code[0] = next_code[1] = 0;
4349
0
        for (i = 1; i <= 15; ++i) {
4350
0
          used_syms += total_syms[i];
4351
0
          next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
4352
0
        }
4353
0
        if ((65536 != total) && (used_syms > 1)) {
4354
0
          TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
4355
0
        }
4356
0
        for (tree_next = -1, sym_index = 0;
4357
0
             sym_index < r->m_table_sizes[r->m_type]; ++sym_index) {
4358
0
          mz_uint rev_code = 0, l, cur_code,
4359
0
                  code_size = pTable->m_code_size[sym_index];
4360
4361
0
          if (!code_size)
4362
0
            continue;
4363
0
          cur_code = next_code[code_size]++;
4364
0
          for (l = code_size; l > 0; l--, cur_code >>= 1)
4365
0
            rev_code = (rev_code << 1) | (cur_code & 1);
4366
0
          if (code_size <= TINFL_FAST_LOOKUP_BITS) {
4367
0
            mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
4368
0
            while (rev_code < TINFL_FAST_LOOKUP_SIZE) {
4369
0
              pTable->m_look_up[rev_code] = k;
4370
0
              rev_code += (1 << code_size);
4371
0
            }
4372
0
            continue;
4373
0
          }
4374
0
          if (0 ==
4375
0
              (tree_cur = pTable->m_look_up[rev_code &
4376
0
                                            (TINFL_FAST_LOOKUP_SIZE - 1)])) {
4377
0
            pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] =
4378
0
                (mz_int16)tree_next;
4379
0
            tree_cur = tree_next;
4380
0
            tree_next -= 2;
4381
0
          }
4382
0
          rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
4383
0
          for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) {
4384
0
            tree_cur -= ((rev_code >>= 1) & 1);
4385
0
            if (!pTable->m_tree[-tree_cur - 1]) {
4386
0
              pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
4387
0
              tree_cur = tree_next;
4388
0
              tree_next -= 2;
4389
0
            } else
4390
0
              tree_cur = pTable->m_tree[-tree_cur - 1];
4391
0
          }
4392
0
          tree_cur -= ((rev_code >>= 1) & 1);
4393
0
          (void)rev_code; // unused
4394
0
          pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
4395
0
        }
4396
0
        if (r->m_type == 2) {
4397
0
          for (counter = 0;
4398
0
               counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) {
4399
0
            mz_uint s;
4400
0
            TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
4401
0
            if (dist < 16) {
4402
0
              r->m_len_codes[counter++] = (mz_uint8)dist;
4403
0
              continue;
4404
0
            }
4405
0
            if ((dist == 16) && (!counter)) {
4406
0
              TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
4407
0
            }
4408
0
            num_extra = "\02\03\07"[dist - 16];
4409
0
            TINFL_GET_BITS(18, s, num_extra);
4410
0
            s += "\03\03\013"[dist - 16];
4411
0
            TINFL_MEMSET(r->m_len_codes + counter,
4412
0
                         (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
4413
0
            counter += s;
4414
0
          }
4415
0
          if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) {
4416
0
            TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
4417
0
          }
4418
0
          TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes,
4419
0
                       r->m_table_sizes[0]);
4420
0
          TINFL_MEMCPY(r->m_tables[1].m_code_size,
4421
0
                       r->m_len_codes + r->m_table_sizes[0],
4422
0
                       r->m_table_sizes[1]);
4423
0
        }
4424
0
      }
4425
0
      for (;;) {
4426
0
        mz_uint8 *pSrc;
4427
0
        for (;;) {
4428
0
          if (((pIn_buf_end - pIn_buf_cur) < 4) ||
4429
0
              ((pOut_buf_end - pOut_buf_cur) < 2)) {
4430
0
            TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
4431
0
            if (counter >= 256)
4432
0
              break;
4433
0
            while (pOut_buf_cur >= pOut_buf_end) {
4434
0
              TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
4435
0
            }
4436
0
            *pOut_buf_cur++ = (mz_uint8)counter;
4437
0
          } else {
4438
0
            int sym2;
4439
0
            mz_uint code_len;
4440
0
#if TINFL_USE_64BIT_BITBUF
4441
0
            if (num_bits < 30) {
4442
0
              bit_buf |=
4443
0
                  (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
4444
0
              pIn_buf_cur += 4;
4445
0
              num_bits += 32;
4446
0
            }
4447
#else
4448
            if (num_bits < 15) {
4449
              bit_buf |=
4450
                  (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
4451
              pIn_buf_cur += 2;
4452
              num_bits += 16;
4453
            }
4454
#endif
4455
0
            if ((sym2 =
4456
0
                     r->m_tables[0]
4457
0
                         .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
4458
0
                0)
4459
0
              code_len = sym2 >> 9;
4460
0
            else {
4461
0
              code_len = TINFL_FAST_LOOKUP_BITS;
4462
0
              do {
4463
0
                sym2 = r->m_tables[0]
4464
0
                           .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
4465
0
              } while (sym2 < 0);
4466
0
            }
4467
0
            counter = sym2;
4468
0
            bit_buf >>= code_len;
4469
0
            num_bits -= code_len;
4470
0
            if (counter & 256)
4471
0
              break;
4472
4473
#if !TINFL_USE_64BIT_BITBUF
4474
            if (num_bits < 15) {
4475
              bit_buf |=
4476
                  (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
4477
              pIn_buf_cur += 2;
4478
              num_bits += 16;
4479
            }
4480
#endif
4481
0
            if ((sym2 =
4482
0
                     r->m_tables[0]
4483
0
                         .m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >=
4484
0
                0)
4485
0
              code_len = sym2 >> 9;
4486
0
            else {
4487
0
              code_len = TINFL_FAST_LOOKUP_BITS;
4488
0
              do {
4489
0
                sym2 = r->m_tables[0]
4490
0
                           .m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
4491
0
              } while (sym2 < 0);
4492
0
            }
4493
0
            bit_buf >>= code_len;
4494
0
            num_bits -= code_len;
4495
4496
0
            pOut_buf_cur[0] = (mz_uint8)counter;
4497
0
            if (sym2 & 256) {
4498
0
              pOut_buf_cur++;
4499
0
              counter = sym2;
4500
0
              break;
4501
0
            }
4502
0
            pOut_buf_cur[1] = (mz_uint8)sym2;
4503
0
            pOut_buf_cur += 2;
4504
0
          }
4505
0
        }
4506
0
        if ((counter &= 511) == 256)
4507
0
          break;
4508
4509
0
        num_extra = s_length_extra[counter - 257];
4510
0
        counter = s_length_base[counter - 257];
4511
0
        if (num_extra) {
4512
0
          mz_uint extra_bits;
4513
0
          TINFL_GET_BITS(25, extra_bits, num_extra);
4514
0
          counter += extra_bits;
4515
0
        }
4516
4517
0
        TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
4518
0
        num_extra = s_dist_extra[dist];
4519
0
        dist = s_dist_base[dist];
4520
0
        if (num_extra) {
4521
0
          mz_uint extra_bits;
4522
0
          TINFL_GET_BITS(27, extra_bits, num_extra);
4523
0
          dist += extra_bits;
4524
0
        }
4525
4526
0
        dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
4527
0
        if ((dist == 0 || dist > dist_from_out_buf_start ||
4528
0
             dist_from_out_buf_start == 0) &&
4529
0
            (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) {
4530
0
          TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
4531
0
        }
4532
4533
0
        pSrc = pOut_buf_start +
4534
0
               ((dist_from_out_buf_start - dist) & out_buf_size_mask);
4535
4536
0
        if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) {
4537
0
          while (counter--) {
4538
0
            while (pOut_buf_cur >= pOut_buf_end) {
4539
0
              TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
4540
0
            }
4541
0
            *pOut_buf_cur++ =
4542
0
                pOut_buf_start[(dist_from_out_buf_start++ - dist) &
4543
0
                               out_buf_size_mask];
4544
0
          }
4545
0
          continue;
4546
0
        }
4547
0
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
4548
0
        else if ((counter >= 9) && (counter <= dist)) {
4549
0
          const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
4550
0
          do {
4551
0
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
4552
0
            memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32) * 2);
4553
#else
4554
            ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
4555
            ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
4556
#endif
4557
0
            pOut_buf_cur += 8;
4558
0
          } while ((pSrc += 8) < pSrc_end);
4559
0
          if ((counter &= 7) < 3) {
4560
0
            if (counter) {
4561
0
              pOut_buf_cur[0] = pSrc[0];
4562
0
              if (counter > 1)
4563
0
                pOut_buf_cur[1] = pSrc[1];
4564
0
              pOut_buf_cur += counter;
4565
0
            }
4566
0
            continue;
4567
0
          }
4568
0
        }
4569
0
#endif
4570
0
        while (counter > 2) {
4571
0
          pOut_buf_cur[0] = pSrc[0];
4572
0
          pOut_buf_cur[1] = pSrc[1];
4573
0
          pOut_buf_cur[2] = pSrc[2];
4574
0
          pOut_buf_cur += 3;
4575
0
          pSrc += 3;
4576
0
          counter -= 3;
4577
0
        }
4578
0
        if (counter > 0) {
4579
0
          pOut_buf_cur[0] = pSrc[0];
4580
0
          if (counter > 1)
4581
0
            pOut_buf_cur[1] = pSrc[1];
4582
0
          pOut_buf_cur += counter;
4583
0
        }
4584
0
      }
4585
0
    }
4586
0
  } while (!(r->m_final & 1));
4587
4588
  /* Ensure byte alignment and put back any bytes from the bitbuf if we've
4589
   * looked ahead too far on gzip, or other Deflate streams followed by
4590
   * arbitrary data. */
4591
  /* I'm being super conservative here. A number of simplifications can be made
4592
   * to the byte alignment part, and the Adler32 check shouldn't ever need to
4593
   * worry about reading from the bitbuf now. */
4594
0
  TINFL_SKIP_BITS(32, num_bits & 7);
4595
0
  while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) {
4596
0
    --pIn_buf_cur;
4597
0
    num_bits -= 8;
4598
0
  }
4599
0
  bit_buf &= (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
4600
0
  MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond the end
4601
                           of non-deflate/zlib streams with following data (such
4602
                           as gzip streams). */
4603
4604
0
  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) {
4605
0
    for (counter = 0; counter < 4; ++counter) {
4606
0
      mz_uint s;
4607
0
      if (num_bits)
4608
0
        TINFL_GET_BITS(41, s, 8);
4609
0
      else
4610
0
        TINFL_GET_BYTE(42, s);
4611
0
      r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
4612
0
    }
4613
0
  }
4614
0
  TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
4615
4616
0
  TINFL_CR_FINISH
4617
4618
0
common_exit:
4619
  /* As long as we aren't telling the caller that we NEED more input to make
4620
   * forward progress: */
4621
  /* Put back any bytes from the bitbuf in case we've looked ahead too far on
4622
   * gzip, or other Deflate streams followed by arbitrary data. */
4623
  /* We need to be very careful here to NOT push back any bytes we definitely
4624
   * know we need to make forward progress, though, or we'll lock the caller up
4625
   * into an inf loop. */
4626
0
  if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) &&
4627
0
      (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS)) {
4628
0
    while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8)) {
4629
0
      --pIn_buf_cur;
4630
0
      num_bits -= 8;
4631
0
    }
4632
0
  }
4633
0
  r->m_num_bits = num_bits;
4634
0
  r->m_bit_buf =
4635
0
      bit_buf & (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
4636
0
  r->m_dist = dist;
4637
0
  r->m_counter = counter;
4638
0
  r->m_num_extra = num_extra;
4639
0
  r->m_dist_from_out_buf_start = dist_from_out_buf_start;
4640
0
  *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
4641
0
  *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
4642
0
  if ((decomp_flags &
4643
0
       (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) &&
4644
0
      (status >= 0)) {
4645
0
    const mz_uint8 *ptr = pOut_buf_next;
4646
0
    size_t buf_len = *pOut_buf_size;
4647
0
    mz_uint32 i, s1 = r->m_check_adler32 & 0xffff,
4648
0
                 s2 = r->m_check_adler32 >> 16;
4649
0
    size_t block_len = buf_len % 5552;
4650
0
    while (buf_len) {
4651
0
      for (i = 0; i + 7 < block_len; i += 8, ptr += 8) {
4652
0
        s1 += ptr[0], s2 += s1;
4653
0
        s1 += ptr[1], s2 += s1;
4654
0
        s1 += ptr[2], s2 += s1;
4655
0
        s1 += ptr[3], s2 += s1;
4656
0
        s1 += ptr[4], s2 += s1;
4657
0
        s1 += ptr[5], s2 += s1;
4658
0
        s1 += ptr[6], s2 += s1;
4659
0
        s1 += ptr[7], s2 += s1;
4660
0
      }
4661
0
      for (; i < block_len; ++i)
4662
0
        s1 += *ptr++, s2 += s1;
4663
0
      s1 %= 65521U, s2 %= 65521U;
4664
0
      buf_len -= block_len;
4665
0
      block_len = 5552;
4666
0
    }
4667
0
    r->m_check_adler32 = (s2 << 16) + s1;
4668
0
    if ((status == TINFL_STATUS_DONE) &&
4669
0
        (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) &&
4670
0
        (r->m_check_adler32 != r->m_z_adler32))
4671
0
      status = TINFL_STATUS_ADLER32_MISMATCH;
4672
0
  }
4673
0
  return status;
4674
0
}
4675
4676
/* Higher level helper functions. */
4677
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
4678
0
                                   size_t *pOut_len, int flags) {
4679
0
  tinfl_decompressor decomp;
4680
0
  void *pBuf = NULL, *pNew_buf;
4681
0
  size_t src_buf_ofs = 0, out_buf_capacity = 0;
4682
0
  *pOut_len = 0;
4683
0
  tinfl_init(&decomp);
4684
0
  for (;;) {
4685
0
    size_t src_buf_size = src_buf_len - src_buf_ofs,
4686
0
           dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
4687
0
    tinfl_status status = tinfl_decompress(
4688
0
        &decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size,
4689
0
        (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL,
4690
0
        &dst_buf_size,
4691
0
        (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
4692
0
            TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
4693
0
    if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) {
4694
0
      MZ_FREE(pBuf);
4695
0
      *pOut_len = 0;
4696
0
      return NULL;
4697
0
    }
4698
0
    src_buf_ofs += src_buf_size;
4699
0
    *pOut_len += dst_buf_size;
4700
0
    if (status == TINFL_STATUS_DONE)
4701
0
      break;
4702
0
    new_out_buf_capacity = out_buf_capacity * 2;
4703
0
    if (new_out_buf_capacity < 128)
4704
0
      new_out_buf_capacity = 128;
4705
0
    pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
4706
0
    if (!pNew_buf) {
4707
0
      MZ_FREE(pBuf);
4708
0
      *pOut_len = 0;
4709
0
      return NULL;
4710
0
    }
4711
0
    pBuf = pNew_buf;
4712
0
    out_buf_capacity = new_out_buf_capacity;
4713
0
  }
4714
0
  return pBuf;
4715
0
}
4716
4717
size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len,
4718
                                   const void *pSrc_buf, size_t src_buf_len,
4719
0
                                   int flags) {
4720
0
  tinfl_decompressor decomp;
4721
0
  tinfl_status status;
4722
0
  tinfl_init(&decomp);
4723
0
  status =
4724
0
      tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len,
4725
0
                       (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len,
4726
0
                       (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
4727
0
                           TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
4728
0
  return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED
4729
0
                                       : out_buf_len;
4730
0
}
4731
4732
int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
4733
                                     tinfl_put_buf_func_ptr pPut_buf_func,
4734
0
                                     void *pPut_buf_user, int flags) {
4735
0
  int result = 0;
4736
0
  tinfl_decompressor decomp;
4737
0
  mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
4738
0
  size_t in_buf_ofs = 0, dict_ofs = 0;
4739
0
  if (!pDict)
4740
0
    return TINFL_STATUS_FAILED;
4741
0
  tinfl_init(&decomp);
4742
0
  for (;;) {
4743
0
    size_t in_buf_size = *pIn_buf_size - in_buf_ofs,
4744
0
           dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
4745
0
    tinfl_status status =
4746
0
        tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs,
4747
0
                         &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
4748
0
                         (flags & ~(TINFL_FLAG_HAS_MORE_INPUT |
4749
0
                                    TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
4750
0
    in_buf_ofs += in_buf_size;
4751
0
    if ((dst_buf_size) &&
4752
0
        (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
4753
0
      break;
4754
0
    if (status != TINFL_STATUS_HAS_MORE_OUTPUT) {
4755
0
      result = (status == TINFL_STATUS_DONE);
4756
0
      break;
4757
0
    }
4758
0
    dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
4759
0
  }
4760
0
  MZ_FREE(pDict);
4761
0
  *pIn_buf_size = in_buf_ofs;
4762
0
  return result;
4763
0
}
4764
4765
#ifndef MINIZ_NO_MALLOC
4766
0
tinfl_decompressor *tinfl_decompressor_alloc() {
4767
0
  tinfl_decompressor *pDecomp =
4768
0
      (tinfl_decompressor *)MZ_MALLOC(sizeof(tinfl_decompressor));
4769
0
  if (pDecomp)
4770
0
    tinfl_init(pDecomp);
4771
0
  return pDecomp;
4772
0
}
4773
4774
0
void tinfl_decompressor_free(tinfl_decompressor *pDecomp) { MZ_FREE(pDecomp); }
4775
#endif
4776
4777
#ifdef __cplusplus
4778
}
4779
#endif
4780
/**************************************************************************
4781
 *
4782
 * Copyright 2013-2014 RAD Game Tools and Valve Software
4783
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
4784
 * Copyright 2016 Martin Raiber
4785
 * All Rights Reserved.
4786
 *
4787
 * Permission is hereby granted, free of charge, to any person obtaining a copy
4788
 * of this software and associated documentation files (the "Software"), to deal
4789
 * in the Software without restriction, including without limitation the rights
4790
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4791
 * copies of the Software, and to permit persons to whom the Software is
4792
 * furnished to do so, subject to the following conditions:
4793
 *
4794
 * The above copyright notice and this permission notice shall be included in
4795
 * all copies or substantial portions of the Software.
4796
 *
4797
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4798
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4799
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4800
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4801
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4802
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4803
 * THE SOFTWARE.
4804
 *
4805
 **************************************************************************/
4806
4807
#ifndef MINIZ_NO_ARCHIVE_APIS
4808
4809
#ifdef __cplusplus
4810
extern "C" {
4811
#endif
4812
4813
/* ------------------- .ZIP archive reading */
4814
4815
#ifdef MINIZ_NO_STDIO
4816
#define MZ_FILE void *
4817
#else
4818
#include <sys/stat.h>
4819
4820
#if defined(_MSC_VER)
4821
#include <windows.h>
4822
#ifndef MINIZ_NO_TIME
4823
#include <sys/utime.h>
4824
#endif
4825
static wchar_t *str2wstr(const char *str) {
4826
  size_t len = strlen(str) + 1;
4827
  wchar_t *wstr = (wchar_t *)malloc(len * sizeof(wchar_t));
4828
  MultiByteToWideChar(CP_UTF8, 0, str, (int)(len * sizeof(char)), wstr,
4829
                      (int)len);
4830
  return wstr;
4831
}
4832
4833
static FILE *mz_fopen(const char *pFilename, const char *pMode) {
4834
  FILE *pFile = NULL;
4835
  wchar_t *wFilename = str2wstr(pFilename);
4836
  wchar_t *wMode = str2wstr(pMode);
4837
4838
  _wfopen_s(&pFile, wFilename, wMode);
4839
4840
  free(wFilename);
4841
  free(wMode);
4842
4843
  return pFile;
4844
}
4845
4846
static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) {
4847
  FILE *pFile = NULL;
4848
  int res = 0;
4849
4850
  wchar_t *wPath = str2wstr(pPath);
4851
  wchar_t *wMode = str2wstr(pMode);
4852
4853
  res = _wfreopen_s(&pFile, wPath, wMode, pStream);
4854
4855
  free(wPath);
4856
  free(wMode);
4857
4858
  if (res) {
4859
    return NULL;
4860
  }
4861
4862
  return pFile;
4863
}
4864
4865
static int mz_stat(const char *pPath, struct _stat64 *buffer) {
4866
  wchar_t *wPath = str2wstr(pPath);
4867
  int res = _wstat64(wPath, buffer);
4868
4869
  free(wPath);
4870
4871
  return res;
4872
}
4873
4874
static int mz_mkdir(const char *pDirname) {
4875
  wchar_t *wDirname = str2wstr(pDirname);
4876
  int res = _wmkdir(wDirname);
4877
4878
  free(wDirname);
4879
4880
  return res;
4881
}
4882
4883
#define MZ_FOPEN mz_fopen
4884
#define MZ_FCLOSE fclose
4885
#define MZ_FREAD fread
4886
#define MZ_FWRITE fwrite
4887
#define MZ_FTELL64 _ftelli64
4888
#define MZ_FSEEK64 _fseeki64
4889
#define MZ_FILE_STAT_STRUCT _stat64
4890
#define MZ_FILE_STAT mz_stat
4891
#define MZ_FFLUSH fflush
4892
#define MZ_FREOPEN mz_freopen
4893
#define MZ_DELETE_FILE remove
4894
#define MZ_MKDIR(d) mz_mkdir(d)
4895
4896
4897
#elif defined(__MINGW32__) || defined(__MINGW64__)
4898
#include <windows.h>
4899
#ifndef MINIZ_NO_TIME
4900
#include <sys/utime.h>
4901
#endif
4902
4903
#define MZ_FOPEN(f, m) fopen(f, m)
4904
#define MZ_FCLOSE fclose
4905
#define MZ_FREAD fread
4906
#define MZ_FWRITE fwrite
4907
#define MZ_FTELL64 ftell
4908
#define MZ_FSEEK64 fseek
4909
#define MZ_FILE_STAT_STRUCT stat
4910
#define MZ_FILE_STAT stat
4911
#define MZ_FFLUSH fflush
4912
#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4913
#define MZ_DELETE_FILE remove
4914
#define MZ_MKDIR(d) _mkdir(d)
4915
4916
#elif defined(__TINYC__)
4917
#ifndef MINIZ_NO_TIME
4918
#include <sys/utime.h>
4919
#endif
4920
4921
#define MZ_FOPEN(f, m) fopen(f, m)
4922
#define MZ_FCLOSE fclose
4923
#define MZ_FREAD fread
4924
#define MZ_FWRITE fwrite
4925
#define MZ_FTELL64 ftell
4926
#define MZ_FSEEK64 fseek
4927
#define MZ_FILE_STAT_STRUCT stat
4928
#define MZ_FILE_STAT stat
4929
#define MZ_FFLUSH fflush
4930
#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4931
#define MZ_DELETE_FILE remove
4932
#define MZ_MKDIR(d) mkdir(d, 0755)
4933
4934
#elif defined(__USE_LARGEFILE64) /* gcc, clang */
4935
#ifndef MINIZ_NO_TIME
4936
#include <utime.h>
4937
#endif
4938
4939
#define MZ_FOPEN(f, m) fopen64(f, m)
4940
#define MZ_FCLOSE fclose
4941
#define MZ_FREAD fread
4942
#define MZ_FWRITE fwrite
4943
#define MZ_FTELL64 ftello64
4944
#define MZ_FSEEK64 fseeko64
4945
#define MZ_FILE_STAT_STRUCT stat64
4946
#define MZ_FILE_STAT stat64
4947
#define MZ_FFLUSH fflush
4948
#define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
4949
#define MZ_DELETE_FILE remove
4950
#define MZ_MKDIR(d) mkdir(d, 0755)
4951
4952
#elif defined(__APPLE__)
4953
#ifndef MINIZ_NO_TIME
4954
#include <utime.h>
4955
#endif
4956
4957
#define MZ_FOPEN(f, m) fopen(f, m)
4958
#define MZ_FCLOSE fclose
4959
#define MZ_FREAD fread
4960
#define MZ_FWRITE fwrite
4961
#define MZ_FTELL64 ftello
4962
#define MZ_FSEEK64 fseeko
4963
#define MZ_FILE_STAT_STRUCT stat
4964
#define MZ_FILE_STAT stat
4965
#define MZ_FFLUSH fflush
4966
#define MZ_FREOPEN(p, m, s) freopen(p, m, s)
4967
#define MZ_DELETE_FILE remove
4968
#define MZ_MKDIR(d) mkdir(d, 0755)
4969
4970
#else
4971
#pragma message(                                                               \
4972
    "Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.")
4973
#ifndef MINIZ_NO_TIME
4974
#include <utime.h>
4975
#endif
4976
4977
0
#define MZ_FOPEN(f, m) fopen(f, m)
4978
0
#define MZ_FCLOSE fclose
4979
0
#define MZ_FREAD fread
4980
0
#define MZ_FWRITE fwrite
4981
#ifdef __STRICT_ANSI__
4982
#define MZ_FTELL64 ftell
4983
#define MZ_FSEEK64 fseek
4984
#else
4985
0
#define MZ_FTELL64 ftello
4986
0
#define MZ_FSEEK64 fseeko
4987
#endif
4988
#define MZ_FILE_STAT_STRUCT stat
4989
0
#define MZ_FILE_STAT stat
4990
0
#define MZ_FFLUSH fflush
4991
0
#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
4992
0
#define MZ_DELETE_FILE remove
4993
0
#define MZ_MKDIR(d) mkdir(d, 0755)
4994
4995
#endif /* #ifdef _MSC_VER */
4996
#endif /* #ifdef MINIZ_NO_STDIO */
4997
4998
0
#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
4999
5000
/* Various ZIP archive enums. To completely avoid cross platform compiler
5001
 * alignment and platform endian issues, miniz.c doesn't use structs for any of
5002
 * this stuff. */
5003
enum {
5004
  /* ZIP archive identifiers and record sizes */
5005
  MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
5006
  MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
5007
  MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
5008
  MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
5009
  MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
5010
  MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
5011
5012
  /* ZIP64 archive identifier and record sizes */
5013
  MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
5014
  MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
5015
  MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
5016
  MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
5017
  MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
5018
  MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
5019
  MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
5020
  MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
5021
5022
  /* Central directory header record offsets */
5023
  MZ_ZIP_CDH_SIG_OFS = 0,
5024
  MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
5025
  MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
5026
  MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
5027
  MZ_ZIP_CDH_METHOD_OFS = 10,
5028
  MZ_ZIP_CDH_FILE_TIME_OFS = 12,
5029
  MZ_ZIP_CDH_FILE_DATE_OFS = 14,
5030
  MZ_ZIP_CDH_CRC32_OFS = 16,
5031
  MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
5032
  MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
5033
  MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
5034
  MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
5035
  MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
5036
  MZ_ZIP_CDH_DISK_START_OFS = 34,
5037
  MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
5038
  MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
5039
  MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
5040
5041
  /* Local directory header offsets */
5042
  MZ_ZIP_LDH_SIG_OFS = 0,
5043
  MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
5044
  MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
5045
  MZ_ZIP_LDH_METHOD_OFS = 8,
5046
  MZ_ZIP_LDH_FILE_TIME_OFS = 10,
5047
  MZ_ZIP_LDH_FILE_DATE_OFS = 12,
5048
  MZ_ZIP_LDH_CRC32_OFS = 14,
5049
  MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
5050
  MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
5051
  MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
5052
  MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
5053
  MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3,
5054
5055
  /* End of central directory offsets */
5056
  MZ_ZIP_ECDH_SIG_OFS = 0,
5057
  MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
5058
  MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
5059
  MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
5060
  MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
5061
  MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
5062
  MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
5063
  MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
5064
5065
  /* ZIP64 End of central directory locator offsets */
5066
  MZ_ZIP64_ECDL_SIG_OFS = 0,                    /* 4 bytes */
5067
  MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4,          /* 4 bytes */
5068
  MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8,  /* 8 bytes */
5069
  MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
5070
5071
  /* ZIP64 End of central directory header offsets */
5072
  MZ_ZIP64_ECDH_SIG_OFS = 0,                       /* 4 bytes */
5073
  MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4,            /* 8 bytes */
5074
  MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12,          /* 2 bytes */
5075
  MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14,           /* 2 bytes */
5076
  MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16,            /* 4 bytes */
5077
  MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20,            /* 4 bytes */
5078
  MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
5079
  MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32,       /* 8 bytes */
5080
  MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40,                /* 8 bytes */
5081
  MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48,                 /* 8 bytes */
5082
  MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
5083
  MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
5084
  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
5085
  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
5086
  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
5087
  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
5088
  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
5089
};
5090
5091
typedef struct {
5092
  void *m_p;
5093
  size_t m_size, m_capacity;
5094
  mz_uint m_element_size;
5095
} mz_zip_array;
5096
5097
struct mz_zip_internal_state_tag {
5098
  mz_zip_array m_central_dir;
5099
  mz_zip_array m_central_dir_offsets;
5100
  mz_zip_array m_sorted_central_dir_offsets;
5101
5102
  /* The flags passed in when the archive is initially opened. */
5103
  uint32_t m_init_flags;
5104
5105
  /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc.
5106
   */
5107
  mz_bool m_zip64;
5108
5109
  /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64
5110
   * will also be slammed to true too, even if we didn't find a zip64 end of
5111
   * central dir header, etc.) */
5112
  mz_bool m_zip64_has_extended_info_fields;
5113
5114
  /* These fields are used by the file, FILE, memory, and memory/heap read/write
5115
   * helpers. */
5116
  MZ_FILE *m_pFile;
5117
  mz_uint64 m_file_archive_start_ofs;
5118
5119
  void *m_pMem;
5120
  size_t m_mem_size;
5121
  size_t m_mem_capacity;
5122
};
5123
5124
#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size)                 \
5125
0
  (array_ptr)->m_element_size = element_size
5126
5127
#if defined(DEBUG) || defined(_DEBUG)
5128
static MZ_FORCEINLINE mz_uint
5129
mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index) {
5130
  MZ_ASSERT(index < pArray->m_size);
5131
  return index;
5132
}
5133
#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index)                   \
5134
  ((element_type *)((array_ptr)                                                \
5135
                        ->m_p))[mz_zip_array_range_check(array_ptr, index)]
5136
#else
5137
#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index)                   \
5138
0
  ((element_type *)((array_ptr)->m_p))[index]
5139
#endif
5140
5141
static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray,
5142
0
                                             mz_uint32 element_size) {
5143
0
  memset(pArray, 0, sizeof(mz_zip_array));
5144
0
  pArray->m_element_size = element_size;
5145
0
}
5146
5147
static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip,
5148
0
                                              mz_zip_array *pArray) {
5149
0
  pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
5150
0
  memset(pArray, 0, sizeof(mz_zip_array));
5151
0
}
5152
5153
static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip,
5154
                                            mz_zip_array *pArray,
5155
                                            size_t min_new_capacity,
5156
0
                                            mz_uint growing) {
5157
0
  void *pNew_p;
5158
0
  size_t new_capacity = min_new_capacity;
5159
0
  MZ_ASSERT(pArray->m_element_size);
5160
0
  if (pArray->m_capacity >= min_new_capacity)
5161
0
    return MZ_TRUE;
5162
0
  if (growing) {
5163
0
    new_capacity = MZ_MAX(1, pArray->m_capacity);
5164
0
    while (new_capacity < min_new_capacity)
5165
0
      new_capacity *= 2;
5166
0
  }
5167
0
  if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p,
5168
0
                                         pArray->m_element_size, new_capacity)))
5169
0
    return MZ_FALSE;
5170
0
  pArray->m_p = pNew_p;
5171
0
  pArray->m_capacity = new_capacity;
5172
0
  return MZ_TRUE;
5173
0
}
5174
5175
static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip,
5176
                                                   mz_zip_array *pArray,
5177
                                                   size_t new_capacity,
5178
0
                                                   mz_uint growing) {
5179
0
  if (new_capacity > pArray->m_capacity) {
5180
0
    if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
5181
0
      return MZ_FALSE;
5182
0
  }
5183
0
  return MZ_TRUE;
5184
0
}
5185
5186
static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip,
5187
                                                  mz_zip_array *pArray,
5188
                                                  size_t new_size,
5189
0
                                                  mz_uint growing) {
5190
0
  if (new_size > pArray->m_capacity) {
5191
0
    if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
5192
0
      return MZ_FALSE;
5193
0
  }
5194
0
  pArray->m_size = new_size;
5195
0
  return MZ_TRUE;
5196
0
}
5197
5198
static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip,
5199
                                                       mz_zip_array *pArray,
5200
0
                                                       size_t n) {
5201
0
  return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
5202
0
}
5203
5204
static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip,
5205
                                                     mz_zip_array *pArray,
5206
                                                     const void *pElements,
5207
0
                                                     size_t n) {
5208
0
  size_t orig_size = pArray->m_size;
5209
0
  if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
5210
0
    return MZ_FALSE;
5211
0
  if (n > 0)
5212
0
    memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size,
5213
0
           pElements, n * pArray->m_element_size);
5214
0
  return MZ_TRUE;
5215
0
}
5216
5217
#ifndef MINIZ_NO_TIME
5218
0
static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date) {
5219
0
  struct tm tm;
5220
0
  memset(&tm, 0, sizeof(tm));
5221
0
  tm.tm_isdst = -1;
5222
0
  tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
5223
0
  tm.tm_mon = ((dos_date >> 5) & 15) - 1;
5224
0
  tm.tm_mday = dos_date & 31;
5225
0
  tm.tm_hour = (dos_time >> 11) & 31;
5226
0
  tm.tm_min = (dos_time >> 5) & 63;
5227
0
  tm.tm_sec = (dos_time << 1) & 62;
5228
0
  return mktime(&tm);
5229
0
}
5230
5231
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5232
static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time,
5233
0
                                      mz_uint16 *pDOS_date) {
5234
#ifdef _MSC_VER
5235
  struct tm tm_struct;
5236
  struct tm *tm = &tm_struct;
5237
  errno_t err = localtime_s(tm, &time);
5238
  if (err) {
5239
    *pDOS_date = 0;
5240
    *pDOS_time = 0;
5241
    return;
5242
  }
5243
#else
5244
0
  struct tm *tm = localtime(&time);
5245
0
#endif /* #ifdef _MSC_VER */
5246
5247
0
  *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) +
5248
0
                           ((tm->tm_sec) >> 1));
5249
0
  *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) +
5250
0
                           ((tm->tm_mon + 1) << 5) + tm->tm_mday);
5251
0
}
5252
#endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
5253
5254
#ifndef MINIZ_NO_STDIO
5255
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5256
static mz_bool mz_zip_get_file_modified_time(const char *pFilename,
5257
0
                                             MZ_TIME_T *pTime) {
5258
0
  struct MZ_FILE_STAT_STRUCT file_stat;
5259
5260
  /* On Linux with x86 glibc, this call will fail on large files (I think >=
5261
   * 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
5262
0
  if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
5263
0
    return MZ_FALSE;
5264
5265
0
  *pTime = file_stat.st_mtime;
5266
5267
0
  return MZ_TRUE;
5268
0
}
5269
#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
5270
5271
static mz_bool mz_zip_set_file_times(const char *pFilename,
5272
                                     MZ_TIME_T access_time,
5273
0
                                     MZ_TIME_T modified_time) {
5274
0
  struct utimbuf t;
5275
5276
0
  memset(&t, 0, sizeof(t));
5277
0
  t.actime = access_time;
5278
0
  t.modtime = modified_time;
5279
5280
0
  return !utime(pFilename, &t);
5281
0
}
5282
#endif /* #ifndef MINIZ_NO_STDIO */
5283
#endif /* #ifndef MINIZ_NO_TIME */
5284
5285
static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip,
5286
0
                                               mz_zip_error err_num) {
5287
0
  if (pZip)
5288
0
    pZip->m_last_error = err_num;
5289
0
  return MZ_FALSE;
5290
0
}
5291
5292
static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip,
5293
0
                                           mz_uint flags) {
5294
0
  (void)flags;
5295
0
  if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5296
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5297
5298
0
  if (!pZip->m_pAlloc)
5299
0
    pZip->m_pAlloc = miniz_def_alloc_func;
5300
0
  if (!pZip->m_pFree)
5301
0
    pZip->m_pFree = miniz_def_free_func;
5302
0
  if (!pZip->m_pRealloc)
5303
0
    pZip->m_pRealloc = miniz_def_realloc_func;
5304
5305
0
  pZip->m_archive_size = 0;
5306
0
  pZip->m_central_directory_file_ofs = 0;
5307
0
  pZip->m_total_files = 0;
5308
0
  pZip->m_last_error = MZ_ZIP_NO_ERROR;
5309
5310
0
  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
5311
0
                   pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5312
0
    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5313
5314
0
  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5315
0
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
5316
0
                                sizeof(mz_uint8));
5317
0
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
5318
0
                                sizeof(mz_uint32));
5319
0
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
5320
0
                                sizeof(mz_uint32));
5321
0
  pZip->m_pState->m_init_flags = flags;
5322
0
  pZip->m_pState->m_zip64 = MZ_FALSE;
5323
0
  pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;
5324
5325
0
  pZip->m_zip_mode = MZ_ZIP_MODE_READING;
5326
5327
0
  return MZ_TRUE;
5328
0
}
5329
5330
static MZ_FORCEINLINE mz_bool
5331
mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array,
5332
                            const mz_zip_array *pCentral_dir_offsets,
5333
0
                            mz_uint l_index, mz_uint r_index) {
5334
0
  const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
5335
0
                     pCentral_dir_array, mz_uint8,
5336
0
                     MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
5337
0
                                          l_index)),
5338
0
                 *pE;
5339
0
  const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(
5340
0
      pCentral_dir_array, mz_uint8,
5341
0
      MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
5342
0
  mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS),
5343
0
          r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5344
0
  mz_uint8 l = 0, r = 0;
5345
0
  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5346
0
  pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
5347
0
  pE = pL + MZ_MIN(l_len, r_len);
5348
0
  while (pL < pE) {
5349
0
    if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
5350
0
      break;
5351
0
    pL++;
5352
0
    pR++;
5353
0
  }
5354
0
  return (pL == pE) ? (l_len < r_len) : (l < r);
5355
0
}
5356
5357
#define MZ_SWAP_UINT32(a, b)                                                   \
5358
0
  do {                                                                         \
5359
0
    mz_uint32 t = a;                                                           \
5360
0
    a = b;                                                                     \
5361
0
    b = t;                                                                     \
5362
0
  }                                                                            \
5363
0
  MZ_MACRO_END
5364
5365
/* Heap sort of lowercased filenames, used to help accelerate plain central
5366
 * directory searches by mz_zip_reader_locate_file(). (Could also use qsort(),
5367
 * but it could allocate memory.) */
5368
static void
5369
0
mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) {
5370
0
  mz_zip_internal_state *pState = pZip->m_pState;
5371
0
  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
5372
0
  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
5373
0
  mz_uint32 *pIndices;
5374
0
  mz_uint32 start, end;
5375
0
  const mz_uint32 size = pZip->m_total_files;
5376
5377
0
  if (size <= 1U)
5378
0
    return;
5379
5380
0
  pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets,
5381
0
                                   mz_uint32, 0);
5382
5383
0
  start = (size - 2U) >> 1U;
5384
0
  for (;;) {
5385
0
    mz_uint64 child, root = start;
5386
0
    for (;;) {
5387
0
      if ((child = (root << 1U) + 1U) >= size)
5388
0
        break;
5389
0
      child += (((child + 1U) < size) &&
5390
0
                (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
5391
0
                                             pIndices[child],
5392
0
                                             pIndices[child + 1U])));
5393
0
      if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
5394
0
                                       pIndices[root], pIndices[child]))
5395
0
        break;
5396
0
      MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
5397
0
      root = child;
5398
0
    }
5399
0
    if (!start)
5400
0
      break;
5401
0
    start--;
5402
0
  }
5403
5404
0
  end = size - 1;
5405
0
  while (end > 0) {
5406
0
    mz_uint64 child, root = 0;
5407
0
    MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
5408
0
    for (;;) {
5409
0
      if ((child = (root << 1U) + 1U) >= end)
5410
0
        break;
5411
0
      child +=
5412
0
          (((child + 1U) < end) &&
5413
0
           mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
5414
0
                                       pIndices[child], pIndices[child + 1U]));
5415
0
      if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets,
5416
0
                                       pIndices[root], pIndices[child]))
5417
0
        break;
5418
0
      MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
5419
0
      root = child;
5420
0
    }
5421
0
    end--;
5422
0
  }
5423
0
}
5424
5425
static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip,
5426
                                               mz_uint32 record_sig,
5427
                                               mz_uint32 record_size,
5428
0
                                               mz_int64 *pOfs) {
5429
0
  mz_int64 cur_file_ofs;
5430
0
  mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
5431
0
  mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
5432
5433
  /* Basic sanity checks - reject files which are too small */
5434
0
  if (pZip->m_archive_size < record_size)
5435
0
    return MZ_FALSE;
5436
5437
  /* Find the record by scanning the file from the end towards the beginning. */
5438
0
  cur_file_ofs =
5439
0
      MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
5440
0
  for (;;) {
5441
0
    int i,
5442
0
        n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
5443
5444
0
    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
5445
0
      return MZ_FALSE;
5446
5447
0
    for (i = n - 4; i >= 0; --i) {
5448
0
      mz_uint s = MZ_READ_LE32(pBuf + i);
5449
0
      if (s == record_sig) {
5450
0
        if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
5451
0
          break;
5452
0
      }
5453
0
    }
5454
5455
0
    if (i >= 0) {
5456
0
      cur_file_ofs += i;
5457
0
      break;
5458
0
    }
5459
5460
    /* Give up if we've searched the entire file, or we've gone back "too far"
5461
     * (~64kb) */
5462
0
    if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >=
5463
0
                            (MZ_UINT16_MAX + record_size)))
5464
0
      return MZ_FALSE;
5465
5466
0
    cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
5467
0
  }
5468
5469
0
  *pOfs = cur_file_ofs;
5470
0
  return MZ_TRUE;
5471
0
}
5472
5473
static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip,
5474
0
                                              mz_uint flags) {
5475
0
  mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0,
5476
0
          cdir_disk_index = 0;
5477
0
  mz_uint64 cdir_ofs = 0;
5478
0
  mz_int64 cur_file_ofs = 0;
5479
0
  const mz_uint8 *p;
5480
5481
0
  mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
5482
0
  mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
5483
0
  mz_bool sort_central_dir =
5484
0
      ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
5485
0
  mz_uint32 zip64_end_of_central_dir_locator_u32
5486
0
      [(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) /
5487
0
       sizeof(mz_uint32)];
5488
0
  mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
5489
5490
0
  mz_uint32 zip64_end_of_central_dir_header_u32
5491
0
      [(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
5492
0
       sizeof(mz_uint32)];
5493
0
  mz_uint8 *pZip64_end_of_central_dir =
5494
0
      (mz_uint8 *)zip64_end_of_central_dir_header_u32;
5495
5496
0
  mz_uint64 zip64_end_of_central_dir_ofs = 0;
5497
5498
  /* Basic sanity checks - reject files which are too small, and check the first
5499
   * 4 bytes of the file to make sure a local header is there. */
5500
0
  if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
5501
0
    return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
5502
5503
0
  if (!mz_zip_reader_locate_header_sig(
5504
0
          pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG,
5505
0
          MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
5506
0
    return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
5507
5508
  /* Read and verify the end of central directory record. */
5509
0
  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
5510
0
                    MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) !=
5511
0
      MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
5512
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5513
5514
0
  if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) !=
5515
0
      MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
5516
0
    return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
5517
5518
0
  if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE +
5519
0
                       MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)) {
5520
0
    if (pZip->m_pRead(pZip->m_pIO_opaque,
5521
0
                      cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE,
5522
0
                      pZip64_locator,
5523
0
                      MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) ==
5524
0
        MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) {
5525
0
      if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) ==
5526
0
          MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG) {
5527
0
        zip64_end_of_central_dir_ofs = MZ_READ_LE64(
5528
0
            pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
5529
0
        if (zip64_end_of_central_dir_ofs >
5530
0
            (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
5531
0
          return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
5532
5533
0
        if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs,
5534
0
                          pZip64_end_of_central_dir,
5535
0
                          MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) ==
5536
0
            MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) {
5537
0
          if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) ==
5538
0
              MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG) {
5539
0
            pZip->m_pState->m_zip64 = MZ_TRUE;
5540
0
          }
5541
0
        }
5542
0
      }
5543
0
    }
5544
0
  }
5545
5546
0
  pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
5547
0
  cdir_entries_on_this_disk =
5548
0
      MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
5549
0
  num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
5550
0
  cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
5551
0
  cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
5552
0
  cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
5553
5554
0
  if (pZip->m_pState->m_zip64) {
5555
0
    mz_uint32 zip64_total_num_of_disks =
5556
0
        MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
5557
0
    mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(
5558
0
        pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
5559
0
    mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(
5560
0
        pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
5561
0
    mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(
5562
0
        pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
5563
0
    mz_uint64 zip64_size_of_central_directory =
5564
0
        MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
5565
5566
0
    if (zip64_size_of_end_of_central_dir_record <
5567
0
        (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
5568
0
      return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5569
5570
0
    if (zip64_total_num_of_disks != 1U)
5571
0
      return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
5572
5573
    /* Check for miniz's practical limits */
5574
0
    if (zip64_cdir_total_entries > MZ_UINT32_MAX)
5575
0
      return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5576
5577
0
    pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
5578
5579
0
    if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
5580
0
      return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5581
5582
0
    cdir_entries_on_this_disk =
5583
0
        (mz_uint32)zip64_cdir_total_entries_on_this_disk;
5584
5585
    /* Check for miniz's current practical limits (sorry, this should be enough
5586
     * for millions of files) */
5587
0
    if (zip64_size_of_central_directory > MZ_UINT32_MAX)
5588
0
      return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
5589
5590
0
    cdir_size = (mz_uint32)zip64_size_of_central_directory;
5591
5592
0
    num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir +
5593
0
                                 MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
5594
5595
0
    cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir +
5596
0
                                   MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
5597
5598
0
    cdir_ofs =
5599
0
        MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
5600
0
  }
5601
5602
0
  if (pZip->m_total_files != cdir_entries_on_this_disk)
5603
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
5604
5605
0
  if (((num_this_disk | cdir_disk_index) != 0) &&
5606
0
      ((num_this_disk != 1) || (cdir_disk_index != 1)))
5607
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
5608
5609
0
  if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
5610
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5611
5612
0
  if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
5613
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5614
5615
0
  pZip->m_central_directory_file_ofs = cdir_ofs;
5616
5617
0
  if (pZip->m_total_files) {
5618
0
    mz_uint i, n;
5619
    /* Read the entire central directory into a heap block, and allocate another
5620
     * heap block to hold the unsorted central dir file record offsets, and
5621
     * possibly another to hold the sorted indices. */
5622
0
    if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size,
5623
0
                              MZ_FALSE)) ||
5624
0
        (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets,
5625
0
                              pZip->m_total_files, MZ_FALSE)))
5626
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5627
5628
0
    if (sort_central_dir) {
5629
0
      if (!mz_zip_array_resize(pZip,
5630
0
                               &pZip->m_pState->m_sorted_central_dir_offsets,
5631
0
                               pZip->m_total_files, MZ_FALSE))
5632
0
        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5633
0
    }
5634
5635
0
    if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs,
5636
0
                      pZip->m_pState->m_central_dir.m_p,
5637
0
                      cdir_size) != cdir_size)
5638
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5639
5640
    /* Now create an index into the central directory file records, do some
5641
     * basic sanity checking on each record */
5642
0
    p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
5643
0
    for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) {
5644
0
      mz_uint total_header_size, disk_index, bit_flags, filename_size,
5645
0
          ext_data_size;
5646
0
      mz_uint64 comp_size, decomp_size, local_header_ofs;
5647
5648
0
      if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) ||
5649
0
          (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
5650
0
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5651
5652
0
      MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
5653
0
                           i) =
5654
0
          (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
5655
5656
0
      if (sort_central_dir)
5657
0
        MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets,
5658
0
                             mz_uint32, i) = i;
5659
5660
0
      comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
5661
0
      decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
5662
0
      local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
5663
0
      filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
5664
0
      ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
5665
5666
0
      if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
5667
0
          (ext_data_size) &&
5668
0
          (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) ==
5669
0
           MZ_UINT32_MAX)) {
5670
        /* Attempt to find zip64 extended information field in the entry's extra
5671
         * data */
5672
0
        mz_uint32 extra_size_remaining = ext_data_size;
5673
5674
0
        if (extra_size_remaining) {
5675
0
          const mz_uint8 *pExtra_data;
5676
0
          void *buf = NULL;
5677
5678
0
          if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size >
5679
0
              n) {
5680
0
            buf = MZ_MALLOC(ext_data_size);
5681
0
            if (buf == NULL)
5682
0
              return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5683
5684
0
            if (pZip->m_pRead(pZip->m_pIO_opaque,
5685
0
                              cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5686
0
                                  filename_size,
5687
0
                              buf, ext_data_size) != ext_data_size) {
5688
0
              MZ_FREE(buf);
5689
0
              return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5690
0
            }
5691
5692
0
            pExtra_data = (mz_uint8 *)buf;
5693
0
          } else {
5694
0
            pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
5695
0
          }
5696
5697
0
          do {
5698
0
            mz_uint32 field_id;
5699
0
            mz_uint32 field_data_size;
5700
5701
0
            if (extra_size_remaining < (sizeof(mz_uint16) * 2)) {
5702
0
              MZ_FREE(buf);
5703
0
              return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5704
0
            }
5705
5706
0
            field_id = MZ_READ_LE16(pExtra_data);
5707
0
            field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
5708
5709
0
            if ((field_data_size + sizeof(mz_uint16) * 2) >
5710
0
                extra_size_remaining) {
5711
0
              MZ_FREE(buf);
5712
0
              return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5713
0
            }
5714
5715
0
            if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) {
5716
              /* Ok, the archive didn't have any zip64 headers but it uses a
5717
               * zip64 extended information field so mark it as zip64 anyway
5718
               * (this can occur with infozip's zip util when it reads
5719
               * compresses files from stdin). */
5720
0
              pZip->m_pState->m_zip64 = MZ_TRUE;
5721
0
              pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
5722
0
              break;
5723
0
            }
5724
5725
0
            pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
5726
0
            extra_size_remaining =
5727
0
                extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
5728
0
          } while (extra_size_remaining);
5729
5730
0
          MZ_FREE(buf);
5731
0
        }
5732
0
      }
5733
5734
      /* I've seen archives that aren't marked as zip64 that uses zip64 ext
5735
       * data, argh */
5736
0
      if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX)) {
5737
0
        if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) &&
5738
0
             (decomp_size != comp_size)) ||
5739
0
            (decomp_size && !comp_size))
5740
0
          return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5741
0
      }
5742
5743
0
      disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
5744
0
      if ((disk_index == MZ_UINT16_MAX) ||
5745
0
          ((disk_index != num_this_disk) && (disk_index != 1)))
5746
0
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
5747
5748
0
      if (comp_size != MZ_UINT32_MAX) {
5749
0
        if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) +
5750
0
             MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
5751
0
          return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5752
0
      }
5753
5754
0
      bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
5755
0
      if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
5756
0
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
5757
5758
0
      if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
5759
0
                               MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
5760
0
                               MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) +
5761
0
                               MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) >
5762
0
          n)
5763
0
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5764
5765
0
      n -= total_header_size;
5766
0
      p += total_header_size;
5767
0
    }
5768
0
  }
5769
5770
0
  if (sort_central_dir)
5771
0
    mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
5772
5773
0
  return MZ_TRUE;
5774
0
}
5775
5776
0
void mz_zip_zero_struct(mz_zip_archive *pZip) {
5777
0
  if (pZip)
5778
0
    MZ_CLEAR_OBJ(*pZip);
5779
0
}
5780
5781
static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip,
5782
0
                                          mz_bool set_last_error) {
5783
0
  mz_bool status = MZ_TRUE;
5784
5785
0
  if (!pZip)
5786
0
    return MZ_FALSE;
5787
5788
0
  if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
5789
0
      (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) {
5790
0
    if (set_last_error)
5791
0
      pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;
5792
5793
0
    return MZ_FALSE;
5794
0
  }
5795
5796
0
  if (pZip->m_pState) {
5797
0
    mz_zip_internal_state *pState = pZip->m_pState;
5798
0
    pZip->m_pState = NULL;
5799
5800
0
    mz_zip_array_clear(pZip, &pState->m_central_dir);
5801
0
    mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5802
0
    mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5803
5804
0
#ifndef MINIZ_NO_STDIO
5805
0
    if (pState->m_pFile) {
5806
0
      if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) {
5807
0
        if (MZ_FCLOSE(pState->m_pFile) == EOF) {
5808
0
          if (set_last_error)
5809
0
            pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED;
5810
0
          status = MZ_FALSE;
5811
0
        }
5812
0
      }
5813
0
      pState->m_pFile = NULL;
5814
0
    }
5815
0
#endif /* #ifndef MINIZ_NO_STDIO */
5816
5817
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5818
0
  }
5819
0
  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5820
5821
0
  return status;
5822
0
}
5823
5824
0
mz_bool mz_zip_reader_end(mz_zip_archive *pZip) {
5825
0
  return mz_zip_reader_end_internal(pZip, MZ_TRUE);
5826
0
}
5827
mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size,
5828
0
                           mz_uint flags) {
5829
0
  if ((!pZip) || (!pZip->m_pRead))
5830
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5831
5832
0
  if (!mz_zip_reader_init_internal(pZip, flags))
5833
0
    return MZ_FALSE;
5834
5835
0
  pZip->m_zip_type = MZ_ZIP_TYPE_USER;
5836
0
  pZip->m_archive_size = size;
5837
5838
0
  if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5839
0
    mz_zip_reader_end_internal(pZip, MZ_FALSE);
5840
0
    return MZ_FALSE;
5841
0
  }
5842
5843
0
  return MZ_TRUE;
5844
0
}
5845
5846
static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs,
5847
0
                                   void *pBuf, size_t n) {
5848
0
  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5849
0
  size_t s = (file_ofs >= pZip->m_archive_size)
5850
0
                 ? 0
5851
0
                 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
5852
0
  memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
5853
0
  return s;
5854
0
}
5855
5856
mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem,
5857
0
                               size_t size, mz_uint flags) {
5858
0
  if (!pMem)
5859
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5860
5861
0
  if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
5862
0
    return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
5863
5864
0
  if (!mz_zip_reader_init_internal(pZip, flags))
5865
0
    return MZ_FALSE;
5866
5867
0
  pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY;
5868
0
  pZip->m_archive_size = size;
5869
0
  pZip->m_pRead = mz_zip_mem_read_func;
5870
0
  pZip->m_pIO_opaque = pZip;
5871
0
  pZip->m_pNeeds_keepalive = NULL;
5872
5873
#ifdef __cplusplus
5874
  pZip->m_pState->m_pMem = const_cast<void *>(pMem);
5875
#else
5876
0
  pZip->m_pState->m_pMem = (void *)pMem;
5877
0
#endif
5878
5879
0
  pZip->m_pState->m_mem_size = size;
5880
5881
0
  if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5882
0
    mz_zip_reader_end_internal(pZip, MZ_FALSE);
5883
0
    return MZ_FALSE;
5884
0
  }
5885
5886
0
  return MZ_TRUE;
5887
0
}
5888
5889
#ifndef MINIZ_NO_STDIO
5890
static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs,
5891
0
                                    void *pBuf, size_t n) {
5892
0
  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5893
0
  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5894
5895
0
  file_ofs += pZip->m_pState->m_file_archive_start_ofs;
5896
5897
0
  if (((mz_int64)file_ofs < 0) ||
5898
0
      (((cur_ofs != (mz_int64)file_ofs)) &&
5899
0
       (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5900
0
    return 0;
5901
5902
0
  return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
5903
0
}
5904
5905
mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename,
5906
0
                                mz_uint32 flags) {
5907
0
  return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);
5908
0
}
5909
5910
mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename,
5911
                                   mz_uint flags, mz_uint64 file_start_ofs,
5912
0
                                   mz_uint64 archive_size) {
5913
0
  mz_uint64 file_size;
5914
0
  MZ_FILE *pFile;
5915
5916
0
  if ((!pZip) || (!pFilename) ||
5917
0
      ((archive_size) &&
5918
0
       (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
5919
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5920
5921
0
  pFile = MZ_FOPEN(pFilename, "rb");
5922
0
  if (!pFile)
5923
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5924
5925
0
  file_size = archive_size;
5926
0
  if (!file_size) {
5927
0
    if (MZ_FSEEK64(pFile, 0, SEEK_END)) {
5928
0
      MZ_FCLOSE(pFile);
5929
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
5930
0
    }
5931
5932
0
    file_size = MZ_FTELL64(pFile);
5933
0
  }
5934
5935
  /* TODO: Better sanity check archive_size and the # of actual remaining bytes
5936
   */
5937
5938
0
  if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) {
5939
0
    MZ_FCLOSE(pFile);
5940
0
    return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
5941
0
  }
5942
5943
0
  if (!mz_zip_reader_init_internal(pZip, flags)) {
5944
0
    MZ_FCLOSE(pFile);
5945
0
    return MZ_FALSE;
5946
0
  }
5947
5948
0
  pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
5949
0
  pZip->m_pRead = mz_zip_file_read_func;
5950
0
  pZip->m_pIO_opaque = pZip;
5951
0
  pZip->m_pState->m_pFile = pFile;
5952
0
  pZip->m_archive_size = file_size;
5953
0
  pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;
5954
5955
0
  if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5956
0
    mz_zip_reader_end_internal(pZip, MZ_FALSE);
5957
0
    return MZ_FALSE;
5958
0
  }
5959
5960
0
  return MZ_TRUE;
5961
0
}
5962
5963
mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile,
5964
0
                                 mz_uint64 archive_size, mz_uint flags) {
5965
0
  mz_uint64 cur_file_ofs;
5966
5967
0
  if ((!pZip) || (!pFile))
5968
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5969
5970
0
  cur_file_ofs = MZ_FTELL64(pFile);
5971
5972
0
  if (!archive_size) {
5973
0
    if (MZ_FSEEK64(pFile, 0, SEEK_END))
5974
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
5975
5976
0
    archive_size = MZ_FTELL64(pFile) - cur_file_ofs;
5977
5978
0
    if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
5979
0
      return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
5980
0
  }
5981
5982
0
  if (!mz_zip_reader_init_internal(pZip, flags))
5983
0
    return MZ_FALSE;
5984
5985
0
  pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
5986
0
  pZip->m_pRead = mz_zip_file_read_func;
5987
5988
0
  pZip->m_pIO_opaque = pZip;
5989
0
  pZip->m_pState->m_pFile = pFile;
5990
0
  pZip->m_archive_size = archive_size;
5991
0
  pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;
5992
5993
0
  if (!mz_zip_reader_read_central_dir(pZip, flags)) {
5994
0
    mz_zip_reader_end_internal(pZip, MZ_FALSE);
5995
0
    return MZ_FALSE;
5996
0
  }
5997
5998
0
  return MZ_TRUE;
5999
0
}
6000
6001
#endif /* #ifndef MINIZ_NO_STDIO */
6002
6003
static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip,
6004
0
                                                     mz_uint file_index) {
6005
0
  if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
6006
0
    return NULL;
6007
0
  return &MZ_ZIP_ARRAY_ELEMENT(
6008
0
      &pZip->m_pState->m_central_dir, mz_uint8,
6009
0
      MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
6010
0
                           file_index));
6011
0
}
6012
6013
mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip,
6014
0
                                        mz_uint file_index) {
6015
0
  mz_uint m_bit_flag;
6016
0
  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
6017
0
  if (!p) {
6018
0
    mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6019
0
    return MZ_FALSE;
6020
0
  }
6021
6022
0
  m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
6023
0
  return (m_bit_flag &
6024
0
          (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED |
6025
0
           MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;
6026
0
}
6027
6028
mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip,
6029
0
                                        mz_uint file_index) {
6030
0
  mz_uint bit_flag;
6031
0
  mz_uint method;
6032
6033
0
  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
6034
0
  if (!p) {
6035
0
    mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6036
0
    return MZ_FALSE;
6037
0
  }
6038
6039
0
  method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
6040
0
  bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
6041
6042
0
  if ((method != 0) && (method != MZ_DEFLATED)) {
6043
0
    mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
6044
0
    return MZ_FALSE;
6045
0
  }
6046
6047
0
  if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED |
6048
0
                  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) {
6049
0
    mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
6050
0
    return MZ_FALSE;
6051
0
  }
6052
6053
0
  if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG) {
6054
0
    mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
6055
0
    return MZ_FALSE;
6056
0
  }
6057
6058
0
  return MZ_TRUE;
6059
0
}
6060
6061
mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip,
6062
0
                                          mz_uint file_index) {
6063
0
  mz_uint filename_len, attribute_mapping_id, external_attr;
6064
0
  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
6065
0
  if (!p) {
6066
0
    mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6067
0
    return MZ_FALSE;
6068
0
  }
6069
6070
0
  filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
6071
0
  if (filename_len) {
6072
0
    if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
6073
0
      return MZ_TRUE;
6074
0
  }
6075
6076
  /* Bugfix: This code was also checking if the internal attribute was non-zero,
6077
   * which wasn't correct. */
6078
  /* Most/all zip writers (hopefully) set DOS file/directory attributes in the
6079
   * low 16-bits, so check for the DOS directory flag and ignore the source OS
6080
   * ID in the created by field. */
6081
  /* FIXME: Remove this check? Is it necessary - we already check the filename.
6082
   */
6083
0
  attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
6084
0
  (void)attribute_mapping_id;
6085
6086
0
  external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
6087
0
  if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0) {
6088
0
    return MZ_TRUE;
6089
0
  }
6090
6091
0
  return MZ_FALSE;
6092
0
}
6093
6094
static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip,
6095
                                         mz_uint file_index,
6096
                                         const mz_uint8 *pCentral_dir_header,
6097
                                         mz_zip_archive_file_stat *pStat,
6098
0
                                         mz_bool *pFound_zip64_extra_data) {
6099
0
  mz_uint n;
6100
0
  const mz_uint8 *p = pCentral_dir_header;
6101
6102
0
  if (pFound_zip64_extra_data)
6103
0
    *pFound_zip64_extra_data = MZ_FALSE;
6104
6105
0
  if ((!p) || (!pStat))
6106
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6107
6108
  /* Extract fields from the central directory record. */
6109
0
  pStat->m_file_index = file_index;
6110
0
  pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(
6111
0
      &pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
6112
0
  pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
6113
0
  pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
6114
0
  pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
6115
0
  pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
6116
0
#ifndef MINIZ_NO_TIME
6117
0
  pStat->m_time =
6118
0
      mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS),
6119
0
                           MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
6120
0
#endif
6121
0
  pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
6122
0
  pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
6123
0
  pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
6124
0
  pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
6125
0
  pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
6126
0
  pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
6127
6128
  /* Copy as much of the filename and comment as possible. */
6129
0
  n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
6130
0
  n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
6131
0
  memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
6132
0
  pStat->m_filename[n] = '\0';
6133
6134
0
  n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6135
0
  n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
6136
0
  pStat->m_comment_size = n;
6137
0
  memcpy(pStat->m_comment,
6138
0
         p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6139
0
             MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
6140
0
             MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
6141
0
         n);
6142
0
  pStat->m_comment[n] = '\0';
6143
6144
  /* Set some flags for convienance */
6145
0
  pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
6146
0
  pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
6147
0
  pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
6148
6149
  /* See if we need to read any zip64 extended information fields. */
6150
  /* Confusingly, these zip64 fields can be present even on non-zip64 archives
6151
   * (Debian zip on a huge files from stdin piped to stdout creates them). */
6152
0
  if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size),
6153
0
             pStat->m_local_header_ofs) == MZ_UINT32_MAX) {
6154
    /* Attempt to find zip64 extended information field in the entry's extra
6155
     * data */
6156
0
    mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
6157
6158
0
    if (extra_size_remaining) {
6159
0
      const mz_uint8 *pExtra_data =
6160
0
          p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
6161
0
          MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
6162
6163
0
      do {
6164
0
        mz_uint32 field_id;
6165
0
        mz_uint32 field_data_size;
6166
6167
0
        if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6168
0
          return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6169
6170
0
        field_id = MZ_READ_LE16(pExtra_data);
6171
0
        field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6172
6173
0
        if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
6174
0
          return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6175
6176
0
        if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) {
6177
0
          const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
6178
0
          mz_uint32 field_data_remaining = field_data_size;
6179
6180
0
          if (pFound_zip64_extra_data)
6181
0
            *pFound_zip64_extra_data = MZ_TRUE;
6182
6183
0
          if (pStat->m_uncomp_size == MZ_UINT32_MAX) {
6184
0
            if (field_data_remaining < sizeof(mz_uint64))
6185
0
              return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6186
6187
0
            pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
6188
0
            pField_data += sizeof(mz_uint64);
6189
0
            field_data_remaining -= sizeof(mz_uint64);
6190
0
          }
6191
6192
0
          if (pStat->m_comp_size == MZ_UINT32_MAX) {
6193
0
            if (field_data_remaining < sizeof(mz_uint64))
6194
0
              return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6195
6196
0
            pStat->m_comp_size = MZ_READ_LE64(pField_data);
6197
0
            pField_data += sizeof(mz_uint64);
6198
0
            field_data_remaining -= sizeof(mz_uint64);
6199
0
          }
6200
6201
0
          if (pStat->m_local_header_ofs == MZ_UINT32_MAX) {
6202
0
            if (field_data_remaining < sizeof(mz_uint64))
6203
0
              return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6204
6205
0
            pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
6206
0
            pField_data += sizeof(mz_uint64);
6207
0
            (void)pField_data; // unused
6208
6209
0
            field_data_remaining -= sizeof(mz_uint64);
6210
0
            (void)field_data_remaining; // unused
6211
0
          }
6212
6213
0
          break;
6214
0
        }
6215
6216
0
        pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
6217
0
        extra_size_remaining =
6218
0
            extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
6219
0
      } while (extra_size_remaining);
6220
0
    }
6221
0
  }
6222
6223
0
  return MZ_TRUE;
6224
0
}
6225
6226
static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA,
6227
                                                  const char *pB, mz_uint len,
6228
0
                                                  mz_uint flags) {
6229
0
  mz_uint i;
6230
0
  if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
6231
0
    return 0 == memcmp(pA, pB, len);
6232
0
  for (i = 0; i < len; ++i)
6233
0
    if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
6234
0
      return MZ_FALSE;
6235
0
  return MZ_TRUE;
6236
0
}
6237
6238
static MZ_FORCEINLINE int
6239
mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array,
6240
                        const mz_zip_array *pCentral_dir_offsets,
6241
0
                        mz_uint l_index, const char *pR, mz_uint r_len) {
6242
0
  const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(
6243
0
                     pCentral_dir_array, mz_uint8,
6244
0
                     MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32,
6245
0
                                          l_index)),
6246
0
                 *pE;
6247
0
  mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
6248
0
  mz_uint8 l = 0, r = 0;
6249
0
  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
6250
0
  pE = pL + MZ_MIN(l_len, r_len);
6251
0
  while (pL < pE) {
6252
0
    if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
6253
0
      break;
6254
0
    pL++;
6255
0
    pR++;
6256
0
  }
6257
0
  return (pL == pE) ? (int)(l_len - r_len) : (l - r);
6258
0
}
6259
6260
static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip,
6261
                                                const char *pFilename,
6262
0
                                                mz_uint32 *pIndex) {
6263
0
  mz_zip_internal_state *pState = pZip->m_pState;
6264
0
  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
6265
0
  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
6266
0
  mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(
6267
0
      &pState->m_sorted_central_dir_offsets, mz_uint32, 0);
6268
0
  const uint32_t size = pZip->m_total_files;
6269
0
  const mz_uint filename_len = (mz_uint)strlen(pFilename);
6270
6271
0
  if (pIndex)
6272
0
    *pIndex = 0;
6273
6274
0
  if (size) {
6275
    /* yes I could use uint32_t's, but then we would have to add some special
6276
     * case checks in the loop, argh, and */
6277
    /* honestly the major expense here on 32-bit CPU's will still be the
6278
     * filename compare */
6279
0
    mz_int64 l = 0, h = (mz_int64)size - 1;
6280
6281
0
    while (l <= h) {
6282
0
      mz_int64 m = l + ((h - l) >> 1);
6283
0
      uint32_t file_index = pIndices[(uint32_t)m];
6284
6285
0
      int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets,
6286
0
                                         file_index, pFilename, filename_len);
6287
0
      if (!comp) {
6288
0
        if (pIndex)
6289
0
          *pIndex = file_index;
6290
0
        return MZ_TRUE;
6291
0
      } else if (comp < 0)
6292
0
        l = m + 1;
6293
0
      else
6294
0
        h = m - 1;
6295
0
    }
6296
0
  }
6297
6298
0
  return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
6299
0
}
6300
6301
int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName,
6302
0
                              const char *pComment, mz_uint flags) {
6303
0
  mz_uint32 index;
6304
0
  if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
6305
0
    return -1;
6306
0
  else
6307
0
    return (int)index;
6308
0
}
6309
6310
mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName,
6311
                                     const char *pComment, mz_uint flags,
6312
0
                                     mz_uint32 *pIndex) {
6313
0
  mz_uint file_index;
6314
0
  size_t name_len, comment_len;
6315
6316
0
  if (pIndex)
6317
0
    *pIndex = 0;
6318
6319
0
  if ((!pZip) || (!pZip->m_pState) || (!pName))
6320
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6321
6322
  /* See if we can use a binary search */
6323
0
  if (((pZip->m_pState->m_init_flags &
6324
0
        MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&
6325
0
      (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
6326
0
      ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) &&
6327
0
      (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size)) {
6328
0
    return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
6329
0
  }
6330
6331
  /* Locate the entry by scanning the entire central directory */
6332
0
  name_len = strlen(pName);
6333
0
  if (name_len > MZ_UINT16_MAX)
6334
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6335
6336
0
  comment_len = pComment ? strlen(pComment) : 0;
6337
0
  if (comment_len > MZ_UINT16_MAX)
6338
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6339
6340
0
  for (file_index = 0; file_index < pZip->m_total_files; file_index++) {
6341
0
    const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(
6342
0
        &pZip->m_pState->m_central_dir, mz_uint8,
6343
0
        MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32,
6344
0
                             file_index));
6345
0
    mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
6346
0
    const char *pFilename =
6347
0
        (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
6348
0
    if (filename_len < name_len)
6349
0
      continue;
6350
0
    if (comment_len) {
6351
0
      mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS),
6352
0
              file_comment_len =
6353
0
                  MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6354
0
      const char *pFile_comment = pFilename + filename_len + file_extra_len;
6355
0
      if ((file_comment_len != comment_len) ||
6356
0
          (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len,
6357
0
                                flags)))
6358
0
        continue;
6359
0
    }
6360
0
    if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) {
6361
0
      int ofs = filename_len - 1;
6362
0
      do {
6363
0
        if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') ||
6364
0
            (pFilename[ofs] == ':'))
6365
0
          break;
6366
0
      } while (--ofs >= 0);
6367
0
      ofs++;
6368
0
      pFilename += ofs;
6369
0
      filename_len -= ofs;
6370
0
    }
6371
0
    if ((filename_len == name_len) &&
6372
0
        (mz_zip_string_equal(pName, pFilename, filename_len, flags))) {
6373
0
      if (pIndex)
6374
0
        *pIndex = file_index;
6375
0
      return MZ_TRUE;
6376
0
    }
6377
0
  }
6378
6379
0
  return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
6380
0
}
6381
6382
mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip,
6383
                                              mz_uint file_index, void *pBuf,
6384
                                              size_t buf_size, mz_uint flags,
6385
                                              void *pUser_read_buf,
6386
0
                                              size_t user_read_buf_size) {
6387
0
  int status = TINFL_STATUS_DONE;
6388
0
  mz_uint64 needed_size, cur_file_ofs, comp_remaining,
6389
0
      out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
6390
0
  mz_zip_archive_file_stat file_stat;
6391
0
  void *pRead_buf;
6392
0
  mz_uint32
6393
0
      local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
6394
0
                       sizeof(mz_uint32)];
6395
0
  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6396
0
  tinfl_decompressor inflator;
6397
6398
0
  if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) ||
6399
0
      ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
6400
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6401
6402
0
  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
6403
0
    return MZ_FALSE;
6404
6405
  /* A directory or zero length file */
6406
0
  if (file_stat.m_is_directory || (!file_stat.m_comp_size))
6407
0
    return MZ_TRUE;
6408
6409
  /* Encryption and patch files are not supported. */
6410
0
  if (file_stat.m_bit_flag &
6411
0
      (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED |
6412
0
       MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION |
6413
0
       MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
6414
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
6415
6416
  /* This function only supports decompressing stored and deflate. */
6417
0
  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
6418
0
      (file_stat.m_method != MZ_DEFLATED))
6419
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
6420
6421
  /* Ensure supplied output buffer is large enough. */
6422
0
  needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size
6423
0
                                                      : file_stat.m_uncomp_size;
6424
0
  if (buf_size < needed_size)
6425
0
    return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);
6426
6427
  /* Read and parse the local directory entry. */
6428
0
  cur_file_ofs = file_stat.m_local_header_ofs;
6429
0
  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
6430
0
                    MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6431
0
      MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6432
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6433
6434
0
  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6435
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6436
6437
0
  cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
6438
0
                  MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
6439
0
                  MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6440
0
  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
6441
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6442
6443
0
  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
6444
    /* The file is stored or the caller has requested the compressed data. */
6445
0
    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf,
6446
0
                      (size_t)needed_size) != needed_size)
6447
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6448
6449
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
6450
0
    if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0) {
6451
0
      if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
6452
0
                   (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
6453
0
        return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
6454
0
    }
6455
0
#endif
6456
6457
0
    return MZ_TRUE;
6458
0
  }
6459
6460
  /* Decompress the file either directly from memory or from a file input
6461
   * buffer. */
6462
0
  tinfl_init(&inflator);
6463
6464
0
  if (pZip->m_pState->m_pMem) {
6465
    /* Read directly from the archive in memory. */
6466
0
    pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
6467
0
    read_buf_size = read_buf_avail = file_stat.m_comp_size;
6468
0
    comp_remaining = 0;
6469
0
  } else if (pUser_read_buf) {
6470
    /* Use a user provided read buffer. */
6471
0
    if (!user_read_buf_size)
6472
0
      return MZ_FALSE;
6473
0
    pRead_buf = (mz_uint8 *)pUser_read_buf;
6474
0
    read_buf_size = user_read_buf_size;
6475
0
    read_buf_avail = 0;
6476
0
    comp_remaining = file_stat.m_comp_size;
6477
0
  } else {
6478
    /* Temporarily allocate a read buffer. */
6479
0
    read_buf_size =
6480
0
        MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
6481
0
    if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
6482
0
      return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6483
6484
0
    if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
6485
0
                                            (size_t)read_buf_size)))
6486
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6487
6488
0
    read_buf_avail = 0;
6489
0
    comp_remaining = file_stat.m_comp_size;
6490
0
  }
6491
6492
0
  do {
6493
    /* The size_t cast here should be OK because we've verified that the output
6494
     * buffer is >= file_stat.m_uncomp_size above */
6495
0
    size_t in_buf_size,
6496
0
        out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
6497
0
    if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
6498
0
      read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
6499
0
      if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
6500
0
                        (size_t)read_buf_avail) != read_buf_avail) {
6501
0
        status = TINFL_STATUS_FAILED;
6502
0
        mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
6503
0
        break;
6504
0
      }
6505
0
      cur_file_ofs += read_buf_avail;
6506
0
      comp_remaining -= read_buf_avail;
6507
0
      read_buf_ofs = 0;
6508
0
    }
6509
0
    in_buf_size = (size_t)read_buf_avail;
6510
0
    status = tinfl_decompress(
6511
0
        &inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
6512
0
        (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size,
6513
0
        TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF |
6514
0
            (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
6515
0
    read_buf_avail -= in_buf_size;
6516
0
    read_buf_ofs += in_buf_size;
6517
0
    out_buf_ofs += out_buf_size;
6518
0
  } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
6519
6520
0
  if (status == TINFL_STATUS_DONE) {
6521
    /* Make sure the entire file was decompressed, and check its CRC. */
6522
0
    if (out_buf_ofs != file_stat.m_uncomp_size) {
6523
0
      mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
6524
0
      status = TINFL_STATUS_FAILED;
6525
0
    }
6526
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
6527
0
    else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf,
6528
0
                      (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32) {
6529
0
      mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
6530
0
      status = TINFL_STATUS_FAILED;
6531
0
    }
6532
0
#endif
6533
0
  }
6534
6535
0
  if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
6536
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6537
6538
0
  return status == TINFL_STATUS_DONE;
6539
0
}
6540
6541
mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(
6542
    mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size,
6543
0
    mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) {
6544
0
  mz_uint32 file_index;
6545
0
  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
6546
0
    return MZ_FALSE;
6547
0
  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
6548
0
                                               flags, pUser_read_buf,
6549
0
                                               user_read_buf_size);
6550
0
}
6551
6552
mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index,
6553
                                     void *pBuf, size_t buf_size,
6554
0
                                     mz_uint flags) {
6555
0
  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size,
6556
0
                                               flags, NULL, 0);
6557
0
}
6558
6559
mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip,
6560
                                          const char *pFilename, void *pBuf,
6561
0
                                          size_t buf_size, mz_uint flags) {
6562
0
  return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf,
6563
0
                                                    buf_size, flags, NULL, 0);
6564
0
}
6565
6566
void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index,
6567
0
                                    size_t *pSize, mz_uint flags) {
6568
0
  mz_uint64 comp_size, uncomp_size, alloc_size;
6569
0
  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
6570
0
  void *pBuf;
6571
6572
0
  if (pSize)
6573
0
    *pSize = 0;
6574
6575
0
  if (!p) {
6576
0
    mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6577
0
    return NULL;
6578
0
  }
6579
6580
0
  comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
6581
0
  uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
6582
6583
0
  alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
6584
0
  if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) {
6585
0
    mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6586
0
    return NULL;
6587
0
  }
6588
6589
0
  if (NULL ==
6590
0
      (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) {
6591
0
    mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6592
0
    return NULL;
6593
0
  }
6594
6595
0
  if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size,
6596
0
                                    flags)) {
6597
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6598
0
    return NULL;
6599
0
  }
6600
6601
0
  if (pSize)
6602
0
    *pSize = (size_t)alloc_size;
6603
0
  return pBuf;
6604
0
}
6605
6606
void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip,
6607
                                         const char *pFilename, size_t *pSize,
6608
0
                                         mz_uint flags) {
6609
0
  mz_uint32 file_index;
6610
0
  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags,
6611
0
                                    &file_index)) {
6612
0
    if (pSize)
6613
0
      *pSize = 0;
6614
0
    return MZ_FALSE;
6615
0
  }
6616
0
  return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
6617
0
}
6618
6619
mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip,
6620
                                          mz_uint file_index,
6621
                                          mz_file_write_func pCallback,
6622
0
                                          void *pOpaque, mz_uint flags) {
6623
0
  int status = TINFL_STATUS_DONE;
6624
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
6625
0
  mz_uint file_crc32 = MZ_CRC32_INIT;
6626
0
#endif
6627
0
  mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining,
6628
0
                           out_buf_ofs = 0, cur_file_ofs;
6629
0
  mz_zip_archive_file_stat file_stat;
6630
0
  void *pRead_buf = NULL;
6631
0
  void *pWrite_buf = NULL;
6632
0
  mz_uint32
6633
0
      local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
6634
0
                       sizeof(mz_uint32)];
6635
0
  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6636
6637
0
  if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))
6638
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6639
6640
0
  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
6641
0
    return MZ_FALSE;
6642
6643
  /* A directory or zero length file */
6644
0
  if (file_stat.m_is_directory || (!file_stat.m_comp_size))
6645
0
    return MZ_TRUE;
6646
6647
  /* Encryption and patch files are not supported. */
6648
0
  if (file_stat.m_bit_flag &
6649
0
      (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED |
6650
0
       MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION |
6651
0
       MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
6652
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
6653
6654
  /* This function only supports decompressing stored and deflate. */
6655
0
  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) &&
6656
0
      (file_stat.m_method != MZ_DEFLATED))
6657
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
6658
6659
  /* Read and do some minimal validation of the local directory entry (this
6660
   * doesn't crack the zip64 stuff, which we already have from the central dir)
6661
   */
6662
0
  cur_file_ofs = file_stat.m_local_header_ofs;
6663
0
  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header,
6664
0
                    MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6665
0
      MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6666
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6667
6668
0
  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6669
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6670
6671
0
  cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
6672
0
                  MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
6673
0
                  MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6674
0
  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
6675
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6676
6677
  /* Decompress the file either directly from memory or from a file input
6678
   * buffer. */
6679
0
  if (pZip->m_pState->m_pMem) {
6680
0
    pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
6681
0
    read_buf_size = read_buf_avail = file_stat.m_comp_size;
6682
0
    comp_remaining = 0;
6683
0
  } else {
6684
0
    read_buf_size =
6685
0
        MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
6686
0
    if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
6687
0
                                            (size_t)read_buf_size)))
6688
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6689
6690
0
    read_buf_avail = 0;
6691
0
    comp_remaining = file_stat.m_comp_size;
6692
0
  }
6693
6694
0
  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) {
6695
    /* The file is stored or the caller has requested the compressed data. */
6696
0
    if (pZip->m_pState->m_pMem) {
6697
0
      if (((sizeof(size_t) == sizeof(mz_uint32))) &&
6698
0
          (file_stat.m_comp_size > MZ_UINT32_MAX))
6699
0
        return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6700
6701
0
      if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
6702
0
                    (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) {
6703
0
        mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
6704
0
        status = TINFL_STATUS_FAILED;
6705
0
      } else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) {
6706
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
6707
0
        file_crc32 =
6708
0
            (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf,
6709
0
                                (size_t)file_stat.m_comp_size);
6710
0
#endif
6711
0
      }
6712
6713
0
      cur_file_ofs += file_stat.m_comp_size;
6714
0
      out_buf_ofs += file_stat.m_comp_size;
6715
0
      comp_remaining = 0;
6716
0
    } else {
6717
0
      while (comp_remaining) {
6718
0
        read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
6719
0
        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
6720
0
                          (size_t)read_buf_avail) != read_buf_avail) {
6721
0
          mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6722
0
          status = TINFL_STATUS_FAILED;
6723
0
          break;
6724
0
        }
6725
6726
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
6727
0
        if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) {
6728
0
          file_crc32 = (mz_uint32)mz_crc32(
6729
0
              file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
6730
0
        }
6731
0
#endif
6732
6733
0
        if (pCallback(pOpaque, out_buf_ofs, pRead_buf,
6734
0
                      (size_t)read_buf_avail) != read_buf_avail) {
6735
0
          mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
6736
0
          status = TINFL_STATUS_FAILED;
6737
0
          break;
6738
0
        }
6739
6740
0
        cur_file_ofs += read_buf_avail;
6741
0
        out_buf_ofs += read_buf_avail;
6742
0
        comp_remaining -= read_buf_avail;
6743
0
      }
6744
0
    }
6745
0
  } else {
6746
0
    tinfl_decompressor inflator;
6747
0
    tinfl_init(&inflator);
6748
6749
0
    if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
6750
0
                                             TINFL_LZ_DICT_SIZE))) {
6751
0
      mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6752
0
      status = TINFL_STATUS_FAILED;
6753
0
    } else {
6754
0
      do {
6755
0
        mz_uint8 *pWrite_buf_cur =
6756
0
            (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
6757
0
        size_t in_buf_size,
6758
0
            out_buf_size =
6759
0
                TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
6760
0
        if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) {
6761
0
          read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
6762
0
          if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf,
6763
0
                            (size_t)read_buf_avail) != read_buf_avail) {
6764
0
            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6765
0
            status = TINFL_STATUS_FAILED;
6766
0
            break;
6767
0
          }
6768
0
          cur_file_ofs += read_buf_avail;
6769
0
          comp_remaining -= read_buf_avail;
6770
0
          read_buf_ofs = 0;
6771
0
        }
6772
6773
0
        in_buf_size = (size_t)read_buf_avail;
6774
0
        status = tinfl_decompress(
6775
0
            &inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size,
6776
0
            (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size,
6777
0
            comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
6778
0
        read_buf_avail -= in_buf_size;
6779
0
        read_buf_ofs += in_buf_size;
6780
6781
0
        if (out_buf_size) {
6782
0
          if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) !=
6783
0
              out_buf_size) {
6784
0
            mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
6785
0
            status = TINFL_STATUS_FAILED;
6786
0
            break;
6787
0
          }
6788
6789
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
6790
0
          file_crc32 =
6791
0
              (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
6792
0
#endif
6793
0
          if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) {
6794
0
            mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
6795
0
            status = TINFL_STATUS_FAILED;
6796
0
            break;
6797
0
          }
6798
0
        }
6799
0
      } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) ||
6800
0
               (status == TINFL_STATUS_HAS_MORE_OUTPUT));
6801
0
    }
6802
0
  }
6803
6804
0
  if ((status == TINFL_STATUS_DONE) &&
6805
0
      (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) {
6806
    /* Make sure the entire file was decompressed, and check its CRC. */
6807
0
    if (out_buf_ofs != file_stat.m_uncomp_size) {
6808
0
      mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
6809
0
      status = TINFL_STATUS_FAILED;
6810
0
    }
6811
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
6812
0
    else if (file_crc32 != file_stat.m_crc32) {
6813
0
      mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
6814
0
      status = TINFL_STATUS_FAILED;
6815
0
    }
6816
0
#endif
6817
0
  }
6818
6819
0
  if (!pZip->m_pState->m_pMem)
6820
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6821
6822
0
  if (pWrite_buf)
6823
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
6824
6825
0
  return status == TINFL_STATUS_DONE;
6826
0
}
6827
6828
mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip,
6829
                                               const char *pFilename,
6830
                                               mz_file_write_func pCallback,
6831
0
                                               void *pOpaque, mz_uint flags) {
6832
0
  mz_uint32 file_index;
6833
0
  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
6834
0
    return MZ_FALSE;
6835
6836
0
  return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque,
6837
0
                                           flags);
6838
0
}
6839
6840
mz_zip_reader_extract_iter_state *
6841
mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index,
6842
0
                               mz_uint flags) {
6843
0
  mz_zip_reader_extract_iter_state *pState;
6844
0
  mz_uint32
6845
0
      local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
6846
0
                       sizeof(mz_uint32)];
6847
0
  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6848
6849
  /* Argument sanity check */
6850
0
  if ((!pZip) || (!pZip->m_pState))
6851
0
    return NULL;
6852
6853
  /* Allocate an iterator status structure */
6854
0
  pState = (mz_zip_reader_extract_iter_state *)pZip->m_pAlloc(
6855
0
      pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_reader_extract_iter_state));
6856
0
  if (!pState) {
6857
0
    mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6858
0
    return NULL;
6859
0
  }
6860
6861
  /* Fetch file details */
6862
0
  if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat)) {
6863
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6864
0
    return NULL;
6865
0
  }
6866
6867
  /* Encryption and patch files are not supported. */
6868
0
  if (pState->file_stat.m_bit_flag &
6869
0
      (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED |
6870
0
       MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION |
6871
0
       MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)) {
6872
0
    mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
6873
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6874
0
    return NULL;
6875
0
  }
6876
6877
  /* This function only supports decompressing stored and deflate. */
6878
0
  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) &&
6879
0
      (pState->file_stat.m_method != 0) &&
6880
0
      (pState->file_stat.m_method != MZ_DEFLATED)) {
6881
0
    mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
6882
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6883
0
    return NULL;
6884
0
  }
6885
6886
  /* Init state - save args */
6887
0
  pState->pZip = pZip;
6888
0
  pState->flags = flags;
6889
6890
  /* Init state - reset variables to defaults */
6891
0
  pState->status = TINFL_STATUS_DONE;
6892
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
6893
0
  pState->file_crc32 = MZ_CRC32_INIT;
6894
0
#endif
6895
0
  pState->read_buf_ofs = 0;
6896
0
  pState->out_buf_ofs = 0;
6897
0
  pState->pRead_buf = NULL;
6898
0
  pState->pWrite_buf = NULL;
6899
0
  pState->out_blk_remain = 0;
6900
6901
  /* Read and parse the local directory entry. */
6902
0
  pState->cur_file_ofs = pState->file_stat.m_local_header_ofs;
6903
0
  if (pZip->m_pRead(pZip->m_pIO_opaque, pState->cur_file_ofs, pLocal_header,
6904
0
                    MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
6905
0
      MZ_ZIP_LOCAL_DIR_HEADER_SIZE) {
6906
0
    mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6907
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6908
0
    return NULL;
6909
0
  }
6910
6911
0
  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) {
6912
0
    mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6913
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6914
0
    return NULL;
6915
0
  }
6916
6917
0
  pState->cur_file_ofs +=
6918
0
      MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
6919
0
      MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) +
6920
0
      MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6921
0
  if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) >
6922
0
      pZip->m_archive_size) {
6923
0
    mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6924
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6925
0
    return NULL;
6926
0
  }
6927
6928
  /* Decompress the file either directly from memory or from a file input
6929
   * buffer. */
6930
0
  if (pZip->m_pState->m_pMem) {
6931
0
    pState->pRead_buf =
6932
0
        (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs;
6933
0
    pState->read_buf_size = pState->read_buf_avail =
6934
0
        pState->file_stat.m_comp_size;
6935
0
    pState->comp_remaining = pState->file_stat.m_comp_size;
6936
0
  } else {
6937
0
    if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ||
6938
0
          (!pState->file_stat.m_method))) {
6939
      /* Decompression required, therefore intermediate read buffer required */
6940
0
      pState->read_buf_size = MZ_MIN(pState->file_stat.m_comp_size,
6941
0
                                     (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
6942
0
      if (NULL ==
6943
0
          (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
6944
0
                                              (size_t)pState->read_buf_size))) {
6945
0
        mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6946
0
        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6947
0
        return NULL;
6948
0
      }
6949
0
    } else {
6950
      /* Decompression not required - we will be reading directly into user
6951
       * buffer, no temp buf required */
6952
0
      pState->read_buf_size = 0;
6953
0
    }
6954
0
    pState->read_buf_avail = 0;
6955
0
    pState->comp_remaining = pState->file_stat.m_comp_size;
6956
0
  }
6957
6958
0
  if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ||
6959
0
        (!pState->file_stat.m_method))) {
6960
    /* Decompression required, init decompressor */
6961
0
    tinfl_init(&pState->inflator);
6962
6963
    /* Allocate write buffer */
6964
0
    if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1,
6965
0
                                                     TINFL_LZ_DICT_SIZE))) {
6966
0
      mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6967
0
      if (pState->pRead_buf)
6968
0
        pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf);
6969
0
      pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
6970
0
      return NULL;
6971
0
    }
6972
0
  }
6973
6974
0
  return pState;
6975
0
}
6976
6977
mz_zip_reader_extract_iter_state *
6978
mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename,
6979
0
                                    mz_uint flags) {
6980
0
  mz_uint32 file_index;
6981
6982
  /* Locate file index by name */
6983
0
  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
6984
0
    return NULL;
6985
6986
  /* Construct iterator */
6987
0
  return mz_zip_reader_extract_iter_new(pZip, file_index, flags);
6988
0
}
6989
6990
size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state *pState,
6991
0
                                       void *pvBuf, size_t buf_size) {
6992
0
  size_t copied_to_caller = 0;
6993
6994
  /* Argument sanity check */
6995
0
  if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf))
6996
0
    return 0;
6997
6998
0
  if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ||
6999
0
      (!pState->file_stat.m_method)) {
7000
    /* The file is stored or the caller has requested the compressed data, calc
7001
     * amount to return. */
7002
0
    copied_to_caller = (size_t)MZ_MIN(buf_size, pState->comp_remaining);
7003
7004
    /* Zip is in memory....or requires reading from a file? */
7005
0
    if (pState->pZip->m_pState->m_pMem) {
7006
      /* Copy data to caller's buffer */
7007
0
      memcpy(pvBuf, pState->pRead_buf, copied_to_caller);
7008
0
      pState->pRead_buf = ((mz_uint8 *)pState->pRead_buf) + copied_to_caller;
7009
0
    } else {
7010
      /* Read directly into caller's buffer */
7011
0
      if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque,
7012
0
                                pState->cur_file_ofs, pvBuf,
7013
0
                                copied_to_caller) != copied_to_caller) {
7014
        /* Failed to read all that was asked for, flag failure and alert user */
7015
0
        mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
7016
0
        pState->status = TINFL_STATUS_FAILED;
7017
0
        copied_to_caller = 0;
7018
0
      }
7019
0
    }
7020
7021
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
7022
    /* Compute CRC if not returning compressed data only */
7023
0
    if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
7024
0
      pState->file_crc32 = (mz_uint32)mz_crc32(
7025
0
          pState->file_crc32, (const mz_uint8 *)pvBuf, copied_to_caller);
7026
0
#endif
7027
7028
    /* Advance offsets, dec counters */
7029
0
    pState->cur_file_ofs += copied_to_caller;
7030
0
    pState->out_buf_ofs += copied_to_caller;
7031
0
    pState->comp_remaining -= copied_to_caller;
7032
0
  } else {
7033
0
    do {
7034
      /* Calc ptr to write buffer - given current output pos and block size */
7035
0
      mz_uint8 *pWrite_buf_cur =
7036
0
          (mz_uint8 *)pState->pWrite_buf +
7037
0
          (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
7038
7039
      /* Calc max output size - given current output pos and block size */
7040
0
      size_t in_buf_size,
7041
0
          out_buf_size = TINFL_LZ_DICT_SIZE -
7042
0
                         (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
7043
7044
0
      if (!pState->out_blk_remain) {
7045
        /* Read more data from file if none available (and reading from file) */
7046
0
        if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem)) {
7047
          /* Calc read size */
7048
0
          pState->read_buf_avail =
7049
0
              MZ_MIN(pState->read_buf_size, pState->comp_remaining);
7050
0
          if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque,
7051
0
                                    pState->cur_file_ofs, pState->pRead_buf,
7052
0
                                    (size_t)pState->read_buf_avail) !=
7053
0
              pState->read_buf_avail) {
7054
0
            mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
7055
0
            pState->status = TINFL_STATUS_FAILED;
7056
0
            break;
7057
0
          }
7058
7059
          /* Advance offsets, dec counters */
7060
0
          pState->cur_file_ofs += pState->read_buf_avail;
7061
0
          pState->comp_remaining -= pState->read_buf_avail;
7062
0
          pState->read_buf_ofs = 0;
7063
0
        }
7064
7065
        /* Perform decompression */
7066
0
        in_buf_size = (size_t)pState->read_buf_avail;
7067
0
        pState->status = tinfl_decompress(
7068
0
            &pState->inflator,
7069
0
            (const mz_uint8 *)pState->pRead_buf + pState->read_buf_ofs,
7070
0
            &in_buf_size, (mz_uint8 *)pState->pWrite_buf, pWrite_buf_cur,
7071
0
            &out_buf_size,
7072
0
            pState->comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
7073
0
        pState->read_buf_avail -= in_buf_size;
7074
0
        pState->read_buf_ofs += in_buf_size;
7075
7076
        /* Update current output block size remaining */
7077
0
        pState->out_blk_remain = out_buf_size;
7078
0
      }
7079
7080
0
      if (pState->out_blk_remain) {
7081
        /* Calc amount to return. */
7082
0
        size_t to_copy =
7083
0
            MZ_MIN((buf_size - copied_to_caller), pState->out_blk_remain);
7084
7085
        /* Copy data to caller's buffer */
7086
0
        memcpy((uint8_t *)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy);
7087
7088
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
7089
        /* Perform CRC */
7090
0
        pState->file_crc32 =
7091
0
            (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy);
7092
0
#endif
7093
7094
        /* Decrement data consumed from block */
7095
0
        pState->out_blk_remain -= to_copy;
7096
7097
        /* Inc output offset, while performing sanity check */
7098
0
        if ((pState->out_buf_ofs += to_copy) >
7099
0
            pState->file_stat.m_uncomp_size) {
7100
0
          mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
7101
0
          pState->status = TINFL_STATUS_FAILED;
7102
0
          break;
7103
0
        }
7104
7105
        /* Increment counter of data copied to caller */
7106
0
        copied_to_caller += to_copy;
7107
0
      }
7108
0
    } while ((copied_to_caller < buf_size) &&
7109
0
             ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) ||
7110
0
              (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)));
7111
0
  }
7112
7113
  /* Return how many bytes were copied into user buffer */
7114
0
  return copied_to_caller;
7115
0
}
7116
7117
mz_bool
7118
0
mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state *pState) {
7119
0
  int status;
7120
7121
  /* Argument sanity check */
7122
0
  if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState))
7123
0
    return MZ_FALSE;
7124
7125
  /* Was decompression completed and requested? */
7126
0
  if ((pState->status == TINFL_STATUS_DONE) &&
7127
0
      (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) {
7128
    /* Make sure the entire file was decompressed, and check its CRC. */
7129
0
    if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size) {
7130
0
      mz_zip_set_error(pState->pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
7131
0
      pState->status = TINFL_STATUS_FAILED;
7132
0
    }
7133
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
7134
0
    else if (pState->file_crc32 != pState->file_stat.m_crc32) {
7135
0
      mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
7136
0
      pState->status = TINFL_STATUS_FAILED;
7137
0
    }
7138
0
#endif
7139
0
  }
7140
7141
  /* Free buffers */
7142
0
  if (!pState->pZip->m_pState->m_pMem)
7143
0
    pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf);
7144
0
  if (pState->pWrite_buf)
7145
0
    pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf);
7146
7147
  /* Save status */
7148
0
  status = pState->status;
7149
7150
  /* Free context */
7151
0
  pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState);
7152
7153
0
  return status == TINFL_STATUS_DONE;
7154
0
}
7155
7156
#ifndef MINIZ_NO_STDIO
7157
static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs,
7158
0
                                         const void *pBuf, size_t n) {
7159
0
  (void)ofs;
7160
7161
0
  return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
7162
0
}
7163
7164
mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index,
7165
                                      const char *pDst_filename,
7166
0
                                      mz_uint flags) {
7167
0
  mz_bool status;
7168
0
  mz_zip_archive_file_stat file_stat;
7169
0
  MZ_FILE *pFile;
7170
7171
0
  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
7172
0
    return MZ_FALSE;
7173
7174
0
  if (file_stat.m_is_directory || (!file_stat.m_is_supported))
7175
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
7176
7177
0
  pFile = MZ_FOPEN(pDst_filename, "wb");
7178
0
  if (!pFile)
7179
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
7180
7181
0
  status = mz_zip_reader_extract_to_callback(
7182
0
      pZip, file_index, mz_zip_file_write_callback, pFile, flags);
7183
7184
0
  if (MZ_FCLOSE(pFile) == EOF) {
7185
0
    if (status)
7186
0
      mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
7187
7188
0
    status = MZ_FALSE;
7189
0
  }
7190
7191
0
#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
7192
0
  if (status)
7193
0
    mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
7194
0
#endif
7195
7196
0
  return status;
7197
0
}
7198
7199
mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip,
7200
                                           const char *pArchive_filename,
7201
                                           const char *pDst_filename,
7202
0
                                           mz_uint flags) {
7203
0
  mz_uint32 file_index;
7204
0
  if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags,
7205
0
                                    &file_index))
7206
0
    return MZ_FALSE;
7207
7208
0
  return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
7209
0
}
7210
7211
mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index,
7212
0
                                       MZ_FILE *pFile, mz_uint flags) {
7213
0
  mz_zip_archive_file_stat file_stat;
7214
7215
0
  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
7216
0
    return MZ_FALSE;
7217
7218
0
  if (file_stat.m_is_directory || (!file_stat.m_is_supported))
7219
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
7220
7221
0
  return mz_zip_reader_extract_to_callback(
7222
0
      pZip, file_index, mz_zip_file_write_callback, pFile, flags);
7223
0
}
7224
7225
mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip,
7226
                                            const char *pArchive_filename,
7227
0
                                            MZ_FILE *pFile, mz_uint flags) {
7228
0
  mz_uint32 file_index;
7229
0
  if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags,
7230
0
                                    &file_index))
7231
0
    return MZ_FALSE;
7232
7233
0
  return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
7234
0
}
7235
#endif /* #ifndef MINIZ_NO_STDIO */
7236
7237
static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs,
7238
0
                                            const void *pBuf, size_t n) {
7239
0
  mz_uint32 *p = (mz_uint32 *)pOpaque;
7240
0
  (void)file_ofs;
7241
0
  *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n);
7242
0
  return n;
7243
0
}
7244
7245
mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index,
7246
0
                             mz_uint flags) {
7247
0
  mz_zip_archive_file_stat file_stat;
7248
0
  mz_zip_internal_state *pState;
7249
0
  const mz_uint8 *pCentral_dir_header;
7250
0
  mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;
7251
0
  mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
7252
0
  mz_uint32
7253
0
      local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
7254
0
                       sizeof(mz_uint32)];
7255
0
  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
7256
0
  mz_uint64 local_header_ofs = 0;
7257
0
  mz_uint32 local_header_filename_len, local_header_extra_len,
7258
0
      local_header_crc32;
7259
0
  mz_uint64 local_header_comp_size, local_header_uncomp_size;
7260
0
  mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;
7261
0
  mz_bool has_data_descriptor;
7262
0
  mz_uint32 local_header_bit_flags;
7263
7264
0
  mz_zip_array file_data_array;
7265
0
  mz_zip_array_init(&file_data_array, 1);
7266
7267
0
  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
7268
0
      (!pZip->m_pRead))
7269
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7270
7271
0
  if (file_index > pZip->m_total_files)
7272
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7273
7274
0
  pState = pZip->m_pState;
7275
7276
0
  pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);
7277
7278
0
  if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header,
7279
0
                                 &file_stat, &found_zip64_ext_data_in_cdir))
7280
0
    return MZ_FALSE;
7281
7282
  /* A directory or zero length file */
7283
0
  if (file_stat.m_is_directory || (!file_stat.m_uncomp_size))
7284
0
    return MZ_TRUE;
7285
7286
  /* Encryption and patch files are not supported. */
7287
0
  if (file_stat.m_is_encrypted)
7288
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
7289
7290
  /* This function only supports stored and deflate. */
7291
0
  if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
7292
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
7293
7294
0
  if (!file_stat.m_is_supported)
7295
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
7296
7297
  /* Read and parse the local directory entry. */
7298
0
  local_header_ofs = file_stat.m_local_header_ofs;
7299
0
  if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header,
7300
0
                    MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
7301
0
      MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
7302
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7303
7304
0
  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
7305
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7306
7307
0
  local_header_filename_len =
7308
0
      MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
7309
0
  local_header_extra_len =
7310
0
      MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
7311
0
  local_header_comp_size =
7312
0
      MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
7313
0
  local_header_uncomp_size =
7314
0
      MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
7315
0
  local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);
7316
0
  local_header_bit_flags =
7317
0
      MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
7318
0
  has_data_descriptor = (local_header_bit_flags & 8) != 0;
7319
7320
0
  if (local_header_filename_len != strlen(file_stat.m_filename))
7321
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7322
7323
0
  if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
7324
0
       local_header_filename_len + local_header_extra_len +
7325
0
       file_stat.m_comp_size) > pZip->m_archive_size)
7326
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7327
7328
0
  if (!mz_zip_array_resize(
7329
0
          pZip, &file_data_array,
7330
0
          MZ_MAX(local_header_filename_len, local_header_extra_len),
7331
0
          MZ_FALSE)) {
7332
0
    mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7333
0
    goto handle_failure;
7334
0
  }
7335
7336
0
  if (local_header_filename_len) {
7337
0
    if (pZip->m_pRead(pZip->m_pIO_opaque,
7338
0
                      local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE,
7339
0
                      file_data_array.m_p,
7340
0
                      local_header_filename_len) != local_header_filename_len) {
7341
0
      mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7342
0
      goto handle_failure;
7343
0
    }
7344
7345
    /* I've seen 1 archive that had the same pathname, but used backslashes in
7346
     * the local dir and forward slashes in the central dir. Do we care about
7347
     * this? For now, this case will fail validation. */
7348
0
    if (memcmp(file_stat.m_filename, file_data_array.m_p,
7349
0
               local_header_filename_len) != 0) {
7350
0
      mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
7351
0
      goto handle_failure;
7352
0
    }
7353
0
  }
7354
7355
0
  if ((local_header_extra_len) &&
7356
0
      ((local_header_comp_size == MZ_UINT32_MAX) ||
7357
0
       (local_header_uncomp_size == MZ_UINT32_MAX))) {
7358
0
    mz_uint32 extra_size_remaining = local_header_extra_len;
7359
0
    const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p;
7360
7361
0
    if (pZip->m_pRead(pZip->m_pIO_opaque,
7362
0
                      local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
7363
0
                          local_header_filename_len,
7364
0
                      file_data_array.m_p,
7365
0
                      local_header_extra_len) != local_header_extra_len) {
7366
0
      mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7367
0
      goto handle_failure;
7368
0
    }
7369
7370
0
    do {
7371
0
      mz_uint32 field_id, field_data_size, field_total_size;
7372
7373
0
      if (extra_size_remaining < (sizeof(mz_uint16) * 2)) {
7374
0
        mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7375
0
        goto handle_failure;
7376
0
      }
7377
7378
0
      field_id = MZ_READ_LE16(pExtra_data);
7379
0
      field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
7380
0
      field_total_size = field_data_size + sizeof(mz_uint16) * 2;
7381
7382
0
      if (field_total_size > extra_size_remaining) {
7383
0
        mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7384
0
        goto handle_failure;
7385
0
      }
7386
7387
0
      if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) {
7388
0
        const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
7389
7390
0
        if (field_data_size < sizeof(mz_uint64) * 2) {
7391
0
          mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7392
0
          goto handle_failure;
7393
0
        }
7394
7395
0
        local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
7396
0
        local_header_comp_size =
7397
0
            MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64));
7398
7399
0
        found_zip64_ext_data_in_ldir = MZ_TRUE;
7400
0
        break;
7401
0
      }
7402
7403
0
      pExtra_data += field_total_size;
7404
0
      extra_size_remaining -= field_total_size;
7405
0
    } while (extra_size_remaining);
7406
0
  }
7407
7408
  /* TODO: parse local header extra data when local_header_comp_size is
7409
   * 0xFFFFFFFF! (big_descriptor.zip) */
7410
  /* I've seen zips in the wild with the data descriptor bit set, but proper
7411
   * local header values and bogus data descriptors */
7412
0
  if ((has_data_descriptor) && (!local_header_comp_size) &&
7413
0
      (!local_header_crc32)) {
7414
0
    mz_uint8 descriptor_buf[32];
7415
0
    mz_bool has_id;
7416
0
    const mz_uint8 *pSrc;
7417
0
    mz_uint32 file_crc32;
7418
0
    mz_uint64 comp_size = 0, uncomp_size = 0;
7419
7420
0
    mz_uint32 num_descriptor_uint32s =
7421
0
        ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;
7422
7423
0
    if (pZip->m_pRead(pZip->m_pIO_opaque,
7424
0
                      local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
7425
0
                          local_header_filename_len + local_header_extra_len +
7426
0
                          file_stat.m_comp_size,
7427
0
                      descriptor_buf,
7428
0
                      sizeof(mz_uint32) * num_descriptor_uint32s) !=
7429
0
        (sizeof(mz_uint32) * num_descriptor_uint32s)) {
7430
0
      mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7431
0
      goto handle_failure;
7432
0
    }
7433
7434
0
    has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
7435
0
    pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf;
7436
7437
0
    file_crc32 = MZ_READ_LE32(pSrc);
7438
7439
0
    if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) {
7440
0
      comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32));
7441
0
      uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64));
7442
0
    } else {
7443
0
      comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32));
7444
0
      uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32));
7445
0
    }
7446
7447
0
    if ((file_crc32 != file_stat.m_crc32) ||
7448
0
        (comp_size != file_stat.m_comp_size) ||
7449
0
        (uncomp_size != file_stat.m_uncomp_size)) {
7450
0
      mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
7451
0
      goto handle_failure;
7452
0
    }
7453
0
  } else {
7454
0
    if ((local_header_crc32 != file_stat.m_crc32) ||
7455
0
        (local_header_comp_size != file_stat.m_comp_size) ||
7456
0
        (local_header_uncomp_size != file_stat.m_uncomp_size)) {
7457
0
      mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
7458
0
      goto handle_failure;
7459
0
    }
7460
0
  }
7461
7462
0
  mz_zip_array_clear(pZip, &file_data_array);
7463
7464
0
  if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0) {
7465
0
    if (!mz_zip_reader_extract_to_callback(
7466
0
            pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))
7467
0
      return MZ_FALSE;
7468
7469
    /* 1 more check to be sure, although the extract checks too. */
7470
0
    if (uncomp_crc32 != file_stat.m_crc32) {
7471
0
      mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
7472
0
      return MZ_FALSE;
7473
0
    }
7474
0
  }
7475
7476
0
  return MZ_TRUE;
7477
7478
0
handle_failure:
7479
0
  mz_zip_array_clear(pZip, &file_data_array);
7480
0
  return MZ_FALSE;
7481
0
}
7482
7483
0
mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags) {
7484
0
  mz_zip_internal_state *pState;
7485
0
  uint32_t i;
7486
7487
0
  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
7488
0
      (!pZip->m_pRead))
7489
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7490
7491
0
  pState = pZip->m_pState;
7492
7493
  /* Basic sanity checks */
7494
0
  if (!pState->m_zip64) {
7495
0
    if (pZip->m_total_files > MZ_UINT16_MAX)
7496
0
      return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7497
7498
0
    if (pZip->m_archive_size > MZ_UINT32_MAX)
7499
0
      return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7500
0
  } else {
7501
0
    if (pZip->m_total_files >= MZ_UINT32_MAX)
7502
0
      return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7503
7504
0
    if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
7505
0
      return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7506
0
  }
7507
7508
0
  for (i = 0; i < pZip->m_total_files; i++) {
7509
0
    if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags) {
7510
0
      mz_uint32 found_index;
7511
0
      mz_zip_archive_file_stat stat;
7512
7513
0
      if (!mz_zip_reader_file_stat(pZip, i, &stat))
7514
0
        return MZ_FALSE;
7515
7516
0
      if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0,
7517
0
                                        &found_index))
7518
0
        return MZ_FALSE;
7519
7520
      /* This check can fail if there are duplicate filenames in the archive
7521
       * (which we don't check for when writing - that's up to the user) */
7522
0
      if (found_index != i)
7523
0
        return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
7524
0
    }
7525
7526
0
    if (!mz_zip_validate_file(pZip, i, flags))
7527
0
      return MZ_FALSE;
7528
0
  }
7529
7530
0
  return MZ_TRUE;
7531
0
}
7532
7533
mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size,
7534
0
                                    mz_uint flags, mz_zip_error *pErr) {
7535
0
  mz_bool success = MZ_TRUE;
7536
0
  mz_zip_archive zip;
7537
0
  mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
7538
7539
0
  if ((!pMem) || (!size)) {
7540
0
    if (pErr)
7541
0
      *pErr = MZ_ZIP_INVALID_PARAMETER;
7542
0
    return MZ_FALSE;
7543
0
  }
7544
7545
0
  mz_zip_zero_struct(&zip);
7546
7547
0
  if (!mz_zip_reader_init_mem(&zip, pMem, size, flags)) {
7548
0
    if (pErr)
7549
0
      *pErr = zip.m_last_error;
7550
0
    return MZ_FALSE;
7551
0
  }
7552
7553
0
  if (!mz_zip_validate_archive(&zip, flags)) {
7554
0
    actual_err = zip.m_last_error;
7555
0
    success = MZ_FALSE;
7556
0
  }
7557
7558
0
  if (!mz_zip_reader_end_internal(&zip, success)) {
7559
0
    if (!actual_err)
7560
0
      actual_err = zip.m_last_error;
7561
0
    success = MZ_FALSE;
7562
0
  }
7563
7564
0
  if (pErr)
7565
0
    *pErr = actual_err;
7566
7567
0
  return success;
7568
0
}
7569
7570
#ifndef MINIZ_NO_STDIO
7571
mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags,
7572
0
                                     mz_zip_error *pErr) {
7573
0
  mz_bool success = MZ_TRUE;
7574
0
  mz_zip_archive zip;
7575
0
  mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
7576
7577
0
  if (!pFilename) {
7578
0
    if (pErr)
7579
0
      *pErr = MZ_ZIP_INVALID_PARAMETER;
7580
0
    return MZ_FALSE;
7581
0
  }
7582
7583
0
  mz_zip_zero_struct(&zip);
7584
7585
0
  if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0)) {
7586
0
    if (pErr)
7587
0
      *pErr = zip.m_last_error;
7588
0
    return MZ_FALSE;
7589
0
  }
7590
7591
0
  if (!mz_zip_validate_archive(&zip, flags)) {
7592
0
    actual_err = zip.m_last_error;
7593
0
    success = MZ_FALSE;
7594
0
  }
7595
7596
0
  if (!mz_zip_reader_end_internal(&zip, success)) {
7597
0
    if (!actual_err)
7598
0
      actual_err = zip.m_last_error;
7599
0
    success = MZ_FALSE;
7600
0
  }
7601
7602
0
  if (pErr)
7603
0
    *pErr = actual_err;
7604
7605
0
  return success;
7606
0
}
7607
#endif /* #ifndef MINIZ_NO_STDIO */
7608
7609
/* ------------------- .ZIP archive writing */
7610
7611
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
7612
7613
0
static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v) {
7614
0
  p[0] = (mz_uint8)v;
7615
0
  p[1] = (mz_uint8)(v >> 8);
7616
0
}
7617
0
static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v) {
7618
0
  p[0] = (mz_uint8)v;
7619
0
  p[1] = (mz_uint8)(v >> 8);
7620
0
  p[2] = (mz_uint8)(v >> 16);
7621
0
  p[3] = (mz_uint8)(v >> 24);
7622
0
}
7623
0
static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v) {
7624
0
  mz_write_le32(p, (mz_uint32)v);
7625
0
  mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32));
7626
0
}
7627
7628
0
#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
7629
0
#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
7630
0
#define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v))
7631
7632
static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs,
7633
0
                                     const void *pBuf, size_t n) {
7634
0
  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
7635
0
  mz_zip_internal_state *pState = pZip->m_pState;
7636
0
  mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
7637
7638
0
  if (!n)
7639
0
    return 0;
7640
7641
  /* An allocation this big is likely to just fail on 32-bit systems, so don't
7642
   * even go there. */
7643
0
  if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF)) {
7644
0
    mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
7645
0
    return 0;
7646
0
  }
7647
7648
0
  if (new_size > pState->m_mem_capacity) {
7649
0
    void *pNew_block;
7650
0
    size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
7651
7652
0
    while (new_capacity < new_size)
7653
0
      new_capacity *= 2;
7654
7655
0
    if (NULL == (pNew_block = pZip->m_pRealloc(
7656
0
                     pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) {
7657
0
      mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7658
0
      return 0;
7659
0
    }
7660
7661
0
    pState->m_pMem = pNew_block;
7662
0
    pState->m_mem_capacity = new_capacity;
7663
0
  }
7664
0
  memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
7665
0
  pState->m_mem_size = (size_t)new_size;
7666
0
  return n;
7667
0
}
7668
7669
static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip,
7670
0
                                          mz_bool set_last_error) {
7671
0
  mz_zip_internal_state *pState;
7672
0
  mz_bool status = MZ_TRUE;
7673
7674
0
  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) ||
7675
0
      ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) &&
7676
0
       (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) {
7677
0
    if (set_last_error)
7678
0
      mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7679
0
    return MZ_FALSE;
7680
0
  }
7681
7682
0
  pState = pZip->m_pState;
7683
0
  pZip->m_pState = NULL;
7684
0
  mz_zip_array_clear(pZip, &pState->m_central_dir);
7685
0
  mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
7686
0
  mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
7687
7688
0
#ifndef MINIZ_NO_STDIO
7689
0
  if (pState->m_pFile) {
7690
0
    if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) {
7691
0
      if (MZ_FCLOSE(pState->m_pFile) == EOF) {
7692
0
        if (set_last_error)
7693
0
          mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
7694
0
        status = MZ_FALSE;
7695
0
      }
7696
0
    }
7697
7698
0
    pState->m_pFile = NULL;
7699
0
  }
7700
0
#endif /* #ifndef MINIZ_NO_STDIO */
7701
7702
0
  if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) {
7703
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
7704
0
    pState->m_pMem = NULL;
7705
0
  }
7706
7707
0
  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
7708
0
  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
7709
0
  return status;
7710
0
}
7711
7712
mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size,
7713
0
                              mz_uint flags) {
7714
0
  mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;
7715
7716
0
  if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) ||
7717
0
      (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
7718
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7719
7720
0
  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) {
7721
0
    if (!pZip->m_pRead)
7722
0
      return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7723
0
  }
7724
7725
0
  if (pZip->m_file_offset_alignment) {
7726
    /* Ensure user specified file offset alignment is a power of 2. */
7727
0
    if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
7728
0
      return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7729
0
  }
7730
7731
0
  if (!pZip->m_pAlloc)
7732
0
    pZip->m_pAlloc = miniz_def_alloc_func;
7733
0
  if (!pZip->m_pFree)
7734
0
    pZip->m_pFree = miniz_def_free_func;
7735
0
  if (!pZip->m_pRealloc)
7736
0
    pZip->m_pRealloc = miniz_def_realloc_func;
7737
7738
0
  pZip->m_archive_size = existing_size;
7739
0
  pZip->m_central_directory_file_ofs = 0;
7740
0
  pZip->m_total_files = 0;
7741
7742
0
  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(
7743
0
                   pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
7744
0
    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7745
7746
0
  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
7747
7748
0
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir,
7749
0
                                sizeof(mz_uint8));
7750
0
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets,
7751
0
                                sizeof(mz_uint32));
7752
0
  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets,
7753
0
                                sizeof(mz_uint32));
7754
7755
0
  pZip->m_pState->m_zip64 = zip64;
7756
0
  pZip->m_pState->m_zip64_has_extended_info_fields = zip64;
7757
7758
0
  pZip->m_zip_type = MZ_ZIP_TYPE_USER;
7759
0
  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
7760
7761
0
  return MZ_TRUE;
7762
0
}
7763
7764
0
mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) {
7765
0
  return mz_zip_writer_init_v2(pZip, existing_size, 0);
7766
0
}
7767
7768
mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip,
7769
                                   size_t size_to_reserve_at_beginning,
7770
                                   size_t initial_allocation_size,
7771
0
                                   mz_uint flags) {
7772
0
  pZip->m_pWrite = mz_zip_heap_write_func;
7773
0
  pZip->m_pNeeds_keepalive = NULL;
7774
7775
0
  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
7776
0
    pZip->m_pRead = mz_zip_mem_read_func;
7777
7778
0
  pZip->m_pIO_opaque = pZip;
7779
7780
0
  if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
7781
0
    return MZ_FALSE;
7782
7783
0
  pZip->m_zip_type = MZ_ZIP_TYPE_HEAP;
7784
7785
0
  if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size,
7786
0
                                             size_to_reserve_at_beginning))) {
7787
0
    if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(
7788
0
                     pZip->m_pAlloc_opaque, 1, initial_allocation_size))) {
7789
0
      mz_zip_writer_end_internal(pZip, MZ_FALSE);
7790
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7791
0
    }
7792
0
    pZip->m_pState->m_mem_capacity = initial_allocation_size;
7793
0
  }
7794
7795
0
  return MZ_TRUE;
7796
0
}
7797
7798
mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip,
7799
                                size_t size_to_reserve_at_beginning,
7800
0
                                size_t initial_allocation_size) {
7801
0
  return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning,
7802
0
                                    initial_allocation_size, 0);
7803
0
}
7804
7805
#ifndef MINIZ_NO_STDIO
7806
static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs,
7807
0
                                     const void *pBuf, size_t n) {
7808
0
  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
7809
0
  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
7810
7811
0
  file_ofs += pZip->m_pState->m_file_archive_start_ofs;
7812
7813
0
  if (((mz_int64)file_ofs < 0) ||
7814
0
      (((cur_ofs != (mz_int64)file_ofs)) &&
7815
0
       (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) {
7816
0
    mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
7817
0
    return 0;
7818
0
  }
7819
7820
0
  return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
7821
0
}
7822
7823
mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename,
7824
0
                                mz_uint64 size_to_reserve_at_beginning) {
7825
0
  return mz_zip_writer_init_file_v2(pZip, pFilename,
7826
0
                                    size_to_reserve_at_beginning, 0);
7827
0
}
7828
7829
mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename,
7830
                                   mz_uint64 size_to_reserve_at_beginning,
7831
0
                                   mz_uint flags) {
7832
0
  MZ_FILE *pFile;
7833
7834
0
  pZip->m_pWrite = mz_zip_file_write_func;
7835
0
  pZip->m_pNeeds_keepalive = NULL;
7836
7837
0
  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
7838
0
    pZip->m_pRead = mz_zip_file_read_func;
7839
7840
0
  pZip->m_pIO_opaque = pZip;
7841
7842
0
  if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
7843
0
    return MZ_FALSE;
7844
7845
0
  if (NULL == (pFile = MZ_FOPEN(
7846
0
                   pFilename,
7847
0
                   (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb"))) {
7848
0
    mz_zip_writer_end(pZip);
7849
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
7850
0
  }
7851
7852
0
  pZip->m_pState->m_pFile = pFile;
7853
0
  pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
7854
7855
0
  if (size_to_reserve_at_beginning) {
7856
0
    mz_uint64 cur_ofs = 0;
7857
0
    char buf[4096];
7858
7859
0
    MZ_CLEAR_OBJ(buf);
7860
7861
0
    do {
7862
0
      size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
7863
0
      if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) {
7864
0
        mz_zip_writer_end(pZip);
7865
0
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7866
0
      }
7867
0
      cur_ofs += n;
7868
0
      size_to_reserve_at_beginning -= n;
7869
0
    } while (size_to_reserve_at_beginning);
7870
0
  }
7871
7872
0
  return MZ_TRUE;
7873
0
}
7874
7875
mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile,
7876
0
                                 mz_uint flags) {
7877
0
  pZip->m_pWrite = mz_zip_file_write_func;
7878
0
  pZip->m_pNeeds_keepalive = NULL;
7879
7880
0
  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
7881
0
    pZip->m_pRead = mz_zip_file_read_func;
7882
7883
0
  pZip->m_pIO_opaque = pZip;
7884
7885
0
  if (!mz_zip_writer_init_v2(pZip, 0, flags))
7886
0
    return MZ_FALSE;
7887
7888
0
  pZip->m_pState->m_pFile = pFile;
7889
0
  pZip->m_pState->m_file_archive_start_ofs =
7890
0
      MZ_FTELL64(pZip->m_pState->m_pFile);
7891
0
  pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
7892
7893
0
  return MZ_TRUE;
7894
0
}
7895
#endif /* #ifndef MINIZ_NO_STDIO */
7896
7897
mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip,
7898
                                          const char *pFilename,
7899
0
                                          mz_uint flags) {
7900
0
  mz_zip_internal_state *pState;
7901
7902
0
  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
7903
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7904
7905
0
  if (flags & MZ_ZIP_FLAG_WRITE_ZIP64) {
7906
    /* We don't support converting a non-zip64 file to zip64 - this seems like
7907
     * more trouble than it's worth. (What about the existing 32-bit data
7908
     * descriptors that could follow the compressed data?) */
7909
0
    if (!pZip->m_pState->m_zip64)
7910
0
      return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7911
0
  }
7912
7913
  /* No sense in trying to write to an archive that's already at the support max
7914
   * size */
7915
0
  if (pZip->m_pState->m_zip64) {
7916
0
    if (pZip->m_total_files == MZ_UINT32_MAX)
7917
0
      return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7918
0
  } else {
7919
0
    if (pZip->m_total_files == MZ_UINT16_MAX)
7920
0
      return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7921
7922
0
    if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
7923
0
         MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)
7924
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
7925
0
  }
7926
7927
0
  pState = pZip->m_pState;
7928
7929
0
  if (pState->m_pFile) {
7930
#ifdef MINIZ_NO_STDIO
7931
    (void)pFilename;
7932
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7933
#else
7934
0
    if (pZip->m_pIO_opaque != pZip)
7935
0
      return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7936
7937
0
    if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE) {
7938
0
      if (!pFilename)
7939
0
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7940
7941
      /* Archive is being read from stdio and was originally opened only for
7942
       * reading. Try to reopen as writable. */
7943
0
      if (NULL ==
7944
0
          (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) {
7945
        /* The mz_zip_archive is now in a bogus state because pState->m_pFile is
7946
         * NULL, so just close it. */
7947
0
        mz_zip_reader_end_internal(pZip, MZ_FALSE);
7948
0
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
7949
0
      }
7950
0
    }
7951
7952
0
    pZip->m_pWrite = mz_zip_file_write_func;
7953
0
    pZip->m_pNeeds_keepalive = NULL;
7954
0
#endif /* #ifdef MINIZ_NO_STDIO */
7955
0
  } else if (pState->m_pMem) {
7956
    /* Archive lives in a memory block. Assume it's from the heap that we can
7957
     * resize using the realloc callback. */
7958
0
    if (pZip->m_pIO_opaque != pZip)
7959
0
      return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7960
7961
0
    pState->m_mem_capacity = pState->m_mem_size;
7962
0
    pZip->m_pWrite = mz_zip_heap_write_func;
7963
0
    pZip->m_pNeeds_keepalive = NULL;
7964
0
  }
7965
  /* Archive is being read via a user provided read function - make sure the
7966
     user has specified a write function too. */
7967
0
  else if (!pZip->m_pWrite)
7968
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7969
7970
  /* Start writing new files at the archive's current central directory
7971
   * location. */
7972
  /* TODO: We could add a flag that lets the user start writing immediately
7973
   * AFTER the existing central dir - this would be safer. */
7974
0
  pZip->m_archive_size = pZip->m_central_directory_file_ofs;
7975
0
  pZip->m_central_directory_file_ofs = 0;
7976
7977
  /* Clear the sorted central dir offsets, they aren't useful or maintained now.
7978
   */
7979
  /* Even though we're now in write mode, files can still be extracted and
7980
   * verified, but file locates will be slow. */
7981
  /* TODO: We could easily maintain the sorted central directory offsets. */
7982
0
  mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets);
7983
7984
0
  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
7985
7986
0
  return MZ_TRUE;
7987
0
}
7988
7989
mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip,
7990
0
                                       const char *pFilename) {
7991
0
  return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);
7992
0
}
7993
7994
/* TODO: pArchive_name is a terrible name here! */
7995
mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name,
7996
                              const void *pBuf, size_t buf_size,
7997
0
                              mz_uint level_and_flags) {
7998
0
  return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0,
7999
0
                                  level_and_flags, 0, 0);
8000
0
}
8001
8002
typedef struct {
8003
  mz_zip_archive *m_pZip;
8004
  mz_uint64 m_cur_archive_file_ofs;
8005
  mz_uint64 m_comp_size;
8006
} mz_zip_writer_add_state;
8007
8008
static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len,
8009
0
                                                  void *pUser) {
8010
0
  mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
8011
0
  if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque,
8012
0
                                    pState->m_cur_archive_file_ofs, pBuf,
8013
0
                                    len) != len)
8014
0
    return MZ_FALSE;
8015
8016
0
  pState->m_cur_archive_file_ofs += len;
8017
0
  pState->m_comp_size += len;
8018
0
  return MZ_TRUE;
8019
0
}
8020
8021
#define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE                                    \
8022
  (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)
8023
#define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE                                  \
8024
0
  (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3)
8025
static mz_uint32
8026
mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size,
8027
                                      mz_uint64 *pComp_size,
8028
0
                                      mz_uint64 *pLocal_header_ofs) {
8029
0
  mz_uint8 *pDst = pBuf;
8030
0
  mz_uint32 field_size = 0;
8031
8032
0
  MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
8033
0
  MZ_WRITE_LE16(pDst + 2, 0);
8034
0
  pDst += sizeof(mz_uint16) * 2;
8035
8036
0
  if (pUncomp_size) {
8037
0
    MZ_WRITE_LE64(pDst, *pUncomp_size);
8038
0
    pDst += sizeof(mz_uint64);
8039
0
    field_size += sizeof(mz_uint64);
8040
0
  }
8041
8042
0
  if (pComp_size) {
8043
0
    MZ_WRITE_LE64(pDst, *pComp_size);
8044
0
    pDst += sizeof(mz_uint64);
8045
0
    field_size += sizeof(mz_uint64);
8046
0
  }
8047
8048
0
  if (pLocal_header_ofs) {
8049
0
    MZ_WRITE_LE64(pDst, *pLocal_header_ofs);
8050
0
    pDst += sizeof(mz_uint64);
8051
0
    field_size += sizeof(mz_uint64);
8052
0
  }
8053
8054
0
  MZ_WRITE_LE16(pBuf + 2, field_size);
8055
8056
0
  return (mz_uint32)(pDst - pBuf);
8057
0
}
8058
8059
static mz_bool mz_zip_writer_create_local_dir_header(
8060
    mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
8061
    mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
8062
    mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
8063
0
    mz_uint16 dos_time, mz_uint16 dos_date) {
8064
0
  (void)pZip;
8065
0
  memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
8066
0
  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
8067
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
8068
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
8069
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
8070
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
8071
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
8072
0
  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
8073
0
  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS,
8074
0
                MZ_MIN(comp_size, MZ_UINT32_MAX));
8075
0
  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS,
8076
0
                MZ_MIN(uncomp_size, MZ_UINT32_MAX));
8077
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
8078
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
8079
0
  return MZ_TRUE;
8080
0
}
8081
8082
static mz_bool mz_zip_writer_create_central_dir_header(
8083
    mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size,
8084
    mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size,
8085
    mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method,
8086
    mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
8087
0
    mz_uint64 local_header_ofs, mz_uint32 ext_attributes) {
8088
0
  (void)pZip;
8089
0
  memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
8090
0
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
8091
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
8092
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
8093
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
8094
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
8095
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
8096
0
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
8097
0
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS,
8098
0
                MZ_MIN(comp_size, MZ_UINT32_MAX));
8099
0
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS,
8100
0
                MZ_MIN(uncomp_size, MZ_UINT32_MAX));
8101
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
8102
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
8103
0
  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
8104
0
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
8105
0
  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS,
8106
0
                MZ_MIN(local_header_ofs, MZ_UINT32_MAX));
8107
0
  return MZ_TRUE;
8108
0
}
8109
8110
static mz_bool mz_zip_writer_add_to_central_dir(
8111
    mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
8112
    const void *pExtra, mz_uint16 extra_size, const void *pComment,
8113
    mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size,
8114
    mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags,
8115
    mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs,
8116
    mz_uint32 ext_attributes, const char *user_extra_data,
8117
0
    mz_uint user_extra_data_len) {
8118
0
  mz_zip_internal_state *pState = pZip->m_pState;
8119
0
  mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
8120
0
  size_t orig_central_dir_size = pState->m_central_dir.m_size;
8121
0
  mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
8122
8123
0
  if (!pZip->m_pState->m_zip64) {
8124
0
    if (local_header_ofs > 0xFFFFFFFF)
8125
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
8126
0
  }
8127
8128
  /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
8129
0
  if (((mz_uint64)pState->m_central_dir.m_size +
8130
0
       MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size +
8131
0
       user_extra_data_len + comment_size) >= MZ_UINT32_MAX)
8132
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
8133
8134
0
  if (!mz_zip_writer_create_central_dir_header(
8135
0
          pZip, central_dir_header, filename_size,
8136
0
          (mz_uint16)(extra_size + user_extra_data_len), comment_size,
8137
0
          uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time,
8138
0
          dos_date, local_header_ofs, ext_attributes))
8139
0
    return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
8140
8141
0
  if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header,
8142
0
                               MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
8143
0
      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename,
8144
0
                               filename_size)) ||
8145
0
      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra,
8146
0
                               extra_size)) ||
8147
0
      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data,
8148
0
                               user_extra_data_len)) ||
8149
0
      (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment,
8150
0
                               comment_size)) ||
8151
0
      (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets,
8152
0
                               &central_dir_ofs, 1))) {
8153
    /* Try to resize the central directory array back into its original state.
8154
     */
8155
0
    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
8156
0
                        MZ_FALSE);
8157
0
    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
8158
0
  }
8159
8160
0
  return MZ_TRUE;
8161
0
}
8162
8163
0
static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) {
8164
  /* Basic ZIP archive filename validity checks: Valid filenames cannot start
8165
   * with a forward slash, cannot contain a drive letter, and cannot use
8166
   * DOS-style backward slashes. */
8167
0
  if (*pArchive_name == '/')
8168
0
    return MZ_FALSE;
8169
8170
  /* Making sure the name does not contain drive letters or DOS style backward
8171
   * slashes is the responsibility of the program using miniz*/
8172
8173
0
  return MZ_TRUE;
8174
0
}
8175
8176
static mz_uint
8177
0
mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) {
8178
0
  mz_uint32 n;
8179
0
  if (!pZip->m_file_offset_alignment)
8180
0
    return 0;
8181
0
  n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
8182
0
  return (mz_uint)((pZip->m_file_offset_alignment - n) &
8183
0
                   (pZip->m_file_offset_alignment - 1));
8184
0
}
8185
8186
static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip,
8187
0
                                         mz_uint64 cur_file_ofs, mz_uint32 n) {
8188
0
  char buf[4096];
8189
0
  memset(buf, 0, MZ_MIN(sizeof(buf), n));
8190
0
  while (n) {
8191
0
    mz_uint32 s = MZ_MIN(sizeof(buf), n);
8192
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
8193
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8194
8195
0
    cur_file_ofs += s;
8196
0
    n -= s;
8197
0
  }
8198
0
  return MZ_TRUE;
8199
0
}
8200
8201
mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip,
8202
                                 const char *pArchive_name, const void *pBuf,
8203
                                 size_t buf_size, const void *pComment,
8204
                                 mz_uint16 comment_size,
8205
                                 mz_uint level_and_flags, mz_uint64 uncomp_size,
8206
0
                                 mz_uint32 uncomp_crc32) {
8207
0
  return mz_zip_writer_add_mem_ex_v2(
8208
0
      pZip, pArchive_name, pBuf, buf_size, pComment, comment_size,
8209
0
      level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0);
8210
0
}
8211
8212
mz_bool mz_zip_writer_add_mem_ex_v2(
8213
    mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf,
8214
    size_t buf_size, const void *pComment, mz_uint16 comment_size,
8215
    mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32,
8216
    MZ_TIME_T *last_modified, const char *user_extra_data,
8217
    mz_uint user_extra_data_len, const char *user_extra_data_central,
8218
0
    mz_uint user_extra_data_central_len) {
8219
0
  mz_uint16 method = 0, dos_time = 0, dos_date = 0;
8220
0
  mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
8221
0
  mz_uint64 local_dir_header_ofs = pZip->m_archive_size,
8222
0
            cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
8223
0
  size_t archive_name_size;
8224
0
  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
8225
0
  tdefl_compressor *pComp = NULL;
8226
0
  mz_bool store_data_uncompressed;
8227
0
  mz_zip_internal_state *pState;
8228
0
  mz_uint8 *pExtra_data = NULL;
8229
0
  mz_uint32 extra_size = 0;
8230
0
  mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
8231
0
  mz_uint16 bit_flags = 0;
8232
8233
0
  if ((int)level_and_flags < 0)
8234
0
    level_and_flags = MZ_DEFAULT_LEVEL;
8235
8236
0
  if (uncomp_size ||
8237
0
      (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
8238
0
    bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
8239
8240
0
  if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
8241
0
    bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
8242
8243
0
  level = level_and_flags & 0xF;
8244
0
  store_data_uncompressed =
8245
0
      ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
8246
8247
0
  if ((!pZip) || (!pZip->m_pState) ||
8248
0
      (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) ||
8249
0
      (!pArchive_name) || ((comment_size) && (!pComment)) ||
8250
0
      (level > MZ_UBER_COMPRESSION))
8251
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
8252
8253
0
  pState = pZip->m_pState;
8254
8255
0
  if (pState->m_zip64) {
8256
0
    if (pZip->m_total_files == MZ_UINT32_MAX)
8257
0
      return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
8258
0
  } else {
8259
0
    if (pZip->m_total_files == MZ_UINT16_MAX) {
8260
0
      pState->m_zip64 = MZ_TRUE;
8261
      /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
8262
0
    }
8263
0
    if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) {
8264
0
      pState->m_zip64 = MZ_TRUE;
8265
      /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
8266
0
    }
8267
0
  }
8268
8269
0
  if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
8270
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
8271
8272
0
  if (!mz_zip_writer_validate_archive_name(pArchive_name))
8273
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
8274
8275
0
#ifndef MINIZ_NO_TIME
8276
0
  if (last_modified != NULL) {
8277
0
    mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
8278
0
  } else {
8279
0
    MZ_TIME_T cur_time;
8280
0
    time(&cur_time);
8281
0
    mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
8282
0
  }
8283
0
#endif /* #ifndef MINIZ_NO_TIME */
8284
8285
0
  if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) {
8286
0
    uncomp_crc32 =
8287
0
        (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
8288
0
    uncomp_size = buf_size;
8289
0
    if (uncomp_size <= 3) {
8290
0
      level = 0;
8291
0
      store_data_uncompressed = MZ_TRUE;
8292
0
    }
8293
0
  }
8294
8295
0
  archive_name_size = strlen(pArchive_name);
8296
0
  if (archive_name_size > MZ_UINT16_MAX)
8297
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
8298
8299
0
  num_alignment_padding_bytes =
8300
0
      mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
8301
8302
  /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
8303
0
  if (((mz_uint64)pState->m_central_dir.m_size +
8304
0
       MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size +
8305
0
       MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
8306
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
8307
8308
0
  if (!pState->m_zip64) {
8309
    /* Bail early if the archive would obviously become too large */
8310
0
    if ((pZip->m_archive_size + num_alignment_padding_bytes +
8311
0
         MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size +
8312
0
         MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size +
8313
0
         user_extra_data_len + pState->m_central_dir.m_size +
8314
0
         MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len +
8315
0
         MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF) {
8316
0
      pState->m_zip64 = MZ_TRUE;
8317
      /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
8318
0
    }
8319
0
  }
8320
8321
0
  if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) {
8322
    /* Set DOS Subdirectory attribute bit. */
8323
0
    ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
8324
8325
    /* Subdirectories cannot contain data. */
8326
0
    if ((buf_size) || (uncomp_size))
8327
0
      return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
8328
0
  }
8329
8330
  /* Try to do any allocations before writing to the archive, so if an
8331
   * allocation fails the file remains unmodified. (A good idea if we're doing
8332
   * an in-place modification.) */
8333
0
  if ((!mz_zip_array_ensure_room(
8334
0
          pZip, &pState->m_central_dir,
8335
0
          MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size +
8336
0
              (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) ||
8337
0
      (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
8338
0
    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
8339
8340
0
  if ((!store_data_uncompressed) && (buf_size)) {
8341
0
    if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(
8342
0
                     pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
8343
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
8344
0
  }
8345
8346
0
  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs,
8347
0
                                 num_alignment_padding_bytes)) {
8348
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
8349
0
    return MZ_FALSE;
8350
0
  }
8351
8352
0
  local_dir_header_ofs += num_alignment_padding_bytes;
8353
0
  if (pZip->m_file_offset_alignment) {
8354
0
    MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
8355
0
              0);
8356
0
  }
8357
0
  cur_archive_file_ofs += num_alignment_padding_bytes;
8358
8359
0
  MZ_CLEAR_OBJ(local_dir_header);
8360
8361
0
  if (!store_data_uncompressed ||
8362
0
      (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) {
8363
0
    method = MZ_DEFLATED;
8364
0
  }
8365
8366
0
  if (pState->m_zip64) {
8367
0
    if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) {
8368
0
      pExtra_data = extra_data;
8369
0
      extra_size = mz_zip_writer_create_zip64_extra_data(
8370
0
          extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
8371
0
          (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL,
8372
0
          (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs
8373
0
                                                  : NULL);
8374
0
    }
8375
8376
0
    if (!mz_zip_writer_create_local_dir_header(
8377
0
            pZip, local_dir_header, (mz_uint16)archive_name_size,
8378
0
            (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method,
8379
0
            bit_flags, dos_time, dos_date))
8380
0
      return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
8381
8382
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs,
8383
0
                       local_dir_header,
8384
0
                       sizeof(local_dir_header)) != sizeof(local_dir_header))
8385
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8386
8387
0
    cur_archive_file_ofs += sizeof(local_dir_header);
8388
8389
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
8390
0
                       archive_name_size) != archive_name_size) {
8391
0
      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
8392
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8393
0
    }
8394
0
    cur_archive_file_ofs += archive_name_size;
8395
8396
0
    if (pExtra_data != NULL) {
8397
0
      if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data,
8398
0
                         extra_size) != extra_size)
8399
0
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8400
8401
0
      cur_archive_file_ofs += extra_size;
8402
0
    }
8403
0
  } else {
8404
0
    if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
8405
0
      return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
8406
0
    if (!mz_zip_writer_create_local_dir_header(
8407
0
            pZip, local_dir_header, (mz_uint16)archive_name_size,
8408
0
            (mz_uint16)user_extra_data_len, 0, 0, 0, method, bit_flags,
8409
0
            dos_time, dos_date))
8410
0
      return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
8411
8412
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs,
8413
0
                       local_dir_header,
8414
0
                       sizeof(local_dir_header)) != sizeof(local_dir_header))
8415
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8416
8417
0
    cur_archive_file_ofs += sizeof(local_dir_header);
8418
8419
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
8420
0
                       archive_name_size) != archive_name_size) {
8421
0
      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
8422
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8423
0
    }
8424
0
    cur_archive_file_ofs += archive_name_size;
8425
0
  }
8426
8427
0
  if (user_extra_data_len > 0) {
8428
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs,
8429
0
                       user_extra_data,
8430
0
                       user_extra_data_len) != user_extra_data_len)
8431
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8432
8433
0
    cur_archive_file_ofs += user_extra_data_len;
8434
0
  }
8435
8436
0
  if (store_data_uncompressed) {
8437
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf,
8438
0
                       buf_size) != buf_size) {
8439
0
      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
8440
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8441
0
    }
8442
8443
0
    cur_archive_file_ofs += buf_size;
8444
0
    comp_size = buf_size;
8445
0
  } else if (buf_size) {
8446
0
    mz_zip_writer_add_state state;
8447
8448
0
    state.m_pZip = pZip;
8449
0
    state.m_cur_archive_file_ofs = cur_archive_file_ofs;
8450
0
    state.m_comp_size = 0;
8451
8452
0
    if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
8453
0
                    tdefl_create_comp_flags_from_zip_params(
8454
0
                        level, -15, MZ_DEFAULT_STRATEGY)) !=
8455
0
         TDEFL_STATUS_OKAY) ||
8456
0
        (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) !=
8457
0
         TDEFL_STATUS_DONE)) {
8458
0
      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
8459
0
      return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
8460
0
    }
8461
8462
0
    comp_size = state.m_comp_size;
8463
0
    cur_archive_file_ofs = state.m_cur_archive_file_ofs;
8464
0
  }
8465
8466
0
  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
8467
0
  pComp = NULL;
8468
8469
0
  if (uncomp_size) {
8470
0
    mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
8471
0
    mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
8472
8473
0
    MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR);
8474
8475
0
    MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
8476
0
    MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
8477
0
    if (pExtra_data == NULL) {
8478
0
      if (comp_size > MZ_UINT32_MAX)
8479
0
        return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
8480
8481
0
      MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
8482
0
      MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
8483
0
    } else {
8484
0
      MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
8485
0
      MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
8486
0
      local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
8487
0
    }
8488
8489
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs,
8490
0
                       local_dir_footer,
8491
0
                       local_dir_footer_size) != local_dir_footer_size)
8492
0
      return MZ_FALSE;
8493
8494
0
    cur_archive_file_ofs += local_dir_footer_size;
8495
0
  }
8496
8497
0
  if (pExtra_data != NULL) {
8498
0
    extra_size = mz_zip_writer_create_zip64_extra_data(
8499
0
        extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
8500
0
        (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL,
8501
0
        (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
8502
0
  }
8503
8504
0
  if (!mz_zip_writer_add_to_central_dir(
8505
0
          pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data,
8506
0
          (mz_uint16)extra_size, pComment, comment_size, uncomp_size, comp_size,
8507
0
          uncomp_crc32, method, bit_flags, dos_time, dos_date,
8508
0
          local_dir_header_ofs, ext_attributes, user_extra_data_central,
8509
0
          user_extra_data_central_len))
8510
0
    return MZ_FALSE;
8511
8512
0
  pZip->m_total_files++;
8513
0
  pZip->m_archive_size = cur_archive_file_ofs;
8514
8515
0
  return MZ_TRUE;
8516
0
}
8517
8518
mz_bool mz_zip_writer_add_read_buf_callback(
8519
    mz_zip_archive *pZip, const char *pArchive_name,
8520
    mz_file_read_func read_callback, void *callback_opaque, mz_uint64 max_size,
8521
    const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size,
8522
    mz_uint level_and_flags, mz_uint32 ext_attributes,
8523
    const char *user_extra_data, mz_uint user_extra_data_len,
8524
0
    const char *user_extra_data_central, mz_uint user_extra_data_central_len) {
8525
0
  mz_uint16 gen_flags = (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE)
8526
0
                            ? 0
8527
0
                            : MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
8528
0
  mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
8529
0
  mz_uint16 method = 0, dos_time = 0, dos_date = 0;
8530
0
  mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size,
8531
0
                                  uncomp_size = 0, comp_size = 0;
8532
0
  size_t archive_name_size;
8533
0
  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
8534
0
  mz_uint8 *pExtra_data = NULL;
8535
0
  mz_uint32 extra_size = 0;
8536
0
  mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
8537
0
  mz_zip_internal_state *pState;
8538
0
  mz_uint64 file_ofs = 0, cur_archive_header_file_ofs;
8539
8540
0
  if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
8541
0
    gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
8542
8543
0
  if ((int)level_and_flags < 0)
8544
0
    level_and_flags = MZ_DEFAULT_LEVEL;
8545
0
  level = level_and_flags & 0xF;
8546
8547
  /* Sanity checks */
8548
0
  if ((!pZip) || (!pZip->m_pState) ||
8549
0
      (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) ||
8550
0
      ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
8551
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
8552
8553
0
  pState = pZip->m_pState;
8554
8555
0
  if ((!pState->m_zip64) && (max_size > MZ_UINT32_MAX)) {
8556
    /* Source file is too large for non-zip64 */
8557
    /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
8558
0
    pState->m_zip64 = MZ_TRUE;
8559
0
  }
8560
8561
  /* We could support this, but why? */
8562
0
  if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
8563
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
8564
8565
0
  if (!mz_zip_writer_validate_archive_name(pArchive_name))
8566
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
8567
8568
0
  if (pState->m_zip64) {
8569
0
    if (pZip->m_total_files == MZ_UINT32_MAX)
8570
0
      return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
8571
0
  } else {
8572
0
    if (pZip->m_total_files == MZ_UINT16_MAX) {
8573
0
      pState->m_zip64 = MZ_TRUE;
8574
      /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
8575
0
    }
8576
0
  }
8577
8578
0
  archive_name_size = strlen(pArchive_name);
8579
0
  if (archive_name_size > MZ_UINT16_MAX)
8580
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
8581
8582
0
  num_alignment_padding_bytes =
8583
0
      mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
8584
8585
  /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
8586
0
  if (((mz_uint64)pState->m_central_dir.m_size +
8587
0
       MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size +
8588
0
       MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
8589
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
8590
8591
0
  if (!pState->m_zip64) {
8592
    /* Bail early if the archive would obviously become too large */
8593
0
    if ((pZip->m_archive_size + num_alignment_padding_bytes +
8594
0
         MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size +
8595
0
         MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size +
8596
0
         user_extra_data_len + pState->m_central_dir.m_size +
8597
0
         MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024 +
8598
0
         MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) >
8599
0
        0xFFFFFFFF) {
8600
0
      pState->m_zip64 = MZ_TRUE;
8601
      /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
8602
0
    }
8603
0
  }
8604
8605
0
#ifndef MINIZ_NO_TIME
8606
0
  if (pFile_time) {
8607
0
    mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);
8608
0
  }
8609
0
#endif
8610
8611
0
  if (max_size <= 3)
8612
0
    level = 0;
8613
8614
0
  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs,
8615
0
                                 num_alignment_padding_bytes)) {
8616
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8617
0
  }
8618
8619
0
  cur_archive_file_ofs += num_alignment_padding_bytes;
8620
0
  local_dir_header_ofs = cur_archive_file_ofs;
8621
8622
0
  if (pZip->m_file_offset_alignment) {
8623
0
    MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) ==
8624
0
              0);
8625
0
  }
8626
8627
0
  if (max_size && level) {
8628
0
    method = MZ_DEFLATED;
8629
0
  }
8630
8631
0
  MZ_CLEAR_OBJ(local_dir_header);
8632
0
  if (pState->m_zip64) {
8633
0
    if (max_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX) {
8634
0
      pExtra_data = extra_data;
8635
0
      if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE)
8636
0
        extra_size = mz_zip_writer_create_zip64_extra_data(
8637
0
            extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
8638
0
            (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL,
8639
0
            (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs
8640
0
                                                    : NULL);
8641
0
      else
8642
0
        extra_size = mz_zip_writer_create_zip64_extra_data(
8643
0
            extra_data, NULL, NULL,
8644
0
            (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs
8645
0
                                                    : NULL);
8646
0
    }
8647
8648
0
    if (!mz_zip_writer_create_local_dir_header(
8649
0
            pZip, local_dir_header, (mz_uint16)archive_name_size,
8650
0
            (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method,
8651
0
            gen_flags, dos_time, dos_date))
8652
0
      return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
8653
8654
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs,
8655
0
                       local_dir_header,
8656
0
                       sizeof(local_dir_header)) != sizeof(local_dir_header))
8657
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8658
8659
0
    cur_archive_file_ofs += sizeof(local_dir_header);
8660
8661
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
8662
0
                       archive_name_size) != archive_name_size) {
8663
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8664
0
    }
8665
8666
0
    cur_archive_file_ofs += archive_name_size;
8667
8668
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data,
8669
0
                       extra_size) != extra_size)
8670
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8671
8672
0
    cur_archive_file_ofs += extra_size;
8673
0
  } else {
8674
0
    if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
8675
0
      return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
8676
0
    if (!mz_zip_writer_create_local_dir_header(
8677
0
            pZip, local_dir_header, (mz_uint16)archive_name_size,
8678
0
            (mz_uint16)user_extra_data_len, 0, 0, 0, method, gen_flags,
8679
0
            dos_time, dos_date))
8680
0
      return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
8681
8682
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs,
8683
0
                       local_dir_header,
8684
0
                       sizeof(local_dir_header)) != sizeof(local_dir_header))
8685
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8686
8687
0
    cur_archive_file_ofs += sizeof(local_dir_header);
8688
8689
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name,
8690
0
                       archive_name_size) != archive_name_size) {
8691
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8692
0
    }
8693
8694
0
    cur_archive_file_ofs += archive_name_size;
8695
0
  }
8696
8697
0
  if (user_extra_data_len > 0) {
8698
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs,
8699
0
                       user_extra_data,
8700
0
                       user_extra_data_len) != user_extra_data_len)
8701
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8702
8703
0
    cur_archive_file_ofs += user_extra_data_len;
8704
0
  }
8705
8706
0
  if (max_size) {
8707
0
    void *pRead_buf =
8708
0
        pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
8709
0
    if (!pRead_buf) {
8710
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
8711
0
    }
8712
8713
0
    if (!level) {
8714
0
      while (1) {
8715
0
        size_t n = read_callback(callback_opaque, file_ofs, pRead_buf,
8716
0
                                 MZ_ZIP_MAX_IO_BUF_SIZE);
8717
0
        if (n == 0)
8718
0
          break;
8719
8720
0
        if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size)) {
8721
0
          pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
8722
0
          return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
8723
0
        }
8724
0
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf,
8725
0
                           n) != n) {
8726
0
          pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
8727
0
          return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8728
0
        }
8729
0
        file_ofs += n;
8730
0
        uncomp_crc32 =
8731
0
            (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
8732
0
        cur_archive_file_ofs += n;
8733
0
      }
8734
0
      uncomp_size = file_ofs;
8735
0
      comp_size = uncomp_size;
8736
0
    } else {
8737
0
      mz_bool result = MZ_FALSE;
8738
0
      mz_zip_writer_add_state state;
8739
0
      tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(
8740
0
          pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
8741
0
      if (!pComp) {
8742
0
        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
8743
0
        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
8744
0
      }
8745
8746
0
      state.m_pZip = pZip;
8747
0
      state.m_cur_archive_file_ofs = cur_archive_file_ofs;
8748
0
      state.m_comp_size = 0;
8749
8750
0
      if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state,
8751
0
                     tdefl_create_comp_flags_from_zip_params(
8752
0
                         level, -15, MZ_DEFAULT_STRATEGY)) !=
8753
0
          TDEFL_STATUS_OKAY) {
8754
0
        pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
8755
0
        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
8756
0
        return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
8757
0
      }
8758
8759
0
      for (;;) {
8760
0
        tdefl_status status;
8761
0
        tdefl_flush flush = TDEFL_NO_FLUSH;
8762
8763
0
        size_t n = read_callback(callback_opaque, file_ofs, pRead_buf,
8764
0
                                 MZ_ZIP_MAX_IO_BUF_SIZE);
8765
0
        if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size)) {
8766
0
          mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
8767
0
          break;
8768
0
        }
8769
8770
0
        file_ofs += n;
8771
0
        uncomp_crc32 =
8772
0
            (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
8773
8774
0
        if (pZip->m_pNeeds_keepalive != NULL &&
8775
0
            pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
8776
0
          flush = TDEFL_FULL_FLUSH;
8777
8778
0
        if (n == 0)
8779
0
          flush = TDEFL_FINISH;
8780
8781
0
        status = tdefl_compress_buffer(pComp, pRead_buf, n, flush);
8782
0
        if (status == TDEFL_STATUS_DONE) {
8783
0
          result = MZ_TRUE;
8784
0
          break;
8785
0
        } else if (status != TDEFL_STATUS_OKAY) {
8786
0
          mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
8787
0
          break;
8788
0
        }
8789
0
      }
8790
8791
0
      pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
8792
8793
0
      if (!result) {
8794
0
        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
8795
0
        return MZ_FALSE;
8796
0
      }
8797
8798
0
      uncomp_size = file_ofs;
8799
0
      comp_size = state.m_comp_size;
8800
0
      cur_archive_file_ofs = state.m_cur_archive_file_ofs;
8801
0
    }
8802
8803
0
    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
8804
0
  }
8805
8806
0
  if (!(level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE)) {
8807
0
    mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
8808
0
    mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
8809
8810
0
    MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
8811
0
    MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
8812
0
    if (pExtra_data == NULL) {
8813
0
      if (comp_size > MZ_UINT32_MAX)
8814
0
        return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
8815
8816
0
      MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
8817
0
      MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
8818
0
    } else {
8819
0
      MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
8820
0
      MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
8821
0
      local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
8822
0
    }
8823
8824
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs,
8825
0
                       local_dir_footer,
8826
0
                       local_dir_footer_size) != local_dir_footer_size)
8827
0
      return MZ_FALSE;
8828
8829
0
    cur_archive_file_ofs += local_dir_footer_size;
8830
0
  }
8831
8832
0
  if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE) {
8833
0
    if (pExtra_data != NULL) {
8834
0
      extra_size = mz_zip_writer_create_zip64_extra_data(
8835
0
          extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
8836
0
          (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL,
8837
0
          (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs
8838
0
                                                  : NULL);
8839
0
    }
8840
8841
0
    if (!mz_zip_writer_create_local_dir_header(
8842
0
            pZip, local_dir_header, (mz_uint16)archive_name_size,
8843
0
            (mz_uint16)(extra_size + user_extra_data_len),
8844
0
            (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : uncomp_size,
8845
0
            (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : comp_size,
8846
0
            uncomp_crc32, method, gen_flags, dos_time, dos_date))
8847
0
      return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
8848
8849
0
    cur_archive_header_file_ofs = local_dir_header_ofs;
8850
8851
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs,
8852
0
                       local_dir_header,
8853
0
                       sizeof(local_dir_header)) != sizeof(local_dir_header))
8854
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8855
8856
0
    if (pExtra_data != NULL) {
8857
0
      cur_archive_header_file_ofs += sizeof(local_dir_header);
8858
8859
0
      if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs,
8860
0
                         pArchive_name,
8861
0
                         archive_name_size) != archive_name_size) {
8862
0
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8863
0
      }
8864
8865
0
      cur_archive_header_file_ofs += archive_name_size;
8866
8867
0
      if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs,
8868
0
                         extra_data, extra_size) != extra_size)
8869
0
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
8870
8871
0
      cur_archive_header_file_ofs += extra_size;
8872
0
    }
8873
0
  }
8874
8875
0
  if (pExtra_data != NULL) {
8876
0
    extra_size = mz_zip_writer_create_zip64_extra_data(
8877
0
        extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
8878
0
        (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL,
8879
0
        (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
8880
0
  }
8881
8882
0
  if (!mz_zip_writer_add_to_central_dir(
8883
0
          pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data,
8884
0
          (mz_uint16)extra_size, pComment, comment_size, uncomp_size, comp_size,
8885
0
          uncomp_crc32, method, gen_flags, dos_time, dos_date,
8886
0
          local_dir_header_ofs, ext_attributes, user_extra_data_central,
8887
0
          user_extra_data_central_len))
8888
0
    return MZ_FALSE;
8889
8890
0
  pZip->m_total_files++;
8891
0
  pZip->m_archive_size = cur_archive_file_ofs;
8892
8893
0
  return MZ_TRUE;
8894
0
}
8895
8896
#ifndef MINIZ_NO_STDIO
8897
8898
static size_t mz_file_read_func_stdio(void *pOpaque, mz_uint64 file_ofs,
8899
0
                                      void *pBuf, size_t n) {
8900
0
  MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque;
8901
0
  mz_int64 cur_ofs = MZ_FTELL64(pSrc_file);
8902
8903
0
  if (((mz_int64)file_ofs < 0) ||
8904
0
      (((cur_ofs != (mz_int64)file_ofs)) &&
8905
0
       (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET))))
8906
0
    return 0;
8907
8908
0
  return MZ_FREAD(pBuf, 1, n, pSrc_file);
8909
0
}
8910
8911
mz_bool mz_zip_writer_add_cfile(
8912
    mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file,
8913
    mz_uint64 max_size, const MZ_TIME_T *pFile_time, const void *pComment,
8914
    mz_uint16 comment_size, mz_uint level_and_flags, mz_uint32 ext_attributes,
8915
    const char *user_extra_data, mz_uint user_extra_data_len,
8916
0
    const char *user_extra_data_central, mz_uint user_extra_data_central_len) {
8917
0
  return mz_zip_writer_add_read_buf_callback(
8918
0
      pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, max_size,
8919
0
      pFile_time, pComment, comment_size, level_and_flags, ext_attributes,
8920
0
      user_extra_data, user_extra_data_len, user_extra_data_central,
8921
0
      user_extra_data_central_len);
8922
0
}
8923
8924
mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name,
8925
                               const char *pSrc_filename, const void *pComment,
8926
                               mz_uint16 comment_size, mz_uint level_and_flags,
8927
0
                               mz_uint32 ext_attributes) {
8928
0
  MZ_FILE *pSrc_file = NULL;
8929
0
  mz_uint64 uncomp_size = 0;
8930
0
  MZ_TIME_T file_modified_time;
8931
0
  MZ_TIME_T *pFile_time = NULL;
8932
0
  mz_bool status;
8933
8934
0
  memset(&file_modified_time, 0, sizeof(file_modified_time));
8935
8936
0
#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
8937
0
  pFile_time = &file_modified_time;
8938
0
  if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
8939
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED);
8940
0
#endif
8941
8942
0
  pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
8943
0
  if (!pSrc_file)
8944
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
8945
8946
0
  MZ_FSEEK64(pSrc_file, 0, SEEK_END);
8947
0
  uncomp_size = MZ_FTELL64(pSrc_file);
8948
0
  MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
8949
8950
0
  status = mz_zip_writer_add_cfile(
8951
0
      pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment,
8952
0
      comment_size, level_and_flags, ext_attributes, NULL, 0, NULL, 0);
8953
8954
0
  MZ_FCLOSE(pSrc_file);
8955
8956
0
  return status;
8957
0
}
8958
#endif /* #ifndef MINIZ_NO_STDIO */
8959
8960
static mz_bool mz_zip_writer_update_zip64_extension_block(
8961
    mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt,
8962
    uint32_t ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size,
8963
0
    mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start) {
8964
  /* + 64 should be enough for any new zip64 data */
8965
0
  if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))
8966
0
    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
8967
8968
0
  mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);
8969
8970
0
  if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start)) {
8971
0
    mz_uint8 new_ext_block[64];
8972
0
    mz_uint8 *pDst = new_ext_block;
8973
0
    mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
8974
0
    mz_write_le16(pDst + sizeof(mz_uint16), 0);
8975
0
    pDst += sizeof(mz_uint16) * 2;
8976
8977
0
    if (pUncomp_size) {
8978
0
      mz_write_le64(pDst, *pUncomp_size);
8979
0
      pDst += sizeof(mz_uint64);
8980
0
    }
8981
8982
0
    if (pComp_size) {
8983
0
      mz_write_le64(pDst, *pComp_size);
8984
0
      pDst += sizeof(mz_uint64);
8985
0
    }
8986
8987
0
    if (pLocal_header_ofs) {
8988
0
      mz_write_le64(pDst, *pLocal_header_ofs);
8989
0
      pDst += sizeof(mz_uint64);
8990
0
    }
8991
8992
0
    if (pDisk_start) {
8993
0
      mz_write_le32(pDst, *pDisk_start);
8994
0
      pDst += sizeof(mz_uint32);
8995
0
    }
8996
8997
0
    mz_write_le16(new_ext_block + sizeof(mz_uint16),
8998
0
                  (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2));
8999
9000
0
    if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block,
9001
0
                                pDst - new_ext_block))
9002
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
9003
0
  }
9004
9005
0
  if ((pExt) && (ext_len)) {
9006
0
    mz_uint32 extra_size_remaining = ext_len;
9007
0
    const mz_uint8 *pExtra_data = pExt;
9008
9009
0
    do {
9010
0
      mz_uint32 field_id, field_data_size, field_total_size;
9011
9012
0
      if (extra_size_remaining < (sizeof(mz_uint16) * 2))
9013
0
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
9014
9015
0
      field_id = MZ_READ_LE16(pExtra_data);
9016
0
      field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
9017
0
      field_total_size = field_data_size + sizeof(mz_uint16) * 2;
9018
9019
0
      if (field_total_size > extra_size_remaining)
9020
0
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
9021
9022
0
      if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) {
9023
0
        if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data,
9024
0
                                    field_total_size))
9025
0
          return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
9026
0
      }
9027
9028
0
      pExtra_data += field_total_size;
9029
0
      extra_size_remaining -= field_total_size;
9030
0
    } while (extra_size_remaining);
9031
0
  }
9032
9033
0
  return MZ_TRUE;
9034
0
}
9035
9036
/* TODO: This func is now pretty freakin complex due to zip64, split it up? */
9037
mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip,
9038
                                          mz_zip_archive *pSource_zip,
9039
0
                                          mz_uint src_file_index) {
9040
0
  mz_uint n, bit_flags, num_alignment_padding_bytes,
9041
0
      src_central_dir_following_data_size;
9042
0
  mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;
9043
0
  mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
9044
0
  mz_uint32
9045
0
      local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) /
9046
0
                       sizeof(mz_uint32)];
9047
0
  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
9048
0
  mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
9049
0
  size_t orig_central_dir_size;
9050
0
  mz_zip_internal_state *pState;
9051
0
  void *pBuf;
9052
0
  const mz_uint8 *pSrc_central_header;
9053
0
  mz_zip_archive_file_stat src_file_stat;
9054
0
  mz_uint32 src_filename_len, src_comment_len, src_ext_len;
9055
0
  mz_uint32 local_header_filename_size, local_header_extra_len;
9056
0
  mz_uint64 local_header_comp_size, local_header_uncomp_size;
9057
0
  mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
9058
9059
  /* Sanity checks */
9060
0
  if ((!pZip) || (!pZip->m_pState) ||
9061
0
      (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))
9062
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
9063
9064
0
  pState = pZip->m_pState;
9065
9066
  /* Don't support copying files from zip64 archives to non-zip64, even though
9067
   * in some cases this is possible */
9068
0
  if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))
9069
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
9070
9071
  /* Get pointer to the source central dir header and crack it */
9072
0
  if (NULL ==
9073
0
      (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
9074
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
9075
9076
0
  if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) !=
9077
0
      MZ_ZIP_CENTRAL_DIR_HEADER_SIG)
9078
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
9079
9080
0
  src_filename_len =
9081
0
      MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);
9082
0
  src_comment_len =
9083
0
      MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
9084
0
  src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);
9085
0
  src_central_dir_following_data_size =
9086
0
      src_filename_len + src_ext_len + src_comment_len;
9087
9088
  /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right now (+32
9089
   * fudge factor in case we need to add more extra data) */
9090
0
  if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
9091
0
       src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)
9092
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
9093
9094
0
  num_alignment_padding_bytes =
9095
0
      mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
9096
9097
0
  if (!pState->m_zip64) {
9098
0
    if (pZip->m_total_files == MZ_UINT16_MAX)
9099
0
      return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
9100
0
  } else {
9101
    /* TODO: Our zip64 support still has some 32-bit limits that may not be
9102
     * worth fixing. */
9103
0
    if (pZip->m_total_files == MZ_UINT32_MAX)
9104
0
      return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
9105
0
  }
9106
9107
0
  if (!mz_zip_file_stat_internal(pSource_zip, src_file_index,
9108
0
                                 pSrc_central_header, &src_file_stat, NULL))
9109
0
    return MZ_FALSE;
9110
9111
0
  cur_src_file_ofs = src_file_stat.m_local_header_ofs;
9112
0
  cur_dst_file_ofs = pZip->m_archive_size;
9113
9114
  /* Read the source archive's local dir header */
9115
0
  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs,
9116
0
                           pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
9117
0
      MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
9118
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
9119
9120
0
  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
9121
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
9122
9123
0
  cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
9124
9125
  /* Compute the total size we need to copy (filename+extra data+compressed
9126
   * data) */
9127
0
  local_header_filename_size =
9128
0
      MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
9129
0
  local_header_extra_len =
9130
0
      MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
9131
0
  local_header_comp_size =
9132
0
      MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
9133
0
  local_header_uncomp_size =
9134
0
      MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
9135
0
  src_archive_bytes_remaining = local_header_filename_size +
9136
0
                                local_header_extra_len +
9137
0
                                src_file_stat.m_comp_size;
9138
9139
  /* Try to find a zip64 extended information field */
9140
0
  if ((local_header_extra_len) &&
9141
0
      ((local_header_comp_size == MZ_UINT32_MAX) ||
9142
0
       (local_header_uncomp_size == MZ_UINT32_MAX))) {
9143
0
    mz_zip_array file_data_array;
9144
0
    const mz_uint8 *pExtra_data;
9145
0
    mz_uint32 extra_size_remaining = local_header_extra_len;
9146
9147
0
    mz_zip_array_init(&file_data_array, 1);
9148
0
    if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len,
9149
0
                             MZ_FALSE)) {
9150
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
9151
0
    }
9152
9153
0
    if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque,
9154
0
                             src_file_stat.m_local_header_ofs +
9155
0
                                 MZ_ZIP_LOCAL_DIR_HEADER_SIZE +
9156
0
                                 local_header_filename_size,
9157
0
                             file_data_array.m_p, local_header_extra_len) !=
9158
0
        local_header_extra_len) {
9159
0
      mz_zip_array_clear(pZip, &file_data_array);
9160
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
9161
0
    }
9162
9163
0
    pExtra_data = (const mz_uint8 *)file_data_array.m_p;
9164
9165
0
    do {
9166
0
      mz_uint32 field_id, field_data_size, field_total_size;
9167
9168
0
      if (extra_size_remaining < (sizeof(mz_uint16) * 2)) {
9169
0
        mz_zip_array_clear(pZip, &file_data_array);
9170
0
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
9171
0
      }
9172
9173
0
      field_id = MZ_READ_LE16(pExtra_data);
9174
0
      field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
9175
0
      field_total_size = field_data_size + sizeof(mz_uint16) * 2;
9176
9177
0
      if (field_total_size > extra_size_remaining) {
9178
0
        mz_zip_array_clear(pZip, &file_data_array);
9179
0
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
9180
0
      }
9181
9182
0
      if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) {
9183
0
        const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
9184
9185
0
        if (field_data_size < sizeof(mz_uint64) * 2) {
9186
0
          mz_zip_array_clear(pZip, &file_data_array);
9187
0
          return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
9188
0
        }
9189
9190
0
        local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
9191
0
        local_header_comp_size = MZ_READ_LE64(
9192
0
            pSrc_field_data +
9193
0
            sizeof(mz_uint64)); /* may be 0 if there's a descriptor */
9194
9195
0
        found_zip64_ext_data_in_ldir = MZ_TRUE;
9196
0
        break;
9197
0
      }
9198
9199
0
      pExtra_data += field_total_size;
9200
0
      extra_size_remaining -= field_total_size;
9201
0
    } while (extra_size_remaining);
9202
9203
0
    mz_zip_array_clear(pZip, &file_data_array);
9204
0
  }
9205
9206
0
  if (!pState->m_zip64) {
9207
    /* Try to detect if the new archive will most likely wind up too big and
9208
     * bail early (+(sizeof(mz_uint32) * 4) is for the optional descriptor which
9209
     * could be present, +64 is a fudge factor). */
9210
    /* We also check when the archive is finalized so this doesn't need to be
9211
     * perfect. */
9212
0
    mz_uint64 approx_new_archive_size =
9213
0
        cur_dst_file_ofs + num_alignment_padding_bytes +
9214
0
        MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining +
9215
0
        (sizeof(mz_uint32) * 4) + pState->m_central_dir.m_size +
9216
0
        MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size +
9217
0
        MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64;
9218
9219
0
    if (approx_new_archive_size >= MZ_UINT32_MAX)
9220
0
      return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
9221
0
  }
9222
9223
  /* Write dest archive padding */
9224
0
  if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs,
9225
0
                                 num_alignment_padding_bytes))
9226
0
    return MZ_FALSE;
9227
9228
0
  cur_dst_file_ofs += num_alignment_padding_bytes;
9229
9230
0
  local_dir_header_ofs = cur_dst_file_ofs;
9231
0
  if (pZip->m_file_offset_alignment) {
9232
0
    MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) ==
9233
0
              0);
9234
0
  }
9235
9236
  /* The original zip's local header+ext block doesn't change, even with zip64,
9237
   * so we can just copy it over to the dest zip */
9238
0
  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header,
9239
0
                     MZ_ZIP_LOCAL_DIR_HEADER_SIZE) !=
9240
0
      MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
9241
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
9242
9243
0
  cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
9244
9245
  /* Copy over the source archive bytes to the dest archive, also ensure we have
9246
   * enough buf space to handle optional data descriptor */
9247
0
  if (NULL == (pBuf = pZip->m_pAlloc(
9248
0
                   pZip->m_pAlloc_opaque, 1,
9249
0
                   (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE,
9250
0
                                              src_archive_bytes_remaining)))))
9251
0
    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
9252
9253
0
  while (src_archive_bytes_remaining) {
9254
0
    n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE,
9255
0
                        src_archive_bytes_remaining);
9256
0
    if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf,
9257
0
                             n) != n) {
9258
0
      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
9259
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
9260
0
    }
9261
0
    cur_src_file_ofs += n;
9262
9263
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
9264
0
      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
9265
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
9266
0
    }
9267
0
    cur_dst_file_ofs += n;
9268
9269
0
    src_archive_bytes_remaining -= n;
9270
0
  }
9271
9272
  /* Now deal with the optional data descriptor */
9273
0
  bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
9274
0
  if (bit_flags & 8) {
9275
    /* Copy data descriptor */
9276
0
    if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir)) {
9277
      /* src is zip64, dest must be zip64 */
9278
9279
      /* name     uint32_t's */
9280
      /* id       1 (optional in zip64?) */
9281
      /* crc      1 */
9282
      /* comp_size  2 */
9283
      /* uncomp_size 2 */
9284
0
      if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs,
9285
0
                               pBuf, (sizeof(mz_uint32) * 6)) !=
9286
0
          (sizeof(mz_uint32) * 6)) {
9287
0
        pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
9288
0
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
9289
0
      }
9290
9291
0
      n = sizeof(mz_uint32) *
9292
0
          ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);
9293
0
    } else {
9294
      /* src is NOT zip64 */
9295
0
      mz_bool has_id;
9296
9297
0
      if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs,
9298
0
                               pBuf, sizeof(mz_uint32) * 4) !=
9299
0
          sizeof(mz_uint32) * 4) {
9300
0
        pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
9301
0
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
9302
0
      }
9303
9304
0
      has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
9305
9306
0
      if (pZip->m_pState->m_zip64) {
9307
        /* dest is zip64, so upgrade the data descriptor */
9308
0
        const mz_uint32 *pSrc_descriptor =
9309
0
            (const mz_uint32 *)((const mz_uint8 *)pBuf +
9310
0
                                (has_id ? sizeof(mz_uint32) : 0));
9311
0
        const mz_uint32 src_crc32 = pSrc_descriptor[0];
9312
0
        const mz_uint64 src_comp_size = pSrc_descriptor[1];
9313
0
        const mz_uint64 src_uncomp_size = pSrc_descriptor[2];
9314
9315
0
        mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID);
9316
0
        mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32);
9317
0
        mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size);
9318
0
        mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4,
9319
0
                      src_uncomp_size);
9320
9321
0
        n = sizeof(mz_uint32) * 6;
9322
0
      } else {
9323
        /* dest is NOT zip64, just copy it as-is */
9324
0
        n = sizeof(mz_uint32) * (has_id ? 4 : 3);
9325
0
      }
9326
0
    }
9327
9328
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) {
9329
0
      pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
9330
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
9331
0
    }
9332
9333
0
    cur_src_file_ofs += n;
9334
0
    cur_dst_file_ofs += n;
9335
0
  }
9336
0
  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
9337
9338
  /* Finally, add the new central dir header */
9339
0
  orig_central_dir_size = pState->m_central_dir.m_size;
9340
9341
0
  memcpy(new_central_header, pSrc_central_header,
9342
0
         MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
9343
9344
0
  if (pState->m_zip64) {
9345
    /* This is the painful part: We need to write a new central dir header + ext
9346
     * block with updated zip64 fields, and ensure the old fields (if any) are
9347
     * not included. */
9348
0
    const mz_uint8 *pSrc_ext =
9349
0
        pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;
9350
0
    mz_zip_array new_ext_block;
9351
9352
0
    mz_zip_array_init(&new_ext_block, sizeof(mz_uint8));
9353
9354
0
    MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS,
9355
0
                  MZ_UINT32_MAX);
9356
0
    MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS,
9357
0
                  MZ_UINT32_MAX);
9358
0
    MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS,
9359
0
                  MZ_UINT32_MAX);
9360
9361
0
    if (!mz_zip_writer_update_zip64_extension_block(
9362
0
            &new_ext_block, pZip, pSrc_ext, src_ext_len,
9363
0
            &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size,
9364
0
            &local_dir_header_ofs, NULL)) {
9365
0
      mz_zip_array_clear(pZip, &new_ext_block);
9366
0
      return MZ_FALSE;
9367
0
    }
9368
9369
0
    MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS,
9370
0
                  new_ext_block.m_size);
9371
9372
0
    if (!mz_zip_array_push_back(pZip, &pState->m_central_dir,
9373
0
                                new_central_header,
9374
0
                                MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) {
9375
0
      mz_zip_array_clear(pZip, &new_ext_block);
9376
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
9377
0
    }
9378
9379
0
    if (!mz_zip_array_push_back(pZip, &pState->m_central_dir,
9380
0
                                pSrc_central_header +
9381
0
                                    MZ_ZIP_CENTRAL_DIR_HEADER_SIZE,
9382
0
                                src_filename_len)) {
9383
0
      mz_zip_array_clear(pZip, &new_ext_block);
9384
0
      mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
9385
0
                          MZ_FALSE);
9386
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
9387
0
    }
9388
9389
0
    if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p,
9390
0
                                new_ext_block.m_size)) {
9391
0
      mz_zip_array_clear(pZip, &new_ext_block);
9392
0
      mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
9393
0
                          MZ_FALSE);
9394
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
9395
0
    }
9396
9397
0
    if (!mz_zip_array_push_back(pZip, &pState->m_central_dir,
9398
0
                                pSrc_central_header +
9399
0
                                    MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
9400
0
                                    src_filename_len + src_ext_len,
9401
0
                                src_comment_len)) {
9402
0
      mz_zip_array_clear(pZip, &new_ext_block);
9403
0
      mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
9404
0
                          MZ_FALSE);
9405
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
9406
0
    }
9407
9408
0
    mz_zip_array_clear(pZip, &new_ext_block);
9409
0
  } else {
9410
    /* sanity checks */
9411
0
    if (cur_dst_file_ofs > MZ_UINT32_MAX)
9412
0
      return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
9413
9414
0
    if (local_dir_header_ofs >= MZ_UINT32_MAX)
9415
0
      return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
9416
9417
0
    MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS,
9418
0
                  local_dir_header_ofs);
9419
9420
0
    if (!mz_zip_array_push_back(pZip, &pState->m_central_dir,
9421
0
                                new_central_header,
9422
0
                                MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
9423
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
9424
9425
0
    if (!mz_zip_array_push_back(pZip, &pState->m_central_dir,
9426
0
                                pSrc_central_header +
9427
0
                                    MZ_ZIP_CENTRAL_DIR_HEADER_SIZE,
9428
0
                                src_central_dir_following_data_size)) {
9429
0
      mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
9430
0
                          MZ_FALSE);
9431
0
      return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
9432
0
    }
9433
0
  }
9434
9435
  /* This shouldn't trigger unless we screwed up during the initial sanity
9436
   * checks */
9437
0
  if (pState->m_central_dir.m_size >= MZ_UINT32_MAX) {
9438
    /* TODO: Support central dirs >= 32-bits in size */
9439
0
    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
9440
0
                        MZ_FALSE);
9441
0
    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
9442
0
  }
9443
9444
0
  n = (mz_uint32)orig_central_dir_size;
9445
0
  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) {
9446
0
    mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size,
9447
0
                        MZ_FALSE);
9448
0
    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
9449
0
  }
9450
9451
0
  pZip->m_total_files++;
9452
0
  pZip->m_archive_size = cur_dst_file_ofs;
9453
9454
0
  return MZ_TRUE;
9455
0
}
9456
9457
0
mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) {
9458
0
  mz_zip_internal_state *pState;
9459
0
  mz_uint64 central_dir_ofs, central_dir_size;
9460
0
  mz_uint8 hdr[256];
9461
9462
0
  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
9463
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
9464
9465
0
  pState = pZip->m_pState;
9466
9467
0
  if (pState->m_zip64) {
9468
0
    if ((pZip->m_total_files > MZ_UINT32_MAX) ||
9469
0
        (pState->m_central_dir.m_size >= MZ_UINT32_MAX))
9470
0
      return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
9471
0
  } else {
9472
0
    if ((pZip->m_total_files > MZ_UINT16_MAX) ||
9473
0
        ((pZip->m_archive_size + pState->m_central_dir.m_size +
9474
0
          MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX))
9475
0
      return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
9476
0
  }
9477
9478
0
  central_dir_ofs = 0;
9479
0
  central_dir_size = 0;
9480
0
  if (pZip->m_total_files) {
9481
    /* Write central directory */
9482
0
    central_dir_ofs = pZip->m_archive_size;
9483
0
    central_dir_size = pState->m_central_dir.m_size;
9484
0
    pZip->m_central_directory_file_ofs = central_dir_ofs;
9485
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs,
9486
0
                       pState->m_central_dir.m_p,
9487
0
                       (size_t)central_dir_size) != central_dir_size)
9488
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
9489
9490
0
    pZip->m_archive_size += central_dir_size;
9491
0
  }
9492
9493
0
  if (pState->m_zip64) {
9494
    /* Write zip64 end of central directory header */
9495
0
    mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size;
9496
9497
0
    MZ_CLEAR_OBJ(hdr);
9498
0
    MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS,
9499
0
                  MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG);
9500
0
    MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS,
9501
0
                  MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - sizeof(mz_uint32) -
9502
0
                      sizeof(mz_uint64));
9503
0
    MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS,
9504
0
                  0x031E); /* TODO: always Unix */
9505
0
    MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D);
9506
0
    MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS,
9507
0
                  pZip->m_total_files);
9508
0
    MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS,
9509
0
                  pZip->m_total_files);
9510
0
    MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size);
9511
0
    MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs);
9512
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr,
9513
0
                       MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) !=
9514
0
        MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
9515
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
9516
9517
0
    pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE;
9518
9519
    /* Write zip64 end of central directory locator */
9520
0
    MZ_CLEAR_OBJ(hdr);
9521
0
    MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS,
9522
0
                  MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG);
9523
0
    MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS,
9524
0
                  rel_ofs_to_zip64_ecdr);
9525
0
    MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1);
9526
0
    if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr,
9527
0
                       MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) !=
9528
0
        MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
9529
0
      return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
9530
9531
0
    pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE;
9532
0
  }
9533
9534
  /* Write end of central directory record */
9535
0
  MZ_CLEAR_OBJ(hdr);
9536
0
  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS,
9537
0
                MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
9538
0
  MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS,
9539
0
                MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
9540
0
  MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS,
9541
0
                MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
9542
0
  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS,
9543
0
                MZ_MIN(MZ_UINT32_MAX, central_dir_size));
9544
0
  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS,
9545
0
                MZ_MIN(MZ_UINT32_MAX, central_dir_ofs));
9546
9547
0
  if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr,
9548
0
                     MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) !=
9549
0
      MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
9550
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
9551
9552
0
#ifndef MINIZ_NO_STDIO
9553
0
  if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
9554
0
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
9555
0
#endif /* #ifndef MINIZ_NO_STDIO */
9556
9557
0
  pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE;
9558
9559
0
  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
9560
0
  return MZ_TRUE;
9561
0
}
9562
9563
mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf,
9564
0
                                            size_t *pSize) {
9565
0
  if ((!ppBuf) || (!pSize))
9566
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
9567
9568
0
  *ppBuf = NULL;
9569
0
  *pSize = 0;
9570
9571
0
  if ((!pZip) || (!pZip->m_pState))
9572
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
9573
9574
0
  if (pZip->m_pWrite != mz_zip_heap_write_func)
9575
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
9576
9577
0
  if (!mz_zip_writer_finalize_archive(pZip))
9578
0
    return MZ_FALSE;
9579
9580
0
  *ppBuf = pZip->m_pState->m_pMem;
9581
0
  *pSize = pZip->m_pState->m_mem_size;
9582
0
  pZip->m_pState->m_pMem = NULL;
9583
0
  pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
9584
9585
0
  return MZ_TRUE;
9586
0
}
9587
9588
0
mz_bool mz_zip_writer_end(mz_zip_archive *pZip) {
9589
0
  return mz_zip_writer_end_internal(pZip, MZ_TRUE);
9590
0
}
9591
9592
#ifndef MINIZ_NO_STDIO
9593
mz_bool mz_zip_add_mem_to_archive_file_in_place(
9594
    const char *pZip_filename, const char *pArchive_name, const void *pBuf,
9595
    size_t buf_size, const void *pComment, mz_uint16 comment_size,
9596
0
    mz_uint level_and_flags) {
9597
0
  return mz_zip_add_mem_to_archive_file_in_place_v2(
9598
0
      pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size,
9599
0
      level_and_flags, NULL);
9600
0
}
9601
9602
mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(
9603
    const char *pZip_filename, const char *pArchive_name, const void *pBuf,
9604
    size_t buf_size, const void *pComment, mz_uint16 comment_size,
9605
0
    mz_uint level_and_flags, mz_zip_error *pErr) {
9606
0
  mz_bool status, created_new_archive = MZ_FALSE;
9607
0
  mz_zip_archive zip_archive;
9608
0
  struct MZ_FILE_STAT_STRUCT file_stat;
9609
0
  mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
9610
9611
0
  mz_zip_zero_struct(&zip_archive);
9612
0
  if ((int)level_and_flags < 0)
9613
0
    level_and_flags = MZ_DEFAULT_LEVEL;
9614
9615
0
  if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) ||
9616
0
      ((comment_size) && (!pComment)) ||
9617
0
      ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) {
9618
0
    if (pErr)
9619
0
      *pErr = MZ_ZIP_INVALID_PARAMETER;
9620
0
    return MZ_FALSE;
9621
0
  }
9622
9623
0
  if (!mz_zip_writer_validate_archive_name(pArchive_name)) {
9624
0
    if (pErr)
9625
0
      *pErr = MZ_ZIP_INVALID_FILENAME;
9626
0
    return MZ_FALSE;
9627
0
  }
9628
9629
  /* Important: The regular non-64 bit version of stat() can fail here if the
9630
   * file is very large, which could cause the archive to be overwritten. */
9631
  /* So be sure to compile with _LARGEFILE64_SOURCE 1 */
9632
0
  if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) {
9633
    /* Create a new archive. */
9634
0
    if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0,
9635
0
                                    level_and_flags)) {
9636
0
      if (pErr)
9637
0
        *pErr = zip_archive.m_last_error;
9638
0
      return MZ_FALSE;
9639
0
    }
9640
9641
0
    created_new_archive = MZ_TRUE;
9642
0
  } else {
9643
    /* Append to an existing archive. */
9644
0
    if (!mz_zip_reader_init_file_v2(
9645
0
            &zip_archive, pZip_filename,
9646
0
            level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0,
9647
0
            0)) {
9648
0
      if (pErr)
9649
0
        *pErr = zip_archive.m_last_error;
9650
0
      return MZ_FALSE;
9651
0
    }
9652
9653
0
    if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename,
9654
0
                                           level_and_flags)) {
9655
0
      if (pErr)
9656
0
        *pErr = zip_archive.m_last_error;
9657
9658
0
      mz_zip_reader_end_internal(&zip_archive, MZ_FALSE);
9659
9660
0
      return MZ_FALSE;
9661
0
    }
9662
0
  }
9663
9664
0
  status =
9665
0
      mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size,
9666
0
                               pComment, comment_size, level_and_flags, 0, 0);
9667
0
  actual_err = zip_archive.m_last_error;
9668
9669
  /* Always finalize, even if adding failed for some reason, so we have a valid
9670
   * central directory. (This may not always succeed, but we can try.) */
9671
0
  if (!mz_zip_writer_finalize_archive(&zip_archive)) {
9672
0
    if (!actual_err)
9673
0
      actual_err = zip_archive.m_last_error;
9674
9675
0
    status = MZ_FALSE;
9676
0
  }
9677
9678
0
  if (!mz_zip_writer_end_internal(&zip_archive, status)) {
9679
0
    if (!actual_err)
9680
0
      actual_err = zip_archive.m_last_error;
9681
9682
0
    status = MZ_FALSE;
9683
0
  }
9684
9685
0
  if ((!status) && (created_new_archive)) {
9686
    /* It's a new archive and something went wrong, so just delete it. */
9687
0
    int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
9688
0
    (void)ignoredStatus;
9689
0
  }
9690
9691
0
  if (pErr)
9692
0
    *pErr = actual_err;
9693
9694
0
  return status;
9695
0
}
9696
9697
void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename,
9698
                                             const char *pArchive_name,
9699
                                             const char *pComment,
9700
                                             size_t *pSize, mz_uint flags,
9701
0
                                             mz_zip_error *pErr) {
9702
0
  mz_uint32 file_index;
9703
0
  mz_zip_archive zip_archive;
9704
0
  void *p = NULL;
9705
9706
0
  if (pSize)
9707
0
    *pSize = 0;
9708
9709
0
  if ((!pZip_filename) || (!pArchive_name)) {
9710
0
    if (pErr)
9711
0
      *pErr = MZ_ZIP_INVALID_PARAMETER;
9712
9713
0
    return NULL;
9714
0
  }
9715
9716
0
  mz_zip_zero_struct(&zip_archive);
9717
0
  if (!mz_zip_reader_init_file_v2(
9718
0
          &zip_archive, pZip_filename,
9719
0
          flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0)) {
9720
0
    if (pErr)
9721
0
      *pErr = zip_archive.m_last_error;
9722
9723
0
    return NULL;
9724
0
  }
9725
9726
0
  if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags,
9727
0
                                   &file_index)) {
9728
0
    p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
9729
0
  }
9730
9731
0
  mz_zip_reader_end_internal(&zip_archive, p != NULL);
9732
9733
0
  if (pErr)
9734
0
    *pErr = zip_archive.m_last_error;
9735
9736
0
  return p;
9737
0
}
9738
9739
void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
9740
                                          const char *pArchive_name,
9741
0
                                          size_t *pSize, mz_uint flags) {
9742
0
  return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name,
9743
0
                                                NULL, pSize, flags, NULL);
9744
0
}
9745
9746
#endif /* #ifndef MINIZ_NO_STDIO */
9747
9748
#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */
9749
9750
/* ------------------- Misc utils */
9751
9752
0
mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip) {
9753
0
  return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
9754
0
}
9755
9756
0
mz_zip_type mz_zip_get_type(mz_zip_archive *pZip) {
9757
0
  return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
9758
0
}
9759
9760
0
mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num) {
9761
0
  mz_zip_error prev_err;
9762
9763
0
  if (!pZip)
9764
0
    return MZ_ZIP_INVALID_PARAMETER;
9765
9766
0
  prev_err = pZip->m_last_error;
9767
9768
0
  pZip->m_last_error = err_num;
9769
0
  return prev_err;
9770
0
}
9771
9772
0
mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip) {
9773
0
  if (!pZip)
9774
0
    return MZ_ZIP_INVALID_PARAMETER;
9775
9776
0
  return pZip->m_last_error;
9777
0
}
9778
9779
0
mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip) {
9780
0
  return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR);
9781
0
}
9782
9783
0
mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip) {
9784
0
  mz_zip_error prev_err;
9785
9786
0
  if (!pZip)
9787
0
    return MZ_ZIP_INVALID_PARAMETER;
9788
9789
0
  prev_err = pZip->m_last_error;
9790
9791
0
  pZip->m_last_error = MZ_ZIP_NO_ERROR;
9792
0
  return prev_err;
9793
0
}
9794
9795
0
const char *mz_zip_get_error_string(mz_zip_error mz_err) {
9796
0
  switch (mz_err) {
9797
0
  case MZ_ZIP_NO_ERROR:
9798
0
    return "no error";
9799
0
  case MZ_ZIP_UNDEFINED_ERROR:
9800
0
    return "undefined error";
9801
0
  case MZ_ZIP_TOO_MANY_FILES:
9802
0
    return "too many files";
9803
0
  case MZ_ZIP_FILE_TOO_LARGE:
9804
0
    return "file too large";
9805
0
  case MZ_ZIP_UNSUPPORTED_METHOD:
9806
0
    return "unsupported method";
9807
0
  case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
9808
0
    return "unsupported encryption";
9809
0
  case MZ_ZIP_UNSUPPORTED_FEATURE:
9810
0
    return "unsupported feature";
9811
0
  case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
9812
0
    return "failed finding central directory";
9813
0
  case MZ_ZIP_NOT_AN_ARCHIVE:
9814
0
    return "not a ZIP archive";
9815
0
  case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
9816
0
    return "invalid header or archive is corrupted";
9817
0
  case MZ_ZIP_UNSUPPORTED_MULTIDISK:
9818
0
    return "unsupported multidisk archive";
9819
0
  case MZ_ZIP_DECOMPRESSION_FAILED:
9820
0
    return "decompression failed or archive is corrupted";
9821
0
  case MZ_ZIP_COMPRESSION_FAILED:
9822
0
    return "compression failed";
9823
0
  case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
9824
0
    return "unexpected decompressed size";
9825
0
  case MZ_ZIP_CRC_CHECK_FAILED:
9826
0
    return "CRC-32 check failed";
9827
0
  case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
9828
0
    return "unsupported central directory size";
9829
0
  case MZ_ZIP_ALLOC_FAILED:
9830
0
    return "allocation failed";
9831
0
  case MZ_ZIP_FILE_OPEN_FAILED:
9832
0
    return "file open failed";
9833
0
  case MZ_ZIP_FILE_CREATE_FAILED:
9834
0
    return "file create failed";
9835
0
  case MZ_ZIP_FILE_WRITE_FAILED:
9836
0
    return "file write failed";
9837
0
  case MZ_ZIP_FILE_READ_FAILED:
9838
0
    return "file read failed";
9839
0
  case MZ_ZIP_FILE_CLOSE_FAILED:
9840
0
    return "file close failed";
9841
0
  case MZ_ZIP_FILE_SEEK_FAILED:
9842
0
    return "file seek failed";
9843
0
  case MZ_ZIP_FILE_STAT_FAILED:
9844
0
    return "file stat failed";
9845
0
  case MZ_ZIP_INVALID_PARAMETER:
9846
0
    return "invalid parameter";
9847
0
  case MZ_ZIP_INVALID_FILENAME:
9848
0
    return "invalid filename";
9849
0
  case MZ_ZIP_BUF_TOO_SMALL:
9850
0
    return "buffer too small";
9851
0
  case MZ_ZIP_INTERNAL_ERROR:
9852
0
    return "internal error";
9853
0
  case MZ_ZIP_FILE_NOT_FOUND:
9854
0
    return "file not found";
9855
0
  case MZ_ZIP_ARCHIVE_TOO_LARGE:
9856
0
    return "archive is too large";
9857
0
  case MZ_ZIP_VALIDATION_FAILED:
9858
0
    return "validation failed";
9859
0
  case MZ_ZIP_WRITE_CALLBACK_FAILED:
9860
0
    return "write calledback failed";
9861
0
  default:
9862
0
    break;
9863
0
  }
9864
9865
0
  return "unknown error";
9866
0
}
9867
9868
/* Note: Just because the archive is not zip64 doesn't necessarily mean it
9869
 * doesn't have Zip64 extended information extra field, argh. */
9870
0
mz_bool mz_zip_is_zip64(mz_zip_archive *pZip) {
9871
0
  if ((!pZip) || (!pZip->m_pState))
9872
0
    return MZ_FALSE;
9873
9874
0
  return pZip->m_pState->m_zip64;
9875
0
}
9876
9877
0
size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip) {
9878
0
  if ((!pZip) || (!pZip->m_pState))
9879
0
    return 0;
9880
9881
0
  return pZip->m_pState->m_central_dir.m_size;
9882
0
}
9883
9884
0
mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) {
9885
0
  return pZip ? pZip->m_total_files : 0;
9886
0
}
9887
9888
0
mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip) {
9889
0
  if (!pZip)
9890
0
    return 0;
9891
0
  return pZip->m_archive_size;
9892
0
}
9893
9894
0
mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip) {
9895
0
  if ((!pZip) || (!pZip->m_pState))
9896
0
    return 0;
9897
0
  return pZip->m_pState->m_file_archive_start_ofs;
9898
0
}
9899
9900
0
MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip) {
9901
0
  if ((!pZip) || (!pZip->m_pState))
9902
0
    return 0;
9903
0
  return pZip->m_pState->m_pFile;
9904
0
}
9905
9906
size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs,
9907
0
                                void *pBuf, size_t n) {
9908
0
  if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
9909
0
    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
9910
9911
0
  return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
9912
0
}
9913
9914
mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index,
9915
0
                                   char *pFilename, mz_uint filename_buf_size) {
9916
0
  mz_uint n;
9917
0
  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
9918
0
  if (!p) {
9919
0
    if (filename_buf_size)
9920
0
      pFilename[0] = '\0';
9921
0
    mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
9922
0
    return 0;
9923
0
  }
9924
0
  n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
9925
0
  if (filename_buf_size) {
9926
0
    n = MZ_MIN(n, filename_buf_size - 1);
9927
0
    memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
9928
0
    pFilename[n] = '\0';
9929
0
  }
9930
0
  return n + 1;
9931
0
}
9932
9933
mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
9934
0
                                mz_zip_archive_file_stat *pStat) {
9935
0
  return mz_zip_file_stat_internal(
9936
0
      pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
9937
0
}
9938
9939
0
mz_bool mz_zip_end(mz_zip_archive *pZip) {
9940
0
  if (!pZip)
9941
0
    return MZ_FALSE;
9942
9943
0
  if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
9944
0
    return mz_zip_reader_end(pZip);
9945
0
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
9946
0
  else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) ||
9947
0
           (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))
9948
0
    return mz_zip_writer_end(pZip);
9949
0
#endif
9950
9951
0
  return MZ_FALSE;
9952
0
}
9953
9954
#ifdef __cplusplus
9955
}
9956
#endif
9957
9958
#endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/
9959
#endif // MINIZ_HEADER_FILE_ONLY