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