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