Coverage Report

Created: 2026-06-15 06:04

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