1 #include "miniz.h"
2
3 /**************************************************************************
4 *
5 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
7 * All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
30 typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
31 typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
32
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36
37 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
38 /* 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/ */
39 #if 0
40 static mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
41 {
42 static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
43 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
44 mz_uint32 crcu32 = (mz_uint32)crc;
45 if (!ptr)
46 return MZ_CRC32_INIT;
47 crcu32 = ~crcu32;
48 while (buf_len--)
49 {
50 mz_uint8 b = *ptr++;
51 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
52 crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
53 }
54 return ~crcu32;
55 }
56 #elif defined(USE_EXTERNAL_MZCRC)
57 /* If USE_EXTERNAL_CRC is defined, an external module will export the
58 * mz_crc32() symbol for us to use, e.g. an SSE-accelerated version.
59 * Depending on the impl, it may be necessary to ~ the input/output crc values.
60 */
61 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len);
62 #else
63 /* Faster, but larger CPU cache footprint.
64 */
mz_crc32(mz_ulong crc,const mz_uint8 * ptr,size_t buf_len)65 static mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
66 {
67 static const mz_uint32 s_crc_table[256] =
68 {
69 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
70 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
71 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
72 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
73 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
74 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
75 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
76 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
77 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
78 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
79 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
80 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
81 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
82 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
83 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
84 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
85 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
86 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
87 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
88 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
89 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
90 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
91 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
92 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
93 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
94 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
95 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
96 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
97 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
98 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
99 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
100 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
101 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
102 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
103 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
104 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
105 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
106 };
107
108 mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
109 const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
110
111 while (buf_len >= 4)
112 {
113 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
114 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
115 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
116 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
117 pByte_buf += 4;
118 buf_len -= 4;
119 }
120
121 while (buf_len)
122 {
123 crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
124 ++pByte_buf;
125 --buf_len;
126 }
127
128 return ~crc32;
129 }
130 #endif
131 #endif /* MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS */
132
miniz_def_alloc_func(void * opaque,size_t items,size_t size)133 static /*MINIZ_EXPORT*/ void *miniz_def_alloc_func(void *opaque, size_t items, size_t size)
134 {
135 (void)opaque, (void)items, (void)size;
136 return MZ_MALLOC(items * size);
137 }
miniz_def_free_func(void * opaque,void * address)138 static /*MINIZ_EXPORT*/ void miniz_def_free_func(void *opaque, void *address)
139 {
140 (void)opaque, (void)address;
141 MZ_FREE(address);
142 }
miniz_def_realloc_func(void * opaque,void * address,size_t items,size_t size)143 static /*MINIZ_EXPORT*/ void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
144 {
145 (void)opaque, (void)address, (void)items, (void)size;
146 return MZ_REALLOC(address, items * size);
147 }
148
149 #ifdef __cplusplus
150 }
151 #endif
152
153 /*
154 This is free and unencumbered software released into the public domain.
155
156 Anyone is free to copy, modify, publish, use, compile, sell, or
157 distribute this software, either in source code form or as a compiled
158 binary, for any purpose, commercial or non-commercial, and by any
159 means.
160
161 In jurisdictions that recognize copyright laws, the author or authors
162 of this software dedicate any and all copyright interest in the
163 software to the public domain. We make this dedication for the benefit
164 of the public at large and to the detriment of our heirs and
165 successors. We intend this dedication to be an overt act of
166 relinquishment in perpetuity of all present and future rights to this
167 software under copyright law.
168
169 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
170 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
171 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
172 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
173 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
174 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
175 OTHER DEALINGS IN THE SOFTWARE.
176
177 For more information, please refer to <http://unlicense.org/>
178 */
179
180 #ifndef MINIZ_NO_INFLATE_APIS
181
182 #ifdef __cplusplus
183 extern "C" {
184 #endif
185
186 /* ------------------- Low-level Decompression (completely independent from all compression API's) */
187
188 #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
189 #define TINFL_MEMSET(p, c, l) memset(p, c, l)
190
191 #define TINFL_CR_BEGIN \
192 switch (r->m_state) \
193 { \
194 case 0:
195 #define TINFL_CR_RETURN(state_index, result) \
196 do \
197 { \
198 status = result; \
199 r->m_state = state_index; \
200 goto common_exit; \
201 case state_index:; \
202 } \
203 MZ_MACRO_END
204 #define TINFL_CR_RETURN_FOREVER(state_index, result) \
205 do \
206 { \
207 for (;;) \
208 { \
209 TINFL_CR_RETURN(state_index, result); \
210 } \
211 } \
212 MZ_MACRO_END
213 #define TINFL_CR_FINISH }
214
215 #define TINFL_GET_BYTE(state_index, c) \
216 do \
217 { \
218 while (pIn_buf_cur >= pIn_buf_end) \
219 { \
220 TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
221 } \
222 c = *pIn_buf_cur++; \
223 } \
224 MZ_MACRO_END
225
226 #define TINFL_NEED_BITS(state_index, n) \
227 do \
228 { \
229 mz_uint c; \
230 TINFL_GET_BYTE(state_index, c); \
231 bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
232 num_bits += 8; \
233 } while (num_bits < (mz_uint)(n))
234 #define TINFL_SKIP_BITS(state_index, n) \
235 do \
236 { \
237 if (num_bits < (mz_uint)(n)) \
238 { \
239 TINFL_NEED_BITS(state_index, n); \
240 } \
241 bit_buf >>= (n); \
242 num_bits -= (n); \
243 } \
244 MZ_MACRO_END
245 #define TINFL_GET_BITS(state_index, b, n) \
246 do \
247 { \
248 if (num_bits < (mz_uint)(n)) \
249 { \
250 TINFL_NEED_BITS(state_index, n); \
251 } \
252 b = bit_buf & ((1 << (n)) - 1); \
253 bit_buf >>= (n); \
254 num_bits -= (n); \
255 } \
256 MZ_MACRO_END
257
258 /* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */
259 /* 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 */
260 /* 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 */
261 /* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
262 #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \
263 do \
264 { \
265 temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \
266 if (temp >= 0) \
267 { \
268 code_len = temp >> 9; \
269 if ((code_len) && (num_bits >= code_len)) \
270 break; \
271 } \
272 else if (num_bits > TINFL_FAST_LOOKUP_BITS) \
273 { \
274 code_len = TINFL_FAST_LOOKUP_BITS; \
275 do \
276 { \
277 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
278 } while ((temp < 0) && (num_bits >= (code_len + 1))); \
279 if (temp >= 0) \
280 break; \
281 } \
282 TINFL_GET_BYTE(state_index, c); \
283 bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
284 num_bits += 8; \
285 } while (num_bits < 15);
286
287 /* 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 */
288 /* 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 */
289 /* 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. */
290 /* The slow path is only executed at the very end of the input buffer. */
291 /* 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 */
292 /* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */
293 #define TINFL_HUFF_DECODE(state_index, sym, pHuff) \
294 do \
295 { \
296 int temp; \
297 mz_uint code_len, c; \
298 if (num_bits < 15) \
299 { \
300 if ((pIn_buf_end - pIn_buf_cur) < 2) \
301 { \
302 TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \
303 } \
304 else \
305 { \
306 bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
307 pIn_buf_cur += 2; \
308 num_bits += 16; \
309 } \
310 } \
311 if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \
312 code_len = temp >> 9, temp &= 511; \
313 else \
314 { \
315 code_len = TINFL_FAST_LOOKUP_BITS; \
316 do \
317 { \
318 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
319 } while (temp < 0); \
320 } \
321 sym = temp; \
322 bit_buf >>= code_len; \
323 num_bits -= code_len; \
324 } \
325 MZ_MACRO_END
326
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)327 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)
328 {
329 static const int s_length_base[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 };
330 static const int s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 };
331 static const int s_dist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 };
332 static const int s_dist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
333 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 };
334 static const int s_min_table_sizes[3] = { 257, 1, 4 };
335
336 tinfl_status status = TINFL_STATUS_FAILED;
337 mz_uint32 num_bits, dist, counter, num_extra;
338 tinfl_bit_buf_t bit_buf;
339 const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
340 mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
341 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;
342
343 /* 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). */
344 if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))
345 {
346 *pIn_buf_size = *pOut_buf_size = 0;
347 return TINFL_STATUS_BAD_PARAM;
348 }
349
350 num_bits = r->m_num_bits;
351 bit_buf = r->m_bit_buf;
352 dist = r->m_dist;
353 counter = r->m_counter;
354 num_extra = r->m_num_extra;
355 dist_from_out_buf_start = r->m_dist_from_out_buf_start;
356 TINFL_CR_BEGIN
357
358 bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
359 r->m_z_adler32 = r->m_check_adler32 = 1;
360 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
361 {
362 TINFL_GET_BYTE(1, r->m_zhdr0);
363 TINFL_GET_BYTE(2, r->m_zhdr1);
364 counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
365 if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
366 counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
367 if (counter)
368 {
369 TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
370 }
371 }
372
373 do
374 {
375 TINFL_GET_BITS(3, r->m_final, 3);
376 r->m_type = r->m_final >> 1;
377 if (r->m_type == 0)
378 {
379 TINFL_SKIP_BITS(5, num_bits & 7);
380 for (counter = 0; counter < 4; ++counter)
381 {
382 if (num_bits)
383 TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
384 else
385 TINFL_GET_BYTE(7, r->m_raw_header[counter]);
386 }
387 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))))
388 {
389 TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
390 }
391 while ((counter) && (num_bits))
392 {
393 TINFL_GET_BITS(51, dist, 8);
394 while (pOut_buf_cur >= pOut_buf_end)
395 {
396 TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
397 }
398 *pOut_buf_cur++ = (mz_uint8)dist;
399 counter--;
400 }
401 while (counter)
402 {
403 size_t n;
404 while (pOut_buf_cur >= pOut_buf_end)
405 {
406 TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
407 }
408 while (pIn_buf_cur >= pIn_buf_end)
409 {
410 TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);
411 }
412 n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
413 TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
414 pIn_buf_cur += n;
415 pOut_buf_cur += n;
416 counter -= (mz_uint)n;
417 }
418 }
419 else if (r->m_type == 3)
420 {
421 TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
422 }
423 else
424 {
425 if (r->m_type == 1)
426 {
427 mz_uint8 *p = r->m_tables[0].m_code_size;
428 mz_uint i;
429 r->m_table_sizes[0] = 288;
430 r->m_table_sizes[1] = 32;
431 TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
432 for (i = 0; i <= 143; ++i)
433 *p++ = 8;
434 for (; i <= 255; ++i)
435 *p++ = 9;
436 for (; i <= 279; ++i)
437 *p++ = 7;
438 for (; i <= 287; ++i)
439 *p++ = 8;
440 }
441 else
442 {
443 for (counter = 0; counter < 3; counter++)
444 {
445 TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
446 r->m_table_sizes[counter] += s_min_table_sizes[counter];
447 }
448 MZ_CLEAR_ARR(r->m_tables[2].m_code_size);
449 for (counter = 0; counter < r->m_table_sizes[2]; counter++)
450 {
451 mz_uint s;
452 TINFL_GET_BITS(14, s, 3);
453 r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
454 }
455 r->m_table_sizes[2] = 19;
456 }
457 for (; (int)r->m_type >= 0; r->m_type--)
458 {
459 int tree_next, tree_cur;
460 tinfl_huff_table *pTable;
461 mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
462 pTable = &r->m_tables[r->m_type];
463 MZ_CLEAR_ARR(total_syms);
464 MZ_CLEAR_ARR(pTable->m_look_up);
465 MZ_CLEAR_ARR(pTable->m_tree);
466 for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
467 total_syms[pTable->m_code_size[i]]++;
468 used_syms = 0, total = 0;
469 next_code[0] = next_code[1] = 0;
470 for (i = 1; i <= 15; ++i)
471 {
472 used_syms += total_syms[i];
473 next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
474 }
475 if ((65536 != total) && (used_syms > 1))
476 {
477 TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
478 }
479 for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
480 {
481 mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index];
482 if (!code_size)
483 continue;
484 cur_code = next_code[code_size]++;
485 for (l = code_size; l > 0; l--, cur_code >>= 1)
486 rev_code = (rev_code << 1) | (cur_code & 1);
487 if (code_size <= TINFL_FAST_LOOKUP_BITS)
488 {
489 mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
490 while (rev_code < TINFL_FAST_LOOKUP_SIZE)
491 {
492 pTable->m_look_up[rev_code] = k;
493 rev_code += (1 << code_size);
494 }
495 continue;
496 }
497 if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
498 {
499 pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
500 tree_cur = tree_next;
501 tree_next -= 2;
502 }
503 rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
504 for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
505 {
506 tree_cur -= ((rev_code >>= 1) & 1);
507 if (!pTable->m_tree[-tree_cur - 1])
508 {
509 pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
510 tree_cur = tree_next;
511 tree_next -= 2;
512 }
513 else
514 tree_cur = pTable->m_tree[-tree_cur - 1];
515 }
516 tree_cur -= ((rev_code >>= 1) & 1);
517 pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
518 }
519 if (r->m_type == 2)
520 {
521 for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)
522 {
523 mz_uint s;
524 TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
525 if (dist < 16)
526 {
527 r->m_len_codes[counter++] = (mz_uint8)dist;
528 continue;
529 }
530 if ((dist == 16) && (!counter))
531 {
532 TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
533 }
534 num_extra = "\02\03\07"[dist - 16];
535 TINFL_GET_BITS(18, s, num_extra);
536 s += "\03\03\013"[dist - 16];
537 TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
538 counter += s;
539 }
540 if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
541 {
542 TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
543 }
544 TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]);
545 TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
546 }
547 }
548 for (;;)
549 {
550 mz_uint8 *pSrc;
551 for (;;)
552 {
553 if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
554 {
555 TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
556 if (counter >= 256)
557 break;
558 while (pOut_buf_cur >= pOut_buf_end)
559 {
560 TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
561 }
562 *pOut_buf_cur++ = (mz_uint8)counter;
563 }
564 else
565 {
566 int sym2;
567 mz_uint code_len;
568 #if TINFL_USE_64BIT_BITBUF
569 if (num_bits < 30)
570 {
571 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
572 pIn_buf_cur += 4;
573 num_bits += 32;
574 }
575 #else
576 if (num_bits < 15)
577 {
578 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
579 pIn_buf_cur += 2;
580 num_bits += 16;
581 }
582 #endif
583 if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
584 code_len = sym2 >> 9;
585 else
586 {
587 code_len = TINFL_FAST_LOOKUP_BITS;
588 do
589 {
590 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
591 } while (sym2 < 0);
592 }
593 counter = sym2;
594 bit_buf >>= code_len;
595 num_bits -= code_len;
596 if (counter & 256)
597 break;
598
599 #if !TINFL_USE_64BIT_BITBUF
600 if (num_bits < 15)
601 {
602 bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
603 pIn_buf_cur += 2;
604 num_bits += 16;
605 }
606 #endif
607 if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
608 code_len = sym2 >> 9;
609 else
610 {
611 code_len = TINFL_FAST_LOOKUP_BITS;
612 do
613 {
614 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
615 } while (sym2 < 0);
616 }
617 bit_buf >>= code_len;
618 num_bits -= code_len;
619
620 pOut_buf_cur[0] = (mz_uint8)counter;
621 if (sym2 & 256)
622 {
623 pOut_buf_cur++;
624 counter = sym2;
625 break;
626 }
627 pOut_buf_cur[1] = (mz_uint8)sym2;
628 pOut_buf_cur += 2;
629 }
630 }
631 if ((counter &= 511) == 256)
632 break;
633
634 num_extra = s_length_extra[counter - 257];
635 counter = s_length_base[counter - 257];
636 if (num_extra)
637 {
638 mz_uint extra_bits;
639 TINFL_GET_BITS(25, extra_bits, num_extra);
640 counter += extra_bits;
641 }
642
643 TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
644 num_extra = s_dist_extra[dist];
645 dist = s_dist_base[dist];
646 if (num_extra)
647 {
648 mz_uint extra_bits;
649 TINFL_GET_BITS(27, extra_bits, num_extra);
650 dist += extra_bits;
651 }
652
653 dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
654 if ((dist == 0 || dist > dist_from_out_buf_start || dist_from_out_buf_start == 0) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
655 {
656 TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
657 }
658
659 pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
660
661 if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
662 {
663 while (counter--)
664 {
665 while (pOut_buf_cur >= pOut_buf_end)
666 {
667 TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
668 }
669 *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
670 }
671 continue;
672 }
673 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
674 else if ((counter >= 9) && (counter <= dist))
675 {
676 const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
677 do
678 {
679 #ifdef MINIZ_UNALIGNED_USE_MEMCPY
680 memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2);
681 #else
682 ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
683 ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
684 #endif
685 pOut_buf_cur += 8;
686 } while ((pSrc += 8) < pSrc_end);
687 if ((counter &= 7) < 3)
688 {
689 if (counter)
690 {
691 pOut_buf_cur[0] = pSrc[0];
692 if (counter > 1)
693 pOut_buf_cur[1] = pSrc[1];
694 pOut_buf_cur += counter;
695 }
696 continue;
697 }
698 }
699 #endif
700 while(counter>2)
701 {
702 pOut_buf_cur[0] = pSrc[0];
703 pOut_buf_cur[1] = pSrc[1];
704 pOut_buf_cur[2] = pSrc[2];
705 pOut_buf_cur += 3;
706 pSrc += 3;
707 counter -= 3;
708 }
709 if (counter > 0)
710 {
711 pOut_buf_cur[0] = pSrc[0];
712 if (counter > 1)
713 pOut_buf_cur[1] = pSrc[1];
714 pOut_buf_cur += counter;
715 }
716 }
717 }
718 } while (!(r->m_final & 1));
719
720 /* 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. */
721 /* 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. */
722 TINFL_SKIP_BITS(32, num_bits & 7);
723 while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
724 {
725 --pIn_buf_cur;
726 num_bits -= 8;
727 }
728 bit_buf &= (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
729 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). */
730
731 if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
732 {
733 for (counter = 0; counter < 4; ++counter)
734 {
735 mz_uint s;
736 if (num_bits)
737 TINFL_GET_BITS(41, s, 8);
738 else
739 TINFL_GET_BYTE(42, s);
740 r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
741 }
742 }
743 TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
744
745 TINFL_CR_FINISH
746
747 common_exit:
748 /* As long as we aren't telling the caller that we NEED more input to make forward progress: */
749 /* 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. */
750 /* 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. */
751 if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS))
752 {
753 while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
754 {
755 --pIn_buf_cur;
756 num_bits -= 8;
757 }
758 }
759 r->m_num_bits = num_bits;
760 r->m_bit_buf = bit_buf & (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
761 r->m_dist = dist;
762 r->m_counter = counter;
763 r->m_num_extra = num_extra;
764 r->m_dist_from_out_buf_start = dist_from_out_buf_start;
765 *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
766 *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
767 if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
768 {
769 const mz_uint8 *ptr = pOut_buf_next;
770 size_t buf_len = *pOut_buf_size;
771 mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;
772 size_t block_len = buf_len % 5552;
773 while (buf_len)
774 {
775 for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
776 {
777 s1 += ptr[0], s2 += s1;
778 s1 += ptr[1], s2 += s1;
779 s1 += ptr[2], s2 += s1;
780 s1 += ptr[3], s2 += s1;
781 s1 += ptr[4], s2 += s1;
782 s1 += ptr[5], s2 += s1;
783 s1 += ptr[6], s2 += s1;
784 s1 += ptr[7], s2 += s1;
785 }
786 for (; i < block_len; ++i)
787 s1 += *ptr++, s2 += s1;
788 s1 %= 65521U, s2 %= 65521U;
789 buf_len -= block_len;
790 block_len = 5552;
791 }
792 r->m_check_adler32 = (s2 << 16) + s1;
793 if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
794 status = TINFL_STATUS_ADLER32_MISMATCH;
795 }
796 return status;
797 }
798
799 #ifdef __cplusplus
800 }
801 #endif
802
803 #endif /*#ifndef MINIZ_NO_INFLATE_APIS*/
804 /**************************************************************************
805 *
806 * Copyright 2013-2014 RAD Game Tools and Valve Software
807 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
808 * Copyright 2016 Martin Raiber
809 * All Rights Reserved.
810 *
811 * Permission is hereby granted, free of charge, to any person obtaining a copy
812 * of this software and associated documentation files (the "Software"), to deal
813 * in the Software without restriction, including without limitation the rights
814 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
815 * copies of the Software, and to permit persons to whom the Software is
816 * furnished to do so, subject to the following conditions:
817 *
818 * The above copyright notice and this permission notice shall be included in
819 * all copies or substantial portions of the Software.
820 *
821 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
822 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
823 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
824 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
825 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
826 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
827 * THE SOFTWARE.
828 *
829 **************************************************************************/
830
831
832 #ifndef MINIZ_NO_ARCHIVE_APIS
833
834 #ifdef __cplusplus
835 extern "C" {
836 #endif
837
838 /* ------------------- .ZIP archive reading */
839
840 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
841
842 /* 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. */
843 enum
844 {
845 /* ZIP archive identifiers and record sizes */
846 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
847 MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
848 MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
849 MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
850 MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
851 MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
852
853 /* ZIP64 archive identifier and record sizes */
854 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
855 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
856 MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
857 MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
858 MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
859 MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
860 MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
861 MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
862
863 /* Central directory header record offsets */
864 MZ_ZIP_CDH_SIG_OFS = 0,
865 MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
866 MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
867 MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
868 MZ_ZIP_CDH_METHOD_OFS = 10,
869 MZ_ZIP_CDH_FILE_TIME_OFS = 12,
870 MZ_ZIP_CDH_FILE_DATE_OFS = 14,
871 MZ_ZIP_CDH_CRC32_OFS = 16,
872 MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
873 MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
874 MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
875 MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
876 MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
877 MZ_ZIP_CDH_DISK_START_OFS = 34,
878 MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
879 MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
880 MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
881
882 /* Local directory header offsets */
883 MZ_ZIP_LDH_SIG_OFS = 0,
884 MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
885 MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
886 MZ_ZIP_LDH_METHOD_OFS = 8,
887 MZ_ZIP_LDH_FILE_TIME_OFS = 10,
888 MZ_ZIP_LDH_FILE_DATE_OFS = 12,
889 MZ_ZIP_LDH_CRC32_OFS = 14,
890 MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
891 MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
892 MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
893 MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
894 MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3,
895
896 /* End of central directory offsets */
897 MZ_ZIP_ECDH_SIG_OFS = 0,
898 MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
899 MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
900 MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
901 MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
902 MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
903 MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
904 MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
905
906 /* ZIP64 End of central directory locator offsets */
907 MZ_ZIP64_ECDL_SIG_OFS = 0, /* 4 bytes */
908 MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4, /* 4 bytes */
909 MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8, /* 8 bytes */
910 MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
911
912 /* ZIP64 End of central directory header offsets */
913 MZ_ZIP64_ECDH_SIG_OFS = 0, /* 4 bytes */
914 MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4, /* 8 bytes */
915 MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12, /* 2 bytes */
916 MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14, /* 2 bytes */
917 MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16, /* 4 bytes */
918 MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20, /* 4 bytes */
919 MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
920 MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32, /* 8 bytes */
921 MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40, /* 8 bytes */
922 MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48, /* 8 bytes */
923 MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
924 MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
925 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
926 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
927 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
928 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
929 MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
930 };
931
932 typedef struct
933 {
934 void *m_p;
935 size_t m_size, m_capacity;
936 mz_uint m_element_size;
937 } mz_zip_array;
938
939 struct mz_zip_internal_state_tag
940 {
941 mz_zip_array m_central_dir;
942 mz_zip_array m_central_dir_offsets;
943 mz_zip_array m_sorted_central_dir_offsets;
944
945 /* The flags passed in when the archive is initially opened. */
946 uint32_t m_init_flags;
947
948 /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */
949 mz_bool m_zip64;
950
951 /* 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.) */
952 mz_bool m_zip64_has_extended_info_fields;
953
954 void *m_pMem;
955 };
956
957 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
958
959 #if defined(DEBUG) || defined(_DEBUG)
mz_zip_array_range_check(const mz_zip_array * pArray,mz_uint index)960 static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index)
961 {
962 MZ_ASSERT(index < pArray->m_size);
963 return index;
964 }
965 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]
966 #else
967 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
968 #endif
969
mz_zip_array_clear(mz_zip_archive * pZip,mz_zip_array * pArray)970 static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
971 {
972 pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
973 memset(pArray, 0, sizeof(mz_zip_array));
974 }
975
mz_zip_array_ensure_capacity(mz_zip_archive * pZip,mz_zip_array * pArray,size_t min_new_capacity,mz_uint growing)976 static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
977 {
978 void *pNew_p;
979 size_t new_capacity = min_new_capacity;
980 MZ_ASSERT(pArray->m_element_size);
981 if (pArray->m_capacity >= min_new_capacity)
982 return MZ_TRUE;
983 if (growing)
984 {
985 new_capacity = MZ_MAX(1, pArray->m_capacity);
986 while (new_capacity < min_new_capacity)
987 new_capacity *= 2;
988 }
989 if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
990 return MZ_FALSE;
991 pArray->m_p = pNew_p;
992 pArray->m_capacity = new_capacity;
993 return MZ_TRUE;
994 }
995
mz_zip_array_resize(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_size,mz_uint growing)996 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
997 {
998 if (new_size > pArray->m_capacity)
999 {
1000 if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
1001 return MZ_FALSE;
1002 }
1003 pArray->m_size = new_size;
1004 return MZ_TRUE;
1005 }
1006
mz_zip_set_error(mz_zip_archive * pZip,mz_zip_error err_num)1007 static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num)
1008 {
1009 if (pZip)
1010 pZip->m_last_error = err_num;
1011 return MZ_FALSE;
1012 }
1013
mz_zip_reader_init_internal(mz_zip_archive * pZip,mz_uint flags)1014 static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
1015 {
1016 (void)flags;
1017 if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
1018 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1019
1020 if (!pZip->m_pAlloc)
1021 pZip->m_pAlloc = miniz_def_alloc_func;
1022 if (!pZip->m_pFree)
1023 pZip->m_pFree = miniz_def_free_func;
1024 if (!pZip->m_pRealloc)
1025 pZip->m_pRealloc = miniz_def_realloc_func;
1026
1027 pZip->m_archive_size = 0;
1028 pZip->m_central_directory_file_ofs = 0;
1029 pZip->m_total_files = 0;
1030 pZip->m_last_error = MZ_ZIP_NO_ERROR;
1031
1032 if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
1033 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
1034
1035 memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
1036 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
1037 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
1038 MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
1039 pZip->m_pState->m_init_flags = flags;
1040 pZip->m_pState->m_zip64 = MZ_FALSE;
1041 pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;
1042
1043 pZip->m_zip_mode = MZ_ZIP_MODE_READING;
1044
1045 return MZ_TRUE;
1046 }
1047
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)1048 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)
1049 {
1050 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;
1051 const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
1052 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);
1053 mz_uint8 l = 0, r = 0;
1054 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
1055 pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
1056 pE = pL + MZ_MIN(l_len, r_len);
1057 while (pL < pE)
1058 {
1059 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
1060 break;
1061 pL++;
1062 pR++;
1063 }
1064 return (pL == pE) ? (l_len < r_len) : (l < r);
1065 }
1066
1067 #define MZ_SWAP_UINT32(a, b) \
1068 do \
1069 { \
1070 mz_uint32 t = a; \
1071 a = b; \
1072 b = t; \
1073 } \
1074 MZ_MACRO_END
1075
1076 /* 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.) */
mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive * pZip)1077 static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
1078 {
1079 mz_zip_internal_state *pState = pZip->m_pState;
1080 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
1081 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
1082 mz_uint32 *pIndices;
1083 mz_uint32 start, end;
1084 const mz_uint32 size = pZip->m_total_files;
1085
1086 if (size <= 1U)
1087 return;
1088
1089 pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
1090
1091 start = (size - 2U) >> 1U;
1092 for (;;)
1093 {
1094 mz_uint64 child, root = start;
1095 for (;;)
1096 {
1097 if ((child = (root << 1U) + 1U) >= size)
1098 break;
1099 child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
1100 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
1101 break;
1102 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
1103 root = child;
1104 }
1105 if (!start)
1106 break;
1107 start--;
1108 }
1109
1110 end = size - 1;
1111 while (end > 0)
1112 {
1113 mz_uint64 child, root = 0;
1114 MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
1115 for (;;)
1116 {
1117 if ((child = (root << 1U) + 1U) >= end)
1118 break;
1119 child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
1120 if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
1121 break;
1122 MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
1123 root = child;
1124 }
1125 end--;
1126 }
1127 }
1128
mz_zip_reader_locate_header_sig(mz_zip_archive * pZip,mz_uint32 record_sig,mz_uint32 record_size,mz_int64 * pOfs)1129 static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)
1130 {
1131 mz_int64 cur_file_ofs;
1132 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
1133 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
1134
1135 /* Basic sanity checks - reject files which are too small */
1136 if (pZip->m_archive_size < record_size)
1137 return MZ_FALSE;
1138
1139 /* Find the record by scanning the file from the end towards the beginning. */
1140 cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
1141 for (;;)
1142 {
1143 int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
1144
1145 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
1146 return MZ_FALSE;
1147
1148 for (i = n - 4; i >= 0; --i)
1149 {
1150 mz_uint s = MZ_READ_LE32(pBuf + i);
1151 if (s == record_sig)
1152 {
1153 if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
1154 break;
1155 }
1156 }
1157
1158 if (i >= 0)
1159 {
1160 cur_file_ofs += i;
1161 break;
1162 }
1163
1164 /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */
1165 if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size)))
1166 return MZ_FALSE;
1167
1168 cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
1169 }
1170
1171 *pOfs = cur_file_ofs;
1172 return MZ_TRUE;
1173 }
1174
mz_zip_reader_read_central_dir(mz_zip_archive * pZip,mz_uint flags)1175 static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)
1176 {
1177 mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
1178 mz_uint64 cdir_ofs = 0;
1179 mz_int64 cur_file_ofs = 0;
1180 const mz_uint8 *p;
1181
1182 mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
1183 mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
1184 mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
1185 mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
1186 mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
1187
1188 mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
1189 mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
1190
1191 mz_uint64 zip64_end_of_central_dir_ofs = 0;
1192
1193 /* 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. */
1194 if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
1195 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
1196
1197 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))
1198 return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
1199
1200 /* Read and verify the end of central directory record. */
1201 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)
1202 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
1203
1204 if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
1205 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
1206
1207 if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
1208 {
1209 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)
1210 {
1211 if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG)
1212 {
1213 zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
1214 if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
1215 return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
1216
1217 if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
1218 {
1219 if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG)
1220 {
1221 pZip->m_pState->m_zip64 = MZ_TRUE;
1222 }
1223 }
1224 }
1225 }
1226 }
1227
1228 pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
1229 cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
1230 num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
1231 cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
1232 cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
1233 cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
1234
1235 if (pZip->m_pState->m_zip64)
1236 {
1237 mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
1238 mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
1239 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);
1240 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);
1241 mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
1242
1243 if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
1244 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1245
1246 if (zip64_total_num_of_disks != 1U)
1247 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
1248
1249 /* Check for miniz's practical limits */
1250 if (zip64_cdir_total_entries > (mz_uint64)MZ_UINT32_MAX)
1251 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
1252
1253 pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
1254
1255 if (zip64_cdir_total_entries_on_this_disk > (mz_uint64)MZ_UINT32_MAX)
1256 return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
1257
1258 cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;
1259
1260 /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */
1261 if (zip64_size_of_central_directory > (mz_uint64)MZ_UINT32_MAX)
1262 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
1263
1264 cdir_size = (mz_uint32)zip64_size_of_central_directory;
1265
1266 num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
1267
1268 cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
1269
1270 cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
1271 }
1272
1273 if (pZip->m_total_files != cdir_entries_on_this_disk)
1274 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
1275
1276 if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
1277 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
1278
1279 if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
1280 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1281
1282 if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
1283 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1284
1285 pZip->m_central_directory_file_ofs = cdir_ofs;
1286
1287 if (pZip->m_total_files)
1288 {
1289 mz_uint i, n;
1290 /* 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. */
1291 if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
1292 (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
1293 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
1294
1295 if (sort_central_dir)
1296 {
1297 if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
1298 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
1299 }
1300
1301 if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
1302 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
1303
1304 /* Now create an index into the central directory file records, do some basic sanity checking on each record */
1305 p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
1306 for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
1307 {
1308 mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
1309 mz_uint64 comp_size, decomp_size, local_header_ofs;
1310
1311 if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
1312 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1313
1314 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);
1315
1316 if (sort_central_dir)
1317 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
1318
1319 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
1320 decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
1321 local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
1322 filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1323 ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
1324
1325 if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
1326 (ext_data_size) &&
1327 (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
1328 {
1329 /* Attempt to find zip64 extended information field in the entry's extra data */
1330 mz_uint32 extra_size_remaining = ext_data_size;
1331
1332 if (extra_size_remaining)
1333 {
1334 const mz_uint8 *pExtra_data;
1335 void* buf = NULL;
1336
1337 if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n)
1338 {
1339 buf = MZ_MALLOC(ext_data_size);
1340 if(buf==NULL)
1341 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
1342
1343 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)
1344 {
1345 MZ_FREE(buf);
1346 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
1347 }
1348
1349 pExtra_data = (mz_uint8*)buf;
1350 }
1351 else
1352 {
1353 pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
1354 }
1355
1356 do
1357 {
1358 mz_uint32 field_id;
1359 mz_uint32 field_data_size;
1360
1361 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
1362 {
1363 MZ_FREE(buf);
1364 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1365 }
1366
1367 field_id = MZ_READ_LE16(pExtra_data);
1368 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
1369
1370 if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
1371 {
1372 MZ_FREE(buf);
1373 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1374 }
1375
1376 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
1377 {
1378 /* 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). */
1379 pZip->m_pState->m_zip64 = MZ_TRUE;
1380 pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
1381 break;
1382 }
1383
1384 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
1385 extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
1386 } while (extra_size_remaining);
1387
1388 MZ_FREE(buf);
1389 }
1390 }
1391
1392 /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */
1393 if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
1394 {
1395 if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
1396 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1397 }
1398
1399 disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
1400 if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
1401 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
1402
1403 if (comp_size != MZ_UINT32_MAX)
1404 {
1405 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)
1406 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1407 }
1408
1409 bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
1410 if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
1411 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
1412
1413 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)
1414 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1415
1416 n -= total_header_size;
1417 p += total_header_size;
1418 }
1419 }
1420
1421 if (sort_central_dir)
1422 mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
1423
1424 return MZ_TRUE;
1425 }
1426
mz_zip_reader_end_internal(mz_zip_archive * pZip,mz_bool set_last_error)1427 static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
1428 {
1429 mz_bool status = MZ_TRUE;
1430
1431 if (!pZip)
1432 return MZ_FALSE;
1433
1434 if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
1435 {
1436 if (set_last_error)
1437 pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;
1438
1439 return MZ_FALSE;
1440 }
1441
1442 if (pZip->m_pState)
1443 {
1444 mz_zip_internal_state *pState = pZip->m_pState;
1445 pZip->m_pState = NULL;
1446
1447 mz_zip_array_clear(pZip, &pState->m_central_dir);
1448 mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
1449 mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
1450
1451 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
1452 }
1453 pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
1454
1455 return status;
1456 }
1457
mz_zip_reader_end(mz_zip_archive * pZip)1458 mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
1459 {
1460 return mz_zip_reader_end_internal(pZip, MZ_TRUE);
1461 }
mz_zip_reader_init(mz_zip_archive * pZip,mz_uint64 size,mz_uint flags)1462 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
1463 {
1464 if ((!pZip) || (!pZip->m_pRead))
1465 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1466
1467 if (!mz_zip_reader_init_internal(pZip, flags))
1468 return MZ_FALSE;
1469
1470 pZip->m_zip_type = MZ_ZIP_TYPE_USER;
1471 pZip->m_archive_size = size;
1472
1473 if (!mz_zip_reader_read_central_dir(pZip, flags))
1474 {
1475 mz_zip_reader_end_internal(pZip, MZ_FALSE);
1476 return MZ_FALSE;
1477 }
1478
1479 return MZ_TRUE;
1480 }
1481
mz_zip_get_cdh(mz_zip_archive * pZip,mz_uint file_index)1482 static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
1483 {
1484 if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
1485 return NULL;
1486 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));
1487 }
1488
mz_zip_reader_is_file_encrypted(mz_zip_archive * pZip,mz_uint file_index)1489 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
1490 {
1491 mz_uint m_bit_flag;
1492 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
1493 if (!p)
1494 {
1495 mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1496 return MZ_FALSE;
1497 }
1498
1499 m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
1500 return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;
1501 }
1502
mz_zip_reader_is_file_supported(mz_zip_archive * pZip,mz_uint file_index)1503 mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)
1504 {
1505 mz_uint bit_flag;
1506 mz_uint method;
1507
1508 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
1509 if (!p)
1510 {
1511 mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1512 return MZ_FALSE;
1513 }
1514
1515 method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
1516 bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
1517
1518 if ((method != 0) && (method != MZ_DEFLATED))
1519 {
1520 mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
1521 return MZ_FALSE;
1522 }
1523
1524 if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION))
1525 {
1526 mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
1527 return MZ_FALSE;
1528 }
1529
1530 if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)
1531 {
1532 mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
1533 return MZ_FALSE;
1534 }
1535
1536 return MZ_TRUE;
1537 }
1538
mz_zip_reader_is_file_a_directory(mz_zip_archive * pZip,mz_uint file_index)1539 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
1540 {
1541 mz_uint filename_len, attribute_mapping_id, external_attr;
1542 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
1543 if (!p)
1544 {
1545 mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1546 return MZ_FALSE;
1547 }
1548
1549 filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1550 if (filename_len)
1551 {
1552 if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
1553 return MZ_TRUE;
1554 }
1555
1556 /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */
1557 /* 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. */
1558 /* FIXME: Remove this check? Is it necessary - we already check the filename. */
1559 attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
1560 (void)attribute_mapping_id;
1561
1562 external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
1563 if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
1564 {
1565 return MZ_TRUE;
1566 }
1567
1568 return MZ_FALSE;
1569 }
1570
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)1571 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)
1572 {
1573 mz_uint n;
1574 const mz_uint8 *p = pCentral_dir_header;
1575
1576 if (pFound_zip64_extra_data)
1577 *pFound_zip64_extra_data = MZ_FALSE;
1578
1579 if ((!p) || (!pStat))
1580 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1581
1582 /* Extract fields from the central directory record. */
1583 pStat->m_file_index = file_index;
1584 pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
1585 pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
1586 pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
1587 pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
1588 pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
1589 pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
1590 pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
1591 pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
1592 pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
1593 pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
1594 pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
1595
1596 /* Copy as much of the filename and comment as possible. */
1597 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1598 n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
1599 memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
1600 pStat->m_filename[n] = '\0';
1601
1602 n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
1603 n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
1604 pStat->m_comment_size = n;
1605 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);
1606 pStat->m_comment[n] = '\0';
1607
1608 /* Set some flags for convienance */
1609 pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
1610 pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
1611 pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
1612
1613 /* See if we need to read any zip64 extended information fields. */
1614 /* 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). */
1615 if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX)
1616 {
1617 /* Attempt to find zip64 extended information field in the entry's extra data */
1618 mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
1619
1620 if (extra_size_remaining)
1621 {
1622 const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1623
1624 do
1625 {
1626 mz_uint32 field_id;
1627 mz_uint32 field_data_size;
1628
1629 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
1630 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1631
1632 field_id = MZ_READ_LE16(pExtra_data);
1633 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
1634
1635 if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
1636 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1637
1638 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
1639 {
1640 const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
1641 mz_uint32 field_data_remaining = field_data_size;
1642
1643 if (pFound_zip64_extra_data)
1644 *pFound_zip64_extra_data = MZ_TRUE;
1645
1646 if (pStat->m_uncomp_size == MZ_UINT32_MAX)
1647 {
1648 if (field_data_remaining < sizeof(mz_uint64))
1649 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1650
1651 pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
1652 pField_data += sizeof(mz_uint64);
1653 field_data_remaining -= sizeof(mz_uint64);
1654 }
1655
1656 if (pStat->m_comp_size == MZ_UINT32_MAX)
1657 {
1658 if (field_data_remaining < sizeof(mz_uint64))
1659 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1660
1661 pStat->m_comp_size = MZ_READ_LE64(pField_data);
1662 pField_data += sizeof(mz_uint64);
1663 field_data_remaining -= sizeof(mz_uint64);
1664 }
1665
1666 if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
1667 {
1668 if (field_data_remaining < sizeof(mz_uint64))
1669 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1670
1671 pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
1672 pField_data += sizeof(mz_uint64);
1673 field_data_remaining -= sizeof(mz_uint64);
1674 }
1675
1676 break;
1677 }
1678
1679 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
1680 extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
1681 } while (extra_size_remaining);
1682 }
1683 }
1684
1685 return MZ_TRUE;
1686 }
1687
mz_zip_string_equal(const char * pA,const char * pB,mz_uint len,mz_uint flags)1688 static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
1689 {
1690 mz_uint i;
1691 if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
1692 return 0 == memcmp(pA, pB, len);
1693 for (i = 0; i < len; ++i)
1694 if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
1695 return MZ_FALSE;
1696 return MZ_TRUE;
1697 }
1698
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)1699 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)
1700 {
1701 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;
1702 mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1703 mz_uint8 l = 0, r = 0;
1704 pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
1705 pE = pL + MZ_MIN(l_len, r_len);
1706 while (pL < pE)
1707 {
1708 if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
1709 break;
1710 pL++;
1711 pR++;
1712 }
1713 return (pL == pE) ? (int)(l_len - r_len) : (l - r);
1714 }
1715
mz_zip_locate_file_binary_search(mz_zip_archive * pZip,const char * pFilename,mz_uint32 * pIndex)1716 static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
1717 {
1718 mz_zip_internal_state *pState = pZip->m_pState;
1719 const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
1720 const mz_zip_array *pCentral_dir = &pState->m_central_dir;
1721 mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
1722 const uint32_t size = pZip->m_total_files;
1723 const mz_uint filename_len = (mz_uint)strlen(pFilename);
1724
1725 if (pIndex)
1726 *pIndex = 0;
1727
1728 if (size)
1729 {
1730 /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */
1731 /* honestly the major expense here on 32-bit CPU's will still be the filename compare */
1732 mz_int64 l = 0, h = (mz_int64)size - 1;
1733
1734 while (l <= h)
1735 {
1736 mz_int64 m = l + ((h - l) >> 1);
1737 uint32_t file_index = pIndices[(uint32_t)m];
1738
1739 int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
1740 if (!comp)
1741 {
1742 if (pIndex)
1743 *pIndex = file_index;
1744 return MZ_TRUE;
1745 }
1746 else if (comp < 0)
1747 l = m + 1;
1748 else
1749 h = m - 1;
1750 }
1751 }
1752
1753 return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
1754 }
1755
mz_zip_reader_locate_file(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags)1756 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
1757 {
1758 mz_uint32 index;
1759 if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
1760 return -1;
1761 else
1762 return (int)index;
1763 }
1764
mz_zip_reader_locate_file_v2(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags,mz_uint32 * pIndex)1765 mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
1766 {
1767 mz_uint file_index;
1768 size_t name_len, comment_len;
1769
1770 if (pIndex)
1771 *pIndex = 0;
1772
1773 if ((!pZip) || (!pZip->m_pState) || (!pName))
1774 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1775
1776 /* See if we can use a binary search */
1777 if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&
1778 (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
1779 ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
1780 {
1781 return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
1782 }
1783
1784 /* Locate the entry by scanning the entire central directory */
1785 name_len = strlen(pName);
1786 if (name_len > MZ_UINT16_MAX)
1787 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1788
1789 comment_len = pComment ? strlen(pComment) : 0;
1790 if (comment_len > MZ_UINT16_MAX)
1791 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1792
1793 for (file_index = 0; file_index < pZip->m_total_files; file_index++)
1794 {
1795 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));
1796 mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1797 const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
1798 if (filename_len < name_len)
1799 continue;
1800 if (comment_len)
1801 {
1802 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);
1803 const char *pFile_comment = pFilename + filename_len + file_extra_len;
1804 if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
1805 continue;
1806 }
1807 if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
1808 {
1809 int ofs = filename_len - 1;
1810 do
1811 {
1812 if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
1813 break;
1814 } while (--ofs >= 0);
1815 ofs++;
1816 pFilename += ofs;
1817 filename_len -= ofs;
1818 }
1819 if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
1820 {
1821 if (pIndex)
1822 *pIndex = file_index;
1823 return MZ_TRUE;
1824 }
1825 }
1826
1827 return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
1828 }
1829
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)1830 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)
1831 {
1832 int status = TINFL_STATUS_DONE;
1833 mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
1834 mz_zip_archive_file_stat file_stat;
1835 void *pRead_buf;
1836 mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
1837 mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
1838 tinfl_decompressor inflator;
1839
1840 if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
1841 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1842
1843 if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
1844 return MZ_FALSE;
1845
1846 /* A directory or zero length file */
1847 if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
1848 return MZ_TRUE;
1849
1850 /* Encryption and patch files are not supported. */
1851 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))
1852 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
1853
1854 /* This function only supports decompressing stored and deflate. */
1855 if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
1856 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
1857
1858 /* Ensure supplied output buffer is large enough. */
1859 needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
1860 if (buf_size < needed_size)
1861 return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);
1862
1863 /* Read and parse the local directory entry. */
1864 cur_file_ofs = file_stat.m_local_header_ofs;
1865 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)
1866 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
1867
1868 if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
1869 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1870
1871 cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
1872 if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
1873 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1874
1875 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
1876 {
1877 /* The file is stored or the caller has requested the compressed data. */
1878 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
1879 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
1880
1881 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
1882 if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
1883 {
1884 if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
1885 return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
1886 }
1887 #endif
1888
1889 return MZ_TRUE;
1890 }
1891
1892 /* Decompress the file either directly from memory or from a file input buffer. */
1893 tinfl_init(&inflator);
1894
1895 if (pZip->m_pState->m_pMem)
1896 {
1897 /* Read directly from the archive in memory. */
1898 pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
1899 read_buf_size = read_buf_avail = file_stat.m_comp_size;
1900 comp_remaining = 0;
1901 }
1902 else if (pUser_read_buf)
1903 {
1904 /* Use a user provided read buffer. */
1905 if (!user_read_buf_size)
1906 return MZ_FALSE;
1907 pRead_buf = (mz_uint8 *)pUser_read_buf;
1908 read_buf_size = user_read_buf_size;
1909 read_buf_avail = 0;
1910 comp_remaining = file_stat.m_comp_size;
1911 }
1912 else
1913 {
1914 /* Temporarily allocate a read buffer. */
1915 read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
1916 if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
1917 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
1918
1919 if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
1920 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
1921
1922 read_buf_avail = 0;
1923 comp_remaining = file_stat.m_comp_size;
1924 }
1925
1926 do
1927 {
1928 /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */
1929 size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
1930 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
1931 {
1932 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
1933 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
1934 {
1935 status = TINFL_STATUS_FAILED;
1936 mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
1937 break;
1938 }
1939 cur_file_ofs += read_buf_avail;
1940 comp_remaining -= read_buf_avail;
1941 read_buf_ofs = 0;
1942 }
1943 in_buf_size = (size_t)read_buf_avail;
1944 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));
1945 read_buf_avail -= in_buf_size;
1946 read_buf_ofs += in_buf_size;
1947 out_buf_ofs += out_buf_size;
1948 } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
1949
1950 if (status == TINFL_STATUS_DONE)
1951 {
1952 /* Make sure the entire file was decompressed, and check its CRC. */
1953 if (out_buf_ofs != file_stat.m_uncomp_size)
1954 {
1955 mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
1956 status = TINFL_STATUS_FAILED;
1957 }
1958 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
1959 else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
1960 {
1961 mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
1962 status = TINFL_STATUS_FAILED;
1963 }
1964 #endif
1965 }
1966
1967 if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
1968 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
1969
1970 return status == TINFL_STATUS_DONE;
1971 }
1972
mz_zip_reader_extract_to_mem(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags)1973 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)
1974 {
1975 return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
1976 }
1977
mz_zip_reader_extract_to_heap(mz_zip_archive * pZip,mz_uint file_index,size_t * pSize,mz_uint flags)1978 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
1979 {
1980 mz_uint64 comp_size, uncomp_size, alloc_size;
1981 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
1982 void *pBuf;
1983
1984 if (pSize)
1985 *pSize = 0;
1986
1987 if (!p)
1988 {
1989 mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1990 return NULL;
1991 }
1992
1993 comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
1994 uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
1995
1996 alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
1997 if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
1998 {
1999 mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
2000 return NULL;
2001 }
2002
2003 if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
2004 {
2005 mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
2006 return NULL;
2007 }
2008
2009 if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
2010 {
2011 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
2012 return NULL;
2013 }
2014
2015 if (pSize)
2016 *pSize = (size_t)alloc_size;
2017 return pBuf;
2018 }
2019
mz_zip_reader_extract_file_to_heap(mz_zip_archive * pZip,const char * pFilename,size_t * pSize,mz_uint flags)2020 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
2021 {
2022 mz_uint32 file_index;
2023 if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
2024 {
2025 if (pSize)
2026 *pSize = 0;
2027 return MZ_FALSE;
2028 }
2029 return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
2030 }
2031
2032 /* ------------------- Misc utils */
2033
2034 #if 0 /* unused for now */
2035 mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip)
2036 {
2037 return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
2038 }
2039
2040 mz_zip_type mz_zip_get_type(mz_zip_archive *pZip)
2041 {
2042 return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
2043 }
2044
2045 mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num)
2046 {
2047 mz_zip_error prev_err;
2048
2049 if (!pZip)
2050 return MZ_ZIP_INVALID_PARAMETER;
2051
2052 prev_err = pZip->m_last_error;
2053
2054 pZip->m_last_error = err_num;
2055 return prev_err;
2056 }
2057
2058 mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip)
2059 {
2060 if (!pZip)
2061 return MZ_ZIP_INVALID_PARAMETER;
2062
2063 return pZip->m_last_error;
2064 }
2065
2066 mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip)
2067 {
2068 return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR);
2069 }
2070
2071 mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip)
2072 {
2073 mz_zip_error prev_err;
2074
2075 if (!pZip)
2076 return MZ_ZIP_INVALID_PARAMETER;
2077
2078 prev_err = pZip->m_last_error;
2079
2080 pZip->m_last_error = MZ_ZIP_NO_ERROR;
2081 return prev_err;
2082 }
2083
2084 const char *mz_zip_get_error_string(mz_zip_error mz_err)
2085 {
2086 switch (mz_err)
2087 {
2088 case MZ_ZIP_NO_ERROR:
2089 return "no error";
2090 case MZ_ZIP_UNDEFINED_ERROR:
2091 return "undefined error";
2092 case MZ_ZIP_TOO_MANY_FILES:
2093 return "too many files";
2094 case MZ_ZIP_FILE_TOO_LARGE:
2095 return "file too large";
2096 case MZ_ZIP_UNSUPPORTED_METHOD:
2097 return "unsupported method";
2098 case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
2099 return "unsupported encryption";
2100 case MZ_ZIP_UNSUPPORTED_FEATURE:
2101 return "unsupported feature";
2102 case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
2103 return "failed finding central directory";
2104 case MZ_ZIP_NOT_AN_ARCHIVE:
2105 return "not a ZIP archive";
2106 case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
2107 return "invalid header or archive is corrupted";
2108 case MZ_ZIP_UNSUPPORTED_MULTIDISK:
2109 return "unsupported multidisk archive";
2110 case MZ_ZIP_DECOMPRESSION_FAILED:
2111 return "decompression failed or archive is corrupted";
2112 case MZ_ZIP_COMPRESSION_FAILED:
2113 return "compression failed";
2114 case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
2115 return "unexpected decompressed size";
2116 case MZ_ZIP_CRC_CHECK_FAILED:
2117 return "CRC-32 check failed";
2118 case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
2119 return "unsupported central directory size";
2120 case MZ_ZIP_ALLOC_FAILED:
2121 return "allocation failed";
2122 case MZ_ZIP_FILE_OPEN_FAILED:
2123 return "file open failed";
2124 case MZ_ZIP_FILE_CREATE_FAILED:
2125 return "file create failed";
2126 case MZ_ZIP_FILE_WRITE_FAILED:
2127 return "file write failed";
2128 case MZ_ZIP_FILE_READ_FAILED:
2129 return "file read failed";
2130 case MZ_ZIP_FILE_CLOSE_FAILED:
2131 return "file close failed";
2132 case MZ_ZIP_FILE_SEEK_FAILED:
2133 return "file seek failed";
2134 case MZ_ZIP_FILE_STAT_FAILED:
2135 return "file stat failed";
2136 case MZ_ZIP_INVALID_PARAMETER:
2137 return "invalid parameter";
2138 case MZ_ZIP_INVALID_FILENAME:
2139 return "invalid filename";
2140 case MZ_ZIP_BUF_TOO_SMALL:
2141 return "buffer too small";
2142 case MZ_ZIP_INTERNAL_ERROR:
2143 return "internal error";
2144 case MZ_ZIP_FILE_NOT_FOUND:
2145 return "file not found";
2146 case MZ_ZIP_ARCHIVE_TOO_LARGE:
2147 return "archive is too large";
2148 case MZ_ZIP_VALIDATION_FAILED:
2149 return "validation failed";
2150 case MZ_ZIP_WRITE_CALLBACK_FAILED:
2151 return "write calledback failed";
2152 default:
2153 break;
2154 }
2155
2156 return "unknown error";
2157 }
2158
2159 /* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */
2160 mz_bool mz_zip_is_zip64(mz_zip_archive *pZip)
2161 {
2162 if ((!pZip) || (!pZip->m_pState))
2163 return MZ_FALSE;
2164
2165 return pZip->m_pState->m_zip64;
2166 }
2167
2168 size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip)
2169 {
2170 if ((!pZip) || (!pZip->m_pState))
2171 return 0;
2172
2173 return pZip->m_pState->m_central_dir.m_size;
2174 }
2175
2176 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
2177 {
2178 return pZip ? pZip->m_total_files : 0;
2179 }
2180
2181 mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip)
2182 {
2183 if (!pZip)
2184 return 0;
2185 return pZip->m_archive_size;
2186 }
2187
2188 MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip)
2189 {
2190 if ((!pZip) || (!pZip->m_pState))
2191 return 0;
2192 return pZip->m_pState->m_pFile;
2193 }
2194
2195 size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
2196 {
2197 if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
2198 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
2199
2200 return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
2201 }
2202
2203 mz_bool mz_zip_end(mz_zip_archive *pZip)
2204 {
2205 if (!pZip)
2206 return MZ_FALSE;
2207
2208 if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
2209 return mz_zip_reader_end(pZip);
2210
2211 return MZ_FALSE;
2212 }
2213
2214 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
2215 {
2216 mz_uint n;
2217 const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
2218 if (!p)
2219 {
2220 if (filename_buf_size)
2221 pFilename[0] = '\0';
2222 mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
2223 return 0;
2224 }
2225 n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
2226 if (filename_buf_size)
2227 {
2228 n = MZ_MIN(n, filename_buf_size - 1);
2229 memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
2230 pFilename[n] = '\0';
2231 }
2232 return n + 1;
2233 }
2234 #endif
2235
mz_zip_reader_file_stat(mz_zip_archive * pZip,mz_uint file_index,mz_zip_archive_file_stat * pStat)2236 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
2237 {
2238 return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
2239 }
2240
2241 #ifdef __cplusplus
2242 }
2243 #endif
2244
2245 #endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/
2246