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