Coverage Report

Created: 2024-06-18 06:21

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