Coverage Report

Created: 2023-03-26 06:41

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