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