Coverage Report

Created: 2025-11-13 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/miniz/build/amalgamation/miniz.c
Line
Count
Source
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
30
typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
31
typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
32
typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
33
34
#ifdef __cplusplus
35
extern "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
189M
    {
43
189M
        mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
44
189M
        size_t block_len = buf_len % 5552;
45
189M
        if (!ptr)
46
105
            return MZ_ADLER32_INIT;
47
378M
        while (buf_len)
48
189M
        {
49
323M
            for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
50
134M
            {
51
134M
                s1 += ptr[0], s2 += s1;
52
134M
                s1 += ptr[1], s2 += s1;
53
134M
                s1 += ptr[2], s2 += s1;
54
134M
                s1 += ptr[3], s2 += s1;
55
134M
                s1 += ptr[4], s2 += s1;
56
134M
                s1 += ptr[5], s2 += s1;
57
134M
                s1 += ptr[6], s2 += s1;
58
134M
                s1 += ptr[7], s2 += s1;
59
134M
            }
60
378M
            for (; i < block_len; ++i)
61
189M
                s1 += *ptr++, s2 += s1;
62
189M
            s1 %= 65521U, s2 %= 65521U;
63
189M
            buf_len -= block_len;
64
189M
            block_len = 5552;
65
189M
        }
66
189M
        return (s2 << 16) + s1;
67
189M
    }
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
 */
92
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len);
93
#else
94
/* Faster, but larger CPU cache footprint.
95
 */
96
mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
97
11.1k
{
98
11.1k
    static const mz_uint32 s_crc_table[256] = {
99
11.1k
        0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
100
11.1k
        0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
101
11.1k
        0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
102
11.1k
        0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
103
11.1k
        0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
104
11.1k
        0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
105
11.1k
        0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
106
11.1k
        0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
107
11.1k
        0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
108
11.1k
        0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
109
11.1k
        0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
110
11.1k
        0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
111
11.1k
        0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
112
11.1k
        0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
113
11.1k
        0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
114
11.1k
        0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
115
11.1k
        0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
116
11.1k
        0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
117
11.1k
        0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
118
11.1k
        0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
119
11.1k
        0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
120
11.1k
        0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
121
11.1k
        0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
122
11.1k
        0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
123
11.1k
        0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
124
11.1k
        0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
125
11.1k
        0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
126
11.1k
        0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
127
11.1k
        0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
128
11.1k
        0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
129
11.1k
        0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
130
11.1k
        0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
131
11.1k
        0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
132
11.1k
        0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
133
11.1k
        0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
134
11.1k
        0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
135
11.1k
        0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
136
11.1k
    };
137
138
11.1k
    mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
139
11.1k
    const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
140
141
95.1M
    while (buf_len >= 4)
142
95.1M
    {
143
95.1M
        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
144
95.1M
        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
145
95.1M
        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
146
95.1M
        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
147
95.1M
        pByte_buf += 4;
148
95.1M
        buf_len -= 4;
149
95.1M
    }
150
151
24.1k
    while (buf_len)
152
12.9k
    {
153
12.9k
        crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
154
12.9k
        ++pByte_buf;
155
12.9k
        --buf_len;
156
12.9k
    }
157
158
11.1k
    return ~crc32;
159
11.1k
}
160
#endif
161
162
    void mz_free(void *p)
163
0
    {
164
0
        MZ_FREE(p);
165
0
    }
166
167
    MINIZ_EXPORT void *miniz_def_alloc_func(void *opaque, size_t items, size_t size)
168
59.3k
    {
169
59.3k
        (void)opaque, (void)items, (void)size;
170
59.3k
        return MZ_MALLOC(items * size);
171
59.3k
    }
172
    MINIZ_EXPORT void miniz_def_free_func(void *opaque, void *address)
173
116k
    {
174
116k
        (void)opaque, (void)address;
175
116k
        MZ_FREE(address);
176
116k
    }
177
    MINIZ_EXPORT void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
178
45.5k
    {
179
45.5k
        (void)opaque, (void)address, (void)items, (void)size;
180
45.5k
        return MZ_REALLOC(address, items * size);
181
45.5k
    }
182
183
    const char *mz_version(void)
184
2.90k
    {
185
2.90k
        return MZ_VERSION;
186
2.90k
    }
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
14.1k
    {
194
14.1k
        return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
195
14.1k
    }
196
197
    int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
198
14.1k
    {
199
14.1k
        tdefl_compressor *pComp;
200
14.1k
        mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
201
202
14.1k
        if (!pStream)
203
0
            return MZ_STREAM_ERROR;
204
14.1k
        if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
205
0
            return MZ_PARAM_ERROR;
206
207
14.1k
        pStream->data_type = 0;
208
14.1k
        pStream->adler = MZ_ADLER32_INIT;
209
14.1k
        pStream->msg = NULL;
210
14.1k
        pStream->reserved = 0;
211
14.1k
        pStream->total_in = 0;
212
14.1k
        pStream->total_out = 0;
213
14.1k
        if (!pStream->zalloc)
214
14.1k
            pStream->zalloc = miniz_def_alloc_func;
215
14.1k
        if (!pStream->zfree)
216
14.1k
            pStream->zfree = miniz_def_free_func;
217
218
14.1k
        pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
219
14.1k
        if (!pComp)
220
0
            return MZ_MEM_ERROR;
221
222
14.1k
        pStream->state = (struct mz_internal_state *)pComp;
223
224
14.1k
        if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
225
0
        {
226
0
            mz_deflateEnd(pStream);
227
0
            return MZ_PARAM_ERROR;
228
0
        }
229
230
14.1k
        return MZ_OK;
231
14.1k
    }
232
233
    int mz_deflateReset(mz_streamp pStream)
234
0
    {
235
0
        if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
236
0
            return MZ_STREAM_ERROR;
237
0
        pStream->total_in = pStream->total_out = 0;
238
0
        tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);
239
0
        return MZ_OK;
240
0
    }
241
242
    int mz_deflate(mz_streamp pStream, int flush)
243
325M
    {
244
325M
        size_t in_bytes, out_bytes;
245
325M
        mz_ulong orig_total_in, orig_total_out;
246
325M
        int mz_status = MZ_OK;
247
248
325M
        if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
249
0
            return MZ_STREAM_ERROR;
250
325M
        if (!pStream->avail_out)
251
0
            return MZ_BUF_ERROR;
252
253
325M
        if (flush == MZ_PARTIAL_FLUSH)
254
0
            flush = MZ_SYNC_FLUSH;
255
256
325M
        if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
257
0
            return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
258
259
325M
        orig_total_in = pStream->total_in;
260
325M
        orig_total_out = pStream->total_out;
261
325M
        for (;;)
262
325M
        {
263
325M
            tdefl_status defl_status;
264
325M
            in_bytes = pStream->avail_in;
265
325M
            out_bytes = pStream->avail_out;
266
267
325M
            defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
268
325M
            pStream->next_in += (mz_uint)in_bytes;
269
325M
            pStream->avail_in -= (mz_uint)in_bytes;
270
325M
            pStream->total_in += (mz_uint)in_bytes;
271
325M
            pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
272
273
325M
            pStream->next_out += (mz_uint)out_bytes;
274
325M
            pStream->avail_out -= (mz_uint)out_bytes;
275
325M
            pStream->total_out += (mz_uint)out_bytes;
276
277
325M
            if (defl_status < 0)
278
0
            {
279
0
                mz_status = MZ_STREAM_ERROR;
280
0
                break;
281
0
            }
282
325M
            else if (defl_status == TDEFL_STATUS_DONE)
283
14.1k
            {
284
14.1k
                mz_status = MZ_STREAM_END;
285
14.1k
                break;
286
14.1k
            }
287
325M
            else if (!pStream->avail_out)
288
136M
                break;
289
189M
            else if ((!pStream->avail_in) && (flush != MZ_FINISH))
290
189M
            {
291
189M
                if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
292
189M
                    break;
293
537
                return MZ_BUF_ERROR; /* Can't make forward progress without some input.
294
                                      */
295
189M
            }
296
325M
        }
297
325M
        return mz_status;
298
325M
    }
299
300
    int mz_deflateEnd(mz_streamp pStream)
301
14.1k
    {
302
14.1k
        if (!pStream)
303
0
            return MZ_STREAM_ERROR;
304
14.1k
        if (pStream->state)
305
14.1k
        {
306
14.1k
            pStream->zfree(pStream->opaque, pStream->state);
307
14.1k
            pStream->state = NULL;
308
14.1k
        }
309
14.1k
        return MZ_OK;
310
14.1k
    }
311
312
    mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
313
5.98k
    {
314
5.98k
        (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
5.98k
        return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
317
5.98k
    }
318
319
    int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
320
10.2k
    {
321
10.2k
        int status;
322
10.2k
        mz_stream stream;
323
10.2k
        memset(&stream, 0, sizeof(stream));
324
325
        /* In case mz_ulong is 64-bits (argh I hate longs). */
326
10.2k
        if ((mz_uint64)(source_len | *pDest_len) > 0xFFFFFFFFU)
327
0
            return MZ_PARAM_ERROR;
328
329
10.2k
        stream.next_in = pSource;
330
10.2k
        stream.avail_in = (mz_uint32)source_len;
331
10.2k
        stream.next_out = pDest;
332
10.2k
        stream.avail_out = (mz_uint32)*pDest_len;
333
334
10.2k
        status = mz_deflateInit(&stream, level);
335
10.2k
        if (status != MZ_OK)
336
0
            return status;
337
338
10.2k
        status = mz_deflate(&stream, MZ_FINISH);
339
10.2k
        if (status != MZ_STREAM_END)
340
0
        {
341
0
            mz_deflateEnd(&stream);
342
0
            return (status == MZ_OK) ? MZ_BUF_ERROR : status;
343
0
        }
344
345
10.2k
        *pDest_len = stream.total_out;
346
10.2k
        return mz_deflateEnd(&stream);
347
10.2k
    }
348
349
    int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
350
0
    {
351
0
        return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
352
0
    }
353
354
    mz_ulong mz_compressBound(mz_ulong source_len)
355
5.98k
    {
356
5.98k
        return mz_deflateBound(NULL, source_len);
357
5.98k
    }
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
17.3k
    {
374
17.3k
        inflate_state *pDecomp;
375
17.3k
        if (!pStream)
376
0
            return MZ_STREAM_ERROR;
377
17.3k
        if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))
378
0
            return MZ_PARAM_ERROR;
379
380
17.3k
        pStream->data_type = 0;
381
17.3k
        pStream->adler = 0;
382
17.3k
        pStream->msg = NULL;
383
17.3k
        pStream->total_in = 0;
384
17.3k
        pStream->total_out = 0;
385
17.3k
        pStream->reserved = 0;
386
17.3k
        if (!pStream->zalloc)
387
17.3k
            pStream->zalloc = miniz_def_alloc_func;
388
17.3k
        if (!pStream->zfree)
389
17.3k
            pStream->zfree = miniz_def_free_func;
390
391
17.3k
        pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
392
17.3k
        if (!pDecomp)
393
0
            return MZ_MEM_ERROR;
394
395
17.3k
        pStream->state = (struct mz_internal_state *)pDecomp;
396
397
17.3k
        tinfl_init(&pDecomp->m_decomp);
398
17.3k
        pDecomp->m_dict_ofs = 0;
399
17.3k
        pDecomp->m_dict_avail = 0;
400
17.3k
        pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
401
17.3k
        pDecomp->m_first_call = 1;
402
17.3k
        pDecomp->m_has_flushed = 0;
403
17.3k
        pDecomp->m_window_bits = window_bits;
404
405
17.3k
        return MZ_OK;
406
17.3k
    }
407
408
    int mz_inflateInit(mz_streamp pStream)
409
17.3k
    {
410
17.3k
        return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
411
17.3k
    }
412
413
    int mz_inflateReset(mz_streamp pStream)
414
0
    {
415
0
        inflate_state *pDecomp;
416
0
        if (!pStream)
417
0
            return MZ_STREAM_ERROR;
418
419
0
        pStream->data_type = 0;
420
0
        pStream->adler = 0;
421
0
        pStream->msg = NULL;
422
0
        pStream->total_in = 0;
423
0
        pStream->total_out = 0;
424
0
        pStream->reserved = 0;
425
426
0
        pDecomp = (inflate_state *)pStream->state;
427
428
0
        tinfl_init(&pDecomp->m_decomp);
429
0
        pDecomp->m_dict_ofs = 0;
430
0
        pDecomp->m_dict_avail = 0;
431
0
        pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
432
0
        pDecomp->m_first_call = 1;
433
0
        pDecomp->m_has_flushed = 0;
434
0
        /* pDecomp->m_window_bits = window_bits */;
435
436
0
        return MZ_OK;
437
0
    }
438
439
    int mz_inflate(mz_streamp pStream, int flush)
440
193M
    {
441
193M
        inflate_state *pState;
442
193M
        mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
443
193M
        size_t in_bytes, out_bytes, orig_avail_in;
444
193M
        tinfl_status status;
445
446
193M
        if ((!pStream) || (!pStream->state))
447
0
            return MZ_STREAM_ERROR;
448
193M
        if (flush == MZ_PARTIAL_FLUSH)
449
0
            flush = MZ_SYNC_FLUSH;
450
193M
        if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
451
0
            return MZ_STREAM_ERROR;
452
453
193M
        pState = (inflate_state *)pStream->state;
454
193M
        if (pState->m_window_bits > 0)
455
193M
            decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
456
193M
        orig_avail_in = pStream->avail_in;
457
458
193M
        first_call = pState->m_first_call;
459
193M
        pState->m_first_call = 0;
460
193M
        if (pState->m_last_status < 0)
461
0
            return MZ_DATA_ERROR;
462
463
193M
        if (pState->m_has_flushed && (flush != MZ_FINISH))
464
0
            return MZ_STREAM_ERROR;
465
193M
        pState->m_has_flushed |= (flush == MZ_FINISH);
466
467
193M
        if ((flush == MZ_FINISH) && (first_call))
468
15.0k
        {
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
15.0k
            decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
471
15.0k
            in_bytes = pStream->avail_in;
472
15.0k
            out_bytes = pStream->avail_out;
473
15.0k
            status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
474
15.0k
            pState->m_last_status = status;
475
15.0k
            pStream->next_in += (mz_uint)in_bytes;
476
15.0k
            pStream->avail_in -= (mz_uint)in_bytes;
477
15.0k
            pStream->total_in += (mz_uint)in_bytes;
478
15.0k
            pStream->adler = tinfl_get_adler32(&pState->m_decomp);
479
15.0k
            pStream->next_out += (mz_uint)out_bytes;
480
15.0k
            pStream->avail_out -= (mz_uint)out_bytes;
481
15.0k
            pStream->total_out += (mz_uint)out_bytes;
482
483
15.0k
            if (status < 0)
484
4.24k
                return MZ_DATA_ERROR;
485
10.8k
            else if (status != TINFL_STATUS_DONE)
486
564
            {
487
564
                pState->m_last_status = TINFL_STATUS_FAILED;
488
564
                return MZ_BUF_ERROR;
489
564
            }
490
10.2k
            return MZ_STREAM_END;
491
15.0k
        }
492
        /* flush != MZ_FINISH then we must assume there's more input. */
493
193M
        if (flush != MZ_FINISH)
494
193M
            decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
495
496
193M
        if (pState->m_dict_avail)
497
56.7M
        {
498
56.7M
            n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
499
56.7M
            memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
500
56.7M
            pStream->next_out += n;
501
56.7M
            pStream->avail_out -= n;
502
56.7M
            pStream->total_out += n;
503
56.7M
            pState->m_dict_avail -= n;
504
56.7M
            pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
505
56.7M
            return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
506
56.7M
        }
507
508
136M
        for (;;)
509
136M
        {
510
136M
            in_bytes = pStream->avail_in;
511
136M
            out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
512
513
136M
            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
136M
            pState->m_last_status = status;
515
516
136M
            pStream->next_in += (mz_uint)in_bytes;
517
136M
            pStream->avail_in -= (mz_uint)in_bytes;
518
136M
            pStream->total_in += (mz_uint)in_bytes;
519
136M
            pStream->adler = tinfl_get_adler32(&pState->m_decomp);
520
521
136M
            pState->m_dict_avail = (mz_uint)out_bytes;
522
523
136M
            n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
524
136M
            memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
525
136M
            pStream->next_out += n;
526
136M
            pStream->avail_out -= n;
527
136M
            pStream->total_out += n;
528
136M
            pState->m_dict_avail -= n;
529
136M
            pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
530
531
136M
            if (status < 0)
532
0
                return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */
533
136M
            else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
534
0
                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
136M
            else if (flush == MZ_FINISH)
536
0
            {
537
                /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */
538
0
                if (status == TINFL_STATUS_DONE)
539
0
                    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
0
                else if (!pStream->avail_out)
542
0
                    return MZ_BUF_ERROR;
543
0
            }
544
136M
            else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
545
136M
                break;
546
136M
        }
547
548
136M
        return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
549
136M
    }
550
551
    int mz_inflateEnd(mz_streamp pStream)
552
17.3k
    {
553
17.3k
        if (!pStream)
554
0
            return MZ_STREAM_ERROR;
555
17.3k
        if (pStream->state)
556
17.3k
        {
557
17.3k
            pStream->zfree(pStream->opaque, pStream->state);
558
17.3k
            pStream->state = NULL;
559
17.3k
        }
560
17.3k
        return MZ_OK;
561
17.3k
    }
562
    int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong *pSource_len)
563
15.0k
    {
564
15.0k
        mz_stream stream;
565
15.0k
        int status;
566
15.0k
        memset(&stream, 0, sizeof(stream));
567
568
        /* In case mz_ulong is 64-bits (argh I hate longs). */
569
15.0k
        if ((mz_uint64)(*pSource_len | *pDest_len) > 0xFFFFFFFFU)
570
0
            return MZ_PARAM_ERROR;
571
572
15.0k
        stream.next_in = pSource;
573
15.0k
        stream.avail_in = (mz_uint32)*pSource_len;
574
15.0k
        stream.next_out = pDest;
575
15.0k
        stream.avail_out = (mz_uint32)*pDest_len;
576
577
15.0k
        status = mz_inflateInit(&stream);
578
15.0k
        if (status != MZ_OK)
579
0
            return status;
580
581
15.0k
        status = mz_inflate(&stream, MZ_FINISH);
582
15.0k
        *pSource_len = *pSource_len - stream.avail_in;
583
15.0k
        if (status != MZ_STREAM_END)
584
4.80k
        {
585
4.80k
            mz_inflateEnd(&stream);
586
4.80k
            return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
587
4.80k
        }
588
10.2k
        *pDest_len = stream.total_out;
589
590
10.2k
        return mz_inflateEnd(&stream);
591
15.0k
    }
592
593
    int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
594
13.8k
    {
595
13.8k
        return mz_uncompress2(pDest, pDest_len, pSource, &source_len);
596
13.8k
    }
597
598
#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/
599
600
    const char *mz_error(int err)
601
0
    {
602
0
        static struct
603
0
        {
604
0
            int m_err;
605
0
            const char *m_pDesc;
606
0
        } s_error_descs[] = {
607
0
            { 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
0
        };
609
0
        mz_uint i;
610
0
        for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
611
0
            if (s_error_descs[i].m_err == err)
612
0
                return s_error_descs[i].m_pDesc;
613
0
        return NULL;
614
0
    }
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
679
extern "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
115k
    {
749
115k
        mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
750
115k
        tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
751
115k
        MZ_CLEAR_ARR(hist);
752
8.82M
        for (i = 0; i < num_syms; i++)
753
8.70M
        {
754
8.70M
            mz_uint freq = pSyms0[i].m_key;
755
8.70M
            hist[freq & 0xFF]++;
756
8.70M
            hist[256 + ((freq >> 8) & 0xFF)]++;
757
8.70M
        }
758
212k
        while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
759
96.2k
            total_passes--;
760
251k
        for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
761
135k
        {
762
135k
            const mz_uint32 *pHist = &hist[pass << 8];
763
135k
            mz_uint offsets[256], cur_ofs = 0;
764
34.7M
            for (i = 0; i < 256; i++)
765
34.6M
            {
766
34.6M
                offsets[i] = cur_ofs;
767
34.6M
                cur_ofs += pHist[i];
768
34.6M
            }
769
12.8M
            for (i = 0; i < num_syms; i++)
770
12.7M
                pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
771
135k
            {
772
135k
                tdefl_sym_freq *t = pCur_syms;
773
135k
                pCur_syms = pNew_syms;
774
135k
                pNew_syms = t;
775
135k
            }
776
135k
        }
777
115k
        return pCur_syms;
778
115k
    }
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
115k
    {
783
115k
        int root, leaf, next, avbl, used, dpth;
784
115k
        if (n == 0)
785
2.10k
            return;
786
113k
        else if (n == 1)
787
3.02k
        {
788
3.02k
            A[0].m_key = 1;
789
3.02k
            return;
790
3.02k
        }
791
110k
        A[0].m_key += A[1].m_key;
792
110k
        root = 0;
793
110k
        leaf = 2;
794
8.59M
        for (next = 1; next < n - 1; next++)
795
8.48M
        {
796
8.48M
            if (leaf >= n || A[root].m_key < A[leaf].m_key)
797
4.23M
            {
798
4.23M
                A[next].m_key = A[root].m_key;
799
4.23M
                A[root++].m_key = (mz_uint16)next;
800
4.23M
            }
801
4.25M
            else
802
4.25M
                A[next].m_key = A[leaf++].m_key;
803
8.48M
            if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key))
804
4.25M
            {
805
4.25M
                A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
806
4.25M
                A[root++].m_key = (mz_uint16)next;
807
4.25M
            }
808
4.23M
            else
809
4.23M
                A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
810
8.48M
        }
811
110k
        A[n - 2].m_key = 0;
812
8.59M
        for (next = n - 3; next >= 0; next--)
813
8.48M
            A[next].m_key = A[A[next].m_key].m_key + 1;
814
110k
        avbl = 1;
815
110k
        used = dpth = 0;
816
110k
        root = n - 2;
817
110k
        next = n - 1;
818
1.05M
        while (avbl > 0)
819
947k
        {
820
9.54M
            while (root >= 0 && (int)A[root].m_key == dpth)
821
8.59M
            {
822
8.59M
                used++;
823
8.59M
                root--;
824
8.59M
            }
825
9.65M
            while (avbl > used)
826
8.70M
            {
827
8.70M
                A[next--].m_key = (mz_uint16)(dpth);
828
8.70M
                avbl--;
829
8.70M
            }
830
947k
            avbl = 2 * used;
831
947k
            dpth++;
832
947k
            used = 0;
833
947k
        }
834
110k
    }
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
115k
    {
843
115k
        int i;
844
115k
        mz_uint32 total = 0;
845
115k
        if (code_list_len <= 1)
846
5.13k
            return;
847
2.30M
        for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
848
2.19M
            pNum_codes[max_code_size] += pNum_codes[i];
849
1.46M
        for (i = max_code_size; i > 0; i--)
850
1.35M
            total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
851
129k
        while (total != (1UL << max_code_size))
852
18.8k
        {
853
18.8k
            pNum_codes[max_code_size]--;
854
24.6k
            for (i = max_code_size - 1; i > 0; i--)
855
24.6k
                if (pNum_codes[i])
856
18.8k
                {
857
18.8k
                    pNum_codes[i]--;
858
18.8k
                    pNum_codes[i + 1] += 2;
859
18.8k
                    break;
860
18.8k
                }
861
18.8k
            total--;
862
18.8k
        }
863
110k
    }
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
128k
    {
867
128k
        int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
868
128k
        mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
869
128k
        MZ_CLEAR_ARR(num_codes);
870
128k
        if (static_table)
871
12.3k
        {
872
1.98M
            for (i = 0; i < table_len; i++)
873
1.97M
                num_codes[d->m_huff_code_sizes[table_num][i]]++;
874
12.3k
        }
875
115k
        else
876
115k
        {
877
115k
            tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
878
115k
            int num_used_syms = 0;
879
115k
            const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
880
13.2M
            for (i = 0; i < table_len; i++)
881
13.0M
                if (pSym_count[i])
882
8.70M
                {
883
8.70M
                    syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
884
8.70M
                    syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
885
8.70M
                }
886
887
115k
            pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
888
115k
            tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
889
890
8.82M
            for (i = 0; i < num_used_syms; i++)
891
8.70M
                num_codes[pSyms[i].m_key]++;
892
893
115k
            tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
894
895
115k
            MZ_CLEAR_ARR(d->m_huff_code_sizes[table_num]);
896
115k
            MZ_CLEAR_ARR(d->m_huff_codes[table_num]);
897
1.54M
            for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
898
10.1M
                for (l = num_codes[i]; l > 0; l--)
899
8.70M
                    d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
900
115k
        }
901
902
128k
        next_code[1] = 0;
903
1.61M
        for (j = 0, i = 2; i <= code_size_limit; i++)
904
1.48M
            next_code[i] = j = ((j + num_codes[i - 1]) << 1);
905
906
15.1M
        for (i = 0; i < table_len; i++)
907
15.0M
        {
908
15.0M
            mz_uint rev_code = 0, code, code_size;
909
15.0M
            if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
910
4.37M
                continue;
911
10.6M
            code = next_code[code_size]++;
912
95.6M
            for (l = code_size; l > 0; l--, code >>= 1)
913
84.9M
                rev_code = (rev_code << 1) | (code & 1);
914
10.6M
            d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
915
10.6M
        }
916
128k
    }
917
918
#define TDEFL_PUT_BITS(b, l)                                       \
919
1.22G
    do                                                             \
920
1.22G
    {                                                              \
921
1.22G
        mz_uint bits = b;                                          \
922
1.22G
        mz_uint len = l;                                           \
923
1.22G
        MZ_ASSERT(bits <= ((1U << len) - 1U));                     \
924
1.22G
        d->m_bit_buffer |= (bits << d->m_bits_in);                 \
925
1.22G
        d->m_bits_in += len;                                       \
926
2.34G
        while (d->m_bits_in >= 8)                                  \
927
1.22G
        {                                                          \
928
1.12G
            if (d->m_pOutput_buf < d->m_pOutput_buf_end)           \
929
1.12G
                *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
930
1.12G
            d->m_bit_buffer >>= 8;                                 \
931
1.12G
            d->m_bits_in -= 8;                                     \
932
1.12G
        }                                                          \
933
1.22G
    }                                                              \
934
1.22G
    MZ_MACRO_END
935
936
#define TDEFL_RLE_PREV_CODE_SIZE()                                                                                       \
937
6.82M
    {                                                                                                                    \
938
6.82M
        if (rle_repeat_count)                                                                                            \
939
6.82M
        {                                                                                                                \
940
1.21M
            if (rle_repeat_count < 3)                                                                                    \
941
1.21M
            {                                                                                                            \
942
390k
                d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
943
906k
                while (rle_repeat_count--)                                                                               \
944
516k
                    packed_code_sizes[num_packed_code_sizes++] = prev_code_size;                                         \
945
390k
            }                                                                                                            \
946
1.21M
            else                                                                                                         \
947
1.21M
            {                                                                                                            \
948
820k
                d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1);                                        \
949
820k
                packed_code_sizes[num_packed_code_sizes++] = 16;                                                         \
950
820k
                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3);                           \
951
820k
            }                                                                                                            \
952
1.21M
            rle_repeat_count = 0;                                                                                        \
953
1.21M
        }                                                                                                                \
954
6.82M
    }
955
956
#define TDEFL_RLE_ZERO_CODE_SIZE()                                                         \
957
8.30M
    {                                                                                      \
958
8.30M
        if (rle_z_count)                                                                   \
959
8.30M
        {                                                                                  \
960
844k
            if (rle_z_count < 3)                                                           \
961
844k
            {                                                                              \
962
671k
                d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count);  \
963
1.41M
                while (rle_z_count--)                                                      \
964
740k
                    packed_code_sizes[num_packed_code_sizes++] = 0;                        \
965
671k
            }                                                                              \
966
844k
            else if (rle_z_count <= 10)                                                    \
967
173k
            {                                                                              \
968
119k
                d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1);          \
969
119k
                packed_code_sizes[num_packed_code_sizes++] = 17;                           \
970
119k
                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3);  \
971
119k
            }                                                                              \
972
173k
            else                                                                           \
973
173k
            {                                                                              \
974
54.1k
                d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1);          \
975
54.1k
                packed_code_sizes[num_packed_code_sizes++] = 18;                           \
976
54.1k
                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
977
54.1k
            }                                                                              \
978
844k
            rle_z_count = 0;                                                               \
979
844k
        }                                                                                  \
980
8.30M
    }
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
38.6k
    {
986
38.6k
        int num_lit_codes, num_dist_codes, num_bit_lengths;
987
38.6k
        mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
988
38.6k
        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
38.6k
        d->m_huff_count[0][256] = 1;
991
992
38.6k
        tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
993
38.6k
        tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
994
995
597k
        for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
996
595k
            if (d->m_huff_code_sizes[0][num_lit_codes - 1])
997
36.4k
                break;
998
374k
        for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
999
370k
            if (d->m_huff_code_sizes[1][num_dist_codes - 1])
1000
34.8k
                break;
1001
1002
38.6k
        memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
1003
38.6k
        memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
1004
38.6k
        total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
1005
38.6k
        num_packed_code_sizes = 0;
1006
38.6k
        rle_z_count = 0;
1007
38.6k
        rle_repeat_count = 0;
1008
1009
38.6k
        memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
1010
11.3M
        for (i = 0; i < total_code_sizes_to_pack; i++)
1011
11.3M
        {
1012
11.3M
            mz_uint8 code_size = code_sizes_to_pack[i];
1013
11.3M
            if (!code_size)
1014
3.02M
            {
1015
3.02M
                TDEFL_RLE_PREV_CODE_SIZE();
1016
3.02M
                if (++rle_z_count == 138)
1017
1.69k
                {
1018
1.69k
                    TDEFL_RLE_ZERO_CODE_SIZE();
1019
1.69k
                }
1020
3.02M
            }
1021
8.27M
            else
1022
8.27M
            {
1023
8.27M
                TDEFL_RLE_ZERO_CODE_SIZE();
1024
8.27M
                if (code_size != prev_code_size)
1025
3.08M
                {
1026
3.08M
                    TDEFL_RLE_PREV_CODE_SIZE();
1027
3.08M
                    d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1);
1028
3.08M
                    packed_code_sizes[num_packed_code_sizes++] = code_size;
1029
3.08M
                }
1030
5.19M
                else if (++rle_repeat_count == 6)
1031
709k
                {
1032
709k
                    TDEFL_RLE_PREV_CODE_SIZE();
1033
709k
                }
1034
8.27M
            }
1035
11.3M
            prev_code_size = code_size;
1036
11.3M
        }
1037
38.6k
        if (rle_repeat_count)
1038
9.21k
        {
1039
9.21k
            TDEFL_RLE_PREV_CODE_SIZE();
1040
9.21k
        }
1041
29.3k
        else
1042
29.3k
        {
1043
29.3k
            TDEFL_RLE_ZERO_CODE_SIZE();
1044
29.3k
        }
1045
1046
38.6k
        tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
1047
1048
38.6k
        TDEFL_PUT_BITS(2, 2);
1049
1050
38.6k
        TDEFL_PUT_BITS(num_lit_codes - 257, 5);
1051
38.6k
        TDEFL_PUT_BITS(num_dist_codes - 1, 5);
1052
1053
119k
        for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
1054
119k
            if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
1055
38.6k
                break;
1056
38.6k
        num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
1057
38.6k
        TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
1058
690k
        for (i = 0; (int)i < num_bit_lengths; i++)
1059
652k
            TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
1060
1061
5.37M
        for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;)
1062
5.33M
        {
1063
5.33M
            mz_uint code = packed_code_sizes[packed_code_sizes_index++];
1064
5.33M
            MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
1065
5.33M
            TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
1066
5.33M
            if (code >= 16)
1067
993k
                TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
1068
5.33M
        }
1069
38.6k
    }
1070
1071
    static void tdefl_start_static_block(tdefl_compressor *d)
1072
6.17k
    {
1073
6.17k
        mz_uint i;
1074
6.17k
        mz_uint8 *p = &d->m_huff_code_sizes[0][0];
1075
1076
895k
        for (i = 0; i <= 143; ++i)
1077
889k
            *p++ = 8;
1078
698k
        for (; i <= 255; ++i)
1079
691k
            *p++ = 9;
1080
154k
        for (; i <= 279; ++i)
1081
148k
            *p++ = 7;
1082
55.6k
        for (; i <= 287; ++i)
1083
49.4k
            *p++ = 8;
1084
1085
6.17k
        memset(d->m_huff_code_sizes[1], 5, 32);
1086
1087
6.17k
        tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
1088
6.17k
        tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
1089
1090
6.17k
        TDEFL_PUT_BITS(1, 2);
1091
6.17k
    }
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
1191
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
1192
44.7k
{
1193
44.7k
    mz_uint flags;
1194
44.7k
    mz_uint8 *pLZ_codes;
1195
1196
44.7k
    flags = 1;
1197
955M
    for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
1198
955M
    {
1199
955M
        if (flags == 1)
1200
119M
            flags = *pLZ_codes++ | 0x100;
1201
955M
        if (flags & 1)
1202
13.8M
        {
1203
13.8M
            mz_uint sym, num_extra_bits;
1204
13.8M
            mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
1205
13.8M
            pLZ_codes += 3;
1206
1207
13.8M
            MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1208
13.8M
            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
13.8M
            TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1210
1211
13.8M
            if (match_dist < 512)
1212
6.77M
            {
1213
6.77M
                sym = s_tdefl_small_dist_sym[match_dist];
1214
6.77M
                num_extra_bits = s_tdefl_small_dist_extra[match_dist];
1215
6.77M
            }
1216
7.09M
            else
1217
7.09M
            {
1218
7.09M
                sym = s_tdefl_large_dist_sym[match_dist >> 8];
1219
7.09M
                num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
1220
7.09M
            }
1221
13.8M
            MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1222
13.8M
            TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1223
13.8M
            TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1224
13.8M
        }
1225
942M
        else
1226
942M
        {
1227
942M
            mz_uint lit = *pLZ_codes++;
1228
942M
            MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1229
942M
            TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1230
942M
        }
1231
955M
    }
1232
1233
44.7k
    TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1234
1235
44.7k
    return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1236
44.7k
}
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
44.7k
    {
1241
44.7k
        if (static_block)
1242
6.17k
            tdefl_start_static_block(d);
1243
38.6k
        else
1244
38.6k
            tdefl_start_dynamic_block(d);
1245
44.7k
        return tdefl_compress_lz_codes(d);
1246
44.7k
    }
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
44.7k
    {
1252
44.7k
        mz_uint saved_bit_buf, saved_bits_in;
1253
44.7k
        mz_uint8 *pSaved_output_buf;
1254
44.7k
        mz_bool comp_block_succeeded = MZ_FALSE;
1255
44.7k
        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
44.7k
        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
44.7k
        d->m_pOutput_buf = pOutput_buf_start;
1259
44.7k
        d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
1260
1261
44.7k
        MZ_ASSERT(!d->m_output_flush_remaining);
1262
44.7k
        d->m_output_flush_ofs = 0;
1263
44.7k
        d->m_output_flush_remaining = 0;
1264
1265
44.7k
        *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
1266
44.7k
        d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
1267
1268
44.7k
        if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
1269
14.1k
        {
1270
14.1k
            const mz_uint8 cmf = 0x78;
1271
14.1k
            mz_uint8 flg, flevel = 3;
1272
14.1k
            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
83.0k
            for (i = 0; i < mz_un; i++)
1276
83.0k
                if (s_tdefl_num_probes[i] == (d->m_flags & 0xFFF))
1277
14.1k
                    break;
1278
1279
14.1k
            if (i < 2)
1280
2.56k
                flevel = 0;
1281
11.6k
            else if (i < 6)
1282
2.56k
                flevel = 1;
1283
9.07k
            else if (i == 6)
1284
5.98k
                flevel = 2;
1285
1286
14.1k
            header = cmf << 8 | (flevel << 6);
1287
14.1k
            header += 31 - (header % 31);
1288
14.1k
            flg = header & 0xFF;
1289
1290
14.1k
            TDEFL_PUT_BITS(cmf, 8);
1291
14.1k
            TDEFL_PUT_BITS(flg, 8);
1292
14.1k
        }
1293
1294
44.7k
        TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
1295
1296
44.7k
        pSaved_output_buf = d->m_pOutput_buf;
1297
44.7k
        saved_bit_buf = d->m_bit_buffer;
1298
44.7k
        saved_bits_in = d->m_bits_in;
1299
1300
44.7k
        if (!use_raw_block)
1301
44.7k
            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
44.7k
        if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
1305
13.8k
            ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size))
1306
13.8k
        {
1307
13.8k
            mz_uint i;
1308
13.8k
            d->m_pOutput_buf = pSaved_output_buf;
1309
13.8k
            d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1310
13.8k
            TDEFL_PUT_BITS(0, 2);
1311
13.8k
            if (d->m_bits_in)
1312
13.5k
            {
1313
13.5k
                TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1314
13.5k
            }
1315
41.6k
            for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
1316
27.7k
            {
1317
27.7k
                TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
1318
27.7k
            }
1319
218M
            for (i = 0; i < d->m_total_lz_bytes; ++i)
1320
218M
            {
1321
218M
                TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
1322
218M
            }
1323
13.8k
        }
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
30.8k
        else if (!comp_block_succeeded)
1326
0
        {
1327
0
            d->m_pOutput_buf = pSaved_output_buf;
1328
0
            d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1329
0
            tdefl_compress_block(d, MZ_TRUE);
1330
0
        }
1331
1332
44.7k
        if (flush)
1333
18.8k
        {
1334
18.8k
            if (flush == TDEFL_FINISH)
1335
17.1k
            {
1336
17.1k
                if (d->m_bits_in)
1337
10.1k
                {
1338
10.1k
                    TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1339
10.1k
                }
1340
17.1k
                if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER)
1341
14.1k
                {
1342
14.1k
                    mz_uint i, a = d->m_adler32;
1343
70.9k
                    for (i = 0; i < 4; i++)
1344
56.7k
                    {
1345
56.7k
                        TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
1346
56.7k
                        a <<= 8;
1347
56.7k
                    }
1348
14.1k
                }
1349
17.1k
            }
1350
1.64k
            else
1351
1.64k
            {
1352
1.64k
                mz_uint i, z = 0;
1353
1.64k
                TDEFL_PUT_BITS(0, 3);
1354
1.64k
                if (d->m_bits_in)
1355
1.64k
                {
1356
1.64k
                    TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1357
1.64k
                }
1358
4.94k
                for (i = 2; i; --i, z ^= 0xFFFF)
1359
3.29k
                {
1360
3.29k
                    TDEFL_PUT_BITS(z & 0xFFFF, 16);
1361
3.29k
                }
1362
1.64k
            }
1363
18.8k
        }
1364
1365
44.7k
        MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
1366
1367
44.7k
        memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1368
44.7k
        memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1369
1370
44.7k
        d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1371
44.7k
        d->m_pLZ_flags = d->m_lz_code_buf;
1372
44.7k
        d->m_num_flags_left = 8;
1373
44.7k
        d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
1374
44.7k
        d->m_total_lz_bytes = 0;
1375
44.7k
        d->m_block_index++;
1376
1377
44.7k
        if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
1378
44.7k
        {
1379
44.7k
            if (d->m_pPut_buf_func)
1380
5.20k
            {
1381
5.20k
                *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1382
5.20k
                if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
1383
0
                    return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
1384
5.20k
            }
1385
39.5k
            else if (pOutput_buf_start == d->m_output_buf)
1386
17.2k
            {
1387
17.2k
                int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
1388
17.2k
                memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
1389
17.2k
                d->m_out_buf_ofs += bytes_to_copy;
1390
17.2k
                if ((n -= bytes_to_copy) != 0)
1391
5.93k
                {
1392
5.93k
                    d->m_output_flush_ofs = bytes_to_copy;
1393
5.93k
                    d->m_output_flush_remaining = n;
1394
5.93k
                }
1395
17.2k
            }
1396
22.3k
            else
1397
22.3k
            {
1398
22.3k
                d->m_out_buf_ofs += n;
1399
22.3k
            }
1400
44.7k
        }
1401
1402
44.7k
        return d->m_output_flush_remaining;
1403
44.7k
    }
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
1476
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)
1477
959M
{
1478
959M
    mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1479
959M
    mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1480
959M
    const mz_uint8 *s = d->m_dict + pos, *p, *q;
1481
959M
    mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
1482
959M
    MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1483
959M
    if (max_match_len <= match_len)
1484
27.5k
        return;
1485
959M
    for (;;)
1486
1.33G
    {
1487
1.33G
        for (;;)
1488
2.23G
        {
1489
2.23G
            if (--num_probes_left == 0)
1490
70.2M
                return;
1491
2.16G
#define TDEFL_PROBE                                                                               \
1492
4.72G
    next_probe_pos = d->m_next[probe_pos];                                                        \
1493
4.72G
    if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))   \
1494
4.72G
        return;                                                                                   \
1495
4.72G
    probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                                         \
1496
3.84G
    if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \
1497
3.84G
        break;
1498
5.39G
            TDEFL_PROBE;
1499
5.39G
            TDEFL_PROBE;
1500
2.26G
            TDEFL_PROBE;
1501
1.81G
        }
1502
380M
        if (!dist)
1503
10.9k
            break;
1504
380M
        p = s;
1505
380M
        q = d->m_dict + probe_pos;
1506
961M
        for (probe_len = 0; probe_len < max_match_len; probe_len++)
1507
960M
            if (*p++ != *q++)
1508
379M
                break;
1509
380M
        if (probe_len > match_len)
1510
23.3M
        {
1511
23.3M
            *pMatch_dist = dist;
1512
23.3M
            if ((*pMatch_len = match_len = probe_len) == max_match_len)
1513
1.02M
                return;
1514
22.2M
            c0 = d->m_dict[pos + match_len];
1515
22.2M
            c1 = d->m_dict[pos + match_len - 1];
1516
22.2M
        }
1517
380M
    }
1518
959M
}
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
942M
    {
1708
942M
        d->m_total_lz_bytes++;
1709
942M
        *d->m_pLZ_code_buf++ = lit;
1710
942M
        *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
1711
942M
        if (--d->m_num_flags_left == 0)
1712
117M
        {
1713
117M
            d->m_num_flags_left = 8;
1714
117M
            d->m_pLZ_flags = d->m_pLZ_code_buf++;
1715
117M
        }
1716
942M
        d->m_huff_count[0][lit]++;
1717
942M
    }
1718
1719
    static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
1720
13.8M
    {
1721
13.8M
        mz_uint32 s0, s1;
1722
1723
13.8M
        MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
1724
1725
13.8M
        d->m_total_lz_bytes += match_len;
1726
1727
13.8M
        d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
1728
1729
13.8M
        match_dist -= 1;
1730
13.8M
        d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
1731
13.8M
        d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
1732
13.8M
        d->m_pLZ_code_buf += 3;
1733
1734
13.8M
        *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
1735
13.8M
        if (--d->m_num_flags_left == 0)
1736
1.73M
        {
1737
1.73M
            d->m_num_flags_left = 8;
1738
1.73M
            d->m_pLZ_flags = d->m_pLZ_code_buf++;
1739
1.73M
        }
1740
1741
13.8M
        s0 = s_tdefl_small_dist_sym[match_dist & 511];
1742
13.8M
        s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
1743
13.8M
        d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
1744
13.8M
        d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
1745
13.8M
    }
1746
1747
    static mz_bool tdefl_compress_normal(tdefl_compressor *d)
1748
189M
    {
1749
189M
        const mz_uint8 *pSrc = d->m_pSrc;
1750
189M
        size_t src_buf_left = d->m_src_buf_left;
1751
189M
        tdefl_flush flush = d->m_flush;
1752
1753
1.14G
        while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
1754
1.00G
        {
1755
1.00G
            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
1.00G
            if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
1758
1.00G
            {
1759
1.00G
                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
1.00G
                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
1.00G
                mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
1762
1.00G
                const mz_uint8 *pSrc_end = pSrc ? pSrc + num_bytes_to_process : NULL;
1763
1.00G
                src_buf_left -= num_bytes_to_process;
1764
1.00G
                d->m_lookahead_size += num_bytes_to_process;
1765
2.35G
                while (pSrc != pSrc_end)
1766
1.35G
                {
1767
1.35G
                    mz_uint8 c = *pSrc++;
1768
1.35G
                    d->m_dict[dst_pos] = c;
1769
1.35G
                    if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1770
10.0M
                        d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1771
1.35G
                    hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1772
1.35G
                    d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1773
1.35G
                    d->m_hash[hash] = (mz_uint16)(ins_pos);
1774
1.35G
                    dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1775
1.35G
                    ins_pos++;
1776
1.35G
                }
1777
1.00G
            }
1778
20.6k
            else
1779
20.6k
            {
1780
2.46M
                while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1781
2.44M
                {
1782
2.44M
                    mz_uint8 c = *pSrc++;
1783
2.44M
                    mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1784
2.44M
                    src_buf_left--;
1785
2.44M
                    d->m_dict[dst_pos] = c;
1786
2.44M
                    if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1787
2.43M
                        d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1788
2.44M
                    if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
1789
2.40M
                    {
1790
2.40M
                        mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
1791
2.40M
                        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
2.40M
                        d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1793
2.40M
                        d->m_hash[hash] = (mz_uint16)(ins_pos);
1794
2.40M
                    }
1795
2.44M
                }
1796
20.6k
            }
1797
1.00G
            d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
1798
1.00G
            if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1799
42.4M
                break;
1800
1801
            /* Simple lazy/greedy parsing state machine. */
1802
959M
            len_to_move = 1;
1803
959M
            cur_match_dist = 0;
1804
959M
            cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
1805
959M
            cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1806
959M
            if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
1807
0
            {
1808
0
                if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
1809
0
                {
1810
0
                    mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
1811
0
                    cur_match_len = 0;
1812
0
                    while (cur_match_len < d->m_lookahead_size)
1813
0
                    {
1814
0
                        if (d->m_dict[cur_pos + cur_match_len] != c)
1815
0
                            break;
1816
0
                        cur_match_len++;
1817
0
                    }
1818
0
                    if (cur_match_len < TDEFL_MIN_MATCH_LEN)
1819
0
                        cur_match_len = 0;
1820
0
                    else
1821
0
                        cur_match_dist = 1;
1822
0
                }
1823
0
            }
1824
959M
            else
1825
959M
            {
1826
959M
                tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
1827
959M
            }
1828
959M
            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
2.34M
            {
1830
2.34M
                cur_match_dist = cur_match_len = 0;
1831
2.34M
            }
1832
959M
            if (d->m_saved_match_len)
1833
4.47M
            {
1834
4.47M
                if (cur_match_len > d->m_saved_match_len)
1835
550k
                {
1836
550k
                    tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
1837
550k
                    if (cur_match_len >= 128)
1838
15.0k
                    {
1839
15.0k
                        tdefl_record_match(d, cur_match_len, cur_match_dist);
1840
15.0k
                        d->m_saved_match_len = 0;
1841
15.0k
                        len_to_move = cur_match_len;
1842
15.0k
                    }
1843
535k
                    else
1844
535k
                    {
1845
535k
                        d->m_saved_lit = d->m_dict[cur_pos];
1846
535k
                        d->m_saved_match_dist = cur_match_dist;
1847
535k
                        d->m_saved_match_len = cur_match_len;
1848
535k
                    }
1849
550k
                }
1850
3.92M
                else
1851
3.92M
                {
1852
3.92M
                    tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
1853
3.92M
                    len_to_move = d->m_saved_match_len - 1;
1854
3.92M
                    d->m_saved_match_len = 0;
1855
3.92M
                }
1856
4.47M
            }
1857
955M
            else if (!cur_match_dist)
1858
941M
                tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
1859
13.8M
            else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
1860
9.93M
            {
1861
9.93M
                tdefl_record_match(d, cur_match_len, cur_match_dist);
1862
9.93M
                len_to_move = cur_match_len;
1863
9.93M
            }
1864
3.93M
            else
1865
3.93M
            {
1866
3.93M
                d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
1867
3.93M
                d->m_saved_match_dist = cur_match_dist;
1868
3.93M
                d->m_saved_match_len = cur_match_len;
1869
3.93M
            }
1870
            /* Move the lookahead forward by len_to_move bytes. */
1871
959M
            d->m_lookahead_pos += len_to_move;
1872
959M
            MZ_ASSERT(d->m_lookahead_size >= len_to_move);
1873
959M
            d->m_lookahead_size -= len_to_move;
1874
959M
            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
959M
            if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
1877
959M
                ((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
25.9k
            {
1879
25.9k
                int n;
1880
25.9k
                d->m_pSrc = pSrc;
1881
25.9k
                d->m_src_buf_left = src_buf_left;
1882
25.9k
                if ((n = tdefl_flush_block(d, 0)) != 0)
1883
4.15k
                    return (n < 0) ? MZ_FALSE : MZ_TRUE;
1884
25.9k
            }
1885
959M
        }
1886
1887
189M
        d->m_pSrc = pSrc;
1888
189M
        d->m_src_buf_left = src_buf_left;
1889
189M
        return MZ_TRUE;
1890
189M
    }
1891
1892
    static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
1893
325M
    {
1894
325M
        if (d->m_pIn_buf_size)
1895
325M
        {
1896
325M
            *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1897
325M
        }
1898
1899
325M
        if (d->m_pOut_buf_size)
1900
325M
        {
1901
325M
            size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
1902
325M
            memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
1903
325M
            d->m_output_flush_ofs += (mz_uint)n;
1904
325M
            d->m_output_flush_remaining -= (mz_uint)n;
1905
325M
            d->m_out_buf_ofs += n;
1906
1907
325M
            *d->m_pOut_buf_size = d->m_out_buf_ofs;
1908
325M
        }
1909
1910
325M
        return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
1911
325M
    }
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
325M
    {
1915
325M
        if (!d)
1916
0
        {
1917
0
            if (pIn_buf_size)
1918
0
                *pIn_buf_size = 0;
1919
0
            if (pOut_buf_size)
1920
0
                *pOut_buf_size = 0;
1921
0
            return TDEFL_STATUS_BAD_PARAM;
1922
0
        }
1923
1924
325M
        d->m_pIn_buf = pIn_buf;
1925
325M
        d->m_pIn_buf_size = pIn_buf_size;
1926
325M
        d->m_pOut_buf = pOut_buf;
1927
325M
        d->m_pOut_buf_size = pOut_buf_size;
1928
325M
        d->m_pSrc = (const mz_uint8 *)(pIn_buf);
1929
325M
        d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
1930
325M
        d->m_out_buf_ofs = 0;
1931
325M
        d->m_flush = flush;
1932
1933
325M
        if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
1934
325M
            (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
0
        {
1936
0
            if (pIn_buf_size)
1937
0
                *pIn_buf_size = 0;
1938
0
            if (pOut_buf_size)
1939
0
                *pOut_buf_size = 0;
1940
0
            return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
1941
0
        }
1942
325M
        d->m_wants_to_finish |= (flush == TDEFL_FINISH);
1943
1944
325M
        if ((d->m_output_flush_remaining) || (d->m_finished))
1945
136M
            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
189M
        {
1958
189M
            if (!tdefl_compress_normal(d))
1959
0
                return d->m_prev_return_status;
1960
189M
        }
1961
1962
189M
        if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
1963
189M
            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
189M
        if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
1966
18.8k
        {
1967
18.8k
            if (tdefl_flush_block(d, flush) < 0)
1968
0
                return d->m_prev_return_status;
1969
18.8k
            d->m_finished = (flush == TDEFL_FINISH);
1970
18.8k
            if (flush == TDEFL_FULL_FLUSH)
1971
1.64k
            {
1972
1.64k
                MZ_CLEAR_ARR(d->m_hash);
1973
1.64k
                MZ_CLEAR_ARR(d->m_next);
1974
1.64k
                d->m_dict_size = 0;
1975
1.64k
            }
1976
18.8k
        }
1977
1978
189M
        return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1979
189M
    }
1980
1981
    tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
1982
2.99k
    {
1983
2.99k
        MZ_ASSERT(d->m_pPut_buf_func);
1984
2.99k
        return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
1985
2.99k
    }
1986
1987
    tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1988
17.1k
    {
1989
17.1k
        d->m_pPut_buf_func = pPut_buf_func;
1990
17.1k
        d->m_pPut_buf_user = pPut_buf_user;
1991
17.1k
        d->m_flags = (mz_uint)(flags);
1992
17.1k
        d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
1993
17.1k
        d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
1994
17.1k
        d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
1995
17.1k
        if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
1996
17.1k
            MZ_CLEAR_ARR(d->m_hash);
1997
17.1k
        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
17.1k
        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
17.1k
        d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
2000
17.1k
        d->m_pLZ_flags = d->m_lz_code_buf;
2001
17.1k
        *d->m_pLZ_flags = 0;
2002
17.1k
        d->m_num_flags_left = 8;
2003
17.1k
        d->m_pOutput_buf = d->m_output_buf;
2004
17.1k
        d->m_pOutput_buf_end = d->m_output_buf;
2005
17.1k
        d->m_prev_return_status = TDEFL_STATUS_OKAY;
2006
17.1k
        d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
2007
17.1k
        d->m_adler32 = 1;
2008
17.1k
        d->m_pIn_buf = NULL;
2009
17.1k
        d->m_pOut_buf = NULL;
2010
17.1k
        d->m_pIn_buf_size = NULL;
2011
17.1k
        d->m_pOut_buf_size = NULL;
2012
17.1k
        d->m_flush = TDEFL_NO_FLUSH;
2013
17.1k
        d->m_pSrc = NULL;
2014
17.1k
        d->m_src_buf_left = 0;
2015
17.1k
        d->m_out_buf_ofs = 0;
2016
17.1k
        if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
2017
17.1k
            MZ_CLEAR_ARR(d->m_dict);
2018
17.1k
        memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
2019
17.1k
        memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
2020
17.1k
        return TDEFL_STATUS_OKAY;
2021
17.1k
    }
2022
2023
    tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
2024
0
    {
2025
0
        return d->m_prev_return_status;
2026
0
    }
2027
2028
    mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
2029
325M
    {
2030
325M
        return d->m_adler32;
2031
325M
    }
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
0
    {
2035
0
        tdefl_compressor *pComp;
2036
0
        mz_bool succeeded;
2037
0
        if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
2038
0
            return MZ_FALSE;
2039
0
        pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2040
0
        if (!pComp)
2041
0
            return MZ_FALSE;
2042
0
        succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
2043
0
        succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
2044
0
        MZ_FREE(pComp);
2045
0
        return succeeded;
2046
0
    }
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
0
    {
2057
0
        tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
2058
0
        size_t new_size = p->m_size + len;
2059
0
        if (new_size > p->m_capacity)
2060
0
        {
2061
0
            size_t new_capacity = p->m_capacity;
2062
0
            mz_uint8 *pNew_buf;
2063
0
            if (!p->m_expandable)
2064
0
                return MZ_FALSE;
2065
0
            do
2066
0
            {
2067
0
                new_capacity = MZ_MAX(128U, new_capacity << 1U);
2068
0
            } while (new_size > new_capacity);
2069
0
            pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
2070
0
            if (!pNew_buf)
2071
0
                return MZ_FALSE;
2072
0
            p->m_pBuf = pNew_buf;
2073
0
            p->m_capacity = new_capacity;
2074
0
        }
2075
0
        memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
2076
0
        p->m_size = new_size;
2077
0
        return MZ_TRUE;
2078
0
    }
2079
2080
    void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2081
0
    {
2082
0
        tdefl_output_buffer out_buf;
2083
0
        MZ_CLEAR_OBJ(out_buf);
2084
0
        if (!pOut_len)
2085
0
            return MZ_FALSE;
2086
0
        else
2087
0
            *pOut_len = 0;
2088
0
        out_buf.m_expandable = MZ_TRUE;
2089
0
        if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2090
0
            return NULL;
2091
0
        *pOut_len = out_buf.m_size;
2092
0
        return out_buf.m_pBuf;
2093
0
    }
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
0
    {
2097
0
        tdefl_output_buffer out_buf;
2098
0
        MZ_CLEAR_OBJ(out_buf);
2099
0
        if (!pOut_buf)
2100
0
            return 0;
2101
0
        out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
2102
0
        out_buf.m_capacity = out_buf_len;
2103
0
        if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2104
0
            return 0;
2105
0
        return out_buf.m_size;
2106
0
    }
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
17.1k
    {
2111
17.1k
        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
17.1k
        if (window_bits > 0)
2113
14.1k
            comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
2114
2115
17.1k
        if (!level)
2116
0
            comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
2117
17.1k
        else if (strategy == MZ_FILTERED)
2118
0
            comp_flags |= TDEFL_FILTER_MATCHES;
2119
17.1k
        else if (strategy == MZ_HUFFMAN_ONLY)
2120
0
            comp_flags &= ~TDEFL_MAX_PROBES_MASK;
2121
17.1k
        else if (strategy == MZ_FIXED)
2122
0
            comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
2123
17.1k
        else if (strategy == MZ_RLE)
2124
0
            comp_flags |= TDEFL_RLE_MATCHES;
2125
2126
17.1k
        return comp_flags;
2127
17.1k
    }
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
0
    {
2139
        /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */
2140
0
        static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2141
0
        tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2142
0
        tdefl_output_buffer out_buf;
2143
0
        int i, bpl = w * num_chans, y, z;
2144
0
        mz_uint32 c;
2145
0
        *pLen_out = 0;
2146
0
        if (!pComp)
2147
0
            return NULL;
2148
0
        MZ_CLEAR_OBJ(out_buf);
2149
0
        out_buf.m_expandable = MZ_TRUE;
2150
0
        out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
2151
0
        if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity)))
2152
0
        {
2153
0
            MZ_FREE(pComp);
2154
0
            return NULL;
2155
0
        }
2156
        /* write dummy header */
2157
0
        for (z = 41; z; --z)
2158
0
            tdefl_output_buffer_putter(&z, 1, &out_buf);
2159
        /* compress image data */
2160
0
        tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
2161
0
        for (y = 0; y < h; ++y)
2162
0
        {
2163
0
            tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
2164
0
            tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH);
2165
0
        }
2166
0
        if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE)
2167
0
        {
2168
0
            MZ_FREE(pComp);
2169
0
            MZ_FREE(out_buf.m_pBuf);
2170
0
            return NULL;
2171
0
        }
2172
        /* write real header */
2173
0
        *pLen_out = out_buf.m_size - 41;
2174
0
        {
2175
0
            static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 };
2176
0
            mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d,
2177
0
                                    0x0a, 0x1a, 0x0a, 0x00, 0x00,
2178
0
                                    0x00, 0x0d, 0x49, 0x48, 0x44,
2179
0
                                    0x52, 0x00, 0x00, 0x00, 0x00,
2180
0
                                    0x00, 0x00, 0x00, 0x00, 0x08,
2181
0
                                    0x00, 0x00, 0x00, 0x00, 0x00,
2182
0
                                    0x00, 0x00, 0x00, 0x00, 0x00,
2183
0
                                    0x00, 0x00, 0x49, 0x44, 0x41,
2184
0
                                    0x54 };
2185
0
            pnghdr[18] = (mz_uint8)(w >> 8);
2186
0
            pnghdr[19] = (mz_uint8)w;
2187
0
            pnghdr[22] = (mz_uint8)(h >> 8);
2188
0
            pnghdr[23] = (mz_uint8)h;
2189
0
            pnghdr[25] = chans[num_chans];
2190
0
            pnghdr[33] = (mz_uint8)(*pLen_out >> 24);
2191
0
            pnghdr[34] = (mz_uint8)(*pLen_out >> 16);
2192
0
            pnghdr[35] = (mz_uint8)(*pLen_out >> 8);
2193
0
            pnghdr[36] = (mz_uint8)*pLen_out;
2194
0
            c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
2195
0
            for (i = 0; i < 4; ++i, c <<= 8)
2196
0
                ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
2197
0
            memcpy(out_buf.m_pBuf, pnghdr, 41);
2198
0
        }
2199
        /* write footer (IDAT CRC-32, followed by IEND chunk) */
2200
0
        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
0
        {
2202
0
            *pLen_out = 0;
2203
0
            MZ_FREE(pComp);
2204
0
            MZ_FREE(out_buf.m_pBuf);
2205
0
            return NULL;
2206
0
        }
2207
0
        c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4);
2208
0
        for (i = 0; i < 4; ++i, c <<= 8)
2209
0
            (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
0
        *pLen_out += 57;
2212
0
        MZ_FREE(pComp);
2213
0
        return out_buf.m_pBuf;
2214
0
    }
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
0
    {
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
0
        return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
2219
0
    }
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
0
    {
2227
0
        return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2228
0
    }
2229
2230
    void tdefl_compressor_free(tdefl_compressor *pComp)
2231
0
    {
2232
0
        MZ_FREE(pComp);
2233
0
    }
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
2276
extern "C"
2277
{
2278
#endif
2279
2280
    /* ------------------- Low-level Decompression (completely independent from all compression API's) */
2281
2282
28.5M
#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
2283
1.73M
#define TINFL_MEMSET(p, c, l) memset(p, c, l)
2284
2285
#define TINFL_CR_BEGIN  \
2286
273M
    switch (r->m_state) \
2287
273M
    {                   \
2288
30.5k
        case 0:
2289
#define TINFL_CR_RETURN(state_index, result) \
2290
136M
    do                                       \
2291
136M
    {                                        \
2292
273M
        status = result;                     \
2293
136M
        r->m_state = state_index;            \
2294
136M
        goto common_exit;                    \
2295
136M
        case state_index:;                   \
2296
136M
    }                                        \
2297
136M
    MZ_MACRO_END
2298
#define TINFL_CR_RETURN_FOREVER(state_index, result) \
2299
19.8k
    do                                               \
2300
19.8k
    {                                                \
2301
19.8k
        for (;;)                                     \
2302
19.8k
        {                                            \
2303
19.8k
            TINFL_CR_RETURN(state_index, result);    \
2304
19.8k
        }                                            \
2305
19.8k
    }                                                \
2306
20.5k
    MZ_MACRO_END
2307
136M
#define TINFL_CR_FINISH }
2308
2309
#define TINFL_GET_BYTE(state_index, c)                                                                                                                           \
2310
108M
    do                                                                                                                                                           \
2311
108M
    {                                                                                                                                                            \
2312
216M
        while (pIn_buf_cur >= pIn_buf_end)                                                                                                                       \
2313
108M
        {                                                                                                                                                        \
2314
108M
            TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
2315
108M
        }                                                                                                                                                        \
2316
108M
        c = *pIn_buf_cur++;                                                                                                                                      \
2317
108M
    }                                                                                                                                                            \
2318
217M
    MZ_MACRO_END
2319
2320
#define TINFL_NEED_BITS(state_index, n)                \
2321
1.66M
    do                                                 \
2322
1.92M
    {                                                  \
2323
1.92M
        mz_uint c;                                     \
2324
1.92M
        TINFL_GET_BYTE(state_index, c);                \
2325
1.92M
        bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2326
1.92M
        num_bits += 8;                                 \
2327
1.92M
    } while (num_bits < (mz_uint)(n))
2328
#define TINFL_SKIP_BITS(state_index, n)      \
2329
49.7k
    do                                       \
2330
49.7k
    {                                        \
2331
49.7k
        if (num_bits < (mz_uint)(n))         \
2332
49.7k
        {                                    \
2333
0
            TINFL_NEED_BITS(state_index, n); \
2334
0
        }                                    \
2335
49.7k
        bit_buf >>= (n);                     \
2336
49.7k
        num_bits -= (n);                     \
2337
49.7k
    }                                        \
2338
64.4k
    MZ_MACRO_END
2339
#define TINFL_GET_BITS(state_index, b, n)    \
2340
15.2M
    do                                       \
2341
15.2M
    {                                        \
2342
15.2M
        if (num_bits < (mz_uint)(n))         \
2343
15.2M
        {                                    \
2344
1.66M
            TINFL_NEED_BITS(state_index, n); \
2345
1.66M
        }                                    \
2346
15.2M
        b = bit_buf & ((1 << (n)) - 1);      \
2347
15.2M
        bit_buf >>= (n);                     \
2348
15.2M
        num_bits -= (n);                     \
2349
15.2M
    }                                        \
2350
15.2M
    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
120M
    do                                                               \
2358
215M
    {                                                                \
2359
215M
        temp = pLookUp[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)];      \
2360
215M
        if (temp >= 0)                                               \
2361
215M
        {                                                            \
2362
214M
            code_len = temp >> 9;                                    \
2363
214M
            if ((code_len) && (num_bits >= code_len))                \
2364
214M
                break;                                               \
2365
214M
        }                                                            \
2366
215M
        else if (num_bits > TINFL_FAST_LOOKUP_BITS)                  \
2367
250k
        {                                                            \
2368
138k
            code_len = TINFL_FAST_LOOKUP_BITS;                       \
2369
138k
            do                                                       \
2370
220k
            {                                                        \
2371
220k
                temp = pTree[~temp + ((bit_buf >> code_len++) & 1)]; \
2372
220k
            } while ((temp < 0) && (num_bits >= (code_len + 1)));    \
2373
138k
            if (temp >= 0)                                           \
2374
138k
                break;                                               \
2375
138k
        }                                                            \
2376
215M
        TINFL_GET_BYTE(state_index, c);                              \
2377
106M
        bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);               \
2378
106M
        num_bits += 8;                                               \
2379
106M
    } 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
164M
    do                                                                                                                              \
2389
164M
    {                                                                                                                               \
2390
164M
        int temp;                                                                                                                   \
2391
164M
        mz_uint code_len, c;                                                                                                        \
2392
164M
        if (num_bits < 15)                                                                                                          \
2393
164M
        {                                                                                                                           \
2394
121M
            if ((pIn_buf_end - pIn_buf_cur) < 2)                                                                                    \
2395
121M
            {                                                                                                                       \
2396
120M
                TINFL_HUFF_BITBUF_FILL(state_index, pLookUp, pTree);                                                                \
2397
120M
            }                                                                                                                       \
2398
121M
            else                                                                                                                    \
2399
121M
            {                                                                                                                       \
2400
796k
                bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
2401
796k
                pIn_buf_cur += 2;                                                                                                   \
2402
796k
                num_bits += 16;                                                                                                     \
2403
796k
            }                                                                                                                       \
2404
121M
        }                                                                                                                           \
2405
164M
        if ((temp = pLookUp[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)                                                          \
2406
164M
            code_len = temp >> 9, temp &= 511;                                                                                      \
2407
164M
        else                                                                                                                        \
2408
164M
        {                                                                                                                           \
2409
296k
            code_len = TINFL_FAST_LOOKUP_BITS;                                                                                      \
2410
296k
            do                                                                                                                      \
2411
643k
            {                                                                                                                       \
2412
643k
                temp = pTree[~temp + ((bit_buf >> code_len++) & 1)];                                                                \
2413
643k
            } while (temp < 0);                                                                                                     \
2414
296k
        }                                                                                                                           \
2415
164M
        sym = temp;                                                                                                                 \
2416
164M
        bit_buf >>= code_len;                                                                                                       \
2417
164M
        num_bits -= code_len;                                                                                                       \
2418
164M
    }                                                                                                                               \
2419
164M
    MZ_MACRO_END
2420
2421
    static void tinfl_clear_tree(tinfl_decompressor *r)
2422
140k
    {
2423
140k
        if (r->m_type == 0)
2424
51.7k
            MZ_CLEAR_ARR(r->m_tree_0);
2425
88.9k
        else if (r->m_type == 1)
2426
51.7k
            MZ_CLEAR_ARR(r->m_tree_1);
2427
37.1k
        else
2428
37.1k
            MZ_CLEAR_ARR(r->m_tree_2);
2429
140k
    }
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
136M
    {
2433
136M
        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
136M
        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
136M
        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
136M
        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
136M
        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
136M
        static const mz_uint16 s_min_table_sizes[3] = { 257, 1, 4 };
2439
2440
136M
        mz_int16 *pTrees[3];
2441
136M
        mz_uint8 *pCode_sizes[3];
2442
2443
136M
        tinfl_status status = TINFL_STATUS_FAILED;
2444
136M
        mz_uint32 num_bits, dist, counter, num_extra;
2445
136M
        tinfl_bit_buf_t bit_buf;
2446
136M
        const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
2447
136M
        mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next ? pOut_buf_next + *pOut_buf_size : NULL;
2448
136M
        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
136M
        if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))
2452
0
        {
2453
0
            *pIn_buf_size = *pOut_buf_size = 0;
2454
0
            return TINFL_STATUS_BAD_PARAM;
2455
0
        }
2456
2457
136M
        pTrees[0] = r->m_tree_0;
2458
136M
        pTrees[1] = r->m_tree_1;
2459
136M
        pTrees[2] = r->m_tree_2;
2460
136M
        pCode_sizes[0] = r->m_code_size_0;
2461
136M
        pCode_sizes[1] = r->m_code_size_1;
2462
136M
        pCode_sizes[2] = r->m_code_size_2;
2463
2464
136M
        num_bits = r->m_num_bits;
2465
136M
        bit_buf = r->m_bit_buf;
2466
136M
        dist = r->m_dist;
2467
136M
        counter = r->m_counter;
2468
136M
        num_extra = r->m_num_extra;
2469
136M
        dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2470
136M
        TINFL_CR_BEGIN
2471
2472
30.5k
        bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2473
30.5k
        r->m_z_adler32 = r->m_check_adler32 = 1;
2474
30.5k
        if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2475
17.3k
        {
2476
17.3k
            TINFL_GET_BYTE(1, r->m_zhdr0);
2477
17.3k
            TINFL_GET_BYTE(2, r->m_zhdr1);
2478
17.3k
            counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2479
17.3k
            if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2480
2.31k
                counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)((size_t)1 << (8U + (r->m_zhdr0 >> 4)))));
2481
17.3k
            if (counter)
2482
40
            {
2483
40
                TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
2484
40
            }
2485
17.3k
        }
2486
2487
30.5k
        do
2488
89.9k
        {
2489
89.9k
            TINFL_GET_BITS(3, r->m_final, 3);
2490
89.5k
            r->m_type = r->m_final >> 1;
2491
89.5k
            if (r->m_type == 0)
2492
33.9k
            {
2493
33.9k
                TINFL_SKIP_BITS(5, num_bits & 7);
2494
168k
                for (counter = 0; counter < 4; ++counter)
2495
135k
                {
2496
135k
                    if (num_bits)
2497
14.7k
                        TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2498
120k
                    else
2499
120k
                        TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2500
135k
                }
2501
33.4k
                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
1.32k
                {
2503
1.32k
                    TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
2504
1.32k
                }
2505
34.2k
                while ((counter) && (num_bits))
2506
2.36k
                {
2507
2.36k
                    TINFL_GET_BITS(51, dist, 8);
2508
2.36k
                    while (pOut_buf_cur >= pOut_buf_end)
2509
214
                    {
2510
214
                        TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
2511
214
                    }
2512
2.15k
                    *pOut_buf_cur++ = (mz_uint8)dist;
2513
2.15k
                    counter--;
2514
2.15k
                }
2515
28.5M
                while (counter)
2516
28.5M
                {
2517
28.5M
                    size_t n;
2518
28.5M
                    while (pOut_buf_cur >= pOut_buf_end)
2519
1.25k
                    {
2520
1.25k
                        TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
2521
1.25k
                    }
2522
56.9M
                    while (pIn_buf_cur >= pIn_buf_end)
2523
28.4M
                    {
2524
28.4M
                        TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);
2525
28.4M
                    }
2526
28.4M
                    n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
2527
28.4M
                    TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2528
28.4M
                    pIn_buf_cur += n;
2529
28.4M
                    pOut_buf_cur += n;
2530
28.4M
                    counter -= (mz_uint)n;
2531
28.4M
                }
2532
31.9k
            }
2533
55.5k
            else if (r->m_type == 3)
2534
907
            {
2535
907
                TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
2536
907
            }
2537
54.6k
            else
2538
54.6k
            {
2539
54.6k
                if (r->m_type == 1)
2540
16.7k
                {
2541
16.7k
                    mz_uint8 *p = r->m_code_size_0;
2542
16.7k
                    mz_uint i;
2543
16.7k
                    r->m_table_sizes[0] = 288;
2544
16.7k
                    r->m_table_sizes[1] = 32;
2545
16.7k
                    TINFL_MEMSET(r->m_code_size_1, 5, 32);
2546
2.42M
                    for (i = 0; i <= 143; ++i)
2547
2.41M
                        *p++ = 8;
2548
1.89M
                    for (; i <= 255; ++i)
2549
1.87M
                        *p++ = 9;
2550
418k
                    for (; i <= 279; ++i)
2551
401k
                        *p++ = 7;
2552
150k
                    for (; i <= 287; ++i)
2553
133k
                        *p++ = 8;
2554
16.7k
                }
2555
37.9k
                else
2556
37.9k
                {
2557
151k
                    for (counter = 0; counter < 3; counter++)
2558
113k
                    {
2559
113k
                        TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
2560
113k
                        r->m_table_sizes[counter] += s_min_table_sizes[counter];
2561
113k
                    }
2562
37.6k
                    MZ_CLEAR_ARR(r->m_code_size_2);
2563
620k
                    for (counter = 0; counter < r->m_table_sizes[2]; counter++)
2564
583k
                    {
2565
583k
                        mz_uint s;
2566
583k
                        TINFL_GET_BITS(14, s, 3);
2567
582k
                        r->m_code_size_2[s_length_dezigzag[counter]] = (mz_uint8)s;
2568
582k
                    }
2569
37.1k
                    r->m_table_sizes[2] = 19;
2570
37.1k
                }
2571
192k
                for (; (int)r->m_type >= 0; r->m_type--)
2572
140k
                {
2573
140k
                    int tree_next, tree_cur;
2574
140k
                    mz_int16 *pLookUp;
2575
140k
                    mz_int16 *pTree;
2576
140k
                    mz_uint8 *pCode_size;
2577
140k
                    mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
2578
140k
                    pLookUp = r->m_look_up[r->m_type];
2579
140k
                    pTree = pTrees[r->m_type];
2580
140k
                    pCode_size = pCode_sizes[r->m_type];
2581
140k
                    MZ_CLEAR_ARR(total_syms);
2582
140k
                    TINFL_MEMSET(pLookUp, 0, sizeof(r->m_look_up[0]));
2583
140k
                    tinfl_clear_tree(r);
2584
16.3M
                    for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2585
16.2M
                        total_syms[pCode_size[i]]++;
2586
140k
                    used_syms = 0, total = 0;
2587
140k
                    next_code[0] = next_code[1] = 0;
2588
2.25M
                    for (i = 1; i <= 15; ++i)
2589
2.10M
                    {
2590
2.10M
                        used_syms += total_syms[i];
2591
2.10M
                        next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2592
2.10M
                    }
2593
140k
                    if ((65536 != total) && (used_syms > 1))
2594
702
                    {
2595
702
                        TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
2596
702
                    }
2597
16.2M
                    for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
2598
16.1M
                    {
2599
16.1M
                        mz_uint rev_code = 0, l, cur_code, code_size = pCode_size[sym_index];
2600
16.1M
                        if (!code_size)
2601
5.07M
                            continue;
2602
11.0M
                        cur_code = next_code[code_size]++;
2603
100M
                        for (l = code_size; l > 0; l--, cur_code >>= 1)
2604
88.9M
                            rev_code = (rev_code << 1) | (cur_code & 1);
2605
11.0M
                        if (code_size <= TINFL_FAST_LOOKUP_BITS)
2606
10.6M
                        {
2607
10.6M
                            mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2608
134M
                            while (rev_code < TINFL_FAST_LOOKUP_SIZE)
2609
123M
                            {
2610
123M
                                pLookUp[rev_code] = k;
2611
123M
                                rev_code += (1 << code_size);
2612
123M
                            }
2613
10.6M
                            continue;
2614
10.6M
                        }
2615
480k
                        if (0 == (tree_cur = pLookUp[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
2616
90.5k
                        {
2617
90.5k
                            pLookUp[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
2618
90.5k
                            tree_cur = tree_next;
2619
90.5k
                            tree_next -= 2;
2620
90.5k
                        }
2621
480k
                        rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2622
1.45M
                        for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
2623
978k
                        {
2624
978k
                            tree_cur -= ((rev_code >>= 1) & 1);
2625
978k
                            if (!pTree[-tree_cur - 1])
2626
314k
                            {
2627
314k
                                pTree[-tree_cur - 1] = (mz_int16)tree_next;
2628
314k
                                tree_cur = tree_next;
2629
314k
                                tree_next -= 2;
2630
314k
                            }
2631
663k
                            else
2632
663k
                                tree_cur = pTree[-tree_cur - 1];
2633
978k
                        }
2634
480k
                        tree_cur -= ((rev_code >>= 1) & 1);
2635
480k
                        pTree[-tree_cur - 1] = (mz_int16)sym_index;
2636
480k
                    }
2637
139k
                    if (r->m_type == 2)
2638
36.6k
                    {
2639
4.62M
                        for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)
2640
4.58M
                        {
2641
4.58M
                            mz_uint s;
2642
4.58M
                            TINFL_HUFF_DECODE(16, dist, r->m_look_up[2], r->m_tree_2);
2643
4.58M
                            if (dist < 16)
2644
3.72M
                            {
2645
3.72M
                                r->m_len_codes[counter++] = (mz_uint8)dist;
2646
3.72M
                                continue;
2647
3.72M
                            }
2648
866k
                            if ((dist == 16) && (!counter))
2649
227
                            {
2650
227
                                TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
2651
227
                            }
2652
865k
                            num_extra = "\02\03\07"[dist - 16];
2653
865k
                            TINFL_GET_BITS(18, s, num_extra);
2654
865k
                            s += "\03\03\013"[dist - 16];
2655
865k
                            TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2656
865k
                            counter += s;
2657
865k
                        }
2658
35.2k
                        if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
2659
295
                        {
2660
295
                            TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
2661
295
                        }
2662
35.0k
                        TINFL_MEMCPY(r->m_code_size_0, r->m_len_codes, r->m_table_sizes[0]);
2663
35.0k
                        TINFL_MEMCPY(r->m_code_size_1, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
2664
35.0k
                    }
2665
139k
                }
2666
51.6k
                for (;;)
2667
19.3M
                {
2668
19.3M
                    mz_uint8 *pSrc;
2669
19.3M
                    for (;;)
2670
437M
                    {
2671
437M
                        if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
2672
140M
                        {
2673
140M
                            TINFL_HUFF_DECODE(23, counter, r->m_look_up[0], r->m_tree_0);
2674
140M
                            if (counter >= 256)
2675
1.57M
                                break;
2676
139M
                            while (pOut_buf_cur >= pOut_buf_end)
2677
1.85k
                            {
2678
1.85k
                                TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
2679
1.85k
                            }
2680
139M
                            *pOut_buf_cur++ = (mz_uint8)counter;
2681
139M
                        }
2682
296M
                        else
2683
296M
                        {
2684
296M
                            int sym2;
2685
296M
                            mz_uint code_len;
2686
296M
#if TINFL_USE_64BIT_BITBUF
2687
296M
                            if (num_bits < 30)
2688
119M
                            {
2689
119M
                                bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2690
119M
                                pIn_buf_cur += 4;
2691
119M
                                num_bits += 32;
2692
119M
                            }
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
296M
                            if ((sym2 = r->m_look_up[0][bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2702
295M
                                code_len = sym2 >> 9;
2703
745k
                            else
2704
745k
                            {
2705
745k
                                code_len = TINFL_FAST_LOOKUP_BITS;
2706
745k
                                do
2707
1.49M
                                {
2708
1.49M
                                    sym2 = r->m_tree_0[~sym2 + ((bit_buf >> code_len++) & 1)];
2709
1.49M
                                } while (sym2 < 0);
2710
745k
                            }
2711
296M
                            counter = sym2;
2712
296M
                            bit_buf >>= code_len;
2713
296M
                            num_bits -= code_len;
2714
296M
                            if (counter & 256)
2715
13.2M
                                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
282M
                            if ((sym2 = r->m_look_up[0][bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2726
282M
                                code_len = sym2 >> 9;
2727
514k
                            else
2728
514k
                            {
2729
514k
                                code_len = TINFL_FAST_LOOKUP_BITS;
2730
514k
                                do
2731
1.02M
                                {
2732
1.02M
                                    sym2 = r->m_tree_0[~sym2 + ((bit_buf >> code_len++) & 1)];
2733
1.02M
                                } while (sym2 < 0);
2734
514k
                            }
2735
282M
                            bit_buf >>= code_len;
2736
282M
                            num_bits -= code_len;
2737
2738
282M
                            pOut_buf_cur[0] = (mz_uint8)counter;
2739
282M
                            if (sym2 & 256)
2740
4.48M
                            {
2741
4.48M
                                pOut_buf_cur++;
2742
4.48M
                                counter = sym2;
2743
4.48M
                                break;
2744
4.48M
                            }
2745
278M
                            pOut_buf_cur[1] = (mz_uint8)sym2;
2746
278M
                            pOut_buf_cur += 2;
2747
278M
                        }
2748
437M
                    }
2749
19.3M
                    if ((counter &= 511) == 256)
2750
44.1k
                        break;
2751
2752
19.2M
                    num_extra = s_length_extra[counter - 257];
2753
19.2M
                    counter = s_length_base[counter - 257];
2754
19.2M
                    if (num_extra)
2755
2.79M
                    {
2756
2.79M
                        mz_uint extra_bits;
2757
2.79M
                        TINFL_GET_BITS(25, extra_bits, num_extra);
2758
2.79M
                        counter += extra_bits;
2759
2.79M
                    }
2760
2761
19.2M
                    TINFL_HUFF_DECODE(26, dist, r->m_look_up[1], r->m_tree_1);
2762
19.2M
                    num_extra = s_dist_extra[dist];
2763
19.2M
                    dist = s_dist_base[dist];
2764
19.2M
                    if (num_extra)
2765
10.7M
                    {
2766
10.7M
                        mz_uint extra_bits;
2767
10.7M
                        TINFL_GET_BITS(27, extra_bits, num_extra);
2768
10.7M
                        dist += extra_bits;
2769
10.7M
                    }
2770
2771
19.2M
                    dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2772
19.2M
                    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
1.29k
                    {
2774
1.29k
                        TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
2775
1.29k
                    }
2776
2777
19.2M
                    pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2778
2779
19.2M
                    if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
2780
4.44k
                    {
2781
893k
                        while (counter--)
2782
889k
                        {
2783
892k
                            while (pOut_buf_cur >= pOut_buf_end)
2784
3.91k
                            {
2785
3.91k
                                TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
2786
3.91k
                            }
2787
888k
                            *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
2788
888k
                        }
2789
4.14k
                        continue;
2790
4.44k
                    }
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
152M
                    while (counter > 2)
2819
133M
                    {
2820
133M
                        pOut_buf_cur[0] = pSrc[0];
2821
133M
                        pOut_buf_cur[1] = pSrc[1];
2822
133M
                        pOut_buf_cur[2] = pSrc[2];
2823
133M
                        pOut_buf_cur += 3;
2824
133M
                        pSrc += 3;
2825
133M
                        counter -= 3;
2826
133M
                    }
2827
19.2M
                    if (counter > 0)
2828
6.30M
                    {
2829
6.30M
                        pOut_buf_cur[0] = pSrc[0];
2830
6.30M
                        if (counter > 1)
2831
2.52M
                            pOut_buf_cur[1] = pSrc[1];
2832
6.30M
                        pOut_buf_cur += counter;
2833
6.30M
                    }
2834
19.2M
                }
2835
51.6k
            }
2836
89.5k
        } 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
15.7k
        TINFL_SKIP_BITS(32, num_bits & 7);
2841
34.8k
        while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2842
19.1k
        {
2843
19.1k
            --pIn_buf_cur;
2844
19.1k
            num_bits -= 8;
2845
19.1k
        }
2846
15.7k
        bit_buf &= ~(~(tinfl_bit_buf_t)0 << num_bits);
2847
15.7k
        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
15.7k
        if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2850
11.7k
        {
2851
56.0k
            for (counter = 0; counter < 4; ++counter)
2852
45.0k
            {
2853
45.0k
                mz_uint s;
2854
45.0k
                if (num_bits)
2855
0
                    TINFL_GET_BITS(41, s, 8);
2856
45.0k
                else
2857
45.0k
                    TINFL_GET_BYTE(42, s);
2858
44.3k
                r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2859
44.3k
            }
2860
11.7k
        }
2861
136M
        TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
2862
2863
136M
        TINFL_CR_FINISH
2864
2865
136M
    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
136M
        if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS))
2870
27.0k
        {
2871
46.3k
            while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2872
19.2k
            {
2873
19.2k
                --pIn_buf_cur;
2874
19.2k
                num_bits -= 8;
2875
19.2k
            }
2876
27.0k
        }
2877
136M
        r->m_num_bits = num_bits;
2878
136M
        r->m_bit_buf = bit_buf & ~(~(tinfl_bit_buf_t)0 << num_bits);
2879
136M
        r->m_dist = dist;
2880
136M
        r->m_counter = counter;
2881
136M
        r->m_num_extra = num_extra;
2882
136M
        r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2883
136M
        *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2884
136M
        *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2885
136M
        if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
2886
136M
        {
2887
136M
            const mz_uint8 *ptr = pOut_buf_next;
2888
136M
            size_t buf_len = *pOut_buf_size;
2889
136M
            mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;
2890
136M
            size_t block_len = buf_len % 5552;
2891
269M
            while (buf_len)
2892
132M
            {
2893
254M
                for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
2894
122M
                {
2895
122M
                    s1 += ptr[0], s2 += s1;
2896
122M
                    s1 += ptr[1], s2 += s1;
2897
122M
                    s1 += ptr[2], s2 += s1;
2898
122M
                    s1 += ptr[3], s2 += s1;
2899
122M
                    s1 += ptr[4], s2 += s1;
2900
122M
                    s1 += ptr[5], s2 += s1;
2901
122M
                    s1 += ptr[6], s2 += s1;
2902
122M
                    s1 += ptr[7], s2 += s1;
2903
122M
                }
2904
283M
                for (; i < block_len; ++i)
2905
150M
                    s1 += *ptr++, s2 += s1;
2906
132M
                s1 %= 65521U, s2 %= 65521U;
2907
132M
                buf_len -= block_len;
2908
132M
                block_len = 5552;
2909
132M
            }
2910
136M
            r->m_check_adler32 = (s2 << 16) + s1;
2911
136M
            if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
2912
287
                status = TINFL_STATUS_ADLER32_MISMATCH;
2913
136M
        }
2914
136M
        return status;
2915
136M
    }
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
0
    {
2920
0
        tinfl_decompressor decomp;
2921
0
        void *pBuf = NULL, *pNew_buf;
2922
0
        size_t src_buf_ofs = 0, out_buf_capacity = 0;
2923
0
        *pOut_len = 0;
2924
0
        tinfl_init(&decomp);
2925
0
        for (;;)
2926
0
        {
2927
0
            size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2928
0
            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
0
                                                   (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2930
0
            if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
2931
0
            {
2932
0
                MZ_FREE(pBuf);
2933
0
                *pOut_len = 0;
2934
0
                return NULL;
2935
0
            }
2936
0
            src_buf_ofs += src_buf_size;
2937
0
            *pOut_len += dst_buf_size;
2938
0
            if (status == TINFL_STATUS_DONE)
2939
0
                break;
2940
0
            new_out_buf_capacity = out_buf_capacity * 2;
2941
0
            if (new_out_buf_capacity < 128)
2942
0
                new_out_buf_capacity = 128;
2943
0
            pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2944
0
            if (!pNew_buf)
2945
0
            {
2946
0
                MZ_FREE(pBuf);
2947
0
                *pOut_len = 0;
2948
0
                return NULL;
2949
0
            }
2950
0
            pBuf = pNew_buf;
2951
0
            out_buf_capacity = new_out_buf_capacity;
2952
0
        }
2953
0
        return pBuf;
2954
0
    }
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
0
    {
2958
0
        tinfl_decompressor decomp;
2959
0
        tinfl_status status;
2960
0
        tinfl_init(&decomp);
2961
0
        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
0
        return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
2963
0
    }
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
0
    {
2967
0
        int result = 0;
2968
0
        tinfl_decompressor decomp;
2969
0
        mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
2970
0
        size_t in_buf_ofs = 0, dict_ofs = 0;
2971
0
        if (!pDict)
2972
0
            return TINFL_STATUS_FAILED;
2973
0
        memset(pDict, 0, TINFL_LZ_DICT_SIZE);
2974
0
        tinfl_init(&decomp);
2975
0
        for (;;)
2976
0
        {
2977
0
            size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
2978
0
            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
0
                                                   (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
2980
0
            in_buf_ofs += in_buf_size;
2981
0
            if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
2982
0
                break;
2983
0
            if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
2984
0
            {
2985
0
                result = (status == TINFL_STATUS_DONE);
2986
0
                break;
2987
0
            }
2988
0
            dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
2989
0
        }
2990
0
        MZ_FREE(pDict);
2991
0
        *pIn_buf_size = in_buf_ofs;
2992
0
        return result;
2993
0
    }
2994
2995
#ifndef MINIZ_NO_MALLOC
2996
    tinfl_decompressor *tinfl_decompressor_alloc(void)
2997
0
    {
2998
0
        tinfl_decompressor *pDecomp = (tinfl_decompressor *)MZ_MALLOC(sizeof(tinfl_decompressor));
2999
0
        if (pDecomp)
3000
0
            tinfl_init(pDecomp);
3001
0
        return pDecomp;
3002
0
    }
3003
3004
    void tinfl_decompressor_free(tinfl_decompressor *pDecomp)
3005
0
    {
3006
0
        MZ_FREE(pDecomp);
3007
0
    }
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
3046
extern "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
3070
static 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
3078
static 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
3089
static 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__)
3101
static 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
3109
static 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
22.9k
#define MZ_FOPEN(f, m) fopen(f, m)
3191
11.2k
#define MZ_FCLOSE fclose
3192
46.7k
#define MZ_FREAD fread
3193
35.7k
#define MZ_FWRITE fwrite
3194
90.8k
#define MZ_FTELL64 ftello
3195
54.8k
#define MZ_FSEEK64 fseeko
3196
#define MZ_FILE_STAT_STRUCT stat
3197
5.51k
#define MZ_FILE_STAT stat
3198
5.46k
#define MZ_FFLUSH fflush
3199
0
#define MZ_FREOPEN(p, m, s) freopen(p, m, s)
3200
31
#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
1.87M
#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
48.1k
#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
1.09M
#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
32.2k
    {
3364
32.2k
        memset(pArray, 0, sizeof(mz_zip_array));
3365
32.2k
        pArray->m_element_size = element_size;
3366
32.2k
    }
3367
3368
    static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
3369
59.2k
    {
3370
59.2k
        pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
3371
59.2k
        memset(pArray, 0, sizeof(mz_zip_array));
3372
59.2k
    }
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
45.5k
    {
3376
45.5k
        void *pNew_p;
3377
45.5k
        size_t new_capacity = min_new_capacity;
3378
45.5k
        MZ_ASSERT(pArray->m_element_size);
3379
45.5k
        if (pArray->m_capacity >= min_new_capacity)
3380
0
            return MZ_TRUE;
3381
45.5k
        if (growing)
3382
10.8k
        {
3383
10.8k
            new_capacity = MZ_MAX(1, pArray->m_capacity);
3384
36.3k
            while (new_capacity < min_new_capacity)
3385
25.4k
                new_capacity *= 2;
3386
10.8k
        }
3387
45.5k
        if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
3388
0
            return MZ_FALSE;
3389
45.5k
        pArray->m_p = pNew_p;
3390
45.5k
        pArray->m_capacity = new_capacity;
3391
45.5k
        return MZ_TRUE;
3392
45.5k
    }
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
10.8k
    {
3396
10.8k
        if (new_capacity > pArray->m_capacity)
3397
10.8k
        {
3398
10.8k
            if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
3399
0
                return MZ_FALSE;
3400
10.8k
        }
3401
10.8k
        return MZ_TRUE;
3402
10.8k
    }
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
69.2k
    {
3406
69.2k
        if (new_size > pArray->m_capacity)
3407
34.7k
        {
3408
34.7k
            if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
3409
0
                return MZ_FALSE;
3410
34.7k
        }
3411
69.2k
        pArray->m_size = new_size;
3412
69.2k
        return MZ_TRUE;
3413
69.2k
    }
3414
3415
    static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
3416
10.8k
    {
3417
10.8k
        return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
3418
10.8k
    }
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
32.5k
    {
3422
32.5k
        size_t orig_size = pArray->m_size;
3423
32.5k
        if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
3424
0
            return MZ_FALSE;
3425
32.5k
        if (n > 0)
3426
20.2k
            memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
3427
32.5k
        return MZ_TRUE;
3428
32.5k
    }
3429
3430
#ifndef MINIZ_NO_TIME
3431
    static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)
3432
93.0k
    {
3433
93.0k
        struct tm tm;
3434
93.0k
        memset(&tm, 0, sizeof(tm));
3435
93.0k
        tm.tm_isdst = -1;
3436
93.0k
        tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
3437
93.0k
        tm.tm_mon = ((dos_date >> 5) & 15) - 1;
3438
93.0k
        tm.tm_mday = dos_date & 31;
3439
93.0k
        tm.tm_hour = (dos_time >> 11) & 31;
3440
93.0k
        tm.tm_min = (dos_time >> 5) & 63;
3441
93.0k
        tm.tm_sec = (dos_time << 1) & 62;
3442
93.0k
        return mktime(&tm);
3443
93.0k
    }
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
5.46k
    {
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
5.46k
        struct tm *tm = localtime(&time);
3460
5.46k
#endif /* #ifdef _MSC_VER */
3461
3462
5.46k
        *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
3463
5.46k
        *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
3464
5.46k
    }
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
0
    {
3471
0
        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
0
        if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
3475
0
            return MZ_FALSE;
3476
3477
0
        *pTime = file_stat.st_mtime;
3478
3479
0
        return MZ_TRUE;
3480
0
    }
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
0
    {
3485
0
        struct utimbuf t;
3486
3487
0
        memset(&t, 0, sizeof(t));
3488
0
        t.actime = access_time;
3489
0
        t.modtime = modified_time;
3490
3491
0
        return !utime(pFilename, &t);
3492
0
    }
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
61.5k
    {
3498
61.5k
        if (pZip)
3499
61.5k
            pZip->m_last_error = err_num;
3500
61.5k
        return MZ_FALSE;
3501
61.5k
    }
3502
3503
    static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
3504
13.2k
    {
3505
13.2k
        (void)flags;
3506
13.2k
        if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3507
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3508
3509
13.2k
        if (!pZip->m_pAlloc)
3510
13.2k
            pZip->m_pAlloc = miniz_def_alloc_func;
3511
13.2k
        if (!pZip->m_pFree)
3512
13.2k
            pZip->m_pFree = miniz_def_free_func;
3513
13.2k
        if (!pZip->m_pRealloc)
3514
13.2k
            pZip->m_pRealloc = miniz_def_realloc_func;
3515
3516
13.2k
        pZip->m_archive_size = 0;
3517
13.2k
        pZip->m_central_directory_file_ofs = 0;
3518
13.2k
        pZip->m_total_files = 0;
3519
13.2k
        pZip->m_last_error = MZ_ZIP_NO_ERROR;
3520
3521
13.2k
        if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3522
0
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3523
3524
13.2k
        memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3525
13.2k
        MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
3526
13.2k
        MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
3527
13.2k
        MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
3528
13.2k
        pZip->m_pState->m_init_flags = flags;
3529
13.2k
        pZip->m_pState->m_zip64 = MZ_FALSE;
3530
13.2k
        pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;
3531
3532
13.2k
        pZip->m_zip_mode = MZ_ZIP_MODE_READING;
3533
3534
13.2k
        return MZ_TRUE;
3535
13.2k
    }
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
183k
    {
3539
183k
        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
183k
        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
183k
        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
183k
        mz_uint8 l = 0, r = 0;
3543
183k
        pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3544
183k
        pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3545
183k
        pE = pL + MZ_MIN(l_len, r_len);
3546
278k
        while (pL < pE)
3547
169k
        {
3548
169k
            if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3549
74.8k
                break;
3550
95.0k
            pL++;
3551
95.0k
            pR++;
3552
95.0k
        }
3553
183k
        return (pL == pE) ? (l_len < r_len) : (l < r);
3554
183k
    }
3555
3556
#define MZ_SWAP_UINT32(a, b) \
3557
88.2k
    do                       \
3558
88.2k
    {                        \
3559
88.2k
        mz_uint32 t = a;     \
3560
88.2k
        a = b;               \
3561
88.2k
        b = t;               \
3562
88.2k
    }                        \
3563
123k
    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
3.50k
    {
3568
3.50k
        mz_zip_internal_state *pState = pZip->m_pState;
3569
3.50k
        const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3570
3.50k
        const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3571
3.50k
        mz_uint32 *pIndices;
3572
3.50k
        mz_uint32 start, end;
3573
3.50k
        const mz_uint32 size = pZip->m_total_files;
3574
3575
3.50k
        if (size <= 1U)
3576
2.32k
            return;
3577
3578
1.18k
        pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
3579
3580
1.18k
        start = (size - 2U) >> 1U;
3581
1.18k
        for (;;)
3582
15.9k
        {
3583
15.9k
            mz_uint64 child, root = start;
3584
15.9k
            for (;;)
3585
24.5k
            {
3586
24.5k
                if ((child = (root << 1U) + 1U) >= size)
3587
3.53k
                    break;
3588
20.9k
                child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
3589
20.9k
                if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3590
12.4k
                    break;
3591
8.55k
                MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3592
8.55k
                root = child;
3593
8.55k
            }
3594
15.9k
            if (!start)
3595
1.18k
                break;
3596
14.7k
            start--;
3597
14.7k
        }
3598
3599
1.18k
        end = size - 1;
3600
32.2k
        while (end > 0)
3601
31.0k
        {
3602
31.0k
            mz_uint64 child, root = 0;
3603
31.0k
            MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
3604
31.0k
            for (;;)
3605
79.6k
            {
3606
79.6k
                if ((child = (root << 1U) + 1U) >= end)
3607
7.89k
                    break;
3608
71.7k
                child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
3609
71.7k
                if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3610
23.1k
                    break;
3611
48.6k
                MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3612
48.6k
                root = child;
3613
48.6k
            }
3614
31.0k
            end--;
3615
31.0k
        }
3616
1.18k
    }
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
13.2k
    {
3620
13.2k
        mz_int64 cur_file_ofs;
3621
13.2k
        mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3622
13.2k
        mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3623
3624
        /* Basic sanity checks - reject files which are too small */
3625
13.2k
        if (pZip->m_archive_size < record_size)
3626
0
            return MZ_FALSE;
3627
3628
        /* Find the record by scanning the file from the end towards the beginning. */
3629
13.2k
        cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
3630
13.2k
        for (;;)
3631
13.3k
        {
3632
13.3k
            int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
3633
3634
13.3k
            if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
3635
18
                return MZ_FALSE;
3636
3637
1.11M
            for (i = n - 4; i >= 0; --i)
3638
1.11M
            {
3639
1.11M
                mz_uint s = MZ_READ_LE32(pBuf + i);
3640
1.11M
                if (s == record_sig)
3641
13.1k
                {
3642
13.1k
                    if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
3643
13.1k
                        break;
3644
13.1k
                }
3645
1.11M
            }
3646
3647
13.3k
            if (i >= 0)
3648
13.1k
            {
3649
13.1k
                cur_file_ofs += i;
3650
13.1k
                break;
3651
13.1k
            }
3652
3653
            /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */
3654
237
            if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= ((mz_uint64)(MZ_UINT16_MAX) + record_size)))
3655
52
                return MZ_FALSE;
3656
3657
185
            cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
3658
185
        }
3659
3660
13.1k
        *pOfs = cur_file_ofs;
3661
13.1k
        return MZ_TRUE;
3662
13.2k
    }
3663
3664
    static mz_bool mz_zip_reader_eocd64_valid(mz_zip_archive *pZip, uint64_t offset, uint8_t *buf)
3665
2.14k
    {
3666
2.14k
        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
2.14k
        {
3668
2.14k
            if (MZ_READ_LE32(buf + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG)
3669
1.75k
            {
3670
1.75k
                return MZ_TRUE;
3671
1.75k
            }
3672
2.14k
        }
3673
3674
385
        return MZ_FALSE;
3675
2.14k
    }
3676
3677
    static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)
3678
13.2k
    {
3679
13.2k
        mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
3680
13.2k
        mz_uint64 cdir_ofs = 0, eocd_ofs = 0, archive_ofs = 0;
3681
13.2k
        mz_int64 cur_file_ofs = 0;
3682
13.2k
        const mz_uint8 *p;
3683
3684
13.2k
        mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3685
13.2k
        mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3686
13.2k
        mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
3687
13.2k
        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
13.2k
        mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
3689
3690
13.2k
        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
13.2k
        mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
3692
3693
13.2k
        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
13.2k
        if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3697
0
            return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3698
3699
13.2k
        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
70
            return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
3701
3702
13.1k
        eocd_ofs = cur_file_ofs;
3703
        /* Read and verify the end of central directory record. */
3704
13.1k
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3706
3707
13.1k
        if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
3708
0
            return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3709
3710
13.1k
        if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3711
10.5k
        {
3712
10.5k
            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
10.5k
            {
3714
10.5k
                if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG)
3715
2.04k
                {
3716
2.04k
                    pZip->m_pState->m_zip64 = MZ_TRUE;
3717
2.04k
                }
3718
10.5k
            }
3719
10.5k
        }
3720
3721
13.1k
        if (pZip->m_pState->m_zip64)
3722
2.04k
        {
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
2.04k
            if (cur_file_ofs < MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE +
3726
2.04k
                                   MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
3727
0
                return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3728
3729
2.04k
            zip64_end_of_central_dir_ofs = cur_file_ofs -
3730
2.04k
                                           MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE -
3731
2.04k
                                           MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE;
3732
3733
2.04k
            if (!mz_zip_reader_eocd64_valid(pZip, zip64_end_of_central_dir_ofs,
3734
2.04k
                                            pZip64_end_of_central_dir))
3735
324
            {
3736
                /* That failed, try reading where the locator tells us to. */
3737
324
                zip64_end_of_central_dir_ofs = MZ_READ_LE64(
3738
324
                    pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
3739
3740
324
                if (zip64_end_of_central_dir_ofs >
3741
324
                    (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3742
228
                    return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3743
3744
96
                if (!mz_zip_reader_eocd64_valid(pZip, zip64_end_of_central_dir_ofs,
3745
96
                                                pZip64_end_of_central_dir))
3746
61
                    return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3747
96
            }
3748
2.04k
        }
3749
3750
12.8k
        pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3751
12.8k
        cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3752
12.8k
        num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
3753
12.8k
        cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
3754
12.8k
        cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
3755
12.8k
        cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
3756
3757
12.8k
        if (pZip->m_pState->m_zip64)
3758
1.75k
        {
3759
1.75k
            mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
3760
1.75k
            mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3761
1.75k
            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
1.75k
            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
1.75k
            mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
3764
3765
1.75k
            if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
3766
4
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3767
3768
1.75k
            if (zip64_total_num_of_disks != 1U)
3769
118
                return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3770
3771
            /* Check for miniz's practical limits */
3772
1.63k
            if (zip64_cdir_total_entries > MZ_UINT32_MAX)
3773
57
                return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3774
3775
1.57k
            pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
3776
3777
1.57k
            if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
3778
50
                return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3779
3780
1.52k
            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
1.52k
            if (zip64_size_of_central_directory > MZ_UINT32_MAX)
3784
47
                return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
3785
3786
1.47k
            cdir_size = (mz_uint32)zip64_size_of_central_directory;
3787
3788
1.47k
            num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
3789
3790
1.47k
            cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
3791
3792
1.47k
            cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
3793
1.47k
        }
3794
3795
12.5k
        if (pZip->m_total_files != cdir_entries_on_this_disk)
3796
90
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3797
3798
12.4k
        if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
3799
118
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3800
3801
12.3k
        if (cdir_size < (mz_uint64)pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
3802
44
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3803
3804
12.3k
        if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
3805
129
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3806
3807
12.1k
        if (eocd_ofs < cdir_ofs + cdir_size)
3808
14
            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
12.1k
        archive_ofs = eocd_ofs - (cdir_ofs + cdir_size);
3813
12.1k
        if (pZip->m_pState->m_zip64)
3814
1.31k
        {
3815
1.31k
            if (archive_ofs < MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE +
3816
1.31k
                                  MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
3817
5
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3818
3819
1.31k
            archive_ofs -= MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE +
3820
1.31k
                           MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE;
3821
1.31k
        }
3822
3823
        /* Update the archive start position, but only if not specified. */
3824
12.1k
        if ((pZip->m_zip_type == MZ_ZIP_TYPE_FILE || pZip->m_zip_type == MZ_ZIP_TYPE_CFILE ||
3825
8.22k
            pZip->m_zip_type == MZ_ZIP_TYPE_USER) && pZip->m_pState->m_file_archive_start_ofs == 0)
3826
8.22k
        {
3827
8.22k
            pZip->m_pState->m_file_archive_start_ofs = archive_ofs;
3828
8.22k
            pZip->m_archive_size -= archive_ofs;
3829
8.22k
        }
3830
3831
12.1k
        pZip->m_central_directory_file_ofs = cdir_ofs;
3832
3833
12.1k
        if (pZip->m_total_files)
3834
12.1k
        {
3835
12.1k
            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
12.1k
            if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
3838
12.1k
                (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
3839
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3840
3841
12.1k
            if (sort_central_dir)
3842
3.93k
            {
3843
3.93k
                if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
3844
0
                    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3845
3.93k
            }
3846
3847
12.1k
            if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
3848
31
                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
12.1k
            p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
3852
62.3k
            for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
3853
50.6k
            {
3854
50.6k
                mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
3855
50.6k
                mz_uint64 comp_size, decomp_size, local_header_ofs;
3856
3857
50.6k
                if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
3858
70
                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3859
3860
50.5k
                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
50.5k
                if (sort_central_dir)
3863
35.8k
                    MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
3864
3865
50.5k
                comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3866
50.5k
                decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3867
50.5k
                local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3868
50.5k
                filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3869
50.5k
                ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
3870
3871
50.5k
                if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
3872
44.3k
                    (ext_data_size) &&
3873
4.41k
                    (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
3874
1.16k
                {
3875
                    /* Attempt to find zip64 extended information field in the entry's extra data */
3876
1.16k
                    mz_uint32 extra_size_remaining = ext_data_size;
3877
3878
1.16k
                    if (extra_size_remaining)
3879
1.16k
                    {
3880
1.16k
                        const mz_uint8 *pExtra_data;
3881
1.16k
                        void *buf = NULL;
3882
3883
1.16k
                        if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n)
3884
89
                        {
3885
89
                            buf = MZ_MALLOC(ext_data_size);
3886
89
                            if (buf == NULL)
3887
0
                                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3888
3889
89
                            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
40
                            {
3891
40
                                MZ_FREE(buf);
3892
40
                                return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3893
40
                            }
3894
3895
49
                            pExtra_data = (mz_uint8 *)buf;
3896
49
                        }
3897
1.07k
                        else
3898
1.07k
                        {
3899
1.07k
                            pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
3900
1.07k
                        }
3901
3902
1.12k
                        do
3903
2.36k
                        {
3904
2.36k
                            mz_uint32 field_id;
3905
2.36k
                            mz_uint32 field_data_size;
3906
3907
2.36k
                            if (extra_size_remaining < (sizeof(mz_uint16) * 2))
3908
12
                            {
3909
12
                                MZ_FREE(buf);
3910
12
                                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3911
12
                            }
3912
3913
2.35k
                            field_id = MZ_READ_LE16(pExtra_data);
3914
2.35k
                            field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
3915
3916
2.35k
                            if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
3917
38
                            {
3918
38
                                MZ_FREE(buf);
3919
38
                                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3920
38
                            }
3921
3922
2.31k
                            if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
3923
749
                            {
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
749
                                pZip->m_pState->m_zip64 = MZ_TRUE;
3926
749
                                pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
3927
749
                                break;
3928
749
                            }
3929
3930
1.56k
                            pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
3931
1.56k
                            extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
3932
1.56k
                        } while (extra_size_remaining);
3933
3934
1.07k
                        MZ_FREE(buf);
3935
1.07k
                    }
3936
1.16k
                }
3937
3938
                /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */
3939
50.4k
                if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
3940
29.8k
                {
3941
29.8k
                    if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
3942
64
                        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3943
29.8k
                }
3944
3945
50.3k
                disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
3946
50.3k
                if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
3947
87
                    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3948
3949
50.3k
                if (comp_size != MZ_UINT32_MAX)
3950
42.4k
                {
3951
42.4k
                    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
78
                        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3953
42.4k
                }
3954
3955
50.2k
                bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3956
50.2k
                if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
3957
1
                    return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
3958
3959
50.2k
                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
33
                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3961
3962
50.1k
                n -= total_header_size;
3963
50.1k
                p += total_header_size;
3964
50.1k
            }
3965
12.1k
        }
3966
3967
11.7k
        if (sort_central_dir)
3968
3.50k
            mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
3969
3970
11.7k
        return MZ_TRUE;
3971
12.1k
    }
3972
3973
    void mz_zip_zero_struct(mz_zip_archive *pZip)
3974
16.6k
    {
3975
16.6k
        if (pZip)
3976
16.6k
            MZ_CLEAR_PTR(pZip);
3977
16.6k
    }
3978
3979
    static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
3980
10.5k
    {
3981
10.5k
        mz_bool status = MZ_TRUE;
3982
3983
10.5k
        if (!pZip)
3984
0
            return MZ_FALSE;
3985
3986
10.5k
        if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3987
0
        {
3988
0
            if (set_last_error)
3989
0
                pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;
3990
3991
0
            return MZ_FALSE;
3992
0
        }
3993
3994
10.5k
        if (pZip->m_pState)
3995
10.5k
        {
3996
10.5k
            mz_zip_internal_state *pState = pZip->m_pState;
3997
10.5k
            pZip->m_pState = NULL;
3998
3999
10.5k
            mz_zip_array_clear(pZip, &pState->m_central_dir);
4000
10.5k
            mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
4001
10.5k
            mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
4002
4003
10.5k
#ifndef MINIZ_NO_STDIO
4004
10.5k
            if (pState->m_pFile)
4005
5.79k
            {
4006
5.79k
                if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
4007
5.79k
                {
4008
5.79k
                    if (MZ_FCLOSE(pState->m_pFile) == EOF)
4009
0
                    {
4010
0
                        if (set_last_error)
4011
0
                            pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED;
4012
0
                        status = MZ_FALSE;
4013
0
                    }
4014
5.79k
                }
4015
5.79k
                pState->m_pFile = NULL;
4016
5.79k
            }
4017
10.5k
#endif /* #ifndef MINIZ_NO_STDIO */
4018
4019
10.5k
            pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4020
10.5k
        }
4021
10.5k
        pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
4022
4023
10.5k
        return status;
4024
10.5k
    }
4025
4026
    mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
4027
3.50k
    {
4028
3.50k
        return mz_zip_reader_end_internal(pZip, MZ_TRUE);
4029
3.50k
    }
4030
    mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
4031
0
    {
4032
0
        if ((!pZip) || (!pZip->m_pRead))
4033
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4034
4035
0
        if (!mz_zip_reader_init_internal(pZip, flags))
4036
0
            return MZ_FALSE;
4037
4038
0
        pZip->m_zip_type = MZ_ZIP_TYPE_USER;
4039
0
        pZip->m_archive_size = size;
4040
4041
0
        if (!mz_zip_reader_read_central_dir(pZip, flags))
4042
0
        {
4043
0
            mz_zip_reader_end_internal(pZip, MZ_FALSE);
4044
0
            return MZ_FALSE;
4045
0
        }
4046
4047
0
        return MZ_TRUE;
4048
0
    }
4049
4050
    static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
4051
59.5k
    {
4052
59.5k
        mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
4053
59.5k
        size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
4054
59.5k
        memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
4055
59.5k
        return s;
4056
59.5k
    }
4057
4058
    mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)
4059
4.80k
    {
4060
4.80k
        if (!pMem)
4061
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4062
4063
4.80k
        if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4064
9
            return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4065
4066
4.79k
        if (!mz_zip_reader_init_internal(pZip, flags))
4067
0
            return MZ_FALSE;
4068
4069
4.79k
        pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY;
4070
4.79k
        pZip->m_archive_size = size;
4071
4.79k
        pZip->m_pRead = mz_zip_mem_read_func;
4072
4.79k
        pZip->m_pIO_opaque = pZip;
4073
4.79k
        pZip->m_pNeeds_keepalive = NULL;
4074
4075
#ifdef __cplusplus
4076
        pZip->m_pState->m_pMem = const_cast<void *>(pMem);
4077
#else
4078
4.79k
    pZip->m_pState->m_pMem = (void *)pMem;
4079
4.79k
#endif
4080
4081
4.79k
        pZip->m_pState->m_mem_size = size;
4082
4083
4.79k
        if (!mz_zip_reader_read_central_dir(pZip, flags))
4084
1.29k
        {
4085
1.29k
            mz_zip_reader_end_internal(pZip, MZ_FALSE);
4086
1.29k
            return MZ_FALSE;
4087
1.29k
        }
4088
4089
3.50k
        return MZ_TRUE;
4090
4.79k
    }
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
46.7k
    {
4095
46.7k
        mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
4096
46.7k
        mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
4097
4098
46.7k
        file_ofs += pZip->m_pState->m_file_archive_start_ofs;
4099
4100
46.7k
        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
0
            return 0;
4102
4103
46.7k
        return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
4104
46.7k
    }
4105
4106
    mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
4107
0
    {
4108
0
        return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);
4109
0
    }
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
8.61k
    {
4113
8.61k
        mz_uint64 file_size;
4114
8.61k
        MZ_FILE *pFile;
4115
4116
8.61k
        if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
4117
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4118
4119
8.61k
        pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_READ_ALLOW_WRITING ) ? "r+b" : "rb");
4120
8.61k
        if (!pFile)
4121
201
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
4122
4123
8.41k
        file_size = archive_size;
4124
8.41k
        if (!file_size)
4125
8.41k
        {
4126
8.41k
            if (MZ_FSEEK64(pFile, 0, SEEK_END))
4127
0
            {
4128
0
                MZ_FCLOSE(pFile);
4129
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
4130
0
            }
4131
4132
8.41k
            file_size = MZ_FTELL64(pFile);
4133
8.41k
        }
4134
4135
        /* TODO: Better sanity check archive_size and the # of actual remaining bytes */
4136
4137
8.41k
        if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4138
0
        {
4139
0
            MZ_FCLOSE(pFile);
4140
0
            return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4141
0
        }
4142
4143
8.41k
        if (!mz_zip_reader_init_internal(pZip, flags))
4144
0
        {
4145
0
            MZ_FCLOSE(pFile);
4146
0
            return MZ_FALSE;
4147
0
        }
4148
4149
8.41k
        pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
4150
8.41k
        pZip->m_pRead = mz_zip_file_read_func;
4151
8.41k
        pZip->m_pIO_opaque = pZip;
4152
8.41k
        pZip->m_pState->m_pFile = pFile;
4153
8.41k
        pZip->m_archive_size = file_size;
4154
8.41k
        pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;
4155
4156
8.41k
        if (!mz_zip_reader_read_central_dir(pZip, flags))
4157
194
        {
4158
194
            mz_zip_reader_end_internal(pZip, MZ_FALSE);
4159
194
            return MZ_FALSE;
4160
194
        }
4161
4162
8.22k
        return MZ_TRUE;
4163
8.41k
    }
4164
4165
    mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags)
4166
0
    {
4167
0
        mz_uint64 cur_file_ofs;
4168
4169
0
        if ((!pZip) || (!pFile))
4170
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
4171
4172
0
        cur_file_ofs = MZ_FTELL64(pFile);
4173
4174
0
        if (!archive_size)
4175
0
        {
4176
0
            if (MZ_FSEEK64(pFile, 0, SEEK_END))
4177
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
4178
4179
0
            archive_size = MZ_FTELL64(pFile) - cur_file_ofs;
4180
4181
0
            if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4182
0
                return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4183
0
        }
4184
4185
0
        if (!mz_zip_reader_init_internal(pZip, flags))
4186
0
            return MZ_FALSE;
4187
4188
0
        pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
4189
0
        pZip->m_pRead = mz_zip_file_read_func;
4190
4191
0
        pZip->m_pIO_opaque = pZip;
4192
0
        pZip->m_pState->m_pFile = pFile;
4193
0
        pZip->m_archive_size = archive_size;
4194
0
        pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;
4195
4196
0
        if (!mz_zip_reader_read_central_dir(pZip, flags))
4197
0
        {
4198
0
            mz_zip_reader_end_internal(pZip, MZ_FALSE);
4199
0
            return MZ_FALSE;
4200
0
        }
4201
4202
0
        return MZ_TRUE;
4203
0
    }
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
469k
    {
4209
469k
        if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
4210
0
            return NULL;
4211
469k
        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
469k
    }
4213
4214
    mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
4215
125k
    {
4216
125k
        mz_uint m_bit_flag;
4217
125k
        const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4218
125k
        if (!p)
4219
0
        {
4220
0
            mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4221
0
            return MZ_FALSE;
4222
0
        }
4223
4224
125k
        m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4225
125k
        return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;
4226
125k
    }
4227
4228
    mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)
4229
93.0k
    {
4230
93.0k
        mz_uint bit_flag;
4231
93.0k
        mz_uint method;
4232
4233
93.0k
        const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4234
93.0k
        if (!p)
4235
0
        {
4236
0
            mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4237
0
            return MZ_FALSE;
4238
0
        }
4239
4240
93.0k
        method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4241
93.0k
        bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4242
4243
93.0k
        if ((method != 0) && (method != MZ_DEFLATED))
4244
9.21k
        {
4245
9.21k
            mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4246
9.21k
            return MZ_FALSE;
4247
9.21k
        }
4248
4249
83.8k
        if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION))
4250
2.89k
        {
4251
2.89k
            mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4252
2.89k
            return MZ_FALSE;
4253
2.89k
        }
4254
4255
80.9k
        if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)
4256
4.74k
        {
4257
4.74k
            mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
4258
4.74k
            return MZ_FALSE;
4259
4.74k
        }
4260
4261
76.2k
        return MZ_TRUE;
4262
80.9k
    }
4263
4264
    mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
4265
127k
    {
4266
127k
        mz_uint filename_len, attribute_mapping_id, external_attr;
4267
127k
        const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4268
127k
        if (!p)
4269
0
        {
4270
0
            mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4271
0
            return MZ_FALSE;
4272
0
        }
4273
4274
127k
        filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4275
127k
        if (filename_len)
4276
36.5k
        {
4277
36.5k
            if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
4278
1.20k
                return MZ_TRUE;
4279
36.5k
        }
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
126k
        attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
4285
126k
        (void)attribute_mapping_id;
4286
4287
126k
        external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4288
126k
        if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
4289
4.08k
        {
4290
4.08k
            return MZ_TRUE;
4291
4.08k
        }
4292
4293
122k
        return MZ_FALSE;
4294
126k
    }
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
93.0k
    {
4298
93.0k
        mz_uint n;
4299
93.0k
        const mz_uint8 *p = pCentral_dir_header;
4300
4301
93.0k
        if (pFound_zip64_extra_data)
4302
32.2k
            *pFound_zip64_extra_data = MZ_FALSE;
4303
4304
93.0k
        if ((!p) || (!pStat))
4305
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4306
4307
        /* Extract fields from the central directory record. */
4308
93.0k
        pStat->m_file_index = file_index;
4309
93.0k
        pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
4310
93.0k
        pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
4311
93.0k
        pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
4312
93.0k
        pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4313
93.0k
        pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4314
93.0k
#ifndef MINIZ_NO_TIME
4315
93.0k
        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
93.0k
#endif
4317
93.0k
        pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
4318
93.0k
        pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4319
93.0k
        pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4320
93.0k
        pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
4321
93.0k
        pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4322
93.0k
        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
93.0k
        n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4326
93.0k
        n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
4327
93.0k
        memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
4328
93.0k
        pStat->m_filename[n] = '\0';
4329
4330
93.0k
        n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4331
93.0k
        n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
4332
93.0k
        pStat->m_comment_size = n;
4333
93.0k
        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
93.0k
        pStat->m_comment[n] = '\0';
4335
4336
        /* Set some flags for convienance */
4337
93.0k
        pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
4338
93.0k
        pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
4339
93.0k
        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
93.0k
        if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX)
4344
45.1k
        {
4345
            /* Attempt to find zip64 extended information field in the entry's extra data */
4346
45.1k
            mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4347
4348
45.1k
            if (extra_size_remaining)
4349
6.98k
            {
4350
6.98k
                const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4351
4352
6.98k
                do
4353
8.31k
                {
4354
8.31k
                    mz_uint32 field_id;
4355
8.31k
                    mz_uint32 field_data_size;
4356
4357
8.31k
                    if (extra_size_remaining < (sizeof(mz_uint16) * 2))
4358
325
                        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4359
4360
7.99k
                    field_id = MZ_READ_LE16(pExtra_data);
4361
7.99k
                    field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4362
4363
7.99k
                    if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
4364
1.03k
                        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4365
4366
6.95k
                    if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
4367
4.28k
                    {
4368
4.28k
                        const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
4369
4.28k
                        mz_uint32 field_data_remaining = field_data_size;
4370
4371
4.28k
                        if (pFound_zip64_extra_data)
4372
1.39k
                            *pFound_zip64_extra_data = MZ_TRUE;
4373
4374
4.28k
                        if (pStat->m_uncomp_size == MZ_UINT32_MAX)
4375
1.98k
                        {
4376
1.98k
                            if (field_data_remaining < sizeof(mz_uint64))
4377
1.07k
                                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4378
4379
907
                            pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
4380
907
                            pField_data += sizeof(mz_uint64);
4381
907
                            field_data_remaining -= sizeof(mz_uint64);
4382
907
                        }
4383
4384
3.20k
                        if (pStat->m_comp_size == MZ_UINT32_MAX)
4385
2.30k
                        {
4386
2.30k
                            if (field_data_remaining < sizeof(mz_uint64))
4387
643
                                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4388
4389
1.66k
                            pStat->m_comp_size = MZ_READ_LE64(pField_data);
4390
1.66k
                            pField_data += sizeof(mz_uint64);
4391
1.66k
                            field_data_remaining -= sizeof(mz_uint64);
4392
1.66k
                        }
4393
4394
2.55k
                        if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
4395
605
                        {
4396
605
                            if (field_data_remaining < sizeof(mz_uint64))
4397
218
                                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4398
4399
387
                            pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
4400
387
                            pField_data += sizeof(mz_uint64);
4401
387
                            field_data_remaining -= sizeof(mz_uint64);
4402
387
                        }
4403
4404
2.34k
                        break;
4405
2.55k
                    }
4406
4407
2.67k
                    pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4408
2.67k
                    extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4409
2.67k
                } while (extra_size_remaining);
4410
6.98k
            }
4411
45.1k
        }
4412
4413
89.7k
        return MZ_TRUE;
4414
93.0k
    }
4415
4416
    static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
4417
5.89k
    {
4418
5.89k
        mz_uint i;
4419
5.89k
        if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
4420
1.56k
            return 0 == memcmp(pA, pB, len);
4421
719k
        for (i = 0; i < len; ++i)
4422
715k
            if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
4423
390
                return MZ_FALSE;
4424
3.93k
        return MZ_TRUE;
4425
4.32k
    }
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
41.4k
    {
4429
41.4k
        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
41.4k
        mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4431
41.4k
        mz_uint8 l = 0, r = 0;
4432
41.4k
        pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4433
41.4k
        pE = pL + MZ_MIN(l_len, r_len);
4434
84.1k
        while (pL < pE)
4435
51.3k
        {
4436
51.3k
            if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4437
8.55k
                break;
4438
42.7k
            pL++;
4439
42.7k
            pR++;
4440
42.7k
        }
4441
41.4k
        return (pL == pE) ? (int)(l_len - r_len) : (l - r);
4442
41.4k
    }
4443
4444
    static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
4445
26.6k
    {
4446
26.6k
        mz_zip_internal_state *pState = pZip->m_pState;
4447
26.6k
        const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4448
26.6k
        const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4449
26.6k
        mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4450
26.6k
        const mz_uint32 size = pZip->m_total_files;
4451
26.6k
        const mz_uint filename_len = (mz_uint)strlen(pFilename);
4452
4453
26.6k
        if (pIndex)
4454
26.6k
            *pIndex = 0;
4455
4456
26.6k
        if (size)
4457
26.6k
        {
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
26.6k
            mz_int64 l = 0, h = (mz_int64)size - 1;
4461
4462
42.5k
            while (l <= h)
4463
41.4k
            {
4464
41.4k
                mz_int64 m = l + ((h - l) >> 1);
4465
41.4k
                mz_uint32 file_index = pIndices[(mz_uint32)m];
4466
4467
41.4k
                int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
4468
41.4k
                if (!comp)
4469
25.5k
                {
4470
25.5k
                    if (pIndex)
4471
25.5k
                        *pIndex = file_index;
4472
25.5k
                    return MZ_TRUE;
4473
25.5k
                }
4474
15.9k
                else if (comp < 0)
4475
6.55k
                    l = m + 1;
4476
9.35k
                else
4477
9.35k
                    h = m - 1;
4478
41.4k
            }
4479
26.6k
        }
4480
4481
1.18k
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4482
26.6k
    }
4483
4484
    int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
4485
0
    {
4486
0
        mz_uint32 index;
4487
0
        if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
4488
0
            return -1;
4489
0
        else
4490
0
            return (int)index;
4491
0
    }
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
32.2k
    {
4495
32.2k
        mz_uint file_index;
4496
32.2k
        size_t name_len, comment_len;
4497
4498
32.2k
        if (pIndex)
4499
32.2k
            *pIndex = 0;
4500
4501
32.2k
        if ((!pZip) || (!pZip->m_pState) || (!pName))
4502
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4503
4504
        /* See if we can use a binary search */
4505
32.2k
        if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&
4506
26.6k
            (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
4507
26.6k
            ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
4508
26.6k
        {
4509
26.6k
            return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
4510
26.6k
        }
4511
4512
        /* Locate the entry by scanning the entire central directory */
4513
5.56k
        name_len = strlen(pName);
4514
5.56k
        if (name_len > MZ_UINT16_MAX)
4515
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4516
4517
5.56k
        comment_len = pComment ? strlen(pComment) : 0;
4518
5.56k
        if (comment_len > MZ_UINT16_MAX)
4519
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4520
4521
8.78k
        for (file_index = 0; file_index < pZip->m_total_files; file_index++)
4522
8.44k
        {
4523
8.44k
            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
8.44k
            mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4525
8.44k
            const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4526
8.44k
            if (filename_len < name_len)
4527
1.23k
                continue;
4528
7.21k
            if (comment_len)
4529
0
            {
4530
0
                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
0
                const char *pFile_comment = pFilename + filename_len + file_extra_len;
4532
0
                if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
4533
0
                    continue;
4534
0
            }
4535
7.21k
            if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
4536
1.04k
            {
4537
1.04k
                int ofs = filename_len - 1;
4538
1.04k
                do
4539
133k
                {
4540
133k
                    if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
4541
360
                        break;
4542
133k
                } while (--ofs >= 0);
4543
1.04k
                ofs++;
4544
1.04k
                pFilename += ofs;
4545
1.04k
                filename_len -= ofs;
4546
1.04k
            }
4547
7.21k
            if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
4548
5.22k
            {
4549
5.22k
                if (pIndex)
4550
5.22k
                    *pIndex = file_index;
4551
5.22k
                return MZ_TRUE;
4552
5.22k
            }
4553
7.21k
        }
4554
4555
339
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4556
5.56k
    }
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
30.7k
    {
4560
30.7k
        int status = TINFL_STATUS_DONE;
4561
30.7k
        mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
4562
30.7k
        mz_zip_archive_file_stat file_stat;
4563
30.7k
        void *pRead_buf;
4564
30.7k
        mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4565
30.7k
        mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4566
30.7k
        tinfl_decompressor inflator;
4567
4568
30.7k
        if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
4569
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4570
4571
30.7k
        if (st)
4572
5.22k
        {
4573
5.22k
            file_stat = *st;
4574
5.22k
        }
4575
25.5k
        else if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4576
1.06k
            return MZ_FALSE;
4577
4578
        /* A directory or zero length file */
4579
29.6k
        if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4580
5.77k
            return MZ_TRUE;
4581
4582
        /* Encryption and patch files are not supported. */
4583
23.8k
        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
1.66k
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4585
4586
        /* This function only supports decompressing stored and deflate. */
4587
22.2k
        if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4588
782
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4589
4590
        /* Ensure supplied output buffer is large enough. */
4591
21.4k
        needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
4592
21.4k
        if (buf_size < needed_size)
4593
2.86k
            return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);
4594
4595
        /* Read and parse the local directory entry. */
4596
18.5k
        cur_file_ofs = file_stat.m_local_header_ofs;
4597
18.5k
        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
468
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4599
4600
18.1k
        if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4601
824
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4602
4603
17.2k
        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
17.2k
        if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4605
462
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4606
4607
16.8k
        if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4608
3.63k
        {
4609
            /* The file is stored or the caller has requested the compressed data. */
4610
3.63k
            if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
4611
639
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4612
4613
2.99k
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4614
2.99k
            if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
4615
2.63k
            {
4616
2.63k
                if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4617
1.05k
                    return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4618
2.63k
            }
4619
1.93k
#endif
4620
4621
1.93k
            return MZ_TRUE;
4622
2.99k
        }
4623
4624
        /* Decompress the file either directly from memory or from a file input buffer. */
4625
13.1k
        tinfl_init(&inflator);
4626
4627
13.1k
        if (pZip->m_pState->m_pMem)
4628
9.64k
        {
4629
            /* Read directly from the archive in memory. */
4630
9.64k
            pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4631
9.64k
            read_buf_size = read_buf_avail = file_stat.m_comp_size;
4632
9.64k
            comp_remaining = 0;
4633
9.64k
        }
4634
3.54k
        else if (pUser_read_buf)
4635
0
        {
4636
            /* Use a user provided read buffer. */
4637
0
            if (!user_read_buf_size)
4638
0
                return MZ_FALSE;
4639
0
            pRead_buf = (mz_uint8 *)pUser_read_buf;
4640
0
            read_buf_size = user_read_buf_size;
4641
0
            read_buf_avail = 0;
4642
0
            comp_remaining = file_stat.m_comp_size;
4643
0
        }
4644
3.54k
        else
4645
3.54k
        {
4646
            /* Temporarily allocate a read buffer. */
4647
3.54k
            read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4648
3.54k
            if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
4649
0
                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4650
4651
3.54k
            if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4652
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4653
4654
3.54k
            read_buf_avail = 0;
4655
3.54k
            comp_remaining = file_stat.m_comp_size;
4656
3.54k
        }
4657
4658
13.1k
        do
4659
14.5k
        {
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
14.5k
            size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
4662
14.5k
            if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4663
4.90k
            {
4664
4.90k
                read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4665
4.90k
                if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4666
0
                {
4667
0
                    status = TINFL_STATUS_FAILED;
4668
0
                    mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4669
0
                    break;
4670
0
                }
4671
4.90k
                cur_file_ofs += read_buf_avail;
4672
4.90k
                comp_remaining -= read_buf_avail;
4673
4.90k
                read_buf_ofs = 0;
4674
4.90k
            }
4675
14.5k
            in_buf_size = (size_t)read_buf_avail;
4676
14.5k
            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
14.5k
            read_buf_avail -= in_buf_size;
4678
14.5k
            read_buf_ofs += in_buf_size;
4679
14.5k
            out_buf_ofs += out_buf_size;
4680
14.5k
        } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
4681
4682
13.1k
        if (status == TINFL_STATUS_DONE)
4683
3.99k
        {
4684
            /* Make sure the entire file was decompressed, and check its CRC. */
4685
3.99k
            if (out_buf_ofs != file_stat.m_uncomp_size)
4686
576
            {
4687
576
                mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4688
576
                status = TINFL_STATUS_FAILED;
4689
576
            }
4690
3.42k
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4691
3.42k
            else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4692
213
            {
4693
213
                mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4694
213
                status = TINFL_STATUS_FAILED;
4695
213
            }
4696
3.99k
#endif
4697
3.99k
        }
4698
4699
13.1k
        if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
4700
3.54k
            pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4701
4702
13.1k
        return status == TINFL_STATUS_DONE;
4703
13.1k
    }
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
0
    {
4707
0
        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
0
    }
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
26.6k
    {
4712
26.6k
        mz_uint32 file_index;
4713
26.6k
        if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4714
1.18k
            return MZ_FALSE;
4715
25.5k
        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
26.6k
    }
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
0
    {
4720
0
        return mz_zip_reader_extract_to_mem_no_alloc1(pZip, file_index, pBuf, buf_size, flags, NULL, 0, NULL);
4721
0
    }
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
26.6k
    {
4725
26.6k
        return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
4726
26.6k
    }
4727
4728
    void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
4729
5.22k
    {
4730
5.22k
        mz_zip_archive_file_stat file_stat;
4731
5.22k
        mz_uint64 alloc_size;
4732
5.22k
        void *pBuf;
4733
4734
5.22k
        if (pSize)
4735
5.22k
            *pSize = 0;
4736
4737
5.22k
        if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4738
0
            return NULL;
4739
4740
5.22k
        alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
4741
5.22k
        if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
4742
0
        {
4743
0
            mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4744
0
            return NULL;
4745
0
        }
4746
4747
5.22k
        if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
4748
0
        {
4749
0
            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4750
0
            return NULL;
4751
0
        }
4752
4753
5.22k
        if (!mz_zip_reader_extract_to_mem_no_alloc1(pZip, file_index, pBuf, (size_t)alloc_size, flags, NULL, 0, &file_stat))
4754
541
        {
4755
541
            pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4756
541
            return NULL;
4757
541
        }
4758
4759
4.68k
        if (pSize)
4760
4.68k
            *pSize = (size_t)alloc_size;
4761
4.68k
        return pBuf;
4762
5.22k
    }
4763
4764
    void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
4765
0
    {
4766
0
        mz_uint32 file_index;
4767
0
        if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4768
0
        {
4769
0
            if (pSize)
4770
0
                *pSize = 0;
4771
0
            return MZ_FALSE;
4772
0
        }
4773
0
        return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
4774
0
    }
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
0
    {
4778
0
        int status = TINFL_STATUS_DONE;
4779
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4780
0
        mz_uint file_crc32 = MZ_CRC32_INIT;
4781
0
#endif
4782
0
        mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
4783
0
        mz_zip_archive_file_stat file_stat;
4784
0
        void *pRead_buf = NULL;
4785
0
        void *pWrite_buf = NULL;
4786
0
        mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4787
0
        mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4788
4789
0
        if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))
4790
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4791
4792
0
        if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4793
0
            return MZ_FALSE;
4794
4795
        /* A directory or zero length file */
4796
0
        if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4797
0
            return MZ_TRUE;
4798
4799
        /* Encryption and patch files are not supported. */
4800
0
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4802
4803
        /* This function only supports decompressing stored and deflate. */
4804
0
        if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4805
0
            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
0
        cur_file_ofs = file_stat.m_local_header_ofs;
4809
0
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4811
4812
0
        if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4813
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4814
4815
0
        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
0
        if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4817
0
            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
0
        if (pZip->m_pState->m_pMem)
4821
0
        {
4822
0
            pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4823
0
            read_buf_size = read_buf_avail = file_stat.m_comp_size;
4824
0
            comp_remaining = 0;
4825
0
        }
4826
0
        else
4827
0
        {
4828
0
            read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4829
0
            if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4830
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4831
4832
0
            read_buf_avail = 0;
4833
0
            comp_remaining = file_stat.m_comp_size;
4834
0
        }
4835
4836
0
        if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4837
0
        {
4838
            /* The file is stored or the caller has requested the compressed data. */
4839
0
            if (pZip->m_pState->m_pMem)
4840
0
            {
4841
0
                if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX))
4842
0
                    return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4843
4844
0
                if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
4845
0
                {
4846
0
                    mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4847
0
                    status = TINFL_STATUS_FAILED;
4848
0
                }
4849
0
                else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4850
0
                {
4851
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4852
0
                    file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
4853
0
#endif
4854
0
                }
4855
4856
0
                cur_file_ofs += file_stat.m_comp_size;
4857
0
                out_buf_ofs += file_stat.m_comp_size;
4858
0
                comp_remaining = 0;
4859
0
            }
4860
0
            else
4861
0
            {
4862
0
                while (comp_remaining)
4863
0
                {
4864
0
                    read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4865
0
                    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4866
0
                    {
4867
0
                        mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4868
0
                        status = TINFL_STATUS_FAILED;
4869
0
                        break;
4870
0
                    }
4871
4872
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4873
0
                    if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4874
0
                    {
4875
0
                        file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
4876
0
                    }
4877
0
#endif
4878
4879
0
                    if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4880
0
                    {
4881
0
                        mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4882
0
                        status = TINFL_STATUS_FAILED;
4883
0
                        break;
4884
0
                    }
4885
4886
0
                    cur_file_ofs += read_buf_avail;
4887
0
                    out_buf_ofs += read_buf_avail;
4888
0
                    comp_remaining -= read_buf_avail;
4889
0
                }
4890
0
            }
4891
0
        }
4892
0
        else
4893
0
        {
4894
0
            tinfl_decompressor inflator;
4895
0
            tinfl_init(&inflator);
4896
4897
0
            if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4898
0
            {
4899
0
                mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4900
0
                status = TINFL_STATUS_FAILED;
4901
0
            }
4902
0
            else
4903
0
            {
4904
0
                do
4905
0
                {
4906
0
                    mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4907
0
                    size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4908
0
                    if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4909
0
                    {
4910
0
                        read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4911
0
                        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4912
0
                        {
4913
0
                            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4914
0
                            status = TINFL_STATUS_FAILED;
4915
0
                            break;
4916
0
                        }
4917
0
                        cur_file_ofs += read_buf_avail;
4918
0
                        comp_remaining -= read_buf_avail;
4919
0
                        read_buf_ofs = 0;
4920
0
                    }
4921
4922
0
                    in_buf_size = (size_t)read_buf_avail;
4923
0
                    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
0
                    read_buf_avail -= in_buf_size;
4925
0
                    read_buf_ofs += in_buf_size;
4926
4927
0
                    if (out_buf_size)
4928
0
                    {
4929
0
                        if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
4930
0
                        {
4931
0
                            mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4932
0
                            status = TINFL_STATUS_FAILED;
4933
0
                            break;
4934
0
                        }
4935
4936
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4937
0
                        file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
4938
0
#endif
4939
0
                        if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
4940
0
                        {
4941
0
                            mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4942
0
                            status = TINFL_STATUS_FAILED;
4943
0
                            break;
4944
0
                        }
4945
0
                    }
4946
0
                } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
4947
0
            }
4948
0
        }
4949
4950
0
        if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
4951
0
        {
4952
            /* Make sure the entire file was decompressed, and check its CRC. */
4953
0
            if (out_buf_ofs != file_stat.m_uncomp_size)
4954
0
            {
4955
0
                mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4956
0
                status = TINFL_STATUS_FAILED;
4957
0
            }
4958
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4959
0
            else if (file_crc32 != file_stat.m_crc32)
4960
0
            {
4961
0
                mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4962
0
                status = TINFL_STATUS_FAILED;
4963
0
            }
4964
0
#endif
4965
0
        }
4966
4967
0
        if (!pZip->m_pState->m_pMem)
4968
0
            pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4969
4970
0
        if (pWrite_buf)
4971
0
            pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
4972
4973
0
        return status == TINFL_STATUS_DONE;
4974
0
    }
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
0
    {
4978
0
        mz_uint32 file_index;
4979
0
        if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4980
0
            return MZ_FALSE;
4981
4982
0
        return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
4983
0
    }
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
0
    {
4987
0
        mz_zip_reader_extract_iter_state *pState;
4988
0
        mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4989
0
        mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4990
4991
        /* Argument sanity check */
4992
0
        if ((!pZip) || (!pZip->m_pState))
4993
0
            return NULL;
4994
4995
        /* Allocate an iterator status structure */
4996
0
        pState = (mz_zip_reader_extract_iter_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_reader_extract_iter_state));
4997
0
        if (!pState)
4998
0
        {
4999
0
            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5000
0
            return NULL;
5001
0
        }
5002
5003
        /* Fetch file details */
5004
0
        if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat))
5005
0
        {
5006
0
            pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5007
0
            return NULL;
5008
0
        }
5009
5010
        /* Encryption and patch files are not supported. */
5011
0
        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
0
        {
5013
0
            mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
5014
0
            pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5015
0
            return NULL;
5016
0
        }
5017
5018
        /* This function only supports decompressing stored and deflate. */
5019
0
        if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (pState->file_stat.m_method != 0) && (pState->file_stat.m_method != MZ_DEFLATED))
5020
0
        {
5021
0
            mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
5022
0
            pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5023
0
            return NULL;
5024
0
        }
5025
5026
        /* Init state - save args */
5027
0
        pState->pZip = pZip;
5028
0
        pState->flags = flags;
5029
5030
        /* Init state - reset variables to defaults */
5031
0
        pState->status = TINFL_STATUS_DONE;
5032
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5033
0
        pState->file_crc32 = MZ_CRC32_INIT;
5034
0
#endif
5035
0
        pState->read_buf_ofs = 0;
5036
0
        pState->out_buf_ofs = 0;
5037
0
        pState->pRead_buf = NULL;
5038
0
        pState->pWrite_buf = NULL;
5039
0
        pState->out_blk_remain = 0;
5040
5041
        /* Read and parse the local directory entry. */
5042
0
        pState->cur_file_ofs = pState->file_stat.m_local_header_ofs;
5043
0
        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
0
        {
5045
0
            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5046
0
            pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5047
0
            return NULL;
5048
0
        }
5049
5050
0
        if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5051
0
        {
5052
0
            mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5053
0
            pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5054
0
            return NULL;
5055
0
        }
5056
5057
0
        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
0
        if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > pZip->m_archive_size)
5059
0
        {
5060
0
            mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5061
0
            pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5062
0
            return NULL;
5063
0
        }
5064
5065
        /* Decompress the file either directly from memory or from a file input buffer. */
5066
0
        if (pZip->m_pState->m_pMem)
5067
0
        {
5068
0
            pState->pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs;
5069
0
            pState->read_buf_size = pState->read_buf_avail = pState->file_stat.m_comp_size;
5070
0
            pState->comp_remaining = pState->file_stat.m_comp_size;
5071
0
        }
5072
0
        else
5073
0
        {
5074
0
            if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
5075
0
            {
5076
                /* Decompression required, therefore intermediate read buffer required */
5077
0
                pState->read_buf_size = MZ_MIN(pState->file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
5078
0
                if (NULL == (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)pState->read_buf_size)))
5079
0
                {
5080
0
                    mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5081
0
                    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5082
0
                    return NULL;
5083
0
                }
5084
0
            }
5085
0
            else
5086
0
            {
5087
                /* Decompression not required - we will be reading directly into user buffer, no temp buf required */
5088
0
                pState->read_buf_size = 0;
5089
0
            }
5090
0
            pState->read_buf_avail = 0;
5091
0
            pState->comp_remaining = pState->file_stat.m_comp_size;
5092
0
        }
5093
5094
0
        if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
5095
0
        {
5096
            /* Decompression required, init decompressor */
5097
0
            tinfl_init(&pState->inflator);
5098
5099
            /* Allocate write buffer */
5100
0
            if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
5101
0
            {
5102
0
                mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5103
0
                if (pState->pRead_buf)
5104
0
                    pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf);
5105
0
                pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5106
0
                return NULL;
5107
0
            }
5108
0
        }
5109
5110
0
        return pState;
5111
0
    }
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
0
    {
5115
0
        mz_uint32 file_index;
5116
5117
        /* Locate file index by name */
5118
0
        if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
5119
0
            return NULL;
5120
5121
        /* Construct iterator */
5122
0
        return mz_zip_reader_extract_iter_new(pZip, file_index, flags);
5123
0
    }
5124
5125
    size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state *pState, void *pvBuf, size_t buf_size)
5126
0
    {
5127
0
        size_t copied_to_caller = 0;
5128
5129
        /* Argument sanity check */
5130
0
        if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf))
5131
0
            return 0;
5132
5133
0
        if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))
5134
0
        {
5135
            /* The file is stored or the caller has requested the compressed data, calc amount to return. */
5136
0
            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
0
            if (pState->pZip->m_pState->m_pMem)
5140
0
            {
5141
                /* Copy data to caller's buffer */
5142
0
                memcpy(pvBuf, pState->pRead_buf, copied_to_caller);
5143
0
                pState->pRead_buf = ((mz_uint8 *)pState->pRead_buf) + copied_to_caller;
5144
0
            }
5145
0
            else
5146
0
            {
5147
                /* Read directly into caller's buffer */
5148
0
                if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, copied_to_caller) != copied_to_caller)
5149
0
                {
5150
                    /* Failed to read all that was asked for, flag failure and alert user */
5151
0
                    mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
5152
0
                    pState->status = TINFL_STATUS_FAILED;
5153
0
                    copied_to_caller = 0;
5154
0
                }
5155
0
            }
5156
5157
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5158
            /* Compute CRC if not returning compressed data only */
5159
0
            if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5160
0
                pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, (const mz_uint8 *)pvBuf, copied_to_caller);
5161
0
#endif
5162
5163
            /* Advance offsets, dec counters */
5164
0
            pState->cur_file_ofs += copied_to_caller;
5165
0
            pState->out_buf_ofs += copied_to_caller;
5166
0
            pState->comp_remaining -= copied_to_caller;
5167
0
        }
5168
0
        else
5169
0
        {
5170
0
            do
5171
0
            {
5172
                /* Calc ptr to write buffer - given current output pos and block size */
5173
0
                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
0
                size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5177
5178
0
                if (!pState->out_blk_remain)
5179
0
                {
5180
                    /* Read more data from file if none available (and reading from file) */
5181
0
                    if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem))
5182
0
                    {
5183
                        /* Calc read size */
5184
0
                        pState->read_buf_avail = MZ_MIN(pState->read_buf_size, pState->comp_remaining);
5185
0
                        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
0
                        {
5187
0
                            mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
5188
0
                            pState->status = TINFL_STATUS_FAILED;
5189
0
                            break;
5190
0
                        }
5191
5192
                        /* Advance offsets, dec counters */
5193
0
                        pState->cur_file_ofs += pState->read_buf_avail;
5194
0
                        pState->comp_remaining -= pState->read_buf_avail;
5195
0
                        pState->read_buf_ofs = 0;
5196
0
                    }
5197
5198
                    /* Perform decompression */
5199
0
                    in_buf_size = (size_t)pState->read_buf_avail;
5200
0
                    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
0
                    pState->read_buf_avail -= in_buf_size;
5202
0
                    pState->read_buf_ofs += in_buf_size;
5203
5204
                    /* Update current output block size remaining */
5205
0
                    pState->out_blk_remain = out_buf_size;
5206
0
                }
5207
5208
0
                if (pState->out_blk_remain)
5209
0
                {
5210
                    /* Calc amount to return. */
5211
0
                    size_t to_copy = MZ_MIN((buf_size - copied_to_caller), pState->out_blk_remain);
5212
5213
                    /* Copy data to caller's buffer */
5214
0
                    memcpy((mz_uint8 *)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy);
5215
5216
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5217
                    /* Perform CRC */
5218
0
                    pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy);
5219
0
#endif
5220
5221
                    /* Decrement data consumed from block */
5222
0
                    pState->out_blk_remain -= to_copy;
5223
5224
                    /* Inc output offset, while performing sanity check */
5225
0
                    if ((pState->out_buf_ofs += to_copy) > pState->file_stat.m_uncomp_size)
5226
0
                    {
5227
0
                        mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5228
0
                        pState->status = TINFL_STATUS_FAILED;
5229
0
                        break;
5230
0
                    }
5231
5232
                    /* Increment counter of data copied to caller */
5233
0
                    copied_to_caller += to_copy;
5234
0
                }
5235
0
            } while ((copied_to_caller < buf_size) && ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)));
5236
0
        }
5237
5238
        /* Return how many bytes were copied into user buffer */
5239
0
        return copied_to_caller;
5240
0
    }
5241
5242
    mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state *pState)
5243
0
    {
5244
0
        int status;
5245
5246
        /* Argument sanity check */
5247
0
        if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState))
5248
0
            return MZ_FALSE;
5249
5250
        /* Was decompression completed and requested? */
5251
0
        if ((pState->status == TINFL_STATUS_DONE) && (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
5252
0
        {
5253
            /* Make sure the entire file was decompressed, and check its CRC. */
5254
0
            if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size)
5255
0
            {
5256
0
                mz_zip_set_error(pState->pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
5257
0
                pState->status = TINFL_STATUS_FAILED;
5258
0
            }
5259
0
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5260
0
            else if (pState->file_crc32 != pState->file_stat.m_crc32)
5261
0
            {
5262
0
                mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5263
0
                pState->status = TINFL_STATUS_FAILED;
5264
0
            }
5265
0
#endif
5266
0
        }
5267
5268
        /* Free buffers */
5269
0
        if (!pState->pZip->m_pState->m_pMem)
5270
0
            pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf);
5271
0
        if (pState->pWrite_buf)
5272
0
            pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf);
5273
5274
        /* Save status */
5275
0
        status = pState->status;
5276
5277
        /* Free context */
5278
0
        pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState);
5279
5280
0
        return status == TINFL_STATUS_DONE;
5281
0
    }
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
0
    {
5286
0
        (void)ofs;
5287
5288
0
        return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5289
0
    }
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
0
    {
5293
0
        mz_bool status;
5294
0
        mz_zip_archive_file_stat file_stat;
5295
0
        MZ_FILE *pFile;
5296
5297
0
        if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5298
0
            return MZ_FALSE;
5299
5300
0
        if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5301
0
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5302
5303
0
        pFile = MZ_FOPEN(pDst_filename, "wb");
5304
0
        if (!pFile)
5305
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5306
5307
0
        status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5308
5309
0
        if (MZ_FCLOSE(pFile) == EOF)
5310
0
        {
5311
0
            if (status)
5312
0
                mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5313
5314
0
            status = MZ_FALSE;
5315
0
        }
5316
5317
0
#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
5318
0
        if (status)
5319
0
            mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5320
0
#endif
5321
5322
0
        return status;
5323
0
    }
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
0
    {
5327
0
        mz_uint32 file_index;
5328
0
        if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5329
0
            return MZ_FALSE;
5330
5331
0
        return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5332
0
    }
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
0
    {
5336
0
        mz_zip_archive_file_stat file_stat;
5337
5338
0
        if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5339
0
            return MZ_FALSE;
5340
5341
0
        if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5342
0
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5343
5344
0
        return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5345
0
    }
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
0
    {
5349
0
        mz_uint32 file_index;
5350
0
        if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5351
0
            return MZ_FALSE;
5352
5353
0
        return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
5354
0
    }
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
0
    {
5359
0
        mz_uint32 *p = (mz_uint32 *)pOpaque;
5360
0
        (void)file_ofs;
5361
0
        *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n);
5362
0
        return n;
5363
0
    }
5364
5365
    mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
5366
32.2k
    {
5367
32.2k
        mz_zip_archive_file_stat file_stat;
5368
32.2k
        mz_zip_internal_state *pState;
5369
32.2k
        const mz_uint8 *pCentral_dir_header;
5370
32.2k
        mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;
5371
32.2k
        mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
5372
32.2k
        mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
5373
32.2k
        mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5374
32.2k
        mz_uint64 local_header_ofs = 0;
5375
32.2k
        mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32;
5376
32.2k
        mz_uint64 local_header_comp_size, local_header_uncomp_size;
5377
32.2k
        mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;
5378
32.2k
        mz_bool has_data_descriptor;
5379
32.2k
        mz_uint32 local_header_bit_flags;
5380
5381
32.2k
        mz_zip_array file_data_array;
5382
32.2k
        mz_zip_array_init(&file_data_array, 1);
5383
5384
32.2k
        if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5385
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5386
5387
32.2k
        if (file_index > pZip->m_total_files)
5388
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5389
5390
32.2k
        pState = pZip->m_pState;
5391
5392
32.2k
        pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);
5393
5394
32.2k
        if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir))
5395
1.18k
            return MZ_FALSE;
5396
5397
        /* A directory or zero length file */
5398
31.0k
        if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size))
5399
2.04k
            return MZ_TRUE;
5400
5401
        /* Encryption and patch files are not supported. */
5402
29.0k
        if (file_stat.m_is_encrypted)
5403
1.95k
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
5404
5405
        /* This function only supports stored and deflate. */
5406
27.0k
        if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
5407
3.04k
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
5408
5409
24.0k
        if (!file_stat.m_is_supported)
5410
1.52k
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5411
5412
        /* Read and parse the local directory entry. */
5413
22.5k
        local_header_ofs = file_stat.m_local_header_ofs;
5414
22.5k
        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
1.65k
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5416
5417
20.8k
        if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5418
7.85k
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5419
5420
13.0k
        local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
5421
13.0k
        local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5422
13.0k
        local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
5423
13.0k
        local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
5424
13.0k
        local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);
5425
13.0k
        local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
5426
13.0k
        has_data_descriptor = (local_header_bit_flags & 8) != 0;
5427
5428
13.0k
        if (local_header_filename_len != strlen(file_stat.m_filename))
5429
4.12k
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5430
5431
8.87k
        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
372
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5433
5434
8.50k
        if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE))
5435
0
        {
5436
0
            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5437
0
            goto handle_failure;
5438
0
        }
5439
5440
8.50k
        if (local_header_filename_len)
5441
881
        {
5442
881
            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
7
            {
5444
7
                mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5445
7
                goto handle_failure;
5446
7
            }
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
874
            if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0)
5450
629
            {
5451
629
                mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5452
629
                goto handle_failure;
5453
629
            }
5454
874
        }
5455
5456
7.86k
        if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
5457
1.92k
        {
5458
1.92k
            mz_uint32 extra_size_remaining = local_header_extra_len;
5459
1.92k
            const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p;
5460
5461
1.92k
            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
34
            {
5463
34
                mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5464
34
                goto handle_failure;
5465
34
            }
5466
5467
1.88k
            do
5468
5.13k
            {
5469
5.13k
                mz_uint32 field_id, field_data_size, field_total_size;
5470
5471
5.13k
                if (extra_size_remaining < (sizeof(mz_uint16) * 2))
5472
375
                {
5473
375
                    mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5474
375
                    goto handle_failure;
5475
375
                }
5476
5477
4.76k
                field_id = MZ_READ_LE16(pExtra_data);
5478
4.76k
                field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
5479
4.76k
                field_total_size = field_data_size + sizeof(mz_uint16) * 2;
5480
5481
4.76k
                if (field_total_size > extra_size_remaining)
5482
568
                {
5483
568
                    mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5484
568
                    goto handle_failure;
5485
568
                }
5486
5487
4.19k
                if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
5488
696
                {
5489
696
                    const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
5490
5491
696
                    if (field_data_size < sizeof(mz_uint64) * 2)
5492
199
                    {
5493
199
                        mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5494
199
                        goto handle_failure;
5495
199
                    }
5496
5497
497
                    local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
5498
497
                    local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64));
5499
5500
497
                    found_zip64_ext_data_in_ldir = MZ_TRUE;
5501
497
                    break;
5502
696
                }
5503
5504
3.49k
                pExtra_data += field_total_size;
5505
3.49k
                extra_size_remaining -= field_total_size;
5506
3.49k
            } while (extra_size_remaining);
5507
1.88k
        }
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
6.69k
        if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32))
5512
2.30k
        {
5513
2.30k
            mz_uint8 descriptor_buf[32];
5514
2.30k
            mz_bool has_id;
5515
2.30k
            const mz_uint8 *pSrc;
5516
2.30k
            mz_uint32 file_crc32;
5517
2.30k
            mz_uint64 comp_size = 0, uncomp_size = 0;
5518
5519
2.30k
            mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;
5520
5521
2.30k
            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
232
            {
5523
232
                mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5524
232
                goto handle_failure;
5525
232
            }
5526
5527
2.06k
            has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
5528
2.06k
            pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf;
5529
5530
2.06k
            file_crc32 = MZ_READ_LE32(pSrc);
5531
5532
2.06k
            if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir))
5533
534
            {
5534
534
                comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32));
5535
534
                uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64));
5536
534
            }
5537
1.53k
            else
5538
1.53k
            {
5539
1.53k
                comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32));
5540
1.53k
                uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32));
5541
1.53k
            }
5542
5543
2.06k
            if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size))
5544
1.86k
            {
5545
1.86k
                mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5546
1.86k
                goto handle_failure;
5547
1.86k
            }
5548
2.06k
        }
5549
4.39k
        else
5550
4.39k
        {
5551
4.39k
            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
4.06k
            {
5553
4.06k
                mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5554
4.06k
                goto handle_failure;
5555
4.06k
            }
5556
4.39k
        }
5557
5558
540
        mz_zip_array_clear(pZip, &file_data_array);
5559
5560
540
        if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0)
5561
0
        {
5562
0
            if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))
5563
0
                return MZ_FALSE;
5564
5565
            /* 1 more check to be sure, although the extract checks too. */
5566
0
            if (uncomp_crc32 != file_stat.m_crc32)
5567
0
            {
5568
0
                mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5569
0
                return MZ_FALSE;
5570
0
            }
5571
0
        }
5572
5573
540
        return MZ_TRUE;
5574
5575
7.96k
    handle_failure:
5576
7.96k
        mz_zip_array_clear(pZip, &file_data_array);
5577
7.96k
        return MZ_FALSE;
5578
540
    }
5579
5580
    mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags)
5581
0
    {
5582
0
        mz_zip_internal_state *pState;
5583
0
        mz_uint32 i;
5584
5585
0
        if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5586
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5587
5588
0
        pState = pZip->m_pState;
5589
5590
        /* Basic sanity checks */
5591
0
        if (!pState->m_zip64)
5592
0
        {
5593
0
            if (pZip->m_total_files > MZ_UINT16_MAX)
5594
0
                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5595
5596
0
            if (pZip->m_archive_size > MZ_UINT32_MAX)
5597
0
                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5598
0
        }
5599
0
        else
5600
0
        {
5601
0
            if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
5602
0
                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5603
0
        }
5604
5605
0
        for (i = 0; i < pZip->m_total_files; i++)
5606
0
        {
5607
0
            if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags)
5608
0
            {
5609
0
                mz_uint32 found_index;
5610
0
                mz_zip_archive_file_stat stat;
5611
5612
0
                if (!mz_zip_reader_file_stat(pZip, i, &stat))
5613
0
                    return MZ_FALSE;
5614
5615
0
                if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index))
5616
0
                    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
0
                if (found_index != i)
5620
0
                    return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5621
0
            }
5622
5623
0
            if (!mz_zip_validate_file(pZip, i, flags))
5624
0
                return MZ_FALSE;
5625
0
        }
5626
5627
0
        return MZ_TRUE;
5628
0
    }
5629
5630
    mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)
5631
0
    {
5632
0
        mz_bool success = MZ_TRUE;
5633
0
        mz_zip_archive zip;
5634
0
        mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5635
5636
0
        if ((!pMem) || (!size))
5637
0
        {
5638
0
            if (pErr)
5639
0
                *pErr = MZ_ZIP_INVALID_PARAMETER;
5640
0
            return MZ_FALSE;
5641
0
        }
5642
5643
0
        mz_zip_zero_struct(&zip);
5644
5645
0
        if (!mz_zip_reader_init_mem(&zip, pMem, size, flags))
5646
0
        {
5647
0
            if (pErr)
5648
0
                *pErr = zip.m_last_error;
5649
0
            return MZ_FALSE;
5650
0
        }
5651
5652
0
        if (!mz_zip_validate_archive(&zip, flags))
5653
0
        {
5654
0
            actual_err = zip.m_last_error;
5655
0
            success = MZ_FALSE;
5656
0
        }
5657
5658
0
        if (!mz_zip_reader_end_internal(&zip, success))
5659
0
        {
5660
0
            if (!actual_err)
5661
0
                actual_err = zip.m_last_error;
5662
0
            success = MZ_FALSE;
5663
0
        }
5664
5665
0
        if (pErr)
5666
0
            *pErr = actual_err;
5667
5668
0
        return success;
5669
0
    }
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
0
    {
5674
0
        mz_bool success = MZ_TRUE;
5675
0
        mz_zip_archive zip;
5676
0
        mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5677
5678
0
        if (!pFilename)
5679
0
        {
5680
0
            if (pErr)
5681
0
                *pErr = MZ_ZIP_INVALID_PARAMETER;
5682
0
            return MZ_FALSE;
5683
0
        }
5684
5685
0
        mz_zip_zero_struct(&zip);
5686
5687
0
        if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0))
5688
0
        {
5689
0
            if (pErr)
5690
0
                *pErr = zip.m_last_error;
5691
0
            return MZ_FALSE;
5692
0
        }
5693
5694
0
        if (!mz_zip_validate_archive(&zip, flags))
5695
0
        {
5696
0
            actual_err = zip.m_last_error;
5697
0
            success = MZ_FALSE;
5698
0
        }
5699
5700
0
        if (!mz_zip_reader_end_internal(&zip, success))
5701
0
        {
5702
0
            if (!actual_err)
5703
0
                actual_err = zip.m_last_error;
5704
0
            success = MZ_FALSE;
5705
0
        }
5706
5707
0
        if (pErr)
5708
0
            *pErr = actual_err;
5709
5710
0
        return success;
5711
0
    }
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
93.7k
    {
5720
93.7k
        p[0] = (mz_uint8)v;
5721
93.7k
        p[1] = (mz_uint8)(v >> 8);
5722
93.7k
    }
5723
    static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v)
5724
101k
    {
5725
101k
        p[0] = (mz_uint8)v;
5726
101k
        p[1] = (mz_uint8)(v >> 8);
5727
101k
        p[2] = (mz_uint8)(v >> 16);
5728
101k
        p[3] = (mz_uint8)(v >> 24);
5729
101k
    }
5730
    static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v)
5731
4.45k
    {
5732
4.45k
        mz_write_le32(p, (mz_uint32)v);
5733
4.45k
        mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32));
5734
4.45k
    }
5735
5736
93.7k
#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5737
92.2k
#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5738
4.45k
#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
0
    {
5742
0
        mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5743
0
        mz_zip_internal_state *pState = pZip->m_pState;
5744
0
        mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5745
5746
0
        if (!n)
5747
0
            return 0;
5748
5749
        /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */
5750
0
        if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))
5751
0
        {
5752
0
            mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5753
0
            return 0;
5754
0
        }
5755
5756
0
        if (new_size > pState->m_mem_capacity)
5757
0
        {
5758
0
            void *pNew_block;
5759
0
            size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5760
5761
0
            while (new_capacity < new_size)
5762
0
                new_capacity *= 2;
5763
5764
0
            if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5765
0
            {
5766
0
                mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5767
0
                return 0;
5768
0
            }
5769
5770
0
            pState->m_pMem = pNew_block;
5771
0
            pState->m_mem_capacity = new_capacity;
5772
0
        }
5773
0
        memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5774
0
        pState->m_mem_size = (size_t)new_size;
5775
0
        return n;
5776
0
    }
5777
5778
    static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
5779
5.46k
    {
5780
5.46k
        mz_zip_internal_state *pState;
5781
5.46k
        mz_bool status = MZ_TRUE;
5782
5783
5.46k
        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
0
        {
5785
0
            if (set_last_error)
5786
0
                mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5787
0
            return MZ_FALSE;
5788
0
        }
5789
5790
5.46k
        pState = pZip->m_pState;
5791
5.46k
        pZip->m_pState = NULL;
5792
5.46k
        mz_zip_array_clear(pZip, &pState->m_central_dir);
5793
5.46k
        mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5794
5.46k
        mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5795
5796
5.46k
#ifndef MINIZ_NO_STDIO
5797
5.46k
        if (pState->m_pFile)
5798
5.46k
        {
5799
5.46k
            if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5800
5.46k
            {
5801
5.46k
                if (MZ_FCLOSE(pState->m_pFile) == EOF)
5802
0
                {
5803
0
                    if (set_last_error)
5804
0
                        mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5805
0
                    status = MZ_FALSE;
5806
0
                }
5807
5.46k
            }
5808
5809
5.46k
            pState->m_pFile = NULL;
5810
5.46k
        }
5811
5.46k
#endif /* #ifndef MINIZ_NO_STDIO */
5812
5813
5.46k
        if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
5814
0
        {
5815
0
            pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
5816
0
            pState->m_pMem = NULL;
5817
0
        }
5818
5819
5.46k
        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5820
5.46k
        pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5821
5.46k
        return status;
5822
5.46k
    }
5823
5824
    mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags)
5825
2.84k
    {
5826
2.84k
        mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;
5827
5828
2.84k
        if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5829
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5830
5831
2.84k
        if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5832
163
        {
5833
163
            if (!pZip->m_pRead)
5834
0
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5835
163
        }
5836
5837
2.84k
        if (pZip->m_file_offset_alignment)
5838
0
        {
5839
            /* Ensure user specified file offset alignment is a power of 2. */
5840
0
            if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5841
0
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5842
0
        }
5843
5844
2.84k
        if (!pZip->m_pAlloc)
5845
2.84k
            pZip->m_pAlloc = miniz_def_alloc_func;
5846
2.84k
        if (!pZip->m_pFree)
5847
2.84k
            pZip->m_pFree = miniz_def_free_func;
5848
2.84k
        if (!pZip->m_pRealloc)
5849
2.84k
            pZip->m_pRealloc = miniz_def_realloc_func;
5850
5851
2.84k
        pZip->m_archive_size = existing_size;
5852
2.84k
        pZip->m_central_directory_file_ofs = 0;
5853
2.84k
        pZip->m_total_files = 0;
5854
5855
2.84k
        if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5856
0
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5857
5858
2.84k
        memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5859
5860
2.84k
        MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
5861
2.84k
        MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
5862
2.84k
        MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
5863
5864
2.84k
        pZip->m_pState->m_zip64 = zip64;
5865
2.84k
        pZip->m_pState->m_zip64_has_extended_info_fields = zip64;
5866
5867
2.84k
        pZip->m_zip_type = MZ_ZIP_TYPE_USER;
5868
2.84k
        pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5869
5870
2.84k
        return MZ_TRUE;
5871
2.84k
    }
5872
5873
    mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
5874
0
    {
5875
0
        return mz_zip_writer_init_v2(pZip, existing_size, 0);
5876
0
    }
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
0
    {
5880
0
        pZip->m_pWrite = mz_zip_heap_write_func;
5881
0
        pZip->m_pNeeds_keepalive = NULL;
5882
5883
0
        if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5884
0
            pZip->m_pRead = mz_zip_mem_read_func;
5885
5886
0
        pZip->m_pIO_opaque = pZip;
5887
5888
0
        if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5889
0
            return MZ_FALSE;
5890
5891
0
        pZip->m_zip_type = MZ_ZIP_TYPE_HEAP;
5892
5893
0
        if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
5894
0
        {
5895
0
            if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
5896
0
            {
5897
0
                mz_zip_writer_end_internal(pZip, MZ_FALSE);
5898
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5899
0
            }
5900
0
            pZip->m_pState->m_mem_capacity = initial_allocation_size;
5901
0
        }
5902
5903
0
        return MZ_TRUE;
5904
0
    }
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
0
    {
5908
0
        return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0);
5909
0
    }
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
35.7k
    {
5914
35.7k
        mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5915
35.7k
        mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5916
5917
35.7k
        file_ofs += pZip->m_pState->m_file_archive_start_ofs;
5918
5919
35.7k
        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
0
        {
5921
0
            mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
5922
0
            return 0;
5923
0
        }
5924
5925
35.7k
        return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5926
35.7k
    }
5927
5928
    mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
5929
0
    {
5930
0
        return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0);
5931
0
    }
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
2.84k
    {
5935
2.84k
        MZ_FILE *pFile;
5936
5937
2.84k
        pZip->m_pWrite = mz_zip_file_write_func;
5938
2.84k
        pZip->m_pNeeds_keepalive = NULL;
5939
5940
2.84k
        if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5941
163
            pZip->m_pRead = mz_zip_file_read_func;
5942
5943
2.84k
        pZip->m_pIO_opaque = pZip;
5944
5945
2.84k
        if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5946
0
            return MZ_FALSE;
5947
5948
2.84k
        if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb")))
5949
0
        {
5950
0
            mz_zip_writer_end(pZip);
5951
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5952
0
        }
5953
5954
2.84k
        pZip->m_pState->m_pFile = pFile;
5955
2.84k
        pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
5956
5957
2.84k
        if (size_to_reserve_at_beginning)
5958
0
        {
5959
0
            mz_uint64 cur_ofs = 0;
5960
0
            char buf[4096];
5961
5962
0
            MZ_CLEAR_ARR(buf);
5963
5964
0
            do
5965
0
            {
5966
0
                size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5967
0
                if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
5968
0
                {
5969
0
                    mz_zip_writer_end(pZip);
5970
0
                    return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
5971
0
                }
5972
0
                cur_ofs += n;
5973
0
                size_to_reserve_at_beginning -= n;
5974
0
            } while (size_to_reserve_at_beginning);
5975
0
        }
5976
5977
2.84k
        return MZ_TRUE;
5978
2.84k
    }
5979
5980
    mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)
5981
0
    {
5982
0
        pZip->m_pWrite = mz_zip_file_write_func;
5983
0
        pZip->m_pNeeds_keepalive = NULL;
5984
5985
0
        if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5986
0
            pZip->m_pRead = mz_zip_file_read_func;
5987
5988
0
        pZip->m_pIO_opaque = pZip;
5989
5990
0
        if (!mz_zip_writer_init_v2(pZip, 0, flags))
5991
0
            return MZ_FALSE;
5992
5993
0
        pZip->m_pState->m_pFile = pFile;
5994
0
        pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5995
0
        pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
5996
5997
0
        return MZ_TRUE;
5998
0
    }
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
2.66k
    {
6003
2.66k
        mz_zip_internal_state *pState;
6004
6005
2.66k
        if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
6006
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6007
6008
2.66k
        if (flags & MZ_ZIP_FLAG_WRITE_ZIP64)
6009
157
        {
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
157
            if (!pZip->m_pState->m_zip64)
6012
37
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6013
157
        }
6014
6015
        /* No sense in trying to write to an archive that's already at the support max size */
6016
2.62k
        if (pZip->m_pState->m_zip64)
6017
507
        {
6018
507
            if (pZip->m_total_files == MZ_UINT32_MAX)
6019
0
                return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6020
507
        }
6021
2.11k
        else
6022
2.11k
        {
6023
2.11k
            if (pZip->m_total_files == MZ_UINT16_MAX)
6024
0
                return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6025
6026
2.11k
            if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)
6027
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
6028
2.11k
        }
6029
6030
2.62k
        pState = pZip->m_pState;
6031
6032
2.62k
        if (pState->m_pFile)
6033
2.62k
        {
6034
#ifdef MINIZ_NO_STDIO
6035
            (void)pFilename;
6036
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6037
#else
6038
2.62k
            if (pZip->m_pIO_opaque != pZip)
6039
0
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6040
6041
2.62k
            if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE &&
6042
2.62k
                !(flags & MZ_ZIP_FLAG_READ_ALLOW_WRITING) )
6043
0
            {
6044
0
                if (!pFilename)
6045
0
                    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
0
                if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
6049
0
                {
6050
                    /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */
6051
0
                    mz_zip_reader_end_internal(pZip, MZ_FALSE);
6052
0
                    return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
6053
0
                }
6054
0
            }
6055
6056
2.62k
            pZip->m_pWrite = mz_zip_file_write_func;
6057
2.62k
            pZip->m_pNeeds_keepalive = NULL;
6058
2.62k
#endif /* #ifdef MINIZ_NO_STDIO */
6059
2.62k
        }
6060
0
        else if (pState->m_pMem)
6061
0
        {
6062
            /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */
6063
0
            if (pZip->m_pIO_opaque != pZip)
6064
0
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6065
6066
0
            pState->m_mem_capacity = pState->m_mem_size;
6067
0
            pZip->m_pWrite = mz_zip_heap_write_func;
6068
0
            pZip->m_pNeeds_keepalive = NULL;
6069
0
        }
6070
        /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */
6071
0
        else if (!pZip->m_pWrite)
6072
0
            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
2.62k
        pZip->m_archive_size = pZip->m_central_directory_file_ofs;
6077
2.62k
        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
2.62k
        mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets);
6083
6084
2.62k
        pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
6085
6086
2.62k
        return MZ_TRUE;
6087
2.62k
    }
6088
6089
    mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
6090
0
    {
6091
0
        return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);
6092
0
    }
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
0
    {
6097
0
        return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
6098
0
    }
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
5.20k
    {
6109
5.20k
        mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
6110
5.20k
        if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
6111
0
            return MZ_FALSE;
6112
6113
5.20k
        pState->m_cur_archive_file_ofs += len;
6114
5.20k
        pState->m_comp_size += len;
6115
5.20k
        return MZ_TRUE;
6116
5.20k
    }
6117
6118
#define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)
6119
6.20k
#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
0
    {
6122
0
        mz_uint8 *pDst = pBuf;
6123
0
        mz_uint32 field_size = 0;
6124
6125
0
        MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
6126
0
        MZ_WRITE_LE16(pDst + 2, 0);
6127
0
        pDst += sizeof(mz_uint16) * 2;
6128
6129
0
        if (pUncomp_size)
6130
0
        {
6131
0
            MZ_WRITE_LE64(pDst, *pUncomp_size);
6132
0
            pDst += sizeof(mz_uint64);
6133
0
            field_size += sizeof(mz_uint64);
6134
0
        }
6135
6136
0
        if (pComp_size)
6137
0
        {
6138
0
            MZ_WRITE_LE64(pDst, *pComp_size);
6139
0
            pDst += sizeof(mz_uint64);
6140
0
            field_size += sizeof(mz_uint64);
6141
0
        }
6142
6143
0
        if (pLocal_header_ofs)
6144
0
        {
6145
0
            MZ_WRITE_LE64(pDst, *pLocal_header_ofs);
6146
0
            pDst += sizeof(mz_uint64);
6147
0
            field_size += sizeof(mz_uint64);
6148
0
        }
6149
6150
0
        MZ_WRITE_LE16(pBuf + 2, field_size);
6151
6152
0
        return (mz_uint32)(pDst - pBuf);
6153
0
    }
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
5.41k
    {
6157
5.41k
        (void)pZip;
6158
5.41k
        memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
6159
5.41k
        MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
6160
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6161
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
6162
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
6163
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
6164
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
6165
5.41k
        MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
6166
5.41k
        MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
6167
5.41k
        MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
6168
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
6169
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
6170
5.41k
        return MZ_TRUE;
6171
5.41k
    }
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
5.41k
    {
6179
5.41k
        (void)pZip;
6180
5.41k
        memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6181
5.41k
        MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6182
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6183
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6184
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6185
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6186
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6187
5.41k
        MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6188
5.41k
        MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
6189
5.41k
        MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
6190
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6191
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6192
5.41k
        MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6193
5.41k
        MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6194
5.41k
        MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_MIN(local_header_ofs, MZ_UINT32_MAX));
6195
5.41k
        return MZ_TRUE;
6196
5.41k
    }
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
5.41k
    {
6205
5.41k
        mz_zip_internal_state *pState = pZip->m_pState;
6206
5.41k
        mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6207
5.41k
        size_t orig_central_dir_size = pState->m_central_dir.m_size;
6208
5.41k
        mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6209
6210
5.41k
        if (!pZip->m_pState->m_zip64)
6211
4.68k
        {
6212
4.68k
            if (local_header_ofs > 0xFFFFFFFF)
6213
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
6214
4.68k
        }
6215
6216
        /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6217
5.41k
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6219
6220
5.41k
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6222
6223
5.41k
        if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6224
5.41k
            (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
6225
5.41k
            (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
6226
5.41k
            (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) ||
6227
5.41k
            (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
6228
5.41k
            (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
6229
0
        {
6230
            /* Try to resize the central directory array back into its original state. */
6231
0
            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6232
0
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6233
0
        }
6234
6235
5.41k
        return MZ_TRUE;
6236
5.41k
    }
6237
6238
    static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
6239
11.0k
    {
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
11.0k
        if (*pArchive_name == '/')
6242
35
            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
10.9k
        return MZ_TRUE;
6247
11.0k
    }
6248
6249
    static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
6250
5.46k
    {
6251
5.46k
        mz_uint32 n;
6252
5.46k
        if (!pZip->m_file_offset_alignment)
6253
5.46k
            return 0;
6254
0
        n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6255
0
        return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1));
6256
5.46k
    }
6257
6258
    static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
6259
5.41k
    {
6260
5.41k
        char buf[4096];
6261
5.41k
        memset(buf, 0, MZ_MIN(sizeof(buf), n));
6262
5.41k
        while (n)
6263
0
        {
6264
0
            mz_uint32 s = MZ_MIN(sizeof(buf), n);
6265
0
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6266
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6267
6268
0
            cur_file_ofs += s;
6269
0
            n -= s;
6270
0
        }
6271
5.41k
        return MZ_TRUE;
6272
5.41k
    }
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
5.46k
    {
6277
5.46k
        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
5.46k
    }
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
5.46k
    {
6284
5.46k
        mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6285
5.46k
        mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
6286
5.46k
        mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
6287
5.46k
        size_t archive_name_size;
6288
5.46k
        mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6289
5.46k
        tdefl_compressor *pComp = NULL;
6290
5.46k
        mz_bool store_data_uncompressed;
6291
5.46k
        mz_zip_internal_state *pState;
6292
5.46k
        mz_uint8 *pExtra_data = NULL;
6293
5.46k
        mz_uint32 extra_size = 0;
6294
5.46k
        mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6295
5.46k
        mz_uint16 bit_flags = 0;
6296
6297
5.46k
        if ((int)level_and_flags < 0)
6298
0
            level_and_flags = MZ_DEFAULT_LEVEL;
6299
6300
5.46k
        if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
6301
4.90k
            bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6302
6303
5.46k
        if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6304
5.17k
            bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6305
6306
5.46k
        level = level_and_flags & 0xF;
6307
5.46k
        store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6308
6309
5.46k
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6311
6312
5.46k
        pState = pZip->m_pState;
6313
6314
5.46k
        if (pState->m_zip64)
6315
742
        {
6316
742
            if (pZip->m_total_files == MZ_UINT32_MAX)
6317
0
                return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6318
742
        }
6319
4.72k
        else
6320
4.72k
        {
6321
4.72k
            if (pZip->m_total_files == MZ_UINT16_MAX)
6322
0
            {
6323
0
                pState->m_zip64 = MZ_TRUE;
6324
                /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6325
0
            }
6326
4.72k
            if (((mz_uint64)buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6327
0
            {
6328
0
                pState->m_zip64 = MZ_TRUE;
6329
                /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6330
0
            }
6331
4.72k
        }
6332
6333
5.46k
        if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6334
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6335
6336
5.46k
        if (!mz_zip_writer_validate_archive_name(pArchive_name))
6337
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6338
6339
5.46k
#ifndef MINIZ_NO_TIME
6340
5.46k
        if (last_modified != NULL)
6341
0
        {
6342
0
            mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
6343
0
        }
6344
5.46k
        else
6345
5.46k
        {
6346
5.46k
            MZ_TIME_T cur_time;
6347
5.46k
            time(&cur_time);
6348
5.46k
            mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6349
5.46k
        }
6350
#else
6351
        (void)last_modified;
6352
#endif /* #ifndef MINIZ_NO_TIME */
6353
6354
5.46k
        if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6355
4.90k
        {
6356
4.90k
            uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6357
4.90k
            uncomp_size = buf_size;
6358
4.90k
            if (uncomp_size <= 3)
6359
798
            {
6360
798
                level = 0;
6361
798
                store_data_uncompressed = MZ_TRUE;
6362
798
            }
6363
4.90k
        }
6364
6365
5.46k
        archive_name_size = strlen(pArchive_name);
6366
5.46k
        if (archive_name_size > MZ_UINT16_MAX)
6367
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6368
6369
5.46k
        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
5.46k
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6374
6375
5.46k
        if (!pState->m_zip64)
6376
4.72k
        {
6377
            /* Bail early if the archive would obviously become too large */
6378
4.72k
            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
4.72k
                 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
0
            {
6381
0
                pState->m_zip64 = MZ_TRUE;
6382
                /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6383
0
            }
6384
4.72k
        }
6385
6386
5.46k
        if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
6387
47
        {
6388
            /* Set DOS Subdirectory attribute bit. */
6389
47
            ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
6390
6391
            /* Subdirectories cannot contain data. */
6392
47
            if ((buf_size) || (uncomp_size))
6393
47
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6394
47
        }
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
5.41k
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6399
6400
5.41k
        if ((!store_data_uncompressed) && (buf_size))
6401
2.99k
        {
6402
2.99k
            if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6403
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6404
2.99k
        }
6405
6406
5.41k
        if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6407
0
        {
6408
0
            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6409
0
            return MZ_FALSE;
6410
0
        }
6411
6412
5.41k
        local_dir_header_ofs += num_alignment_padding_bytes;
6413
5.41k
        if (pZip->m_file_offset_alignment)
6414
0
        {
6415
0
            MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6416
0
        }
6417
5.41k
        cur_archive_file_ofs += num_alignment_padding_bytes;
6418
6419
5.41k
        MZ_CLEAR_ARR(local_dir_header);
6420
6421
5.41k
        if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6422
3.54k
        {
6423
3.54k
            method = MZ_DEFLATED;
6424
3.54k
        }
6425
6426
5.41k
        if (pState->m_zip64)
6427
735
        {
6428
735
            if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6429
0
            {
6430
0
                pExtra_data = extra_data;
6431
0
                extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6432
0
                                                                   (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6433
0
            }
6434
6435
735
            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
0
                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6437
6438
735
            if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6439
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6440
6441
735
            cur_archive_file_ofs += sizeof(local_dir_header);
6442
6443
735
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6444
0
            {
6445
0
                pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6446
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6447
0
            }
6448
735
            cur_archive_file_ofs += archive_name_size;
6449
6450
735
            if (pExtra_data != NULL)
6451
0
            {
6452
0
                if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6453
0
                    return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6454
6455
0
                cur_archive_file_ofs += extra_size;
6456
0
            }
6457
735
        }
6458
4.68k
        else
6459
4.68k
        {
6460
4.68k
            if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6461
0
                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6462
4.68k
            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
0
                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6464
6465
4.68k
            if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6466
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6467
6468
4.68k
            cur_archive_file_ofs += sizeof(local_dir_header);
6469
6470
4.68k
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6471
0
            {
6472
0
                pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6473
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6474
0
            }
6475
4.68k
            cur_archive_file_ofs += archive_name_size;
6476
4.68k
        }
6477
6478
5.41k
        if (user_extra_data_len > 0)
6479
0
        {
6480
0
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6481
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6482
6483
0
            cur_archive_file_ofs += user_extra_data_len;
6484
0
        }
6485
6486
5.41k
        if (store_data_uncompressed)
6487
2.42k
        {
6488
2.42k
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
6489
0
            {
6490
0
                pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6491
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6492
0
            }
6493
6494
2.42k
            cur_archive_file_ofs += buf_size;
6495
2.42k
            comp_size = buf_size;
6496
2.42k
        }
6497
2.99k
        else if (buf_size)
6498
2.99k
        {
6499
2.99k
            mz_zip_writer_add_state state;
6500
6501
2.99k
            state.m_pZip = pZip;
6502
2.99k
            state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6503
2.99k
            state.m_comp_size = 0;
6504
6505
2.99k
            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
2.99k
                (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
6507
0
            {
6508
0
                pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6509
0
                return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6510
0
            }
6511
6512
2.99k
            comp_size = state.m_comp_size;
6513
2.99k
            cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6514
2.99k
        }
6515
6516
5.41k
        pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6517
5.41k
        pComp = NULL;
6518
6519
5.41k
        if (uncomp_size)
6520
4.86k
        {
6521
4.86k
            mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6522
4.86k
            mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6523
6524
4.86k
            MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR);
6525
6526
4.86k
            MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6527
4.86k
            MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6528
4.86k
            if (pExtra_data == NULL)
6529
4.86k
            {
6530
4.86k
                if (comp_size > MZ_UINT32_MAX)
6531
0
                    return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6532
6533
4.86k
                MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6534
4.86k
                MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6535
4.86k
            }
6536
0
            else
6537
0
            {
6538
0
                MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6539
0
                MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6540
0
                local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6541
0
            }
6542
6543
4.86k
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6544
0
                return MZ_FALSE;
6545
6546
4.86k
            cur_archive_file_ofs += local_dir_footer_size;
6547
4.86k
        }
6548
6549
5.41k
        if (pExtra_data != NULL)
6550
0
        {
6551
0
            extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6552
0
                                                               (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6553
0
        }
6554
6555
5.41k
        if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment,
6556
5.41k
                                              comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6557
5.41k
                                              user_extra_data_central, user_extra_data_central_len))
6558
0
            return MZ_FALSE;
6559
6560
5.41k
        pZip->m_total_files++;
6561
5.41k
        pZip->m_archive_size = cur_archive_file_ofs;
6562
6563
5.41k
        return MZ_TRUE;
6564
5.41k
    }
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
0
    {
6569
0
        mz_uint16 gen_flags;
6570
0
        mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6571
0
        mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
6572
0
        mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0;
6573
0
        size_t archive_name_size;
6574
0
        mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6575
0
        mz_uint8 *pExtra_data = NULL;
6576
0
        mz_uint32 extra_size = 0;
6577
0
        mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6578
0
        mz_zip_internal_state *pState;
6579
0
        mz_uint64 file_ofs = 0, cur_archive_header_file_ofs;
6580
6581
0
        if ((int)level_and_flags < 0)
6582
0
            level_and_flags = MZ_DEFAULT_LEVEL;
6583
0
        level = level_and_flags & 0xF;
6584
6585
0
        gen_flags = (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE) ? 0 : MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6586
6587
0
        if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6588
0
            gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6589
6590
        /* Sanity checks */
6591
0
        if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6592
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6593
6594
0
        pState = pZip->m_pState;
6595
6596
0
        if ((!pState->m_zip64) && (max_size > MZ_UINT32_MAX))
6597
0
        {
6598
            /* Source file is too large for non-zip64 */
6599
            /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6600
0
            pState->m_zip64 = MZ_TRUE;
6601
0
        }
6602
6603
        /* We could support this, but why? */
6604
0
        if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6605
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6606
6607
0
        if (!mz_zip_writer_validate_archive_name(pArchive_name))
6608
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6609
6610
0
        if (pState->m_zip64)
6611
0
        {
6612
0
            if (pZip->m_total_files == MZ_UINT32_MAX)
6613
0
                return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6614
0
        }
6615
0
        else
6616
0
        {
6617
0
            if (pZip->m_total_files == MZ_UINT16_MAX)
6618
0
            {
6619
0
                pState->m_zip64 = MZ_TRUE;
6620
                /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6621
0
            }
6622
0
        }
6623
6624
0
        archive_name_size = strlen(pArchive_name);
6625
0
        if (archive_name_size > MZ_UINT16_MAX)
6626
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6627
6628
0
        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
0
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6633
6634
0
        if (!pState->m_zip64)
6635
0
        {
6636
            /* Bail early if the archive would obviously become too large */
6637
0
            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
0
            {
6639
0
                pState->m_zip64 = MZ_TRUE;
6640
                /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6641
0
            }
6642
0
        }
6643
6644
0
#ifndef MINIZ_NO_TIME
6645
0
        if (pFile_time)
6646
0
        {
6647
0
            mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);
6648
0
        }
6649
#else
6650
        (void)pFile_time;
6651
#endif
6652
6653
0
        if (max_size <= 3)
6654
0
            level = 0;
6655
6656
0
        if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6657
0
        {
6658
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6659
0
        }
6660
6661
0
        cur_archive_file_ofs += num_alignment_padding_bytes;
6662
0
        local_dir_header_ofs = cur_archive_file_ofs;
6663
6664
0
        if (pZip->m_file_offset_alignment)
6665
0
        {
6666
0
            MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6667
0
        }
6668
6669
0
        if (max_size && level)
6670
0
        {
6671
0
            method = MZ_DEFLATED;
6672
0
        }
6673
6674
0
        MZ_CLEAR_ARR(local_dir_header);
6675
0
        if (pState->m_zip64)
6676
0
        {
6677
0
            if (max_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6678
0
            {
6679
0
                pExtra_data = extra_data;
6680
0
                if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE)
6681
0
                    extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6682
0
                                                                       (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL,
6683
0
                                                                       (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6684
0
                else
6685
0
                    extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, NULL,
6686
0
                                                                       NULL,
6687
0
                                                                       (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6688
0
            }
6689
6690
0
            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
0
                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6692
6693
0
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6694
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6695
6696
0
            cur_archive_file_ofs += sizeof(local_dir_header);
6697
6698
0
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6699
0
            {
6700
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6701
0
            }
6702
6703
0
            cur_archive_file_ofs += archive_name_size;
6704
6705
0
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6706
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6707
6708
0
            cur_archive_file_ofs += extra_size;
6709
0
        }
6710
0
        else
6711
0
        {
6712
0
            if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6713
0
                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6714
0
            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
0
                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6716
6717
0
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6718
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6719
6720
0
            cur_archive_file_ofs += sizeof(local_dir_header);
6721
6722
0
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6723
0
            {
6724
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6725
0
            }
6726
6727
0
            cur_archive_file_ofs += archive_name_size;
6728
0
        }
6729
6730
0
        if (user_extra_data_len > 0)
6731
0
        {
6732
0
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6733
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6734
6735
0
            cur_archive_file_ofs += user_extra_data_len;
6736
0
        }
6737
6738
0
        if (max_size)
6739
0
        {
6740
0
            void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6741
0
            if (!pRead_buf)
6742
0
            {
6743
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6744
0
            }
6745
6746
0
            if (!level)
6747
0
            {
6748
0
                while (1)
6749
0
                {
6750
0
                    size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE);
6751
0
                    if (n == 0)
6752
0
                        break;
6753
6754
0
                    if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size))
6755
0
                    {
6756
0
                        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6757
0
                        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6758
0
                    }
6759
0
                    if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)
6760
0
                    {
6761
0
                        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6762
0
                        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6763
0
                    }
6764
0
                    file_ofs += n;
6765
0
                    uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6766
0
                    cur_archive_file_ofs += n;
6767
0
                }
6768
0
                uncomp_size = file_ofs;
6769
0
                comp_size = uncomp_size;
6770
0
            }
6771
0
            else
6772
0
            {
6773
0
                mz_bool result = MZ_FALSE;
6774
0
                mz_zip_writer_add_state state;
6775
0
                tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6776
0
                if (!pComp)
6777
0
                {
6778
0
                    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6779
0
                    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6780
0
                }
6781
6782
0
                state.m_pZip = pZip;
6783
0
                state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6784
0
                state.m_comp_size = 0;
6785
6786
0
                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
0
                {
6788
0
                    pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6789
0
                    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6790
0
                    return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6791
0
                }
6792
6793
0
                for (;;)
6794
0
                {
6795
0
                    tdefl_status status;
6796
0
                    tdefl_flush flush = TDEFL_NO_FLUSH;
6797
6798
0
                    size_t n = read_callback(callback_opaque, file_ofs, pRead_buf, MZ_ZIP_MAX_IO_BUF_SIZE);
6799
0
                    if ((n > MZ_ZIP_MAX_IO_BUF_SIZE) || (file_ofs + n > max_size))
6800
0
                    {
6801
0
                        mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6802
0
                        break;
6803
0
                    }
6804
6805
0
                    file_ofs += n;
6806
0
                    uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6807
6808
0
                    if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
6809
0
                        flush = TDEFL_FULL_FLUSH;
6810
6811
0
                    if (n == 0)
6812
0
                        flush = TDEFL_FINISH;
6813
6814
0
                    status = tdefl_compress_buffer(pComp, pRead_buf, n, flush);
6815
0
                    if (status == TDEFL_STATUS_DONE)
6816
0
                    {
6817
0
                        result = MZ_TRUE;
6818
0
                        break;
6819
0
                    }
6820
0
                    else if (status != TDEFL_STATUS_OKAY)
6821
0
                    {
6822
0
                        mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6823
0
                        break;
6824
0
                    }
6825
0
                }
6826
6827
0
                pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6828
6829
0
                if (!result)
6830
0
                {
6831
0
                    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6832
0
                    return MZ_FALSE;
6833
0
                }
6834
6835
0
                uncomp_size = file_ofs;
6836
0
                comp_size = state.m_comp_size;
6837
0
                cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6838
0
            }
6839
6840
0
            pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6841
0
        }
6842
6843
0
        if (!(level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE))
6844
0
        {
6845
0
            mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6846
0
            mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6847
6848
0
            MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6849
0
            MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6850
0
            if (pExtra_data == NULL)
6851
0
            {
6852
0
                if (comp_size > MZ_UINT32_MAX)
6853
0
                    return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6854
6855
0
                MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6856
0
                MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6857
0
            }
6858
0
            else
6859
0
            {
6860
0
                MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6861
0
                MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6862
0
                local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6863
0
            }
6864
6865
0
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6866
0
                return MZ_FALSE;
6867
6868
0
            cur_archive_file_ofs += local_dir_footer_size;
6869
0
        }
6870
6871
0
        if (level_and_flags & MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE)
6872
0
        {
6873
0
            if (pExtra_data != NULL)
6874
0
            {
6875
0
                extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (max_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6876
0
                                                                   (max_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6877
0
            }
6878
6879
0
            if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header,
6880
0
                                                       (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len),
6881
0
                                                       (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : uncomp_size,
6882
0
                                                       (max_size >= MZ_UINT32_MAX) ? MZ_UINT32_MAX : comp_size,
6883
0
                                                       uncomp_crc32, method, gen_flags, dos_time, dos_date))
6884
0
                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6885
6886
0
            cur_archive_header_file_ofs = local_dir_header_ofs;
6887
6888
0
            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
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6890
6891
0
            if (pExtra_data != NULL)
6892
0
            {
6893
0
                cur_archive_header_file_ofs += sizeof(local_dir_header);
6894
6895
0
                if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6896
0
                {
6897
0
                    return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6898
0
                }
6899
6900
0
                cur_archive_header_file_ofs += archive_name_size;
6901
6902
0
                if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_header_file_ofs, extra_data, extra_size) != extra_size)
6903
0
                    return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6904
6905
0
                cur_archive_header_file_ofs += extra_size;
6906
0
            }
6907
0
        }
6908
6909
0
        if (pExtra_data != NULL)
6910
0
        {
6911
0
            extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6912
0
                                                               (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6913
0
        }
6914
6915
0
        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
0
                                              uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6917
0
                                              user_extra_data_central, user_extra_data_central_len))
6918
0
            return MZ_FALSE;
6919
6920
0
        pZip->m_total_files++;
6921
0
        pZip->m_archive_size = cur_archive_file_ofs;
6922
6923
0
        return MZ_TRUE;
6924
0
    }
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
0
    {
6930
0
        MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque;
6931
0
        mz_int64 cur_ofs = MZ_FTELL64(pSrc_file);
6932
6933
0
        if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET))))
6934
0
            return 0;
6935
6936
0
        return MZ_FREAD(pBuf, 1, n, pSrc_file);
6937
0
    }
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
0
    {
6942
0
        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
0
                                                   user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len);
6944
0
    }
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
0
    {
6948
0
        MZ_FILE *pSrc_file = NULL;
6949
0
        mz_uint64 uncomp_size = 0;
6950
0
        MZ_TIME_T file_modified_time;
6951
0
        MZ_TIME_T *pFile_time = NULL;
6952
0
        mz_bool status;
6953
6954
0
        memset(&file_modified_time, 0, sizeof(file_modified_time));
6955
6956
0
#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
6957
0
        pFile_time = &file_modified_time;
6958
0
        if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6959
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED);
6960
0
#endif
6961
6962
0
        pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6963
0
        if (!pSrc_file)
6964
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
6965
6966
0
        MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6967
0
        uncomp_size = MZ_FTELL64(pSrc_file);
6968
0
        MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6969
6970
0
        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
0
        MZ_FCLOSE(pSrc_file);
6973
6974
0
        return status;
6975
0
    }
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
0
    {
6980
        /* + 64 should be enough for any new zip64 data */
6981
0
        if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))
6982
0
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6983
6984
0
        mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);
6985
6986
0
        if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start))
6987
0
        {
6988
0
            mz_uint8 new_ext_block[64];
6989
0
            mz_uint8 *pDst = new_ext_block;
6990
0
            mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
6991
0
            mz_write_le16(pDst + sizeof(mz_uint16), 0);
6992
0
            pDst += sizeof(mz_uint16) * 2;
6993
6994
0
            if (pUncomp_size)
6995
0
            {
6996
0
                mz_write_le64(pDst, *pUncomp_size);
6997
0
                pDst += sizeof(mz_uint64);
6998
0
            }
6999
7000
0
            if (pComp_size)
7001
0
            {
7002
0
                mz_write_le64(pDst, *pComp_size);
7003
0
                pDst += sizeof(mz_uint64);
7004
0
            }
7005
7006
0
            if (pLocal_header_ofs)
7007
0
            {
7008
0
                mz_write_le64(pDst, *pLocal_header_ofs);
7009
0
                pDst += sizeof(mz_uint64);
7010
0
            }
7011
7012
0
            if (pDisk_start)
7013
0
            {
7014
0
                mz_write_le32(pDst, *pDisk_start);
7015
0
                pDst += sizeof(mz_uint32);
7016
0
            }
7017
7018
0
            mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2));
7019
7020
0
            if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block))
7021
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7022
0
        }
7023
7024
0
        if ((pExt) && (ext_len))
7025
0
        {
7026
0
            mz_uint32 extra_size_remaining = ext_len;
7027
0
            const mz_uint8 *pExtra_data = pExt;
7028
7029
0
            do
7030
0
            {
7031
0
                mz_uint32 field_id, field_data_size, field_total_size;
7032
7033
0
                if (extra_size_remaining < (sizeof(mz_uint16) * 2))
7034
0
                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7035
7036
0
                field_id = MZ_READ_LE16(pExtra_data);
7037
0
                field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
7038
0
                field_total_size = field_data_size + sizeof(mz_uint16) * 2;
7039
7040
0
                if (field_total_size > extra_size_remaining)
7041
0
                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7042
7043
0
                if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
7044
0
                {
7045
0
                    if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size))
7046
0
                        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7047
0
                }
7048
7049
0
                pExtra_data += field_total_size;
7050
0
                extra_size_remaining -= field_total_size;
7051
0
            } while (extra_size_remaining);
7052
0
        }
7053
7054
0
        return MZ_TRUE;
7055
0
    }
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
0
    {
7060
0
        mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size;
7061
0
        mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;
7062
0
        mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
7063
0
        mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
7064
0
        mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
7065
0
        mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
7066
0
        size_t orig_central_dir_size;
7067
0
        mz_zip_internal_state *pState;
7068
0
        void *pBuf;
7069
0
        const mz_uint8 *pSrc_central_header;
7070
0
        mz_zip_archive_file_stat src_file_stat;
7071
0
        mz_uint32 src_filename_len, src_comment_len, src_ext_len;
7072
0
        mz_uint32 local_header_filename_size, local_header_extra_len;
7073
0
        mz_uint64 local_header_comp_size, local_header_uncomp_size;
7074
0
        mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
7075
7076
        /* Sanity checks */
7077
0
        if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))
7078
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7079
7080
0
        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
0
        if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))
7084
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7085
7086
        /* Get pointer to the source central dir header and crack it */
7087
0
        if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
7088
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7089
7090
0
        if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)
7091
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7092
7093
0
        src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);
7094
0
        src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
7095
0
        src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);
7096
0
        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
0
        if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)
7100
0
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
7101
7102
0
        num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
7103
7104
0
        if (!pState->m_zip64)
7105
0
        {
7106
0
            if (pZip->m_total_files == MZ_UINT16_MAX)
7107
0
                return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7108
0
        }
7109
0
        else
7110
0
        {
7111
            /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */
7112
0
            if (pZip->m_total_files == MZ_UINT32_MAX)
7113
0
                return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7114
0
        }
7115
7116
0
        if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL))
7117
0
            return MZ_FALSE;
7118
7119
0
        cur_src_file_ofs = src_file_stat.m_local_header_ofs;
7120
0
        cur_dst_file_ofs = pZip->m_archive_size;
7121
7122
        /* Read the source archive's local dir header */
7123
0
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7125
7126
0
        if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
7127
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7128
7129
0
        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
0
        local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
7133
0
        local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
7134
0
        local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
7135
0
        local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
7136
0
        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
0
        if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
7140
0
        {
7141
0
            mz_zip_array file_data_array;
7142
0
            const mz_uint8 *pExtra_data;
7143
0
            mz_uint32 extra_size_remaining = local_header_extra_len;
7144
7145
0
            mz_zip_array_init(&file_data_array, 1);
7146
0
            if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE))
7147
0
            {
7148
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7149
0
            }
7150
7151
0
            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
0
            {
7153
0
                mz_zip_array_clear(pZip, &file_data_array);
7154
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7155
0
            }
7156
7157
0
            pExtra_data = (const mz_uint8 *)file_data_array.m_p;
7158
7159
0
            do
7160
0
            {
7161
0
                mz_uint32 field_id, field_data_size, field_total_size;
7162
7163
0
                if (extra_size_remaining < (sizeof(mz_uint16) * 2))
7164
0
                {
7165
0
                    mz_zip_array_clear(pZip, &file_data_array);
7166
0
                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7167
0
                }
7168
7169
0
                field_id = MZ_READ_LE16(pExtra_data);
7170
0
                field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
7171
0
                field_total_size = field_data_size + sizeof(mz_uint16) * 2;
7172
7173
0
                if (field_total_size > extra_size_remaining)
7174
0
                {
7175
0
                    mz_zip_array_clear(pZip, &file_data_array);
7176
0
                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7177
0
                }
7178
7179
0
                if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
7180
0
                {
7181
0
                    const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
7182
7183
0
                    if (field_data_size < sizeof(mz_uint64) * 2)
7184
0
                    {
7185
0
                        mz_zip_array_clear(pZip, &file_data_array);
7186
0
                        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7187
0
                    }
7188
7189
0
                    local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
7190
0
                    local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */
7191
7192
0
                    found_zip64_ext_data_in_ldir = MZ_TRUE;
7193
0
                    break;
7194
0
                }
7195
7196
0
                pExtra_data += field_total_size;
7197
0
                extra_size_remaining -= field_total_size;
7198
0
            } while (extra_size_remaining);
7199
7200
0
            mz_zip_array_clear(pZip, &file_data_array);
7201
0
        }
7202
7203
0
        if (!pState->m_zip64)
7204
0
        {
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
0
            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
0
                                                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
0
            if (approx_new_archive_size >= MZ_UINT32_MAX)
7211
0
                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7212
0
        }
7213
7214
        /* Write dest archive padding */
7215
0
        if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
7216
0
            return MZ_FALSE;
7217
7218
0
        cur_dst_file_ofs += num_alignment_padding_bytes;
7219
7220
0
        local_dir_header_ofs = cur_dst_file_ofs;
7221
0
        if (pZip->m_file_offset_alignment)
7222
0
        {
7223
0
            MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
7224
0
        }
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
0
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7229
7230
0
        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
0
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7235
7236
0
        while (src_archive_bytes_remaining)
7237
0
        {
7238
0
            n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining);
7239
0
            if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
7240
0
            {
7241
0
                pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7242
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7243
0
            }
7244
0
            cur_src_file_ofs += n;
7245
7246
0
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7247
0
            {
7248
0
                pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7249
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7250
0
            }
7251
0
            cur_dst_file_ofs += n;
7252
7253
0
            src_archive_bytes_remaining -= n;
7254
0
        }
7255
7256
        /* Now deal with the optional data descriptor */
7257
0
        bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
7258
0
        if (bit_flags & 8)
7259
0
        {
7260
            /* Copy data descriptor */
7261
0
            if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir))
7262
0
            {
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
0
                if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6))
7271
0
                {
7272
0
                    pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7273
0
                    return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7274
0
                }
7275
7276
0
                n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);
7277
0
            }
7278
0
            else
7279
0
            {
7280
                /* src is NOT zip64 */
7281
0
                mz_bool has_id;
7282
7283
0
                if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
7284
0
                {
7285
0
                    pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7286
0
                    return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7287
0
                }
7288
7289
0
                has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
7290
7291
0
                if (pZip->m_pState->m_zip64)
7292
0
                {
7293
                    /* dest is zip64, so upgrade the data descriptor */
7294
0
                    const mz_uint8 *pSrc_descriptor = (const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0);
7295
0
                    const mz_uint32 src_crc32 = MZ_READ_LE32(pSrc_descriptor);
7296
0
                    const mz_uint64 src_comp_size = MZ_READ_LE32(pSrc_descriptor + sizeof(mz_uint32));
7297
0
                    const mz_uint64 src_uncomp_size = MZ_READ_LE32(pSrc_descriptor + 2 * sizeof(mz_uint32));
7298
7299
0
                    mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID);
7300
0
                    mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32);
7301
0
                    mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size);
7302
0
                    mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size);
7303
7304
0
                    n = sizeof(mz_uint32) * 6;
7305
0
                }
7306
0
                else
7307
0
                {
7308
                    /* dest is NOT zip64, just copy it as-is */
7309
0
                    n = sizeof(mz_uint32) * (has_id ? 4 : 3);
7310
0
                }
7311
0
            }
7312
7313
0
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7314
0
            {
7315
0
                pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7316
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7317
0
            }
7318
7319
0
            cur_src_file_ofs += n;
7320
0
            cur_dst_file_ofs += n;
7321
0
        }
7322
0
        pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7323
7324
        /* Finally, add the new central dir header */
7325
0
        orig_central_dir_size = pState->m_central_dir.m_size;
7326
7327
0
        memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
7328
7329
0
        if (pState->m_zip64)
7330
0
        {
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
0
            const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;
7333
0
            mz_zip_array new_ext_block;
7334
7335
0
            mz_zip_array_init(&new_ext_block, sizeof(mz_uint8));
7336
7337
0
            MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7338
0
            MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7339
0
            MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX);
7340
7341
0
            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
0
            {
7343
0
                mz_zip_array_clear(pZip, &new_ext_block);
7344
0
                return MZ_FALSE;
7345
0
            }
7346
7347
0
            MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size);
7348
7349
0
            if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7350
0
            {
7351
0
                mz_zip_array_clear(pZip, &new_ext_block);
7352
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7353
0
            }
7354
7355
0
            if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len))
7356
0
            {
7357
0
                mz_zip_array_clear(pZip, &new_ext_block);
7358
0
                mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7359
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7360
0
            }
7361
7362
0
            if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size))
7363
0
            {
7364
0
                mz_zip_array_clear(pZip, &new_ext_block);
7365
0
                mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7366
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7367
0
            }
7368
7369
0
            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
0
            {
7371
0
                mz_zip_array_clear(pZip, &new_ext_block);
7372
0
                mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7373
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7374
0
            }
7375
7376
0
            mz_zip_array_clear(pZip, &new_ext_block);
7377
0
        }
7378
0
        else
7379
0
        {
7380
            /* sanity checks */
7381
0
            if (cur_dst_file_ofs > MZ_UINT32_MAX)
7382
0
                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7383
7384
0
            if (local_dir_header_ofs >= MZ_UINT32_MAX)
7385
0
                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7386
7387
0
            MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
7388
7389
0
            if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7390
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7391
7392
0
            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
0
            {
7394
0
                mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7395
0
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7396
0
            }
7397
0
        }
7398
7399
        /* This shouldn't trigger unless we screwed up during the initial sanity checks */
7400
0
        if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
7401
0
        {
7402
            /* TODO: Support central dirs >= 32-bits in size */
7403
0
            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7404
0
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
7405
0
        }
7406
7407
0
        n = (mz_uint32)orig_central_dir_size;
7408
0
        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
7409
0
        {
7410
0
            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7411
0
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7412
0
        }
7413
7414
0
        pZip->m_total_files++;
7415
0
        pZip->m_archive_size = cur_dst_file_ofs;
7416
7417
0
        return MZ_TRUE;
7418
0
    }
7419
7420
    mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
7421
5.46k
    {
7422
5.46k
        mz_zip_internal_state *pState;
7423
5.46k
        mz_uint64 central_dir_ofs, central_dir_size;
7424
5.46k
        mz_uint8 hdr[256];
7425
7426
5.46k
        if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
7427
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7428
7429
5.46k
        pState = pZip->m_pState;
7430
7431
5.46k
        if (pState->m_zip64)
7432
742
        {
7433
742
            if ((mz_uint64)pState->m_central_dir.m_size >= MZ_UINT32_MAX)
7434
0
                return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7435
742
        }
7436
4.72k
        else
7437
4.72k
        {
7438
4.72k
            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
0
                return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7440
4.72k
        }
7441
7442
5.46k
        central_dir_ofs = 0;
7443
5.46k
        central_dir_size = 0;
7444
5.46k
        if (pZip->m_total_files)
7445
5.43k
        {
7446
            /* Write central directory */
7447
5.43k
            central_dir_ofs = pZip->m_archive_size;
7448
5.43k
            central_dir_size = pState->m_central_dir.m_size;
7449
5.43k
            pZip->m_central_directory_file_ofs = central_dir_ofs;
7450
5.43k
            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
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7452
7453
5.43k
            pZip->m_archive_size += central_dir_size;
7454
5.43k
        }
7455
7456
5.46k
        if (pState->m_zip64)
7457
742
        {
7458
            /* Write zip64 end of central directory header */
7459
742
            mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size;
7460
7461
742
            MZ_CLEAR_ARR(hdr);
7462
742
            MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG);
7463
742
            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
742
            MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E); /* TODO: always Unix */
7465
742
            MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D);
7466
742
            MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
7467
742
            MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
7468
742
            MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size);
7469
742
            MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs);
7470
742
            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
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7472
7473
742
            pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE;
7474
7475
            /* Write zip64 end of central directory locator */
7476
742
            MZ_CLEAR_ARR(hdr);
7477
742
            MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG);
7478
742
            MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr);
7479
742
            MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1);
7480
742
            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
0
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7482
7483
742
            pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE;
7484
742
        }
7485
7486
        /* Write end of central directory record */
7487
5.46k
        MZ_CLEAR_ARR(hdr);
7488
5.46k
        MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
7489
5.46k
        MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7490
5.46k
        MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7491
5.46k
        MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_size));
7492
5.46k
        MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_ofs));
7493
7494
5.46k
        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
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7496
7497
5.46k
#ifndef MINIZ_NO_STDIO
7498
5.46k
        if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
7499
0
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
7500
5.46k
#endif /* #ifndef MINIZ_NO_STDIO */
7501
7502
5.46k
        pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE;
7503
7504
5.46k
        pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
7505
5.46k
        return MZ_TRUE;
7506
5.46k
    }
7507
7508
    mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize)
7509
0
    {
7510
0
        if ((!ppBuf) || (!pSize))
7511
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7512
7513
0
        *ppBuf = NULL;
7514
0
        *pSize = 0;
7515
7516
0
        if ((!pZip) || (!pZip->m_pState))
7517
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7518
7519
0
        if (pZip->m_pWrite != mz_zip_heap_write_func)
7520
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7521
7522
0
        if (!mz_zip_writer_finalize_archive(pZip))
7523
0
            return MZ_FALSE;
7524
7525
0
        *ppBuf = pZip->m_pState->m_pMem;
7526
0
        *pSize = pZip->m_pState->m_mem_size;
7527
0
        pZip->m_pState->m_pMem = NULL;
7528
0
        pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
7529
7530
0
        return MZ_TRUE;
7531
0
    }
7532
7533
    mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
7534
0
    {
7535
0
        return mz_zip_writer_end_internal(pZip, MZ_TRUE);
7536
0
    }
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
5.93k
    {
7541
5.93k
        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
5.93k
    }
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
5.93k
    {
7546
5.93k
        mz_bool status, created_new_archive = MZ_FALSE;
7547
5.93k
        mz_zip_archive zip_archive;
7548
5.93k
        struct MZ_FILE_STAT_STRUCT file_stat;
7549
5.93k
        mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
7550
7551
5.93k
        mz_zip_zero_struct(&zip_archive);
7552
5.93k
        if ((int)level_and_flags < 0)
7553
0
            level_and_flags = MZ_DEFAULT_LEVEL;
7554
7555
5.93k
        if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
7556
385
        {
7557
385
            if (pErr)
7558
0
                *pErr = MZ_ZIP_INVALID_PARAMETER;
7559
385
            return MZ_FALSE;
7560
385
        }
7561
7562
5.55k
        if (!mz_zip_writer_validate_archive_name(pArchive_name))
7563
35
        {
7564
35
            if (pErr)
7565
0
                *pErr = MZ_ZIP_INVALID_FILENAME;
7566
35
            return MZ_FALSE;
7567
35
        }
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
5.51k
        if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
7572
2.84k
        {
7573
            /* Create a new archive. */
7574
2.84k
            if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags))
7575
0
            {
7576
0
                if (pErr)
7577
0
                    *pErr = zip_archive.m_last_error;
7578
0
                return MZ_FALSE;
7579
0
            }
7580
7581
2.84k
            created_new_archive = MZ_TRUE;
7582
2.84k
        }
7583
2.67k
        else
7584
2.67k
        {
7585
            /* Append to an existing archive. */
7586
2.67k
            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
16
            {
7588
16
                if (pErr)
7589
0
                    *pErr = zip_archive.m_last_error;
7590
16
                return MZ_FALSE;
7591
16
            }
7592
7593
2.66k
            if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_READ_ALLOW_WRITING))
7594
37
            {
7595
37
                if (pErr)
7596
0
                    *pErr = zip_archive.m_last_error;
7597
7598
37
                mz_zip_reader_end_internal(&zip_archive, MZ_FALSE);
7599
7600
37
                return MZ_FALSE;
7601
37
            }
7602
2.66k
        }
7603
7604
5.46k
        status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
7605
5.46k
        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
5.46k
        if (!mz_zip_writer_finalize_archive(&zip_archive))
7609
0
        {
7610
0
            if (!actual_err)
7611
0
                actual_err = zip_archive.m_last_error;
7612
7613
0
            status = MZ_FALSE;
7614
0
        }
7615
7616
5.46k
        if (!mz_zip_writer_end_internal(&zip_archive, status))
7617
0
        {
7618
0
            if (!actual_err)
7619
0
                actual_err = zip_archive.m_last_error;
7620
7621
0
            status = MZ_FALSE;
7622
0
        }
7623
7624
5.46k
        if ((!status) && (created_new_archive))
7625
31
        {
7626
            /* It's a new archive and something went wrong, so just delete it. */
7627
31
            int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
7628
31
            (void)ignoredStatus;
7629
31
        }
7630
7631
5.46k
        if (pErr)
7632
0
            *pErr = actual_err;
7633
7634
5.46k
        return status;
7635
5.51k
    }
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
5.93k
    {
7639
5.93k
        mz_uint32 file_index;
7640
5.93k
        mz_zip_archive zip_archive;
7641
5.93k
        void *p = NULL;
7642
7643
5.93k
        if (pSize)
7644
5.93k
            *pSize = 0;
7645
7646
5.93k
        if ((!pZip_filename) || (!pArchive_name))
7647
0
        {
7648
0
            if (pErr)
7649
0
                *pErr = MZ_ZIP_INVALID_PARAMETER;
7650
7651
0
            return NULL;
7652
0
        }
7653
7654
5.93k
        mz_zip_zero_struct(&zip_archive);
7655
5.93k
        if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7656
379
        {
7657
379
            if (pErr)
7658
0
                *pErr = zip_archive.m_last_error;
7659
7660
379
            return NULL;
7661
379
        }
7662
7663
5.56k
        if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index))
7664
5.22k
        {
7665
5.22k
            p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
7666
5.22k
        }
7667
7668
5.56k
        mz_zip_reader_end_internal(&zip_archive, p != NULL);
7669
7670
5.56k
        if (pErr)
7671
0
            *pErr = zip_archive.m_last_error;
7672
7673
5.56k
        return p;
7674
5.93k
    }
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
5.93k
    {
7678
5.93k
        return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL);
7679
5.93k
    }
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
0
    {
7689
0
        return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
7690
0
    }
7691
7692
    mz_zip_type mz_zip_get_type(mz_zip_archive *pZip)
7693
0
    {
7694
0
        return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
7695
0
    }
7696
7697
    mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num)
7698
64.6k
    {
7699
64.6k
        mz_zip_error prev_err;
7700
7701
64.6k
        if (!pZip)
7702
0
            return MZ_ZIP_INVALID_PARAMETER;
7703
7704
64.6k
        prev_err = pZip->m_last_error;
7705
7706
64.6k
        pZip->m_last_error = err_num;
7707
64.6k
        return prev_err;
7708
64.6k
    }
7709
7710
    mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip)
7711
0
    {
7712
0
        if (!pZip)
7713
0
            return MZ_ZIP_INVALID_PARAMETER;
7714
7715
0
        return pZip->m_last_error;
7716
0
    }
7717
7718
    mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip)
7719
64.6k
    {
7720
64.6k
        return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR);
7721
64.6k
    }
7722
7723
    mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip)
7724
30.0k
    {
7725
30.0k
        mz_zip_error prev_err;
7726
7727
30.0k
        if (!pZip)
7728
0
            return MZ_ZIP_INVALID_PARAMETER;
7729
7730
30.0k
        prev_err = pZip->m_last_error;
7731
7732
30.0k
        pZip->m_last_error = MZ_ZIP_NO_ERROR;
7733
30.0k
        return prev_err;
7734
30.0k
    }
7735
7736
    const char *mz_zip_get_error_string(mz_zip_error mz_err)
7737
0
    {
7738
0
        switch (mz_err)
7739
0
        {
7740
0
            case MZ_ZIP_NO_ERROR:
7741
0
                return "no error";
7742
0
            case MZ_ZIP_UNDEFINED_ERROR:
7743
0
                return "undefined error";
7744
0
            case MZ_ZIP_TOO_MANY_FILES:
7745
0
                return "too many files";
7746
0
            case MZ_ZIP_FILE_TOO_LARGE:
7747
0
                return "file too large";
7748
0
            case MZ_ZIP_UNSUPPORTED_METHOD:
7749
0
                return "unsupported method";
7750
0
            case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
7751
0
                return "unsupported encryption";
7752
0
            case MZ_ZIP_UNSUPPORTED_FEATURE:
7753
0
                return "unsupported feature";
7754
0
            case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
7755
0
                return "failed finding central directory";
7756
0
            case MZ_ZIP_NOT_AN_ARCHIVE:
7757
0
                return "not a ZIP archive";
7758
0
            case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
7759
0
                return "invalid header or archive is corrupted";
7760
0
            case MZ_ZIP_UNSUPPORTED_MULTIDISK:
7761
0
                return "unsupported multidisk archive";
7762
0
            case MZ_ZIP_DECOMPRESSION_FAILED:
7763
0
                return "decompression failed or archive is corrupted";
7764
0
            case MZ_ZIP_COMPRESSION_FAILED:
7765
0
                return "compression failed";
7766
0
            case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
7767
0
                return "unexpected decompressed size";
7768
0
            case MZ_ZIP_CRC_CHECK_FAILED:
7769
0
                return "CRC-32 check failed";
7770
0
            case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
7771
0
                return "unsupported central directory size";
7772
0
            case MZ_ZIP_ALLOC_FAILED:
7773
0
                return "allocation failed";
7774
0
            case MZ_ZIP_FILE_OPEN_FAILED:
7775
0
                return "file open failed";
7776
0
            case MZ_ZIP_FILE_CREATE_FAILED:
7777
0
                return "file create failed";
7778
0
            case MZ_ZIP_FILE_WRITE_FAILED:
7779
0
                return "file write failed";
7780
0
            case MZ_ZIP_FILE_READ_FAILED:
7781
0
                return "file read failed";
7782
0
            case MZ_ZIP_FILE_CLOSE_FAILED:
7783
0
                return "file close failed";
7784
0
            case MZ_ZIP_FILE_SEEK_FAILED:
7785
0
                return "file seek failed";
7786
0
            case MZ_ZIP_FILE_STAT_FAILED:
7787
0
                return "file stat failed";
7788
0
            case MZ_ZIP_INVALID_PARAMETER:
7789
0
                return "invalid parameter";
7790
0
            case MZ_ZIP_INVALID_FILENAME:
7791
0
                return "invalid filename";
7792
0
            case MZ_ZIP_BUF_TOO_SMALL:
7793
0
                return "buffer too small";
7794
0
            case MZ_ZIP_INTERNAL_ERROR:
7795
0
                return "internal error";
7796
0
            case MZ_ZIP_FILE_NOT_FOUND:
7797
0
                return "file not found";
7798
0
            case MZ_ZIP_ARCHIVE_TOO_LARGE:
7799
0
                return "archive is too large";
7800
0
            case MZ_ZIP_VALIDATION_FAILED:
7801
0
                return "validation failed";
7802
0
            case MZ_ZIP_WRITE_CALLBACK_FAILED:
7803
0
                return "write callback failed";
7804
0
            case MZ_ZIP_TOTAL_ERRORS:
7805
0
                return "total errors";
7806
0
            default:
7807
0
                break;
7808
0
        }
7809
7810
0
        return "unknown error";
7811
0
    }
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
0
    {
7816
0
        if ((!pZip) || (!pZip->m_pState))
7817
0
            return MZ_FALSE;
7818
7819
0
        return pZip->m_pState->m_zip64;
7820
0
    }
7821
7822
    size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip)
7823
0
    {
7824
0
        if ((!pZip) || (!pZip->m_pState))
7825
0
            return 0;
7826
7827
0
        return pZip->m_pState->m_central_dir.m_size;
7828
0
    }
7829
7830
    mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
7831
3.50k
    {
7832
3.50k
        return pZip ? pZip->m_total_files : 0;
7833
3.50k
    }
7834
7835
    mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip)
7836
0
    {
7837
0
        if (!pZip)
7838
0
            return 0;
7839
0
        return pZip->m_archive_size;
7840
0
    }
7841
7842
    mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip)
7843
0
    {
7844
0
        if ((!pZip) || (!pZip->m_pState))
7845
0
            return 0;
7846
0
        return pZip->m_pState->m_file_archive_start_ofs;
7847
0
    }
7848
7849
    MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip)
7850
0
    {
7851
0
        if ((!pZip) || (!pZip->m_pState))
7852
0
            return 0;
7853
0
        return pZip->m_pState->m_pFile;
7854
0
    }
7855
7856
    size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
7857
0
    {
7858
0
        if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
7859
0
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7860
7861
0
        return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
7862
0
    }
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
30.0k
    {
7866
30.0k
        mz_uint n;
7867
30.0k
        const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
7868
30.0k
        if (!p)
7869
0
        {
7870
0
            if (filename_buf_size)
7871
0
                pFilename[0] = '\0';
7872
0
            mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7873
0
            return 0;
7874
0
        }
7875
30.0k
        n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
7876
30.0k
        if (filename_buf_size)
7877
30.0k
        {
7878
30.0k
            n = MZ_MIN(n, filename_buf_size - 1);
7879
30.0k
            memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
7880
30.0k
            pFilename[n] = '\0';
7881
30.0k
        }
7882
30.0k
        return n + 1;
7883
30.0k
    }
7884
7885
    mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
7886
60.7k
    {
7887
60.7k
        return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
7888
60.7k
    }
7889
7890
    mz_bool mz_zip_end(mz_zip_archive *pZip)
7891
0
    {
7892
0
        if (!pZip)
7893
0
            return MZ_FALSE;
7894
7895
0
        if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
7896
0
            return mz_zip_reader_end(pZip);
7897
0
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
7898
0
        else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))
7899
0
            return mz_zip_writer_end(pZip);
7900
0
#endif
7901
7902
0
        return MZ_FALSE;
7903
0
    }
7904
7905
#ifdef __cplusplus
7906
}
7907
#endif
7908
7909
#endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/