All Classes Namespaces Functions Variables Enumerations Properties Pages
miniz.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26 
27 #include "miniz.h"
28 
29 typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
30 typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
31 typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 /* ------------------- zlib-style API's */
38 
39 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
40 {
41  mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
42  size_t block_len = buf_len % 5552;
43  if (!ptr)
44  return MZ_ADLER32_INIT;
45  while (buf_len)
46  {
47  for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
48  {
49  s1 += ptr[0], s2 += s1;
50  s1 += ptr[1], s2 += s1;
51  s1 += ptr[2], s2 += s1;
52  s1 += ptr[3], s2 += s1;
53  s1 += ptr[4], s2 += s1;
54  s1 += ptr[5], s2 += s1;
55  s1 += ptr[6], s2 += s1;
56  s1 += ptr[7], s2 += s1;
57  }
58  for (; i < block_len; ++i)
59  s1 += *ptr++, s2 += s1;
60  s1 %= 65521U, s2 %= 65521U;
61  buf_len -= block_len;
62  block_len = 5552;
63  }
64  return (s2 << 16) + s1;
65 }
66 
67 /* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ */
68 #if 0
69  mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
70  {
71  static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
72  0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
73  mz_uint32 crcu32 = (mz_uint32)crc;
74  if (!ptr)
75  return MZ_CRC32_INIT;
76  crcu32 = ~crcu32;
77  while (buf_len--)
78  {
79  mz_uint8 b = *ptr++;
80  crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
81  crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
82  }
83  return ~crcu32;
84  }
85 #else
86 /* Faster, but larger CPU cache footprint.
87  */
88 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
89 {
90  static const mz_uint32 s_crc_table[256] =
91  {
92  0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
93  0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
94  0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
95  0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
96  0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
97  0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
98  0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
99  0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
100  0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
101  0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
102  0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
103  0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
104  0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
105  0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
106  0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
107  0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
108  0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
109  0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
110  0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
111  0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
112  0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
113  0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
114  0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
115  0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
116  0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
117  0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
118  0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
119  0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
120  0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
121  0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
122  0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
123  0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
124  0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
125  0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
126  0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
127  0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
128  0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
129  };
130 
131  mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
132  const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
133 
134  while (buf_len >= 4)
135  {
136  crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
137  crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
138  crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
139  crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
140  pByte_buf += 4;
141  buf_len -= 4;
142  }
143 
144  while (buf_len)
145  {
146  crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
147  ++pByte_buf;
148  --buf_len;
149  }
150 
151  return ~crc32;
152 }
153 #endif
154 
155 void mz_free(void *p)
156 {
157  MZ_FREE(p);
158 }
159 
160 void *miniz_def_alloc_func(void *opaque, size_t items, size_t size)
161 {
162  (void)opaque, (void)items, (void)size;
163  return MZ_MALLOC(items * size);
164 }
165 void miniz_def_free_func(void *opaque, void *address)
166 {
167  (void)opaque, (void)address;
168  MZ_FREE(address);
169 }
170 void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
171 {
172  (void)opaque, (void)address, (void)items, (void)size;
173  return MZ_REALLOC(address, items * size);
174 }
175 
176 const char *mz_version(void)
177 {
178  return MZ_VERSION;
179 }
180 
181 #ifndef MINIZ_NO_ZLIB_APIS
182 
183 int mz_deflateInit(mz_streamp pStream, int level)
184 {
185  return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
186 }
187 
188 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
189 {
190  tdefl_compressor *pComp;
191  mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
192 
193  if (!pStream)
194  return MZ_STREAM_ERROR;
195  if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
196  return MZ_PARAM_ERROR;
197 
198  pStream->data_type = 0;
199  pStream->adler = MZ_ADLER32_INIT;
200  pStream->msg = NULL;
201  pStream->reserved = 0;
202  pStream->total_in = 0;
203  pStream->total_out = 0;
204  if (!pStream->zalloc)
205  pStream->zalloc = miniz_def_alloc_func;
206  if (!pStream->zfree)
207  pStream->zfree = miniz_def_free_func;
208 
209  pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
210  if (!pComp)
211  return MZ_MEM_ERROR;
212 
213  pStream->state = (struct mz_internal_state *)pComp;
214 
215  if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
216  {
217  mz_deflateEnd(pStream);
218  return MZ_PARAM_ERROR;
219  }
220 
221  return MZ_OK;
222 }
223 
224 int mz_deflateReset(mz_streamp pStream)
225 {
226  if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
227  return MZ_STREAM_ERROR;
228  pStream->total_in = pStream->total_out = 0;
229  tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);
230  return MZ_OK;
231 }
232 
233 int mz_deflate(mz_streamp pStream, int flush)
234 {
235  size_t in_bytes, out_bytes;
236  mz_ulong orig_total_in, orig_total_out;
237  int mz_status = MZ_OK;
238 
239  if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
240  return MZ_STREAM_ERROR;
241  if (!pStream->avail_out)
242  return MZ_BUF_ERROR;
243 
244  if (flush == MZ_PARTIAL_FLUSH)
245  flush = MZ_SYNC_FLUSH;
246 
247  if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
248  return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
249 
250  orig_total_in = pStream->total_in;
251  orig_total_out = pStream->total_out;
252  for (;;)
253  {
254  tdefl_status defl_status;
255  in_bytes = pStream->avail_in;
256  out_bytes = pStream->avail_out;
257 
258  defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
259  pStream->next_in += (mz_uint)in_bytes;
260  pStream->avail_in -= (mz_uint)in_bytes;
261  pStream->total_in += (mz_uint)in_bytes;
262  pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
263 
264  pStream->next_out += (mz_uint)out_bytes;
265  pStream->avail_out -= (mz_uint)out_bytes;
266  pStream->total_out += (mz_uint)out_bytes;
267 
268  if (defl_status < 0)
269  {
270  mz_status = MZ_STREAM_ERROR;
271  break;
272  }
273  else if (defl_status == TDEFL_STATUS_DONE)
274  {
275  mz_status = MZ_STREAM_END;
276  break;
277  }
278  else if (!pStream->avail_out)
279  break;
280  else if ((!pStream->avail_in) && (flush != MZ_FINISH))
281  {
282  if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
283  break;
284  return MZ_BUF_ERROR; /* Can't make forward progress without some input.
285  */
286  }
287  }
288  return mz_status;
289 }
290 
291 int mz_deflateEnd(mz_streamp pStream)
292 {
293  if (!pStream)
294  return MZ_STREAM_ERROR;
295  if (pStream->state)
296  {
297  pStream->zfree(pStream->opaque, pStream->state);
298  pStream->state = NULL;
299  }
300  return MZ_OK;
301 }
302 
303 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
304 {
305  (void)pStream;
306  /* This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) */
307  return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
308 }
309 
310 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
311 {
312  int status;
313  mz_stream stream;
314  memset(&stream, 0, sizeof(stream));
315 
316  /* In case mz_ulong is 64-bits (argh I hate longs). */
317  if ((source_len | *pDest_len) > 0xFFFFFFFFU)
318  return MZ_PARAM_ERROR;
319 
320  stream.next_in = pSource;
321  stream.avail_in = (mz_uint32)source_len;
322  stream.next_out = pDest;
323  stream.avail_out = (mz_uint32)*pDest_len;
324 
325  status = mz_deflateInit(&stream, level);
326  if (status != MZ_OK)
327  return status;
328 
329  status = mz_deflate(&stream, MZ_FINISH);
330  if (status != MZ_STREAM_END)
331  {
332  mz_deflateEnd(&stream);
333  return (status == MZ_OK) ? MZ_BUF_ERROR : status;
334  }
335 
336  *pDest_len = stream.total_out;
337  return mz_deflateEnd(&stream);
338 }
339 
340 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
341 {
342  return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
343 }
344 
345 mz_ulong mz_compressBound(mz_ulong source_len)
346 {
347  return mz_deflateBound(NULL, source_len);
348 }
349 
350 typedef struct
351 {
352  tinfl_decompressor m_decomp;
353  mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
354  int m_window_bits;
355  mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
356  tinfl_status m_last_status;
357 } inflate_state;
358 
359 int mz_inflateInit2(mz_streamp pStream, int window_bits)
360 {
361  inflate_state *pDecomp;
362  if (!pStream)
363  return MZ_STREAM_ERROR;
364  if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))
365  return MZ_PARAM_ERROR;
366 
367  pStream->data_type = 0;
368  pStream->adler = 0;
369  pStream->msg = NULL;
370  pStream->total_in = 0;
371  pStream->total_out = 0;
372  pStream->reserved = 0;
373  if (!pStream->zalloc)
374  pStream->zalloc = miniz_def_alloc_func;
375  if (!pStream->zfree)
376  pStream->zfree = miniz_def_free_func;
377 
378  pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
379  if (!pDecomp)
380  return MZ_MEM_ERROR;
381 
382  pStream->state = (struct mz_internal_state *)pDecomp;
383 
384  tinfl_init(&pDecomp->m_decomp);
385  pDecomp->m_dict_ofs = 0;
386  pDecomp->m_dict_avail = 0;
387  pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
388  pDecomp->m_first_call = 1;
389  pDecomp->m_has_flushed = 0;
390  pDecomp->m_window_bits = window_bits;
391 
392  return MZ_OK;
393 }
394 
395 int mz_inflateInit(mz_streamp pStream)
396 {
397  return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
398 }
399 
400 int mz_inflateReset(mz_streamp pStream)
401 {
402  inflate_state *pDecomp;
403  if (!pStream)
404  return MZ_STREAM_ERROR;
405 
406  pStream->data_type = 0;
407  pStream->adler = 0;
408  pStream->msg = NULL;
409  pStream->total_in = 0;
410  pStream->total_out = 0;
411  pStream->reserved = 0;
412 
413  pDecomp = (inflate_state *)pStream->state;
414 
415  tinfl_init(&pDecomp->m_decomp);
416  pDecomp->m_dict_ofs = 0;
417  pDecomp->m_dict_avail = 0;
418  pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
419  pDecomp->m_first_call = 1;
420  pDecomp->m_has_flushed = 0;
421  /* pDecomp->m_window_bits = window_bits */;
422 
423  return MZ_OK;
424 }
425 
426 int mz_inflate(mz_streamp pStream, int flush)
427 {
428  inflate_state *pState;
429  mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
430  size_t in_bytes, out_bytes, orig_avail_in;
431  tinfl_status status;
432 
433  if ((!pStream) || (!pStream->state))
434  return MZ_STREAM_ERROR;
435  if (flush == MZ_PARTIAL_FLUSH)
436  flush = MZ_SYNC_FLUSH;
437  if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
438  return MZ_STREAM_ERROR;
439 
440  pState = (inflate_state *)pStream->state;
441  if (pState->m_window_bits > 0)
442  decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
443  orig_avail_in = pStream->avail_in;
444 
445  first_call = pState->m_first_call;
446  pState->m_first_call = 0;
447  if (pState->m_last_status < 0)
448  return MZ_DATA_ERROR;
449 
450  if (pState->m_has_flushed && (flush != MZ_FINISH))
451  return MZ_STREAM_ERROR;
452  pState->m_has_flushed |= (flush == MZ_FINISH);
453 
454  if ((flush == MZ_FINISH) && (first_call))
455  {
456  /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */
457  decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
458  in_bytes = pStream->avail_in;
459  out_bytes = pStream->avail_out;
460  status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
461  pState->m_last_status = status;
462  pStream->next_in += (mz_uint)in_bytes;
463  pStream->avail_in -= (mz_uint)in_bytes;
464  pStream->total_in += (mz_uint)in_bytes;
465  pStream->adler = tinfl_get_adler32(&pState->m_decomp);
466  pStream->next_out += (mz_uint)out_bytes;
467  pStream->avail_out -= (mz_uint)out_bytes;
468  pStream->total_out += (mz_uint)out_bytes;
469 
470  if (status < 0)
471  return MZ_DATA_ERROR;
472  else if (status != TINFL_STATUS_DONE)
473  {
474  pState->m_last_status = TINFL_STATUS_FAILED;
475  return MZ_BUF_ERROR;
476  }
477  return MZ_STREAM_END;
478  }
479  /* flush != MZ_FINISH then we must assume there's more input. */
480  if (flush != MZ_FINISH)
481  decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
482 
483  if (pState->m_dict_avail)
484  {
485  n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
486  memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
487  pStream->next_out += n;
488  pStream->avail_out -= n;
489  pStream->total_out += n;
490  pState->m_dict_avail -= n;
491  pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
492  return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
493  }
494 
495  for (;;)
496  {
497  in_bytes = pStream->avail_in;
498  out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
499 
500  status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
501  pState->m_last_status = status;
502 
503  pStream->next_in += (mz_uint)in_bytes;
504  pStream->avail_in -= (mz_uint)in_bytes;
505  pStream->total_in += (mz_uint)in_bytes;
506  pStream->adler = tinfl_get_adler32(&pState->m_decomp);
507 
508  pState->m_dict_avail = (mz_uint)out_bytes;
509 
510  n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
511  memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
512  pStream->next_out += n;
513  pStream->avail_out -= n;
514  pStream->total_out += n;
515  pState->m_dict_avail -= n;
516  pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
517 
518  if (status < 0)
519  return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */
520  else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
521  return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */
522  else if (flush == MZ_FINISH)
523  {
524  /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */
525  if (status == TINFL_STATUS_DONE)
526  return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
527  /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */
528  else if (!pStream->avail_out)
529  return MZ_BUF_ERROR;
530  }
531  else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
532  break;
533  }
534 
535  return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
536 }
537 
538 int mz_inflateEnd(mz_streamp pStream)
539 {
540  if (!pStream)
541  return MZ_STREAM_ERROR;
542  if (pStream->state)
543  {
544  pStream->zfree(pStream->opaque, pStream->state);
545  pStream->state = NULL;
546  }
547  return MZ_OK;
548 }
549 
550 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
551 {
552  mz_stream stream;
553  int status;
554  memset(&stream, 0, sizeof(stream));
555 
556  /* In case mz_ulong is 64-bits (argh I hate longs). */
557  if ((source_len | *pDest_len) > 0xFFFFFFFFU)
558  return MZ_PARAM_ERROR;
559 
560  stream.next_in = pSource;
561  stream.avail_in = (mz_uint32)source_len;
562  stream.next_out = pDest;
563  stream.avail_out = (mz_uint32)*pDest_len;
564 
565  status = mz_inflateInit(&stream);
566  if (status != MZ_OK)
567  return status;
568 
569  status = mz_inflate(&stream, MZ_FINISH);
570  if (status != MZ_STREAM_END)
571  {
572  mz_inflateEnd(&stream);
573  return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
574  }
575  *pDest_len = stream.total_out;
576 
577  return mz_inflateEnd(&stream);
578 }
579 
580 const char *mz_error(int err)
581 {
582  static struct
583  {
584  int m_err;
585  const char *m_pDesc;
586  } s_error_descs[] =
587  {
588  { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
589  };
590  mz_uint i;
591  for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
592  if (s_error_descs[i].m_err == err)
593  return s_error_descs[i].m_pDesc;
594  return NULL;
595 }
596 
597 #endif /*MINIZ_NO_ZLIB_APIS */
598 
599 #ifdef __cplusplus
600 }
601 #endif
602 
603 /*
604  This is free and unencumbered software released into the public domain.
605 
606  Anyone is free to copy, modify, publish, use, compile, sell, or
607  distribute this software, either in source code form or as a compiled
608  binary, for any purpose, commercial or non-commercial, and by any
609  means.
610 
611  In jurisdictions that recognize copyright laws, the author or authors
612  of this software dedicate any and all copyright interest in the
613  software to the public domain. We make this dedication for the benefit
614  of the public at large and to the detriment of our heirs and
615  successors. We intend this dedication to be an overt act of
616  relinquishment in perpetuity of all present and future rights to this
617  software under copyright law.
618 
619  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
620  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
621  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
622  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
623  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
624  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
625  OTHER DEALINGS IN THE SOFTWARE.
626 
627  For more information, please refer to <http://unlicense.org/>
628 */
629 /**************************************************************************
630  *
631  * Copyright 2013-2014 RAD Game Tools and Valve Software
632  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
633  * All Rights Reserved.
634  *
635  * Permission is hereby granted, free of charge, to any person obtaining a copy
636  * of this software and associated documentation files (the "Software"), to deal
637  * in the Software without restriction, including without limitation the rights
638  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
639  * copies of the Software, and to permit persons to whom the Software is
640  * furnished to do so, subject to the following conditions:
641  *
642  * The above copyright notice and this permission notice shall be included in
643  * all copies or substantial portions of the Software.
644  *
645  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
646  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
647  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
648  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
649  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
650  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
651  * THE SOFTWARE.
652  *
653  **************************************************************************/
654 
655 
656 
657 
658 #ifdef __cplusplus
659 extern "C" {
660 #endif
661 
662 /* ------------------- Low-level Compression (independent from all decompression API's) */
663 
664 /* Purposely making these tables static for faster init and thread safety. */
665 static const mz_uint16 s_tdefl_len_sym[256] =
666  {
667  257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272,
668  273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276,
669  277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
670  279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
671  281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
672  282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
673  283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
674  284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285
675  };
676 
677 static const mz_uint8 s_tdefl_len_extra[256] =
678  {
679  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
680  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
681  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, 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, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
682  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, 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, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0
683  };
684 
685 static const mz_uint8 s_tdefl_small_dist_sym[512] =
686  {
687  0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11,
688  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13,
689  13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
690  14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
691  14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
692  15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
693  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
694  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
695  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
696  17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
697  17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
698  17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17
699  };
700 
701 static const mz_uint8 s_tdefl_small_dist_extra[512] =
702  {
703  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, 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, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
704  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, 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, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
705  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, 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, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
706  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, 6, 6, 6, 6, 6, 6, 6, 6, 6, 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, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
707  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, 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, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
708  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, 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, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
709  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, 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, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
710  7, 7, 7, 7, 7, 7, 7, 7
711  };
712 
713 static const mz_uint8 s_tdefl_large_dist_sym[128] =
714  {
715  0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
716  26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
717  28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
718  };
719 
720 static const mz_uint8 s_tdefl_large_dist_extra[128] =
721  {
722  0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
723  12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
724  13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13
725  };
726 
727 /* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */
728 typedef struct
729 {
730  mz_uint16 m_key, m_sym_index;
732 static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1)
733 {
734  mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
735  tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
736  MZ_CLEAR_OBJ(hist);
737  for (i = 0; i < num_syms; i++)
738  {
739  mz_uint freq = pSyms0[i].m_key;
740  hist[freq & 0xFF]++;
741  hist[256 + ((freq >> 8) & 0xFF)]++;
742  }
743  while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
744  total_passes--;
745  for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
746  {
747  const mz_uint32 *pHist = &hist[pass << 8];
748  mz_uint offsets[256], cur_ofs = 0;
749  for (i = 0; i < 256; i++)
750  {
751  offsets[i] = cur_ofs;
752  cur_ofs += pHist[i];
753  }
754  for (i = 0; i < num_syms; i++)
755  pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
756  {
757  tdefl_sym_freq *t = pCur_syms;
758  pCur_syms = pNew_syms;
759  pNew_syms = t;
760  }
761  }
762  return pCur_syms;
763 }
764 
765 /* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */
766 static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
767 {
768  int root, leaf, next, avbl, used, dpth;
769  if (n == 0)
770  return;
771  else if (n == 1)
772  {
773  A[0].m_key = 1;
774  return;
775  }
776  A[0].m_key += A[1].m_key;
777  root = 0;
778  leaf = 2;
779  for (next = 1; next < n - 1; next++)
780  {
781  if (leaf >= n || A[root].m_key < A[leaf].m_key)
782  {
783  A[next].m_key = A[root].m_key;
784  A[root++].m_key = (mz_uint16)next;
785  }
786  else
787  A[next].m_key = A[leaf++].m_key;
788  if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key))
789  {
790  A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
791  A[root++].m_key = (mz_uint16)next;
792  }
793  else
794  A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
795  }
796  A[n - 2].m_key = 0;
797  for (next = n - 3; next >= 0; next--)
798  A[next].m_key = A[A[next].m_key].m_key + 1;
799  avbl = 1;
800  used = dpth = 0;
801  root = n - 2;
802  next = n - 1;
803  while (avbl > 0)
804  {
805  while (root >= 0 && (int)A[root].m_key == dpth)
806  {
807  used++;
808  root--;
809  }
810  while (avbl > used)
811  {
812  A[next--].m_key = (mz_uint16)(dpth);
813  avbl--;
814  }
815  avbl = 2 * used;
816  dpth++;
817  used = 0;
818  }
819 }
820 
821 /* Limits canonical Huffman code table's max code size. */
822 enum
823 {
824  TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32
825 };
826 static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
827 {
828  int i;
829  mz_uint32 total = 0;
830  if (code_list_len <= 1)
831  return;
832  for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
833  pNum_codes[max_code_size] += pNum_codes[i];
834  for (i = max_code_size; i > 0; i--)
835  total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
836  while (total != (1UL << max_code_size))
837  {
838  pNum_codes[max_code_size]--;
839  for (i = max_code_size - 1; i > 0; i--)
840  if (pNum_codes[i])
841  {
842  pNum_codes[i]--;
843  pNum_codes[i + 1] += 2;
844  break;
845  }
846  total--;
847  }
848 }
849 
850 static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
851 {
852  int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
853  mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
854  MZ_CLEAR_OBJ(num_codes);
855  if (static_table)
856  {
857  for (i = 0; i < table_len; i++)
858  num_codes[d->m_huff_code_sizes[table_num][i]]++;
859  }
860  else
861  {
862  tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
863  int num_used_syms = 0;
864  const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
865  for (i = 0; i < table_len; i++)
866  if (pSym_count[i])
867  {
868  syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
869  syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
870  }
871 
872  pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
873  tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
874 
875  for (i = 0; i < num_used_syms; i++)
876  num_codes[pSyms[i].m_key]++;
877 
878  tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
879 
880  MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
881  MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
882  for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
883  for (l = num_codes[i]; l > 0; l--)
884  d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
885  }
886 
887  next_code[1] = 0;
888  for (j = 0, i = 2; i <= code_size_limit; i++)
889  next_code[i] = j = ((j + num_codes[i - 1]) << 1);
890 
891  for (i = 0; i < table_len; i++)
892  {
893  mz_uint rev_code = 0, code, code_size;
894  if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
895  continue;
896  code = next_code[code_size]++;
897  for (l = code_size; l > 0; l--, code >>= 1)
898  rev_code = (rev_code << 1) | (code & 1);
899  d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
900  }
901 }
902 
903 #define TDEFL_PUT_BITS(b, l) \
904  do \
905  { \
906  mz_uint bits = b; \
907  mz_uint len = l; \
908  MZ_ASSERT(bits <= ((1U << len) - 1U)); \
909  d->m_bit_buffer |= (bits << d->m_bits_in); \
910  d->m_bits_in += len; \
911  while (d->m_bits_in >= 8) \
912  { \
913  if (d->m_pOutput_buf < d->m_pOutput_buf_end) \
914  *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
915  d->m_bit_buffer >>= 8; \
916  d->m_bits_in -= 8; \
917  } \
918  } \
919  MZ_MACRO_END
920 
921 #define TDEFL_RLE_PREV_CODE_SIZE() \
922  { \
923  if (rle_repeat_count) \
924  { \
925  if (rle_repeat_count < 3) \
926  { \
927  d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
928  while (rle_repeat_count--) \
929  packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \
930  } \
931  else \
932  { \
933  d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); \
934  packed_code_sizes[num_packed_code_sizes++] = 16; \
935  packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \
936  } \
937  rle_repeat_count = 0; \
938  } \
939  }
940 
941 #define TDEFL_RLE_ZERO_CODE_SIZE() \
942  { \
943  if (rle_z_count) \
944  { \
945  if (rle_z_count < 3) \
946  { \
947  d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); \
948  while (rle_z_count--) \
949  packed_code_sizes[num_packed_code_sizes++] = 0; \
950  } \
951  else if (rle_z_count <= 10) \
952  { \
953  d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); \
954  packed_code_sizes[num_packed_code_sizes++] = 17; \
955  packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \
956  } \
957  else \
958  { \
959  d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); \
960  packed_code_sizes[num_packed_code_sizes++] = 18; \
961  packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
962  } \
963  rle_z_count = 0; \
964  } \
965  }
966 
967 static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
968 
969 static void tdefl_start_dynamic_block(tdefl_compressor *d)
970 {
971  int num_lit_codes, num_dist_codes, num_bit_lengths;
972  mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
973  mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;
974 
975  d->m_huff_count[0][256] = 1;
976 
977  tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
978  tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
979 
980  for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
981  if (d->m_huff_code_sizes[0][num_lit_codes - 1])
982  break;
983  for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
984  if (d->m_huff_code_sizes[1][num_dist_codes - 1])
985  break;
986 
987  memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
988  memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
989  total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
990  num_packed_code_sizes = 0;
991  rle_z_count = 0;
992  rle_repeat_count = 0;
993 
994  memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
995  for (i = 0; i < total_code_sizes_to_pack; i++)
996  {
997  mz_uint8 code_size = code_sizes_to_pack[i];
998  if (!code_size)
999  {
1000  TDEFL_RLE_PREV_CODE_SIZE();
1001  if (++rle_z_count == 138)
1002  {
1003  TDEFL_RLE_ZERO_CODE_SIZE();
1004  }
1005  }
1006  else
1007  {
1008  TDEFL_RLE_ZERO_CODE_SIZE();
1009  if (code_size != prev_code_size)
1010  {
1011  TDEFL_RLE_PREV_CODE_SIZE();
1012  d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1);
1013  packed_code_sizes[num_packed_code_sizes++] = code_size;
1014  }
1015  else if (++rle_repeat_count == 6)
1016  {
1017  TDEFL_RLE_PREV_CODE_SIZE();
1018  }
1019  }
1020  prev_code_size = code_size;
1021  }
1022  if (rle_repeat_count)
1023  {
1024  TDEFL_RLE_PREV_CODE_SIZE();
1025  }
1026  else
1027  {
1028  TDEFL_RLE_ZERO_CODE_SIZE();
1029  }
1030 
1031  tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
1032 
1033  TDEFL_PUT_BITS(2, 2);
1034 
1035  TDEFL_PUT_BITS(num_lit_codes - 257, 5);
1036  TDEFL_PUT_BITS(num_dist_codes - 1, 5);
1037 
1038  for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
1039  if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
1040  break;
1041  num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
1042  TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
1043  for (i = 0; (int)i < num_bit_lengths; i++)
1044  TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
1045 
1046  for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;)
1047  {
1048  mz_uint code = packed_code_sizes[packed_code_sizes_index++];
1049  MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
1050  TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
1051  if (code >= 16)
1052  TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
1053  }
1054 }
1055 
1056 static void tdefl_start_static_block(tdefl_compressor *d)
1057 {
1058  mz_uint i;
1059  mz_uint8 *p = &d->m_huff_code_sizes[0][0];
1060 
1061  for (i = 0; i <= 143; ++i)
1062  *p++ = 8;
1063  for (; i <= 255; ++i)
1064  *p++ = 9;
1065  for (; i <= 279; ++i)
1066  *p++ = 7;
1067  for (; i <= 287; ++i)
1068  *p++ = 8;
1069 
1070  memset(d->m_huff_code_sizes[1], 5, 32);
1071 
1072  tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
1073  tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
1074 
1075  TDEFL_PUT_BITS(1, 2);
1076 }
1077 
1078 static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
1079 
1080 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
1081 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
1082 {
1083  mz_uint flags;
1084  mz_uint8 *pLZ_codes;
1085  mz_uint8 *pOutput_buf = d->m_pOutput_buf;
1086  mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
1087  mz_uint64 bit_buffer = d->m_bit_buffer;
1088  mz_uint bits_in = d->m_bits_in;
1089 
1090 #define TDEFL_PUT_BITS_FAST(b, l) \
1091  { \
1092  bit_buffer |= (((mz_uint64)(b)) << bits_in); \
1093  bits_in += (l); \
1094  }
1095 
1096  flags = 1;
1097  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
1098  {
1099  if (flags == 1)
1100  flags = *pLZ_codes++ | 0x100;
1101 
1102  if (flags & 1)
1103  {
1104  mz_uint s0, s1, n0, n1, sym, num_extra_bits;
1105  mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
1106  pLZ_codes += 3;
1107 
1108  MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1109  TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1110  TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1111 
1112  /* This sequence coaxes MSVC into using cmov's vs. jmp's. */
1113  s0 = s_tdefl_small_dist_sym[match_dist & 511];
1114  n0 = s_tdefl_small_dist_extra[match_dist & 511];
1115  s1 = s_tdefl_large_dist_sym[match_dist >> 8];
1116  n1 = s_tdefl_large_dist_extra[match_dist >> 8];
1117  sym = (match_dist < 512) ? s0 : s1;
1118  num_extra_bits = (match_dist < 512) ? n0 : n1;
1119 
1120  MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1121  TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1122  TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1123  }
1124  else
1125  {
1126  mz_uint lit = *pLZ_codes++;
1127  MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1128  TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1129 
1130  if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1131  {
1132  flags >>= 1;
1133  lit = *pLZ_codes++;
1134  MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1135  TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1136 
1137  if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1138  {
1139  flags >>= 1;
1140  lit = *pLZ_codes++;
1141  MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1142  TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1143  }
1144  }
1145  }
1146 
1147  if (pOutput_buf >= d->m_pOutput_buf_end)
1148  return MZ_FALSE;
1149 
1150  *(mz_uint64 *)pOutput_buf = bit_buffer;
1151  pOutput_buf += (bits_in >> 3);
1152  bit_buffer >>= (bits_in & ~7);
1153  bits_in &= 7;
1154  }
1155 
1156 #undef TDEFL_PUT_BITS_FAST
1157 
1158  d->m_pOutput_buf = pOutput_buf;
1159  d->m_bits_in = 0;
1160  d->m_bit_buffer = 0;
1161 
1162  while (bits_in)
1163  {
1164  mz_uint32 n = MZ_MIN(bits_in, 16);
1165  TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
1166  bit_buffer >>= n;
1167  bits_in -= n;
1168  }
1169 
1170  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1171 
1172  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1173 }
1174 #else
1175 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
1176 {
1177  mz_uint flags;
1178  mz_uint8 *pLZ_codes;
1179 
1180  flags = 1;
1181  for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
1182  {
1183  if (flags == 1)
1184  flags = *pLZ_codes++ | 0x100;
1185  if (flags & 1)
1186  {
1187  mz_uint sym, num_extra_bits;
1188  mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
1189  pLZ_codes += 3;
1190 
1191  MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1192  TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1193  TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1194 
1195  if (match_dist < 512)
1196  {
1197  sym = s_tdefl_small_dist_sym[match_dist];
1198  num_extra_bits = s_tdefl_small_dist_extra[match_dist];
1199  }
1200  else
1201  {
1202  sym = s_tdefl_large_dist_sym[match_dist >> 8];
1203  num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
1204  }
1205  MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1206  TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1207  TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1208  }
1209  else
1210  {
1211  mz_uint lit = *pLZ_codes++;
1212  MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1213  TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1214  }
1215  }
1216 
1217  TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1218 
1219  return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1220 }
1221 #endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */
1222 
1223 static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
1224 {
1225  if (static_block)
1226  tdefl_start_static_block(d);
1227  else
1228  tdefl_start_dynamic_block(d);
1229  return tdefl_compress_lz_codes(d);
1230 }
1231 
1232 static int tdefl_flush_block(tdefl_compressor *d, int flush)
1233 {
1234  mz_uint saved_bit_buf, saved_bits_in;
1235  mz_uint8 *pSaved_output_buf;
1236  mz_bool comp_block_succeeded = MZ_FALSE;
1237  int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
1238  mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
1239 
1240  d->m_pOutput_buf = pOutput_buf_start;
1241  d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
1242 
1243  MZ_ASSERT(!d->m_output_flush_remaining);
1244  d->m_output_flush_ofs = 0;
1245  d->m_output_flush_remaining = 0;
1246 
1247  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
1248  d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
1249 
1250  if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
1251  {
1252  TDEFL_PUT_BITS(0x78, 8);
1253  TDEFL_PUT_BITS(0x01, 8);
1254  }
1255 
1256  TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
1257 
1258  pSaved_output_buf = d->m_pOutput_buf;
1259  saved_bit_buf = d->m_bit_buffer;
1260  saved_bits_in = d->m_bits_in;
1261 
1262  if (!use_raw_block)
1263  comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
1264 
1265  /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */
1266  if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
1267  ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size))
1268  {
1269  mz_uint i;
1270  d->m_pOutput_buf = pSaved_output_buf;
1271  d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1272  TDEFL_PUT_BITS(0, 2);
1273  if (d->m_bits_in)
1274  {
1275  TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1276  }
1277  for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
1278  {
1279  TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
1280  }
1281  for (i = 0; i < d->m_total_lz_bytes; ++i)
1282  {
1283  TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
1284  }
1285  }
1286  /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */
1287  else if (!comp_block_succeeded)
1288  {
1289  d->m_pOutput_buf = pSaved_output_buf;
1290  d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1291  tdefl_compress_block(d, MZ_TRUE);
1292  }
1293 
1294  if (flush)
1295  {
1296  if (flush == TDEFL_FINISH)
1297  {
1298  if (d->m_bits_in)
1299  {
1300  TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1301  }
1302  if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER)
1303  {
1304  mz_uint i, a = d->m_adler32;
1305  for (i = 0; i < 4; i++)
1306  {
1307  TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
1308  a <<= 8;
1309  }
1310  }
1311  }
1312  else
1313  {
1314  mz_uint i, z = 0;
1315  TDEFL_PUT_BITS(0, 3);
1316  if (d->m_bits_in)
1317  {
1318  TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1319  }
1320  for (i = 2; i; --i, z ^= 0xFFFF)
1321  {
1322  TDEFL_PUT_BITS(z & 0xFFFF, 16);
1323  }
1324  }
1325  }
1326 
1327  MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
1328 
1329  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1330  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1331 
1332  d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1333  d->m_pLZ_flags = d->m_lz_code_buf;
1334  d->m_num_flags_left = 8;
1335  d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
1336  d->m_total_lz_bytes = 0;
1337  d->m_block_index++;
1338 
1339  if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
1340  {
1341  if (d->m_pPut_buf_func)
1342  {
1343  *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1344  if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
1345  return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
1346  }
1347  else if (pOutput_buf_start == d->m_output_buf)
1348  {
1349  int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
1350  memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
1351  d->m_out_buf_ofs += bytes_to_copy;
1352  if ((n -= bytes_to_copy) != 0)
1353  {
1354  d->m_output_flush_ofs = bytes_to_copy;
1355  d->m_output_flush_remaining = n;
1356  }
1357  }
1358  else
1359  {
1360  d->m_out_buf_ofs += n;
1361  }
1362  }
1363 
1364  return d->m_output_flush_remaining;
1365 }
1366 
1367 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
1368 #ifdef MINIZ_UNALIGNED_USE_MEMCPY
1369 static mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p)
1370 {
1371  mz_uint16 ret;
1372  memcpy(&ret, p, sizeof(mz_uint16));
1373  return ret;
1374 }
1375 static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p)
1376 {
1377  mz_uint16 ret;
1378  memcpy(&ret, p, sizeof(mz_uint16));
1379  return ret;
1380 }
1381 #else
1382 #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
1383 #define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p)
1384 #endif
1385 static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1386 {
1387  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1388  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1389  const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
1390  mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD2(s);
1391  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1392  if (max_match_len <= match_len)
1393  return;
1394  for (;;)
1395  {
1396  for (;;)
1397  {
1398  if (--num_probes_left == 0)
1399  return;
1400 #define TDEFL_PROBE \
1401  next_probe_pos = d->m_next[probe_pos]; \
1402  if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
1403  return; \
1404  probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
1405  if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) \
1406  break;
1407  TDEFL_PROBE;
1408  TDEFL_PROBE;
1409  TDEFL_PROBE;
1410  }
1411  if (!dist)
1412  break;
1413  q = (const mz_uint16 *)(d->m_dict + probe_pos);
1414  if (TDEFL_READ_UNALIGNED_WORD2(q) != s01)
1415  continue;
1416  p = s;
1417  probe_len = 32;
1418  do
1419  {
1420  } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1421  (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1422  if (!probe_len)
1423  {
1424  *pMatch_dist = dist;
1425  *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN);
1426  break;
1427  }
1428  else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len)
1429  {
1430  *pMatch_dist = dist;
1431  if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len)
1432  break;
1433  c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
1434  }
1435  }
1436 }
1437 #else
1438 static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1439 {
1440  mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1441  mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1442  const mz_uint8 *s = d->m_dict + pos, *p, *q;
1443  mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
1444  MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1445  if (max_match_len <= match_len)
1446  return;
1447  for (;;)
1448  {
1449  for (;;)
1450  {
1451  if (--num_probes_left == 0)
1452  return;
1453 #define TDEFL_PROBE \
1454  next_probe_pos = d->m_next[probe_pos]; \
1455  if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
1456  return; \
1457  probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \
1458  if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \
1459  break;
1460  TDEFL_PROBE;
1461  TDEFL_PROBE;
1462  TDEFL_PROBE;
1463  }
1464  if (!dist)
1465  break;
1466  p = s;
1467  q = d->m_dict + probe_pos;
1468  for (probe_len = 0; probe_len < max_match_len; probe_len++)
1469  if (*p++ != *q++)
1470  break;
1471  if (probe_len > match_len)
1472  {
1473  *pMatch_dist = dist;
1474  if ((*pMatch_len = match_len = probe_len) == max_match_len)
1475  return;
1476  c0 = d->m_dict[pos + match_len];
1477  c1 = d->m_dict[pos + match_len - 1];
1478  }
1479  }
1480 }
1481 #endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */
1482 
1483 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1484 #ifdef MINIZ_UNALIGNED_USE_MEMCPY
1485 static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(const mz_uint8* p)
1486 {
1487  mz_uint32 ret;
1488  memcpy(&ret, p, sizeof(mz_uint32));
1489  return ret;
1490 }
1491 #else
1492 #define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p)
1493 #endif
1494 static mz_bool tdefl_compress_fast(tdefl_compressor *d)
1495 {
1496  /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */
1497  mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;
1498  mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
1499  mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1500 
1501  while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
1502  {
1503  const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
1504  mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1505  mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
1506  d->m_src_buf_left -= num_bytes_to_process;
1507  lookahead_size += num_bytes_to_process;
1508 
1509  while (num_bytes_to_process)
1510  {
1511  mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
1512  memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
1513  if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1514  memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
1515  d->m_pSrc += n;
1516  dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
1517  num_bytes_to_process -= n;
1518  }
1519 
1520  dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
1521  if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
1522  break;
1523 
1524  while (lookahead_size >= 4)
1525  {
1526  mz_uint cur_match_dist, cur_match_len = 1;
1527  mz_uint8 *pCur_dict = d->m_dict + cur_pos;
1528  mz_uint first_trigram = TDEFL_READ_UNALIGNED_WORD32(pCur_dict) & 0xFFFFFF;
1529  mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
1530  mz_uint probe_pos = d->m_hash[hash];
1531  d->m_hash[hash] = (mz_uint16)lookahead_pos;
1532 
1533  if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((TDEFL_READ_UNALIGNED_WORD32(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
1534  {
1535  const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
1536  const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
1537  mz_uint32 probe_len = 32;
1538  do
1539  {
1540  } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1541  (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1542  cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
1543  if (!probe_len)
1544  cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
1545 
1546  if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)))
1547  {
1548  cur_match_len = 1;
1549  *pLZ_code_buf++ = (mz_uint8)first_trigram;
1550  *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1551  d->m_huff_count[0][(mz_uint8)first_trigram]++;
1552  }
1553  else
1554  {
1555  mz_uint32 s0, s1;
1556  cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
1557 
1558  MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
1559 
1560  cur_match_dist--;
1561 
1562  pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
1563 #ifdef MINIZ_UNALIGNED_USE_MEMCPY
1564  memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist));
1565 #else
1566  *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
1567 #endif
1568  pLZ_code_buf += 3;
1569  *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
1570 
1571  s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
1572  s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
1573  d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
1574 
1575  d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
1576  }
1577  }
1578  else
1579  {
1580  *pLZ_code_buf++ = (mz_uint8)first_trigram;
1581  *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1582  d->m_huff_count[0][(mz_uint8)first_trigram]++;
1583  }
1584 
1585  if (--num_flags_left == 0)
1586  {
1587  num_flags_left = 8;
1588  pLZ_flags = pLZ_code_buf++;
1589  }
1590 
1591  total_lz_bytes += cur_match_len;
1592  lookahead_pos += cur_match_len;
1593  dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE);
1594  cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
1595  MZ_ASSERT(lookahead_size >= cur_match_len);
1596  lookahead_size -= cur_match_len;
1597 
1598  if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1599  {
1600  int n;
1601  d->m_lookahead_pos = lookahead_pos;
1602  d->m_lookahead_size = lookahead_size;
1603  d->m_dict_size = dict_size;
1604  d->m_total_lz_bytes = total_lz_bytes;
1605  d->m_pLZ_code_buf = pLZ_code_buf;
1606  d->m_pLZ_flags = pLZ_flags;
1607  d->m_num_flags_left = num_flags_left;
1608  if ((n = tdefl_flush_block(d, 0)) != 0)
1609  return (n < 0) ? MZ_FALSE : MZ_TRUE;
1610  total_lz_bytes = d->m_total_lz_bytes;
1611  pLZ_code_buf = d->m_pLZ_code_buf;
1612  pLZ_flags = d->m_pLZ_flags;
1613  num_flags_left = d->m_num_flags_left;
1614  }
1615  }
1616 
1617  while (lookahead_size)
1618  {
1619  mz_uint8 lit = d->m_dict[cur_pos];
1620 
1621  total_lz_bytes++;
1622  *pLZ_code_buf++ = lit;
1623  *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1624  if (--num_flags_left == 0)
1625  {
1626  num_flags_left = 8;
1627  pLZ_flags = pLZ_code_buf++;
1628  }
1629 
1630  d->m_huff_count[0][lit]++;
1631 
1632  lookahead_pos++;
1633  dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE);
1634  cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1635  lookahead_size--;
1636 
1637  if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1638  {
1639  int n;
1640  d->m_lookahead_pos = lookahead_pos;
1641  d->m_lookahead_size = lookahead_size;
1642  d->m_dict_size = dict_size;
1643  d->m_total_lz_bytes = total_lz_bytes;
1644  d->m_pLZ_code_buf = pLZ_code_buf;
1645  d->m_pLZ_flags = pLZ_flags;
1646  d->m_num_flags_left = num_flags_left;
1647  if ((n = tdefl_flush_block(d, 0)) != 0)
1648  return (n < 0) ? MZ_FALSE : MZ_TRUE;
1649  total_lz_bytes = d->m_total_lz_bytes;
1650  pLZ_code_buf = d->m_pLZ_code_buf;
1651  pLZ_flags = d->m_pLZ_flags;
1652  num_flags_left = d->m_num_flags_left;
1653  }
1654  }
1655  }
1656 
1657  d->m_lookahead_pos = lookahead_pos;
1658  d->m_lookahead_size = lookahead_size;
1659  d->m_dict_size = dict_size;
1660  d->m_total_lz_bytes = total_lz_bytes;
1661  d->m_pLZ_code_buf = pLZ_code_buf;
1662  d->m_pLZ_flags = pLZ_flags;
1663  d->m_num_flags_left = num_flags_left;
1664  return MZ_TRUE;
1665 }
1666 #endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1667 
1668 static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
1669 {
1670  d->m_total_lz_bytes++;
1671  *d->m_pLZ_code_buf++ = lit;
1672  *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
1673  if (--d->m_num_flags_left == 0)
1674  {
1675  d->m_num_flags_left = 8;
1676  d->m_pLZ_flags = d->m_pLZ_code_buf++;
1677  }
1678  d->m_huff_count[0][lit]++;
1679 }
1680 
1681 static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
1682 {
1683  mz_uint32 s0, s1;
1684 
1685  MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
1686 
1687  d->m_total_lz_bytes += match_len;
1688 
1689  d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
1690 
1691  match_dist -= 1;
1692  d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
1693  d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
1694  d->m_pLZ_code_buf += 3;
1695 
1696  *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
1697  if (--d->m_num_flags_left == 0)
1698  {
1699  d->m_num_flags_left = 8;
1700  d->m_pLZ_flags = d->m_pLZ_code_buf++;
1701  }
1702 
1703  s0 = s_tdefl_small_dist_sym[match_dist & 511];
1704  s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
1705  d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
1706 
1707  if (match_len >= TDEFL_MIN_MATCH_LEN)
1708  d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
1709 }
1710 
1711 static mz_bool tdefl_compress_normal(tdefl_compressor *d)
1712 {
1713  const mz_uint8 *pSrc = d->m_pSrc;
1714  size_t src_buf_left = d->m_src_buf_left;
1715  tdefl_flush flush = d->m_flush;
1716 
1717  while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
1718  {
1719  mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
1720  /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */
1721  if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
1722  {
1723  mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
1724  mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
1725  mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
1726  const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
1727  src_buf_left -= num_bytes_to_process;
1728  d->m_lookahead_size += num_bytes_to_process;
1729  while (pSrc != pSrc_end)
1730  {
1731  mz_uint8 c = *pSrc++;
1732  d->m_dict[dst_pos] = c;
1733  if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1734  d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1735  hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1736  d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1737  d->m_hash[hash] = (mz_uint16)(ins_pos);
1738  dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1739  ins_pos++;
1740  }
1741  }
1742  else
1743  {
1744  while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1745  {
1746  mz_uint8 c = *pSrc++;
1747  mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1748  src_buf_left--;
1749  d->m_dict[dst_pos] = c;
1750  if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1751  d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1752  if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
1753  {
1754  mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
1755  mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1756  d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1757  d->m_hash[hash] = (mz_uint16)(ins_pos);
1758  }
1759  }
1760  }
1761  d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
1762  if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1763  break;
1764 
1765  /* Simple lazy/greedy parsing state machine. */
1766  len_to_move = 1;
1767  cur_match_dist = 0;
1768  cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
1769  cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1770  if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
1771  {
1772  if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
1773  {
1774  mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
1775  cur_match_len = 0;
1776  while (cur_match_len < d->m_lookahead_size)
1777  {
1778  if (d->m_dict[cur_pos + cur_match_len] != c)
1779  break;
1780  cur_match_len++;
1781  }
1782  if (cur_match_len < TDEFL_MIN_MATCH_LEN)
1783  cur_match_len = 0;
1784  else
1785  cur_match_dist = 1;
1786  }
1787  }
1788  else
1789  {
1790  tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
1791  }
1792  if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
1793  {
1794  cur_match_dist = cur_match_len = 0;
1795  }
1796  if (d->m_saved_match_len)
1797  {
1798  if (cur_match_len > d->m_saved_match_len)
1799  {
1800  tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
1801  if (cur_match_len >= 128)
1802  {
1803  tdefl_record_match(d, cur_match_len, cur_match_dist);
1804  d->m_saved_match_len = 0;
1805  len_to_move = cur_match_len;
1806  }
1807  else
1808  {
1809  d->m_saved_lit = d->m_dict[cur_pos];
1810  d->m_saved_match_dist = cur_match_dist;
1811  d->m_saved_match_len = cur_match_len;
1812  }
1813  }
1814  else
1815  {
1816  tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
1817  len_to_move = d->m_saved_match_len - 1;
1818  d->m_saved_match_len = 0;
1819  }
1820  }
1821  else if (!cur_match_dist)
1822  tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
1823  else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
1824  {
1825  tdefl_record_match(d, cur_match_len, cur_match_dist);
1826  len_to_move = cur_match_len;
1827  }
1828  else
1829  {
1830  d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
1831  d->m_saved_match_dist = cur_match_dist;
1832  d->m_saved_match_len = cur_match_len;
1833  }
1834  /* Move the lookahead forward by len_to_move bytes. */
1835  d->m_lookahead_pos += len_to_move;
1836  MZ_ASSERT(d->m_lookahead_size >= len_to_move);
1837  d->m_lookahead_size -= len_to_move;
1838  d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
1839  /* Check if it's time to flush the current LZ codes to the internal output buffer. */
1840  if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
1841  ((d->m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))))
1842  {
1843  int n;
1844  d->m_pSrc = pSrc;
1845  d->m_src_buf_left = src_buf_left;
1846  if ((n = tdefl_flush_block(d, 0)) != 0)
1847  return (n < 0) ? MZ_FALSE : MZ_TRUE;
1848  }
1849  }
1850 
1851  d->m_pSrc = pSrc;
1852  d->m_src_buf_left = src_buf_left;
1853  return MZ_TRUE;
1854 }
1855 
1856 static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
1857 {
1858  if (d->m_pIn_buf_size)
1859  {
1860  *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1861  }
1862 
1863  if (d->m_pOut_buf_size)
1864  {
1865  size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
1866  memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
1867  d->m_output_flush_ofs += (mz_uint)n;
1868  d->m_output_flush_remaining -= (mz_uint)n;
1869  d->m_out_buf_ofs += n;
1870 
1871  *d->m_pOut_buf_size = d->m_out_buf_ofs;
1872  }
1873 
1874  return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
1875 }
1876 
1877 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
1878 {
1879  if (!d)
1880  {
1881  if (pIn_buf_size)
1882  *pIn_buf_size = 0;
1883  if (pOut_buf_size)
1884  *pOut_buf_size = 0;
1885  return TDEFL_STATUS_BAD_PARAM;
1886  }
1887 
1888  d->m_pIn_buf = pIn_buf;
1889  d->m_pIn_buf_size = pIn_buf_size;
1890  d->m_pOut_buf = pOut_buf;
1891  d->m_pOut_buf_size = pOut_buf_size;
1892  d->m_pSrc = (const mz_uint8 *)(pIn_buf);
1893  d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
1894  d->m_out_buf_ofs = 0;
1895  d->m_flush = flush;
1896 
1897  if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
1898  (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf))
1899  {
1900  if (pIn_buf_size)
1901  *pIn_buf_size = 0;
1902  if (pOut_buf_size)
1903  *pOut_buf_size = 0;
1904  return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
1905  }
1906  d->m_wants_to_finish |= (flush == TDEFL_FINISH);
1907 
1908  if ((d->m_output_flush_remaining) || (d->m_finished))
1909  return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1910 
1911 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1912  if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
1913  ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
1914  ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
1915  {
1916  if (!tdefl_compress_fast(d))
1917  return d->m_prev_return_status;
1918  }
1919  else
1920 #endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1921  {
1922  if (!tdefl_compress_normal(d))
1923  return d->m_prev_return_status;
1924  }
1925 
1926  if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
1927  d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
1928 
1929  if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
1930  {
1931  if (tdefl_flush_block(d, flush) < 0)
1932  return d->m_prev_return_status;
1933  d->m_finished = (flush == TDEFL_FINISH);
1934  if (flush == TDEFL_FULL_FLUSH)
1935  {
1936  MZ_CLEAR_OBJ(d->m_hash);
1937  MZ_CLEAR_OBJ(d->m_next);
1938  d->m_dict_size = 0;
1939  }
1940  }
1941 
1942  return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1943 }
1944 
1945 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
1946 {
1947  MZ_ASSERT(d->m_pPut_buf_func);
1948  return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
1949 }
1950 
1951 tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1952 {
1953  d->m_pPut_buf_func = pPut_buf_func;
1954  d->m_pPut_buf_user = pPut_buf_user;
1955  d->m_flags = (mz_uint)(flags);
1956  d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
1957  d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
1958  d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
1959  if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
1960  MZ_CLEAR_OBJ(d->m_hash);
1961  d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
1962  d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
1963  d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1964  d->m_pLZ_flags = d->m_lz_code_buf;
1965  d->m_num_flags_left = 8;
1966  d->m_pOutput_buf = d->m_output_buf;
1967  d->m_pOutput_buf_end = d->m_output_buf;
1968  d->m_prev_return_status = TDEFL_STATUS_OKAY;
1969  d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
1970  d->m_adler32 = 1;
1971  d->m_pIn_buf = NULL;
1972  d->m_pOut_buf = NULL;
1973  d->m_pIn_buf_size = NULL;
1974  d->m_pOut_buf_size = NULL;
1975  d->m_flush = TDEFL_NO_FLUSH;
1976  d->m_pSrc = NULL;
1977  d->m_src_buf_left = 0;
1978  d->m_out_buf_ofs = 0;
1979  if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
1980  MZ_CLEAR_OBJ(d->m_dict);
1981  memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1982  memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1983  return TDEFL_STATUS_OKAY;
1984 }
1985 
1986 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
1987 {
1988  return d->m_prev_return_status;
1989 }
1990 
1991 mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
1992 {
1993  return d->m_adler32;
1994 }
1995 
1996 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1997 {
1998  tdefl_compressor *pComp;
1999  mz_bool succeeded;
2000  if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
2001  return MZ_FALSE;
2002  pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2003  if (!pComp)
2004  return MZ_FALSE;
2005  succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
2006  succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
2007  MZ_FREE(pComp);
2008  return succeeded;
2009 }
2010 
2011 typedef struct
2012 {
2013  size_t m_size, m_capacity;
2014  mz_uint8 *m_pBuf;
2015  mz_bool m_expandable;
2017 
2018 static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
2019 {
2021  size_t new_size = p->m_size + len;
2022  if (new_size > p->m_capacity)
2023  {
2024  size_t new_capacity = p->m_capacity;
2025  mz_uint8 *pNew_buf;
2026  if (!p->m_expandable)
2027  return MZ_FALSE;
2028  do
2029  {
2030  new_capacity = MZ_MAX(128U, new_capacity << 1U);
2031  } while (new_size > new_capacity);
2032  pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
2033  if (!pNew_buf)
2034  return MZ_FALSE;
2035  p->m_pBuf = pNew_buf;
2036  p->m_capacity = new_capacity;
2037  }
2038  memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
2039  p->m_size = new_size;
2040  return MZ_TRUE;
2041 }
2042 
2043 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2044 {
2045  tdefl_output_buffer out_buf;
2046  MZ_CLEAR_OBJ(out_buf);
2047  if (!pOut_len)
2048  return MZ_FALSE;
2049  else
2050  *pOut_len = 0;
2051  out_buf.m_expandable = MZ_TRUE;
2052  if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2053  return NULL;
2054  *pOut_len = out_buf.m_size;
2055  return out_buf.m_pBuf;
2056 }
2057 
2058 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2059 {
2060  tdefl_output_buffer out_buf;
2061  MZ_CLEAR_OBJ(out_buf);
2062  if (!pOut_buf)
2063  return 0;
2064  out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
2065  out_buf.m_capacity = out_buf_len;
2066  if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2067  return 0;
2068  return out_buf.m_size;
2069 }
2070 
2071 static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2072 
2073 /* level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). */
2074 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
2075 {
2076  mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
2077  if (window_bits > 0)
2078  comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
2079 
2080  if (!level)
2081  comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
2082  else if (strategy == MZ_FILTERED)
2083  comp_flags |= TDEFL_FILTER_MATCHES;
2084  else if (strategy == MZ_HUFFMAN_ONLY)
2085  comp_flags &= ~TDEFL_MAX_PROBES_MASK;
2086  else if (strategy == MZ_FIXED)
2087  comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
2088  else if (strategy == MZ_RLE)
2089  comp_flags |= TDEFL_RLE_MATCHES;
2090 
2091  return comp_flags;
2092 }
2093 
2094 #ifdef _MSC_VER
2095 #pragma warning(push)
2096 #pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) */
2097 #endif
2098 
2099 /* Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
2100  http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
2101  This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. */
2102 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
2103 {
2104  /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */
2105  static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2106  tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2107  tdefl_output_buffer out_buf;
2108  int i, bpl = w * num_chans, y, z;
2109  mz_uint32 c;
2110  *pLen_out = 0;
2111  if (!pComp)
2112  return NULL;
2113  MZ_CLEAR_OBJ(out_buf);
2114  out_buf.m_expandable = MZ_TRUE;
2115  out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
2116  if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity)))
2117  {
2118  MZ_FREE(pComp);
2119  return NULL;
2120  }
2121  /* write dummy header */
2122  for (z = 41; z; --z)
2123  tdefl_output_buffer_putter(&z, 1, &out_buf);
2124  /* compress image data */
2125  tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
2126  for (y = 0; y < h; ++y)
2127  {
2128  tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
2129  tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH);
2130  }
2131  if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE)
2132  {
2133  MZ_FREE(pComp);
2134  MZ_FREE(out_buf.m_pBuf);
2135  return NULL;
2136  }
2137  /* write real header */
2138  *pLen_out = out_buf.m_size - 41;
2139  {
2140  static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 };
2141  mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d,
2142  0x0a, 0x1a, 0x0a, 0x00, 0x00,
2143  0x00, 0x0d, 0x49, 0x48, 0x44,
2144  0x52, 0x00, 0x00, 0x00, 0x00,
2145  0x00, 0x00, 0x00, 0x00, 0x08,
2146  0x00, 0x00, 0x00, 0x00, 0x00,
2147  0x00, 0x00, 0x00, 0x00, 0x00,
2148  0x00, 0x00, 0x49, 0x44, 0x41,
2149  0x54 };
2150  pnghdr[18] = (mz_uint8)(w >> 8);
2151  pnghdr[19] = (mz_uint8)w;
2152  pnghdr[22] = (mz_uint8)(h >> 8);
2153  pnghdr[23] = (mz_uint8)h;
2154  pnghdr[25] = chans[num_chans];
2155  pnghdr[33] = (mz_uint8)(*pLen_out >> 24);
2156  pnghdr[34] = (mz_uint8)(*pLen_out >> 16);
2157  pnghdr[35] = (mz_uint8)(*pLen_out >> 8);
2158  pnghdr[36] = (mz_uint8)*pLen_out;
2159  c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
2160  for (i = 0; i < 4; ++i, c <<= 8)
2161  ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
2162  memcpy(out_buf.m_pBuf, pnghdr, 41);
2163  }
2164  /* write footer (IDAT CRC-32, followed by IEND chunk) */
2165  if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf))
2166  {
2167  *pLen_out = 0;
2168  MZ_FREE(pComp);
2169  MZ_FREE(out_buf.m_pBuf);
2170  return NULL;
2171  }
2172  c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4);
2173  for (i = 0; i < 4; ++i, c <<= 8)
2174  (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
2175  /* compute final size of file, grab compressed data buffer and return */
2176  *pLen_out += 57;
2177  MZ_FREE(pComp);
2178  return out_buf.m_pBuf;
2179 }
2180 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
2181 {
2182  /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) */
2183  return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
2184 }
2185 
2186 #ifndef MINIZ_NO_MALLOC
2187 /* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */
2188 /* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */
2189 /* structure size and allocation mechanism. */
2190 tdefl_compressor *tdefl_compressor_alloc()
2191 {
2192  return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2193 }
2194 
2195 void tdefl_compressor_free(tdefl_compressor *pComp)
2196 {
2197  MZ_FREE(pComp);
2198 }
2199 #endif
2200 
2201 #ifdef _MSC_VER
2202 #pragma warning(pop)
2203 #endif
2204 
2205 #ifdef __cplusplus
2206 }
2207 #endif
2208 /**************************************************************************
2209  *
2210  * Copyright 2013-2014 RAD Game Tools and Valve Software
2211  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
2212  * All Rights Reserved.
2213  *
2214  * Permission is hereby granted, free of charge, to any person obtaining a copy
2215  * of this software and associated documentation files (the "Software"), to deal
2216  * in the Software without restriction, including without limitation the rights
2217  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2218  * copies of the Software, and to permit persons to whom the Software is
2219  * furnished to do so, subject to the following conditions:
2220  *
2221  * The above copyright notice and this permission notice shall be included in
2222  * all copies or substantial portions of the Software.
2223  *
2224  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2225  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2226  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2227  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2228  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2229  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2230  * THE SOFTWARE.
2231  *
2232  **************************************************************************/
2233 
2234 
2235 
2236 #ifdef __cplusplus
2237 extern "C" {
2238 #endif
2239 
2240 /* ------------------- Low-level Decompression (completely independent from all compression API's) */
2241 
2242 #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
2243 #define TINFL_MEMSET(p, c, l) memset(p, c, l)
2244 
2245 #define TINFL_CR_BEGIN \
2246  switch (r->m_state) \
2247  { \
2248  case 0:
2249 #define TINFL_CR_RETURN(state_index, result) \
2250  do \
2251  { \
2252  status = result; \
2253  r->m_state = state_index; \
2254  goto common_exit; \
2255  case state_index:; \
2256  } \
2257  MZ_MACRO_END
2258 #define TINFL_CR_RETURN_FOREVER(state_index, result) \
2259  do \
2260  { \
2261  for (;;) \
2262  { \
2263  TINFL_CR_RETURN(state_index, result); \
2264  } \
2265  } \
2266  MZ_MACRO_END
2267 #define TINFL_CR_FINISH }
2268 
2269 #define TINFL_GET_BYTE(state_index, c) \
2270  do \
2271  { \
2272  while (pIn_buf_cur >= pIn_buf_end) \
2273  { \
2274  TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
2275  } \
2276  c = *pIn_buf_cur++; \
2277  } \
2278  MZ_MACRO_END
2279 
2280 #define TINFL_NEED_BITS(state_index, n) \
2281  do \
2282  { \
2283  mz_uint c; \
2284  TINFL_GET_BYTE(state_index, c); \
2285  bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2286  num_bits += 8; \
2287  } while (num_bits < (mz_uint)(n))
2288 #define TINFL_SKIP_BITS(state_index, n) \
2289  do \
2290  { \
2291  if (num_bits < (mz_uint)(n)) \
2292  { \
2293  TINFL_NEED_BITS(state_index, n); \
2294  } \
2295  bit_buf >>= (n); \
2296  num_bits -= (n); \
2297  } \
2298  MZ_MACRO_END
2299 #define TINFL_GET_BITS(state_index, b, n) \
2300  do \
2301  { \
2302  if (num_bits < (mz_uint)(n)) \
2303  { \
2304  TINFL_NEED_BITS(state_index, n); \
2305  } \
2306  b = bit_buf & ((1 << (n)) - 1); \
2307  bit_buf >>= (n); \
2308  num_bits -= (n); \
2309  } \
2310  MZ_MACRO_END
2311 
2312 /* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */
2313 /* It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a */
2314 /* Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the */
2315 /* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
2316 #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
2317  do \
2318  { \
2319  temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
2320  if (temp >= 0) \
2321  { \
2322  code_len = temp >> 9; \
2323  if ((code_len) && (num_bits >= code_len)) \
2324  break; \
2325  } \
2326  else if (num_bits > TINFL_FAST_LOOKUP_BITS) \
2327  { \
2328  code_len = TINFL_FAST_LOOKUP_BITS; \
2329  do \
2330  { \
2331  temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
2332  } while ((temp < 0) && (num_bits >= (code_len + 1))); \
2333  if (temp >= 0) \
2334  break; \
2335  } \
2336  TINFL_GET_BYTE(state_index, c); \
2337  bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2338  num_bits += 8; \
2339  } while (num_bits < 15);
2340 
2341 /* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */
2342 /* beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully */
2343 /* decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. */
2344 /* The slow path is only executed at the very end of the input buffer. */
2345 /* v1.16: The original macro handled the case at the very end of the passed-in input buffer, but we also need to handle the case where the user passes in 1+zillion bytes */
2346 /* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */
2347 #define TINFL_HUFF_DECODE(state_index, sym, pHuff) \
2348  do \
2349  { \
2350  int temp; \
2351  mz_uint code_len, c; \
2352  if (num_bits < 15) \
2353  { \
2354  if ((pIn_buf_end - pIn_buf_cur) < 2) \
2355  { \
2356  TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
2357  } \
2358  else \
2359  { \
2360  bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
2361  pIn_buf_cur += 2; \
2362  num_bits += 16; \
2363  } \
2364  } \
2365  if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
2366  code_len = temp >> 9, temp &= 511; \
2367  else \
2368  { \
2369  code_len = TINFL_FAST_LOOKUP_BITS; \
2370  do \
2371  { \
2372  temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
2373  } while (temp < 0); \
2374  } \
2375  sym = temp; \
2376  bit_buf >>= code_len; \
2377  num_bits -= code_len; \
2378  } \
2379  MZ_MACRO_END
2380 
2381 tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
2382 {
2383  static const int s_length_base[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 };
2384  static const int s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 };
2385  static const int s_dist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 };
2386  static const int s_dist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
2387  static const mz_uint8 s_length_dezigzag[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
2388  static const int s_min_table_sizes[3] = { 257, 1, 4 };
2389 
2390  tinfl_status status = TINFL_STATUS_FAILED;
2391  mz_uint32 num_bits, dist, counter, num_extra;
2392  tinfl_bit_buf_t bit_buf;
2393  const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
2394  mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
2395  size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
2396 
2397  /* Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). */
2398  if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))
2399  {
2400  *pIn_buf_size = *pOut_buf_size = 0;
2401  return TINFL_STATUS_BAD_PARAM;
2402  }
2403 
2404  num_bits = r->m_num_bits;
2405  bit_buf = r->m_bit_buf;
2406  dist = r->m_dist;
2407  counter = r->m_counter;
2408  num_extra = r->m_num_extra;
2409  dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2410  TINFL_CR_BEGIN
2411 
2412  bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2413  r->m_z_adler32 = r->m_check_adler32 = 1;
2414  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2415  {
2416  TINFL_GET_BYTE(1, r->m_zhdr0);
2417  TINFL_GET_BYTE(2, r->m_zhdr1);
2418  counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2419  if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2420  counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
2421  if (counter)
2422  {
2423  TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
2424  }
2425  }
2426 
2427  do
2428  {
2429  TINFL_GET_BITS(3, r->m_final, 3);
2430  r->m_type = r->m_final >> 1;
2431  if (r->m_type == 0)
2432  {
2433  TINFL_SKIP_BITS(5, num_bits & 7);
2434  for (counter = 0; counter < 4; ++counter)
2435  {
2436  if (num_bits)
2437  TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2438  else
2439  TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2440  }
2441  if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8))))
2442  {
2443  TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
2444  }
2445  while ((counter) && (num_bits))
2446  {
2447  TINFL_GET_BITS(51, dist, 8);
2448  while (pOut_buf_cur >= pOut_buf_end)
2449  {
2450  TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
2451  }
2452  *pOut_buf_cur++ = (mz_uint8)dist;
2453  counter--;
2454  }
2455  while (counter)
2456  {
2457  size_t n;
2458  while (pOut_buf_cur >= pOut_buf_end)
2459  {
2460  TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
2461  }
2462  while (pIn_buf_cur >= pIn_buf_end)
2463  {
2464  TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);
2465  }
2466  n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
2467  TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2468  pIn_buf_cur += n;
2469  pOut_buf_cur += n;
2470  counter -= (mz_uint)n;
2471  }
2472  }
2473  else if (r->m_type == 3)
2474  {
2475  TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
2476  }
2477  else
2478  {
2479  if (r->m_type == 1)
2480  {
2481  mz_uint8 *p = r->m_tables[0].m_code_size;
2482  mz_uint i;
2483  r->m_table_sizes[0] = 288;
2484  r->m_table_sizes[1] = 32;
2485  TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
2486  for (i = 0; i <= 143; ++i)
2487  *p++ = 8;
2488  for (; i <= 255; ++i)
2489  *p++ = 9;
2490  for (; i <= 279; ++i)
2491  *p++ = 7;
2492  for (; i <= 287; ++i)
2493  *p++ = 8;
2494  }
2495  else
2496  {
2497  for (counter = 0; counter < 3; counter++)
2498  {
2499  TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
2500  r->m_table_sizes[counter] += s_min_table_sizes[counter];
2501  }
2502  MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
2503  for (counter = 0; counter < r->m_table_sizes[2]; counter++)
2504  {
2505  mz_uint s;
2506  TINFL_GET_BITS(14, s, 3);
2507  r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
2508  }
2509  r->m_table_sizes[2] = 19;
2510  }
2511  for (; (int)r->m_type >= 0; r->m_type--)
2512  {
2513  int tree_next, tree_cur;
2514  tinfl_huff_table *pTable;
2515  mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
2516  pTable = &r->m_tables[r->m_type];
2517  MZ_CLEAR_OBJ(total_syms);
2518  MZ_CLEAR_OBJ(pTable->m_look_up);
2519  MZ_CLEAR_OBJ(pTable->m_tree);
2520  for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2521  total_syms[pTable->m_code_size[i]]++;
2522  used_syms = 0, total = 0;
2523  next_code[0] = next_code[1] = 0;
2524  for (i = 1; i <= 15; ++i)
2525  {
2526  used_syms += total_syms[i];
2527  next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2528  }
2529  if ((65536 != total) && (used_syms > 1))
2530  {
2531  TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
2532  }
2533  for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
2534  {
2535  mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index];
2536  if (!code_size)
2537  continue;
2538  cur_code = next_code[code_size]++;
2539  for (l = code_size; l > 0; l--, cur_code >>= 1)
2540  rev_code = (rev_code << 1) | (cur_code & 1);
2541  if (code_size <= TINFL_FAST_LOOKUP_BITS)
2542  {
2543  mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2544  while (rev_code < TINFL_FAST_LOOKUP_SIZE)
2545  {
2546  pTable->m_look_up[rev_code] = k;
2547  rev_code += (1 << code_size);
2548  }
2549  continue;
2550  }
2551  if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
2552  {
2553  pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
2554  tree_cur = tree_next;
2555  tree_next -= 2;
2556  }
2557  rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2558  for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
2559  {
2560  tree_cur -= ((rev_code >>= 1) & 1);
2561  if (!pTable->m_tree[-tree_cur - 1])
2562  {
2563  pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
2564  tree_cur = tree_next;
2565  tree_next -= 2;
2566  }
2567  else
2568  tree_cur = pTable->m_tree[-tree_cur - 1];
2569  }
2570  tree_cur -= ((rev_code >>= 1) & 1);
2571  pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
2572  }
2573  if (r->m_type == 2)
2574  {
2575  for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)
2576  {
2577  mz_uint s;
2578  TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
2579  if (dist < 16)
2580  {
2581  r->m_len_codes[counter++] = (mz_uint8)dist;
2582  continue;
2583  }
2584  if ((dist == 16) && (!counter))
2585  {
2586  TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
2587  }
2588  num_extra = "\02\03\07"[dist - 16];
2589  TINFL_GET_BITS(18, s, num_extra);
2590  s += "\03\03\013"[dist - 16];
2591  TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2592  counter += s;
2593  }
2594  if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
2595  {
2596  TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
2597  }
2598  TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]);
2599  TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
2600  }
2601  }
2602  for (;;)
2603  {
2604  mz_uint8 *pSrc;
2605  for (;;)
2606  {
2607  if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
2608  {
2609  TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
2610  if (counter >= 256)
2611  break;
2612  while (pOut_buf_cur >= pOut_buf_end)
2613  {
2614  TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
2615  }
2616  *pOut_buf_cur++ = (mz_uint8)counter;
2617  }
2618  else
2619  {
2620  int sym2;
2621  mz_uint code_len;
2622 #if TINFL_USE_64BIT_BITBUF
2623  if (num_bits < 30)
2624  {
2625  bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2626  pIn_buf_cur += 4;
2627  num_bits += 32;
2628  }
2629 #else
2630  if (num_bits < 15)
2631  {
2632  bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2633  pIn_buf_cur += 2;
2634  num_bits += 16;
2635  }
2636 #endif
2637  if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2638  code_len = sym2 >> 9;
2639  else
2640  {
2641  code_len = TINFL_FAST_LOOKUP_BITS;
2642  do
2643  {
2644  sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2645  } while (sym2 < 0);
2646  }
2647  counter = sym2;
2648  bit_buf >>= code_len;
2649  num_bits -= code_len;
2650  if (counter & 256)
2651  break;
2652 
2653 #if !TINFL_USE_64BIT_BITBUF
2654  if (num_bits < 15)
2655  {
2656  bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2657  pIn_buf_cur += 2;
2658  num_bits += 16;
2659  }
2660 #endif
2661  if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2662  code_len = sym2 >> 9;
2663  else
2664  {
2665  code_len = TINFL_FAST_LOOKUP_BITS;
2666  do
2667  {
2668  sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2669  } while (sym2 < 0);
2670  }
2671  bit_buf >>= code_len;
2672  num_bits -= code_len;
2673 
2674  pOut_buf_cur[0] = (mz_uint8)counter;
2675  if (sym2 & 256)
2676  {
2677  pOut_buf_cur++;
2678  counter = sym2;
2679  break;
2680  }
2681  pOut_buf_cur[1] = (mz_uint8)sym2;
2682  pOut_buf_cur += 2;
2683  }
2684  }
2685  if ((counter &= 511) == 256)
2686  break;
2687 
2688  num_extra = s_length_extra[counter - 257];
2689  counter = s_length_base[counter - 257];
2690  if (num_extra)
2691  {
2692  mz_uint extra_bits;
2693  TINFL_GET_BITS(25, extra_bits, num_extra);
2694  counter += extra_bits;
2695  }
2696 
2697  TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
2698  num_extra = s_dist_extra[dist];
2699  dist = s_dist_base[dist];
2700  if (num_extra)
2701  {
2702  mz_uint extra_bits;
2703  TINFL_GET_BITS(27, extra_bits, num_extra);
2704  dist += extra_bits;
2705  }
2706 
2707  dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2708  if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2709  {
2710  TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
2711  }
2712 
2713  pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2714 
2715  if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
2716  {
2717  while (counter--)
2718  {
2719  while (pOut_buf_cur >= pOut_buf_end)
2720  {
2721  TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
2722  }
2723  *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
2724  }
2725  continue;
2726  }
2727 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2728  else if ((counter >= 9) && (counter <= dist))
2729  {
2730  const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2731  do
2732  {
2733 #ifdef MINIZ_UNALIGNED_USE_MEMCPY
2734  memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2);
2735 #else
2736  ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
2737  ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
2738 #endif
2739  pOut_buf_cur += 8;
2740  } while ((pSrc += 8) < pSrc_end);
2741  if ((counter &= 7) < 3)
2742  {
2743  if (counter)
2744  {
2745  pOut_buf_cur[0] = pSrc[0];
2746  if (counter > 1)
2747  pOut_buf_cur[1] = pSrc[1];
2748  pOut_buf_cur += counter;
2749  }
2750  continue;
2751  }
2752  }
2753 #endif
2754  while(counter>2)
2755  {
2756  pOut_buf_cur[0] = pSrc[0];
2757  pOut_buf_cur[1] = pSrc[1];
2758  pOut_buf_cur[2] = pSrc[2];
2759  pOut_buf_cur += 3;
2760  pSrc += 3;
2761  counter -= 3;
2762  }
2763  if (counter > 0)
2764  {
2765  pOut_buf_cur[0] = pSrc[0];
2766  if (counter > 1)
2767  pOut_buf_cur[1] = pSrc[1];
2768  pOut_buf_cur += counter;
2769  }
2770  }
2771  }
2772  } while (!(r->m_final & 1));
2773 
2774  /* Ensure byte alignment and put back any bytes from the bitbuf if we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
2775  /* I'm being super conservative here. A number of simplifications can be made to the byte alignment part, and the Adler32 check shouldn't ever need to worry about reading from the bitbuf now. */
2776  TINFL_SKIP_BITS(32, num_bits & 7);
2777  while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2778  {
2779  --pIn_buf_cur;
2780  num_bits -= 8;
2781  }
2782  bit_buf &= (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
2783  MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond the end of non-deflate/zlib streams with following data (such as gzip streams). */
2784 
2785  if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2786  {
2787  for (counter = 0; counter < 4; ++counter)
2788  {
2789  mz_uint s;
2790  if (num_bits)
2791  TINFL_GET_BITS(41, s, 8);
2792  else
2793  TINFL_GET_BYTE(42, s);
2794  r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2795  }
2796  }
2797  TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
2798 
2799  TINFL_CR_FINISH
2800 
2801 common_exit:
2802  /* As long as we aren't telling the caller that we NEED more input to make forward progress: */
2803  /* Put back any bytes from the bitbuf in case we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
2804  /* We need to be very careful here to NOT push back any bytes we definitely know we need to make forward progress, though, or we'll lock the caller up into an inf loop. */
2805  if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS))
2806  {
2807  while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2808  {
2809  --pIn_buf_cur;
2810  num_bits -= 8;
2811  }
2812  }
2813  r->m_num_bits = num_bits;
2814  r->m_bit_buf = bit_buf & (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
2815  r->m_dist = dist;
2816  r->m_counter = counter;
2817  r->m_num_extra = num_extra;
2818  r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2819  *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2820  *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2821  if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
2822  {
2823  const mz_uint8 *ptr = pOut_buf_next;
2824  size_t buf_len = *pOut_buf_size;
2825  mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;
2826  size_t block_len = buf_len % 5552;
2827  while (buf_len)
2828  {
2829  for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
2830  {
2831  s1 += ptr[0], s2 += s1;
2832  s1 += ptr[1], s2 += s1;
2833  s1 += ptr[2], s2 += s1;
2834  s1 += ptr[3], s2 += s1;
2835  s1 += ptr[4], s2 += s1;
2836  s1 += ptr[5], s2 += s1;
2837  s1 += ptr[6], s2 += s1;
2838  s1 += ptr[7], s2 += s1;
2839  }
2840  for (; i < block_len; ++i)
2841  s1 += *ptr++, s2 += s1;
2842  s1 %= 65521U, s2 %= 65521U;
2843  buf_len -= block_len;
2844  block_len = 5552;
2845  }
2846  r->m_check_adler32 = (s2 << 16) + s1;
2847  if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
2848  status = TINFL_STATUS_ADLER32_MISMATCH;
2849  }
2850  return status;
2851 }
2852 
2853 /* Higher level helper functions. */
2854 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2855 {
2856  tinfl_decompressor decomp;
2857  void *pBuf = NULL, *pNew_buf;
2858  size_t src_buf_ofs = 0, out_buf_capacity = 0;
2859  *pOut_len = 0;
2860  tinfl_init(&decomp);
2861  for (;;)
2862  {
2863  size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2864  tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, &dst_buf_size,
2865  (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2866  if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
2867  {
2868  MZ_FREE(pBuf);
2869  *pOut_len = 0;
2870  return NULL;
2871  }
2872  src_buf_ofs += src_buf_size;
2873  *pOut_len += dst_buf_size;
2874  if (status == TINFL_STATUS_DONE)
2875  break;
2876  new_out_buf_capacity = out_buf_capacity * 2;
2877  if (new_out_buf_capacity < 128)
2878  new_out_buf_capacity = 128;
2879  pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2880  if (!pNew_buf)
2881  {
2882  MZ_FREE(pBuf);
2883  *pOut_len = 0;
2884  return NULL;
2885  }
2886  pBuf = pNew_buf;
2887  out_buf_capacity = new_out_buf_capacity;
2888  }
2889  return pBuf;
2890 }
2891 
2892 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2893 {
2894  tinfl_decompressor decomp;
2895  tinfl_status status;
2896  tinfl_init(&decomp);
2897  status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len, (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2898  return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
2899 }
2900 
2901 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
2902 {
2903  int result = 0;
2904  tinfl_decompressor decomp;
2905  mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
2906  size_t in_buf_ofs = 0, dict_ofs = 0;
2907  if (!pDict)
2908  return TINFL_STATUS_FAILED;
2909  tinfl_init(&decomp);
2910  for (;;)
2911  {
2912  size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
2913  tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
2914  (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
2915  in_buf_ofs += in_buf_size;
2916  if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
2917  break;
2918  if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
2919  {
2920  result = (status == TINFL_STATUS_DONE);
2921  break;
2922  }
2923  dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
2924  }
2925  MZ_FREE(pDict);
2926  *pIn_buf_size = in_buf_ofs;
2927  return result;
2928 }
2929 
2930 #ifndef MINIZ_NO_MALLOC
2931 tinfl_decompressor *tinfl_decompressor_alloc()
2932 {
2933  tinfl_decompressor *pDecomp = (tinfl_decompressor *)MZ_MALLOC(sizeof(tinfl_decompressor));
2934  if (pDecomp)
2935  tinfl_init(pDecomp);
2936  return pDecomp;
2937 }
2938 
2939 void tinfl_decompressor_free(tinfl_decompressor *pDecomp)
2940 {
2941  MZ_FREE(pDecomp);
2942 }
2943 #endif
2944 
2945 #ifdef __cplusplus
2946 }
2947 #endif
2948 /**************************************************************************
2949  *
2950  * Copyright 2013-2014 RAD Game Tools and Valve Software
2951  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
2952  * Copyright 2016 Martin Raiber
2953  * All Rights Reserved.
2954  *
2955  * Permission is hereby granted, free of charge, to any person obtaining a copy
2956  * of this software and associated documentation files (the "Software"), to deal
2957  * in the Software without restriction, including without limitation the rights
2958  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2959  * copies of the Software, and to permit persons to whom the Software is
2960  * furnished to do so, subject to the following conditions:
2961  *
2962  * The above copyright notice and this permission notice shall be included in
2963  * all copies or substantial portions of the Software.
2964  *
2965  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2966  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2967  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2968  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2969  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2970  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2971  * THE SOFTWARE.
2972  *
2973  **************************************************************************/
2974 
2975 
2976 #ifndef MINIZ_NO_ARCHIVE_APIS
2977 
2978 #ifdef __cplusplus
2979 //extern "C" {
2980 #endif
2981 
2982 /* ------------------- .ZIP archive reading */
2983 
2984 #ifdef MINIZ_NO_STDIO
2985 #define MZ_FILE void *
2986 #else
2987 #include <sys/stat.h>
2988 
2989 #if defined(_MSC_VER) || defined(__MINGW64__)
2990 #include <codecvt>
2991 #include <string>
2992 #include <locale>
2993 
2994 static FILE *mz_fopen(const char *pFilename, const char *pMode)
2995 {
2996  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
2997  std::wstring wideFilename = converter.from_bytes(pFilename);
2998  std::wstring wideMode = converter.from_bytes(pMode);
2999 
3000  FILE *pFile = NULL;
3001  _wfopen_s(&pFile, wideFilename.c_str(), wideMode.c_str());
3002  return pFile;
3003 }
3004 static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
3005 {
3006  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
3007  std::wstring widePath = converter.from_bytes(pPath);
3008  std::wstring wideMode = converter.from_bytes(pMode);
3009 
3010  FILE *pFile = NULL;
3011  if (_wfreopen_s(&pFile, widePath.c_str(), wideMode.c_str(), pStream))
3012  return NULL;
3013  return pFile;
3014 }
3015 #ifndef MINIZ_NO_TIME
3016 #include <sys/utime.h>
3017 #endif
3018 #define MZ_FOPEN mz_fopen
3019 #define MZ_FCLOSE fclose
3020 #define MZ_FREAD fread
3021 #define MZ_FWRITE fwrite
3022 #define MZ_FTELL64 _ftelli64
3023 #define MZ_FSEEK64 _fseeki64
3024 #define MZ_FILE_STAT_STRUCT _stat64
3025 #define MZ_FILE_STAT _stat64
3026 #define MZ_FFLUSH fflush
3027 #define MZ_FREOPEN mz_freopen
3028 #define MZ_DELETE_FILE remove
3029 #elif defined(__MINGW32__)
3030 #ifndef MINIZ_NO_TIME
3031 #include <sys/utime.h>
3032 #endif
3033 #define MZ_FOPEN(f, m) fopen(f, m)
3034 #define MZ_FCLOSE fclose
3035 #define MZ_FREAD fread
3036 #define MZ_FWRITE fwrite
3037 #define MZ_FTELL64 ftello64
3038 #define MZ_FSEEK64 fseeko64
3039 #define MZ_FILE_STAT_STRUCT _stat
3040 #define MZ_FILE_STAT _stat
3041 #define MZ_FFLUSH fflush
3042 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3043 #define MZ_DELETE_FILE remove
3044 #elif defined(__TINYC__)
3045 #ifndef MINIZ_NO_TIME
3046 #include <sys/utime.h>
3047 #endif
3048 #define MZ_FOPEN(f, m) fopen(f, m)
3049 #define MZ_FCLOSE fclose
3050 #define MZ_FREAD fread
3051 #define MZ_FWRITE fwrite
3052 #define MZ_FTELL64 ftell
3053 #define MZ_FSEEK64 fseek
3054 #define MZ_FILE_STAT_STRUCT stat
3055 #define MZ_FILE_STAT stat
3056 #define MZ_FFLUSH fflush
3057 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3058 #define MZ_DELETE_FILE remove
3059 #elif defined(__GNUC__) && defined(_LARGEFILE64_SOURCE)
3060 #ifndef MINIZ_NO_TIME
3061 #include <utime.h>
3062 #endif
3063 #define MZ_FOPEN(f, m) fopen64(f, m)
3064 #define MZ_FCLOSE fclose
3065 #define MZ_FREAD fread
3066 #define MZ_FWRITE fwrite
3067 #define MZ_FTELL64 ftello64
3068 #define MZ_FSEEK64 fseeko64
3069 #define MZ_FILE_STAT_STRUCT stat64
3070 #define MZ_FILE_STAT stat64
3071 #define MZ_FFLUSH fflush
3072 #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
3073 #define MZ_DELETE_FILE remove
3074 #elif defined(__APPLE__)
3075 #ifndef MINIZ_NO_TIME
3076 #include <utime.h>
3077 #endif
3078 #define MZ_FOPEN(f, m) fopen(f, m)
3079 #define MZ_FCLOSE fclose
3080 #define MZ_FREAD fread
3081 #define MZ_FWRITE fwrite
3082 #define MZ_FTELL64 ftello
3083 #define MZ_FSEEK64 fseeko
3084 #define MZ_FILE_STAT_STRUCT stat
3085 #define MZ_FILE_STAT stat
3086 #define MZ_FFLUSH fflush
3087 #define MZ_FREOPEN(p, m, s) freopen(p, m, s)
3088 #define MZ_DELETE_FILE remove
3089 
3090 #else
3091 #pragma message("Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.")
3092 #ifndef MINIZ_NO_TIME
3093 #include <utime.h>
3094 #endif
3095 #define MZ_FOPEN(f, m) fopen(f, m)
3096 #define MZ_FCLOSE fclose
3097 #define MZ_FREAD fread
3098 #define MZ_FWRITE fwrite
3099 #ifdef __STRICT_ANSI__
3100 #define MZ_FTELL64 ftell
3101 #define MZ_FSEEK64 fseek
3102 #else
3103 #define MZ_FTELL64 ftello
3104 #define MZ_FSEEK64 fseeko
3105 #endif
3106 #define MZ_FILE_STAT_STRUCT stat
3107 #define MZ_FILE_STAT stat
3108 #define MZ_FFLUSH fflush
3109 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3110 #define MZ_DELETE_FILE remove
3111 #endif /* #ifdef _MSC_VER */
3112 #endif /* #ifdef MINIZ_NO_STDIO */
3113 
3114 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
3115 
3116 /* Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. */
3117 enum
3118 {
3119  /* ZIP archive identifiers and record sizes */
3120  MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
3121  MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
3122  MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
3123  MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
3124  MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
3125  MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
3126 
3127  /* ZIP64 archive identifier and record sizes */
3128  MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
3129  MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
3130  MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
3131  MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
3132  MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
3133  MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
3134  MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
3135  MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
3136 
3137  /* Central directory header record offsets */
3138  MZ_ZIP_CDH_SIG_OFS = 0,
3139  MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
3140  MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
3141  MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
3142  MZ_ZIP_CDH_METHOD_OFS = 10,
3143  MZ_ZIP_CDH_FILE_TIME_OFS = 12,
3144  MZ_ZIP_CDH_FILE_DATE_OFS = 14,
3145  MZ_ZIP_CDH_CRC32_OFS = 16,
3146  MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
3147  MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
3148  MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
3149  MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
3150  MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
3151  MZ_ZIP_CDH_DISK_START_OFS = 34,
3152  MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
3153  MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
3154  MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
3155 
3156  /* Local directory header offsets */
3157  MZ_ZIP_LDH_SIG_OFS = 0,
3158  MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
3159  MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
3160  MZ_ZIP_LDH_METHOD_OFS = 8,
3161  MZ_ZIP_LDH_FILE_TIME_OFS = 10,
3162  MZ_ZIP_LDH_FILE_DATE_OFS = 12,
3163  MZ_ZIP_LDH_CRC32_OFS = 14,
3164  MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
3165  MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
3166  MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
3167  MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
3168  MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3,
3169 
3170  /* End of central directory offsets */
3171  MZ_ZIP_ECDH_SIG_OFS = 0,
3172  MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
3173  MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
3174  MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
3175  MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
3176  MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
3177  MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
3178  MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
3179 
3180  /* ZIP64 End of central directory locator offsets */
3181  MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */
3182  MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */
3183  MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */
3184  MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
3185 
3186  /* ZIP64 End of central directory header offsets */
3187  MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */
3188  MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */
3189  MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */
3190  MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */
3191  MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */
3192  MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */
3193  MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
3194  MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */
3195  MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */
3196  MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */
3197  MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
3198  MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
3199  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
3200  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
3201  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
3202  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
3203  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
3204 };
3205 
3206 typedef struct
3207 {
3208  void *m_p;
3209  size_t m_size, m_capacity;
3210  mz_uint m_element_size;
3211 } mz_zip_array;
3212 
3214 {
3215  mz_zip_array m_central_dir;
3216  mz_zip_array m_central_dir_offsets;
3217  mz_zip_array m_sorted_central_dir_offsets;
3218 
3219  /* The flags passed in when the archive is initially opened. */
3220  uint32_t m_init_flags;
3221 
3222  /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */
3223  mz_bool m_zip64;
3224 
3225  /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 will also be slammed to true too, even if we didn't find a zip64 end of central dir header, etc.) */
3226  mz_bool m_zip64_has_extended_info_fields;
3227 
3228  /* These fields are used by the file, FILE, memory, and memory/heap read/write helpers. */
3229  MZ_FILE *m_pFile;
3230  mz_uint64 m_file_archive_start_ofs;
3231 
3232  void *m_pMem;
3233  size_t m_mem_size;
3234  size_t m_mem_capacity;
3235 };
3236 
3237 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
3238 
3239 #if defined(DEBUG) || defined(_DEBUG) || defined(NDEBUG)
3240 static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index)
3241 {
3242  MZ_ASSERT(index < pArray->m_size);
3243  return index;
3244 }
3245 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]
3246 #else
3247 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
3248 #endif
3249 
3250 static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size)
3251 {
3252  memset(pArray, 0, sizeof(mz_zip_array));
3253  pArray->m_element_size = element_size;
3254 }
3255 
3256 static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
3257 {
3258  pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
3259  memset(pArray, 0, sizeof(mz_zip_array));
3260 }
3261 
3262 static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
3263 {
3264  void *pNew_p;
3265  size_t new_capacity = min_new_capacity;
3266  MZ_ASSERT(pArray->m_element_size);
3267  if (pArray->m_capacity >= min_new_capacity)
3268  return MZ_TRUE;
3269  if (growing)
3270  {
3271  new_capacity = MZ_MAX(1, pArray->m_capacity);
3272  while (new_capacity < min_new_capacity)
3273  new_capacity *= 2;
3274  }
3275  if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
3276  return MZ_FALSE;
3277  pArray->m_p = pNew_p;
3278  pArray->m_capacity = new_capacity;
3279  return MZ_TRUE;
3280 }
3281 
3282 static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
3283 {
3284  if (new_capacity > pArray->m_capacity)
3285  {
3286  if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
3287  return MZ_FALSE;
3288  }
3289  return MZ_TRUE;
3290 }
3291 
3292 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
3293 {
3294  if (new_size > pArray->m_capacity)
3295  {
3296  if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
3297  return MZ_FALSE;
3298  }
3299  pArray->m_size = new_size;
3300  return MZ_TRUE;
3301 }
3302 
3303 static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
3304 {
3305  return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
3306 }
3307 
3308 static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
3309 {
3310  size_t orig_size = pArray->m_size;
3311  if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
3312  return MZ_FALSE;
3313  if (n > 0)
3314  memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
3315  return MZ_TRUE;
3316 }
3317 
3318 #ifndef MINIZ_NO_TIME
3319 static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)
3320 {
3321  struct tm tm;
3322  memset(&tm, 0, sizeof(tm));
3323  tm.tm_isdst = -1;
3324  tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
3325  tm.tm_mon = ((dos_date >> 5) & 15) - 1;
3326  tm.tm_mday = dos_date & 31;
3327  tm.tm_hour = (dos_time >> 11) & 31;
3328  tm.tm_min = (dos_time >> 5) & 63;
3329  tm.tm_sec = (dos_time << 1) & 62;
3330  return mktime(&tm);
3331 }
3332 
3333 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3334 static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3335 {
3336 #ifdef _MSC_VER
3337  struct tm tm_struct;
3338  struct tm *tm = &tm_struct;
3339  errno_t err = localtime_s(tm, &time);
3340  if (err)
3341  {
3342  *pDOS_date = 0;
3343  *pDOS_time = 0;
3344  return;
3345  }
3346 #else
3347  struct tm *tm = localtime(&time);
3348 #endif /* #ifdef _MSC_VER */
3349 
3350  *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
3351  *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
3352 }
3353 #endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
3354 
3355 #ifndef MINIZ_NO_STDIO
3356 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3357 static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime)
3358 {
3359  struct MZ_FILE_STAT_STRUCT file_stat;
3360 
3361  /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
3362  if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
3363  return MZ_FALSE;
3364 
3365  *pTime = file_stat.st_mtime;
3366 
3367  return MZ_TRUE;
3368 }
3369 #endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
3370 
3371 static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)
3372 {
3373  struct utimbuf t;
3374 
3375  memset(&t, 0, sizeof(t));
3376  t.actime = access_time;
3377  t.modtime = modified_time;
3378 
3379  return !utime(pFilename, &t);
3380 }
3381 #endif /* #ifndef MINIZ_NO_STDIO */
3382 #endif /* #ifndef MINIZ_NO_TIME */
3383 
3384 static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num)
3385 {
3386  if (pZip)
3387  pZip->m_last_error = err_num;
3388  return MZ_FALSE;
3389 }
3390 
3391 static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
3392 {
3393  (void)flags;
3394  if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3395  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3396 
3397  if (!pZip->m_pAlloc)
3398  pZip->m_pAlloc = miniz_def_alloc_func;
3399  if (!pZip->m_pFree)
3400  pZip->m_pFree = miniz_def_free_func;
3401  if (!pZip->m_pRealloc)
3402  pZip->m_pRealloc = miniz_def_realloc_func;
3403 
3404  pZip->m_archive_size = 0;
3405  pZip->m_central_directory_file_ofs = 0;
3406  pZip->m_total_files = 0;
3407  pZip->m_last_error = MZ_ZIP_NO_ERROR;
3408 
3409  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3410  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3411 
3412  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3413  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
3414  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
3415  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
3416  pZip->m_pState->m_init_flags = flags;
3417  pZip->m_pState->m_zip64 = MZ_FALSE;
3418  pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;
3419 
3420  pZip->m_zip_mode = MZ_ZIP_MODE_READING;
3421 
3422  return MZ_TRUE;
3423 }
3424 
3425 static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
3426 {
3427  const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
3428  const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
3429  mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3430  mz_uint8 l = 0, r = 0;
3431  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3432  pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3433  pE = pL + MZ_MIN(l_len, r_len);
3434  while (pL < pE)
3435  {
3436  if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3437  break;
3438  pL++;
3439  pR++;
3440  }
3441  return (pL == pE) ? (l_len < r_len) : (l < r);
3442 }
3443 
3444 #define MZ_SWAP_UINT32(a, b) \
3445  do \
3446  { \
3447  mz_uint32 t = a; \
3448  a = b; \
3449  b = t; \
3450  } \
3451  MZ_MACRO_END
3452 
3453 /* Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) */
3454 static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
3455 {
3456  mz_zip_internal_state *pState = pZip->m_pState;
3457  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3458  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3459  mz_uint32 *pIndices;
3460  mz_uint32 start, end;
3461  const mz_uint32 size = pZip->m_total_files;
3462 
3463  if (size <= 1U)
3464  return;
3465 
3466  pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
3467 
3468  start = (size - 2U) >> 1U;
3469  for (;;)
3470  {
3471  mz_uint64 child, root = start;
3472  for (;;)
3473  {
3474  if ((child = (root << 1U) + 1U) >= size)
3475  break;
3476  child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
3477  if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3478  break;
3479  MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3480  root = child;
3481  }
3482  if (!start)
3483  break;
3484  start--;
3485  }
3486 
3487  end = size - 1;
3488  while (end > 0)
3489  {
3490  mz_uint64 child, root = 0;
3491  MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
3492  for (;;)
3493  {
3494  if ((child = (root << 1U) + 1U) >= end)
3495  break;
3496  child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
3497  if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3498  break;
3499  MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3500  root = child;
3501  }
3502  end--;
3503  }
3504 }
3505 
3506 static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)
3507 {
3508  mz_int64 cur_file_ofs;
3509  mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3510  mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3511 
3512  /* Basic sanity checks - reject files which are too small */
3513  if (pZip->m_archive_size < record_size)
3514  return MZ_FALSE;
3515 
3516  /* Find the record by scanning the file from the end towards the beginning. */
3517  cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
3518  for (;;)
3519  {
3520  int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
3521 
3522  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
3523  return MZ_FALSE;
3524 
3525  for (i = n - 4; i >= 0; --i)
3526  {
3527  mz_uint s = MZ_READ_LE32(pBuf + i);
3528  if (s == record_sig)
3529  {
3530  if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
3531  break;
3532  }
3533  }
3534 
3535  if (i >= 0)
3536  {
3537  cur_file_ofs += i;
3538  break;
3539  }
3540 
3541  /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */
3542  if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size)))
3543  return MZ_FALSE;
3544 
3545  cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
3546  }
3547 
3548  *pOfs = cur_file_ofs;
3549  return MZ_TRUE;
3550 }
3551 
3552 static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)
3553 {
3554  mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
3555  mz_uint64 cdir_ofs = 0;
3556  mz_int64 cur_file_ofs = 0;
3557  const mz_uint8 *p;
3558 
3559  mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3560  mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3561  mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
3562  mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3563  mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
3564 
3565  mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3566  mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
3567 
3568  mz_uint64 zip64_end_of_central_dir_ofs = 0;
3569 
3570  /* Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. */
3571  if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3572  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3573 
3574  if (!mz_zip_reader_locate_header_sig(pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
3575  return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
3576 
3577  /* Read and verify the end of central directory record. */
3578  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3579  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3580 
3581  if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
3582  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3583 
3584  if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3585  {
3586  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, pZip64_locator, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
3587  {
3588  if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG)
3589  {
3590  zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
3591  if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3592  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3593 
3594  if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
3595  {
3596  if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG)
3597  {
3598  pZip->m_pState->m_zip64 = MZ_TRUE;
3599  }
3600  }
3601  }
3602  }
3603  }
3604 
3605  pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3606  cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3607  num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
3608  cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
3609  cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
3610  cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
3611 
3612  if (pZip->m_pState->m_zip64)
3613  {
3614  mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
3615  mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3616  mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3617  mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
3618  mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
3619 
3620  if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
3621  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3622 
3623  if (zip64_total_num_of_disks != 1U)
3624  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3625 
3626  /* Check for miniz's practical limits */
3627  if (zip64_cdir_total_entries > MZ_UINT32_MAX)
3628  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3629 
3630  pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
3631 
3632  if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
3633  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3634 
3635  cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;
3636 
3637  /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */
3638  if (zip64_size_of_central_directory > MZ_UINT32_MAX)
3639  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
3640 
3641  cdir_size = (mz_uint32)zip64_size_of_central_directory;
3642 
3643  num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
3644 
3645  cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
3646 
3647  cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
3648  }
3649 
3650  if (pZip->m_total_files != cdir_entries_on_this_disk)
3651  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3652 
3653  if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
3654  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3655 
3656  if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
3657  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3658 
3659  if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
3660  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3661 
3662  pZip->m_central_directory_file_ofs = cdir_ofs;
3663 
3664  if (pZip->m_total_files)
3665  {
3666  mz_uint i, n;
3667  /* Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and possibly another to hold the sorted indices. */
3668  if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
3669  (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
3670  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3671 
3672  if (sort_central_dir)
3673  {
3674  if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
3675  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3676  }
3677 
3678  if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
3679  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3680 
3681  /* Now create an index into the central directory file records, do some basic sanity checking on each record */
3682  p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
3683  for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
3684  {
3685  mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
3686  mz_uint64 comp_size, decomp_size, local_header_ofs;
3687 
3688  if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
3689  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3690 
3691  MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
3692 
3693  if (sort_central_dir)
3694  MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
3695 
3696  comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3697  decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3698  local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3699  filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3700  ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
3701 
3702  if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
3703  (ext_data_size) &&
3704  (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
3705  {
3706  /* Attempt to find zip64 extended information field in the entry's extra data */
3707  mz_uint32 extra_size_remaining = ext_data_size;
3708 
3709  if (extra_size_remaining)
3710  {
3711  const mz_uint8 *pExtra_data;
3712  void* buf = NULL;
3713 
3714  if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n)
3715  {
3716  buf = MZ_MALLOC(ext_data_size);
3717  if(buf==NULL)
3718  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3719 
3720  if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size, buf, ext_data_size) != ext_data_size)
3721  {
3722  MZ_FREE(buf);
3723  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3724  }
3725 
3726  pExtra_data = (mz_uint8*)buf;
3727  }
3728  else
3729  {
3730  pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
3731  }
3732 
3733  do
3734  {
3735  mz_uint32 field_id;
3736  mz_uint32 field_data_size;
3737 
3738  if (extra_size_remaining < (sizeof(mz_uint16) * 2))
3739  {
3740  MZ_FREE(buf);
3741  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3742  }
3743 
3744  field_id = MZ_READ_LE16(pExtra_data);
3745  field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
3746 
3747  if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
3748  {
3749  MZ_FREE(buf);
3750  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3751  }
3752 
3753  if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
3754  {
3755  /* Ok, the archive didn't have any zip64 headers but it uses a zip64 extended information field so mark it as zip64 anyway (this can occur with infozip's zip util when it reads compresses files from stdin). */
3756  pZip->m_pState->m_zip64 = MZ_TRUE;
3757  pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
3758  break;
3759  }
3760 
3761  pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
3762  extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
3763  } while (extra_size_remaining);
3764 
3765  MZ_FREE(buf);
3766  }
3767  }
3768 
3769  /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */
3770  if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
3771  {
3772  if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
3773  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3774  }
3775 
3776  disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
3777  if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
3778  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3779 
3780  if (comp_size != MZ_UINT32_MAX)
3781  {
3782  if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
3783  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3784  }
3785 
3786  bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3787  if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
3788  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
3789 
3790  if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)
3791  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3792 
3793  n -= total_header_size;
3794  p += total_header_size;
3795  }
3796  }
3797 
3798  if (sort_central_dir)
3799  mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
3800 
3801  return MZ_TRUE;
3802 }
3803 
3804 void mz_zip_zero_struct(mz_zip_archive *pZip)
3805 {
3806  if (pZip)
3807  MZ_CLEAR_OBJ(*pZip);
3808 }
3809 
3810 static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
3811 {
3812  mz_bool status = MZ_TRUE;
3813 
3814  if (!pZip)
3815  return MZ_FALSE;
3816 
3817  if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3818  {
3819  if (set_last_error)
3820  pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;
3821 
3822  return MZ_FALSE;
3823  }
3824 
3825  if (pZip->m_pState)
3826  {
3827  mz_zip_internal_state *pState = pZip->m_pState;
3828  pZip->m_pState = NULL;
3829 
3830  mz_zip_array_clear(pZip, &pState->m_central_dir);
3831  mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
3832  mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
3833 
3834 #ifndef MINIZ_NO_STDIO
3835  if (pState->m_pFile)
3836  {
3837  if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
3838  {
3839  if (MZ_FCLOSE(pState->m_pFile) == EOF)
3840  {
3841  if (set_last_error)
3842  pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED;
3843  status = MZ_FALSE;
3844  }
3845  }
3846  pState->m_pFile = NULL;
3847  }
3848 #endif /* #ifndef MINIZ_NO_STDIO */
3849 
3850  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
3851  }
3852  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
3853 
3854  return status;
3855 }
3856 
3857 mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
3858 {
3859  return mz_zip_reader_end_internal(pZip, MZ_TRUE);
3860 }
3861 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
3862 {
3863  if ((!pZip) || (!pZip->m_pRead))
3864  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3865 
3866  if (!mz_zip_reader_init_internal(pZip, flags))
3867  return MZ_FALSE;
3868 
3869  pZip->m_zip_type = MZ_ZIP_TYPE_USER;
3870  pZip->m_archive_size = size;
3871 
3872  if (!mz_zip_reader_read_central_dir(pZip, flags))
3873  {
3874  mz_zip_reader_end_internal(pZip, MZ_FALSE);
3875  return MZ_FALSE;
3876  }
3877 
3878  return MZ_TRUE;
3879 }
3880 
3881 static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3882 {
3883  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3884  size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
3885  memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
3886  return s;
3887 }
3888 
3889 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)
3890 {
3891  if (!pMem)
3892  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3893 
3894  if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3895  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3896 
3897  if (!mz_zip_reader_init_internal(pZip, flags))
3898  return MZ_FALSE;
3899 
3900  pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY;
3901  pZip->m_archive_size = size;
3902  pZip->m_pRead = mz_zip_mem_read_func;
3903  pZip->m_pIO_opaque = pZip;
3904  pZip->m_pNeeds_keepalive = NULL;
3905 
3906 #ifdef __cplusplus
3907  pZip->m_pState->m_pMem = const_cast<void *>(pMem);
3908 #else
3909  pZip->m_pState->m_pMem = (void *)pMem;
3910 #endif
3911 
3912  pZip->m_pState->m_mem_size = size;
3913 
3914  if (!mz_zip_reader_read_central_dir(pZip, flags))
3915  {
3916  mz_zip_reader_end_internal(pZip, MZ_FALSE);
3917  return MZ_FALSE;
3918  }
3919 
3920  return MZ_TRUE;
3921 }
3922 
3923 #ifndef MINIZ_NO_STDIO
3924 static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3925 {
3926  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3927  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
3928 
3929  file_ofs += pZip->m_pState->m_file_archive_start_ofs;
3930 
3931  if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
3932  return 0;
3933 
3934  return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
3935 }
3936 
3937 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
3938 {
3939  return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);
3940 }
3941 
3942 mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size)
3943 {
3944  mz_uint64 file_size;
3945  MZ_FILE *pFile;
3946 
3947  if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
3948  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3949 
3950  pFile = MZ_FOPEN(pFilename, "rb");
3951  if (!pFile)
3952  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
3953 
3954  file_size = archive_size;
3955  if (!file_size)
3956  {
3957  if (MZ_FSEEK64(pFile, 0, SEEK_END))
3958  {
3959  MZ_FCLOSE(pFile);
3960  return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
3961  }
3962 
3963  file_size = MZ_FTELL64(pFile);
3964  }
3965 
3966  /* TODO: Better sanity check archive_size and the # of actual remaining bytes */
3967 
3968  if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3969  {
3970  MZ_FCLOSE(pFile);
3971  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3972  }
3973 
3974  if (!mz_zip_reader_init_internal(pZip, flags))
3975  {
3976  MZ_FCLOSE(pFile);
3977  return MZ_FALSE;
3978  }
3979 
3980  pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
3981  pZip->m_pRead = mz_zip_file_read_func;
3982  pZip->m_pIO_opaque = pZip;
3983  pZip->m_pState->m_pFile = pFile;
3984  pZip->m_archive_size = file_size;
3985  pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;
3986 
3987  if (!mz_zip_reader_read_central_dir(pZip, flags))
3988  {
3989  mz_zip_reader_end_internal(pZip, MZ_FALSE);
3990  return MZ_FALSE;
3991  }
3992 
3993  return MZ_TRUE;
3994 }
3995 
3996 mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags)
3997 {
3998  mz_uint64 cur_file_ofs;
3999 
4000  if ((!pZip) || (!pFile))
4001  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
4002 
4003  cur_file_ofs = MZ_FTELL64(pFile);
4004 
4005  if (!archive_size)
4006  {
4007  if (MZ_FSEEK64(pFile, 0, SEEK_END))
4008  return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
4009 
4010  archive_size = MZ_FTELL64(pFile) - cur_file_ofs;
4011 
4012  if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4013  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4014  }
4015 
4016  if (!mz_zip_reader_init_internal(pZip, flags))
4017  return MZ_FALSE;
4018 
4019  pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
4020  pZip->m_pRead = mz_zip_file_read_func;
4021 
4022  pZip->m_pIO_opaque = pZip;
4023  pZip->m_pState->m_pFile = pFile;
4024  pZip->m_archive_size = archive_size;
4025  pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;
4026 
4027  if (!mz_zip_reader_read_central_dir(pZip, flags))
4028  {
4029  mz_zip_reader_end_internal(pZip, MZ_FALSE);
4030  return MZ_FALSE;
4031  }
4032 
4033  return MZ_TRUE;
4034 }
4035 
4036 #endif /* #ifndef MINIZ_NO_STDIO */
4037 
4038 static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
4039 {
4040  if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
4041  return NULL;
4042  return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
4043 }
4044 
4045 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
4046 {
4047  mz_uint m_bit_flag;
4048  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4049  if (!p)
4050  {
4051  mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4052  return MZ_FALSE;
4053  }
4054 
4055  m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4056  return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;
4057 }
4058 
4059 mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)
4060 {
4061  mz_uint bit_flag;
4062  mz_uint method;
4063 
4064  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4065  if (!p)
4066  {
4067  mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4068  return MZ_FALSE;
4069  }
4070 
4071  method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4072  bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4073 
4074  if ((method != 0) && (method != MZ_DEFLATED))
4075  {
4076  mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4077  return MZ_FALSE;
4078  }
4079 
4080  if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION))
4081  {
4082  mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4083  return MZ_FALSE;
4084  }
4085 
4086  if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)
4087  {
4088  mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
4089  return MZ_FALSE;
4090  }
4091 
4092  return MZ_TRUE;
4093 }
4094 
4095 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
4096 {
4097  mz_uint filename_len, attribute_mapping_id, external_attr;
4098  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4099  if (!p)
4100  {
4101  mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4102  return MZ_FALSE;
4103  }
4104 
4105  filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4106  if (filename_len)
4107  {
4108  if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
4109  return MZ_TRUE;
4110  }
4111 
4112  /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */
4113  /* Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. */
4114  /* FIXME: Remove this check? Is it necessary - we already check the filename. */
4115  attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
4116  (void)attribute_mapping_id;
4117 
4118  external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4119  if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
4120  {
4121  return MZ_TRUE;
4122  }
4123 
4124  return MZ_FALSE;
4125 }
4126 
4127 static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_index, const mz_uint8 *pCentral_dir_header, mz_zip_archive_file_stat *pStat, mz_bool *pFound_zip64_extra_data)
4128 {
4129  mz_uint n;
4130  const mz_uint8 *p = pCentral_dir_header;
4131 
4132  if (pFound_zip64_extra_data)
4133  *pFound_zip64_extra_data = MZ_FALSE;
4134 
4135  if ((!p) || (!pStat))
4136  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4137 
4138  /* Extract fields from the central directory record. */
4139  pStat->m_file_index = file_index;
4140  pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
4141  pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
4142  pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
4143  pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4144  pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4145 #ifndef MINIZ_NO_TIME
4146  pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
4147 #endif
4148  pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
4149  pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4150  pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4151  pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
4152  pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4153  pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4154 
4155  /* Copy as much of the filename and comment as possible. */
4156  n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4157  n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
4158  memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
4159  pStat->m_filename[n] = '\0';
4160 
4161  n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4162  n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
4163  pStat->m_comment_size = n;
4164  memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n);
4165  pStat->m_comment[n] = '\0';
4166 
4167  /* Set some flags for convienance */
4168  pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
4169  pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
4170  pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
4171 
4172  /* See if we need to read any zip64 extended information fields. */
4173  /* Confusingly, these zip64 fields can be present even on non-zip64 archives (Debian zip on a huge files from stdin piped to stdout creates them). */
4174  if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX)
4175  {
4176  /* Attempt to find zip64 extended information field in the entry's extra data */
4177  mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4178 
4179  if (extra_size_remaining)
4180  {
4181  const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4182 
4183  do
4184  {
4185  mz_uint32 field_id;
4186  mz_uint32 field_data_size;
4187 
4188  if (extra_size_remaining < (sizeof(mz_uint16) * 2))
4189  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4190 
4191  field_id = MZ_READ_LE16(pExtra_data);
4192  field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4193 
4194  if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
4195  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4196 
4197  if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
4198  {
4199  const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
4200  mz_uint32 field_data_remaining = field_data_size;
4201 
4202  if (pFound_zip64_extra_data)
4203  *pFound_zip64_extra_data = MZ_TRUE;
4204 
4205  if (pStat->m_uncomp_size == MZ_UINT32_MAX)
4206  {
4207  if (field_data_remaining < sizeof(mz_uint64))
4208  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4209 
4210  pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
4211  pField_data += sizeof(mz_uint64);
4212  field_data_remaining -= sizeof(mz_uint64);
4213  }
4214 
4215  if (pStat->m_comp_size == MZ_UINT32_MAX)
4216  {
4217  if (field_data_remaining < sizeof(mz_uint64))
4218  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4219 
4220  pStat->m_comp_size = MZ_READ_LE64(pField_data);
4221  pField_data += sizeof(mz_uint64);
4222  field_data_remaining -= sizeof(mz_uint64);
4223  }
4224 
4225  if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
4226  {
4227  if (field_data_remaining < sizeof(mz_uint64))
4228  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4229 
4230  pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
4231  pField_data += sizeof(mz_uint64);
4232  field_data_remaining -= sizeof(mz_uint64);
4233  }
4234 
4235  break;
4236  }
4237 
4238  pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4239  extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4240  } while (extra_size_remaining);
4241  }
4242  }
4243 
4244  return MZ_TRUE;
4245 }
4246 
4247 static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
4248 {
4249  mz_uint i;
4250  if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
4251  return 0 == memcmp(pA, pB, len);
4252  for (i = 0; i < len; ++i)
4253  if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
4254  return MZ_FALSE;
4255  return MZ_TRUE;
4256 }
4257 
4258 static MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
4259 {
4260  const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
4261  mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4262  mz_uint8 l = 0, r = 0;
4263  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4264  pE = pL + MZ_MIN(l_len, r_len);
4265  while (pL < pE)
4266  {
4267  if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4268  break;
4269  pL++;
4270  pR++;
4271  }
4272  return (pL == pE) ? (int)(l_len - r_len) : (l - r);
4273 }
4274 
4275 static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
4276 {
4277  mz_zip_internal_state *pState = pZip->m_pState;
4278  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4279  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4280  mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4281  const uint32_t size = pZip->m_total_files;
4282  const mz_uint filename_len = (mz_uint)strlen(pFilename);
4283 
4284  if (pIndex)
4285  *pIndex = 0;
4286 
4287  if (size)
4288  {
4289  /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */
4290  /* honestly the major expense here on 32-bit CPU's will still be the filename compare */
4291  mz_int64 l = 0, h = (mz_int64)size - 1;
4292 
4293  while (l <= h)
4294  {
4295  mz_int64 m = l + ((h - l) >> 1);
4296  uint32_t file_index = pIndices[(uint32_t)m];
4297 
4298  int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
4299  if (!comp)
4300  {
4301  if (pIndex)
4302  *pIndex = file_index;
4303  return MZ_TRUE;
4304  }
4305  else if (comp < 0)
4306  l = m + 1;
4307  else
4308  h = m - 1;
4309  }
4310  }
4311 
4312  return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4313 }
4314 
4315 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
4316 {
4317  mz_uint32 index;
4318  if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
4319  return -1;
4320  else
4321  return (int)index;
4322 }
4323 
4324 mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
4325 {
4326  mz_uint file_index;
4327  size_t name_len, comment_len;
4328 
4329  if (pIndex)
4330  *pIndex = 0;
4331 
4332  if ((!pZip) || (!pZip->m_pState) || (!pName))
4333  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4334 
4335  /* See if we can use a binary search */
4336  if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&
4337  (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
4338  ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
4339  {
4340  return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
4341  }
4342 
4343  /* Locate the entry by scanning the entire central directory */
4344  name_len = strlen(pName);
4345  if (name_len > MZ_UINT16_MAX)
4346  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4347 
4348  comment_len = pComment ? strlen(pComment) : 0;
4349  if (comment_len > MZ_UINT16_MAX)
4350  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4351 
4352  for (file_index = 0; file_index < pZip->m_total_files; file_index++)
4353  {
4354  const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
4355  mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4356  const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4357  if (filename_len < name_len)
4358  continue;
4359  if (comment_len)
4360  {
4361  mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4362  const char *pFile_comment = pFilename + filename_len + file_extra_len;
4363  if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
4364  continue;
4365  }
4366  if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
4367  {
4368  int ofs = filename_len - 1;
4369  do
4370  {
4371  if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
4372  break;
4373  } while (--ofs >= 0);
4374  ofs++;
4375  pFilename += ofs;
4376  filename_len -= ofs;
4377  }
4378  if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
4379  {
4380  if (pIndex)
4381  *pIndex = file_index;
4382  return MZ_TRUE;
4383  }
4384  }
4385 
4386  return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4387 }
4388 
4389 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
4390 {
4391  int status = TINFL_STATUS_DONE;
4392  mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
4393  mz_zip_archive_file_stat file_stat;
4394  void *pRead_buf;
4395  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4396  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4397  tinfl_decompressor inflator;
4398 
4399  if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
4400  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4401 
4402  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4403  return MZ_FALSE;
4404 
4405  /* A directory or zero length file */
4406  if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4407  return MZ_TRUE;
4408 
4409  /* Encryption and patch files are not supported. */
4410  if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
4411  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4412 
4413  /* This function only supports decompressing stored and deflate. */
4414  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4415  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4416 
4417  /* Ensure supplied output buffer is large enough. */
4418  needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
4419  if (buf_size < needed_size)
4420  return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);
4421 
4422  /* Read and parse the local directory entry. */
4423  cur_file_ofs = file_stat.m_local_header_ofs;
4424  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4425  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4426 
4427  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4428  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4429 
4430  cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4431  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4432  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4433 
4434  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4435  {
4436  /* The file is stored or the caller has requested the compressed data. */
4437  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
4438  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4439 
4440 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4441  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
4442  {
4443  if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4444  return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4445  }
4446 #endif
4447 
4448  return MZ_TRUE;
4449  }
4450 
4451  /* Decompress the file either directly from memory or from a file input buffer. */
4452  tinfl_init(&inflator);
4453 
4454  if (pZip->m_pState->m_pMem)
4455  {
4456  /* Read directly from the archive in memory. */
4457  pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4458  read_buf_size = read_buf_avail = file_stat.m_comp_size;
4459  comp_remaining = 0;
4460  }
4461  else if (pUser_read_buf)
4462  {
4463  /* Use a user provided read buffer. */
4464  if (!user_read_buf_size)
4465  return MZ_FALSE;
4466  pRead_buf = (mz_uint8 *)pUser_read_buf;
4467  read_buf_size = user_read_buf_size;
4468  read_buf_avail = 0;
4469  comp_remaining = file_stat.m_comp_size;
4470  }
4471  else
4472  {
4473  /* Temporarily allocate a read buffer. */
4474  read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4475  if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
4476  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4477 
4478  if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4479  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4480 
4481  read_buf_avail = 0;
4482  comp_remaining = file_stat.m_comp_size;
4483  }
4484 
4485  do
4486  {
4487  /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */
4488  size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
4489  if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4490  {
4491  read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4492  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4493  {
4494  status = TINFL_STATUS_FAILED;
4495  mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4496  break;
4497  }
4498  cur_file_ofs += read_buf_avail;
4499  comp_remaining -= read_buf_avail;
4500  read_buf_ofs = 0;
4501  }
4502  in_buf_size = (size_t)read_buf_avail;
4503  status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
4504  read_buf_avail -= in_buf_size;
4505  read_buf_ofs += in_buf_size;
4506  out_buf_ofs += out_buf_size;
4507  } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
4508 
4509  if (status == TINFL_STATUS_DONE)
4510  {
4511  /* Make sure the entire file was decompressed, and check its CRC. */
4512  if (out_buf_ofs != file_stat.m_uncomp_size)
4513  {
4514  mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4515  status = TINFL_STATUS_FAILED;
4516  }
4517 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4518  else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4519  {
4520  mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4521  status = TINFL_STATUS_FAILED;
4522  }
4523 #endif
4524  }
4525 
4526  if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
4527  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4528 
4529  return status == TINFL_STATUS_DONE;
4530 }
4531 
4532 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
4533 {
4534  mz_uint32 file_index;
4535  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4536  return MZ_FALSE;
4537  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
4538 }
4539 
4540 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
4541 {
4542  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
4543 }
4544 
4545 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
4546 {
4547  return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
4548 }
4549 
4550 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
4551 {
4552  mz_uint64 comp_size, uncomp_size, alloc_size;
4553  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4554  void *pBuf;
4555 
4556  if (pSize)
4557  *pSize = 0;
4558 
4559  if (!p)
4560  {
4561  mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4562  return NULL;
4563  }
4564 
4565  comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4566  uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4567 
4568  alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
4569  if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
4570  {
4571  mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4572  return NULL;
4573  }
4574 
4575  if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
4576  {
4577  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4578  return NULL;
4579  }
4580 
4581  if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
4582  {
4583  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4584  return NULL;
4585  }
4586 
4587  if (pSize)
4588  *pSize = (size_t)alloc_size;
4589  return pBuf;
4590 }
4591 
4592 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
4593 {
4594  mz_uint32 file_index;
4595  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4596  {
4597  if (pSize)
4598  *pSize = 0;
4599  return MZ_FALSE;
4600  }
4601  return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
4602 }
4603 
4604 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
4605 {
4606  int status = TINFL_STATUS_DONE;
4607  mz_uint file_crc32 = MZ_CRC32_INIT;
4608  mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
4609  mz_zip_archive_file_stat file_stat;
4610  void *pRead_buf = NULL;
4611  void *pWrite_buf = NULL;
4612  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4613  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4614 
4615  if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))
4616  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4617 
4618  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4619  return MZ_FALSE;
4620 
4621  /* A directory or zero length file */
4622  if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4623  return MZ_TRUE;
4624 
4625  /* Encryption and patch files are not supported. */
4626  if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
4627  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4628 
4629  /* This function only supports decompressing stored and deflate. */
4630  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4631  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4632 
4633  /* Read and do some minimal validation of the local directory entry (this doesn't crack the zip64 stuff, which we already have from the central dir) */
4634  cur_file_ofs = file_stat.m_local_header_ofs;
4635  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4636  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4637 
4638  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4639  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4640 
4641  cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4642  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4643  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4644 
4645  /* Decompress the file either directly from memory or from a file input buffer. */
4646  if (pZip->m_pState->m_pMem)
4647  {
4648  pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4649  read_buf_size = read_buf_avail = file_stat.m_comp_size;
4650  comp_remaining = 0;
4651  }
4652  else
4653  {
4654  read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4655  if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4656  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4657 
4658  read_buf_avail = 0;
4659  comp_remaining = file_stat.m_comp_size;
4660  }
4661 
4662  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4663  {
4664  /* The file is stored or the caller has requested the compressed data. */
4665  if (pZip->m_pState->m_pMem)
4666  {
4667  if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX))
4668  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4669 
4670  if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
4671  {
4672  mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4673  status = TINFL_STATUS_FAILED;
4674  }
4675  else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4676  {
4677 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4678  file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
4679 #endif
4680  }
4681 
4682  cur_file_ofs += file_stat.m_comp_size;
4683  out_buf_ofs += file_stat.m_comp_size;
4684  comp_remaining = 0;
4685  }
4686  else
4687  {
4688  while (comp_remaining)
4689  {
4690  read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4691  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4692  {
4693  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4694  status = TINFL_STATUS_FAILED;
4695  break;
4696  }
4697 
4698 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4699  if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4700  {
4701  file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
4702  }
4703 #endif
4704 
4705  if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4706  {
4707  mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4708  status = TINFL_STATUS_FAILED;
4709  break;
4710  }
4711 
4712  cur_file_ofs += read_buf_avail;
4713  out_buf_ofs += read_buf_avail;
4714  comp_remaining -= read_buf_avail;
4715  }
4716  }
4717  }
4718  else
4719  {
4720  tinfl_decompressor inflator;
4721  tinfl_init(&inflator);
4722 
4723  if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4724  {
4725  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4726  status = TINFL_STATUS_FAILED;
4727  }
4728  else
4729  {
4730  do
4731  {
4732  mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4733  size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4734  if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4735  {
4736  read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4737  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4738  {
4739  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4740  status = TINFL_STATUS_FAILED;
4741  break;
4742  }
4743  cur_file_ofs += read_buf_avail;
4744  comp_remaining -= read_buf_avail;
4745  read_buf_ofs = 0;
4746  }
4747 
4748  in_buf_size = (size_t)read_buf_avail;
4749  status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
4750  read_buf_avail -= in_buf_size;
4751  read_buf_ofs += in_buf_size;
4752 
4753  if (out_buf_size)
4754  {
4755  if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
4756  {
4757  mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4758  status = TINFL_STATUS_FAILED;
4759  break;
4760  }
4761 
4762 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4763  file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
4764 #endif
4765  if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
4766  {
4767  mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4768  status = TINFL_STATUS_FAILED;
4769  break;
4770  }
4771  }
4772  } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
4773  }
4774  }
4775 
4776  if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
4777  {
4778  /* Make sure the entire file was decompressed, and check its CRC. */
4779  if (out_buf_ofs != file_stat.m_uncomp_size)
4780  {
4781  mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4782  status = TINFL_STATUS_FAILED;
4783  }
4784 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4785  else if (file_crc32 != file_stat.m_crc32)
4786  {
4787  mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4788  status = TINFL_STATUS_FAILED;
4789  }
4790 #endif
4791  }
4792 
4793  if (!pZip->m_pState->m_pMem)
4794  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4795 
4796  if (pWrite_buf)
4797  pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
4798 
4799  return status == TINFL_STATUS_DONE;
4800 }
4801 
4802 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
4803 {
4804  mz_uint32 file_index;
4805  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4806  return MZ_FALSE;
4807 
4808  return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
4809 }
4810 
4811 mz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
4812 {
4814  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4815  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4816 
4817  /* Argument sanity check */
4818  if ((!pZip) || (!pZip->m_pState))
4819  return NULL;
4820 
4821  /* Allocate an iterator status structure */
4822  pState = (mz_zip_reader_extract_iter_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_reader_extract_iter_state));
4823  if (!pState)
4824  {
4825  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4826  return NULL;
4827  }
4828 
4829  /* Fetch file details */
4830  if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat))
4831  {
4832  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4833  return NULL;
4834  }
4835 
4836  /* Encryption and patch files are not supported. */
4837  if (pState->file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
4838  {
4839  mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4840  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4841  return NULL;
4842  }
4843 
4844  /* This function only supports decompressing stored and deflate. */
4845  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (pState->file_stat.m_method != 0) && (pState->file_stat.m_method != MZ_DEFLATED))
4846  {
4847  mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4848  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4849  return NULL;
4850  }
4851 
4852  /* Init state - save args */
4853  pState->pZip = pZip;
4854  pState->flags = flags;
4855 
4856  /* Init state - reset variables to defaults */
4857  pState->status = TINFL_STATUS_DONE;
4858 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4859  pState->file_crc32 = MZ_CRC32_INIT;
4860 #endif
4861  pState->read_buf_ofs = 0;
4862  pState->out_buf_ofs = 0;
4863  pState->pRead_buf = NULL;
4864  pState->pWrite_buf = NULL;
4865  pState->out_blk_remain = 0;
4866 
4867  /* Read and parse the local directory entry. */
4868  pState->cur_file_ofs = pState->file_stat.m_local_header_ofs;
4869  if (pZip->m_pRead(pZip->m_pIO_opaque, pState->cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4870  {
4871  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4872  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4873  return NULL;
4874  }
4875 
4876  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4877  {
4878  mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4879  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4880  return NULL;
4881  }
4882 
4883  pState->cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
4884  if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > pZip->m_archive_size)
4885  {
4886  mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4887  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4888  return NULL;
4889  }
4890 
4891  /* Decompress the file either directly from memory or from a file input buffer. */
4892  if (pZip->m_pState->m_pMem)
4893  {
4894  pState->pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs;
4895  pState->read_buf_size = pState->read_buf_avail = pState->file_stat.m_comp_size;
4896  pState->comp_remaining = pState->file_stat.m_comp_size;
4897  }
4898  else
4899  {
4900  if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
4901  {
4902  /* Decompression required, therefore intermediate read buffer required */
4903  pState->read_buf_size = MZ_MIN(pState->file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
4904  if (NULL == (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)pState->read_buf_size)))
4905  {
4906  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4907  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4908  return NULL;
4909  }
4910  }
4911  else
4912  {
4913  /* Decompression not required - we will be reading directly into user buffer, no temp buf required */
4914  pState->read_buf_size = 0;
4915  }
4916  pState->read_buf_avail = 0;
4917  pState->comp_remaining = pState->file_stat.m_comp_size;
4918  }
4919 
4920  if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
4921  {
4922  /* Decompression required, init decompressor */
4923  tinfl_init( &pState->inflator );
4924 
4925  /* Allocate write buffer */
4926  if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4927  {
4928  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4929  if (pState->pRead_buf)
4930  pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf);
4931  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4932  return NULL;
4933  }
4934  }
4935 
4936  return pState;
4937 }
4938 
4939 mz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
4940 {
4941  mz_uint32 file_index;
4942 
4943  /* Locate file index by name */
4944  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4945  return NULL;
4946 
4947  /* Construct iterator */
4948  return mz_zip_reader_extract_iter_new(pZip, file_index, flags);
4949 }
4950 
4951 size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size)
4952 {
4953  size_t copied_to_caller = 0;
4954 
4955  /* Argument sanity check */
4956  if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf))
4957  return 0;
4958 
4959  if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))
4960  {
4961  /* The file is stored or the caller has requested the compressed data, calc amount to return. */
4962  copied_to_caller = (size_t)MZ_MIN( buf_size, pState->comp_remaining );
4963 
4964  /* Zip is in memory....or requires reading from a file? */
4965  if (pState->pZip->m_pState->m_pMem)
4966  {
4967  /* Copy data to caller's buffer */
4968  memcpy( pvBuf, pState->pRead_buf, copied_to_caller );
4969  pState->pRead_buf = ((mz_uint8*)pState->pRead_buf) + copied_to_caller;
4970  }
4971  else
4972  {
4973  /* Read directly into caller's buffer */
4974  if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, copied_to_caller) != copied_to_caller)
4975  {
4976  /* Failed to read all that was asked for, flag failure and alert user */
4977  mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
4978  pState->status = TINFL_STATUS_FAILED;
4979  copied_to_caller = 0;
4980  }
4981  }
4982 
4983 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4984  /* Compute CRC if not returning compressed data only */
4985  if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4986  pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, (const mz_uint8 *)pvBuf, copied_to_caller);
4987 #endif
4988 
4989  /* Advance offsets, dec counters */
4990  pState->cur_file_ofs += copied_to_caller;
4991  pState->out_buf_ofs += copied_to_caller;
4992  pState->comp_remaining -= copied_to_caller;
4993  }
4994  else
4995  {
4996  do
4997  {
4998  /* Calc ptr to write buffer - given current output pos and block size */
4999  mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pState->pWrite_buf + (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5000 
5001  /* Calc max output size - given current output pos and block size */
5002  size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5003 
5004  if (!pState->out_blk_remain)
5005  {
5006  /* Read more data from file if none available (and reading from file) */
5007  if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem))
5008  {
5009  /* Calc read size */
5010  pState->read_buf_avail = MZ_MIN(pState->read_buf_size, pState->comp_remaining);
5011  if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pState->pRead_buf, (size_t)pState->read_buf_avail) != pState->read_buf_avail)
5012  {
5013  mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
5014  pState->status = TINFL_STATUS_FAILED;
5015  break;
5016  }
5017 
5018  /* Advance offsets, dec counters */
5019  pState->cur_file_ofs += pState->read_buf_avail;
5020  pState->comp_remaining -= pState->read_buf_avail;
5021  pState->read_buf_ofs = 0;
5022  }
5023 
5024  /* Perform decompression */
5025  in_buf_size = (size_t)pState->read_buf_avail;
5026  pState->status = tinfl_decompress(&pState->inflator, (const mz_uint8 *)pState->pRead_buf + pState->read_buf_ofs, &in_buf_size, (mz_uint8 *)pState->pWrite_buf, pWrite_buf_cur, &out_buf_size, pState->comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
5027  pState->read_buf_avail -= in_buf_size;
5028  pState->read_buf_ofs += in_buf_size;
5029 
5030  /* Update current output block size remaining */
5031  pState->out_blk_remain = out_buf_size;
5032  }
5033 
5034  if (pState->out_blk_remain)
5035  {
5036  /* Calc amount to return. */
5037  size_t to_copy = MZ_MIN( (buf_size - copied_to_caller), pState->out_blk_remain );
5038 
5039  /* Copy data to caller's buffer */
5040  memcpy( (uint8_t*)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy );
5041 
5042 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5043  /* Perform CRC */
5044  pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy);
5045 #endif
5046 
5047  /* Decrement data consumed from block */
5048  pState->out_blk_remain -= to_copy;
5049 
5050  /* Inc output offset, while performing sanity check */
5051  if ((pState->out_buf_ofs += to_copy) > pState->file_stat.m_uncomp_size)
5052  {
5053  mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5054  pState->status = TINFL_STATUS_FAILED;
5055  break;
5056  }
5057 
5058  /* Increment counter of data copied to caller */
5059  copied_to_caller += to_copy;
5060  }
5061  } while ( (copied_to_caller < buf_size) && ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)) );
5062  }
5063 
5064  /* Return how many bytes were copied into user buffer */
5065  return copied_to_caller;
5066 }
5067 
5068 mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState)
5069 {
5070  int status;
5071 
5072  /* Argument sanity check */
5073  if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState))
5074  return MZ_FALSE;
5075 
5076  /* Was decompression completed and requested? */
5077  if ((pState->status == TINFL_STATUS_DONE) && (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
5078  {
5079  /* Make sure the entire file was decompressed, and check its CRC. */
5080  if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size)
5081  {
5082  mz_zip_set_error(pState->pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
5083  pState->status = TINFL_STATUS_FAILED;
5084  }
5085 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5086  else if (pState->file_crc32 != pState->file_stat.m_crc32)
5087  {
5088  mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5089  pState->status = TINFL_STATUS_FAILED;
5090  }
5091 #endif
5092  }
5093 
5094  /* Free buffers */
5095  if (!pState->pZip->m_pState->m_pMem)
5096  pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf);
5097  if (pState->pWrite_buf)
5098  pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf);
5099 
5100  /* Save status */
5101  status = pState->status;
5102 
5103  /* Free context */
5104  pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState);
5105 
5106  return status == TINFL_STATUS_DONE;
5107 }
5108 
5109 #ifndef MINIZ_NO_STDIO
5110 static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
5111 {
5112  (void)ofs;
5113 
5114  return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5115 }
5116 
5117 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
5118 {
5119  mz_bool status;
5120  mz_zip_archive_file_stat file_stat;
5121  MZ_FILE *pFile;
5122 
5123  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5124  return MZ_FALSE;
5125 
5126  if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5127  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5128 
5129  pFile = MZ_FOPEN(pDst_filename, "wb");
5130  if (!pFile)
5131  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5132 
5133  status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5134 
5135  if (MZ_FCLOSE(pFile) == EOF)
5136  {
5137  if (status)
5138  mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5139 
5140  status = MZ_FALSE;
5141  }
5142 
5143 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
5144  if (status)
5145  mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5146 #endif
5147 
5148  return status;
5149 }
5150 
5151 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
5152 {
5153  mz_uint32 file_index;
5154  if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5155  return MZ_FALSE;
5156 
5157  return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5158 }
5159 
5160 mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags)
5161 {
5162  mz_zip_archive_file_stat file_stat;
5163 
5164  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5165  return MZ_FALSE;
5166 
5167  if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5168  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5169 
5170  return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5171 }
5172 
5173 mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
5174 {
5175  mz_uint32 file_index;
5176  if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5177  return MZ_FALSE;
5178 
5179  return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
5180 }
5181 #endif /* #ifndef MINIZ_NO_STDIO */
5182 
5183 static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5184 {
5185  mz_uint32 *p = (mz_uint32 *)pOpaque;
5186  (void)file_ofs;
5187  *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n);
5188  return n;
5189 }
5190 
5191 mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
5192 {
5193  mz_zip_archive_file_stat file_stat;
5194  mz_zip_internal_state *pState;
5195  const mz_uint8 *pCentral_dir_header;
5196  mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;
5197  mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
5198  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
5199  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5200  mz_uint64 local_header_ofs = 0;
5201  mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32;
5202  mz_uint64 local_header_comp_size, local_header_uncomp_size;
5203  mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;
5204  mz_bool has_data_descriptor;
5205  mz_uint32 local_header_bit_flags;
5206 
5207  mz_zip_array file_data_array;
5208  mz_zip_array_init(&file_data_array, 1);
5209 
5210  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5211  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5212 
5213  if (file_index > pZip->m_total_files)
5214  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5215 
5216  pState = pZip->m_pState;
5217 
5218  pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);
5219 
5220  if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir))
5221  return MZ_FALSE;
5222 
5223  /* A directory or zero length file */
5224  if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size))
5225  return MZ_TRUE;
5226 
5227  /* Encryption and patch files are not supported. */
5228  if (file_stat.m_is_encrypted)
5229  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
5230 
5231  /* This function only supports stored and deflate. */
5232  if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
5233  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
5234 
5235  if (!file_stat.m_is_supported)
5236  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5237 
5238  /* Read and parse the local directory entry. */
5239  local_header_ofs = file_stat.m_local_header_ofs;
5240  if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5241  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5242 
5243  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5244  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5245 
5246  local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
5247  local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5248  local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
5249  local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
5250  local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);
5251  local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
5252  has_data_descriptor = (local_header_bit_flags & 8) != 0;
5253 
5254  if (local_header_filename_len != strlen(file_stat.m_filename))
5255  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5256 
5257  if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size) > pZip->m_archive_size)
5258  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5259 
5260  if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE))
5261  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5262 
5263  if (local_header_filename_len)
5264  {
5265  if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, file_data_array.m_p, local_header_filename_len) != local_header_filename_len)
5266  {
5267  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5268  goto handle_failure;
5269  }
5270 
5271  /* I've seen 1 archive that had the same pathname, but used backslashes in the local dir and forward slashes in the central dir. Do we care about this? For now, this case will fail validation. */
5272  if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0)
5273  {
5274  mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5275  goto handle_failure;
5276  }
5277  }
5278 
5279  if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
5280  {
5281  mz_uint32 extra_size_remaining = local_header_extra_len;
5282  const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p;
5283 
5284  if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
5285  {
5286  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5287  goto handle_failure;
5288  }
5289 
5290  do
5291  {
5292  mz_uint32 field_id, field_data_size, field_total_size;
5293 
5294  if (extra_size_remaining < (sizeof(mz_uint16) * 2))
5295  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5296 
5297  field_id = MZ_READ_LE16(pExtra_data);
5298  field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
5299  field_total_size = field_data_size + sizeof(mz_uint16) * 2;
5300 
5301  if (field_total_size > extra_size_remaining)
5302  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5303 
5304  if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
5305  {
5306  const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
5307 
5308  if (field_data_size < sizeof(mz_uint64) * 2)
5309  {
5310  mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5311  goto handle_failure;
5312  }
5313 
5314  local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
5315  local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64));
5316 
5317  found_zip64_ext_data_in_ldir = MZ_TRUE;
5318  break;
5319  }
5320 
5321  pExtra_data += field_total_size;
5322  extra_size_remaining -= field_total_size;
5323  } while (extra_size_remaining);
5324  }
5325 
5326  /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */
5327  /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */
5328  if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32))
5329  {
5330  mz_uint8 descriptor_buf[32];
5331  mz_bool has_id;
5332  const mz_uint8 *pSrc;
5333  mz_uint32 file_crc32;
5334  mz_uint64 comp_size = 0, uncomp_size = 0;
5335 
5336  mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;
5337 
5338  if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size, descriptor_buf, sizeof(mz_uint32) * num_descriptor_uint32s) != (sizeof(mz_uint32) * num_descriptor_uint32s))
5339  {
5340  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5341  goto handle_failure;
5342  }
5343 
5344  has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
5345  pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf;
5346 
5347  file_crc32 = MZ_READ_LE32(pSrc);
5348 
5349  if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir))
5350  {
5351  comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32));
5352  uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64));
5353  }
5354  else
5355  {
5356  comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32));
5357  uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32));
5358  }
5359 
5360  if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size))
5361  {
5362  mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5363  goto handle_failure;
5364  }
5365  }
5366  else
5367  {
5368  if ((local_header_crc32 != file_stat.m_crc32) || (local_header_comp_size != file_stat.m_comp_size) || (local_header_uncomp_size != file_stat.m_uncomp_size))
5369  {
5370  mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5371  goto handle_failure;
5372  }
5373  }
5374 
5375  mz_zip_array_clear(pZip, &file_data_array);
5376 
5377  if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0)
5378  {
5379  if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))
5380  return MZ_FALSE;
5381 
5382  /* 1 more check to be sure, although the extract checks too. */
5383  if (uncomp_crc32 != file_stat.m_crc32)
5384  {
5385  mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5386  return MZ_FALSE;
5387  }
5388  }
5389 
5390  return MZ_TRUE;
5391 
5392 handle_failure:
5393  mz_zip_array_clear(pZip, &file_data_array);
5394  return MZ_FALSE;
5395 }
5396 
5397 mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags)
5398 {
5399  mz_zip_internal_state *pState;
5400  uint32_t i;
5401 
5402  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5403  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5404 
5405  pState = pZip->m_pState;
5406 
5407  /* Basic sanity checks */
5408  if (!pState->m_zip64)
5409  {
5410  if (pZip->m_total_files > MZ_UINT16_MAX)
5411  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5412 
5413  if (pZip->m_archive_size > MZ_UINT32_MAX)
5414  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5415  }
5416  else
5417  {
5418  if (pZip->m_total_files >= MZ_UINT32_MAX)
5419  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5420 
5421  if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
5422  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5423  }
5424 
5425  for (i = 0; i < pZip->m_total_files; i++)
5426  {
5427  if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags)
5428  {
5429  mz_uint32 found_index;
5431 
5432  if (!mz_zip_reader_file_stat(pZip, i, &stat))
5433  return MZ_FALSE;
5434 
5435  if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index))
5436  return MZ_FALSE;
5437 
5438  /* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */
5439  if (found_index != i)
5440  return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5441  }
5442 
5443  if (!mz_zip_validate_file(pZip, i, flags))
5444  return MZ_FALSE;
5445  }
5446 
5447  return MZ_TRUE;
5448 }
5449 
5450 mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)
5451 {
5452  mz_bool success = MZ_TRUE;
5453  mz_zip_archive zip;
5454  mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5455 
5456  if ((!pMem) || (!size))
5457  {
5458  if (pErr)
5459  *pErr = MZ_ZIP_INVALID_PARAMETER;
5460  return MZ_FALSE;
5461  }
5462 
5463  mz_zip_zero_struct(&zip);
5464 
5465  if (!mz_zip_reader_init_mem(&zip, pMem, size, flags))
5466  {
5467  if (pErr)
5468  *pErr = zip.m_last_error;
5469  return MZ_FALSE;
5470  }
5471 
5472  if (!mz_zip_validate_archive(&zip, flags))
5473  {
5474  actual_err = zip.m_last_error;
5475  success = MZ_FALSE;
5476  }
5477 
5478  if (!mz_zip_reader_end_internal(&zip, success))
5479  {
5480  if (!actual_err)
5481  actual_err = zip.m_last_error;
5482  success = MZ_FALSE;
5483  }
5484 
5485  if (pErr)
5486  *pErr = actual_err;
5487 
5488  return success;
5489 }
5490 
5491 #ifndef MINIZ_NO_STDIO
5492 mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr)
5493 {
5494  mz_bool success = MZ_TRUE;
5495  mz_zip_archive zip;
5496  mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5497 
5498  if (!pFilename)
5499  {
5500  if (pErr)
5501  *pErr = MZ_ZIP_INVALID_PARAMETER;
5502  return MZ_FALSE;
5503  }
5504 
5505  mz_zip_zero_struct(&zip);
5506 
5507  if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0))
5508  {
5509  if (pErr)
5510  *pErr = zip.m_last_error;
5511  return MZ_FALSE;
5512  }
5513 
5514  if (!mz_zip_validate_archive(&zip, flags))
5515  {
5516  actual_err = zip.m_last_error;
5517  success = MZ_FALSE;
5518  }
5519 
5520  if (!mz_zip_reader_end_internal(&zip, success))
5521  {
5522  if (!actual_err)
5523  actual_err = zip.m_last_error;
5524  success = MZ_FALSE;
5525  }
5526 
5527  if (pErr)
5528  *pErr = actual_err;
5529 
5530  return success;
5531 }
5532 #endif /* #ifndef MINIZ_NO_STDIO */
5533 
5534 /* ------------------- .ZIP archive writing */
5535 
5536 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5537 
5538 static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v)
5539 {
5540  p[0] = (mz_uint8)v;
5541  p[1] = (mz_uint8)(v >> 8);
5542 }
5543 static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v)
5544 {
5545  p[0] = (mz_uint8)v;
5546  p[1] = (mz_uint8)(v >> 8);
5547  p[2] = (mz_uint8)(v >> 16);
5548  p[3] = (mz_uint8)(v >> 24);
5549 }
5550 static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v)
5551 {
5552  mz_write_le32(p, (mz_uint32)v);
5553  mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32));
5554 }
5555 
5556 #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5557 #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5558 #define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v))
5559 
5560 static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5561 {
5562  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5563  mz_zip_internal_state *pState = pZip->m_pState;
5564  mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5565 
5566  if (!n)
5567  return 0;
5568 
5569  /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */
5570  if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))
5571  {
5572  mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5573  return 0;
5574  }
5575 
5576  if (new_size > pState->m_mem_capacity)
5577  {
5578  void *pNew_block;
5579  size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5580 
5581  while (new_capacity < new_size)
5582  new_capacity *= 2;
5583 
5584  if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5585  {
5586  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5587  return 0;
5588  }
5589 
5590  pState->m_pMem = pNew_block;
5591  pState->m_mem_capacity = new_capacity;
5592  }
5593  memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5594  pState->m_mem_size = (size_t)new_size;
5595  return n;
5596 }
5597 
5598 static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
5599 {
5600  mz_zip_internal_state *pState;
5601  mz_bool status = MZ_TRUE;
5602 
5603  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
5604  {
5605  if (set_last_error)
5606  mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5607  return MZ_FALSE;
5608  }
5609 
5610  pState = pZip->m_pState;
5611  pZip->m_pState = NULL;
5612  mz_zip_array_clear(pZip, &pState->m_central_dir);
5613  mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5614  mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5615 
5616 #ifndef MINIZ_NO_STDIO
5617  if (pState->m_pFile)
5618  {
5619  if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5620  {
5621  if (MZ_FCLOSE(pState->m_pFile) == EOF)
5622  {
5623  if (set_last_error)
5624  mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5625  status = MZ_FALSE;
5626  }
5627  }
5628 
5629  pState->m_pFile = NULL;
5630  }
5631 #endif /* #ifndef MINIZ_NO_STDIO */
5632 
5633  if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
5634  {
5635  pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
5636  pState->m_pMem = NULL;
5637  }
5638 
5639  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5640  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5641  return status;
5642 }
5643 
5644 mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags)
5645 {
5646  mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;
5647 
5648  if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5649  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5650 
5651  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5652  {
5653  if (!pZip->m_pRead)
5654  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5655  }
5656 
5657  if (pZip->m_file_offset_alignment)
5658  {
5659  /* Ensure user specified file offset alignment is a power of 2. */
5660  if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5661  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5662  }
5663 
5664  if (!pZip->m_pAlloc)
5665  pZip->m_pAlloc = miniz_def_alloc_func;
5666  if (!pZip->m_pFree)
5667  pZip->m_pFree = miniz_def_free_func;
5668  if (!pZip->m_pRealloc)
5669  pZip->m_pRealloc = miniz_def_realloc_func;
5670 
5671  pZip->m_archive_size = existing_size;
5672  pZip->m_central_directory_file_ofs = 0;
5673  pZip->m_total_files = 0;
5674 
5675  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5676  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5677 
5678  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5679 
5680  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
5681  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
5682  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
5683 
5684  pZip->m_pState->m_zip64 = zip64;
5685  pZip->m_pState->m_zip64_has_extended_info_fields = zip64;
5686 
5687  pZip->m_zip_type = MZ_ZIP_TYPE_USER;
5688  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5689 
5690  return MZ_TRUE;
5691 }
5692 
5693 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
5694 {
5695  return mz_zip_writer_init_v2(pZip, existing_size, 0);
5696 }
5697 
5698 mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags)
5699 {
5700  pZip->m_pWrite = mz_zip_heap_write_func;
5701  pZip->m_pNeeds_keepalive = NULL;
5702 
5703  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5704  pZip->m_pRead = mz_zip_mem_read_func;
5705 
5706  pZip->m_pIO_opaque = pZip;
5707 
5708  if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5709  return MZ_FALSE;
5710 
5711  pZip->m_zip_type = MZ_ZIP_TYPE_HEAP;
5712 
5713  if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
5714  {
5715  if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
5716  {
5717  mz_zip_writer_end_internal(pZip, MZ_FALSE);
5718  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5719  }
5720  pZip->m_pState->m_mem_capacity = initial_allocation_size;
5721  }
5722 
5723  return MZ_TRUE;
5724 }
5725 
5726 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
5727 {
5728  return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0);
5729 }
5730 
5731 #ifndef MINIZ_NO_STDIO
5732 static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5733 {
5734  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5735  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5736 
5737  file_ofs += pZip->m_pState->m_file_archive_start_ofs;
5738 
5739  if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5740  {
5741  mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
5742  return 0;
5743  }
5744 
5745  return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5746 }
5747 
5748 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
5749 {
5750  return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0);
5751 }
5752 
5753 mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags)
5754 {
5755  MZ_FILE *pFile;
5756 
5757  pZip->m_pWrite = mz_zip_file_write_func;
5758  pZip->m_pNeeds_keepalive = NULL;
5759 
5760  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5761  pZip->m_pRead = mz_zip_file_read_func;
5762 
5763  pZip->m_pIO_opaque = pZip;
5764 
5765  if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5766  return MZ_FALSE;
5767 
5768  if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb")))
5769  {
5770  mz_zip_writer_end(pZip);
5771  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5772  }
5773 
5774  pZip->m_pState->m_pFile = pFile;
5775  pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
5776 
5777  if (size_to_reserve_at_beginning)
5778  {
5779  mz_uint64 cur_ofs = 0;
5780  char buf[4096];
5781 
5782  MZ_CLEAR_OBJ(buf);
5783 
5784  do
5785  {
5786  size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5787  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
5788  {
5789  mz_zip_writer_end(pZip);
5790  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
5791  }
5792  cur_ofs += n;
5793  size_to_reserve_at_beginning -= n;
5794  } while (size_to_reserve_at_beginning);
5795  }
5796 
5797  return MZ_TRUE;
5798 }
5799 
5800 mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)
5801 {
5802  pZip->m_pWrite = mz_zip_file_write_func;
5803  pZip->m_pNeeds_keepalive = NULL;
5804 
5805  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5806  pZip->m_pRead = mz_zip_file_read_func;
5807 
5808  pZip->m_pIO_opaque = pZip;
5809 
5810  if (!mz_zip_writer_init_v2(pZip, 0, flags))
5811  return MZ_FALSE;
5812 
5813  pZip->m_pState->m_pFile = pFile;
5814  pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5815  pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
5816 
5817  return MZ_TRUE;
5818 }
5819 #endif /* #ifndef MINIZ_NO_STDIO */
5820 
5821 mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
5822 {
5823  mz_zip_internal_state *pState;
5824 
5825  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5826  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5827 
5828  if (flags & MZ_ZIP_FLAG_WRITE_ZIP64)
5829  {
5830  /* We don't support converting a non-zip64 file to zip64 - this seems like more trouble than it's worth. (What about the existing 32-bit data descriptors that could follow the compressed data?) */
5831  if (!pZip->m_pState->m_zip64)
5832  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5833  }
5834 
5835  /* No sense in trying to write to an archive that's already at the support max size */
5836  if (pZip->m_pState->m_zip64)
5837  {
5838  if (pZip->m_total_files == MZ_UINT32_MAX)
5839  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5840  }
5841  else
5842  {
5843  if (pZip->m_total_files == MZ_UINT16_MAX)
5844  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5845 
5846  if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)
5847  return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5848  }
5849 
5850  pState = pZip->m_pState;
5851 
5852  if (pState->m_pFile)
5853  {
5854 #ifdef MINIZ_NO_STDIO
5855  (void)pFilename;
5856  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5857 #else
5858  if (pZip->m_pIO_opaque != pZip)
5859  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5860 
5861  if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5862  {
5863  if (!pFilename)
5864  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5865 
5866  /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */
5867  if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
5868  {
5869  /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */
5870  mz_zip_reader_end_internal(pZip, MZ_FALSE);
5871  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5872  }
5873  }
5874 
5875  pZip->m_pWrite = mz_zip_file_write_func;
5876  pZip->m_pNeeds_keepalive = NULL;
5877 #endif /* #ifdef MINIZ_NO_STDIO */
5878  }
5879  else if (pState->m_pMem)
5880  {
5881  /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */
5882  if (pZip->m_pIO_opaque != pZip)
5883  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5884 
5885  pState->m_mem_capacity = pState->m_mem_size;
5886  pZip->m_pWrite = mz_zip_heap_write_func;
5887  pZip->m_pNeeds_keepalive = NULL;
5888  }
5889  /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */
5890  else if (!pZip->m_pWrite)
5891  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5892 
5893  /* Start writing new files at the archive's current central directory location. */
5894  /* TODO: We could add a flag that lets the user start writing immediately AFTER the existing central dir - this would be safer. */
5895  pZip->m_archive_size = pZip->m_central_directory_file_ofs;
5896  pZip->m_central_directory_file_ofs = 0;
5897 
5898  /* Clear the sorted central dir offsets, they aren't useful or maintained now. */
5899  /* Even though we're now in write mode, files can still be extracted and verified, but file locates will be slow. */
5900  /* TODO: We could easily maintain the sorted central directory offsets. */
5901  mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets);
5902 
5903  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5904 
5905  return MZ_TRUE;
5906 }
5907 
5908 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
5909 {
5910  return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);
5911 }
5912 
5913 /* TODO: pArchive_name is a terrible name here! */
5914 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
5915 {
5916  return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
5917 }
5918 
5919 typedef struct
5920 {
5921  mz_zip_archive *m_pZip;
5922  mz_uint64 m_cur_archive_file_ofs;
5923  mz_uint64 m_comp_size;
5925 
5926 static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser)
5927 {
5929  if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
5930  return MZ_FALSE;
5931 
5932  pState->m_cur_archive_file_ofs += len;
5933  pState->m_comp_size += len;
5934  return MZ_TRUE;
5935 }
5936 
5937 #define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)
5938 #define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3)
5939 static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, mz_uint64 *pLocal_header_ofs)
5940 {
5941  mz_uint8 *pDst = pBuf;
5942  mz_uint32 field_size = 0;
5943 
5944  MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
5945  MZ_WRITE_LE16(pDst + 2, 0);
5946  pDst += sizeof(mz_uint16) * 2;
5947 
5948  if (pUncomp_size)
5949  {
5950  MZ_WRITE_LE64(pDst, *pUncomp_size);
5951  pDst += sizeof(mz_uint64);
5952  field_size += sizeof(mz_uint64);
5953  }
5954 
5955  if (pComp_size)
5956  {
5957  MZ_WRITE_LE64(pDst, *pComp_size);
5958  pDst += sizeof(mz_uint64);
5959  field_size += sizeof(mz_uint64);
5960  }
5961 
5962  if (pLocal_header_ofs)
5963  {
5964  MZ_WRITE_LE64(pDst, *pLocal_header_ofs);
5965  pDst += sizeof(mz_uint64);
5966  field_size += sizeof(mz_uint64);
5967  }
5968 
5969  MZ_WRITE_LE16(pBuf + 2, field_size);
5970 
5971  return (mz_uint32)(pDst - pBuf);
5972 }
5973 
5974 static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
5975 {
5976  (void)pZip;
5977  memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
5978  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
5979  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
5980  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
5981  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
5982  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
5983  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
5984  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
5985  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
5986  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
5987  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
5988  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
5989  return MZ_TRUE;
5990 }
5991 
5992 static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst,
5993  mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size,
5994  mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
5995  mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
5996  mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
5997 {
5998  (void)pZip;
5999  memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6000  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6001  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6002  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6003  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6004  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6005  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6006  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6007  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
6008  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
6009  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6010  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6011  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6012  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6013  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_MIN(local_header_ofs, MZ_UINT32_MAX));
6014  return MZ_TRUE;
6015 }
6016 
6017 static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
6018  const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size,
6019  mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
6020  mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6021  mz_uint64 local_header_ofs, mz_uint32 ext_attributes,
6022  const char *user_extra_data, mz_uint user_extra_data_len)
6023 {
6024  mz_zip_internal_state *pState = pZip->m_pState;
6025  mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6026  size_t orig_central_dir_size = pState->m_central_dir.m_size;
6027  mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6028 
6029  if (!pZip->m_pState->m_zip64)
6030  {
6031  if (local_header_ofs > 0xFFFFFFFF)
6032  return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
6033  }
6034 
6035  /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6036  if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX)
6037  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6038 
6039  if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, (mz_uint16)(extra_size + user_extra_data_len), comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
6040  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6041 
6042  if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6043  (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
6044  (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
6045  (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) ||
6046  (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
6047  (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
6048  {
6049  /* Try to resize the central directory array back into its original state. */
6050  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6051  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6052  }
6053 
6054  return MZ_TRUE;
6055 }
6056 
6057 static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
6058 {
6059  /* Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. */
6060  if (*pArchive_name == '/')
6061  return MZ_FALSE;
6062 
6063  /* Making sure the name does not contain drive letters or DOS style backward slashes is the responsibility of the program using miniz*/
6064 
6065  return MZ_TRUE;
6066 }
6067 
6068 static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
6069 {
6070  mz_uint32 n;
6071  if (!pZip->m_file_offset_alignment)
6072  return 0;
6073  n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6074  return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1));
6075 }
6076 
6077 static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
6078 {
6079  char buf[4096];
6080  memset(buf, 0, MZ_MIN(sizeof(buf), n));
6081  while (n)
6082  {
6083  mz_uint32 s = MZ_MIN(sizeof(buf), n);
6084  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6085  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6086 
6087  cur_file_ofs += s;
6088  n -= s;
6089  }
6090  return MZ_TRUE;
6091 }
6092 
6093 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6094  mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
6095 {
6096  return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0);
6097 }
6098 
6099 mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size,
6100  mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified,
6101  const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6102 {
6103  mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6104  mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
6105  mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
6106  size_t archive_name_size;
6107  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6108  tdefl_compressor *pComp = NULL;
6109  mz_bool store_data_uncompressed;
6110  mz_zip_internal_state *pState;
6111  mz_uint8 *pExtra_data = NULL;
6112  mz_uint32 extra_size = 0;
6113  mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6114  mz_uint16 bit_flags = 0;
6115 
6116  if ((int)level_and_flags < 0)
6117  level_and_flags = MZ_DEFAULT_LEVEL;
6118 
6119  if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
6120  bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6121 
6122  if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6123  bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6124 
6125  level = level_and_flags & 0xF;
6126  store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6127 
6128  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6129  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6130 
6131  pState = pZip->m_pState;
6132 
6133  if (pState->m_zip64)
6134  {
6135  if (pZip->m_total_files == MZ_UINT32_MAX)
6136  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6137  }
6138  else
6139  {
6140  if (pZip->m_total_files == MZ_UINT16_MAX)
6141  {
6142  pState->m_zip64 = MZ_TRUE;
6143  /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6144  }
6145  if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6146  {
6147  pState->m_zip64 = MZ_TRUE;
6148  /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6149  }
6150  }
6151 
6152  if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6153  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6154 
6155  if (!mz_zip_writer_validate_archive_name(pArchive_name))
6156  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6157 
6158 #ifndef MINIZ_NO_TIME
6159  if (last_modified != NULL)
6160  {
6161  mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
6162  }
6163  else
6164  {
6165  MZ_TIME_T cur_time;
6166  time(&cur_time);
6167  mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6168  }
6169 #endif /* #ifndef MINIZ_NO_TIME */
6170 
6171  if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6172  {
6173  uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6174  uncomp_size = buf_size;
6175  if (uncomp_size <= 3)
6176  {
6177  level = 0;
6178  store_data_uncompressed = MZ_TRUE;
6179  }
6180  }
6181 
6182  archive_name_size = strlen(pArchive_name);
6183  if (archive_name_size > MZ_UINT16_MAX)
6184  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6185 
6186  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6187 
6188  /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6189  if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
6190  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6191 
6192  if (!pState->m_zip64)
6193  {
6194  /* Bail early if the archive would obviously become too large */
6195  if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size
6196  + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len +
6197  pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len
6198  + MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF)
6199  {
6200  pState->m_zip64 = MZ_TRUE;
6201  /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6202  }
6203  }
6204 
6205  if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
6206  {
6207  /* Set DOS Subdirectory attribute bit. */
6208  ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
6209 
6210  /* Subdirectories cannot contain data. */
6211  if ((buf_size) || (uncomp_size))
6212  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6213  }
6214 
6215  /* Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) */
6216  if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
6217  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6218 
6219  if ((!store_data_uncompressed) && (buf_size))
6220  {
6221  if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6222  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6223  }
6224 
6225  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6226  {
6227  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6228  return MZ_FALSE;
6229  }
6230 
6231  local_dir_header_ofs += num_alignment_padding_bytes;
6232  if (pZip->m_file_offset_alignment)
6233  {
6234  MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6235  }
6236  cur_archive_file_ofs += num_alignment_padding_bytes;
6237 
6238  MZ_CLEAR_OBJ(local_dir_header);
6239 
6240  if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6241  {
6242  method = MZ_DEFLATED;
6243  }
6244 
6245  if (pState->m_zip64)
6246  {
6247  if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6248  {
6249  pExtra_data = extra_data;
6250  extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6251  (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6252  }
6253 
6254  if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, bit_flags, dos_time, dos_date))
6255  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6256 
6257  if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6258  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6259 
6260  cur_archive_file_ofs += sizeof(local_dir_header);
6261 
6262  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6263  {
6264  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6265  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6266  }
6267  cur_archive_file_ofs += archive_name_size;
6268 
6269  if (pExtra_data != NULL)
6270  {
6271  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6272  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6273 
6274  cur_archive_file_ofs += extra_size;
6275  }
6276  }
6277  else
6278  {
6279  if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6280  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6281  if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))
6282  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6283 
6284  if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6285  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6286 
6287  cur_archive_file_ofs += sizeof(local_dir_header);
6288 
6289  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6290  {
6291  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6292  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6293  }
6294  cur_archive_file_ofs += archive_name_size;
6295  }
6296 
6297  if (user_extra_data_len > 0)
6298  {
6299  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6300  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6301 
6302  cur_archive_file_ofs += user_extra_data_len;
6303  }
6304 
6305  if (store_data_uncompressed)
6306  {
6307  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
6308  {
6309  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6310  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6311  }
6312 
6313  cur_archive_file_ofs += buf_size;
6314  comp_size = buf_size;
6315  }
6316  else if (buf_size)
6317  {
6319 
6320  state.m_pZip = pZip;
6321  state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6322  state.m_comp_size = 0;
6323 
6324  if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||
6325  (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
6326  {
6327  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6328  return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6329  }
6330 
6331  comp_size = state.m_comp_size;
6332  cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6333  }
6334 
6335  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6336  pComp = NULL;
6337 
6338  if (uncomp_size)
6339  {
6340  mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6341  mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6342 
6343  MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR);
6344 
6345  MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6346  MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6347  if (pExtra_data == NULL)
6348  {
6349  if (comp_size > MZ_UINT32_MAX)
6350  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6351 
6352  MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6353  MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6354  }
6355  else
6356  {
6357  MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6358  MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6359  local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6360  }
6361 
6362  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6363  return MZ_FALSE;
6364 
6365  cur_archive_file_ofs += local_dir_footer_size;
6366  }
6367 
6368  if (pExtra_data != NULL)
6369  {
6370  extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6371  (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6372  }
6373 
6374  if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment,
6375  comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6376  user_extra_data_central, user_extra_data_central_len))
6377  return MZ_FALSE;
6378 
6379  pZip->m_total_files++;
6380  pZip->m_archive_size = cur_archive_file_ofs;
6381 
6382  return MZ_TRUE;
6383 }
6384 
6385 mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6386  const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6387 {
6388  mz_uint16 gen_flags = MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6389  mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6390  mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
6391  mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0;
6392  size_t archive_name_size;
6393  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6394  mz_uint8 *pExtra_data = NULL;
6395  mz_uint32 extra_size = 0;
6396  mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6397  mz_zip_internal_state *pState;
6398  mz_uint64 file_ofs = 0;
6399 
6400  if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6401  gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6402 
6403  if ((int)level_and_flags < 0)
6404  level_and_flags = MZ_DEFAULT_LEVEL;
6405  level = level_and_flags & 0xF;
6406 
6407  /* Sanity checks */
6408  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6409  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6410 
6411  pState = pZip->m_pState;
6412 
6413  if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX))
6414  {
6415  /* Source file is too large for non-zip64 */
6416  /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6417  pState->m_zip64 = MZ_TRUE;
6418  }
6419 
6420  /* We could support this, but why? */
6421  if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6422  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6423 
6424  if (!mz_zip_writer_validate_archive_name(pArchive_name))
6425  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6426 
6427  if (pState->m_zip64)
6428  {
6429  if (pZip->m_total_files == MZ_UINT32_MAX)
6430  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6431  }
6432  else
6433  {
6434  if (pZip->m_total_files == MZ_UINT16_MAX)
6435  {
6436  pState->m_zip64 = MZ_TRUE;
6437  /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6438  }
6439  }
6440 
6441  archive_name_size = strlen(pArchive_name);
6442  if (archive_name_size > MZ_UINT16_MAX)
6443  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6444 
6445  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6446 
6447  /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6448  if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
6449  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6450 
6451  if (!pState->m_zip64)
6452  {
6453  /* Bail early if the archive would obviously become too large */
6454  if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE
6455  + archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024
6456  + MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF)
6457  {
6458  pState->m_zip64 = MZ_TRUE;
6459  /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6460  }
6461  }
6462 
6463 #ifndef MINIZ_NO_TIME
6464  if (pFile_time)
6465  {
6466  mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);
6467  }
6468 #endif
6469 
6470  if (uncomp_size <= 3)
6471  level = 0;
6472 
6473  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6474  {
6475  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6476  }
6477 
6478  cur_archive_file_ofs += num_alignment_padding_bytes;
6479  local_dir_header_ofs = cur_archive_file_ofs;
6480 
6481  if (pZip->m_file_offset_alignment)
6482  {
6483  MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6484  }
6485 
6486  if (uncomp_size && level)
6487  {
6488  method = MZ_DEFLATED;
6489  }
6490 
6491  MZ_CLEAR_OBJ(local_dir_header);
6492  if (pState->m_zip64)
6493  {
6494  if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6495  {
6496  pExtra_data = extra_data;
6497  extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6498  (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6499  }
6500 
6501  if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, gen_flags, dos_time, dos_date))
6502  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6503 
6504  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6505  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6506 
6507  cur_archive_file_ofs += sizeof(local_dir_header);
6508 
6509  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6510  {
6511  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6512  }
6513 
6514  cur_archive_file_ofs += archive_name_size;
6515 
6516  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6517  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6518 
6519  cur_archive_file_ofs += extra_size;
6520  }
6521  else
6522  {
6523  if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6524  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6525  if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))
6526  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6527 
6528  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6529  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6530 
6531  cur_archive_file_ofs += sizeof(local_dir_header);
6532 
6533  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6534  {
6535  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6536  }
6537 
6538  cur_archive_file_ofs += archive_name_size;
6539  }
6540 
6541  if (user_extra_data_len > 0)
6542  {
6543  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6544  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6545 
6546  cur_archive_file_ofs += user_extra_data_len;
6547  }
6548 
6549  if (uncomp_size)
6550  {
6551  mz_uint64 uncomp_remaining = uncomp_size;
6552  void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6553  if (!pRead_buf)
6554  {
6555  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6556  }
6557 
6558  if (!level)
6559  {
6560  while (uncomp_remaining)
6561  {
6562  mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6563  if ((read_callback(callback_opaque, file_ofs, pRead_buf, n) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
6564  {
6565  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6566  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6567  }
6568  file_ofs += n;
6569  uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6570  uncomp_remaining -= n;
6571  cur_archive_file_ofs += n;
6572  }
6573  comp_size = uncomp_size;
6574  }
6575  else
6576  {
6577  mz_bool result = MZ_FALSE;
6579  tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6580  if (!pComp)
6581  {
6582  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6583  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6584  }
6585 
6586  state.m_pZip = pZip;
6587  state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6588  state.m_comp_size = 0;
6589 
6590  if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)
6591  {
6592  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6593  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6594  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6595  }
6596 
6597  for (;;)
6598  {
6599  size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
6600  tdefl_status status;
6601  tdefl_flush flush = TDEFL_NO_FLUSH;
6602 
6603  if (read_callback(callback_opaque, file_ofs, pRead_buf, in_buf_size)!= in_buf_size)
6604  {
6605  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6606  break;
6607  }
6608 
6609  file_ofs += in_buf_size;
6610  uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6611  uncomp_remaining -= in_buf_size;
6612 
6613  if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
6614  flush = TDEFL_FULL_FLUSH;
6615 
6616  status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH);
6617  if (status == TDEFL_STATUS_DONE)
6618  {
6619  result = MZ_TRUE;
6620  break;
6621  }
6622  else if (status != TDEFL_STATUS_OKAY)
6623  {
6624  mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6625  break;
6626  }
6627  }
6628 
6629  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6630 
6631  if (!result)
6632  {
6633  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6634  return MZ_FALSE;
6635  }
6636 
6637  comp_size = state.m_comp_size;
6638  cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6639  }
6640 
6641  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6642  }
6643 
6644  {
6645  mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6646  mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6647 
6648  MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6649  MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6650  if (pExtra_data == NULL)
6651  {
6652  if (comp_size > MZ_UINT32_MAX)
6653  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6654 
6655  MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6656  MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6657  }
6658  else
6659  {
6660  MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6661  MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6662  local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6663  }
6664 
6665  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6666  return MZ_FALSE;
6667 
6668  cur_archive_file_ofs += local_dir_footer_size;
6669  }
6670 
6671  if (pExtra_data != NULL)
6672  {
6673  extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6674  (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6675  }
6676 
6677  if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment, comment_size,
6678  uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6679  user_extra_data_central, user_extra_data_central_len))
6680  return MZ_FALSE;
6681 
6682  pZip->m_total_files++;
6683  pZip->m_archive_size = cur_archive_file_ofs;
6684 
6685  return MZ_TRUE;
6686 }
6687 
6688 #ifndef MINIZ_NO_STDIO
6689 
6690 static size_t mz_file_read_func_stdio(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
6691 {
6692  MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque;
6693  mz_int64 cur_ofs = MZ_FTELL64(pSrc_file);
6694 
6695  if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET))))
6696  return 0;
6697 
6698  return MZ_FREAD(pBuf, 1, n, pSrc_file);
6699 }
6700 
6701 mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6702  const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6703 {
6704  return mz_zip_writer_add_read_buf_callback(pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, size_to_add, pFile_time, pComment, comment_size, level_and_flags,
6705  user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len);
6706 }
6707 
6708 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
6709 {
6710  MZ_FILE *pSrc_file = NULL;
6711  mz_uint64 uncomp_size = 0;
6712  MZ_TIME_T file_modified_time;
6713  MZ_TIME_T *pFile_time = NULL;
6714  mz_bool status;
6715 
6716  memset(&file_modified_time, 0, sizeof(file_modified_time));
6717 
6718 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
6719  pFile_time = &file_modified_time;
6720  if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6721  return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED);
6722 #endif
6723 
6724  pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6725  if (!pSrc_file)
6726  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
6727 
6728  MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6729  uncomp_size = MZ_FTELL64(pSrc_file);
6730  MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6731 
6732  status = mz_zip_writer_add_cfile(pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment, comment_size, level_and_flags, NULL, 0, NULL, 0);
6733 
6734  MZ_FCLOSE(pSrc_file);
6735 
6736  return status;
6737 }
6738 #endif /* #ifndef MINIZ_NO_STDIO */
6739 
6740 static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, uint32_t ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start)
6741 {
6742  /* + 64 should be enough for any new zip64 data */
6743  if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))
6744  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6745 
6746  mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);
6747 
6748  if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start))
6749  {
6750  mz_uint8 new_ext_block[64];
6751  mz_uint8 *pDst = new_ext_block;
6752  mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
6753  mz_write_le16(pDst + sizeof(mz_uint16), 0);
6754  pDst += sizeof(mz_uint16) * 2;
6755 
6756  if (pUncomp_size)
6757  {
6758  mz_write_le64(pDst, *pUncomp_size);
6759  pDst += sizeof(mz_uint64);
6760  }
6761 
6762  if (pComp_size)
6763  {
6764  mz_write_le64(pDst, *pComp_size);
6765  pDst += sizeof(mz_uint64);
6766  }
6767 
6768  if (pLocal_header_ofs)
6769  {
6770  mz_write_le64(pDst, *pLocal_header_ofs);
6771  pDst += sizeof(mz_uint64);
6772  }
6773 
6774  if (pDisk_start)
6775  {
6776  mz_write_le32(pDst, *pDisk_start);
6777  pDst += sizeof(mz_uint32);
6778  }
6779 
6780  mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2));
6781 
6782  if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block))
6783  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6784  }
6785 
6786  if ((pExt) && (ext_len))
6787  {
6788  mz_uint32 extra_size_remaining = ext_len;
6789  const mz_uint8 *pExtra_data = pExt;
6790 
6791  do
6792  {
6793  mz_uint32 field_id, field_data_size, field_total_size;
6794 
6795  if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6796  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6797 
6798  field_id = MZ_READ_LE16(pExtra_data);
6799  field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6800  field_total_size = field_data_size + sizeof(mz_uint16) * 2;
6801 
6802  if (field_total_size > extra_size_remaining)
6803  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6804 
6805  if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
6806  {
6807  if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size))
6808  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6809  }
6810 
6811  pExtra_data += field_total_size;
6812  extra_size_remaining -= field_total_size;
6813  } while (extra_size_remaining);
6814  }
6815 
6816  return MZ_TRUE;
6817 }
6818 
6819 /* TODO: This func is now pretty freakin complex due to zip64, split it up? */
6820 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index)
6821 {
6822  mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size;
6823  mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;
6824  mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6825  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
6826  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6827  mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6828  size_t orig_central_dir_size;
6829  mz_zip_internal_state *pState;
6830  void *pBuf;
6831  const mz_uint8 *pSrc_central_header;
6832  mz_zip_archive_file_stat src_file_stat;
6833  mz_uint32 src_filename_len, src_comment_len, src_ext_len;
6834  mz_uint32 local_header_filename_size, local_header_extra_len;
6835  mz_uint64 local_header_comp_size, local_header_uncomp_size;
6836  mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
6837 
6838  /* Sanity checks */
6839  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))
6840  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6841 
6842  pState = pZip->m_pState;
6843 
6844  /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */
6845  if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))
6846  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6847 
6848  /* Get pointer to the source central dir header and crack it */
6849  if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
6850  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6851 
6852  if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)
6853  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6854 
6855  src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);
6856  src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6857  src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);
6858  src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len;
6859 
6860  /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right now (+32 fudge factor in case we need to add more extra data) */
6861  if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)
6862  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6863 
6864  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6865 
6866  if (!pState->m_zip64)
6867  {
6868  if (pZip->m_total_files == MZ_UINT16_MAX)
6869  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6870  }
6871  else
6872  {
6873  /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */
6874  if (pZip->m_total_files == MZ_UINT32_MAX)
6875  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6876  }
6877 
6878  if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL))
6879  return MZ_FALSE;
6880 
6881  cur_src_file_ofs = src_file_stat.m_local_header_ofs;
6882  cur_dst_file_ofs = pZip->m_archive_size;
6883 
6884  /* Read the source archive's local dir header */
6885  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6886  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6887 
6888  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6889  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6890 
6891  cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6892 
6893  /* Compute the total size we need to copy (filename+extra data+compressed data) */
6894  local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
6895  local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6896  local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
6897  local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
6898  src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size;
6899 
6900  /* Try to find a zip64 extended information field */
6901  if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
6902  {
6903  mz_zip_array file_data_array;
6904  const mz_uint8 *pExtra_data;
6905  mz_uint32 extra_size_remaining = local_header_extra_len;
6906 
6907  mz_zip_array_init(&file_data_array, 1);
6908  if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE))
6909  {
6910  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6911  }
6912 
6913  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, src_file_stat.m_local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_size, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
6914  {
6915  mz_zip_array_clear(pZip, &file_data_array);
6916  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6917  }
6918 
6919  pExtra_data = (const mz_uint8 *)file_data_array.m_p;
6920 
6921  do
6922  {
6923  mz_uint32 field_id, field_data_size, field_total_size;
6924 
6925  if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6926  {
6927  mz_zip_array_clear(pZip, &file_data_array);
6928  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6929  }
6930 
6931  field_id = MZ_READ_LE16(pExtra_data);
6932  field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6933  field_total_size = field_data_size + sizeof(mz_uint16) * 2;
6934 
6935  if (field_total_size > extra_size_remaining)
6936  {
6937  mz_zip_array_clear(pZip, &file_data_array);
6938  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6939  }
6940 
6941  if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
6942  {
6943  const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
6944 
6945  if (field_data_size < sizeof(mz_uint64) * 2)
6946  {
6947  mz_zip_array_clear(pZip, &file_data_array);
6948  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6949  }
6950 
6951  local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
6952  local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */
6953 
6954  found_zip64_ext_data_in_ldir = MZ_TRUE;
6955  break;
6956  }
6957 
6958  pExtra_data += field_total_size;
6959  extra_size_remaining -= field_total_size;
6960  } while (extra_size_remaining);
6961 
6962  mz_zip_array_clear(pZip, &file_data_array);
6963  }
6964 
6965  if (!pState->m_zip64)
6966  {
6967  /* Try to detect if the new archive will most likely wind up too big and bail early (+(sizeof(mz_uint32) * 4) is for the optional descriptor which could be present, +64 is a fudge factor). */
6968  /* We also check when the archive is finalized so this doesn't need to be perfect. */
6969  mz_uint64 approx_new_archive_size = cur_dst_file_ofs + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining + (sizeof(mz_uint32) * 4) +
6970  pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64;
6971 
6972  if (approx_new_archive_size >= MZ_UINT32_MAX)
6973  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6974  }
6975 
6976  /* Write dest archive padding */
6977  if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
6978  return MZ_FALSE;
6979 
6980  cur_dst_file_ofs += num_alignment_padding_bytes;
6981 
6982  local_dir_header_ofs = cur_dst_file_ofs;
6983  if (pZip->m_file_offset_alignment)
6984  {
6985  MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6986  }
6987 
6988  /* The original zip's local header+ext block doesn't change, even with zip64, so we can just copy it over to the dest zip */
6989  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6990  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6991 
6992  cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6993 
6994  /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */
6995  if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining)))))
6996  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6997 
6998  while (src_archive_bytes_remaining)
6999  {
7000  n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining);
7001  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
7002  {
7003  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7004  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7005  }
7006  cur_src_file_ofs += n;
7007 
7008  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7009  {
7010  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7011  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7012  }
7013  cur_dst_file_ofs += n;
7014 
7015  src_archive_bytes_remaining -= n;
7016  }
7017 
7018  /* Now deal with the optional data descriptor */
7019  bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
7020  if (bit_flags & 8)
7021  {
7022  /* Copy data descriptor */
7023  if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir))
7024  {
7025  /* src is zip64, dest must be zip64 */
7026 
7027  /* name uint32_t's */
7028  /* id 1 (optional in zip64?) */
7029  /* crc 1 */
7030  /* comp_size 2 */
7031  /* uncomp_size 2 */
7032  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6))
7033  {
7034  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7035  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7036  }
7037 
7038  n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);
7039  }
7040  else
7041  {
7042  /* src is NOT zip64 */
7043  mz_bool has_id;
7044 
7045  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
7046  {
7047  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7048  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7049  }
7050 
7051  has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
7052 
7053  if (pZip->m_pState->m_zip64)
7054  {
7055  /* dest is zip64, so upgrade the data descriptor */
7056  const mz_uint32 *pSrc_descriptor = (const mz_uint32 *)((const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0));
7057  const mz_uint32 src_crc32 = pSrc_descriptor[0];
7058  const mz_uint64 src_comp_size = pSrc_descriptor[1];
7059  const mz_uint64 src_uncomp_size = pSrc_descriptor[2];
7060 
7061  mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID);
7062  mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32);
7063  mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size);
7064  mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size);
7065 
7066  n = sizeof(mz_uint32) * 6;
7067  }
7068  else
7069  {
7070  /* dest is NOT zip64, just copy it as-is */
7071  n = sizeof(mz_uint32) * (has_id ? 4 : 3);
7072  }
7073  }
7074 
7075  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7076  {
7077  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7078  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7079  }
7080 
7081  cur_src_file_ofs += n;
7082  cur_dst_file_ofs += n;
7083  }
7084  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7085 
7086  /* Finally, add the new central dir header */
7087  orig_central_dir_size = pState->m_central_dir.m_size;
7088 
7089  memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
7090 
7091  if (pState->m_zip64)
7092  {
7093  /* This is the painful part: We need to write a new central dir header + ext block with updated zip64 fields, and ensure the old fields (if any) are not included. */
7094  const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;
7095  mz_zip_array new_ext_block;
7096 
7097  mz_zip_array_init(&new_ext_block, sizeof(mz_uint8));
7098 
7099  MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7100  MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7101  MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX);
7102 
7103  if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL))
7104  {
7105  mz_zip_array_clear(pZip, &new_ext_block);
7106  return MZ_FALSE;
7107  }
7108 
7109  MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size);
7110 
7111  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7112  {
7113  mz_zip_array_clear(pZip, &new_ext_block);
7114  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7115  }
7116 
7117  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len))
7118  {
7119  mz_zip_array_clear(pZip, &new_ext_block);
7120  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7121  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7122  }
7123 
7124  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size))
7125  {
7126  mz_zip_array_clear(pZip, &new_ext_block);
7127  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7128  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7129  }
7130 
7131  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len + src_ext_len, src_comment_len))
7132  {
7133  mz_zip_array_clear(pZip, &new_ext_block);
7134  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7135  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7136  }
7137 
7138  mz_zip_array_clear(pZip, &new_ext_block);
7139  }
7140  else
7141  {
7142  /* sanity checks */
7143  if (cur_dst_file_ofs > MZ_UINT32_MAX)
7144  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7145 
7146  if (local_dir_header_ofs >= MZ_UINT32_MAX)
7147  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7148 
7149  MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
7150 
7151  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7152  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7153 
7154  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_central_dir_following_data_size))
7155  {
7156  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7157  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7158  }
7159  }
7160 
7161  /* This shouldn't trigger unless we screwed up during the initial sanity checks */
7162  if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
7163  {
7164  /* TODO: Support central dirs >= 32-bits in size */
7165  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7166  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
7167  }
7168 
7169  n = (mz_uint32)orig_central_dir_size;
7170  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
7171  {
7172  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7173  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7174  }
7175 
7176  pZip->m_total_files++;
7177  pZip->m_archive_size = cur_dst_file_ofs;
7178 
7179  return MZ_TRUE;
7180 }
7181 
7182 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
7183 {
7184  mz_zip_internal_state *pState;
7185  mz_uint64 central_dir_ofs, central_dir_size;
7186  mz_uint8 hdr[256];
7187 
7188  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
7189  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7190 
7191  pState = pZip->m_pState;
7192 
7193  if (pState->m_zip64)
7194  {
7195  if ((pZip->m_total_files > MZ_UINT32_MAX) || (pState->m_central_dir.m_size >= MZ_UINT32_MAX))
7196  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7197  }
7198  else
7199  {
7200  if ((pZip->m_total_files > MZ_UINT16_MAX) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX))
7201  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7202  }
7203 
7204  central_dir_ofs = 0;
7205  central_dir_size = 0;
7206  if (pZip->m_total_files)
7207  {
7208  /* Write central directory */
7209  central_dir_ofs = pZip->m_archive_size;
7210  central_dir_size = pState->m_central_dir.m_size;
7211  pZip->m_central_directory_file_ofs = central_dir_ofs;
7212  if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
7213  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7214 
7215  pZip->m_archive_size += central_dir_size;
7216  }
7217 
7218  if (pState->m_zip64)
7219  {
7220  /* Write zip64 end of central directory header */
7221  mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size;
7222 
7223  MZ_CLEAR_OBJ(hdr);
7224  MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG);
7225  MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - sizeof(mz_uint32) - sizeof(mz_uint64));
7226  MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E); /* TODO: always Unix */
7227  MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D);
7228  MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
7229  MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
7230  MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size);
7231  MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs);
7232  if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
7233  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7234 
7235  pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE;
7236 
7237  /* Write zip64 end of central directory locator */
7238  MZ_CLEAR_OBJ(hdr);
7239  MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG);
7240  MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr);
7241  MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1);
7242  if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
7243  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7244 
7245  pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE;
7246  }
7247 
7248  /* Write end of central directory record */
7249  MZ_CLEAR_OBJ(hdr);
7250  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
7251  MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7252  MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7253  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_size));
7254  MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_ofs));
7255 
7256  if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
7257  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7258 
7259 #ifndef MINIZ_NO_STDIO
7260  if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
7261  return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
7262 #endif /* #ifndef MINIZ_NO_STDIO */
7263 
7264  pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE;
7265 
7266  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
7267  return MZ_TRUE;
7268 }
7269 
7270 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize)
7271 {
7272  if ((!ppBuf) || (!pSize))
7273  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7274 
7275  *ppBuf = NULL;
7276  *pSize = 0;
7277 
7278  if ((!pZip) || (!pZip->m_pState))
7279  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7280 
7281  if (pZip->m_pWrite != mz_zip_heap_write_func)
7282  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7283 
7284  if (!mz_zip_writer_finalize_archive(pZip))
7285  return MZ_FALSE;
7286 
7287  *ppBuf = pZip->m_pState->m_pMem;
7288  *pSize = pZip->m_pState->m_mem_size;
7289  pZip->m_pState->m_pMem = NULL;
7290  pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
7291 
7292  return MZ_TRUE;
7293 }
7294 
7295 mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
7296 {
7297  return mz_zip_writer_end_internal(pZip, MZ_TRUE);
7298 }
7299 
7300 #ifndef MINIZ_NO_STDIO
7301 mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
7302 {
7303  return mz_zip_add_mem_to_archive_file_in_place_v2(pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, NULL);
7304 }
7305 
7306 mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr)
7307 {
7308  mz_bool status, created_new_archive = MZ_FALSE;
7309  mz_zip_archive zip_archive;
7310  struct MZ_FILE_STAT_STRUCT file_stat;
7311  mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
7312 
7313  mz_zip_zero_struct(&zip_archive);
7314  if ((int)level_and_flags < 0)
7315  level_and_flags = MZ_DEFAULT_LEVEL;
7316 
7317  if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
7318  {
7319  if (pErr)
7320  *pErr = MZ_ZIP_INVALID_PARAMETER;
7321  return MZ_FALSE;
7322  }
7323 
7324  if (!mz_zip_writer_validate_archive_name(pArchive_name))
7325  {
7326  if (pErr)
7327  *pErr = MZ_ZIP_INVALID_FILENAME;
7328  return MZ_FALSE;
7329  }
7330 
7331  /* Important: The regular non-64 bit version of stat() can fail here if the file is very large, which could cause the archive to be overwritten. */
7332  /* So be sure to compile with _LARGEFILE64_SOURCE 1 */
7333  if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
7334  {
7335  /* Create a new archive. */
7336  if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags))
7337  {
7338  if (pErr)
7339  *pErr = zip_archive.m_last_error;
7340  return MZ_FALSE;
7341  }
7342 
7343  created_new_archive = MZ_TRUE;
7344  }
7345  else
7346  {
7347  /* Append to an existing archive. */
7348  if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7349  {
7350  if (pErr)
7351  *pErr = zip_archive.m_last_error;
7352  return MZ_FALSE;
7353  }
7354 
7355  if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags))
7356  {
7357  if (pErr)
7358  *pErr = zip_archive.m_last_error;
7359 
7360  mz_zip_reader_end_internal(&zip_archive, MZ_FALSE);
7361 
7362  return MZ_FALSE;
7363  }
7364  }
7365 
7366  status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
7367  actual_err = zip_archive.m_last_error;
7368 
7369  /* Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) */
7370  if (!mz_zip_writer_finalize_archive(&zip_archive))
7371  {
7372  if (!actual_err)
7373  actual_err = zip_archive.m_last_error;
7374 
7375  status = MZ_FALSE;
7376  }
7377 
7378  if (!mz_zip_writer_end_internal(&zip_archive, status))
7379  {
7380  if (!actual_err)
7381  actual_err = zip_archive.m_last_error;
7382 
7383  status = MZ_FALSE;
7384  }
7385 
7386  if ((!status) && (created_new_archive))
7387  {
7388  /* It's a new archive and something went wrong, so just delete it. */
7389  int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
7390  (void)ignoredStatus;
7391  }
7392 
7393  if (pErr)
7394  *pErr = actual_err;
7395 
7396  return status;
7397 }
7398 
7399 void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr)
7400 {
7401  mz_uint32 file_index;
7402  mz_zip_archive zip_archive;
7403  void *p = NULL;
7404 
7405  if (pSize)
7406  *pSize = 0;
7407 
7408  if ((!pZip_filename) || (!pArchive_name))
7409  {
7410  if (pErr)
7411  *pErr = MZ_ZIP_INVALID_PARAMETER;
7412 
7413  return NULL;
7414  }
7415 
7416  mz_zip_zero_struct(&zip_archive);
7417  if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7418  {
7419  if (pErr)
7420  *pErr = zip_archive.m_last_error;
7421 
7422  return NULL;
7423  }
7424 
7425  if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index))
7426  {
7427  p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
7428  }
7429 
7430  mz_zip_reader_end_internal(&zip_archive, p != NULL);
7431 
7432  if (pErr)
7433  *pErr = zip_archive.m_last_error;
7434 
7435  return p;
7436 }
7437 
7438 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
7439 {
7440  return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL);
7441 }
7442 
7443 #endif /* #ifndef MINIZ_NO_STDIO */
7444 
7445 #endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */
7446 
7447 /* ------------------- Misc utils */
7448 
7449 mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip)
7450 {
7451  return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
7452 }
7453 
7454 mz_zip_type mz_zip_get_type(mz_zip_archive *pZip)
7455 {
7456  return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
7457 }
7458 
7459 mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num)
7460 {
7461  mz_zip_error prev_err;
7462 
7463  if (!pZip)
7464  return MZ_ZIP_INVALID_PARAMETER;
7465 
7466  prev_err = pZip->m_last_error;
7467 
7468  pZip->m_last_error = err_num;
7469  return prev_err;
7470 }
7471 
7472 mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip)
7473 {
7474  if (!pZip)
7475  return MZ_ZIP_INVALID_PARAMETER;
7476 
7477  return pZip->m_last_error;
7478 }
7479 
7480 mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip)
7481 {
7482  return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR);
7483 }
7484 
7485 mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip)
7486 {
7487  mz_zip_error prev_err;
7488 
7489  if (!pZip)
7490  return MZ_ZIP_INVALID_PARAMETER;
7491 
7492  prev_err = pZip->m_last_error;
7493 
7494  pZip->m_last_error = MZ_ZIP_NO_ERROR;
7495  return prev_err;
7496 }
7497 
7498 const char *mz_zip_get_error_string(mz_zip_error mz_err)
7499 {
7500  switch (mz_err)
7501  {
7502  case MZ_ZIP_NO_ERROR:
7503  return "no error";
7504  case MZ_ZIP_UNDEFINED_ERROR:
7505  return "undefined error";
7506  case MZ_ZIP_TOO_MANY_FILES:
7507  return "too many files";
7508  case MZ_ZIP_FILE_TOO_LARGE:
7509  return "file too large";
7510  case MZ_ZIP_UNSUPPORTED_METHOD:
7511  return "unsupported method";
7512  case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
7513  return "unsupported encryption";
7514  case MZ_ZIP_UNSUPPORTED_FEATURE:
7515  return "unsupported feature";
7516  case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
7517  return "failed finding central directory";
7518  case MZ_ZIP_NOT_AN_ARCHIVE:
7519  return "not a ZIP archive";
7520  case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
7521  return "invalid header or archive is corrupted";
7522  case MZ_ZIP_UNSUPPORTED_MULTIDISK:
7523  return "unsupported multidisk archive";
7524  case MZ_ZIP_DECOMPRESSION_FAILED:
7525  return "decompression failed or archive is corrupted";
7526  case MZ_ZIP_COMPRESSION_FAILED:
7527  return "compression failed";
7528  case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
7529  return "unexpected decompressed size";
7530  case MZ_ZIP_CRC_CHECK_FAILED:
7531  return "CRC-32 check failed";
7532  case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
7533  return "unsupported central directory size";
7534  case MZ_ZIP_ALLOC_FAILED:
7535  return "allocation failed";
7536  case MZ_ZIP_FILE_OPEN_FAILED:
7537  return "file open failed";
7538  case MZ_ZIP_FILE_CREATE_FAILED:
7539  return "file create failed";
7540  case MZ_ZIP_FILE_WRITE_FAILED:
7541  return "file write failed";
7542  case MZ_ZIP_FILE_READ_FAILED:
7543  return "file read failed";
7544  case MZ_ZIP_FILE_CLOSE_FAILED:
7545  return "file close failed";
7546  case MZ_ZIP_FILE_SEEK_FAILED:
7547  return "file seek failed";
7548  case MZ_ZIP_FILE_STAT_FAILED:
7549  return "file stat failed";
7550  case MZ_ZIP_INVALID_PARAMETER:
7551  return "invalid parameter";
7552  case MZ_ZIP_INVALID_FILENAME:
7553  return "invalid filename";
7554  case MZ_ZIP_BUF_TOO_SMALL:
7555  return "buffer too small";
7556  case MZ_ZIP_INTERNAL_ERROR:
7557  return "internal error";
7558  case MZ_ZIP_FILE_NOT_FOUND:
7559  return "file not found";
7560  case MZ_ZIP_ARCHIVE_TOO_LARGE:
7561  return "archive is too large";
7562  case MZ_ZIP_VALIDATION_FAILED:
7563  return "validation failed";
7564  case MZ_ZIP_WRITE_CALLBACK_FAILED:
7565  return "write calledback failed";
7566  default:
7567  break;
7568  }
7569 
7570  return "unknown error";
7571 }
7572 
7573 /* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */
7574 mz_bool mz_zip_is_zip64(mz_zip_archive *pZip)
7575 {
7576  if ((!pZip) || (!pZip->m_pState))
7577  return MZ_FALSE;
7578 
7579  return pZip->m_pState->m_zip64;
7580 }
7581 
7582 size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip)
7583 {
7584  if ((!pZip) || (!pZip->m_pState))
7585  return 0;
7586 
7587  return pZip->m_pState->m_central_dir.m_size;
7588 }
7589 
7590 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
7591 {
7592  return pZip ? pZip->m_total_files : 0;
7593 }
7594 
7595 mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip)
7596 {
7597  if (!pZip)
7598  return 0;
7599  return pZip->m_archive_size;
7600 }
7601 
7602 mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip)
7603 {
7604  if ((!pZip) || (!pZip->m_pState))
7605  return 0;
7606  return pZip->m_pState->m_file_archive_start_ofs;
7607 }
7608 
7609 MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip)
7610 {
7611  if ((!pZip) || (!pZip->m_pState))
7612  return 0;
7613  return pZip->m_pState->m_pFile;
7614 }
7615 
7616 size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
7617 {
7618  if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
7619  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7620 
7621  return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
7622 }
7623 
7624 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
7625 {
7626  mz_uint n;
7627  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
7628  if (!p)
7629  {
7630  if (filename_buf_size)
7631  pFilename[0] = '\0';
7632  mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7633  return 0;
7634  }
7635  n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
7636  if (filename_buf_size)
7637  {
7638  n = MZ_MIN(n, filename_buf_size - 1);
7639  memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
7640  pFilename[n] = '\0';
7641  }
7642  return n + 1;
7643 }
7644 
7645 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
7646 {
7647  return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
7648 }
7649 
7650 mz_bool mz_zip_end(mz_zip_archive *pZip)
7651 {
7652  if (!pZip)
7653  return MZ_FALSE;
7654 
7655  if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
7656  return mz_zip_reader_end(pZip);
7657 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
7658  else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))
7659  return mz_zip_writer_end(pZip);
7660 #endif
7661 
7662  return MZ_FALSE;
7663 }
7664 
7665 #ifdef __cplusplus
7666 //}
7667 #endif
7668 
7669 #endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/