Coverage Report

Created: 2025-12-16 09:45

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