1 /* unzip.c -- IO for uncompress .zip files using zlib
2 Version 1.2.0, September 16th, 2017
3 part of the MiniZip project
5 Copyright (C) 2010-2017 Nathan Moinvaziri
6 Modifications for AES, PKWARE disk spanning
7 https://github.com/nmoinvaz/minizip
8 Copyright (C) 2009-2010 Mathias Svensson
9 Modifications for Zip64 support on both zip and unzip
11 Copyright (C) 2007-2008 Even Rouault
12 Modifications of Unzip for Zip64
13 Copyright (C) 1998-2010 Gilles Vollant
14 http://www.winimage.com/zLibDll/minizip.html
16 This program is distributed under the terms of the same license as zlib.
17 See the accompanying LICENSE file for the full text of the license.
30 # define AES_METHOD (99)
31 # define AES_PWVERIFYSIZE (2)
32 # define AES_MAXSALTLENGTH (16)
33 # define AES_AUTHCODESIZE (10)
34 # define AES_HEADERSIZE (11)
35 # define AES_KEYSIZE(mode) (64 + (mode * 64))
38 # include "aes/fileenc.h"
40 #ifdef HAVE_APPLE_COMPRESSION
41 # include <compression.h>
48 #define DISKHEADERMAGIC (0x08074b50)
49 #define LOCALHEADERMAGIC (0x04034b50)
50 #define CENTRALHEADERMAGIC (0x02014b50)
51 #define ENDHEADERMAGIC (0x06054b50)
52 #define ZIP64ENDHEADERMAGIC (0x06064b50)
53 #define ZIP64ENDLOCHEADERMAGIC (0x07064b50)
55 #define SIZECENTRALDIRITEM (0x2e)
56 #define SIZECENTRALHEADERLOCATOR (0x14)
57 #define SIZEZIPLOCALHEADER (0x1e)
59 #ifndef BUFREADCOMMENT
60 # define BUFREADCOMMENT (0x400)
64 # define UNZ_BUFSIZE (UINT16_MAX)
66 #ifndef UNZ_MAXFILENAMEINZIP
67 # define UNZ_MAXFILENAMEINZIP (256)
71 # define ALLOC(size) (malloc(size))
74 # define TRYFREE(p) {if (p) free(p);}
77 const char unz_copyright[] = " unzip 1.2.0 Copyright 1998-2017 - https://github.com/nmoinvaz/minizip";
79 /* unz_file_info_internal contain internal info about a file in zipfile*/
80 typedef struct unz_file_info64_internal_s
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) */
85 uint8_t aes_encryption_mode;
86 uint16_t aes_compression_method;
89 } unz_file_info64_internal;
91 /* file_in_zip_read_info_s contain internal information about a file in zipfile */
94 uint8_t *read_buffer; /* internal buffer for compressed data */
95 z_stream stream; /* zLib stream structure for inflate */
97 bz_stream bstream; /* bzLib stream structure for bziped */
99 #ifdef HAVE_APPLE_COMPRESSION
100 compression_stream astream; /* libcompression stream structure */
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 */
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;
113 uint32_t crc32; /* crc32 of all data uncompressed */
114 uint32_t crc32_expected; /* 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 */
118 zlib_filefunc64_32_def z_filefunc;
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) */
124 } file_in_zip64_read_info_s;
126 /* unz64_s contain internal information about the zipfile */
129 zlib_filefunc64_32_def z_filefunc;
131 voidpf filestream; /* io structure of the current zipfile */
132 voidpf filestream_with_CD; /* io structure of the disk with the central directory */
134 unz_global_info64 gi; /* public global information */
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 */
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 */
153 uint32_t keys[3]; /* keys defining the pseudo-random sequence */
154 const z_crc_t *pcrc_32_tab;
158 /* Read a byte from a gz_stream; Return EOF for end of file. */
159 static int unzReadUInt8(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint8_t *value)
162 if (ZREAD64(*pzlib_filefunc_def, filestream, &c, 1) == 1)
168 if (ZERROR64(*pzlib_filefunc_def, filestream))
173 static int unzReadUInt16(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint16_t *value)
179 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
182 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
183 x |= ((uint16_t)c) << 8;
192 static int unzReadUInt32(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint32_t *value)
198 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
201 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
202 x |= ((uint32_t)c) << 8;
204 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
205 x |= ((uint32_t)c) << 16;
207 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
208 x += ((uint32_t)c) << 24;
217 static int unzReadUInt64(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint64_t *value)
223 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
226 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
227 x |= ((uint64_t)i) << 8;
229 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
230 x |= ((uint64_t)i) << 16;
232 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
233 x |= ((uint64_t)i) << 24;
235 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
236 x |= ((uint64_t)i) << 32;
238 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
239 x |= ((uint64_t)i) << 40;
241 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
242 x |= ((uint64_t)i) << 48;
244 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
245 x |= ((uint64_t)i) << 56;
254 /* Locate the Central directory of a zip file (at the end, just before the global comment) */
255 static int unzSearchCentralDir(const zlib_filefunc64_32_def *pzlib_filefunc_def, uint64_t *pos_found, voidpf filestream)
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 uint32_t read_size = 0;
262 uint64_t read_pos = 0;
266 if (ZSEEK64(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
269 file_size = ZTELL64(*pzlib_filefunc_def, filestream);
271 if (max_back > file_size)
272 max_back = file_size;
274 while (back_read < max_back)
276 if (back_read + BUFREADCOMMENT > max_back)
277 back_read = max_back;
279 back_read += BUFREADCOMMENT;
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);
285 if (ZSEEK64(*pzlib_filefunc_def, filestream, read_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
287 if (ZREAD64(*pzlib_filefunc_def, filestream, buf, read_size) != read_size)
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)))
296 *pos_found = read_pos+i;
304 /* Locate the Central directory 64 of a zipfile (at the end, just before the global comment) */
305 static int unzSearchCentralDir64(const zlib_filefunc64_32_def *pzlib_filefunc_def, uint64_t *offset, voidpf filestream,
306 const uint64_t endcentraloffset)
308 uint32_t value32 = 0;
311 /* Zip64 end of central directory locator */
312 if (ZSEEK64(*pzlib_filefunc_def, filestream, endcentraloffset - SIZECENTRALHEADERLOCATOR, ZLIB_FILEFUNC_SEEK_SET) != 0)
315 /* Read locator signature */
316 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
318 if (value32 != ZIP64ENDLOCHEADERMAGIC)
320 /* Number of the disk with the start of the zip64 end of central directory */
321 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
323 /* Relative offset of the zip64 end of central directory record */
324 if (unzReadUInt64(pzlib_filefunc_def, filestream, offset) != UNZ_OK)
326 /* Total number of disks */
327 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
329 /* Goto end of central directory record */
330 if (ZSEEK64(*pzlib_filefunc_def, filestream, *offset, ZLIB_FILEFUNC_SEEK_SET) != 0)
333 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
335 if (value32 != ZIP64ENDHEADERMAGIC)
341 static unzFile unzOpenInternal(const void *path, zlib_filefunc64_32_def *pzlib_filefunc64_32_def)
344 unz64_internal *s = NULL;
345 uint64_t central_pos = 0;
346 uint64_t central_pos64 = 0;
347 uint64_t number_entry_CD = 0;
348 uint16_t value16 = 0;
349 uint32_t value32 = 0;
350 uint64_t value64 = 0;
351 voidpf filestream = NULL;
355 us.filestream = NULL;
356 us.filestream_with_CD = NULL;
357 us.z_filefunc.zseek32_file = NULL;
358 us.z_filefunc.ztell32_file = NULL;
360 if (pzlib_filefunc64_32_def == NULL)
361 fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
363 us.z_filefunc = *pzlib_filefunc64_32_def;
365 us.filestream = ZOPEN64(us.z_filefunc, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
367 if (us.filestream == NULL)
370 us.filestream_with_CD = us.filestream;
373 /* Search for end of central directory header */
374 err = unzSearchCentralDir(&us.z_filefunc, ¢ral_pos, us.filestream);
377 if (ZSEEK64(us.z_filefunc, us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
380 /* The signature, already checked */
381 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
383 /* Number of this disk */
384 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
386 us.number_disk = value16;
387 /* Number of the disk with the start of the central directory */
388 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
390 us.gi.number_disk_with_CD = value16;
391 /* Total number of entries in the central directory on this disk */
392 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
394 us.gi.number_entry = value16;
395 /* Total number of entries in the central directory */
396 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
398 number_entry_CD = value16;
399 if (number_entry_CD != us.gi.number_entry)
400 err = UNZ_BADZIPFILE;
401 /* Size of the central directory */
402 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
404 us.size_central_dir = value32;
405 /* Offset of start of central directory with respect to the starting disk number */
406 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
408 us.offset_central_dir = value32;
409 /* Zipfile comment length */
410 if (unzReadUInt16(&us.z_filefunc, us.filestream, &us.gi.size_comment) != UNZ_OK)
415 /* Search for Zip64 end of central directory header */
416 err64 = unzSearchCentralDir64(&us.z_filefunc, ¢ral_pos64, us.filestream, central_pos);
419 central_pos = central_pos64;
422 if (ZSEEK64(us.z_filefunc, us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
425 /* the signature, already checked */
426 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
428 /* size of zip64 end of central directory record */
429 if (unzReadUInt64(&us.z_filefunc, us.filestream, &value64) != UNZ_OK)
431 /* version made by */
432 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
434 /* version needed to extract */
435 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
437 /* number of this disk */
438 if (unzReadUInt32(&us.z_filefunc, us.filestream, &us.number_disk) != UNZ_OK)
440 /* number of the disk with the start of the central directory */
441 if (unzReadUInt32(&us.z_filefunc, us.filestream, &us.gi.number_disk_with_CD) != UNZ_OK)
443 /* total number of entries in the central directory on this disk */
444 if (unzReadUInt64(&us.z_filefunc, us.filestream, &us.gi.number_entry) != UNZ_OK)
446 /* total number of entries in the central directory */
447 if (unzReadUInt64(&us.z_filefunc, us.filestream, &number_entry_CD) != UNZ_OK)
449 if (number_entry_CD != us.gi.number_entry)
450 err = UNZ_BADZIPFILE;
451 /* size of the central directory */
452 if (unzReadUInt64(&us.z_filefunc, us.filestream, &us.size_central_dir) != UNZ_OK)
454 /* offset of start of central directory with respect to the starting disk number */
455 if (unzReadUInt64(&us.z_filefunc, us.filestream, &us.offset_central_dir) != UNZ_OK)
458 else if ((us.size_central_dir == UINT16_MAX) || (us.offset_central_dir == UINT32_MAX))
459 err = UNZ_BADZIPFILE;
465 if ((err == UNZ_OK) && (central_pos < us.offset_central_dir + us.size_central_dir))
466 err = UNZ_BADZIPFILE;
470 ZCLOSE64(us.z_filefunc, us.filestream);
474 if (us.gi.number_disk_with_CD == 0)
476 /* If there is only one disk open another stream so we don't have to seek between the CD
477 and the file headers constantly */
478 filestream = ZOPEN64(us.z_filefunc, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
479 if (filestream != NULL)
480 us.filestream = filestream;
483 /* Hack for zip files that have no respect for zip64
484 if ((central_pos > 0xffffffff) && (us.offset_central_dir < 0xffffffff))
485 us.offset_central_dir = central_pos - us.size_central_dir;*/
487 us.byte_before_the_zipfile = central_pos - (us.offset_central_dir + us.size_central_dir);
488 us.central_pos = central_pos;
489 us.pfile_in_zip_read = NULL;
491 s = (unz64_internal*)ALLOC(sizeof(unz64_internal));
496 // workaround incorrect count #184
497 s->gi.number_entry = unzCountEntries(s);
499 unzGoToFirstFile((unzFile)s);
504 extern unzFile ZEXPORT unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc32_def)
506 if (pzlib_filefunc32_def != NULL)
508 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
509 fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill, pzlib_filefunc32_def);
510 return unzOpenInternal(path, &zlib_filefunc64_32_def_fill);
512 return unzOpenInternal(path, NULL);
515 extern unzFile ZEXPORT unzOpen2_64(const void *path, zlib_filefunc64_def *pzlib_filefunc_def)
517 if (pzlib_filefunc_def != NULL)
519 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
520 zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
521 zlib_filefunc64_32_def_fill.ztell32_file = NULL;
522 zlib_filefunc64_32_def_fill.zseek32_file = NULL;
523 return unzOpenInternal(path, &zlib_filefunc64_32_def_fill);
525 return unzOpenInternal(path, NULL);
528 extern unzFile ZEXPORT unzOpen(const char *path)
530 return unzOpenInternal(path, NULL);
533 extern unzFile ZEXPORT unzOpen64(const void *path)
535 return unzOpenInternal(path, NULL);
538 extern int ZEXPORT unzClose(unzFile file)
542 return UNZ_PARAMERROR;
543 s = (unz64_internal*)file;
545 if (s->pfile_in_zip_read != NULL)
546 unzCloseCurrentFile(file);
548 if ((s->filestream != NULL) && (s->filestream != s->filestream_with_CD))
549 ZCLOSE64(s->z_filefunc, s->filestream);
550 if (s->filestream_with_CD != NULL)
551 ZCLOSE64(s->z_filefunc, s->filestream_with_CD);
553 s->filestream = NULL;
554 s->filestream_with_CD = NULL;
559 /* Goto to the next available disk for spanned archives */
560 static int unzGoToNextDisk(unzFile file)
563 uint32_t number_disk_next = 0;
565 s = (unz64_internal*)file;
567 return UNZ_PARAMERROR;
568 number_disk_next = s->number_disk;
570 if ((s->pfile_in_zip_read != NULL) && (s->pfile_in_zip_read->rest_read_uncompressed > 0))
571 /* We are currently reading a file and we need the next sequential disk */
572 number_disk_next += 1;
574 /* Goto the disk for the current file */
575 number_disk_next = s->cur_file_info.disk_num_start;
577 if (number_disk_next != s->number_disk)
580 if ((s->filestream != NULL) && (s->filestream != s->filestream_with_CD))
581 ZCLOSE64(s->z_filefunc, s->filestream);
583 if (number_disk_next == s->gi.number_disk_with_CD)
585 s->filestream = s->filestream_with_CD;
589 s->filestream = ZOPENDISK64(s->z_filefunc, s->filestream_with_CD, number_disk_next,
590 ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
593 if (s->filestream == NULL)
596 s->number_disk = number_disk_next;
602 extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32)
604 unz64_internal *s = NULL;
606 return UNZ_PARAMERROR;
607 s = (unz64_internal*)file;
609 pglobal_info32->number_entry = (uint32_t)s->gi.number_entry;
610 pglobal_info32->size_comment = s->gi.size_comment;
611 pglobal_info32->number_disk_with_CD = s->gi.number_disk_with_CD;
615 extern int ZEXPORT unzGetGlobalInfo64(unzFile file, unz_global_info64 *pglobal_info)
617 unz64_internal *s = NULL;
619 return UNZ_PARAMERROR;
620 s = (unz64_internal*)file;
621 *pglobal_info = s->gi;
625 extern int ZEXPORT unzGetGlobalComment(unzFile file, char *comment, uint16_t comment_size)
627 unz64_internal *s = NULL;
628 uint16_t bytes_to_read = comment_size;
630 return (int)UNZ_PARAMERROR;
631 s = (unz64_internal*)file;
633 if (bytes_to_read > s->gi.size_comment)
634 bytes_to_read = s->gi.size_comment;
636 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, s->central_pos + 22, ZLIB_FILEFUNC_SEEK_SET) != 0)
639 if (bytes_to_read > 0)
642 if (ZREAD64(s->z_filefunc, s->filestream_with_CD, comment, bytes_to_read) != bytes_to_read)
646 if ((comment != NULL) && (comment_size > s->gi.size_comment))
647 *(comment + s->gi.size_comment) = 0;
649 return (int)bytes_to_read;
652 static int unzGetCurrentFileInfoField(unzFile file, uint32_t *seek, void *field, uint16_t field_size, uint16_t size_file_field, int null_terminated_field)
654 unz64_internal *s = NULL;
655 uint32_t bytes_to_read = 0;
659 return (int)UNZ_PARAMERROR;
660 s = (unz64_internal*)file;
665 if (size_file_field < field_size)
667 if (null_terminated_field)
668 *((char *)field+size_file_field) = 0;
670 bytes_to_read = size_file_field;
673 bytes_to_read = field_size;
677 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, *seek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
683 if ((size_file_field > 0) && (field_size > 0))
685 if (ZREAD64(s->z_filefunc, s->filestream_with_CD, field, bytes_to_read) != bytes_to_read)
688 *seek += size_file_field - bytes_to_read;
692 *seek += size_file_field;
698 /* Get info about the current file in the zipfile, with internal only info */
699 static int unzGetCurrentFileInfoInternal(unzFile file, unz_file_info64 *pfile_info,
700 unz_file_info64_internal *pfile_info_internal, char *filename, uint16_t filename_size, void *extrafield,
701 uint16_t extrafield_size, char *comment, uint16_t comment_size)
703 unz64_internal *s = NULL;
704 unz_file_info64 file_info;
705 unz_file_info64_internal file_info_internal;
707 uint64_t current_pos = 0;
709 uint32_t extra_pos = 0;
710 uint16_t extra_header_id = 0;
711 uint16_t extra_data_size = 0;
712 uint16_t value16 = 0;
713 uint32_t value32 = 0;
714 uint64_t value64 = 0;
718 return UNZ_PARAMERROR;
719 s = (unz64_internal*)file;
721 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD,
722 s->pos_in_central_dir + s->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
725 /* Check the magic */
728 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &magic) != UNZ_OK)
730 else if (magic != CENTRALHEADERMAGIC)
731 err = UNZ_BADZIPFILE;
734 /* Read central directory header */
735 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.version) != UNZ_OK)
737 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.version_needed) != UNZ_OK)
739 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.flag) != UNZ_OK)
741 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.compression_method) != UNZ_OK)
743 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.dos_date) != UNZ_OK)
745 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.crc) != UNZ_OK)
747 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &value32) != UNZ_OK)
749 file_info.compressed_size = value32;
750 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &value32) != UNZ_OK)
752 file_info.uncompressed_size = value32;
753 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.size_filename) != UNZ_OK)
755 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.size_file_extra) != UNZ_OK)
757 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.size_file_comment) != UNZ_OK)
759 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &value16) != UNZ_OK)
761 file_info.disk_num_start = value16;
762 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.internal_fa) != UNZ_OK)
764 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.external_fa) != UNZ_OK)
766 /* Relative offset of local header */
767 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &value32) != UNZ_OK)
770 file_info.size_file_extra_internal = 0;
771 file_info.disk_offset = value32;
772 file_info_internal.offset_curfile = value32;
774 file_info_internal.aes_compression_method = 0;
775 file_info_internal.aes_encryption_mode = 0;
776 file_info_internal.aes_version = 0;
780 err = unzGetCurrentFileInfoField(file, &seek, filename, filename_size, file_info.size_filename, 1);
782 /* Read extrafield */
784 err = unzGetCurrentFileInfoField(file, &seek, extrafield, extrafield_size, file_info.size_file_extra, 0);
786 if ((err == UNZ_OK) && (file_info.size_file_extra != 0))
790 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, seek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
796 /* We are going to parse the extra field so we need to move back */
797 current_pos = ZTELL64(s->z_filefunc, s->filestream_with_CD);
798 if (current_pos < file_info.size_file_extra)
800 current_pos -= file_info.size_file_extra;
801 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, current_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
804 while ((err != UNZ_ERRNO) && (extra_pos < file_info.size_file_extra))
806 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &extra_header_id) != UNZ_OK)
808 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &extra_data_size) != UNZ_OK)
811 /* ZIP64 extra fields */
812 if (extra_header_id == 0x0001)
814 /* Subtract size of ZIP64 field, since ZIP64 is handled internally */
815 file_info.size_file_extra_internal += 2 + 2 + extra_data_size;
817 if (file_info.uncompressed_size == UINT32_MAX)
819 if (unzReadUInt64(&s->z_filefunc, s->filestream_with_CD, &file_info.uncompressed_size) != UNZ_OK)
822 if (file_info.compressed_size == UINT32_MAX)
824 if (unzReadUInt64(&s->z_filefunc, s->filestream_with_CD, &file_info.compressed_size) != UNZ_OK)
827 if (file_info_internal.offset_curfile == UINT32_MAX)
829 /* Relative Header offset */
830 if (unzReadUInt64(&s->z_filefunc, s->filestream_with_CD, &value64) != UNZ_OK)
832 file_info_internal.offset_curfile = value64;
833 file_info.disk_offset = value64;
835 if (file_info.disk_num_start == UINT32_MAX)
837 /* Disk Start Number */
838 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.disk_num_start) != UNZ_OK)
844 else if (extra_header_id == 0x9901)
848 /* Subtract size of AES field, since AES is handled internally */
849 file_info.size_file_extra_internal += 2 + 2 + extra_data_size;
851 /* Verify version info */
852 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &value16) != UNZ_OK)
854 /* Support AE-1 and AE-2 */
855 if (value16 != 1 && value16 != 2)
857 file_info_internal.aes_version = value16;
858 if (unzReadUInt8(&s->z_filefunc, s->filestream_with_CD, &value8) != UNZ_OK)
860 if ((char)value8 != 'A')
862 if (unzReadUInt8(&s->z_filefunc, s->filestream_with_CD, &value8) != UNZ_OK)
864 if ((char)value8 != 'E')
866 /* Get AES encryption strength and actual compression method */
867 if (unzReadUInt8(&s->z_filefunc, s->filestream_with_CD, &value8) != UNZ_OK)
869 file_info_internal.aes_encryption_mode = value8;
870 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &value16) != UNZ_OK)
872 file_info_internal.aes_compression_method = value16;
877 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD,extra_data_size, ZLIB_FILEFUNC_SEEK_CUR) != 0)
881 extra_pos += 2 + 2 + extra_data_size;
885 if (file_info.disk_num_start == s->gi.number_disk_with_CD)
886 file_info_internal.byte_before_the_zipfile = s->byte_before_the_zipfile;
888 file_info_internal.byte_before_the_zipfile = 0;
891 err = unzGetCurrentFileInfoField(file, &seek, comment, comment_size, file_info.size_file_comment, 1);
893 if ((err == UNZ_OK) && (pfile_info != NULL))
894 *pfile_info = file_info;
895 if ((err == UNZ_OK) && (pfile_info_internal != NULL))
896 *pfile_info_internal = file_info_internal;
901 extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *filename,
902 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
904 unz_file_info64 file_info64;
907 err = unzGetCurrentFileInfoInternal(file, &file_info64, NULL, filename, filename_size,
908 extrafield, extrafield_size, comment, comment_size);
910 if ((err == UNZ_OK) && (pfile_info != NULL))
912 pfile_info->version = file_info64.version;
913 pfile_info->version_needed = file_info64.version_needed;
914 pfile_info->flag = file_info64.flag;
915 pfile_info->compression_method = file_info64.compression_method;
916 pfile_info->dos_date = file_info64.dos_date;
917 pfile_info->crc = file_info64.crc;
919 pfile_info->size_filename = file_info64.size_filename;
920 pfile_info->size_file_extra = file_info64.size_file_extra - file_info64.size_file_extra_internal;
921 pfile_info->size_file_comment = file_info64.size_file_comment;
923 pfile_info->disk_num_start = (uint16_t)file_info64.disk_num_start;
924 pfile_info->internal_fa = file_info64.internal_fa;
925 pfile_info->external_fa = file_info64.external_fa;
927 pfile_info->compressed_size = (uint32_t)file_info64.compressed_size;
928 pfile_info->uncompressed_size = (uint32_t)file_info64.uncompressed_size;
933 extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file, unz_file_info64 * pfile_info, char *filename,
934 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
936 return unzGetCurrentFileInfoInternal(file, pfile_info, NULL, filename, filename_size,
937 extrafield, extrafield_size, comment,comment_size);
940 /* Read the local header of the current zipfile. Check the coherency of the local header and info in the
941 end of central directory about this file store in *piSizeVar the size of extra info in local header
942 (filename and size of extra field data) */
943 static int unzCheckCurrentFileCoherencyHeader(unz64_internal *s, uint32_t *psize_variable, uint64_t *poffset_local_extrafield,
944 uint16_t *psize_local_extrafield)
947 uint16_t value16 = 0;
948 uint32_t value32 = 0;
950 uint16_t size_filename = 0;
951 uint16_t size_extra_field = 0;
952 uint16_t compression_method = 0;
955 if (psize_variable == NULL)
956 return UNZ_PARAMERROR;
958 if (poffset_local_extrafield == NULL)
959 return UNZ_PARAMERROR;
960 *poffset_local_extrafield = 0;
961 if (psize_local_extrafield == NULL)
962 return UNZ_PARAMERROR;
963 *psize_local_extrafield = 0;
965 err = unzGoToNextDisk((unzFile)s);
969 if (ZSEEK64(s->z_filefunc, s->filestream, s->cur_file_info_internal.offset_curfile +
970 s->cur_file_info_internal.byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
975 if (unzReadUInt32(&s->z_filefunc, s->filestream, &magic) != UNZ_OK)
977 else if (magic != LOCALHEADERMAGIC)
978 err = UNZ_BADZIPFILE;
981 if (unzReadUInt16(&s->z_filefunc, s->filestream, &value16) != UNZ_OK)
983 if (unzReadUInt16(&s->z_filefunc, s->filestream, &value16) != UNZ_OK)
986 if (unzReadUInt16(&s->z_filefunc, s->filestream, &value16) != UNZ_OK)
988 else if ((err == UNZ_OK) && (value16 != s->cur_file_info.compression_method))
989 err = UNZ_BADZIPFILE;
991 compression_method = s->cur_file_info.compression_method;
993 if (compression_method == AES_METHOD)
994 compression_method = s->cur_file_info_internal.aes_compression_method;
997 if ((err == UNZ_OK) && (compression_method != 0) && (compression_method != Z_DEFLATED))
1000 if (compression_method != Z_BZIP2ED)
1002 err = UNZ_BADZIPFILE;
1005 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* date/time */
1007 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* crc */
1009 else if ((err == UNZ_OK) && (value32 != s->cur_file_info.crc) && ((flags & 8) == 0))
1010 err = UNZ_BADZIPFILE;
1011 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* size compr */
1013 else if ((value32 != UINT32_MAX) && (err == UNZ_OK) && (value32 != s->cur_file_info.compressed_size) && ((flags & 8) == 0))
1014 err = UNZ_BADZIPFILE;
1015 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* size uncompr */
1017 else if ((value32 != UINT32_MAX) && (err == UNZ_OK) && (value32 != s->cur_file_info.uncompressed_size) && ((flags & 8) == 0))
1018 err = UNZ_BADZIPFILE;
1019 if (unzReadUInt16(&s->z_filefunc, s->filestream, &size_filename) != UNZ_OK)
1022 *psize_variable += size_filename;
1024 if (unzReadUInt16(&s->z_filefunc, s->filestream, &size_extra_field) != UNZ_OK)
1027 *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_filename;
1028 *psize_local_extrafield = size_extra_field;
1029 *psize_variable += size_extra_field;
1034 extern uint64_t ZEXPORT unzCountEntries(const unzFile file)
1039 unz64_internal s = *(unz64_internal*)file;
1041 s.pos_in_central_dir = s.offset_central_dir;
1043 while (UNZ_OK == unzGetCurrentFileInfoInternal(&s,
1045 &s.cur_file_info_internal,
1046 NULL, 0, NULL, 0, NULL, 0))
1048 s.pos_in_central_dir += SIZECENTRALDIRITEM
1049 + s.cur_file_info.size_filename
1050 + s.cur_file_info.size_file_extra
1051 + s.cur_file_info.size_file_comment;
1058 Open for reading data the current file in the zipfile.
1059 If there is no error and the file is opened, the return value is UNZ_OK.
1061 extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password)
1063 unz64_internal *s = NULL;
1064 file_in_zip64_read_info_s *pfile_in_zip_read_info = NULL;
1065 uint16_t compression_method = 0;
1066 uint64_t offset_local_extrafield = 0;
1067 uint16_t size_local_extrafield = 0;
1068 uint32_t size_variable = 0;
1073 if (password != NULL)
1074 return UNZ_PARAMERROR;
1077 return UNZ_PARAMERROR;
1078 s = (unz64_internal*)file;
1079 if (!s->current_file_ok)
1080 return UNZ_PARAMERROR;
1082 if (s->pfile_in_zip_read != NULL)
1083 unzCloseCurrentFile(file);
1085 if (unzCheckCurrentFileCoherencyHeader(s, &size_variable, &offset_local_extrafield, &size_local_extrafield) != UNZ_OK)
1086 return UNZ_BADZIPFILE;
1088 compression_method = s->cur_file_info.compression_method;
1090 if (compression_method == AES_METHOD)
1092 compression_method = s->cur_file_info_internal.aes_compression_method;
1093 if (password == NULL)
1095 return UNZ_PARAMERROR;
1101 *method = compression_method;
1106 switch (s->cur_file_info.flag & 0x06)
1108 case 6 : *level = 1; break;
1109 case 4 : *level = 2; break;
1110 case 2 : *level = 9; break;
1114 if ((compression_method != 0) && (compression_method != Z_DEFLATED))
1117 if (compression_method != Z_BZIP2ED)
1120 return UNZ_BADZIPFILE;
1124 pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
1125 if (pfile_in_zip_read_info == NULL)
1126 return UNZ_INTERNALERROR;
1128 pfile_in_zip_read_info->read_buffer = (uint8_t*)ALLOC(UNZ_BUFSIZE);
1129 if (pfile_in_zip_read_info->read_buffer == NULL)
1131 TRYFREE(pfile_in_zip_read_info);
1132 return UNZ_INTERNALERROR;
1135 pfile_in_zip_read_info->stream_initialised = 0;
1137 pfile_in_zip_read_info->filestream = s->filestream;
1138 pfile_in_zip_read_info->z_filefunc = s->z_filefunc;
1140 pfile_in_zip_read_info->raw = raw;
1141 pfile_in_zip_read_info->crc32 = 0;
1142 pfile_in_zip_read_info->crc32_expected = s->cur_file_info.crc;
1143 pfile_in_zip_read_info->total_out_64 = 0;
1144 pfile_in_zip_read_info->compression_method = compression_method;
1146 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1147 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1148 pfile_in_zip_read_info->pos_local_extrafield = 0;
1150 pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size;
1151 pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size;
1152 pfile_in_zip_read_info->byte_before_the_zipfile = 0;
1154 if (s->number_disk == s->gi.number_disk_with_CD)
1155 pfile_in_zip_read_info->byte_before_the_zipfile = s->byte_before_the_zipfile;
1157 pfile_in_zip_read_info->pos_in_zipfile = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_variable;
1159 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1160 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1161 pfile_in_zip_read_info->stream.opaque = (voidpf)s;
1162 pfile_in_zip_read_info->stream.total_out = 0;
1163 pfile_in_zip_read_info->stream.total_in = 0;
1164 pfile_in_zip_read_info->stream.next_in = NULL;
1165 pfile_in_zip_read_info->stream.avail_in = 0;
1169 if (compression_method == Z_BZIP2ED)
1172 pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
1173 pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
1174 pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
1175 pfile_in_zip_read_info->bstream.state = (voidpf)0;
1177 err = BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
1180 pfile_in_zip_read_info->stream_initialised = Z_BZIP2ED;
1184 TRYFREE(pfile_in_zip_read_info);
1188 pfile_in_zip_read_info->raw = 1;
1191 else if (compression_method == Z_DEFLATED)
1193 #ifdef HAVE_APPLE_COMPRESSION
1194 err = compression_stream_init(&pfile_in_zip_read_info->astream, COMPRESSION_STREAM_DECODE, COMPRESSION_ZLIB);
1195 if (err == COMPRESSION_STATUS_ERROR)
1196 err = UNZ_INTERNALERROR;
1200 err = inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1204 pfile_in_zip_read_info->stream_initialised = Z_DEFLATED;
1208 TRYFREE(pfile_in_zip_read_info);
1211 /* windowBits is passed < 0 to tell that there is no zlib header.
1212 * Note that in this case inflate *requires* an extra "dummy" byte
1213 * after the compressed stream in order to complete decompression and
1214 * return Z_STREAM_END.
1215 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1216 * size of both compressed and uncompressed data
1221 s->pfile_in_zip_read = pfile_in_zip_read_info;
1224 s->pcrc_32_tab = NULL;
1226 if ((password != NULL) && ((s->cur_file_info.flag & 1) != 0))
1228 if (ZSEEK64(s->z_filefunc, s->filestream,
1229 s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile,
1230 ZLIB_FILEFUNC_SEEK_SET) != 0)
1231 return UNZ_INTERNALERROR;
1233 if (s->cur_file_info.compression_method == AES_METHOD)
1235 unsigned char passverify_archive[AES_PWVERIFYSIZE];
1236 unsigned char passverify_password[AES_PWVERIFYSIZE];
1237 unsigned char salt_value[AES_MAXSALTLENGTH];
1238 uint32_t salt_length = 0;
1240 if ((s->cur_file_info_internal.aes_encryption_mode < 1) ||
1241 (s->cur_file_info_internal.aes_encryption_mode > 3))
1242 return UNZ_INTERNALERROR;
1244 salt_length = SALT_LENGTH(s->cur_file_info_internal.aes_encryption_mode);
1246 if (ZREAD64(s->z_filefunc, s->filestream, salt_value, salt_length) != salt_length)
1247 return UNZ_INTERNALERROR;
1248 if (ZREAD64(s->z_filefunc, s->filestream, passverify_archive, AES_PWVERIFYSIZE) != AES_PWVERIFYSIZE)
1249 return UNZ_INTERNALERROR;
1251 fcrypt_init(s->cur_file_info_internal.aes_encryption_mode, (uint8_t *)password,
1252 (uint32_t)strlen(password), salt_value, passverify_password, &s->pfile_in_zip_read->aes_ctx);
1254 if (memcmp(passverify_archive, passverify_password, AES_PWVERIFYSIZE) != 0)
1255 return UNZ_BADPASSWORD;
1257 s->pfile_in_zip_read->rest_read_compressed -= salt_length + AES_PWVERIFYSIZE;
1258 s->pfile_in_zip_read->rest_read_compressed -= AES_AUTHCODESIZE;
1260 s->pfile_in_zip_read->pos_in_zipfile += salt_length + AES_PWVERIFYSIZE;
1266 s->pcrc_32_tab = (const z_crc_t*)get_crc_table();
1267 init_keys(password, s->keys, s->pcrc_32_tab);
1269 if (ZREAD64(s->z_filefunc, s->filestream, source, 12) < 12)
1270 return UNZ_INTERNALERROR;
1272 for (i = 0; i < 12; i++)
1273 zdecode(s->keys, s->pcrc_32_tab, source[i]);
1275 s->pfile_in_zip_read->rest_read_compressed -= 12;
1276 s->pfile_in_zip_read->pos_in_zipfile += 12;
1284 extern int ZEXPORT unzOpenCurrentFile(unzFile file)
1286 return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1289 extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char *password)
1291 return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1294 extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int *method, int *level, int raw)
1296 return unzOpenCurrentFile3(file, method, level, raw, NULL);
1299 /* Read bytes from the current file.
1300 buf contain buffer where data must be copied
1301 len the size of buf.
1303 return the number of byte copied if some bytes are copied
1304 return 0 if the end of file was reached
1305 return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */
1306 extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, uint32_t len)
1308 unz64_internal *s = NULL;
1313 return UNZ_PARAMERROR;
1314 s = (unz64_internal*)file;
1316 if (s->pfile_in_zip_read == NULL)
1317 return UNZ_PARAMERROR;
1318 if (s->pfile_in_zip_read->read_buffer == NULL)
1319 return UNZ_END_OF_LIST_OF_FILE;
1322 if (len > UINT16_MAX)
1323 return UNZ_PARAMERROR;
1325 s->pfile_in_zip_read->stream.next_out = (uint8_t*)buf;
1326 s->pfile_in_zip_read->stream.avail_out = (uint16_t)len;
1328 if ((s->pfile_in_zip_read->compression_method == 0) || (s->pfile_in_zip_read->raw))
1330 if (len > s->pfile_in_zip_read->rest_read_compressed + s->pfile_in_zip_read->stream.avail_in)
1331 s->pfile_in_zip_read->stream.avail_out = (uint16_t)s->pfile_in_zip_read->rest_read_compressed +
1332 s->pfile_in_zip_read->stream.avail_in;
1337 if (s->pfile_in_zip_read->stream.avail_in == 0)
1339 uint32_t bytes_to_read = UNZ_BUFSIZE;
1340 uint32_t bytes_not_read = 0;
1341 uint32_t bytes_read = 0;
1342 uint32_t total_bytes_read = 0;
1344 if (s->pfile_in_zip_read->stream.next_in != NULL)
1345 bytes_not_read = (uint32_t)(s->pfile_in_zip_read->read_buffer + UNZ_BUFSIZE -
1346 s->pfile_in_zip_read->stream.next_in);
1347 bytes_to_read -= bytes_not_read;
1348 if (bytes_not_read > 0)
1349 memcpy(s->pfile_in_zip_read->read_buffer, s->pfile_in_zip_read->stream.next_in, bytes_not_read);
1350 if (s->pfile_in_zip_read->rest_read_compressed < bytes_to_read)
1351 bytes_to_read = (uint16_t)s->pfile_in_zip_read->rest_read_compressed;
1353 while (total_bytes_read != bytes_to_read)
1355 if (ZSEEK64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream,
1356 s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile,
1357 ZLIB_FILEFUNC_SEEK_SET) != 0)
1360 bytes_read = ZREAD64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream,
1361 s->pfile_in_zip_read->read_buffer + bytes_not_read + total_bytes_read,
1362 bytes_to_read - total_bytes_read);
1364 total_bytes_read += bytes_read;
1365 s->pfile_in_zip_read->pos_in_zipfile += bytes_read;
1367 if (bytes_read == 0)
1369 if (ZERROR64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream))
1372 err = unzGoToNextDisk(file);
1376 s->pfile_in_zip_read->pos_in_zipfile = 0;
1377 s->pfile_in_zip_read->filestream = s->filestream;
1382 if ((s->cur_file_info.flag & 1) != 0)
1385 if (s->cur_file_info.compression_method == AES_METHOD)
1387 fcrypt_decrypt(s->pfile_in_zip_read->read_buffer, bytes_to_read, &s->pfile_in_zip_read->aes_ctx);
1391 if (s->pcrc_32_tab != NULL)
1395 for (i = 0; i < total_bytes_read; i++)
1396 s->pfile_in_zip_read->read_buffer[i] =
1397 zdecode(s->keys, s->pcrc_32_tab, s->pfile_in_zip_read->read_buffer[i]);
1402 s->pfile_in_zip_read->rest_read_compressed -= total_bytes_read;
1403 s->pfile_in_zip_read->stream.next_in = (uint8_t*)s->pfile_in_zip_read->read_buffer;
1404 s->pfile_in_zip_read->stream.avail_in = (uint16_t)(bytes_not_read + total_bytes_read);
1407 if ((s->pfile_in_zip_read->compression_method == 0) || (s->pfile_in_zip_read->raw))
1412 if ((s->pfile_in_zip_read->stream.avail_in == 0) &&
1413 (s->pfile_in_zip_read->rest_read_compressed == 0))
1414 return (read == 0) ? UNZ_EOF : read;
1416 if (s->pfile_in_zip_read->stream.avail_out < s->pfile_in_zip_read->stream.avail_in)
1417 copy = s->pfile_in_zip_read->stream.avail_out;
1419 copy = s->pfile_in_zip_read->stream.avail_in;
1421 for (i = 0; i < copy; i++)
1422 *(s->pfile_in_zip_read->stream.next_out + i) =
1423 *(s->pfile_in_zip_read->stream.next_in + i);
1425 s->pfile_in_zip_read->total_out_64 = s->pfile_in_zip_read->total_out_64 + copy;
1426 s->pfile_in_zip_read->rest_read_uncompressed -= copy;
1427 s->pfile_in_zip_read->crc32 = (uint32_t)crc32(s->pfile_in_zip_read->crc32,
1428 s->pfile_in_zip_read->stream.next_out, copy);
1430 s->pfile_in_zip_read->stream.avail_in -= copy;
1431 s->pfile_in_zip_read->stream.avail_out -= copy;
1432 s->pfile_in_zip_read->stream.next_out += copy;
1433 s->pfile_in_zip_read->stream.next_in += copy;
1434 s->pfile_in_zip_read->stream.total_out += copy;
1438 else if (s->pfile_in_zip_read->compression_method == Z_BZIP2ED)
1441 uint64_t total_out_before = 0;
1442 uint64_t total_out_after = 0;
1443 uint64_t out_bytes = 0;
1444 const uint8_t *buf_before = NULL;
1446 s->pfile_in_zip_read->bstream.next_in = (char*)s->pfile_in_zip_read->stream.next_in;
1447 s->pfile_in_zip_read->bstream.avail_in = s->pfile_in_zip_read->stream.avail_in;
1448 s->pfile_in_zip_read->bstream.total_in_lo32 = (uint32_t)s->pfile_in_zip_read->stream.total_in;
1449 s->pfile_in_zip_read->bstream.total_in_hi32 = s->pfile_in_zip_read->stream.total_in >> 32;
1451 s->pfile_in_zip_read->bstream.next_out = (char*)s->pfile_in_zip_read->stream.next_out;
1452 s->pfile_in_zip_read->bstream.avail_out = s->pfile_in_zip_read->stream.avail_out;
1453 s->pfile_in_zip_read->bstream.total_out_lo32 = (uint32_t)s->pfile_in_zip_read->stream.total_out;
1454 s->pfile_in_zip_read->bstream.total_out_hi32 = s->pfile_in_zip_read->stream.total_out >> 32;
1456 total_out_before = s->pfile_in_zip_read->bstream.total_out_lo32 +
1457 (((uint32_t)s->pfile_in_zip_read->bstream.total_out_hi32) << 32);
1458 buf_before = (const uint8_t*)s->pfile_in_zip_read->bstream.next_out;
1460 err = BZ2_bzDecompress(&s->pfile_in_zip_read->bstream);
1462 total_out_after = s->pfile_in_zip_read->bstream.total_out_lo32 +
1463 (((uint32_t)s->pfile_in_zip_read->bstream.total_out_hi32) << 32);
1465 out_bytes = total_out_after - total_out_before;
1467 s->pfile_in_zip_read->total_out_64 = s->pfile_in_zip_read->total_out_64 + out_bytes;
1468 s->pfile_in_zip_read->rest_read_uncompressed -= out_bytes;
1469 s->pfile_in_zip_read->crc32 = crc32(s->pfile_in_zip_read->crc32, buf_before, (uint32_t)out_bytes);
1471 read += (uint32_t)out_bytes;
1473 s->pfile_in_zip_read->stream.next_in = (uint8_t*)s->pfile_in_zip_read->bstream.next_in;
1474 s->pfile_in_zip_read->stream.avail_in = s->pfile_in_zip_read->bstream.avail_in;
1475 s->pfile_in_zip_read->stream.total_in = s->pfile_in_zip_read->bstream.total_in_lo32;
1476 s->pfile_in_zip_read->stream.next_out = (uint8_t*)s->pfile_in_zip_read->bstream.next_out;
1477 s->pfile_in_zip_read->stream.avail_out = s->pfile_in_zip_read->bstream.avail_out;
1478 s->pfile_in_zip_read->stream.total_out = s->pfile_in_zip_read->bstream.total_out_lo32;
1480 if (err == BZ_STREAM_END)
1481 return (read == 0) ? UNZ_EOF : read;
1486 #ifdef HAVE_APPLE_COMPRESSION
1489 uint64_t total_out_before = 0;
1490 uint64_t total_out_after = 0;
1491 uint64_t out_bytes = 0;
1492 const uint8_t *buf_before = NULL;
1494 s->pfile_in_zip_read->astream.src_ptr = s->pfile_in_zip_read->stream.next_in;
1495 s->pfile_in_zip_read->astream.src_size = s->pfile_in_zip_read->stream.avail_in;
1496 s->pfile_in_zip_read->astream.dst_ptr = s->pfile_in_zip_read->stream.next_out;
1497 s->pfile_in_zip_read->astream.dst_size = len;
1499 total_out_before = s->pfile_in_zip_read->stream.total_out;
1500 buf_before = s->pfile_in_zip_read->stream.next_out;
1502 compression_status status;
1503 compression_stream_flags flags;
1505 if (s->pfile_in_zip_read->stream.avail_in == 0)
1507 flags = COMPRESSION_STREAM_FINALIZE;
1510 status = compression_stream_process(&s->pfile_in_zip_read->astream, flags);
1512 total_out_after = len - s->pfile_in_zip_read->astream.dst_size;
1513 out_bytes = total_out_after - total_out_before;
1515 s->pfile_in_zip_read->total_out_64 += out_bytes;
1516 s->pfile_in_zip_read->rest_read_uncompressed -= out_bytes;
1517 s->pfile_in_zip_read->crc32 =
1518 crc32(s->pfile_in_zip_read->crc32, buf_before, (uint32_t)out_bytes);
1520 read += (uint32_t)out_bytes;
1522 s->pfile_in_zip_read->stream.next_in = s->pfile_in_zip_read->astream.src_ptr;
1523 s->pfile_in_zip_read->stream.avail_in = s->pfile_in_zip_read->astream.src_size;
1524 s->pfile_in_zip_read->stream.next_out = s->pfile_in_zip_read->astream.dst_ptr;
1525 s->pfile_in_zip_read->stream.avail_out = s->pfile_in_zip_read->astream.dst_size;
1527 if (status == COMPRESSION_STATUS_END)
1528 return (read == 0) ? UNZ_EOF : read;
1529 if (status == COMPRESSION_STATUS_ERROR)
1530 return Z_DATA_ERROR;
1536 uint64_t total_out_before = 0;
1537 uint64_t total_out_after = 0;
1538 uint64_t out_bytes = 0;
1539 const uint8_t *buf_before = NULL;
1540 int flush = Z_SYNC_FLUSH;
1542 total_out_before = s->pfile_in_zip_read->stream.total_out;
1543 buf_before = s->pfile_in_zip_read->stream.next_out;
1546 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1547 pfile_in_zip_read_info->stream.avail_out) &&
1548 (pfile_in_zip_read_info->rest_read_compressed == 0))
1551 err = inflate(&s->pfile_in_zip_read->stream, flush);
1553 if ((err >= 0) && (s->pfile_in_zip_read->stream.msg != NULL))
1556 total_out_after = s->pfile_in_zip_read->stream.total_out;
1557 out_bytes = total_out_after - total_out_before;
1559 s->pfile_in_zip_read->total_out_64 += out_bytes;
1560 s->pfile_in_zip_read->rest_read_uncompressed -= out_bytes;
1561 s->pfile_in_zip_read->crc32 =
1562 (uint32_t)crc32(s->pfile_in_zip_read->crc32,buf_before, (uint32_t)out_bytes);
1564 read += (uint32_t)out_bytes;
1566 if (err == Z_STREAM_END)
1567 return (read == 0) ? UNZ_EOF : read;
1573 while (s->pfile_in_zip_read->stream.avail_out > 0);
1580 extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, uint32_t len)
1582 unz64_internal *s = NULL;
1583 uint64_t size_to_read = 0;
1584 uint32_t read_now = 0;
1587 return UNZ_PARAMERROR;
1588 s = (unz64_internal*)file;
1589 if (s->pfile_in_zip_read == NULL)
1590 return UNZ_PARAMERROR;
1592 size_to_read = s->pfile_in_zip_read->size_local_extrafield - s->pfile_in_zip_read->pos_local_extrafield;
1595 return (int)size_to_read;
1597 if (len > size_to_read)
1598 read_now = (uint32_t)size_to_read;
1605 if (ZSEEK64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream,
1606 s->pfile_in_zip_read->offset_local_extrafield + s->pfile_in_zip_read->pos_local_extrafield,
1607 ZLIB_FILEFUNC_SEEK_SET) != 0)
1610 if (ZREAD64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream, buf, read_now) != read_now)
1613 return (int)read_now;
1616 extern int ZEXPORT unzCloseCurrentFile(unzFile file)
1618 unz64_internal *s = NULL;
1619 file_in_zip64_read_info_s *pfile_in_zip_read_info = NULL;
1623 return UNZ_PARAMERROR;
1624 s = (unz64_internal*)file;
1625 pfile_in_zip_read_info = s->pfile_in_zip_read;
1626 if (pfile_in_zip_read_info == NULL)
1627 return UNZ_PARAMERROR;
1630 if (s->cur_file_info.compression_method == AES_METHOD)
1632 unsigned char authcode[AES_AUTHCODESIZE];
1633 unsigned char rauthcode[AES_AUTHCODESIZE];
1635 if (ZREAD64(s->z_filefunc, s->filestream, authcode, AES_AUTHCODESIZE) != AES_AUTHCODESIZE)
1638 if (fcrypt_end(rauthcode, &s->pfile_in_zip_read->aes_ctx) != AES_AUTHCODESIZE)
1640 if (memcmp(authcode, rauthcode, AES_AUTHCODESIZE) != 0)
1643 /* AES zip version AE-1 will expect a valid crc as well */
1644 if ((s->cur_file_info.compression_method != AES_METHOD) ||
1645 (s->cur_file_info_internal.aes_version == 0x0001))
1648 if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1649 (!pfile_in_zip_read_info->raw))
1651 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_expected)
1656 TRYFREE(pfile_in_zip_read_info->read_buffer);
1657 pfile_in_zip_read_info->read_buffer = NULL;
1658 if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
1660 #ifdef HAVE_APPLE_COMPRESSION
1661 if (compression_stream_destroy)
1662 compression_stream_destroy(&pfile_in_zip_read_info->astream);
1664 inflateEnd(&pfile_in_zip_read_info->stream);
1669 else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
1670 BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
1673 pfile_in_zip_read_info->stream_initialised = 0;
1674 TRYFREE(pfile_in_zip_read_info);
1676 s->pfile_in_zip_read = NULL;
1681 extern int ZEXPORT unzGoToFirstFile2(unzFile file, unz_file_info64 *pfile_info, char *filename,
1682 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
1684 unz64_internal *s = NULL;
1688 return UNZ_PARAMERROR;
1689 s = (unz64_internal*)file;
1691 if (s->gi.number_entry == 0)
1692 return UNZ_END_OF_LIST_OF_FILE;
1694 s->pos_in_central_dir = s->offset_central_dir;
1697 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal,
1698 filename, filename_size, extrafield, extrafield_size, comment,comment_size);
1700 s->current_file_ok = (err == UNZ_OK);
1701 if ((err == UNZ_OK) && (pfile_info != NULL))
1702 memcpy(pfile_info, &s->cur_file_info, sizeof(unz_file_info64));
1707 extern int ZEXPORT unzGoToFirstFile(unzFile file)
1709 return unzGoToFirstFile2(file, NULL, NULL, 0, NULL, 0, NULL, 0);
1712 extern int ZEXPORT unzGoToNextFile2(unzFile file, unz_file_info64 *pfile_info, char *filename,
1713 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
1715 unz64_internal *s = NULL;
1719 return UNZ_PARAMERROR;
1720 s = (unz64_internal*)file;
1722 if (!s->current_file_ok)
1723 return UNZ_END_OF_LIST_OF_FILE;
1724 if (s->gi.number_entry != UINT16_MAX) /* 2^16 files overflow hack */
1726 if (s->num_file+1 == s->gi.number_entry)
1727 return UNZ_END_OF_LIST_OF_FILE;
1730 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
1731 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment;
1734 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal,
1735 filename, filename_size, extrafield,extrafield_size, comment, comment_size);
1737 s->current_file_ok = (err == UNZ_OK);
1738 if ((err == UNZ_OK) && (pfile_info != NULL))
1739 memcpy(pfile_info, &s->cur_file_info, sizeof(unz_file_info64));
1744 extern int ZEXPORT unzGoToNextFile(unzFile file)
1746 return unzGoToNextFile2(file, NULL, NULL, 0, NULL, 0, NULL, 0);
1749 extern int ZEXPORT unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filename_compare_func)
1751 unz64_internal *s = NULL;
1752 unz_file_info64 cur_file_info_saved;
1753 unz_file_info64_internal cur_file_info_internal_saved;
1754 uint64_t num_file_saved = 0;
1755 uint64_t pos_in_central_dir_saved = 0;
1756 char current_filename[UNZ_MAXFILENAMEINZIP+1];
1760 return UNZ_PARAMERROR;
1761 if (strlen(filename) >= UNZ_MAXFILENAMEINZIP)
1762 return UNZ_PARAMERROR;
1763 s = (unz64_internal*)file;
1764 if (!s->current_file_ok)
1765 return UNZ_END_OF_LIST_OF_FILE;
1767 /* Save the current state */
1768 num_file_saved = s->num_file;
1769 pos_in_central_dir_saved = s->pos_in_central_dir;
1770 cur_file_info_saved = s->cur_file_info;
1771 cur_file_info_internal_saved = s->cur_file_info_internal;
1773 err = unzGoToFirstFile2(file, NULL, current_filename, sizeof(current_filename)-1, NULL, 0, NULL, 0);
1775 while (err == UNZ_OK)
1777 if (filename_compare_func != NULL)
1778 err = filename_compare_func(file, current_filename, filename);
1780 err = strcmp(current_filename, filename);
1783 err = unzGoToNextFile2(file, NULL, current_filename, sizeof(current_filename)-1, NULL, 0, NULL, 0);
1786 /* We failed, so restore the state of the 'current file' to where we were. */
1787 s->num_file = num_file_saved;
1788 s->pos_in_central_dir = pos_in_central_dir_saved;
1789 s->cur_file_info = cur_file_info_saved;
1790 s->cur_file_info_internal = cur_file_info_internal_saved;
1794 extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos *file_pos)
1796 unz64_file_pos file_pos64;
1797 int err = unzGetFilePos64(file, &file_pos64);
1800 file_pos->pos_in_zip_directory = (uint32_t)file_pos64.pos_in_zip_directory;
1801 file_pos->num_of_file = (uint32_t)file_pos64.num_of_file;
1806 extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos *file_pos)
1808 unz64_file_pos file_pos64;
1809 if (file_pos == NULL)
1810 return UNZ_PARAMERROR;
1811 file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
1812 file_pos64.num_of_file = file_pos->num_of_file;
1813 return unzGoToFilePos64(file, &file_pos64);
1816 extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos *file_pos)
1818 unz64_internal *s = NULL;
1820 if (file == NULL || file_pos == NULL)
1821 return UNZ_PARAMERROR;
1822 s = (unz64_internal*)file;
1823 if (!s->current_file_ok)
1824 return UNZ_END_OF_LIST_OF_FILE;
1826 file_pos->pos_in_zip_directory = s->pos_in_central_dir;
1827 file_pos->num_of_file = s->num_file;
1831 extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos *file_pos)
1833 unz64_internal *s = NULL;
1836 if (file == NULL || file_pos == NULL)
1837 return UNZ_PARAMERROR;
1838 s = (unz64_internal*)file;
1840 /* Jump to the right spot */
1841 s->pos_in_central_dir = file_pos->pos_in_zip_directory;
1842 s->num_file = file_pos->num_of_file;
1844 /* Set the current file */
1845 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0);
1846 /* Return results */
1847 s->current_file_ok = (err == UNZ_OK);
1851 extern int32_t ZEXPORT unzGetOffset(unzFile file)
1853 uint64_t offset64 = 0;
1856 return UNZ_PARAMERROR;
1857 offset64 = unzGetOffset64(file);
1858 return (int32_t)offset64;
1861 extern int64_t ZEXPORT unzGetOffset64(unzFile file)
1863 unz64_internal *s = NULL;
1866 return UNZ_PARAMERROR;
1867 s = (unz64_internal*)file;
1868 if (!s->current_file_ok)
1870 if (s->gi.number_entry != 0 && s->gi.number_entry != UINT16_MAX)
1872 if (s->num_file == s->gi.number_entry)
1875 return s->pos_in_central_dir;
1878 extern int ZEXPORT unzSetOffset(unzFile file, uint32_t pos)
1880 return unzSetOffset64(file, pos);
1883 extern int ZEXPORT unzSetOffset64(unzFile file, uint64_t pos)
1885 unz64_internal *s = NULL;
1889 return UNZ_PARAMERROR;
1890 s = (unz64_internal*)file;
1891 s->pos_in_central_dir = pos;
1892 s->num_file = s->gi.number_entry; /* hack */
1894 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0);
1896 s->current_file_ok = (err == UNZ_OK);
1900 extern int32_t ZEXPORT unzTell(unzFile file)
1902 unz64_internal *s = NULL;
1904 return UNZ_PARAMERROR;
1905 s = (unz64_internal*)file;
1906 if (s->pfile_in_zip_read == NULL)
1907 return UNZ_PARAMERROR;
1908 return (int32_t)s->pfile_in_zip_read->stream.total_out;
1911 extern int64_t ZEXPORT unzTell64(unzFile file)
1913 unz64_internal *s = NULL;
1915 return UNZ_PARAMERROR;
1916 s = (unz64_internal*)file;
1917 if (s->pfile_in_zip_read == NULL)
1918 return UNZ_PARAMERROR;
1919 return s->pfile_in_zip_read->total_out_64;
1922 extern int ZEXPORT unzSeek(unzFile file, uint32_t offset, int origin)
1924 return unzSeek64(file, offset, origin);
1927 extern int ZEXPORT unzSeek64(unzFile file, uint64_t offset, int origin)
1929 unz64_internal *s = NULL;
1930 uint64_t stream_pos_begin = 0;
1931 uint64_t stream_pos_end = 0;
1932 uint64_t position = 0;
1933 int is_within_buffer = 0;
1936 return UNZ_PARAMERROR;
1937 s = (unz64_internal*)file;
1939 if (s->pfile_in_zip_read == NULL)
1941 if (s->pfile_in_zip_read->compression_method != 0)
1944 if (origin == SEEK_SET)
1946 else if (origin == SEEK_CUR)
1947 position = s->pfile_in_zip_read->total_out_64 + offset;
1948 else if (origin == SEEK_END)
1949 position = s->cur_file_info.compressed_size + offset;
1951 return UNZ_PARAMERROR;
1953 if (position > s->cur_file_info.compressed_size)
1954 return UNZ_PARAMERROR;
1956 stream_pos_end = s->pfile_in_zip_read->pos_in_zipfile;
1957 stream_pos_begin = stream_pos_end;
1959 if (stream_pos_begin > UNZ_BUFSIZE)
1960 stream_pos_begin -= UNZ_BUFSIZE;
1962 stream_pos_begin = 0;
1965 (s->pfile_in_zip_read->stream.avail_in != 0) &&
1966 (s->pfile_in_zip_read->rest_read_compressed != 0 || s->cur_file_info.compressed_size < UNZ_BUFSIZE) &&
1967 (position >= stream_pos_begin && position < stream_pos_end);
1969 if (is_within_buffer)
1971 s->pfile_in_zip_read->stream.next_in += position - s->pfile_in_zip_read->total_out_64;
1972 s->pfile_in_zip_read->stream.avail_in = (uInt)(stream_pos_end - position);
1976 s->pfile_in_zip_read->stream.avail_in = 0;
1977 s->pfile_in_zip_read->stream.next_in = 0;
1979 s->pfile_in_zip_read->pos_in_zipfile = s->pfile_in_zip_read->offset_local_extrafield + position;
1980 s->pfile_in_zip_read->rest_read_compressed = s->cur_file_info.compressed_size - position;
1983 s->pfile_in_zip_read->rest_read_uncompressed -= (position - s->pfile_in_zip_read->total_out_64);
1984 s->pfile_in_zip_read->stream.total_out = (uint32_t)position;
1985 s->pfile_in_zip_read->total_out_64 = position;
1990 extern int ZEXPORT unzEndOfFile(unzFile file)
1992 unz64_internal *s = NULL;
1994 return UNZ_PARAMERROR;
1995 s = (unz64_internal*)file;
1996 if (s->pfile_in_zip_read == NULL)
1997 return UNZ_PARAMERROR;
1998 if (s->pfile_in_zip_read->rest_read_uncompressed == 0)