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