Coverage Report

Created: 2026-04-28 06:44

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