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__) || defined(__MINGW32__)
2990 
2991 #define WIN32_LEAN_AND_MEAN
2992 #include <windows.h>
2993 #include <string>
2994 
2995 static std::wstring convert_to_utf16(const char *s)
2996 {
2997  std::wstring utf16String;
2998  int inputSize = strlen(s);
2999  int requiredSize = MultiByteToWideChar(CP_UTF8, 0, s, inputSize, 0, 0);
3000  if( requiredSize > 0 )
3001  {
3002  utf16String.resize(requiredSize);
3003  MultiByteToWideChar(CP_UTF8, 0, s, inputSize, &utf16String[0], requiredSize);
3004  }
3005  return utf16String;
3006 }
3007 static FILE *mz_fopen(const char *pFilename, const char *pMode)
3008 {
3009  std::wstring wideFilename = convert_to_utf16(pFilename);
3010  std::wstring wideMode = convert_to_utf16(pMode);
3011 
3012  FILE *pFile = NULL;
3013  _wfopen_s(&pFile, wideFilename.c_str(), wideMode.c_str());
3014  return pFile;
3015 }
3016 static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
3017 {
3018  std::wstring widePath = convert_to_utf16(pPath);
3019  std::wstring wideMode = convert_to_utf16(pMode);
3020 
3021  FILE *pFile = NULL;
3022  if (_wfreopen_s(&pFile, widePath.c_str(), wideMode.c_str(), pStream))
3023  return NULL;
3024  return pFile;
3025 }
3026 #ifndef MINIZ_NO_TIME
3027 #include <sys/utime.h>
3028 #endif
3029 #define MZ_FOPEN mz_fopen
3030 #define MZ_FCLOSE fclose
3031 #define MZ_FREAD fread
3032 #define MZ_FWRITE fwrite
3033 #define MZ_FTELL64 _ftelli64
3034 #define MZ_FSEEK64 _fseeki64
3035 #define MZ_FILE_STAT_STRUCT _stat64
3036 #define MZ_FILE_STAT _stat64
3037 #define MZ_FFLUSH fflush
3038 #define MZ_FREOPEN mz_freopen
3039 #define MZ_DELETE_FILE remove
3040 //#elif defined(__MINGW32__)
3041 //#ifndef MINIZ_NO_TIME
3042 //#include <sys/utime.h>
3043 //#endif
3044 //#define MZ_FOPEN(f, m) fopen(f, m)
3045 //#define MZ_FCLOSE fclose
3046 //#define MZ_FREAD fread
3047 //#define MZ_FWRITE fwrite
3048 //#define MZ_FTELL64 ftello64
3049 //#define MZ_FSEEK64 fseeko64
3050 //#define MZ_FILE_STAT_STRUCT _stat
3051 //#define MZ_FILE_STAT _stat
3052 //#define MZ_FFLUSH fflush
3053 //#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3054 //#define MZ_DELETE_FILE remove
3055 #elif defined(__TINYC__)
3056 #ifndef MINIZ_NO_TIME
3057 #include <sys/utime.h>
3058 #endif
3059 #define MZ_FOPEN(f, m) fopen(f, m)
3060 #define MZ_FCLOSE fclose
3061 #define MZ_FREAD fread
3062 #define MZ_FWRITE fwrite
3063 #define MZ_FTELL64 ftell
3064 #define MZ_FSEEK64 fseek
3065 #define MZ_FILE_STAT_STRUCT stat
3066 #define MZ_FILE_STAT stat
3067 #define MZ_FFLUSH fflush
3068 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3069 #define MZ_DELETE_FILE remove
3070 #elif defined(__GNUC__) && defined(_LARGEFILE64_SOURCE)
3071 #ifndef MINIZ_NO_TIME
3072 #include <utime.h>
3073 #endif
3074 #define MZ_FOPEN(f, m) fopen64(f, m)
3075 #define MZ_FCLOSE fclose
3076 #define MZ_FREAD fread
3077 #define MZ_FWRITE fwrite
3078 #define MZ_FTELL64 ftello64
3079 #define MZ_FSEEK64 fseeko64
3080 #define MZ_FILE_STAT_STRUCT stat64
3081 #define MZ_FILE_STAT stat64
3082 #define MZ_FFLUSH fflush
3083 #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
3084 #define MZ_DELETE_FILE remove
3085 #elif defined(__APPLE__)
3086 #ifndef MINIZ_NO_TIME
3087 #include <utime.h>
3088 #endif
3089 #define MZ_FOPEN(f, m) fopen(f, m)
3090 #define MZ_FCLOSE fclose
3091 #define MZ_FREAD fread
3092 #define MZ_FWRITE fwrite
3093 #define MZ_FTELL64 ftello
3094 #define MZ_FSEEK64 fseeko
3095 #define MZ_FILE_STAT_STRUCT stat
3096 #define MZ_FILE_STAT stat
3097 #define MZ_FFLUSH fflush
3098 #define MZ_FREOPEN(p, m, s) freopen(p, m, s)
3099 #define MZ_DELETE_FILE remove
3100 
3101 #else
3102 #pragma message("Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.")
3103 #ifndef MINIZ_NO_TIME
3104 #include <utime.h>
3105 #endif
3106 #define MZ_FOPEN(f, m) fopen(f, m)
3107 #define MZ_FCLOSE fclose
3108 #define MZ_FREAD fread
3109 #define MZ_FWRITE fwrite
3110 #ifdef __STRICT_ANSI__
3111 #define MZ_FTELL64 ftell
3112 #define MZ_FSEEK64 fseek
3113 #else
3114 #define MZ_FTELL64 ftello
3115 #define MZ_FSEEK64 fseeko
3116 #endif
3117 #define MZ_FILE_STAT_STRUCT stat
3118 #define MZ_FILE_STAT stat
3119 #define MZ_FFLUSH fflush
3120 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3121 #define MZ_DELETE_FILE remove
3122 #endif /* #ifdef _MSC_VER */
3123 #endif /* #ifdef MINIZ_NO_STDIO */
3124 
3125 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
3126 
3127 /* 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. */
3128 enum
3129 {
3130  /* ZIP archive identifiers and record sizes */
3131  MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
3132  MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
3133  MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
3134  MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
3135  MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
3136  MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
3137 
3138  /* ZIP64 archive identifier and record sizes */
3139  MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
3140  MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
3141  MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
3142  MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
3143  MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
3144  MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
3145  MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
3146  MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
3147 
3148  /* Central directory header record offsets */
3149  MZ_ZIP_CDH_SIG_OFS = 0,
3150  MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
3151  MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
3152  MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
3153  MZ_ZIP_CDH_METHOD_OFS = 10,
3154  MZ_ZIP_CDH_FILE_TIME_OFS = 12,
3155  MZ_ZIP_CDH_FILE_DATE_OFS = 14,
3156  MZ_ZIP_CDH_CRC32_OFS = 16,
3157  MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
3158  MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
3159  MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
3160  MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
3161  MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
3162  MZ_ZIP_CDH_DISK_START_OFS = 34,
3163  MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
3164  MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
3165  MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
3166 
3167  /* Local directory header offsets */
3168  MZ_ZIP_LDH_SIG_OFS = 0,
3169  MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
3170  MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
3171  MZ_ZIP_LDH_METHOD_OFS = 8,
3172  MZ_ZIP_LDH_FILE_TIME_OFS = 10,
3173  MZ_ZIP_LDH_FILE_DATE_OFS = 12,
3174  MZ_ZIP_LDH_CRC32_OFS = 14,
3175  MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
3176  MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
3177  MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
3178  MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
3179  MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3,
3180 
3181  /* End of central directory offsets */
3182  MZ_ZIP_ECDH_SIG_OFS = 0,
3183  MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
3184  MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
3185  MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
3186  MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
3187  MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
3188  MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
3189  MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
3190 
3191  /* ZIP64 End of central directory locator offsets */
3192  MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */
3193  MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */
3194  MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */
3195  MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
3196 
3197  /* ZIP64 End of central directory header offsets */
3198  MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */
3199  MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */
3200  MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */
3201  MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */
3202  MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */
3203  MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */
3204  MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
3205  MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */
3206  MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */
3207  MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */
3208  MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
3209  MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
3210  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
3211  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
3212  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
3213  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
3214  MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
3215 };
3216 
3217 typedef struct
3218 {
3219  void *m_p;
3220  size_t m_size, m_capacity;
3221  mz_uint m_element_size;
3222 } mz_zip_array;
3223 
3225 {
3226  mz_zip_array m_central_dir;
3227  mz_zip_array m_central_dir_offsets;
3228  mz_zip_array m_sorted_central_dir_offsets;
3229 
3230  /* The flags passed in when the archive is initially opened. */
3231  uint32_t m_init_flags;
3232 
3233  /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */
3234  mz_bool m_zip64;
3235 
3236  /* 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.) */
3237  mz_bool m_zip64_has_extended_info_fields;
3238 
3239  /* These fields are used by the file, FILE, memory, and memory/heap read/write helpers. */
3240  MZ_FILE *m_pFile;
3241  mz_uint64 m_file_archive_start_ofs;
3242 
3243  void *m_pMem;
3244  size_t m_mem_size;
3245  size_t m_mem_capacity;
3246 };
3247 
3248 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
3249 
3250 #if defined(DEBUG) || defined(_DEBUG) || defined(NDEBUG)
3251 static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index)
3252 {
3253  MZ_ASSERT(index < pArray->m_size);
3254  return index;
3255 }
3256 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]
3257 #else
3258 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
3259 #endif
3260 
3261 static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size)
3262 {
3263  memset(pArray, 0, sizeof(mz_zip_array));
3264  pArray->m_element_size = element_size;
3265 }
3266 
3267 static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
3268 {
3269  pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
3270  memset(pArray, 0, sizeof(mz_zip_array));
3271 }
3272 
3273 static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
3274 {
3275  void *pNew_p;
3276  size_t new_capacity = min_new_capacity;
3277  MZ_ASSERT(pArray->m_element_size);
3278  if (pArray->m_capacity >= min_new_capacity)
3279  return MZ_TRUE;
3280  if (growing)
3281  {
3282  new_capacity = MZ_MAX(1, pArray->m_capacity);
3283  while (new_capacity < min_new_capacity)
3284  new_capacity *= 2;
3285  }
3286  if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
3287  return MZ_FALSE;
3288  pArray->m_p = pNew_p;
3289  pArray->m_capacity = new_capacity;
3290  return MZ_TRUE;
3291 }
3292 
3293 static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
3294 {
3295  if (new_capacity > pArray->m_capacity)
3296  {
3297  if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
3298  return MZ_FALSE;
3299  }
3300  return MZ_TRUE;
3301 }
3302 
3303 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
3304 {
3305  if (new_size > pArray->m_capacity)
3306  {
3307  if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
3308  return MZ_FALSE;
3309  }
3310  pArray->m_size = new_size;
3311  return MZ_TRUE;
3312 }
3313 
3314 static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
3315 {
3316  return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
3317 }
3318 
3319 static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
3320 {
3321  size_t orig_size = pArray->m_size;
3322  if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
3323  return MZ_FALSE;
3324  if (n > 0)
3325  memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
3326  return MZ_TRUE;
3327 }
3328 
3329 #ifndef MINIZ_NO_TIME
3330 static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)
3331 {
3332  struct tm tm;
3333  memset(&tm, 0, sizeof(tm));
3334  tm.tm_isdst = -1;
3335  tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
3336  tm.tm_mon = ((dos_date >> 5) & 15) - 1;
3337  tm.tm_mday = dos_date & 31;
3338  tm.tm_hour = (dos_time >> 11) & 31;
3339  tm.tm_min = (dos_time >> 5) & 63;
3340  tm.tm_sec = (dos_time << 1) & 62;
3341  return mktime(&tm);
3342 }
3343 
3344 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3345 static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3346 {
3347 #ifdef _MSC_VER
3348  struct tm tm_struct;
3349  struct tm *tm = &tm_struct;
3350  errno_t err = localtime_s(tm, &time);
3351  if (err)
3352  {
3353  *pDOS_date = 0;
3354  *pDOS_time = 0;
3355  return;
3356  }
3357 #else
3358  struct tm *tm = localtime(&time);
3359 #endif /* #ifdef _MSC_VER */
3360 
3361  *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
3362  *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
3363 }
3364 #endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
3365 
3366 #ifndef MINIZ_NO_STDIO
3367 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3368 static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime)
3369 {
3370  struct MZ_FILE_STAT_STRUCT file_stat;
3371 
3372  /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
3373  if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
3374  return MZ_FALSE;
3375 
3376  *pTime = file_stat.st_mtime;
3377 
3378  return MZ_TRUE;
3379 }
3380 #endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
3381 
3382 static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)
3383 {
3384  struct utimbuf t;
3385 
3386  memset(&t, 0, sizeof(t));
3387  t.actime = access_time;
3388  t.modtime = modified_time;
3389 
3390  return !utime(pFilename, &t);
3391 }
3392 #endif /* #ifndef MINIZ_NO_STDIO */
3393 #endif /* #ifndef MINIZ_NO_TIME */
3394 
3395 static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num)
3396 {
3397  if (pZip)
3398  pZip->m_last_error = err_num;
3399  return MZ_FALSE;
3400 }
3401 
3402 static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
3403 {
3404  (void)flags;
3405  if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3406  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3407 
3408  if (!pZip->m_pAlloc)
3409  pZip->m_pAlloc = miniz_def_alloc_func;
3410  if (!pZip->m_pFree)
3411  pZip->m_pFree = miniz_def_free_func;
3412  if (!pZip->m_pRealloc)
3413  pZip->m_pRealloc = miniz_def_realloc_func;
3414 
3415  pZip->m_archive_size = 0;
3416  pZip->m_central_directory_file_ofs = 0;
3417  pZip->m_total_files = 0;
3418  pZip->m_last_error = MZ_ZIP_NO_ERROR;
3419 
3420  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3421  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3422 
3423  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3424  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
3425  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
3426  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
3427  pZip->m_pState->m_init_flags = flags;
3428  pZip->m_pState->m_zip64 = MZ_FALSE;
3429  pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;
3430 
3431  pZip->m_zip_mode = MZ_ZIP_MODE_READING;
3432 
3433  return MZ_TRUE;
3434 }
3435 
3436 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)
3437 {
3438  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;
3439  const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
3440  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);
3441  mz_uint8 l = 0, r = 0;
3442  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3443  pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3444  pE = pL + MZ_MIN(l_len, r_len);
3445  while (pL < pE)
3446  {
3447  if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3448  break;
3449  pL++;
3450  pR++;
3451  }
3452  return (pL == pE) ? (l_len < r_len) : (l < r);
3453 }
3454 
3455 #define MZ_SWAP_UINT32(a, b) \
3456  do \
3457  { \
3458  mz_uint32 t = a; \
3459  a = b; \
3460  b = t; \
3461  } \
3462  MZ_MACRO_END
3463 
3464 /* 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.) */
3465 static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
3466 {
3467  mz_zip_internal_state *pState = pZip->m_pState;
3468  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3469  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3470  mz_uint32 *pIndices;
3471  mz_uint32 start, end;
3472  const mz_uint32 size = pZip->m_total_files;
3473 
3474  if (size <= 1U)
3475  return;
3476 
3477  pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
3478 
3479  start = (size - 2U) >> 1U;
3480  for (;;)
3481  {
3482  mz_uint64 child, root = start;
3483  for (;;)
3484  {
3485  if ((child = (root << 1U) + 1U) >= size)
3486  break;
3487  child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
3488  if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3489  break;
3490  MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3491  root = child;
3492  }
3493  if (!start)
3494  break;
3495  start--;
3496  }
3497 
3498  end = size - 1;
3499  while (end > 0)
3500  {
3501  mz_uint64 child, root = 0;
3502  MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
3503  for (;;)
3504  {
3505  if ((child = (root << 1U) + 1U) >= end)
3506  break;
3507  child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
3508  if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3509  break;
3510  MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3511  root = child;
3512  }
3513  end--;
3514  }
3515 }
3516 
3517 static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)
3518 {
3519  mz_int64 cur_file_ofs;
3520  mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3521  mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3522 
3523  /* Basic sanity checks - reject files which are too small */
3524  if (pZip->m_archive_size < record_size)
3525  return MZ_FALSE;
3526 
3527  /* Find the record by scanning the file from the end towards the beginning. */
3528  cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
3529  for (;;)
3530  {
3531  int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
3532 
3533  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
3534  return MZ_FALSE;
3535 
3536  for (i = n - 4; i >= 0; --i)
3537  {
3538  mz_uint s = MZ_READ_LE32(pBuf + i);
3539  if (s == record_sig)
3540  {
3541  if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
3542  break;
3543  }
3544  }
3545 
3546  if (i >= 0)
3547  {
3548  cur_file_ofs += i;
3549  break;
3550  }
3551 
3552  /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */
3553  if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size)))
3554  return MZ_FALSE;
3555 
3556  cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
3557  }
3558 
3559  *pOfs = cur_file_ofs;
3560  return MZ_TRUE;
3561 }
3562 
3563 static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)
3564 {
3565  mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
3566  mz_uint64 cdir_ofs = 0;
3567  mz_int64 cur_file_ofs = 0;
3568  const mz_uint8 *p;
3569 
3570  mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3571  mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3572  mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
3573  mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3574  mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
3575 
3576  mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3577  mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
3578 
3579  mz_uint64 zip64_end_of_central_dir_ofs = 0;
3580 
3581  /* 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. */
3582  if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3583  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3584 
3585  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))
3586  return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
3587 
3588  /* Read and verify the end of central directory record. */
3589  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)
3590  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3591 
3592  if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
3593  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3594 
3595  if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3596  {
3597  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)
3598  {
3599  if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG)
3600  {
3601  zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
3602  if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3603  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3604 
3605  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)
3606  {
3607  if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG)
3608  {
3609  pZip->m_pState->m_zip64 = MZ_TRUE;
3610  }
3611  }
3612  }
3613  }
3614  }
3615 
3616  pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3617  cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3618  num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
3619  cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
3620  cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
3621  cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
3622 
3623  if (pZip->m_pState->m_zip64)
3624  {
3625  mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
3626  mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3627  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);
3628  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);
3629  mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
3630 
3631  if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
3632  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3633 
3634  if (zip64_total_num_of_disks != 1U)
3635  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3636 
3637  /* Check for miniz's practical limits */
3638  if (zip64_cdir_total_entries > MZ_UINT32_MAX)
3639  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3640 
3641  pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
3642 
3643  if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
3644  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3645 
3646  cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;
3647 
3648  /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */
3649  if (zip64_size_of_central_directory > MZ_UINT32_MAX)
3650  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
3651 
3652  cdir_size = (mz_uint32)zip64_size_of_central_directory;
3653 
3654  num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
3655 
3656  cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
3657 
3658  cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
3659  }
3660 
3661  if (pZip->m_total_files != cdir_entries_on_this_disk)
3662  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3663 
3664  if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
3665  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3666 
3667  if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
3668  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3669 
3670  if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
3671  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3672 
3673  pZip->m_central_directory_file_ofs = cdir_ofs;
3674 
3675  if (pZip->m_total_files)
3676  {
3677  mz_uint i, n;
3678  /* 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. */
3679  if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
3680  (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
3681  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3682 
3683  if (sort_central_dir)
3684  {
3685  if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
3686  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3687  }
3688 
3689  if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
3690  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3691 
3692  /* Now create an index into the central directory file records, do some basic sanity checking on each record */
3693  p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
3694  for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
3695  {
3696  mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
3697  mz_uint64 comp_size, decomp_size, local_header_ofs;
3698 
3699  if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
3700  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3701 
3702  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);
3703 
3704  if (sort_central_dir)
3705  MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
3706 
3707  comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3708  decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3709  local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3710  filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3711  ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
3712 
3713  if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
3714  (ext_data_size) &&
3715  (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
3716  {
3717  /* Attempt to find zip64 extended information field in the entry's extra data */
3718  mz_uint32 extra_size_remaining = ext_data_size;
3719 
3720  if (extra_size_remaining)
3721  {
3722  const mz_uint8 *pExtra_data;
3723  void* buf = NULL;
3724 
3725  if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n)
3726  {
3727  buf = MZ_MALLOC(ext_data_size);
3728  if(buf==NULL)
3729  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3730 
3731  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)
3732  {
3733  MZ_FREE(buf);
3734  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3735  }
3736 
3737  pExtra_data = (mz_uint8*)buf;
3738  }
3739  else
3740  {
3741  pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
3742  }
3743 
3744  do
3745  {
3746  mz_uint32 field_id;
3747  mz_uint32 field_data_size;
3748 
3749  if (extra_size_remaining < (sizeof(mz_uint16) * 2))
3750  {
3751  MZ_FREE(buf);
3752  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3753  }
3754 
3755  field_id = MZ_READ_LE16(pExtra_data);
3756  field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
3757 
3758  if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
3759  {
3760  MZ_FREE(buf);
3761  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3762  }
3763 
3764  if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
3765  {
3766  /* 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). */
3767  pZip->m_pState->m_zip64 = MZ_TRUE;
3768  pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
3769  break;
3770  }
3771 
3772  pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
3773  extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
3774  } while (extra_size_remaining);
3775 
3776  MZ_FREE(buf);
3777  }
3778  }
3779 
3780  /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */
3781  if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
3782  {
3783  if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
3784  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3785  }
3786 
3787  disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
3788  if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
3789  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3790 
3791  if (comp_size != MZ_UINT32_MAX)
3792  {
3793  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)
3794  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3795  }
3796 
3797  bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3798  if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
3799  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
3800 
3801  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)
3802  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3803 
3804  n -= total_header_size;
3805  p += total_header_size;
3806  }
3807  }
3808 
3809  if (sort_central_dir)
3810  mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
3811 
3812  return MZ_TRUE;
3813 }
3814 
3815 void mz_zip_zero_struct(mz_zip_archive *pZip)
3816 {
3817  if (pZip)
3818  MZ_CLEAR_OBJ(*pZip);
3819 }
3820 
3821 static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
3822 {
3823  mz_bool status = MZ_TRUE;
3824 
3825  if (!pZip)
3826  return MZ_FALSE;
3827 
3828  if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3829  {
3830  if (set_last_error)
3831  pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;
3832 
3833  return MZ_FALSE;
3834  }
3835 
3836  if (pZip->m_pState)
3837  {
3838  mz_zip_internal_state *pState = pZip->m_pState;
3839  pZip->m_pState = NULL;
3840 
3841  mz_zip_array_clear(pZip, &pState->m_central_dir);
3842  mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
3843  mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
3844 
3845 #ifndef MINIZ_NO_STDIO
3846  if (pState->m_pFile)
3847  {
3848  if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
3849  {
3850  if (MZ_FCLOSE(pState->m_pFile) == EOF)
3851  {
3852  if (set_last_error)
3853  pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED;
3854  status = MZ_FALSE;
3855  }
3856  }
3857  pState->m_pFile = NULL;
3858  }
3859 #endif /* #ifndef MINIZ_NO_STDIO */
3860 
3861  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
3862  }
3863  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
3864 
3865  return status;
3866 }
3867 
3868 mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
3869 {
3870  return mz_zip_reader_end_internal(pZip, MZ_TRUE);
3871 }
3872 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
3873 {
3874  if ((!pZip) || (!pZip->m_pRead))
3875  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3876 
3877  if (!mz_zip_reader_init_internal(pZip, flags))
3878  return MZ_FALSE;
3879 
3880  pZip->m_zip_type = MZ_ZIP_TYPE_USER;
3881  pZip->m_archive_size = size;
3882 
3883  if (!mz_zip_reader_read_central_dir(pZip, flags))
3884  {
3885  mz_zip_reader_end_internal(pZip, MZ_FALSE);
3886  return MZ_FALSE;
3887  }
3888 
3889  return MZ_TRUE;
3890 }
3891 
3892 static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3893 {
3894  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3895  size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
3896  memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
3897  return s;
3898 }
3899 
3900 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)
3901 {
3902  if (!pMem)
3903  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3904 
3905  if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3906  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3907 
3908  if (!mz_zip_reader_init_internal(pZip, flags))
3909  return MZ_FALSE;
3910 
3911  pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY;
3912  pZip->m_archive_size = size;
3913  pZip->m_pRead = mz_zip_mem_read_func;
3914  pZip->m_pIO_opaque = pZip;
3915  pZip->m_pNeeds_keepalive = NULL;
3916 
3917 #ifdef __cplusplus
3918  pZip->m_pState->m_pMem = const_cast<void *>(pMem);
3919 #else
3920  pZip->m_pState->m_pMem = (void *)pMem;
3921 #endif
3922 
3923  pZip->m_pState->m_mem_size = size;
3924 
3925  if (!mz_zip_reader_read_central_dir(pZip, flags))
3926  {
3927  mz_zip_reader_end_internal(pZip, MZ_FALSE);
3928  return MZ_FALSE;
3929  }
3930 
3931  return MZ_TRUE;
3932 }
3933 
3934 #ifndef MINIZ_NO_STDIO
3935 static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3936 {
3937  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3938  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
3939 
3940  file_ofs += pZip->m_pState->m_file_archive_start_ofs;
3941 
3942  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))))
3943  return 0;
3944 
3945  return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
3946 }
3947 
3948 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
3949 {
3950  return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);
3951 }
3952 
3953 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)
3954 {
3955  mz_uint64 file_size;
3956  MZ_FILE *pFile;
3957 
3958  if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
3959  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3960 
3961  pFile = MZ_FOPEN(pFilename, "rb");
3962  if (!pFile)
3963  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
3964 
3965  file_size = archive_size;
3966  if (!file_size)
3967  {
3968  if (MZ_FSEEK64(pFile, 0, SEEK_END))
3969  {
3970  MZ_FCLOSE(pFile);
3971  return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
3972  }
3973 
3974  file_size = MZ_FTELL64(pFile);
3975  }
3976 
3977  /* TODO: Better sanity check archive_size and the # of actual remaining bytes */
3978 
3979  if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3980  {
3981  MZ_FCLOSE(pFile);
3982  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3983  }
3984 
3985  if (!mz_zip_reader_init_internal(pZip, flags))
3986  {
3987  MZ_FCLOSE(pFile);
3988  return MZ_FALSE;
3989  }
3990 
3991  pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
3992  pZip->m_pRead = mz_zip_file_read_func;
3993  pZip->m_pIO_opaque = pZip;
3994  pZip->m_pState->m_pFile = pFile;
3995  pZip->m_archive_size = file_size;
3996  pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;
3997 
3998  if (!mz_zip_reader_read_central_dir(pZip, flags))
3999  {
4000  mz_zip_reader_end_internal(pZip, MZ_FALSE);
4001  return MZ_FALSE;
4002  }
4003 
4004  return MZ_TRUE;
4005 }
4006 
4007 mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags)
4008 {
4009  mz_uint64 cur_file_ofs;
4010 
4011  if ((!pZip) || (!pFile))
4012  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
4013 
4014  cur_file_ofs = MZ_FTELL64(pFile);
4015 
4016  if (!archive_size)
4017  {
4018  if (MZ_FSEEK64(pFile, 0, SEEK_END))
4019  return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
4020 
4021  archive_size = MZ_FTELL64(pFile) - cur_file_ofs;
4022 
4023  if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4024  return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4025  }
4026 
4027  if (!mz_zip_reader_init_internal(pZip, flags))
4028  return MZ_FALSE;
4029 
4030  pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
4031  pZip->m_pRead = mz_zip_file_read_func;
4032 
4033  pZip->m_pIO_opaque = pZip;
4034  pZip->m_pState->m_pFile = pFile;
4035  pZip->m_archive_size = archive_size;
4036  pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;
4037 
4038  if (!mz_zip_reader_read_central_dir(pZip, flags))
4039  {
4040  mz_zip_reader_end_internal(pZip, MZ_FALSE);
4041  return MZ_FALSE;
4042  }
4043 
4044  return MZ_TRUE;
4045 }
4046 
4047 #endif /* #ifndef MINIZ_NO_STDIO */
4048 
4049 static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
4050 {
4051  if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
4052  return NULL;
4053  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));
4054 }
4055 
4056 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
4057 {
4058  mz_uint m_bit_flag;
4059  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4060  if (!p)
4061  {
4062  mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4063  return MZ_FALSE;
4064  }
4065 
4066  m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4067  return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;
4068 }
4069 
4070 mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)
4071 {
4072  mz_uint bit_flag;
4073  mz_uint method;
4074 
4075  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4076  if (!p)
4077  {
4078  mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4079  return MZ_FALSE;
4080  }
4081 
4082  method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4083  bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4084 
4085  if ((method != 0) && (method != MZ_DEFLATED))
4086  {
4087  mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4088  return MZ_FALSE;
4089  }
4090 
4091  if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION))
4092  {
4093  mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4094  return MZ_FALSE;
4095  }
4096 
4097  if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)
4098  {
4099  mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
4100  return MZ_FALSE;
4101  }
4102 
4103  return MZ_TRUE;
4104 }
4105 
4106 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
4107 {
4108  mz_uint filename_len, attribute_mapping_id, external_attr;
4109  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4110  if (!p)
4111  {
4112  mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4113  return MZ_FALSE;
4114  }
4115 
4116  filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4117  if (filename_len)
4118  {
4119  if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
4120  return MZ_TRUE;
4121  }
4122 
4123  /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */
4124  /* 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. */
4125  /* FIXME: Remove this check? Is it necessary - we already check the filename. */
4126  attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
4127  (void)attribute_mapping_id;
4128 
4129  external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4130  if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
4131  {
4132  return MZ_TRUE;
4133  }
4134 
4135  return MZ_FALSE;
4136 }
4137 
4138 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)
4139 {
4140  mz_uint n;
4141  const mz_uint8 *p = pCentral_dir_header;
4142 
4143  if (pFound_zip64_extra_data)
4144  *pFound_zip64_extra_data = MZ_FALSE;
4145 
4146  if ((!p) || (!pStat))
4147  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4148 
4149  /* Extract fields from the central directory record. */
4150  pStat->m_file_index = file_index;
4151  pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
4152  pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
4153  pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
4154  pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4155  pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4156 #ifndef MINIZ_NO_TIME
4157  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));
4158 #endif
4159  pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
4160  pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4161  pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4162  pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
4163  pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4164  pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4165 
4166  /* Copy as much of the filename and comment as possible. */
4167  n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4168  n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
4169  memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
4170  pStat->m_filename[n] = '\0';
4171 
4172  n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4173  n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
4174  pStat->m_comment_size = n;
4175  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);
4176  pStat->m_comment[n] = '\0';
4177 
4178  /* Set some flags for convienance */
4179  pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
4180  pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
4181  pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
4182 
4183  /* See if we need to read any zip64 extended information fields. */
4184  /* 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). */
4185  if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX)
4186  {
4187  /* Attempt to find zip64 extended information field in the entry's extra data */
4188  mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4189 
4190  if (extra_size_remaining)
4191  {
4192  const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4193 
4194  do
4195  {
4196  mz_uint32 field_id;
4197  mz_uint32 field_data_size;
4198 
4199  if (extra_size_remaining < (sizeof(mz_uint16) * 2))
4200  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4201 
4202  field_id = MZ_READ_LE16(pExtra_data);
4203  field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4204 
4205  if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
4206  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4207 
4208  if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
4209  {
4210  const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
4211  mz_uint32 field_data_remaining = field_data_size;
4212 
4213  if (pFound_zip64_extra_data)
4214  *pFound_zip64_extra_data = MZ_TRUE;
4215 
4216  if (pStat->m_uncomp_size == MZ_UINT32_MAX)
4217  {
4218  if (field_data_remaining < sizeof(mz_uint64))
4219  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4220 
4221  pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
4222  pField_data += sizeof(mz_uint64);
4223  field_data_remaining -= sizeof(mz_uint64);
4224  }
4225 
4226  if (pStat->m_comp_size == MZ_UINT32_MAX)
4227  {
4228  if (field_data_remaining < sizeof(mz_uint64))
4229  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4230 
4231  pStat->m_comp_size = MZ_READ_LE64(pField_data);
4232  pField_data += sizeof(mz_uint64);
4233  field_data_remaining -= sizeof(mz_uint64);
4234  }
4235 
4236  if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
4237  {
4238  if (field_data_remaining < sizeof(mz_uint64))
4239  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4240 
4241  pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
4242  pField_data += sizeof(mz_uint64);
4243  field_data_remaining -= sizeof(mz_uint64);
4244  }
4245 
4246  break;
4247  }
4248 
4249  pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4250  extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4251  } while (extra_size_remaining);
4252  }
4253  }
4254 
4255  return MZ_TRUE;
4256 }
4257 
4258 static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
4259 {
4260  mz_uint i;
4261  if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
4262  return 0 == memcmp(pA, pB, len);
4263  for (i = 0; i < len; ++i)
4264  if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
4265  return MZ_FALSE;
4266  return MZ_TRUE;
4267 }
4268 
4269 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)
4270 {
4271  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;
4272  mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4273  mz_uint8 l = 0, r = 0;
4274  pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4275  pE = pL + MZ_MIN(l_len, r_len);
4276  while (pL < pE)
4277  {
4278  if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4279  break;
4280  pL++;
4281  pR++;
4282  }
4283  return (pL == pE) ? (int)(l_len - r_len) : (l - r);
4284 }
4285 
4286 static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
4287 {
4288  mz_zip_internal_state *pState = pZip->m_pState;
4289  const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4290  const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4291  mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4292  const uint32_t size = pZip->m_total_files;
4293  const mz_uint filename_len = (mz_uint)strlen(pFilename);
4294 
4295  if (pIndex)
4296  *pIndex = 0;
4297 
4298  if (size)
4299  {
4300  /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */
4301  /* honestly the major expense here on 32-bit CPU's will still be the filename compare */
4302  mz_int64 l = 0, h = (mz_int64)size - 1;
4303 
4304  while (l <= h)
4305  {
4306  mz_int64 m = l + ((h - l) >> 1);
4307  uint32_t file_index = pIndices[(uint32_t)m];
4308 
4309  int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
4310  if (!comp)
4311  {
4312  if (pIndex)
4313  *pIndex = file_index;
4314  return MZ_TRUE;
4315  }
4316  else if (comp < 0)
4317  l = m + 1;
4318  else
4319  h = m - 1;
4320  }
4321  }
4322 
4323  return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4324 }
4325 
4326 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
4327 {
4328  mz_uint32 index;
4329  if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
4330  return -1;
4331  else
4332  return (int)index;
4333 }
4334 
4335 mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
4336 {
4337  mz_uint file_index;
4338  size_t name_len, comment_len;
4339 
4340  if (pIndex)
4341  *pIndex = 0;
4342 
4343  if ((!pZip) || (!pZip->m_pState) || (!pName))
4344  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4345 
4346  /* See if we can use a binary search */
4347  if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&
4348  (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
4349  ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
4350  {
4351  return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
4352  }
4353 
4354  /* Locate the entry by scanning the entire central directory */
4355  name_len = strlen(pName);
4356  if (name_len > MZ_UINT16_MAX)
4357  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4358 
4359  comment_len = pComment ? strlen(pComment) : 0;
4360  if (comment_len > MZ_UINT16_MAX)
4361  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4362 
4363  for (file_index = 0; file_index < pZip->m_total_files; file_index++)
4364  {
4365  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));
4366  mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4367  const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4368  if (filename_len < name_len)
4369  continue;
4370  if (comment_len)
4371  {
4372  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);
4373  const char *pFile_comment = pFilename + filename_len + file_extra_len;
4374  if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
4375  continue;
4376  }
4377  if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
4378  {
4379  int ofs = filename_len - 1;
4380  do
4381  {
4382  if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
4383  break;
4384  } while (--ofs >= 0);
4385  ofs++;
4386  pFilename += ofs;
4387  filename_len -= ofs;
4388  }
4389  if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
4390  {
4391  if (pIndex)
4392  *pIndex = file_index;
4393  return MZ_TRUE;
4394  }
4395  }
4396 
4397  return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4398 }
4399 
4400 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)
4401 {
4402  int status = TINFL_STATUS_DONE;
4403  mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
4404  mz_zip_archive_file_stat file_stat;
4405  void *pRead_buf;
4406  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4407  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4408  tinfl_decompressor inflator;
4409 
4410  if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
4411  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4412 
4413  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4414  return MZ_FALSE;
4415 
4416  /* A directory or zero length file */
4417  if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4418  return MZ_TRUE;
4419 
4420  /* Encryption and patch files are not supported. */
4421  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))
4422  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4423 
4424  /* This function only supports decompressing stored and deflate. */
4425  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4426  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4427 
4428  /* Ensure supplied output buffer is large enough. */
4429  needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
4430  if (buf_size < needed_size)
4431  return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);
4432 
4433  /* Read and parse the local directory entry. */
4434  cur_file_ofs = file_stat.m_local_header_ofs;
4435  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)
4436  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4437 
4438  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4439  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4440 
4441  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);
4442  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4443  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4444 
4445  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4446  {
4447  /* The file is stored or the caller has requested the compressed data. */
4448  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
4449  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4450 
4451 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4452  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
4453  {
4454  if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4455  return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4456  }
4457 #endif
4458 
4459  return MZ_TRUE;
4460  }
4461 
4462  /* Decompress the file either directly from memory or from a file input buffer. */
4463  tinfl_init(&inflator);
4464 
4465  if (pZip->m_pState->m_pMem)
4466  {
4467  /* Read directly from the archive in memory. */
4468  pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4469  read_buf_size = read_buf_avail = file_stat.m_comp_size;
4470  comp_remaining = 0;
4471  }
4472  else if (pUser_read_buf)
4473  {
4474  /* Use a user provided read buffer. */
4475  if (!user_read_buf_size)
4476  return MZ_FALSE;
4477  pRead_buf = (mz_uint8 *)pUser_read_buf;
4478  read_buf_size = user_read_buf_size;
4479  read_buf_avail = 0;
4480  comp_remaining = file_stat.m_comp_size;
4481  }
4482  else
4483  {
4484  /* Temporarily allocate a read buffer. */
4485  read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4486  if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
4487  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4488 
4489  if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4490  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4491 
4492  read_buf_avail = 0;
4493  comp_remaining = file_stat.m_comp_size;
4494  }
4495 
4496  do
4497  {
4498  /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */
4499  size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
4500  if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4501  {
4502  read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4503  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4504  {
4505  status = TINFL_STATUS_FAILED;
4506  mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4507  break;
4508  }
4509  cur_file_ofs += read_buf_avail;
4510  comp_remaining -= read_buf_avail;
4511  read_buf_ofs = 0;
4512  }
4513  in_buf_size = (size_t)read_buf_avail;
4514  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));
4515  read_buf_avail -= in_buf_size;
4516  read_buf_ofs += in_buf_size;
4517  out_buf_ofs += out_buf_size;
4518  } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
4519 
4520  if (status == TINFL_STATUS_DONE)
4521  {
4522  /* Make sure the entire file was decompressed, and check its CRC. */
4523  if (out_buf_ofs != file_stat.m_uncomp_size)
4524  {
4525  mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4526  status = TINFL_STATUS_FAILED;
4527  }
4528 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4529  else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4530  {
4531  mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4532  status = TINFL_STATUS_FAILED;
4533  }
4534 #endif
4535  }
4536 
4537  if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
4538  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4539 
4540  return status == TINFL_STATUS_DONE;
4541 }
4542 
4543 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)
4544 {
4545  mz_uint32 file_index;
4546  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4547  return MZ_FALSE;
4548  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
4549 }
4550 
4551 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)
4552 {
4553  return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
4554 }
4555 
4556 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)
4557 {
4558  return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
4559 }
4560 
4561 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
4562 {
4563  mz_uint64 comp_size, uncomp_size, alloc_size;
4564  const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4565  void *pBuf;
4566 
4567  if (pSize)
4568  *pSize = 0;
4569 
4570  if (!p)
4571  {
4572  mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4573  return NULL;
4574  }
4575 
4576  comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4577  uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4578 
4579  alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
4580  if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
4581  {
4582  mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4583  return NULL;
4584  }
4585 
4586  if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
4587  {
4588  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4589  return NULL;
4590  }
4591 
4592  if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
4593  {
4594  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4595  return NULL;
4596  }
4597 
4598  if (pSize)
4599  *pSize = (size_t)alloc_size;
4600  return pBuf;
4601 }
4602 
4603 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
4604 {
4605  mz_uint32 file_index;
4606  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4607  {
4608  if (pSize)
4609  *pSize = 0;
4610  return MZ_FALSE;
4611  }
4612  return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
4613 }
4614 
4615 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)
4616 {
4617  int status = TINFL_STATUS_DONE;
4618  mz_uint file_crc32 = MZ_CRC32_INIT;
4619  mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
4620  mz_zip_archive_file_stat file_stat;
4621  void *pRead_buf = NULL;
4622  void *pWrite_buf = NULL;
4623  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4624  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4625 
4626  if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))
4627  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4628 
4629  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4630  return MZ_FALSE;
4631 
4632  /* A directory or zero length file */
4633  if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4634  return MZ_TRUE;
4635 
4636  /* Encryption and patch files are not supported. */
4637  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))
4638  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4639 
4640  /* This function only supports decompressing stored and deflate. */
4641  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4642  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4643 
4644  /* 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) */
4645  cur_file_ofs = file_stat.m_local_header_ofs;
4646  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)
4647  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4648 
4649  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4650  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4651 
4652  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);
4653  if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4654  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4655 
4656  /* Decompress the file either directly from memory or from a file input buffer. */
4657  if (pZip->m_pState->m_pMem)
4658  {
4659  pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4660  read_buf_size = read_buf_avail = file_stat.m_comp_size;
4661  comp_remaining = 0;
4662  }
4663  else
4664  {
4665  read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4666  if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4667  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4668 
4669  read_buf_avail = 0;
4670  comp_remaining = file_stat.m_comp_size;
4671  }
4672 
4673  if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4674  {
4675  /* The file is stored or the caller has requested the compressed data. */
4676  if (pZip->m_pState->m_pMem)
4677  {
4678  if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX))
4679  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4680 
4681  if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
4682  {
4683  mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4684  status = TINFL_STATUS_FAILED;
4685  }
4686  else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4687  {
4688 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4689  file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
4690 #endif
4691  }
4692 
4693  cur_file_ofs += file_stat.m_comp_size;
4694  out_buf_ofs += file_stat.m_comp_size;
4695  comp_remaining = 0;
4696  }
4697  else
4698  {
4699  while (comp_remaining)
4700  {
4701  read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4702  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4703  {
4704  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4705  status = TINFL_STATUS_FAILED;
4706  break;
4707  }
4708 
4709 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4710  if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4711  {
4712  file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
4713  }
4714 #endif
4715 
4716  if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4717  {
4718  mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4719  status = TINFL_STATUS_FAILED;
4720  break;
4721  }
4722 
4723  cur_file_ofs += read_buf_avail;
4724  out_buf_ofs += read_buf_avail;
4725  comp_remaining -= read_buf_avail;
4726  }
4727  }
4728  }
4729  else
4730  {
4731  tinfl_decompressor inflator;
4732  tinfl_init(&inflator);
4733 
4734  if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4735  {
4736  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4737  status = TINFL_STATUS_FAILED;
4738  }
4739  else
4740  {
4741  do
4742  {
4743  mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4744  size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4745  if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4746  {
4747  read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4748  if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4749  {
4750  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4751  status = TINFL_STATUS_FAILED;
4752  break;
4753  }
4754  cur_file_ofs += read_buf_avail;
4755  comp_remaining -= read_buf_avail;
4756  read_buf_ofs = 0;
4757  }
4758 
4759  in_buf_size = (size_t)read_buf_avail;
4760  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);
4761  read_buf_avail -= in_buf_size;
4762  read_buf_ofs += in_buf_size;
4763 
4764  if (out_buf_size)
4765  {
4766  if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
4767  {
4768  mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4769  status = TINFL_STATUS_FAILED;
4770  break;
4771  }
4772 
4773 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4774  file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
4775 #endif
4776  if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
4777  {
4778  mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4779  status = TINFL_STATUS_FAILED;
4780  break;
4781  }
4782  }
4783  } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
4784  }
4785  }
4786 
4787  if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
4788  {
4789  /* Make sure the entire file was decompressed, and check its CRC. */
4790  if (out_buf_ofs != file_stat.m_uncomp_size)
4791  {
4792  mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4793  status = TINFL_STATUS_FAILED;
4794  }
4795 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4796  else if (file_crc32 != file_stat.m_crc32)
4797  {
4798  mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4799  status = TINFL_STATUS_FAILED;
4800  }
4801 #endif
4802  }
4803 
4804  if (!pZip->m_pState->m_pMem)
4805  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4806 
4807  if (pWrite_buf)
4808  pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
4809 
4810  return status == TINFL_STATUS_DONE;
4811 }
4812 
4813 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)
4814 {
4815  mz_uint32 file_index;
4816  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4817  return MZ_FALSE;
4818 
4819  return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
4820 }
4821 
4822 mz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
4823 {
4825  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4826  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4827 
4828  /* Argument sanity check */
4829  if ((!pZip) || (!pZip->m_pState))
4830  return NULL;
4831 
4832  /* Allocate an iterator status structure */
4833  pState = (mz_zip_reader_extract_iter_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_reader_extract_iter_state));
4834  if (!pState)
4835  {
4836  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4837  return NULL;
4838  }
4839 
4840  /* Fetch file details */
4841  if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat))
4842  {
4843  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4844  return NULL;
4845  }
4846 
4847  /* Encryption and patch files are not supported. */
4848  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))
4849  {
4850  mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4851  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4852  return NULL;
4853  }
4854 
4855  /* This function only supports decompressing stored and deflate. */
4856  if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (pState->file_stat.m_method != 0) && (pState->file_stat.m_method != MZ_DEFLATED))
4857  {
4858  mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4859  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4860  return NULL;
4861  }
4862 
4863  /* Init state - save args */
4864  pState->pZip = pZip;
4865  pState->flags = flags;
4866 
4867  /* Init state - reset variables to defaults */
4868  pState->status = TINFL_STATUS_DONE;
4869 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4870  pState->file_crc32 = MZ_CRC32_INIT;
4871 #endif
4872  pState->read_buf_ofs = 0;
4873  pState->out_buf_ofs = 0;
4874  pState->pRead_buf = NULL;
4875  pState->pWrite_buf = NULL;
4876  pState->out_blk_remain = 0;
4877 
4878  /* Read and parse the local directory entry. */
4879  pState->cur_file_ofs = pState->file_stat.m_local_header_ofs;
4880  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)
4881  {
4882  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4883  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4884  return NULL;
4885  }
4886 
4887  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4888  {
4889  mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4890  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4891  return NULL;
4892  }
4893 
4894  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);
4895  if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > pZip->m_archive_size)
4896  {
4897  mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4898  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4899  return NULL;
4900  }
4901 
4902  /* Decompress the file either directly from memory or from a file input buffer. */
4903  if (pZip->m_pState->m_pMem)
4904  {
4905  pState->pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs;
4906  pState->read_buf_size = pState->read_buf_avail = pState->file_stat.m_comp_size;
4907  pState->comp_remaining = pState->file_stat.m_comp_size;
4908  }
4909  else
4910  {
4911  if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
4912  {
4913  /* Decompression required, therefore intermediate read buffer required */
4914  pState->read_buf_size = MZ_MIN(pState->file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
4915  if (NULL == (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)pState->read_buf_size)))
4916  {
4917  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4918  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4919  return NULL;
4920  }
4921  }
4922  else
4923  {
4924  /* Decompression not required - we will be reading directly into user buffer, no temp buf required */
4925  pState->read_buf_size = 0;
4926  }
4927  pState->read_buf_avail = 0;
4928  pState->comp_remaining = pState->file_stat.m_comp_size;
4929  }
4930 
4931  if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
4932  {
4933  /* Decompression required, init decompressor */
4934  tinfl_init( &pState->inflator );
4935 
4936  /* Allocate write buffer */
4937  if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4938  {
4939  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4940  if (pState->pRead_buf)
4941  pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf);
4942  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4943  return NULL;
4944  }
4945  }
4946 
4947  return pState;
4948 }
4949 
4950 mz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
4951 {
4952  mz_uint32 file_index;
4953 
4954  /* Locate file index by name */
4955  if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4956  return NULL;
4957 
4958  /* Construct iterator */
4959  return mz_zip_reader_extract_iter_new(pZip, file_index, flags);
4960 }
4961 
4962 size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size)
4963 {
4964  size_t copied_to_caller = 0;
4965 
4966  /* Argument sanity check */
4967  if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf))
4968  return 0;
4969 
4970  if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))
4971  {
4972  /* The file is stored or the caller has requested the compressed data, calc amount to return. */
4973  copied_to_caller = (size_t)MZ_MIN( buf_size, pState->comp_remaining );
4974 
4975  /* Zip is in memory....or requires reading from a file? */
4976  if (pState->pZip->m_pState->m_pMem)
4977  {
4978  /* Copy data to caller's buffer */
4979  memcpy( pvBuf, pState->pRead_buf, copied_to_caller );
4980  pState->pRead_buf = ((mz_uint8*)pState->pRead_buf) + copied_to_caller;
4981  }
4982  else
4983  {
4984  /* Read directly into caller's buffer */
4985  if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, copied_to_caller) != copied_to_caller)
4986  {
4987  /* Failed to read all that was asked for, flag failure and alert user */
4988  mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
4989  pState->status = TINFL_STATUS_FAILED;
4990  copied_to_caller = 0;
4991  }
4992  }
4993 
4994 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4995  /* Compute CRC if not returning compressed data only */
4996  if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4997  pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, (const mz_uint8 *)pvBuf, copied_to_caller);
4998 #endif
4999 
5000  /* Advance offsets, dec counters */
5001  pState->cur_file_ofs += copied_to_caller;
5002  pState->out_buf_ofs += copied_to_caller;
5003  pState->comp_remaining -= copied_to_caller;
5004  }
5005  else
5006  {
5007  do
5008  {
5009  /* Calc ptr to write buffer - given current output pos and block size */
5010  mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pState->pWrite_buf + (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5011 
5012  /* Calc max output size - given current output pos and block size */
5013  size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5014 
5015  if (!pState->out_blk_remain)
5016  {
5017  /* Read more data from file if none available (and reading from file) */
5018  if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem))
5019  {
5020  /* Calc read size */
5021  pState->read_buf_avail = MZ_MIN(pState->read_buf_size, pState->comp_remaining);
5022  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)
5023  {
5024  mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
5025  pState->status = TINFL_STATUS_FAILED;
5026  break;
5027  }
5028 
5029  /* Advance offsets, dec counters */
5030  pState->cur_file_ofs += pState->read_buf_avail;
5031  pState->comp_remaining -= pState->read_buf_avail;
5032  pState->read_buf_ofs = 0;
5033  }
5034 
5035  /* Perform decompression */
5036  in_buf_size = (size_t)pState->read_buf_avail;
5037  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);
5038  pState->read_buf_avail -= in_buf_size;
5039  pState->read_buf_ofs += in_buf_size;
5040 
5041  /* Update current output block size remaining */
5042  pState->out_blk_remain = out_buf_size;
5043  }
5044 
5045  if (pState->out_blk_remain)
5046  {
5047  /* Calc amount to return. */
5048  size_t to_copy = MZ_MIN( (buf_size - copied_to_caller), pState->out_blk_remain );
5049 
5050  /* Copy data to caller's buffer */
5051  memcpy( (uint8_t*)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy );
5052 
5053 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5054  /* Perform CRC */
5055  pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy);
5056 #endif
5057 
5058  /* Decrement data consumed from block */
5059  pState->out_blk_remain -= to_copy;
5060 
5061  /* Inc output offset, while performing sanity check */
5062  if ((pState->out_buf_ofs += to_copy) > pState->file_stat.m_uncomp_size)
5063  {
5064  mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5065  pState->status = TINFL_STATUS_FAILED;
5066  break;
5067  }
5068 
5069  /* Increment counter of data copied to caller */
5070  copied_to_caller += to_copy;
5071  }
5072  } while ( (copied_to_caller < buf_size) && ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)) );
5073  }
5074 
5075  /* Return how many bytes were copied into user buffer */
5076  return copied_to_caller;
5077 }
5078 
5079 mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState)
5080 {
5081  int status;
5082 
5083  /* Argument sanity check */
5084  if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState))
5085  return MZ_FALSE;
5086 
5087  /* Was decompression completed and requested? */
5088  if ((pState->status == TINFL_STATUS_DONE) && (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
5089  {
5090  /* Make sure the entire file was decompressed, and check its CRC. */
5091  if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size)
5092  {
5093  mz_zip_set_error(pState->pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
5094  pState->status = TINFL_STATUS_FAILED;
5095  }
5096 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5097  else if (pState->file_crc32 != pState->file_stat.m_crc32)
5098  {
5099  mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5100  pState->status = TINFL_STATUS_FAILED;
5101  }
5102 #endif
5103  }
5104 
5105  /* Free buffers */
5106  if (!pState->pZip->m_pState->m_pMem)
5107  pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf);
5108  if (pState->pWrite_buf)
5109  pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf);
5110 
5111  /* Save status */
5112  status = pState->status;
5113 
5114  /* Free context */
5115  pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState);
5116 
5117  return status == TINFL_STATUS_DONE;
5118 }
5119 
5120 #ifndef MINIZ_NO_STDIO
5121 static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
5122 {
5123  (void)ofs;
5124 
5125  return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5126 }
5127 
5128 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
5129 {
5130  mz_bool status;
5131  mz_zip_archive_file_stat file_stat;
5132  MZ_FILE *pFile;
5133 
5134  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5135  return MZ_FALSE;
5136 
5137  if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5138  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5139 
5140  pFile = MZ_FOPEN(pDst_filename, "wb");
5141  if (!pFile)
5142  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5143 
5144  status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5145 
5146  if (MZ_FCLOSE(pFile) == EOF)
5147  {
5148  if (status)
5149  mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5150 
5151  status = MZ_FALSE;
5152  }
5153 
5154 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
5155  if (status)
5156  mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5157 #endif
5158 
5159  return status;
5160 }
5161 
5162 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
5163 {
5164  mz_uint32 file_index;
5165  if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5166  return MZ_FALSE;
5167 
5168  return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5169 }
5170 
5171 mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags)
5172 {
5173  mz_zip_archive_file_stat file_stat;
5174 
5175  if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5176  return MZ_FALSE;
5177 
5178  if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5179  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5180 
5181  return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5182 }
5183 
5184 mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
5185 {
5186  mz_uint32 file_index;
5187  if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5188  return MZ_FALSE;
5189 
5190  return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
5191 }
5192 #endif /* #ifndef MINIZ_NO_STDIO */
5193 
5194 static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5195 {
5196  mz_uint32 *p = (mz_uint32 *)pOpaque;
5197  (void)file_ofs;
5198  *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n);
5199  return n;
5200 }
5201 
5202 mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
5203 {
5204  mz_zip_archive_file_stat file_stat;
5205  mz_zip_internal_state *pState;
5206  const mz_uint8 *pCentral_dir_header;
5207  mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;
5208  mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
5209  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
5210  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5211  mz_uint64 local_header_ofs = 0;
5212  mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32;
5213  mz_uint64 local_header_comp_size, local_header_uncomp_size;
5214  mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;
5215  mz_bool has_data_descriptor;
5216  mz_uint32 local_header_bit_flags;
5217 
5218  mz_zip_array file_data_array;
5219  mz_zip_array_init(&file_data_array, 1);
5220 
5221  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5222  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5223 
5224  if (file_index > pZip->m_total_files)
5225  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5226 
5227  pState = pZip->m_pState;
5228 
5229  pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);
5230 
5231  if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir))
5232  return MZ_FALSE;
5233 
5234  /* A directory or zero length file */
5235  if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size))
5236  return MZ_TRUE;
5237 
5238  /* Encryption and patch files are not supported. */
5239  if (file_stat.m_is_encrypted)
5240  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
5241 
5242  /* This function only supports stored and deflate. */
5243  if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
5244  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
5245 
5246  if (!file_stat.m_is_supported)
5247  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5248 
5249  /* Read and parse the local directory entry. */
5250  local_header_ofs = file_stat.m_local_header_ofs;
5251  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)
5252  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5253 
5254  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5255  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5256 
5257  local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
5258  local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5259  local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
5260  local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
5261  local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);
5262  local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
5263  has_data_descriptor = (local_header_bit_flags & 8) != 0;
5264 
5265  if (local_header_filename_len != strlen(file_stat.m_filename))
5266  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5267 
5268  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)
5269  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5270 
5271  if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE))
5272  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5273 
5274  if (local_header_filename_len)
5275  {
5276  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)
5277  {
5278  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5279  goto handle_failure;
5280  }
5281 
5282  /* 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. */
5283  if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0)
5284  {
5285  mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5286  goto handle_failure;
5287  }
5288  }
5289 
5290  if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
5291  {
5292  mz_uint32 extra_size_remaining = local_header_extra_len;
5293  const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p;
5294 
5295  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)
5296  {
5297  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5298  goto handle_failure;
5299  }
5300 
5301  do
5302  {
5303  mz_uint32 field_id, field_data_size, field_total_size;
5304 
5305  if (extra_size_remaining < (sizeof(mz_uint16) * 2))
5306  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5307 
5308  field_id = MZ_READ_LE16(pExtra_data);
5309  field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
5310  field_total_size = field_data_size + sizeof(mz_uint16) * 2;
5311 
5312  if (field_total_size > extra_size_remaining)
5313  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5314 
5315  if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
5316  {
5317  const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
5318 
5319  if (field_data_size < sizeof(mz_uint64) * 2)
5320  {
5321  mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5322  goto handle_failure;
5323  }
5324 
5325  local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
5326  local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64));
5327 
5328  found_zip64_ext_data_in_ldir = MZ_TRUE;
5329  break;
5330  }
5331 
5332  pExtra_data += field_total_size;
5333  extra_size_remaining -= field_total_size;
5334  } while (extra_size_remaining);
5335  }
5336 
5337  /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */
5338  /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */
5339  if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32))
5340  {
5341  mz_uint8 descriptor_buf[32];
5342  mz_bool has_id;
5343  const mz_uint8 *pSrc;
5344  mz_uint32 file_crc32;
5345  mz_uint64 comp_size = 0, uncomp_size = 0;
5346 
5347  mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;
5348 
5349  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))
5350  {
5351  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5352  goto handle_failure;
5353  }
5354 
5355  has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
5356  pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf;
5357 
5358  file_crc32 = MZ_READ_LE32(pSrc);
5359 
5360  if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir))
5361  {
5362  comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32));
5363  uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64));
5364  }
5365  else
5366  {
5367  comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32));
5368  uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32));
5369  }
5370 
5371  if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size))
5372  {
5373  mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5374  goto handle_failure;
5375  }
5376  }
5377  else
5378  {
5379  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))
5380  {
5381  mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5382  goto handle_failure;
5383  }
5384  }
5385 
5386  mz_zip_array_clear(pZip, &file_data_array);
5387 
5388  if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0)
5389  {
5390  if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))
5391  return MZ_FALSE;
5392 
5393  /* 1 more check to be sure, although the extract checks too. */
5394  if (uncomp_crc32 != file_stat.m_crc32)
5395  {
5396  mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5397  return MZ_FALSE;
5398  }
5399  }
5400 
5401  return MZ_TRUE;
5402 
5403 handle_failure:
5404  mz_zip_array_clear(pZip, &file_data_array);
5405  return MZ_FALSE;
5406 }
5407 
5408 mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags)
5409 {
5410  mz_zip_internal_state *pState;
5411  uint32_t i;
5412 
5413  if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5414  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5415 
5416  pState = pZip->m_pState;
5417 
5418  /* Basic sanity checks */
5419  if (!pState->m_zip64)
5420  {
5421  if (pZip->m_total_files > MZ_UINT16_MAX)
5422  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5423 
5424  if (pZip->m_archive_size > MZ_UINT32_MAX)
5425  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5426  }
5427  else
5428  {
5429  if (pZip->m_total_files >= MZ_UINT32_MAX)
5430  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5431 
5432  if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
5433  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5434  }
5435 
5436  for (i = 0; i < pZip->m_total_files; i++)
5437  {
5438  if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags)
5439  {
5440  mz_uint32 found_index;
5442 
5443  if (!mz_zip_reader_file_stat(pZip, i, &stat))
5444  return MZ_FALSE;
5445 
5446  if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index))
5447  return MZ_FALSE;
5448 
5449  /* 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) */
5450  if (found_index != i)
5451  return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5452  }
5453 
5454  if (!mz_zip_validate_file(pZip, i, flags))
5455  return MZ_FALSE;
5456  }
5457 
5458  return MZ_TRUE;
5459 }
5460 
5461 mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)
5462 {
5463  mz_bool success = MZ_TRUE;
5464  mz_zip_archive zip;
5465  mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5466 
5467  if ((!pMem) || (!size))
5468  {
5469  if (pErr)
5470  *pErr = MZ_ZIP_INVALID_PARAMETER;
5471  return MZ_FALSE;
5472  }
5473 
5474  mz_zip_zero_struct(&zip);
5475 
5476  if (!mz_zip_reader_init_mem(&zip, pMem, size, flags))
5477  {
5478  if (pErr)
5479  *pErr = zip.m_last_error;
5480  return MZ_FALSE;
5481  }
5482 
5483  if (!mz_zip_validate_archive(&zip, flags))
5484  {
5485  actual_err = zip.m_last_error;
5486  success = MZ_FALSE;
5487  }
5488 
5489  if (!mz_zip_reader_end_internal(&zip, success))
5490  {
5491  if (!actual_err)
5492  actual_err = zip.m_last_error;
5493  success = MZ_FALSE;
5494  }
5495 
5496  if (pErr)
5497  *pErr = actual_err;
5498 
5499  return success;
5500 }
5501 
5502 #ifndef MINIZ_NO_STDIO
5503 mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr)
5504 {
5505  mz_bool success = MZ_TRUE;
5506  mz_zip_archive zip;
5507  mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5508 
5509  if (!pFilename)
5510  {
5511  if (pErr)
5512  *pErr = MZ_ZIP_INVALID_PARAMETER;
5513  return MZ_FALSE;
5514  }
5515 
5516  mz_zip_zero_struct(&zip);
5517 
5518  if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0))
5519  {
5520  if (pErr)
5521  *pErr = zip.m_last_error;
5522  return MZ_FALSE;
5523  }
5524 
5525  if (!mz_zip_validate_archive(&zip, flags))
5526  {
5527  actual_err = zip.m_last_error;
5528  success = MZ_FALSE;
5529  }
5530 
5531  if (!mz_zip_reader_end_internal(&zip, success))
5532  {
5533  if (!actual_err)
5534  actual_err = zip.m_last_error;
5535  success = MZ_FALSE;
5536  }
5537 
5538  if (pErr)
5539  *pErr = actual_err;
5540 
5541  return success;
5542 }
5543 #endif /* #ifndef MINIZ_NO_STDIO */
5544 
5545 /* ------------------- .ZIP archive writing */
5546 
5547 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5548 
5549 static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v)
5550 {
5551  p[0] = (mz_uint8)v;
5552  p[1] = (mz_uint8)(v >> 8);
5553 }
5554 static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v)
5555 {
5556  p[0] = (mz_uint8)v;
5557  p[1] = (mz_uint8)(v >> 8);
5558  p[2] = (mz_uint8)(v >> 16);
5559  p[3] = (mz_uint8)(v >> 24);
5560 }
5561 static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v)
5562 {
5563  mz_write_le32(p, (mz_uint32)v);
5564  mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32));
5565 }
5566 
5567 #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5568 #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5569 #define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v))
5570 
5571 static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5572 {
5573  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5574  mz_zip_internal_state *pState = pZip->m_pState;
5575  mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5576 
5577  if (!n)
5578  return 0;
5579 
5580  /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */
5581  if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))
5582  {
5583  mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5584  return 0;
5585  }
5586 
5587  if (new_size > pState->m_mem_capacity)
5588  {
5589  void *pNew_block;
5590  size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5591 
5592  while (new_capacity < new_size)
5593  new_capacity *= 2;
5594 
5595  if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5596  {
5597  mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5598  return 0;
5599  }
5600 
5601  pState->m_pMem = pNew_block;
5602  pState->m_mem_capacity = new_capacity;
5603  }
5604  memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5605  pState->m_mem_size = (size_t)new_size;
5606  return n;
5607 }
5608 
5609 static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
5610 {
5611  mz_zip_internal_state *pState;
5612  mz_bool status = MZ_TRUE;
5613 
5614  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)))
5615  {
5616  if (set_last_error)
5617  mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5618  return MZ_FALSE;
5619  }
5620 
5621  pState = pZip->m_pState;
5622  pZip->m_pState = NULL;
5623  mz_zip_array_clear(pZip, &pState->m_central_dir);
5624  mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5625  mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5626 
5627 #ifndef MINIZ_NO_STDIO
5628  if (pState->m_pFile)
5629  {
5630  if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5631  {
5632  if (MZ_FCLOSE(pState->m_pFile) == EOF)
5633  {
5634  if (set_last_error)
5635  mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5636  status = MZ_FALSE;
5637  }
5638  }
5639 
5640  pState->m_pFile = NULL;
5641  }
5642 #endif /* #ifndef MINIZ_NO_STDIO */
5643 
5644  if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
5645  {
5646  pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
5647  pState->m_pMem = NULL;
5648  }
5649 
5650  pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5651  pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5652  return status;
5653 }
5654 
5655 mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags)
5656 {
5657  mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;
5658 
5659  if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5660  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5661 
5662  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5663  {
5664  if (!pZip->m_pRead)
5665  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5666  }
5667 
5668  if (pZip->m_file_offset_alignment)
5669  {
5670  /* Ensure user specified file offset alignment is a power of 2. */
5671  if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5672  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5673  }
5674 
5675  if (!pZip->m_pAlloc)
5676  pZip->m_pAlloc = miniz_def_alloc_func;
5677  if (!pZip->m_pFree)
5678  pZip->m_pFree = miniz_def_free_func;
5679  if (!pZip->m_pRealloc)
5680  pZip->m_pRealloc = miniz_def_realloc_func;
5681 
5682  pZip->m_archive_size = existing_size;
5683  pZip->m_central_directory_file_ofs = 0;
5684  pZip->m_total_files = 0;
5685 
5686  if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5687  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5688 
5689  memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5690 
5691  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
5692  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
5693  MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
5694 
5695  pZip->m_pState->m_zip64 = zip64;
5696  pZip->m_pState->m_zip64_has_extended_info_fields = zip64;
5697 
5698  pZip->m_zip_type = MZ_ZIP_TYPE_USER;
5699  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5700 
5701  return MZ_TRUE;
5702 }
5703 
5704 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
5705 {
5706  return mz_zip_writer_init_v2(pZip, existing_size, 0);
5707 }
5708 
5709 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)
5710 {
5711  pZip->m_pWrite = mz_zip_heap_write_func;
5712  pZip->m_pNeeds_keepalive = NULL;
5713 
5714  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5715  pZip->m_pRead = mz_zip_mem_read_func;
5716 
5717  pZip->m_pIO_opaque = pZip;
5718 
5719  if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5720  return MZ_FALSE;
5721 
5722  pZip->m_zip_type = MZ_ZIP_TYPE_HEAP;
5723 
5724  if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
5725  {
5726  if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
5727  {
5728  mz_zip_writer_end_internal(pZip, MZ_FALSE);
5729  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5730  }
5731  pZip->m_pState->m_mem_capacity = initial_allocation_size;
5732  }
5733 
5734  return MZ_TRUE;
5735 }
5736 
5737 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
5738 {
5739  return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0);
5740 }
5741 
5742 #ifndef MINIZ_NO_STDIO
5743 static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5744 {
5745  mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5746  mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5747 
5748  file_ofs += pZip->m_pState->m_file_archive_start_ofs;
5749 
5750  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))))
5751  {
5752  mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
5753  return 0;
5754  }
5755 
5756  return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5757 }
5758 
5759 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
5760 {
5761  return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0);
5762 }
5763 
5764 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)
5765 {
5766  MZ_FILE *pFile;
5767 
5768  pZip->m_pWrite = mz_zip_file_write_func;
5769  pZip->m_pNeeds_keepalive = NULL;
5770 
5771  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5772  pZip->m_pRead = mz_zip_file_read_func;
5773 
5774  pZip->m_pIO_opaque = pZip;
5775 
5776  if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5777  return MZ_FALSE;
5778 
5779  if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb")))
5780  {
5781  mz_zip_writer_end(pZip);
5782  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5783  }
5784 
5785  pZip->m_pState->m_pFile = pFile;
5786  pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
5787 
5788  if (size_to_reserve_at_beginning)
5789  {
5790  mz_uint64 cur_ofs = 0;
5791  char buf[4096];
5792 
5793  MZ_CLEAR_OBJ(buf);
5794 
5795  do
5796  {
5797  size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5798  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
5799  {
5800  mz_zip_writer_end(pZip);
5801  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
5802  }
5803  cur_ofs += n;
5804  size_to_reserve_at_beginning -= n;
5805  } while (size_to_reserve_at_beginning);
5806  }
5807 
5808  return MZ_TRUE;
5809 }
5810 
5811 mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)
5812 {
5813  pZip->m_pWrite = mz_zip_file_write_func;
5814  pZip->m_pNeeds_keepalive = NULL;
5815 
5816  if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5817  pZip->m_pRead = mz_zip_file_read_func;
5818 
5819  pZip->m_pIO_opaque = pZip;
5820 
5821  if (!mz_zip_writer_init_v2(pZip, 0, flags))
5822  return MZ_FALSE;
5823 
5824  pZip->m_pState->m_pFile = pFile;
5825  pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5826  pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
5827 
5828  return MZ_TRUE;
5829 }
5830 #endif /* #ifndef MINIZ_NO_STDIO */
5831 
5832 mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
5833 {
5834  mz_zip_internal_state *pState;
5835 
5836  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5837  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5838 
5839  if (flags & MZ_ZIP_FLAG_WRITE_ZIP64)
5840  {
5841  /* 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?) */
5842  if (!pZip->m_pState->m_zip64)
5843  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5844  }
5845 
5846  /* No sense in trying to write to an archive that's already at the support max size */
5847  if (pZip->m_pState->m_zip64)
5848  {
5849  if (pZip->m_total_files == MZ_UINT32_MAX)
5850  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5851  }
5852  else
5853  {
5854  if (pZip->m_total_files == MZ_UINT16_MAX)
5855  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5856 
5857  if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)
5858  return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5859  }
5860 
5861  pState = pZip->m_pState;
5862 
5863  if (pState->m_pFile)
5864  {
5865 #ifdef MINIZ_NO_STDIO
5866  (void)pFilename;
5867  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5868 #else
5869  if (pZip->m_pIO_opaque != pZip)
5870  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5871 
5872  if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5873  {
5874  if (!pFilename)
5875  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5876 
5877  /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */
5878  if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
5879  {
5880  /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */
5881  mz_zip_reader_end_internal(pZip, MZ_FALSE);
5882  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5883  }
5884  }
5885 
5886  pZip->m_pWrite = mz_zip_file_write_func;
5887  pZip->m_pNeeds_keepalive = NULL;
5888 #endif /* #ifdef MINIZ_NO_STDIO */
5889  }
5890  else if (pState->m_pMem)
5891  {
5892  /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */
5893  if (pZip->m_pIO_opaque != pZip)
5894  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5895 
5896  pState->m_mem_capacity = pState->m_mem_size;
5897  pZip->m_pWrite = mz_zip_heap_write_func;
5898  pZip->m_pNeeds_keepalive = NULL;
5899  }
5900  /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */
5901  else if (!pZip->m_pWrite)
5902  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5903 
5904  /* Start writing new files at the archive's current central directory location. */
5905  /* TODO: We could add a flag that lets the user start writing immediately AFTER the existing central dir - this would be safer. */
5906  pZip->m_archive_size = pZip->m_central_directory_file_ofs;
5907  pZip->m_central_directory_file_ofs = 0;
5908 
5909  /* Clear the sorted central dir offsets, they aren't useful or maintained now. */
5910  /* Even though we're now in write mode, files can still be extracted and verified, but file locates will be slow. */
5911  /* TODO: We could easily maintain the sorted central directory offsets. */
5912  mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets);
5913 
5914  pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5915 
5916  return MZ_TRUE;
5917 }
5918 
5919 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
5920 {
5921  return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);
5922 }
5923 
5924 /* TODO: pArchive_name is a terrible name here! */
5925 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)
5926 {
5927  return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
5928 }
5929 
5930 typedef struct
5931 {
5932  mz_zip_archive *m_pZip;
5933  mz_uint64 m_cur_archive_file_ofs;
5934  mz_uint64 m_comp_size;
5936 
5937 static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser)
5938 {
5940  if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
5941  return MZ_FALSE;
5942 
5943  pState->m_cur_archive_file_ofs += len;
5944  pState->m_comp_size += len;
5945  return MZ_TRUE;
5946 }
5947 
5948 #define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)
5949 #define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3)
5950 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)
5951 {
5952  mz_uint8 *pDst = pBuf;
5953  mz_uint32 field_size = 0;
5954 
5955  MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
5956  MZ_WRITE_LE16(pDst + 2, 0);
5957  pDst += sizeof(mz_uint16) * 2;
5958 
5959  if (pUncomp_size)
5960  {
5961  MZ_WRITE_LE64(pDst, *pUncomp_size);
5962  pDst += sizeof(mz_uint64);
5963  field_size += sizeof(mz_uint64);
5964  }
5965 
5966  if (pComp_size)
5967  {
5968  MZ_WRITE_LE64(pDst, *pComp_size);
5969  pDst += sizeof(mz_uint64);
5970  field_size += sizeof(mz_uint64);
5971  }
5972 
5973  if (pLocal_header_ofs)
5974  {
5975  MZ_WRITE_LE64(pDst, *pLocal_header_ofs);
5976  pDst += sizeof(mz_uint64);
5977  field_size += sizeof(mz_uint64);
5978  }
5979 
5980  MZ_WRITE_LE16(pBuf + 2, field_size);
5981 
5982  return (mz_uint32)(pDst - pBuf);
5983 }
5984 
5985 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)
5986 {
5987  (void)pZip;
5988  memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
5989  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
5990  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
5991  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
5992  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
5993  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
5994  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
5995  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
5996  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
5997  MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
5998  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
5999  MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
6000  return MZ_TRUE;
6001 }
6002 
6003 static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst,
6004  mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size,
6005  mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
6006  mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6007  mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
6008 {
6009  (void)pZip;
6010  memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6011  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6012  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6013  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6014  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6015  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6016  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6017  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6018  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
6019  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
6020  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6021  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6022  MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6023  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6024  MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_MIN(local_header_ofs, MZ_UINT32_MAX));
6025  return MZ_TRUE;
6026 }
6027 
6028 static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
6029  const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size,
6030  mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
6031  mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6032  mz_uint64 local_header_ofs, mz_uint32 ext_attributes,
6033  const char *user_extra_data, mz_uint user_extra_data_len)
6034 {
6035  mz_zip_internal_state *pState = pZip->m_pState;
6036  mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6037  size_t orig_central_dir_size = pState->m_central_dir.m_size;
6038  mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6039 
6040  if (!pZip->m_pState->m_zip64)
6041  {
6042  if (local_header_ofs > 0xFFFFFFFF)
6043  return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
6044  }
6045 
6046  /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6047  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)
6048  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6049 
6050  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))
6051  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6052 
6053  if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6054  (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
6055  (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
6056  (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) ||
6057  (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
6058  (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
6059  {
6060  /* Try to resize the central directory array back into its original state. */
6061  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6062  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6063  }
6064 
6065  return MZ_TRUE;
6066 }
6067 
6068 static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
6069 {
6070  /* 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. */
6071  if (*pArchive_name == '/')
6072  return MZ_FALSE;
6073 
6074  /* Making sure the name does not contain drive letters or DOS style backward slashes is the responsibility of the program using miniz*/
6075 
6076  return MZ_TRUE;
6077 }
6078 
6079 static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
6080 {
6081  mz_uint32 n;
6082  if (!pZip->m_file_offset_alignment)
6083  return 0;
6084  n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6085  return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1));
6086 }
6087 
6088 static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
6089 {
6090  char buf[4096];
6091  memset(buf, 0, MZ_MIN(sizeof(buf), n));
6092  while (n)
6093  {
6094  mz_uint32 s = MZ_MIN(sizeof(buf), n);
6095  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6096  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6097 
6098  cur_file_ofs += s;
6099  n -= s;
6100  }
6101  return MZ_TRUE;
6102 }
6103 
6104 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,
6105  mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
6106 {
6107  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);
6108 }
6109 
6110 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,
6111  mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified,
6112  const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6113 {
6114  mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6115  mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
6116  mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
6117  size_t archive_name_size;
6118  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6119  tdefl_compressor *pComp = NULL;
6120  mz_bool store_data_uncompressed;
6121  mz_zip_internal_state *pState;
6122  mz_uint8 *pExtra_data = NULL;
6123  mz_uint32 extra_size = 0;
6124  mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6125  mz_uint16 bit_flags = 0;
6126 
6127  if ((int)level_and_flags < 0)
6128  level_and_flags = MZ_DEFAULT_LEVEL;
6129 
6130  if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
6131  bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6132 
6133  if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6134  bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6135 
6136  level = level_and_flags & 0xF;
6137  store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6138 
6139  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))
6140  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6141 
6142  pState = pZip->m_pState;
6143 
6144  if (pState->m_zip64)
6145  {
6146  if (pZip->m_total_files == MZ_UINT32_MAX)
6147  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6148  }
6149  else
6150  {
6151  if (pZip->m_total_files == MZ_UINT16_MAX)
6152  {
6153  pState->m_zip64 = MZ_TRUE;
6154  /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6155  }
6156  if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6157  {
6158  pState->m_zip64 = MZ_TRUE;
6159  /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6160  }
6161  }
6162 
6163  if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6164  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6165 
6166  if (!mz_zip_writer_validate_archive_name(pArchive_name))
6167  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6168 
6169 #ifndef MINIZ_NO_TIME
6170  if (last_modified != NULL)
6171  {
6172  mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
6173  }
6174  else
6175  {
6176  MZ_TIME_T cur_time;
6177  time(&cur_time);
6178  mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6179  }
6180 #endif /* #ifndef MINIZ_NO_TIME */
6181 
6182  if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6183  {
6184  uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6185  uncomp_size = buf_size;
6186  if (uncomp_size <= 3)
6187  {
6188  level = 0;
6189  store_data_uncompressed = MZ_TRUE;
6190  }
6191  }
6192 
6193  archive_name_size = strlen(pArchive_name);
6194  if (archive_name_size > MZ_UINT16_MAX)
6195  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6196 
6197  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6198 
6199  /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6200  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)
6201  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6202 
6203  if (!pState->m_zip64)
6204  {
6205  /* Bail early if the archive would obviously become too large */
6206  if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size
6207  + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len +
6208  pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len
6209  + MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF)
6210  {
6211  pState->m_zip64 = MZ_TRUE;
6212  /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6213  }
6214  }
6215 
6216  if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
6217  {
6218  /* Set DOS Subdirectory attribute bit. */
6219  ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
6220 
6221  /* Subdirectories cannot contain data. */
6222  if ((buf_size) || (uncomp_size))
6223  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6224  }
6225 
6226  /* 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.) */
6227  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)))
6228  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6229 
6230  if ((!store_data_uncompressed) && (buf_size))
6231  {
6232  if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6233  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6234  }
6235 
6236  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6237  {
6238  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6239  return MZ_FALSE;
6240  }
6241 
6242  local_dir_header_ofs += num_alignment_padding_bytes;
6243  if (pZip->m_file_offset_alignment)
6244  {
6245  MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6246  }
6247  cur_archive_file_ofs += num_alignment_padding_bytes;
6248 
6249  MZ_CLEAR_OBJ(local_dir_header);
6250 
6251  if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6252  {
6253  method = MZ_DEFLATED;
6254  }
6255 
6256  if (pState->m_zip64)
6257  {
6258  if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6259  {
6260  pExtra_data = extra_data;
6261  extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6262  (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6263  }
6264 
6265  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))
6266  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6267 
6268  if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6269  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6270 
6271  cur_archive_file_ofs += sizeof(local_dir_header);
6272 
6273  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6274  {
6275  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6276  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6277  }
6278  cur_archive_file_ofs += archive_name_size;
6279 
6280  if (pExtra_data != NULL)
6281  {
6282  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6283  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6284 
6285  cur_archive_file_ofs += extra_size;
6286  }
6287  }
6288  else
6289  {
6290  if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6291  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6292  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))
6293  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6294 
6295  if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6296  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6297 
6298  cur_archive_file_ofs += sizeof(local_dir_header);
6299 
6300  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6301  {
6302  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6303  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6304  }
6305  cur_archive_file_ofs += archive_name_size;
6306  }
6307 
6308  if (user_extra_data_len > 0)
6309  {
6310  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6311  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6312 
6313  cur_archive_file_ofs += user_extra_data_len;
6314  }
6315 
6316  if (store_data_uncompressed)
6317  {
6318  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
6319  {
6320  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6321  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6322  }
6323 
6324  cur_archive_file_ofs += buf_size;
6325  comp_size = buf_size;
6326  }
6327  else if (buf_size)
6328  {
6330 
6331  state.m_pZip = pZip;
6332  state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6333  state.m_comp_size = 0;
6334 
6335  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) ||
6336  (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
6337  {
6338  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6339  return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6340  }
6341 
6342  comp_size = state.m_comp_size;
6343  cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6344  }
6345 
6346  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6347  pComp = NULL;
6348 
6349  if (uncomp_size)
6350  {
6351  mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6352  mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6353 
6354  MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR);
6355 
6356  MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6357  MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6358  if (pExtra_data == NULL)
6359  {
6360  if (comp_size > MZ_UINT32_MAX)
6361  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6362 
6363  MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6364  MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6365  }
6366  else
6367  {
6368  MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6369  MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6370  local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6371  }
6372 
6373  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6374  return MZ_FALSE;
6375 
6376  cur_archive_file_ofs += local_dir_footer_size;
6377  }
6378 
6379  if (pExtra_data != NULL)
6380  {
6381  extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6382  (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6383  }
6384 
6385  if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment,
6386  comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6387  user_extra_data_central, user_extra_data_central_len))
6388  return MZ_FALSE;
6389 
6390  pZip->m_total_files++;
6391  pZip->m_archive_size = cur_archive_file_ofs;
6392 
6393  return MZ_TRUE;
6394 }
6395 
6396 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,
6397  const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6398 {
6399  mz_uint16 gen_flags = MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6400  mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6401  mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
6402  mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0;
6403  size_t archive_name_size;
6404  mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6405  mz_uint8 *pExtra_data = NULL;
6406  mz_uint32 extra_size = 0;
6407  mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6408  mz_zip_internal_state *pState;
6409  mz_uint64 file_ofs = 0;
6410 
6411  if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6412  gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6413 
6414  if ((int)level_and_flags < 0)
6415  level_and_flags = MZ_DEFAULT_LEVEL;
6416  level = level_and_flags & 0xF;
6417 
6418  /* Sanity checks */
6419  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6420  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6421 
6422  pState = pZip->m_pState;
6423 
6424  if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX))
6425  {
6426  /* Source file is too large for non-zip64 */
6427  /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6428  pState->m_zip64 = MZ_TRUE;
6429  }
6430 
6431  /* We could support this, but why? */
6432  if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6433  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6434 
6435  if (!mz_zip_writer_validate_archive_name(pArchive_name))
6436  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6437 
6438  if (pState->m_zip64)
6439  {
6440  if (pZip->m_total_files == MZ_UINT32_MAX)
6441  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6442  }
6443  else
6444  {
6445  if (pZip->m_total_files == MZ_UINT16_MAX)
6446  {
6447  pState->m_zip64 = MZ_TRUE;
6448  /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6449  }
6450  }
6451 
6452  archive_name_size = strlen(pArchive_name);
6453  if (archive_name_size > MZ_UINT16_MAX)
6454  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6455 
6456  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6457 
6458  /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6459  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)
6460  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6461 
6462  if (!pState->m_zip64)
6463  {
6464  /* Bail early if the archive would obviously become too large */
6465  if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE
6466  + archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024
6467  + MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF)
6468  {
6469  pState->m_zip64 = MZ_TRUE;
6470  /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6471  }
6472  }
6473 
6474 #ifndef MINIZ_NO_TIME
6475  if (pFile_time)
6476  {
6477  mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);
6478  }
6479 #endif
6480 
6481  if (uncomp_size <= 3)
6482  level = 0;
6483 
6484  if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6485  {
6486  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6487  }
6488 
6489  cur_archive_file_ofs += num_alignment_padding_bytes;
6490  local_dir_header_ofs = cur_archive_file_ofs;
6491 
6492  if (pZip->m_file_offset_alignment)
6493  {
6494  MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6495  }
6496 
6497  if (uncomp_size && level)
6498  {
6499  method = MZ_DEFLATED;
6500  }
6501 
6502  MZ_CLEAR_OBJ(local_dir_header);
6503  if (pState->m_zip64)
6504  {
6505  if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6506  {
6507  pExtra_data = extra_data;
6508  extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6509  (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6510  }
6511 
6512  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))
6513  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6514 
6515  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6516  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6517 
6518  cur_archive_file_ofs += sizeof(local_dir_header);
6519 
6520  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6521  {
6522  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6523  }
6524 
6525  cur_archive_file_ofs += archive_name_size;
6526 
6527  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6528  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6529 
6530  cur_archive_file_ofs += extra_size;
6531  }
6532  else
6533  {
6534  if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6535  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6536  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))
6537  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6538 
6539  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6540  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6541 
6542  cur_archive_file_ofs += sizeof(local_dir_header);
6543 
6544  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6545  {
6546  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6547  }
6548 
6549  cur_archive_file_ofs += archive_name_size;
6550  }
6551 
6552  if (user_extra_data_len > 0)
6553  {
6554  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6555  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6556 
6557  cur_archive_file_ofs += user_extra_data_len;
6558  }
6559 
6560  if (uncomp_size)
6561  {
6562  mz_uint64 uncomp_remaining = uncomp_size;
6563  void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6564  if (!pRead_buf)
6565  {
6566  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6567  }
6568 
6569  if (!level)
6570  {
6571  while (uncomp_remaining)
6572  {
6573  mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6574  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))
6575  {
6576  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6577  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6578  }
6579  file_ofs += n;
6580  uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6581  uncomp_remaining -= n;
6582  cur_archive_file_ofs += n;
6583  }
6584  comp_size = uncomp_size;
6585  }
6586  else
6587  {
6588  mz_bool result = MZ_FALSE;
6590  tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6591  if (!pComp)
6592  {
6593  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6594  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6595  }
6596 
6597  state.m_pZip = pZip;
6598  state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6599  state.m_comp_size = 0;
6600 
6601  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)
6602  {
6603  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6604  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6605  return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6606  }
6607 
6608  for (;;)
6609  {
6610  size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
6611  tdefl_status status;
6612  tdefl_flush flush = TDEFL_NO_FLUSH;
6613 
6614  if (read_callback(callback_opaque, file_ofs, pRead_buf, in_buf_size)!= in_buf_size)
6615  {
6616  mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6617  break;
6618  }
6619 
6620  file_ofs += in_buf_size;
6621  uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6622  uncomp_remaining -= in_buf_size;
6623 
6624  if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
6625  flush = TDEFL_FULL_FLUSH;
6626 
6627  status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH);
6628  if (status == TDEFL_STATUS_DONE)
6629  {
6630  result = MZ_TRUE;
6631  break;
6632  }
6633  else if (status != TDEFL_STATUS_OKAY)
6634  {
6635  mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6636  break;
6637  }
6638  }
6639 
6640  pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6641 
6642  if (!result)
6643  {
6644  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6645  return MZ_FALSE;
6646  }
6647 
6648  comp_size = state.m_comp_size;
6649  cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6650  }
6651 
6652  pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6653  }
6654 
6655  {
6656  mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6657  mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6658 
6659  MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6660  MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6661  if (pExtra_data == NULL)
6662  {
6663  if (comp_size > MZ_UINT32_MAX)
6664  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6665 
6666  MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6667  MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6668  }
6669  else
6670  {
6671  MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6672  MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6673  local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6674  }
6675 
6676  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6677  return MZ_FALSE;
6678 
6679  cur_archive_file_ofs += local_dir_footer_size;
6680  }
6681 
6682  if (pExtra_data != NULL)
6683  {
6684  extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6685  (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6686  }
6687 
6688  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,
6689  uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6690  user_extra_data_central, user_extra_data_central_len))
6691  return MZ_FALSE;
6692 
6693  pZip->m_total_files++;
6694  pZip->m_archive_size = cur_archive_file_ofs;
6695 
6696  return MZ_TRUE;
6697 }
6698 
6699 #ifndef MINIZ_NO_STDIO
6700 
6701 static size_t mz_file_read_func_stdio(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
6702 {
6703  MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque;
6704  mz_int64 cur_ofs = MZ_FTELL64(pSrc_file);
6705 
6706  if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET))))
6707  return 0;
6708 
6709  return MZ_FREAD(pBuf, 1, n, pSrc_file);
6710 }
6711 
6712 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,
6713  const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6714 {
6715  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,
6716  user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len);
6717 }
6718 
6719 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)
6720 {
6721  MZ_FILE *pSrc_file = NULL;
6722  mz_uint64 uncomp_size = 0;
6723  MZ_TIME_T file_modified_time;
6724  MZ_TIME_T *pFile_time = NULL;
6725  mz_bool status;
6726 
6727  memset(&file_modified_time, 0, sizeof(file_modified_time));
6728 
6729 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
6730  pFile_time = &file_modified_time;
6731  if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6732  return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED);
6733 #endif
6734 
6735  pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6736  if (!pSrc_file)
6737  return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
6738 
6739  MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6740  uncomp_size = MZ_FTELL64(pSrc_file);
6741  MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6742 
6743  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);
6744 
6745  MZ_FCLOSE(pSrc_file);
6746 
6747  return status;
6748 }
6749 #endif /* #ifndef MINIZ_NO_STDIO */
6750 
6751 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)
6752 {
6753  /* + 64 should be enough for any new zip64 data */
6754  if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))
6755  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6756 
6757  mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);
6758 
6759  if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start))
6760  {
6761  mz_uint8 new_ext_block[64];
6762  mz_uint8 *pDst = new_ext_block;
6763  mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
6764  mz_write_le16(pDst + sizeof(mz_uint16), 0);
6765  pDst += sizeof(mz_uint16) * 2;
6766 
6767  if (pUncomp_size)
6768  {
6769  mz_write_le64(pDst, *pUncomp_size);
6770  pDst += sizeof(mz_uint64);
6771  }
6772 
6773  if (pComp_size)
6774  {
6775  mz_write_le64(pDst, *pComp_size);
6776  pDst += sizeof(mz_uint64);
6777  }
6778 
6779  if (pLocal_header_ofs)
6780  {
6781  mz_write_le64(pDst, *pLocal_header_ofs);
6782  pDst += sizeof(mz_uint64);
6783  }
6784 
6785  if (pDisk_start)
6786  {
6787  mz_write_le32(pDst, *pDisk_start);
6788  pDst += sizeof(mz_uint32);
6789  }
6790 
6791  mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2));
6792 
6793  if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block))
6794  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6795  }
6796 
6797  if ((pExt) && (ext_len))
6798  {
6799  mz_uint32 extra_size_remaining = ext_len;
6800  const mz_uint8 *pExtra_data = pExt;
6801 
6802  do
6803  {
6804  mz_uint32 field_id, field_data_size, field_total_size;
6805 
6806  if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6807  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6808 
6809  field_id = MZ_READ_LE16(pExtra_data);
6810  field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6811  field_total_size = field_data_size + sizeof(mz_uint16) * 2;
6812 
6813  if (field_total_size > extra_size_remaining)
6814  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6815 
6816  if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
6817  {
6818  if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size))
6819  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6820  }
6821 
6822  pExtra_data += field_total_size;
6823  extra_size_remaining -= field_total_size;
6824  } while (extra_size_remaining);
6825  }
6826 
6827  return MZ_TRUE;
6828 }
6829 
6830 /* TODO: This func is now pretty freakin complex due to zip64, split it up? */
6831 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index)
6832 {
6833  mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size;
6834  mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;
6835  mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6836  mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
6837  mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6838  mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6839  size_t orig_central_dir_size;
6840  mz_zip_internal_state *pState;
6841  void *pBuf;
6842  const mz_uint8 *pSrc_central_header;
6843  mz_zip_archive_file_stat src_file_stat;
6844  mz_uint32 src_filename_len, src_comment_len, src_ext_len;
6845  mz_uint32 local_header_filename_size, local_header_extra_len;
6846  mz_uint64 local_header_comp_size, local_header_uncomp_size;
6847  mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
6848 
6849  /* Sanity checks */
6850  if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))
6851  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6852 
6853  pState = pZip->m_pState;
6854 
6855  /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */
6856  if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))
6857  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6858 
6859  /* Get pointer to the source central dir header and crack it */
6860  if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
6861  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6862 
6863  if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)
6864  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6865 
6866  src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);
6867  src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6868  src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);
6869  src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len;
6870 
6871  /* 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) */
6872  if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)
6873  return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6874 
6875  num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6876 
6877  if (!pState->m_zip64)
6878  {
6879  if (pZip->m_total_files == MZ_UINT16_MAX)
6880  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6881  }
6882  else
6883  {
6884  /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */
6885  if (pZip->m_total_files == MZ_UINT32_MAX)
6886  return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6887  }
6888 
6889  if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL))
6890  return MZ_FALSE;
6891 
6892  cur_src_file_ofs = src_file_stat.m_local_header_ofs;
6893  cur_dst_file_ofs = pZip->m_archive_size;
6894 
6895  /* Read the source archive's local dir header */
6896  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)
6897  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6898 
6899  if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6900  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6901 
6902  cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6903 
6904  /* Compute the total size we need to copy (filename+extra data+compressed data) */
6905  local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
6906  local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6907  local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
6908  local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
6909  src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size;
6910 
6911  /* Try to find a zip64 extended information field */
6912  if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
6913  {
6914  mz_zip_array file_data_array;
6915  const mz_uint8 *pExtra_data;
6916  mz_uint32 extra_size_remaining = local_header_extra_len;
6917 
6918  mz_zip_array_init(&file_data_array, 1);
6919  if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE))
6920  {
6921  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6922  }
6923 
6924  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)
6925  {
6926  mz_zip_array_clear(pZip, &file_data_array);
6927  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6928  }
6929 
6930  pExtra_data = (const mz_uint8 *)file_data_array.m_p;
6931 
6932  do
6933  {
6934  mz_uint32 field_id, field_data_size, field_total_size;
6935 
6936  if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6937  {
6938  mz_zip_array_clear(pZip, &file_data_array);
6939  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6940  }
6941 
6942  field_id = MZ_READ_LE16(pExtra_data);
6943  field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6944  field_total_size = field_data_size + sizeof(mz_uint16) * 2;
6945 
6946  if (field_total_size > extra_size_remaining)
6947  {
6948  mz_zip_array_clear(pZip, &file_data_array);
6949  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6950  }
6951 
6952  if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
6953  {
6954  const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
6955 
6956  if (field_data_size < sizeof(mz_uint64) * 2)
6957  {
6958  mz_zip_array_clear(pZip, &file_data_array);
6959  return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6960  }
6961 
6962  local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
6963  local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */
6964 
6965  found_zip64_ext_data_in_ldir = MZ_TRUE;
6966  break;
6967  }
6968 
6969  pExtra_data += field_total_size;
6970  extra_size_remaining -= field_total_size;
6971  } while (extra_size_remaining);
6972 
6973  mz_zip_array_clear(pZip, &file_data_array);
6974  }
6975 
6976  if (!pState->m_zip64)
6977  {
6978  /* 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). */
6979  /* We also check when the archive is finalized so this doesn't need to be perfect. */
6980  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) +
6981  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;
6982 
6983  if (approx_new_archive_size >= MZ_UINT32_MAX)
6984  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6985  }
6986 
6987  /* Write dest archive padding */
6988  if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
6989  return MZ_FALSE;
6990 
6991  cur_dst_file_ofs += num_alignment_padding_bytes;
6992 
6993  local_dir_header_ofs = cur_dst_file_ofs;
6994  if (pZip->m_file_offset_alignment)
6995  {
6996  MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6997  }
6998 
6999  /* 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 */
7000  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)
7001  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7002 
7003  cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
7004 
7005  /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */
7006  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)))))
7007  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7008 
7009  while (src_archive_bytes_remaining)
7010  {
7011  n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining);
7012  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
7013  {
7014  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7015  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7016  }
7017  cur_src_file_ofs += n;
7018 
7019  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7020  {
7021  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7022  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7023  }
7024  cur_dst_file_ofs += n;
7025 
7026  src_archive_bytes_remaining -= n;
7027  }
7028 
7029  /* Now deal with the optional data descriptor */
7030  bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
7031  if (bit_flags & 8)
7032  {
7033  /* Copy data descriptor */
7034  if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir))
7035  {
7036  /* src is zip64, dest must be zip64 */
7037 
7038  /* name uint32_t's */
7039  /* id 1 (optional in zip64?) */
7040  /* crc 1 */
7041  /* comp_size 2 */
7042  /* uncomp_size 2 */
7043  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6))
7044  {
7045  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7046  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7047  }
7048 
7049  n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);
7050  }
7051  else
7052  {
7053  /* src is NOT zip64 */
7054  mz_bool has_id;
7055 
7056  if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
7057  {
7058  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7059  return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7060  }
7061 
7062  has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
7063 
7064  if (pZip->m_pState->m_zip64)
7065  {
7066  /* dest is zip64, so upgrade the data descriptor */
7067  const mz_uint32 *pSrc_descriptor = (const mz_uint32 *)((const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0));
7068  const mz_uint32 src_crc32 = pSrc_descriptor[0];
7069  const mz_uint64 src_comp_size = pSrc_descriptor[1];
7070  const mz_uint64 src_uncomp_size = pSrc_descriptor[2];
7071 
7072  mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID);
7073  mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32);
7074  mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size);
7075  mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size);
7076 
7077  n = sizeof(mz_uint32) * 6;
7078  }
7079  else
7080  {
7081  /* dest is NOT zip64, just copy it as-is */
7082  n = sizeof(mz_uint32) * (has_id ? 4 : 3);
7083  }
7084  }
7085 
7086  if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7087  {
7088  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7089  return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7090  }
7091 
7092  cur_src_file_ofs += n;
7093  cur_dst_file_ofs += n;
7094  }
7095  pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7096 
7097  /* Finally, add the new central dir header */
7098  orig_central_dir_size = pState->m_central_dir.m_size;
7099 
7100  memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
7101 
7102  if (pState->m_zip64)
7103  {
7104  /* 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. */
7105  const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;
7106  mz_zip_array new_ext_block;
7107 
7108  mz_zip_array_init(&new_ext_block, sizeof(mz_uint8));
7109 
7110  MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7111  MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7112  MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX);
7113 
7114  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))
7115  {
7116  mz_zip_array_clear(pZip, &new_ext_block);
7117  return MZ_FALSE;
7118  }
7119 
7120  MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size);
7121 
7122  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7123  {
7124  mz_zip_array_clear(pZip, &new_ext_block);
7125  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7126  }
7127 
7128  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len))
7129  {
7130  mz_zip_array_clear(pZip, &new_ext_block);
7131  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7132  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7133  }
7134 
7135  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size))
7136  {
7137  mz_zip_array_clear(pZip, &new_ext_block);
7138  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7139  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7140  }
7141 
7142  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))
7143  {
7144  mz_zip_array_clear(pZip, &new_ext_block);
7145  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7146  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7147  }
7148 
7149  mz_zip_array_clear(pZip, &new_ext_block);
7150  }
7151  else
7152  {
7153  /* sanity checks */
7154  if (cur_dst_file_ofs > MZ_UINT32_MAX)
7155  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7156 
7157  if (local_dir_header_ofs >= MZ_UINT32_MAX)
7158  return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7159 
7160  MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
7161 
7162  if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7163  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7164 
7165  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))
7166  {
7167  mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7168  return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7169  }
7170  }
7171</