Coverage Report

Created: 2025-11-11 06:58

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