1 /* unzip.c -- IO for uncompress .zip files using zlib
2 Version 1.1, February 14h, 2010
3 part of the MiniZip project
4
5 Copyright (C) 1998-2010 Gilles Vollant
6 http://www.winimage.com/zLibDll/minizip.html
7 Modifications of Unzip for Zip64
8 Copyright (C) 2007-2008 Even Rouault
9 Modifications for Zip64 support on both zip and unzip
10 Copyright (C) 2009-2010 Mathias Svensson
11 http://result42.com
12 Modifications for AES, PKWARE disk spanning
13 Copyright (C) 2010-2014 Nathan Moinvaziri
14
15 This program is distributed under the terms of the same license as zlib.
16 See the accompanying LICENSE file for the full text of the license.
17 */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include <errno.h>
24
25 #include "zlib.h"
26 #include "unzip.h"
27
28 #ifdef HAVE_AES
29 # define AES_METHOD (99)
30 # define AES_PWVERIFYSIZE (2)
31 # define AES_MAXSALTLENGTH (16)
32 # define AES_AUTHCODESIZE (10)
33 # define AES_HEADERSIZE (11)
34 # define AES_KEYSIZE(mode) (64 + (mode * 64))
35
36 # include "aes/aes.h"
37 # include "aes/fileenc.h"
38 #endif
39 #ifdef HAVE_APPLE_COMPRESSION
40 # include <compression.h>
41 #endif
42
43 #ifndef NOUNCRYPT
44 # include "crypt.h"
45 #endif
46
47 #define DISKHEADERMAGIC (0x08074b50)
48 #define LOCALHEADERMAGIC (0x04034b50)
49 #define CENTRALHEADERMAGIC (0x02014b50)
50 #define ENDHEADERMAGIC (0x06054b50)
51 #define ZIP64ENDHEADERMAGIC (0x06064b50)
52 #define ZIP64ENDLOCHEADERMAGIC (0x07064b50)
53
54 #define SIZECENTRALDIRITEM (0x2e)
55 #define SIZECENTRALHEADERLOCATOR (0x14)
56 #define SIZEZIPLOCALHEADER (0x1e)
57
58 #ifndef BUFREADCOMMENT
59 # define BUFREADCOMMENT (0x400)
60 #endif
61
62 #ifndef UNZ_BUFSIZE
63 # define UNZ_BUFSIZE (UINT16_MAX)
64 #endif
65 #ifndef UNZ_MAXFILENAMEINZIP
66 # define UNZ_MAXFILENAMEINZIP (256)
67 #endif
68
69 #ifndef ALLOC
70 # define ALLOC(size) (malloc(size))
71 #endif
72 #ifndef TRYFREE
73 # define TRYFREE(p) {if (p) free(p);}
74 #endif
75
76 const char unz_copyright[] =
77 " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
78
79 /* unz_file_info_internal contain internal info about a file in zipfile*/
80 typedef struct unz_file_info64_internal_s
81 {
82 uint64_t offset_curfile; /* relative offset of local header 8 bytes */
83 uint64_t byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx) */
84 #ifdef HAVE_AES
85 uint8_t aes_encryption_mode;
86 uint16_t aes_compression_method;
87 uint16_t aes_version;
88 #endif
89 } unz_file_info64_internal;
90
91 /* file_in_zip_read_info_s contain internal information about a file in zipfile */
92 typedef struct
93 {
94 uint8_t *read_buffer; /* internal buffer for compressed data */
95 z_stream stream; /* zLib stream structure for inflate */
96 #ifdef HAVE_BZIP2
97 bz_stream bstream; /* bzLib stream structure for bziped */
98 #endif
99 #ifdef HAVE_APPLE_COMPRESSION
100 compression_stream astream; /* libcompression stream structure */
101 #endif
102 #ifdef HAVE_AES
103 fcrypt_ctx aes_ctx;
104 #endif
105 uint64_t pos_in_zipfile; /* position in byte on the zipfile, for fseek */
106 uint8_t stream_initialised; /* flag set if stream structure is initialised */
107
108 uint64_t offset_local_extrafield; /* offset of the local extra field */
109 uint16_t size_local_extrafield; /* size of the local extra field */
110 uint64_t pos_local_extrafield; /* position in the local extra field in read */
111 uint64_t total_out_64;
112
113 uint32_t crc32; /* crc32 of all data uncompressed */
114 uint32_t crc32_wait; /* crc32 we must obtain after decompress all */
115 uint64_t rest_read_compressed; /* number of byte to be decompressed */
116 uint64_t rest_read_uncompressed; /* number of byte to be obtained after decomp */
117
118 zlib_filefunc64_32_def z_filefunc;
119
120 voidpf filestream; /* io structore of the zipfile */
121 uint16_t compression_method; /* compression method (0==store) */
122 uint64_t byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx) */
123 int raw;
124 } file_in_zip64_read_info_s;
125
126 /* unz64_s contain internal information about the zipfile */
127 typedef struct
128 {
129 zlib_filefunc64_32_def z_filefunc;
130
131 voidpf filestream; /* io structure of the current zipfile */
132 voidpf filestream_with_CD; /* io structure of the disk with the central directory */
133
134 unz_global_info64 gi; /* public global information */
135
136 uint64_t byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx) */
137 uint64_t num_file; /* number of the current file in the zipfile */
138 uint64_t pos_in_central_dir; /* pos of the current file in the central dir */
139 uint64_t current_file_ok; /* flag about the usability of the current file */
140 uint64_t central_pos; /* position of the beginning of the central dir */
141 uint32_t number_disk; /* number of the current disk, used for spanning ZIP */
142 uint64_t size_central_dir; /* size of the central directory */
143 uint64_t offset_central_dir; /* offset of start of central directory with
144 respect to the starting disk number */
145
146 unz_file_info64 cur_file_info; /* public info about the current file in zip*/
147 unz_file_info64_internal cur_file_info_internal;
148 /* private info about it*/
149 file_in_zip64_read_info_s *pfile_in_zip_read;
150 /* structure about the current file if we are decompressing it */
151 int is_zip64; /* is the current file zip64 */
152 #ifndef NOUNCRYPT
153 uint32_t keys[3]; /* keys defining the pseudo-random sequence */
154 const z_crc_t *pcrc_32_tab;
155 #endif
156 } unz64_s;
157
158 /* Read a byte from a gz_stream; Return EOF for end of file. */
unzReadUInt8(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,uint8_t * value)159 static int unzReadUInt8(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint8_t *value)
160 {
161 uint8_t c = 0;
162 if (ZREAD64(*pzlib_filefunc_def, filestream, &c, 1) == 1)
163 {
164 *value = (uint8_t)c;
165 return UNZ_OK;
166 }
167 *value = 0;
168 if (ZERROR64(*pzlib_filefunc_def, filestream))
169 return UNZ_ERRNO;
170 return UNZ_EOF;
171 }
172
unzReadUInt16(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,uint16_t * value)173 static int unzReadUInt16(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint16_t *value)
174 {
175 uint16_t x;
176 uint8_t c = 0;
177 int err = UNZ_OK;
178
179 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
180 x = (uint16_t)c;
181 if (err == UNZ_OK)
182 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
183 x |= ((uint16_t)c) << 8;
184
185 if (err == UNZ_OK)
186 *value = x;
187 else
188 *value = 0;
189 return err;
190 }
191
unzReadUInt32(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,uint32_t * value)192 static int unzReadUInt32(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint32_t *value)
193 {
194 uint32_t x = 0;
195 uint8_t c = 0;
196 int err = UNZ_OK;
197
198 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
199 x = (uint32_t)c;
200 if (err == UNZ_OK)
201 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
202 x |= ((uint32_t)c) << 8;
203 if (err == UNZ_OK)
204 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
205 x |= ((uint32_t)c) << 16;
206 if (err == UNZ_OK)
207 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
208 x += ((uint32_t)c) << 24;
209
210 if (err == UNZ_OK)
211 *value = x;
212 else
213 *value = 0;
214 return err;
215 }
216
unzReadUInt64(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,uint64_t * value)217 static int unzReadUInt64(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint64_t *value)
218 {
219 uint64_t x = 0;
220 uint8_t i = 0;
221 int err = UNZ_OK;
222
223 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
224 x = (uint64_t)i;
225 if (err == UNZ_OK)
226 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
227 x |= ((uint64_t)i) << 8;
228 if (err == UNZ_OK)
229 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
230 x |= ((uint64_t)i) << 16;
231 if (err == UNZ_OK)
232 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
233 x |= ((uint64_t)i) << 24;
234 if (err == UNZ_OK)
235 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
236 x |= ((uint64_t)i) << 32;
237 if (err == UNZ_OK)
238 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
239 x |= ((uint64_t)i) << 40;
240 if (err == UNZ_OK)
241 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
242 x |= ((uint64_t)i) << 48;
243 if (err == UNZ_OK)
244 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
245 x |= ((uint64_t)i) << 56;
246
247 if (err == UNZ_OK)
248 *value = x;
249 else
250 *value = 0;
251 return err;
252 }
253
254 /* Locate the Central directory of a zip file (at the end, just before the global comment) */
unzSearchCentralDir(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream)255 static uint64_t unzSearchCentralDir(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream)
256 {
257 uint8_t buf[BUFREADCOMMENT + 4];
258 uint64_t file_size = 0;
259 uint64_t back_read = 4;
260 uint64_t max_back = UINT16_MAX; /* maximum size of global comment */
261 uint64_t pos_found = 0;
262 uint32_t read_size = 0;
263 uint64_t read_pos = 0;
264 uint32_t i = 0;
265
266 if (ZSEEK64(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
267 return 0;
268
269 file_size = ZTELL64(*pzlib_filefunc_def, filestream);
270
271 if (max_back > file_size)
272 max_back = file_size;
273
274 while (back_read < max_back)
275 {
276 if (back_read + BUFREADCOMMENT > max_back)
277 back_read = max_back;
278 else
279 back_read += BUFREADCOMMENT;
280
281 read_pos = file_size - back_read;
282 read_size = ((BUFREADCOMMENT + 4) < (file_size - read_pos)) ?
283 (BUFREADCOMMENT + 4) : (uint32_t)(file_size - read_pos);
284
285 if (ZSEEK64(*pzlib_filefunc_def, filestream, read_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
286 break;
287 if (ZREAD64(*pzlib_filefunc_def, filestream, buf, read_size) != read_size)
288 break;
289
290 for (i = read_size - 3; (i--) > 0;)
291 if (((*(buf+i)) == (ENDHEADERMAGIC & 0xff)) &&
292 ((*(buf+i+1)) == (ENDHEADERMAGIC >> 8 & 0xff)) &&
293 ((*(buf+i+2)) == (ENDHEADERMAGIC >> 16 & 0xff)) &&
294 ((*(buf+i+3)) == (ENDHEADERMAGIC >> 24 & 0xff)))
295 {
296 pos_found = read_pos+i;
297 break;
298 }
299
300 if (pos_found != 0)
301 break;
302 }
303
304 return pos_found;
305 }
306
307 /* Locate the Central directory 64 of a zipfile (at the end, just before the global comment) */
unzSearchCentralDir64(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,const uint64_t endcentraloffset)308 static uint64_t unzSearchCentralDir64(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream,
309 const uint64_t endcentraloffset)
310 {
311 uint64_t offset = 0;
312 uint32_t value32 = 0;
313
314 /* Zip64 end of central directory locator */
315 if (ZSEEK64(*pzlib_filefunc_def, filestream, endcentraloffset - SIZECENTRALHEADERLOCATOR, ZLIB_FILEFUNC_SEEK_SET) != 0)
316 return 0;
317
318 /* Read locator signature */
319 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
320 return 0;
321 if (value32 != ZIP64ENDLOCHEADERMAGIC)
322 return 0;
323 /* Number of the disk with the start of the zip64 end of central directory */
324 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
325 return 0;
326 /* Relative offset of the zip64 end of central directory record */
327 if (unzReadUInt64(pzlib_filefunc_def, filestream, &offset) != UNZ_OK)
328 return 0;
329 /* Total number of disks */
330 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
331 return 0;
332 /* Goto end of central directory record */
333 if (ZSEEK64(*pzlib_filefunc_def, filestream, offset, ZLIB_FILEFUNC_SEEK_SET) != 0)
334 return 0;
335 /* The signature */
336 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
337 return 0;
338 if (value32 != ZIP64ENDHEADERMAGIC)
339 return 0;
340
341 return offset;
342 }
343
unzOpenInternal(const void * path,zlib_filefunc64_32_def * pzlib_filefunc64_32_def)344 static unzFile unzOpenInternal(const void *path, zlib_filefunc64_32_def *pzlib_filefunc64_32_def)
345 {
346 unz64_s us;
347 unz64_s *s = NULL;
348 uint64_t central_pos = 0;
349 uint64_t central_pos64 = 0;
350 uint64_t number_entry_CD = 0;
351 uint16_t value16 = 0;
352 uint32_t value32 = 0;
353 uint64_t value64 = 0;
354 voidpf filestream = NULL;
355 int err = UNZ_OK;
356
357 if (unz_copyright[0] != ' ')
358 return NULL;
359
360 us.filestream = NULL;
361 us.filestream_with_CD = NULL;
362 us.z_filefunc.zseek32_file = NULL;
363 us.z_filefunc.ztell32_file = NULL;
364
365 if (pzlib_filefunc64_32_def == NULL)
366 fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
367 else
368 us.z_filefunc = *pzlib_filefunc64_32_def;
369
370 us.filestream = ZOPEN64(us.z_filefunc, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
371
372 if (us.filestream == NULL)
373 return NULL;
374
375 us.filestream_with_CD = us.filestream;
376 us.is_zip64 = 0;
377
378 /* Search for end of central directory header */
379 central_pos = unzSearchCentralDir(&us.z_filefunc, us.filestream);
380 if (central_pos)
381 {
382 if (ZSEEK64(us.z_filefunc, us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
383 err = UNZ_ERRNO;
384
385 /* The signature, already checked */
386 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
387 err = UNZ_ERRNO;
388 /* Number of this disk */
389 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
390 err = UNZ_ERRNO;
391 us.number_disk = value16;
392 /* Number of the disk with the start of the central directory */
393 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
394 err = UNZ_ERRNO;
395 us.gi.number_disk_with_CD = value16;
396 /* Total number of entries in the central directory on this disk */
397 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
398 err = UNZ_ERRNO;
399 us.gi.number_entry = value16;
400 /* Total number of entries in the central directory */
401 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
402 err = UNZ_ERRNO;
403 number_entry_CD = value16;
404 if (number_entry_CD != us.gi.number_entry)
405 err = UNZ_BADZIPFILE;
406 /* Size of the central directory */
407 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
408 err = UNZ_ERRNO;
409 us.size_central_dir = value32;
410 /* Offset of start of central directory with respect to the starting disk number */
411 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
412 err = UNZ_ERRNO;
413 us.offset_central_dir = value32;
414 /* Zipfile comment length */
415 if (unzReadUInt16(&us.z_filefunc, us.filestream, &us.gi.size_comment) != UNZ_OK)
416 err = UNZ_ERRNO;
417
418 if (err == UNZ_OK)
419 {
420 /* Search for Zip64 end of central directory header */
421 central_pos64 = unzSearchCentralDir64(&us.z_filefunc, us.filestream, central_pos);
422 if (central_pos64)
423 {
424 central_pos = central_pos64;
425 us.is_zip64 = 1;
426
427 if (ZSEEK64(us.z_filefunc, us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
428 err = UNZ_ERRNO;
429
430 /* the signature, already checked */
431 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
432 err = UNZ_ERRNO;
433 /* size of zip64 end of central directory record */
434 if (unzReadUInt64(&us.z_filefunc, us.filestream, &value64) != UNZ_OK)
435 err = UNZ_ERRNO;
436 /* version made by */
437 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
438 err = UNZ_ERRNO;
439 /* version needed to extract */
440 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
441 err = UNZ_ERRNO;
442 /* number of this disk */
443 if (unzReadUInt32(&us.z_filefunc, us.filestream, &us.number_disk) != UNZ_OK)
444 err = UNZ_ERRNO;
445 /* number of the disk with the start of the central directory */
446 if (unzReadUInt32(&us.z_filefunc, us.filestream, &us.gi.number_disk_with_CD) != UNZ_OK)
447 err = UNZ_ERRNO;
448 /* total number of entries in the central directory on this disk */
449 if (unzReadUInt64(&us.z_filefunc, us.filestream, &us.gi.number_entry) != UNZ_OK)
450 err = UNZ_ERRNO;
451 /* total number of entries in the central directory */
452 if (unzReadUInt64(&us.z_filefunc, us.filestream, &number_entry_CD) != UNZ_OK)
453 err = UNZ_ERRNO;
454 if (number_entry_CD != us.gi.number_entry)
455 err = UNZ_BADZIPFILE;
456 /* size of the central directory */
457 if (unzReadUInt64(&us.z_filefunc, us.filestream, &us.size_central_dir) != UNZ_OK)
458 err = UNZ_ERRNO;
459 /* offset of start of central directory with respect to the starting disk number */
460 if (unzReadUInt64(&us.z_filefunc, us.filestream, &us.offset_central_dir) != UNZ_OK)
461 err = UNZ_ERRNO;
462 }
463 else if ((us.gi.number_entry == UINT16_MAX) || (us.size_central_dir == UINT16_MAX) || (us.offset_central_dir == UINT32_MAX))
464 err = UNZ_BADZIPFILE;
465 }
466 }
467 else
468 err = UNZ_ERRNO;
469
470 if ((err == UNZ_OK) && (central_pos < us.offset_central_dir + us.size_central_dir))
471 err = UNZ_BADZIPFILE;
472
473 if (err != UNZ_OK)
474 {
475 ZCLOSE64(us.z_filefunc, us.filestream);
476 return NULL;
477 }
478
479 if (us.gi.number_disk_with_CD == 0)
480 {
481 /* If there is only one disk open another stream so we don't have to seek between the CD
482 and the file headers constantly */
483 filestream = ZOPEN64(us.z_filefunc, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
484 if (filestream != NULL)
485 us.filestream = filestream;
486 }
487
488 /* Hack for zip files that have no respect for zip64
489 if ((central_pos > 0xffffffff) && (us.offset_central_dir < 0xffffffff))
490 us.offset_central_dir = central_pos - us.size_central_dir;*/
491
492 us.byte_before_the_zipfile = central_pos - (us.offset_central_dir + us.size_central_dir);
493 us.central_pos = central_pos;
494 us.pfile_in_zip_read = NULL;
495
496 s = (unz64_s*)ALLOC(sizeof(unz64_s));
497 if (s != NULL)
498 {
499 *s = us;
500 unzGoToFirstFile((unzFile)s);
501 }
502 return (unzFile)s;
503 }
504
unzOpen2(const char * path,zlib_filefunc_def * pzlib_filefunc32_def)505 extern unzFile ZEXPORT unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc32_def)
506 {
507 if (pzlib_filefunc32_def != NULL)
508 {
509 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
510 fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill, pzlib_filefunc32_def);
511 return unzOpenInternal(path, &zlib_filefunc64_32_def_fill);
512 }
513 return unzOpenInternal(path, NULL);
514 }
515
unzOpen2_64(const void * path,zlib_filefunc64_def * pzlib_filefunc_def)516 extern unzFile ZEXPORT unzOpen2_64(const void *path, zlib_filefunc64_def *pzlib_filefunc_def)
517 {
518 if (pzlib_filefunc_def != NULL)
519 {
520 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
521 zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
522 zlib_filefunc64_32_def_fill.ztell32_file = NULL;
523 zlib_filefunc64_32_def_fill.zseek32_file = NULL;
524 return unzOpenInternal(path, &zlib_filefunc64_32_def_fill);
525 }
526 return unzOpenInternal(path, NULL);
527 }
528
unzOpen(const char * path)529 extern unzFile ZEXPORT unzOpen(const char *path)
530 {
531 return unzOpenInternal(path, NULL);
532 }
533
unzOpen64(const void * path)534 extern unzFile ZEXPORT unzOpen64(const void *path)
535 {
536 return unzOpenInternal(path, NULL);
537 }
538
unzClose(unzFile file)539 extern int ZEXPORT unzClose(unzFile file)
540 {
541 unz64_s *s;
542 if (file == NULL)
543 return UNZ_PARAMERROR;
544 s = (unz64_s*)file;
545
546 if (s->pfile_in_zip_read != NULL)
547 unzCloseCurrentFile(file);
548
549 if ((s->filestream != NULL) && (s->filestream != s->filestream_with_CD))
550 ZCLOSE64(s->z_filefunc, s->filestream);
551 if (s->filestream_with_CD != NULL)
552 ZCLOSE64(s->z_filefunc, s->filestream_with_CD);
553
554 s->filestream = NULL;
555 s->filestream_with_CD = NULL;
556 TRYFREE(s);
557 return UNZ_OK;
558 }
559
560 /* Goto to the next available disk for spanned archives */
unzGoToNextDisk(unzFile file)561 static int unzGoToNextDisk(unzFile file)
562 {
563 unz64_s *s;
564 uint32_t number_disk_next = 0;
565
566 s = (unz64_s*)file;
567 if (s == NULL)
568 return UNZ_PARAMERROR;
569 number_disk_next = s->number_disk;
570
571 if ((s->pfile_in_zip_read != NULL) && (s->pfile_in_zip_read->rest_read_uncompressed > 0))
572 /* We are currently reading a file and we need the next sequential disk */
573 number_disk_next += 1;
574 else
575 /* Goto the disk for the current file */
576 number_disk_next = s->cur_file_info.disk_num_start;
577
578 if (number_disk_next != s->number_disk)
579 {
580 /* Switch disks */
581 if ((s->filestream != NULL) && (s->filestream != s->filestream_with_CD))
582 ZCLOSE64(s->z_filefunc, s->filestream);
583
584 if (number_disk_next == s->gi.number_disk_with_CD)
585 {
586 s->filestream = s->filestream_with_CD;
587 }
588 else
589 {
590 s->filestream = ZOPENDISK64(s->z_filefunc, s->filestream_with_CD, number_disk_next,
591 ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
592 }
593
594 if (s->filestream == NULL)
595 return UNZ_ERRNO;
596
597 s->number_disk = number_disk_next;
598 }
599
600 return UNZ_OK;
601 }
602
unzGetGlobalInfo(unzFile file,unz_global_info * pglobal_info32)603 extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32)
604 {
605 unz64_s *s = NULL;
606 if (file == NULL)
607 return UNZ_PARAMERROR;
608 s = (unz64_s*)file;
609
610 pglobal_info32->number_entry = (uint32_t)s->gi.number_entry;
611 pglobal_info32->size_comment = s->gi.size_comment;
612 pglobal_info32->number_disk_with_CD = s->gi.number_disk_with_CD;
613 return UNZ_OK;
614 }
615
unzGetGlobalInfo64(unzFile file,unz_global_info64 * pglobal_info)616 extern int ZEXPORT unzGetGlobalInfo64(unzFile file, unz_global_info64 *pglobal_info)
617 {
618 unz64_s *s = NULL;
619 if (file == NULL)
620 return UNZ_PARAMERROR;
621 s = (unz64_s*)file;
622 *pglobal_info = s->gi;
623 return UNZ_OK;
624 }
625
unzGetGlobalComment(unzFile file,char * comment,uint16_t comment_size)626 extern int ZEXPORT unzGetGlobalComment(unzFile file, char *comment, uint16_t comment_size)
627 {
628 unz64_s *s = NULL;
629 uint16_t bytes_to_read = comment_size;
630 if (file == NULL)
631 return (int)UNZ_PARAMERROR;
632 s = (unz64_s*)file;
633
634 if (bytes_to_read > s->gi.size_comment)
635 bytes_to_read = s->gi.size_comment;
636
637 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, s->central_pos + 22, ZLIB_FILEFUNC_SEEK_SET) != 0)
638 return UNZ_ERRNO;
639
640 if (bytes_to_read > 0)
641 {
642 *comment = 0;
643 if (ZREAD64(s->z_filefunc, s->filestream_with_CD, comment, bytes_to_read) != bytes_to_read)
644 return UNZ_ERRNO;
645 }
646
647 if ((comment != NULL) && (comment_size > s->gi.size_comment))
648 *(comment + s->gi.size_comment) = 0;
649
650 return (int)bytes_to_read;
651 }
652
unzGetCurrentFileInfoField(unzFile file,uint32_t * seek,void * field,uint16_t field_size,uint16_t size_file_field,int null_terminated_field)653 static int unzGetCurrentFileInfoField(unzFile file, uint32_t *seek, void *field, uint16_t field_size, uint16_t size_file_field, int null_terminated_field)
654 {
655 unz64_s *s = NULL;
656 uint32_t bytes_to_read = 0;
657 int err = UNZ_OK;
658
659 if (file == NULL)
660 return (int)UNZ_PARAMERROR;
661 s = (unz64_s*)file;
662
663 /* Read field */
664 if (field != NULL)
665 {
666 if (size_file_field < field_size)
667 {
668 if (null_terminated_field)
669 *((char *)field+size_file_field) = 0;
670
671 bytes_to_read = size_file_field;
672 }
673 else
674 bytes_to_read = field_size;
675
676 if (*seek != 0)
677 {
678 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, *seek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
679 *seek = 0;
680 else
681 err = UNZ_ERRNO;
682 }
683
684 if ((size_file_field > 0) && (field_size > 0))
685 {
686 if (ZREAD64(s->z_filefunc, s->filestream_with_CD, field, bytes_to_read) != bytes_to_read)
687 err = UNZ_ERRNO;
688 }
689 *seek += size_file_field - bytes_to_read;
690 }
691 else
692 {
693 *seek += size_file_field;
694 }
695
696 return err;
697 }
698
699 /* Get info about the current file in the zipfile, with internal only info */
unzGetCurrentFileInfoInternal(unzFile file,unz_file_info64 * pfile_info,unz_file_info64_internal * pfile_info_internal,char * filename,uint16_t filename_size,void * extrafield,uint16_t extrafield_size,char * comment,uint16_t comment_size)700 static int unzGetCurrentFileInfoInternal(unzFile file, unz_file_info64 *pfile_info,
701 unz_file_info64_internal *pfile_info_internal, char *filename, uint16_t filename_size, void *extrafield,
702 uint16_t extrafield_size, char *comment, uint16_t comment_size)
703 {
704 unz64_s *s = NULL;
705 unz_file_info64 file_info;
706 unz_file_info64_internal file_info_internal;
707 uint32_t magic = 0;
708 uint64_t current_pos = 0;
709 uint32_t seek = 0;
710 uint32_t extra_pos = 0;
711 uint16_t extra_header_id = 0;
712 uint16_t extra_data_size = 0;
713 uint16_t value16 = 0;
714 uint32_t value32 = 0;
715 uint64_t value64 = 0;
716 int err = UNZ_OK;
717
718 if (file == NULL)
719 return UNZ_PARAMERROR;
720 s = (unz64_s*)file;
721
722 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD,
723 s->pos_in_central_dir + s->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
724 err = UNZ_ERRNO;
725
726 /* Check the magic */
727 if (err == UNZ_OK)
728 {
729 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &magic) != UNZ_OK)
730 err = UNZ_ERRNO;
731 else if (magic != CENTRALHEADERMAGIC)
732 err = UNZ_BADZIPFILE;
733 }
734
735 /* Read central directory header */
736 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.version) != UNZ_OK)
737 err = UNZ_ERRNO;
738 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.version_needed) != UNZ_OK)
739 err = UNZ_ERRNO;
740 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.flag) != UNZ_OK)
741 err = UNZ_ERRNO;
742 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.compression_method) != UNZ_OK)
743 err = UNZ_ERRNO;
744 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.dos_date) != UNZ_OK)
745 err = UNZ_ERRNO;
746 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.crc) != UNZ_OK)
747 err = UNZ_ERRNO;
748 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &value32) != UNZ_OK)
749 err = UNZ_ERRNO;
750 file_info.compressed_size = value32;
751 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &value32) != UNZ_OK)
752 err = UNZ_ERRNO;
753 file_info.uncompressed_size = value32;
754 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.size_filename) != UNZ_OK)
755 err = UNZ_ERRNO;
756 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.size_file_extra) != UNZ_OK)
757 err = UNZ_ERRNO;
758 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.size_file_comment) != UNZ_OK)
759 err = UNZ_ERRNO;
760 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &value16) != UNZ_OK)
761 err = UNZ_ERRNO;
762 file_info.disk_num_start = value16;
763 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.internal_fa) != UNZ_OK)
764 err = UNZ_ERRNO;
765 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.external_fa) != UNZ_OK)
766 err = UNZ_ERRNO;
767 /* Relative offset of local header */
768 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &value32) != UNZ_OK)
769 err = UNZ_ERRNO;
770
771 file_info.size_file_extra_internal = 0;
772 file_info.disk_offset = value32;
773 file_info_internal.offset_curfile = value32;
774 #ifdef HAVE_AES
775 file_info_internal.aes_compression_method = 0;
776 file_info_internal.aes_encryption_mode = 0;
777 file_info_internal.aes_version = 0;
778 #endif
779
780 if (err == UNZ_OK)
781 err = unzGetCurrentFileInfoField(file, &seek, filename, filename_size, file_info.size_filename, 1);
782
783 /* Read extrafield */
784 if (err == UNZ_OK)
785 err = unzGetCurrentFileInfoField(file, &seek, extrafield, extrafield_size, file_info.size_file_extra, 0);
786
787 if ((err == UNZ_OK) && (file_info.size_file_extra != 0))
788 {
789 if (seek != 0)
790 {
791 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, seek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
792 seek = 0;
793 else
794 err = UNZ_ERRNO;
795 }
796
797 /* We are going to parse the extra field so we need to move back */
798 current_pos = ZTELL64(s->z_filefunc, s->filestream_with_CD);
799 if (current_pos < file_info.size_file_extra)
800 err = UNZ_ERRNO;
801 current_pos -= file_info.size_file_extra;
802 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, current_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
803 err = UNZ_ERRNO;
804
805 while ((err != UNZ_ERRNO) && (extra_pos < file_info.size_file_extra))
806 {
807 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &extra_header_id) != UNZ_OK)
808 err = UNZ_ERRNO;
809 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &extra_data_size) != UNZ_OK)
810 err = UNZ_ERRNO;
811
812 /* ZIP64 extra fields */
813 if (extra_header_id == 0x0001)
814 {
815 /* Subtract size of ZIP64 field, since ZIP64 is handled internally */
816 file_info.size_file_extra_internal += 2 + 2 + extra_data_size;
817
818 if (file_info.uncompressed_size == UINT32_MAX)
819 {
820 if (unzReadUInt64(&s->z_filefunc, s->filestream_with_CD, &file_info.uncompressed_size) != UNZ_OK)
821 err = UNZ_ERRNO;
822 }
823 if (file_info.compressed_size == UINT32_MAX)
824 {
825 if (unzReadUInt64(&s->z_filefunc, s->filestream_with_CD, &file_info.compressed_size) != UNZ_OK)
826 err = UNZ_ERRNO;
827 }
828 if (file_info_internal.offset_curfile == UINT32_MAX)
829 {
830 /* Relative Header offset */
831 if (unzReadUInt64(&s->z_filefunc, s->filestream_with_CD, &value64) != UNZ_OK)
832 err = UNZ_ERRNO;
833 file_info_internal.offset_curfile = value64;
834 file_info.disk_offset = value64;
835 }
836 if (file_info.disk_num_start == UINT32_MAX)
837 {
838 /* Disk Start Number */
839 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.disk_num_start) != UNZ_OK)
840 err = UNZ_ERRNO;
841 }
842 }
843 #ifdef HAVE_AES
844 /* AES header */
845 else if (extra_header_id == 0x9901)
846 {
847 uint8_t value8 = 0;
848
849 /* Subtract size of AES field, since AES is handled internally */
850 file_info.size_file_extra_internal += 2 + 2 + extra_data_size;
851
852 /* Verify version info */
853 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &value16) != UNZ_OK)
854 err = UNZ_ERRNO;
855 /* Support AE-1 and AE-2 */
856 if (value16 != 1 && value16 != 2)
857 err = UNZ_ERRNO;
858 file_info_internal.aes_version = value16;
859 if (unzReadUInt8(&s->z_filefunc, s->filestream_with_CD, &value8) != UNZ_OK)
860 err = UNZ_ERRNO;
861 if ((char)value8 != 'A')
862 err = UNZ_ERRNO;
863 if (unzReadUInt8(&s->z_filefunc, s->filestream_with_CD, &value8) != UNZ_OK)
864 err = UNZ_ERRNO;
865 if ((char)value8 != 'E')
866 err = UNZ_ERRNO;
867 /* Get AES encryption strength and actual compression method */
868 if (unzReadUInt8(&s->z_filefunc, s->filestream_with_CD, &value8) != UNZ_OK)
869 err = UNZ_ERRNO;
870 file_info_internal.aes_encryption_mode = value8;
871 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &value16) != UNZ_OK)
872 err = UNZ_ERRNO;
873 file_info_internal.aes_compression_method = value16;
874 }
875 #endif
876 else
877 {
878 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD,extra_data_size, ZLIB_FILEFUNC_SEEK_CUR) != 0)
879 err = UNZ_ERRNO;
880 }
881
882 extra_pos += 2 + 2 + extra_data_size;
883 }
884 }
885
886 if (file_info.disk_num_start == s->gi.number_disk_with_CD)
887 file_info_internal.byte_before_the_zipfile = s->byte_before_the_zipfile;
888 else
889 file_info_internal.byte_before_the_zipfile = 0;
890
891 if (err == UNZ_OK)
892 err = unzGetCurrentFileInfoField(file, &seek, comment, comment_size, file_info.size_file_comment, 1);
893
894 if ((err == UNZ_OK) && (pfile_info != NULL))
895 *pfile_info = file_info;
896 if ((err == UNZ_OK) && (pfile_info_internal != NULL))
897 *pfile_info_internal = file_info_internal;
898
899 return err;
900 }
901
unzGetCurrentFileInfo(unzFile file,unz_file_info * pfile_info,char * filename,uint16_t filename_size,void * extrafield,uint16_t extrafield_size,char * comment,uint16_t comment_size)902 extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *filename,
903 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
904 {
905 unz_file_info64 file_info64;
906 int err = UNZ_OK;
907
908 err = unzGetCurrentFileInfoInternal(file, &file_info64, NULL, filename, filename_size,
909 extrafield, extrafield_size, comment, comment_size);
910
911 if ((err == UNZ_OK) && (pfile_info != NULL))
912 {
913 pfile_info->version = file_info64.version;
914 pfile_info->version_needed = file_info64.version_needed;
915 pfile_info->flag = file_info64.flag;
916 pfile_info->compression_method = file_info64.compression_method;
917 pfile_info->dos_date = file_info64.dos_date;
918 pfile_info->crc = file_info64.crc;
919
920 pfile_info->size_filename = file_info64.size_filename;
921 pfile_info->size_file_extra = file_info64.size_file_extra - file_info64.size_file_extra_internal;
922 pfile_info->size_file_comment = file_info64.size_file_comment;
923
924 pfile_info->disk_num_start = (uint16_t)file_info64.disk_num_start;
925 pfile_info->internal_fa = file_info64.internal_fa;
926 pfile_info->external_fa = file_info64.external_fa;
927
928 pfile_info->compressed_size = (uint32_t)file_info64.compressed_size;
929 pfile_info->uncompressed_size = (uint32_t)file_info64.uncompressed_size;
930 }
931 return err;
932 }
933
unzGetCurrentFileInfo64(unzFile file,unz_file_info64 * pfile_info,char * filename,uint16_t filename_size,void * extrafield,uint16_t extrafield_size,char * comment,uint16_t comment_size)934 extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file, unz_file_info64 * pfile_info, char *filename,
935 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
936 {
937 return unzGetCurrentFileInfoInternal(file, pfile_info, NULL, filename, filename_size,
938 extrafield, extrafield_size, comment,comment_size);
939 }
940
941 /* Read the local header of the current zipfile. Check the coherency of the local header and info in the
942 end of central directory about this file store in *piSizeVar the size of extra info in local header
943 (filename and size of extra field data) */
unzCheckCurrentFileCoherencyHeader(unz64_s * s,uint32_t * psize_variable,uint64_t * poffset_local_extrafield,uint16_t * psize_local_extrafield)944 static int unzCheckCurrentFileCoherencyHeader(unz64_s *s, uint32_t *psize_variable, uint64_t *poffset_local_extrafield,
945 uint16_t *psize_local_extrafield)
946 {
947 uint32_t magic = 0;
948 uint16_t value16 = 0;
949 uint32_t value32 = 0;
950 uint32_t flags = 0;
951 uint16_t size_filename = 0;
952 uint16_t size_extra_field = 0;
953 uint16_t compression_method = 0;
954 int err = UNZ_OK;
955
956 if (psize_variable == NULL)
957 return UNZ_PARAMERROR;
958 *psize_variable = 0;
959 if (poffset_local_extrafield == NULL)
960 return UNZ_PARAMERROR;
961 *poffset_local_extrafield = 0;
962 if (psize_local_extrafield == NULL)
963 return UNZ_PARAMERROR;
964 *psize_local_extrafield = 0;
965
966 err = unzGoToNextDisk((unzFile)s);
967 if (err != UNZ_OK)
968 return err;
969
970 if (ZSEEK64(s->z_filefunc, s->filestream, s->cur_file_info_internal.offset_curfile +
971 s->cur_file_info_internal.byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
972 return UNZ_ERRNO;
973
974 if (err == UNZ_OK)
975 {
976 if (unzReadUInt32(&s->z_filefunc, s->filestream, &magic) != UNZ_OK)
977 err = UNZ_ERRNO;
978 else if (magic != LOCALHEADERMAGIC)
979 err = UNZ_BADZIPFILE;
980 }
981
982 if (unzReadUInt16(&s->z_filefunc, s->filestream, &value16) != UNZ_OK)
983 err = UNZ_ERRNO;
984 if (unzReadUInt16(&s->z_filefunc, s->filestream, &value16) != UNZ_OK)
985 err = UNZ_ERRNO;
986 flags = value16;
987 if (unzReadUInt16(&s->z_filefunc, s->filestream, &value16) != UNZ_OK)
988 err = UNZ_ERRNO;
989 else if ((err == UNZ_OK) && (value16 != s->cur_file_info.compression_method))
990 err = UNZ_BADZIPFILE;
991
992 compression_method = s->cur_file_info.compression_method;
993 #ifdef HAVE_AES
994 if (compression_method == AES_METHOD)
995 compression_method = s->cur_file_info_internal.aes_compression_method;
996 #endif
997
998 if ((err == UNZ_OK) && (compression_method != 0) && (compression_method != Z_DEFLATED))
999 {
1000 #ifdef HAVE_BZIP2
1001 if (compression_method != Z_BZIP2ED)
1002 #endif
1003 err = UNZ_BADZIPFILE;
1004 }
1005
1006 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* date/time */
1007 err = UNZ_ERRNO;
1008 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* crc */
1009 err = UNZ_ERRNO;
1010 else if ((err == UNZ_OK) && (value32 != s->cur_file_info.crc) && ((flags & 8) == 0))
1011 err = UNZ_BADZIPFILE;
1012 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* size compr */
1013 err = UNZ_ERRNO;
1014 else if ((value32 != UINT32_MAX) && (err == UNZ_OK) && (value32 != s->cur_file_info.compressed_size) && ((flags & 8) == 0))
1015 err = UNZ_BADZIPFILE;
1016 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* size uncompr */
1017 err = UNZ_ERRNO;
1018 else if ((value32 != UINT32_MAX) && (err == UNZ_OK) && (value32 != s->cur_file_info.uncompressed_size) && ((flags & 8) == 0))
1019 err = UNZ_BADZIPFILE;
1020 if (unzReadUInt16(&s->z_filefunc, s->filestream, &size_filename) != UNZ_OK)
1021 err = UNZ_ERRNO;
1022 else if ((err == UNZ_OK) && (size_filename != s->cur_file_info.size_filename))
1023 err = UNZ_BADZIPFILE;
1024
1025 *psize_variable += size_filename;
1026
1027 if (unzReadUInt16(&s->z_filefunc, s->filestream, &size_extra_field) != UNZ_OK)
1028 err = UNZ_ERRNO;
1029
1030 *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_filename;
1031 *psize_local_extrafield = size_extra_field;
1032 *psize_variable += size_extra_field;
1033
1034 return err;
1035 }
1036
1037 /*
1038 Open for reading data the current file in the zipfile.
1039 If there is no error and the file is opened, the return value is UNZ_OK.
1040 */
unzOpenCurrentFile3(unzFile file,int * method,int * level,int raw,const char * password)1041 extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password)
1042 {
1043 unz64_s *s = NULL;
1044 file_in_zip64_read_info_s *pfile_in_zip_read_info = NULL;
1045 uint16_t compression_method = 0;
1046 uint64_t offset_local_extrafield = 0;
1047 uint16_t size_local_extrafield = 0;
1048 uint32_t size_variable = 0;
1049 int err = UNZ_OK;
1050 #ifndef NOUNCRYPT
1051 char source[12];
1052 #else
1053 if (password != NULL)
1054 return UNZ_PARAMERROR;
1055 #endif
1056 if (file == NULL)
1057 return UNZ_PARAMERROR;
1058 s = (unz64_s*)file;
1059 if (!s->current_file_ok)
1060 return UNZ_PARAMERROR;
1061
1062 if (s->pfile_in_zip_read != NULL)
1063 unzCloseCurrentFile(file);
1064
1065 if (unzCheckCurrentFileCoherencyHeader(s, &size_variable, &offset_local_extrafield, &size_local_extrafield) != UNZ_OK)
1066 return UNZ_BADZIPFILE;
1067
1068 pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
1069 if (pfile_in_zip_read_info == NULL)
1070 return UNZ_INTERNALERROR;
1071
1072 pfile_in_zip_read_info->read_buffer = (uint8_t*)ALLOC(UNZ_BUFSIZE);
1073 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1074 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1075 pfile_in_zip_read_info->pos_local_extrafield = 0;
1076 pfile_in_zip_read_info->raw = raw;
1077
1078 if (pfile_in_zip_read_info->read_buffer == NULL)
1079 {
1080 TRYFREE(pfile_in_zip_read_info);
1081 return UNZ_INTERNALERROR;
1082 }
1083
1084 pfile_in_zip_read_info->stream_initialised = 0;
1085
1086 compression_method = s->cur_file_info.compression_method;
1087 #ifdef HAVE_AES
1088 if (compression_method == AES_METHOD)
1089 {
1090 compression_method = s->cur_file_info_internal.aes_compression_method;
1091 if (password == NULL)
1092 {
1093 TRYFREE(pfile_in_zip_read_info);
1094 return UNZ_PARAMERROR;
1095 }
1096 }
1097 #endif
1098
1099 if (method != NULL)
1100 *method = compression_method;
1101
1102 if (level != NULL)
1103 {
1104 *level = 6;
1105 switch (s->cur_file_info.flag & 0x06)
1106 {
1107 case 6 : *level = 1; break;
1108 case 4 : *level = 2; break;
1109 case 2 : *level = 9; break;
1110 }
1111 }
1112
1113 if ((compression_method != 0) && (compression_method != Z_DEFLATED))
1114 {
1115 #ifdef HAVE_BZIP2
1116 if (compression_method != Z_BZIP2ED)
1117 #endif
1118 {
1119 TRYFREE(pfile_in_zip_read_info);
1120 return UNZ_BADZIPFILE;
1121 }
1122 }
1123
1124 pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc;
1125 pfile_in_zip_read_info->crc32 = 0;
1126 pfile_in_zip_read_info->total_out_64 = 0;
1127 pfile_in_zip_read_info->compression_method = compression_method;
1128 pfile_in_zip_read_info->filestream = s->filestream;
1129 pfile_in_zip_read_info->z_filefunc = s->z_filefunc;
1130 if (s->number_disk == s->gi.number_disk_with_CD)
1131 pfile_in_zip_read_info->byte_before_the_zipfile = s->byte_before_the_zipfile;
1132 else
1133 pfile_in_zip_read_info->byte_before_the_zipfile = 0;
1134 pfile_in_zip_read_info->stream.total_out = 0;
1135 pfile_in_zip_read_info->stream.total_in = 0;
1136 pfile_in_zip_read_info->stream.next_in = NULL;
1137
1138 if (!raw)
1139 {
1140 if (compression_method == Z_BZIP2ED)
1141 {
1142 #ifdef HAVE_BZIP2
1143 pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
1144 pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
1145 pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
1146 pfile_in_zip_read_info->bstream.state = (voidpf)0;
1147
1148 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1149 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1150 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1151 pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1152 pfile_in_zip_read_info->stream.avail_in = 0;
1153
1154 err = BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
1155 if (err == Z_OK)
1156 {
1157 pfile_in_zip_read_info->stream_initialised = Z_BZIP2ED;
1158 }
1159 else
1160 {
1161 TRYFREE(pfile_in_zip_read_info);
1162 return err;
1163 }
1164 #else
1165 pfile_in_zip_read_info->raw = 1;
1166 #endif
1167 }
1168 else if (compression_method == Z_DEFLATED)
1169 {
1170 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1171 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1172 pfile_in_zip_read_info->stream.opaque = (voidpf)s;
1173 pfile_in_zip_read_info->stream.next_in = 0;
1174 pfile_in_zip_read_info->stream.avail_in = 0;
1175
1176 #ifdef HAVE_APPLE_COMPRESSION
1177 err = compression_stream_init(&pfile_in_zip_read_info->astream, COMPRESSION_STREAM_DECODE, COMPRESSION_ZLIB);
1178 if (err == COMPRESSION_STATUS_ERROR)
1179 err = UNZ_INTERNALERROR;
1180 else
1181 err = Z_OK;
1182 #else
1183 err = inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1184 #endif
1185 if (err == Z_OK)
1186 {
1187 pfile_in_zip_read_info->stream_initialised = Z_DEFLATED;
1188 }
1189 else
1190 {
1191 TRYFREE(pfile_in_zip_read_info);
1192 return err;
1193 }
1194 /* windowBits is passed < 0 to tell that there is no zlib header.
1195 * Note that in this case inflate *requires* an extra "dummy" byte
1196 * after the compressed stream in order to complete decompression and
1197 * return Z_STREAM_END.
1198 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1199 * size of both compressed and uncompressed data
1200 */
1201 }
1202 }
1203
1204 pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size;
1205 pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size;
1206 pfile_in_zip_read_info->pos_in_zipfile = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_variable;
1207 pfile_in_zip_read_info->stream.avail_in = 0;
1208
1209 s->pfile_in_zip_read = pfile_in_zip_read_info;
1210
1211 #ifndef NOUNCRYPT
1212 s->pcrc_32_tab = NULL;
1213
1214 if ((password != NULL) && ((s->cur_file_info.flag & 1) != 0))
1215 {
1216 if (ZSEEK64(s->z_filefunc, s->filestream,
1217 s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile,
1218 ZLIB_FILEFUNC_SEEK_SET) != 0)
1219 return UNZ_INTERNALERROR;
1220 #ifdef HAVE_AES
1221 if (s->cur_file_info.compression_method == AES_METHOD)
1222 {
1223 unsigned char passverify_archive[AES_PWVERIFYSIZE];
1224 unsigned char passverify_password[AES_PWVERIFYSIZE];
1225 unsigned char salt_value[AES_MAXSALTLENGTH];
1226 uint32_t salt_length = 0;
1227
1228 if ((s->cur_file_info_internal.aes_encryption_mode < 1) ||
1229 (s->cur_file_info_internal.aes_encryption_mode > 3))
1230 return UNZ_INTERNALERROR;
1231
1232 salt_length = SALT_LENGTH(s->cur_file_info_internal.aes_encryption_mode);
1233
1234 if (ZREAD64(s->z_filefunc, s->filestream, salt_value, salt_length) != salt_length)
1235 return UNZ_INTERNALERROR;
1236 if (ZREAD64(s->z_filefunc, s->filestream, passverify_archive, AES_PWVERIFYSIZE) != AES_PWVERIFYSIZE)
1237 return UNZ_INTERNALERROR;
1238
1239 fcrypt_init(s->cur_file_info_internal.aes_encryption_mode, (uint8_t *)password,
1240 (uint32_t)strlen(password), salt_value, passverify_password, &s->pfile_in_zip_read->aes_ctx);
1241
1242 if (memcmp(passverify_archive, passverify_password, AES_PWVERIFYSIZE) != 0)
1243 return UNZ_BADPASSWORD;
1244
1245 s->pfile_in_zip_read->rest_read_compressed -= salt_length + AES_PWVERIFYSIZE;
1246 s->pfile_in_zip_read->rest_read_compressed -= AES_AUTHCODESIZE;
1247
1248 s->pfile_in_zip_read->pos_in_zipfile += salt_length + AES_PWVERIFYSIZE;
1249 }
1250 else
1251 #endif
1252 {
1253 int i;
1254 s->pcrc_32_tab = (const z_crc_t*)get_crc_table();
1255 init_keys(password, s->keys, s->pcrc_32_tab);
1256
1257 if (ZREAD64(s->z_filefunc, s->filestream, source, 12) < 12)
1258 return UNZ_INTERNALERROR;
1259
1260 for (i = 0; i < 12; i++)
1261 zdecode(s->keys, s->pcrc_32_tab, source[i]);
1262
1263 s->pfile_in_zip_read->rest_read_compressed -= 12;
1264 s->pfile_in_zip_read->pos_in_zipfile += 12;
1265 }
1266 }
1267 #endif
1268
1269 return UNZ_OK;
1270 }
1271
unzOpenCurrentFile(unzFile file)1272 extern int ZEXPORT unzOpenCurrentFile(unzFile file)
1273 {
1274 return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1275 }
1276
unzOpenCurrentFilePassword(unzFile file,const char * password)1277 extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char *password)
1278 {
1279 return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1280 }
1281
unzOpenCurrentFile2(unzFile file,int * method,int * level,int raw)1282 extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int *method, int *level, int raw)
1283 {
1284 return unzOpenCurrentFile3(file, method, level, raw, NULL);
1285 }
1286
1287 /* Read bytes from the current file.
1288 buf contain buffer where data must be copied
1289 len the size of buf.
1290
1291 return the number of byte copied if some bytes are copied
1292 return 0 if the end of file was reached
1293 return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */
unzReadCurrentFile(unzFile file,voidp buf,uint32_t len)1294 extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, uint32_t len)
1295 {
1296 unz64_s *s = NULL;
1297 uint32_t read = 0;
1298 int err = UNZ_OK;
1299
1300 if (file == NULL)
1301 return UNZ_PARAMERROR;
1302 s = (unz64_s*)file;
1303
1304 if (s->pfile_in_zip_read == NULL)
1305 return UNZ_PARAMERROR;
1306 if (s->pfile_in_zip_read->read_buffer == NULL)
1307 return UNZ_END_OF_LIST_OF_FILE;
1308 if (len == 0)
1309 return 0;
1310 if (len > UINT16_MAX)
1311 return UNZ_PARAMERROR;
1312
1313 s->pfile_in_zip_read->stream.next_out = (uint8_t*)buf;
1314 s->pfile_in_zip_read->stream.avail_out = (uint16_t)len;
1315
1316 if (s->pfile_in_zip_read->raw)
1317 {
1318 if (len > s->pfile_in_zip_read->rest_read_compressed + s->pfile_in_zip_read->stream.avail_in)
1319 s->pfile_in_zip_read->stream.avail_out = (uint16_t)s->pfile_in_zip_read->rest_read_compressed +
1320 s->pfile_in_zip_read->stream.avail_in;
1321 }
1322 else
1323 {
1324 if (len > s->pfile_in_zip_read->rest_read_uncompressed)
1325 s->pfile_in_zip_read->stream.avail_out = (uint16_t)s->pfile_in_zip_read->rest_read_uncompressed;
1326 }
1327
1328 while (s->pfile_in_zip_read->stream.avail_out > 0)
1329 {
1330 if (s->pfile_in_zip_read->stream.avail_in == 0)
1331 {
1332 uint32_t bytes_to_read = UNZ_BUFSIZE;
1333 uint32_t bytes_not_read = 0;
1334 uint32_t bytes_read = 0;
1335 uint32_t total_bytes_read = 0;
1336
1337 if (s->pfile_in_zip_read->stream.next_in != NULL)
1338 bytes_not_read = (uint32_t)(s->pfile_in_zip_read->read_buffer + UNZ_BUFSIZE -
1339 s->pfile_in_zip_read->stream.next_in);
1340 bytes_to_read -= bytes_not_read;
1341 if (bytes_not_read > 0)
1342 memcpy(s->pfile_in_zip_read->read_buffer, s->pfile_in_zip_read->stream.next_in, bytes_not_read);
1343 if (s->pfile_in_zip_read->rest_read_compressed < bytes_to_read)
1344 bytes_to_read = (uint16_t)s->pfile_in_zip_read->rest_read_compressed;
1345
1346 while (total_bytes_read != bytes_to_read)
1347 {
1348 if (ZSEEK64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream,
1349 s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile,
1350 ZLIB_FILEFUNC_SEEK_SET) != 0)
1351 return UNZ_ERRNO;
1352
1353 bytes_read = ZREAD64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream,
1354 s->pfile_in_zip_read->read_buffer + bytes_not_read + total_bytes_read,
1355 bytes_to_read - total_bytes_read);
1356
1357 total_bytes_read += bytes_read;
1358 s->pfile_in_zip_read->pos_in_zipfile += bytes_read;
1359
1360 if (bytes_read == 0)
1361 {
1362 if (ZERROR64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream))
1363 return UNZ_ERRNO;
1364
1365 err = unzGoToNextDisk(file);
1366 if (err != UNZ_OK)
1367 return err;
1368
1369 s->pfile_in_zip_read->pos_in_zipfile = 0;
1370 s->pfile_in_zip_read->filestream = s->filestream;
1371 }
1372 }
1373
1374 #ifndef NOUNCRYPT
1375 if ((s->cur_file_info.flag & 1) != 0)
1376 {
1377 #ifdef HAVE_AES
1378 if (s->cur_file_info.compression_method == AES_METHOD)
1379 {
1380 fcrypt_decrypt(s->pfile_in_zip_read->read_buffer, bytes_to_read, &s->pfile_in_zip_read->aes_ctx);
1381 }
1382 else
1383 #endif
1384 if (s->pcrc_32_tab != NULL)
1385 {
1386 uint32_t i = 0;
1387
1388 for (i = 0; i < total_bytes_read; i++)
1389 s->pfile_in_zip_read->read_buffer[i] =
1390 zdecode(s->keys, s->pcrc_32_tab, s->pfile_in_zip_read->read_buffer[i]);
1391 }
1392 }
1393 #endif
1394
1395 s->pfile_in_zip_read->rest_read_compressed -= total_bytes_read;
1396 s->pfile_in_zip_read->stream.next_in = (uint8_t*)s->pfile_in_zip_read->read_buffer;
1397 s->pfile_in_zip_read->stream.avail_in = (uint16_t)(bytes_not_read + total_bytes_read);
1398 }
1399
1400 if ((s->pfile_in_zip_read->compression_method == 0) || (s->pfile_in_zip_read->raw))
1401 {
1402 uint32_t i = 0;
1403 uint32_t copy = 0;
1404
1405 if ((s->pfile_in_zip_read->stream.avail_in == 0) &&
1406 (s->pfile_in_zip_read->rest_read_compressed == 0))
1407 return (read == 0) ? UNZ_EOF : read;
1408
1409 if (s->pfile_in_zip_read->stream.avail_out < s->pfile_in_zip_read->stream.avail_in)
1410 copy = s->pfile_in_zip_read->stream.avail_out;
1411 else
1412 copy = s->pfile_in_zip_read->stream.avail_in;
1413
1414 for (i = 0; i < copy; i++)
1415 *(s->pfile_in_zip_read->stream.next_out + i) =
1416 *(s->pfile_in_zip_read->stream.next_in + i);
1417
1418 s->pfile_in_zip_read->total_out_64 = s->pfile_in_zip_read->total_out_64 + copy;
1419 s->pfile_in_zip_read->rest_read_uncompressed -= copy;
1420 s->pfile_in_zip_read->crc32 = (uint32_t)crc32(s->pfile_in_zip_read->crc32,
1421 s->pfile_in_zip_read->stream.next_out, copy);
1422
1423 s->pfile_in_zip_read->stream.avail_in -= copy;
1424 s->pfile_in_zip_read->stream.avail_out -= copy;
1425 s->pfile_in_zip_read->stream.next_out += copy;
1426 s->pfile_in_zip_read->stream.next_in += copy;
1427 s->pfile_in_zip_read->stream.total_out += copy;
1428
1429 read += copy;
1430 }
1431 else if (s->pfile_in_zip_read->compression_method == Z_BZIP2ED)
1432 {
1433 #ifdef HAVE_BZIP2
1434 uint64_t total_out_before = 0;
1435 uint64_t total_out_after = 0;
1436 uint64_t out_bytes = 0;
1437 const uint8_t *buf_before = NULL;
1438
1439 s->pfile_in_zip_read->bstream.next_in = (char*)s->pfile_in_zip_read->stream.next_in;
1440 s->pfile_in_zip_read->bstream.avail_in = s->pfile_in_zip_read->stream.avail_in;
1441 s->pfile_in_zip_read->bstream.total_in_lo32 = (uint32_t)s->pfile_in_zip_read->stream.total_in;
1442 s->pfile_in_zip_read->bstream.total_in_hi32 = s->pfile_in_zip_read->stream.total_in >> 32;
1443
1444 s->pfile_in_zip_read->bstream.next_out = (char*)s->pfile_in_zip_read->stream.next_out;
1445 s->pfile_in_zip_read->bstream.avail_out = s->pfile_in_zip_read->stream.avail_out;
1446 s->pfile_in_zip_read->bstream.total_out_lo32 = (uint32_t)s->pfile_in_zip_read->stream.total_out;
1447 s->pfile_in_zip_read->bstream.total_out_hi32 = s->pfile_in_zip_read->stream.total_out >> 32;
1448
1449 total_out_before = s->pfile_in_zip_read->bstream.total_out_lo32 +
1450 (((uint32_t)s->pfile_in_zip_read->bstream.total_out_hi32) << 32);
1451 buf_before = (const uint8_t*)s->pfile_in_zip_read->bstream.next_out;
1452
1453 err = BZ2_bzDecompress(&s->pfile_in_zip_read->bstream);
1454
1455 total_out_after = s->pfile_in_zip_read->bstream.total_out_lo32 +
1456 (((uint32_t)s->pfile_in_zip_read->bstream.total_out_hi32) << 32);
1457
1458 out_bytes = total_out_after - total_out_before;
1459
1460 s->pfile_in_zip_read->total_out_64 = s->pfile_in_zip_read->total_out_64 + out_bytes;
1461 s->pfile_in_zip_read->rest_read_uncompressed -= out_bytes;
1462 s->pfile_in_zip_read->crc32 = crc32(s->pfile_in_zip_read->crc32, buf_before, (uint32_t)out_bytes);
1463
1464 read += (uint32_t)out_bytes;
1465
1466 s->pfile_in_zip_read->stream.next_in = (uint8_t*)s->pfile_in_zip_read->bstream.next_in;
1467 s->pfile_in_zip_read->stream.avail_in = s->pfile_in_zip_read->bstream.avail_in;
1468 s->pfile_in_zip_read->stream.total_in = s->pfile_in_zip_read->bstream.total_in_lo32;
1469 s->pfile_in_zip_read->stream.next_out = (uint8_t*)s->pfile_in_zip_read->bstream.next_out;
1470 s->pfile_in_zip_read->stream.avail_out = s->pfile_in_zip_read->bstream.avail_out;
1471 s->pfile_in_zip_read->stream.total_out = s->pfile_in_zip_read->bstream.total_out_lo32;
1472
1473 if (err == BZ_STREAM_END)
1474 return (read == 0) ? UNZ_EOF : read;
1475 if (err != BZ_OK)
1476 break;
1477 #endif
1478 }
1479 #ifdef HAVE_APPLE_COMPRESSION
1480 else
1481 {
1482 uint64_t total_out_before = 0;
1483 uint64_t total_out_after = 0;
1484 uint64_t out_bytes = 0;
1485 const uint8_t *buf_before = NULL;
1486
1487 s->pfile_in_zip_read->astream.src_ptr = s->pfile_in_zip_read->stream.next_in;
1488 s->pfile_in_zip_read->astream.src_size = s->pfile_in_zip_read->stream.avail_in;
1489 s->pfile_in_zip_read->astream.dst_ptr = s->pfile_in_zip_read->stream.next_out;
1490 s->pfile_in_zip_read->astream.dst_size = len;
1491
1492 total_out_before = s->pfile_in_zip_read->stream.total_out;
1493 buf_before = s->pfile_in_zip_read->stream.next_out;
1494
1495 compression_status status;
1496 compression_stream_flags flags;
1497
1498 if (s->pfile_in_zip_read->stream.avail_in == 0)
1499 {
1500 flags = COMPRESSION_STREAM_FINALIZE;
1501 }
1502
1503 status = compression_stream_process(&s->pfile_in_zip_read->astream, flags);
1504
1505 total_out_after = len - s->pfile_in_zip_read->astream.dst_size;
1506 out_bytes = total_out_after - total_out_before;
1507
1508 s->pfile_in_zip_read->total_out_64 += out_bytes;
1509 s->pfile_in_zip_read->rest_read_uncompressed -= out_bytes;
1510 s->pfile_in_zip_read->crc32 =
1511 crc32(s->pfile_in_zip_read->crc32, buf_before, (uint32_t)out_bytes);
1512
1513 read += (uint32_t)out_bytes;
1514
1515 s->pfile_in_zip_read->stream.next_in = s->pfile_in_zip_read->astream.src_ptr;
1516 s->pfile_in_zip_read->stream.avail_in = s->pfile_in_zip_read->astream.src_size;
1517 s->pfile_in_zip_read->stream.next_out = s->pfile_in_zip_read->astream.dst_ptr;
1518 s->pfile_in_zip_read->stream.avail_out = s->pfile_in_zip_read->astream.dst_size;
1519
1520 if (status == COMPRESSION_STATUS_END)
1521 return (read == 0) ? UNZ_EOF : read;
1522 if (status == COMPRESSION_STATUS_ERROR)
1523 return Z_DATA_ERROR;
1524 return read;
1525 }
1526 #else
1527 else
1528 {
1529
1530 uint64_t total_out_before = 0;
1531 uint64_t total_out_after = 0;
1532 uint64_t out_bytes = 0;
1533 const uint8_t *buf_before = NULL;
1534 int flush = Z_SYNC_FLUSH;
1535
1536 total_out_before = s->pfile_in_zip_read->stream.total_out;
1537 buf_before = s->pfile_in_zip_read->stream.next_out;
1538
1539 /*
1540 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1541 pfile_in_zip_read_info->stream.avail_out) &&
1542 (pfile_in_zip_read_info->rest_read_compressed == 0))
1543 flush = Z_FINISH;
1544 */
1545 err = inflate(&s->pfile_in_zip_read->stream, flush);
1546
1547 if ((err >= 0) && (s->pfile_in_zip_read->stream.msg != NULL))
1548 err = Z_DATA_ERROR;
1549
1550 total_out_after = s->pfile_in_zip_read->stream.total_out;
1551 out_bytes = total_out_after - total_out_before;
1552
1553 s->pfile_in_zip_read->total_out_64 += out_bytes;
1554 s->pfile_in_zip_read->rest_read_uncompressed -= out_bytes;
1555 s->pfile_in_zip_read->crc32 =
1556 (uint32_t)crc32(s->pfile_in_zip_read->crc32,buf_before, (uint32_t)out_bytes);
1557
1558 read += (uint32_t)out_bytes;
1559
1560 if (err == Z_STREAM_END)
1561 return (read == 0) ? UNZ_EOF : read;
1562 if (err != Z_OK)
1563 break;
1564 }
1565 #endif
1566 }
1567
1568 if (err == Z_OK)
1569 return read;
1570 return err;
1571 }
1572
unzGetLocalExtrafield(unzFile file,voidp buf,uint32_t len)1573 extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, uint32_t len)
1574 {
1575 unz64_s *s = NULL;
1576 uint64_t size_to_read = 0;
1577 uint32_t read_now = 0;
1578
1579 if (file == NULL)
1580 return UNZ_PARAMERROR;
1581 s = (unz64_s*)file;
1582 if (s->pfile_in_zip_read == NULL)
1583 return UNZ_PARAMERROR;
1584
1585 size_to_read = s->pfile_in_zip_read->size_local_extrafield - s->pfile_in_zip_read->pos_local_extrafield;
1586
1587 if (buf == NULL)
1588 return (int)size_to_read;
1589
1590 if (len > size_to_read)
1591 read_now = (uint32_t)size_to_read;
1592 else
1593 read_now = len;
1594
1595 if (read_now == 0)
1596 return 0;
1597
1598 if (ZSEEK64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream,
1599 s->pfile_in_zip_read->offset_local_extrafield + s->pfile_in_zip_read->pos_local_extrafield,
1600 ZLIB_FILEFUNC_SEEK_SET) != 0)
1601 return UNZ_ERRNO;
1602
1603 if (ZREAD64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream, buf, read_now) != read_now)
1604 return UNZ_ERRNO;
1605
1606 return (int)read_now;
1607 }
1608
unzCloseCurrentFile(unzFile file)1609 extern int ZEXPORT unzCloseCurrentFile(unzFile file)
1610 {
1611 unz64_s *s = NULL;
1612 file_in_zip64_read_info_s *pfile_in_zip_read_info = NULL;
1613 int err = UNZ_OK;
1614
1615 if (file == NULL)
1616 return UNZ_PARAMERROR;
1617 s = (unz64_s*)file;
1618 pfile_in_zip_read_info = s->pfile_in_zip_read;
1619 if (pfile_in_zip_read_info == NULL)
1620 return UNZ_PARAMERROR;
1621
1622 #ifdef HAVE_AES
1623 if (s->cur_file_info.compression_method == AES_METHOD)
1624 {
1625 unsigned char authcode[AES_AUTHCODESIZE];
1626 unsigned char rauthcode[AES_AUTHCODESIZE];
1627
1628 if (ZREAD64(s->z_filefunc, s->filestream, authcode, AES_AUTHCODESIZE) != AES_AUTHCODESIZE)
1629 return UNZ_ERRNO;
1630
1631 if (fcrypt_end(rauthcode, &s->pfile_in_zip_read->aes_ctx) != AES_AUTHCODESIZE)
1632 err = UNZ_CRCERROR;
1633 if (memcmp(authcode, rauthcode, AES_AUTHCODESIZE) != 0)
1634 err = UNZ_CRCERROR;
1635 }
1636 /* AES zip version AE-1 will expect a valid crc as well */
1637 if ((s->cur_file_info.compression_method != AES_METHOD) ||
1638 (s->cur_file_info_internal.aes_version == 0x0001))
1639 #endif
1640 {
1641 if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1642 (!pfile_in_zip_read_info->raw))
1643 {
1644 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1645 err = UNZ_CRCERROR;
1646 }
1647 }
1648
1649 TRYFREE(pfile_in_zip_read_info->read_buffer);
1650 pfile_in_zip_read_info->read_buffer = NULL;
1651 if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
1652 {
1653 #ifdef HAVE_APPLE_COMPRESSION
1654 if (compression_stream_destroy)
1655 compression_stream_destroy(&pfile_in_zip_read_info->astream);
1656 #else
1657 inflateEnd(&pfile_in_zip_read_info->stream);
1658 #endif
1659
1660 }
1661 #ifdef HAVE_BZIP2
1662 else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
1663 BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
1664 #endif
1665
1666 pfile_in_zip_read_info->stream_initialised = 0;
1667 TRYFREE(pfile_in_zip_read_info);
1668
1669 s->pfile_in_zip_read = NULL;
1670
1671 return err;
1672 }
1673
unzGoToFirstFile2(unzFile file,unz_file_info64 * pfile_info,char * filename,uint16_t filename_size,void * extrafield,uint16_t extrafield_size,char * comment,uint16_t comment_size)1674 extern int ZEXPORT unzGoToFirstFile2(unzFile file, unz_file_info64 *pfile_info, char *filename,
1675 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
1676 {
1677 unz64_s *s = NULL;
1678 int err = UNZ_OK;
1679
1680 if (file == NULL)
1681 return UNZ_PARAMERROR;
1682 s = (unz64_s*)file;
1683
1684 s->pos_in_central_dir = s->offset_central_dir;
1685 s->num_file = 0;
1686
1687 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal,
1688 filename, filename_size, extrafield, extrafield_size, comment,comment_size);
1689
1690 s->current_file_ok = (err == UNZ_OK);
1691 if ((err == UNZ_OK) && (pfile_info != NULL))
1692 memcpy(pfile_info, &s->cur_file_info, sizeof(unz_file_info64));
1693
1694 return err;
1695 }
1696
unzGoToFirstFile(unzFile file)1697 extern int ZEXPORT unzGoToFirstFile(unzFile file)
1698 {
1699 return unzGoToFirstFile2(file, NULL, NULL, 0, NULL, 0, NULL, 0);
1700 }
1701
unzGoToNextFile2(unzFile file,unz_file_info64 * pfile_info,char * filename,uint16_t filename_size,void * extrafield,uint16_t extrafield_size,char * comment,uint16_t comment_size)1702 extern int ZEXPORT unzGoToNextFile2(unzFile file, unz_file_info64 *pfile_info, char *filename,
1703 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
1704 {
1705 unz64_s *s = NULL;
1706 int err = UNZ_OK;
1707
1708 if (file == NULL)
1709 return UNZ_PARAMERROR;
1710 s = (unz64_s*)file;
1711
1712 if (!s->current_file_ok)
1713 return UNZ_END_OF_LIST_OF_FILE;
1714 if (s->gi.number_entry != UINT16_MAX) /* 2^16 files overflow hack */
1715 {
1716 if (s->num_file+1 == s->gi.number_entry)
1717 return UNZ_END_OF_LIST_OF_FILE;
1718 }
1719
1720 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
1721 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment;
1722 s->num_file += 1;
1723
1724 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal,
1725 filename, filename_size, extrafield,extrafield_size, comment, comment_size);
1726
1727 s->current_file_ok = (err == UNZ_OK);
1728 if ((err == UNZ_OK) && (pfile_info != NULL))
1729 memcpy(pfile_info, &s->cur_file_info, sizeof(unz_file_info64));
1730
1731 return err;
1732 }
1733
unzGoToNextFile(unzFile file)1734 extern int ZEXPORT unzGoToNextFile(unzFile file)
1735 {
1736 return unzGoToNextFile2(file, NULL, NULL, 0, NULL, 0, NULL, 0);
1737 }
1738
unzLocateFile(unzFile file,const char * filename,unzFileNameComparer filename_compare_func)1739 extern int ZEXPORT unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filename_compare_func)
1740 {
1741 unz64_s *s = NULL;
1742 unz_file_info64 cur_file_info_saved;
1743 unz_file_info64_internal cur_file_info_internal_saved;
1744 uint64_t num_file_saved = 0;
1745 uint64_t pos_in_central_dir_saved = 0;
1746 char current_filename[UNZ_MAXFILENAMEINZIP+1];
1747 int err = UNZ_OK;
1748
1749 if (file == NULL)
1750 return UNZ_PARAMERROR;
1751 if (strlen(filename) >= UNZ_MAXFILENAMEINZIP)
1752 return UNZ_PARAMERROR;
1753 s = (unz64_s*)file;
1754 if (!s->current_file_ok)
1755 return UNZ_END_OF_LIST_OF_FILE;
1756
1757 /* Save the current state */
1758 num_file_saved = s->num_file;
1759 pos_in_central_dir_saved = s->pos_in_central_dir;
1760 cur_file_info_saved = s->cur_file_info;
1761 cur_file_info_internal_saved = s->cur_file_info_internal;
1762
1763 err = unzGoToFirstFile2(file, NULL, current_filename, sizeof(current_filename)-1, NULL, 0, NULL, 0);
1764
1765 while (err == UNZ_OK)
1766 {
1767 if (filename_compare_func != NULL)
1768 err = filename_compare_func(file, current_filename, filename);
1769 else
1770 err = strcmp(current_filename, filename);
1771 if (err == 0)
1772 return UNZ_OK;
1773 err = unzGoToNextFile2(file, NULL, current_filename, sizeof(current_filename)-1, NULL, 0, NULL, 0);
1774 }
1775
1776 /* We failed, so restore the state of the 'current file' to where we were. */
1777 s->num_file = num_file_saved;
1778 s->pos_in_central_dir = pos_in_central_dir_saved;
1779 s->cur_file_info = cur_file_info_saved;
1780 s->cur_file_info_internal = cur_file_info_internal_saved;
1781 return err;
1782 }
1783
unzGetFilePos(unzFile file,unz_file_pos * file_pos)1784 extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos *file_pos)
1785 {
1786 unz64_file_pos file_pos64;
1787 int err = unzGetFilePos64(file, &file_pos64);
1788 if (err == UNZ_OK)
1789 {
1790 file_pos->pos_in_zip_directory = (uint32_t)file_pos64.pos_in_zip_directory;
1791 file_pos->num_of_file = (uint32_t)file_pos64.num_of_file;
1792 }
1793 return err;
1794 }
1795
unzGoToFilePos(unzFile file,unz_file_pos * file_pos)1796 extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos *file_pos)
1797 {
1798 unz64_file_pos file_pos64;
1799 if (file_pos == NULL)
1800 return UNZ_PARAMERROR;
1801 file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
1802 file_pos64.num_of_file = file_pos->num_of_file;
1803 return unzGoToFilePos64(file, &file_pos64);
1804 }
1805
unzGetFilePos64(unzFile file,unz64_file_pos * file_pos)1806 extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos *file_pos)
1807 {
1808 unz64_s *s = NULL;
1809
1810 if (file == NULL || file_pos == NULL)
1811 return UNZ_PARAMERROR;
1812 s = (unz64_s*)file;
1813 if (!s->current_file_ok)
1814 return UNZ_END_OF_LIST_OF_FILE;
1815
1816 file_pos->pos_in_zip_directory = s->pos_in_central_dir;
1817 file_pos->num_of_file = s->num_file;
1818 return UNZ_OK;
1819 }
1820
unzGoToFilePos64(unzFile file,const unz64_file_pos * file_pos)1821 extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos *file_pos)
1822 {
1823 unz64_s *s = NULL;
1824 int err = UNZ_OK;
1825
1826 if (file == NULL || file_pos == NULL)
1827 return UNZ_PARAMERROR;
1828 s = (unz64_s*)file;
1829
1830 /* Jump to the right spot */
1831 s->pos_in_central_dir = file_pos->pos_in_zip_directory;
1832 s->num_file = file_pos->num_of_file;
1833
1834 /* Set the current file */
1835 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0);
1836 /* Return results */
1837 s->current_file_ok = (err == UNZ_OK);
1838 return err;
1839 }
1840
unzGetOffset(unzFile file)1841 extern int32_t ZEXPORT unzGetOffset(unzFile file)
1842 {
1843 uint64_t offset64 = 0;
1844
1845 if (file == NULL)
1846 return UNZ_PARAMERROR;
1847 offset64 = unzGetOffset64(file);
1848 return (int32_t)offset64;
1849 }
1850
unzGetOffset64(unzFile file)1851 extern int64_t ZEXPORT unzGetOffset64(unzFile file)
1852 {
1853 unz64_s *s = NULL;
1854
1855 if (file == NULL)
1856 return UNZ_PARAMERROR;
1857 s = (unz64_s*)file;
1858 if (!s->current_file_ok)
1859 return 0;
1860 if (s->gi.number_entry != 0 && s->gi.number_entry != UINT16_MAX)
1861 {
1862 if (s->num_file == s->gi.number_entry)
1863 return 0;
1864 }
1865 return s->pos_in_central_dir;
1866 }
1867
unzSetOffset(unzFile file,uint32_t pos)1868 extern int ZEXPORT unzSetOffset(unzFile file, uint32_t pos)
1869 {
1870 return unzSetOffset64(file, pos);
1871 }
1872
unzSetOffset64(unzFile file,uint64_t pos)1873 extern int ZEXPORT unzSetOffset64(unzFile file, uint64_t pos)
1874 {
1875 unz64_s *s = NULL;
1876 int err = UNZ_OK;
1877
1878 if (file == NULL)
1879 return UNZ_PARAMERROR;
1880 s = (unz64_s*)file;
1881 s->pos_in_central_dir = pos;
1882 s->num_file = s->gi.number_entry; /* hack */
1883
1884 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0);
1885
1886 s->current_file_ok = (err == UNZ_OK);
1887 return err;
1888 }
1889
unzTell(unzFile file)1890 extern int32_t ZEXPORT unzTell(unzFile file)
1891 {
1892 unz64_s *s = NULL;
1893 if (file == NULL)
1894 return UNZ_PARAMERROR;
1895 s = (unz64_s*)file;
1896 if (s->pfile_in_zip_read == NULL)
1897 return UNZ_PARAMERROR;
1898 return (int32_t)s->pfile_in_zip_read->stream.total_out;
1899 }
1900
unzTell64(unzFile file)1901 extern int64_t ZEXPORT unzTell64(unzFile file)
1902 {
1903 unz64_s *s = NULL;
1904 if (file == NULL)
1905 return UNZ_PARAMERROR;
1906 s = (unz64_s*)file;
1907 if (s->pfile_in_zip_read == NULL)
1908 return UNZ_PARAMERROR;
1909 return s->pfile_in_zip_read->total_out_64;
1910 }
1911
unzSeek(unzFile file,uint32_t offset,int origin)1912 extern int ZEXPORT unzSeek(unzFile file, uint32_t offset, int origin)
1913 {
1914 return unzSeek64(file, offset, origin);
1915 }
1916
unzSeek64(unzFile file,uint64_t offset,int origin)1917 extern int ZEXPORT unzSeek64(unzFile file, uint64_t offset, int origin)
1918 {
1919 unz64_s *s = NULL;
1920 uint64_t stream_pos_begin = 0;
1921 uint64_t stream_pos_end = 0;
1922 uint64_t position = 0;
1923 int is_within_buffer = 0;
1924
1925 if (file == NULL)
1926 return UNZ_PARAMERROR;
1927 s = (unz64_s*)file;
1928
1929 if (s->pfile_in_zip_read == NULL)
1930 return UNZ_ERRNO;
1931 if (s->pfile_in_zip_read->compression_method != 0)
1932 return UNZ_ERRNO;
1933
1934 if (origin == SEEK_SET)
1935 position = offset;
1936 else if (origin == SEEK_CUR)
1937 position = s->pfile_in_zip_read->total_out_64 + offset;
1938 else if (origin == SEEK_END)
1939 position = s->cur_file_info.compressed_size + offset;
1940 else
1941 return UNZ_PARAMERROR;
1942
1943 if (position > s->cur_file_info.compressed_size)
1944 return UNZ_PARAMERROR;
1945
1946 stream_pos_end = s->pfile_in_zip_read->pos_in_zipfile;
1947 stream_pos_begin = stream_pos_end;
1948
1949 if (stream_pos_begin > UNZ_BUFSIZE)
1950 stream_pos_begin -= UNZ_BUFSIZE;
1951 else
1952 stream_pos_begin = 0;
1953
1954 is_within_buffer =
1955 (s->pfile_in_zip_read->stream.avail_in != 0) &&
1956 (s->pfile_in_zip_read->rest_read_compressed != 0 || s->cur_file_info.compressed_size < UNZ_BUFSIZE) &&
1957 (position >= stream_pos_begin && position < stream_pos_end);
1958
1959 if (is_within_buffer)
1960 {
1961 s->pfile_in_zip_read->stream.next_in += position - s->pfile_in_zip_read->total_out_64;
1962 s->pfile_in_zip_read->stream.avail_in = (uInt)(stream_pos_end - position);
1963 }
1964 else
1965 {
1966 s->pfile_in_zip_read->stream.avail_in = 0;
1967 s->pfile_in_zip_read->stream.next_in = 0;
1968
1969 s->pfile_in_zip_read->pos_in_zipfile = s->pfile_in_zip_read->offset_local_extrafield + position;
1970 s->pfile_in_zip_read->rest_read_compressed = s->cur_file_info.compressed_size - position;
1971 }
1972
1973 s->pfile_in_zip_read->rest_read_uncompressed -= (position - s->pfile_in_zip_read->total_out_64);
1974 s->pfile_in_zip_read->stream.total_out = (uint32_t)position;
1975 s->pfile_in_zip_read->total_out_64 = position;
1976
1977 return UNZ_OK;
1978 }
1979
unzEndOfFile(unzFile file)1980 extern int ZEXPORT unzEndOfFile(unzFile file)
1981 {
1982 unz64_s *s = NULL;
1983 if (file == NULL)
1984 return UNZ_PARAMERROR;
1985 s = (unz64_s*)file;
1986 if (s->pfile_in_zip_read == NULL)
1987 return UNZ_PARAMERROR;
1988 if (s->pfile_in_zip_read->rest_read_uncompressed == 0)
1989 return 1;
1990 return 0;
1991 }
1992