Stroika Library 3.0d20
 
Loading...
Searching...
No Matches
Private_minizip_.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
6#if qStroika_HasComponent_zlib
7#include <zlib.h>
8#endif
9
10#ifdef HAVE_BZIP2
11#include "bzlib.h"
12#endif
13
16#include "Stroika/Foundation/Streams/MemoryStream.h"
17
18#include "Private_minizip_.h"
19
20#if qStroika_HasComponent_zlib
21using namespace Stroika::Foundation::DataExchange::Archive::Zip;
22using namespace Stroika::Foundation::DataExchange::Archive::Zip::PrivateMinizip_;
23
24///// START OF IOAPI.c //////////////////
25/* ioapi.h -- IO base function header for compress/uncompress .zip
26 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
27
28 Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
29
30 Modifications for Zip64 support
31 Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
32
33 For more info read MiniZip_info.txt
34
35*/
36
37voidpf PrivateMinizip_::call_zopen64 (const zlib_filefunc64_32_def* pfilefunc, const void* filename, int mode)
38{
39 if (pfilefunc->zfile_func64.zopen64_file != NULL)
40 return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque, filename, mode);
41 else {
42 return (*(pfilefunc->zopen32_file)) (pfilefunc->zfile_func64.opaque, (const char*)filename, mode);
43 }
44}
45long PrivateMinizip_::call_zseek64 (const zlib_filefunc64_32_def* pfilefunc, voidpf filestream, ZPOS64_T offset, int origin)
46{
47 if (pfilefunc->zfile_func64.zseek64_file != NULL)
48 return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque, filestream, offset, origin);
49 else {
50 uLong offsetTruncated = (uLong)offset;
51 if (offsetTruncated != offset)
52 return -1;
53 else
54 return (*(pfilefunc->zseek32_file)) (pfilefunc->zfile_func64.opaque, filestream, offsetTruncated, origin);
55 }
56}
57ZPOS64_T PrivateMinizip_::call_ztell64 (const zlib_filefunc64_32_def* pfilefunc, voidpf filestream)
58{
59 if (pfilefunc->zfile_func64.zseek64_file != NULL)
60 return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque, filestream);
61 else {
62 uLong tell_uLong = (*(pfilefunc->ztell32_file)) (pfilefunc->zfile_func64.opaque, filestream);
63 if ((tell_uLong) == numeric_limits<uLong>::max ())
64 return (ZPOS64_T)-1;
65 else
66 return tell_uLong;
67 }
68}
69void PrivateMinizip_::fill_zlib_filefunc64_32_def_from_filefunc32 (zlib_filefunc64_32_def* p_filefunc64_32, const zlib_filefunc_def* p_filefunc32)
70{
71 p_filefunc64_32->zfile_func64.zopen64_file = NULL;
72 p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
73 p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
74 p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
75 p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
76 p_filefunc64_32->zfile_func64.ztell64_file = NULL;
77 p_filefunc64_32->zfile_func64.zseek64_file = NULL;
78 p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
79 p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
80 p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
81 p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
82 p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
83}
84///////////////////////////////////////////////// end of IOAPI.c /////////////////////
85
86///////////////////////////////// START OF unzip.c ////////////////////
87namespace {
88
89#ifndef NOUNCRYPT
90#define NOUNCRYPT
91#endif
92
93#ifndef CASESENSITIVITYDEFAULT_NO
94#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
95#define CASESENSITIVITYDEFAULT_NO
96#endif
97#endif
98
99#ifndef UNZ_BUFSIZE
100#define UNZ_BUFSIZE (16384)
101#endif
102
103#ifndef UNZ_MAXFILENAMEINZIP
104#define UNZ_MAXFILENAMEINZIP (256)
105#endif
106
107#ifndef ALLOC
108#define ALLOC(size) (malloc (size))
109#endif
110#ifndef TRYFREE
111#define TRYFREE(p) \
112 { \
113 if (p) \
114 free (p); \
115 }
116#endif
117
118#define SIZECENTRALDIRITEM (0x2e)
119#define SIZEZIPLOCALHEADER (0x1e)
120
121 // const char unz_copyright[] = " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
122
123 /* unz_file_info_interntal contain internal info about a file in zipfile*/
124 typedef struct unz_file_info64_internal_s {
125 ZPOS64_T offset_curfile; /* relative offset of local header 8 bytes */
126 } unz_file_info64_internal;
127
128 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
129 when reading and decompress it */
130 typedef struct {
131 char* read_buffer; /* internal buffer for compressed data */
132 z_stream stream; /* zLib stream structure for inflate */
133
134#ifdef HAVE_BZIP2
135 bz_stream bstream; /* bzLib stream structure for bziped */
136#endif
137
138 ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
139 uLong stream_initialised; /* flag set if stream structure is initialised*/
140
141 ZPOS64_T offset_local_extrafield; /* offset of the local extra field */
142 uInt size_local_extrafield; /* size of the local extra field */
143 ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/
144 ZPOS64_T total_out_64;
145
146 uLong crc32; /* crc32 of all data uncompressed */
147 uLong crc32_wait; /* crc32 we must obtain after decompress all */
148 ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
149 ZPOS64_T rest_read_uncompressed; /*number of byte to be obtained after decomp*/
150 zlib_filefunc64_32_def z_filefunc;
151 voidpf filestream; /* io structore of the zipfile */
152 uLong compression_method; /* compression method (0==store) */
153 ZPOS64_T byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/
154 int raw;
155 } file_in_zip64_read_info_s;
156
157 /* unz64_s contain internal information about the zipfile
158 */
159 struct unz64_s {
160 zlib_filefunc64_32_def z_filefunc;
161 int is64bitOpenFunction;
162 voidpf filestream; /* io structore of the zipfile */
163 unz_global_info64 gi; /* public global information */
164 ZPOS64_T byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/
165 ZPOS64_T num_file; /* number of the current file in the zipfile*/
166 ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/
167 ZPOS64_T current_file_ok; /* flag about the usability of the current file*/
168 ZPOS64_T central_pos; /* position of the beginning of the central dir*/
169
170 ZPOS64_T size_central_dir; /* size of the central directory */
171 ZPOS64_T offset_central_dir; /* offset of start of central directory with
172 respect to the starting disk number */
173
174 unz_file_info64 cur_file_info; /* public info about the current file in zip*/
175 unz_file_info64_internal cur_file_info_internal; /* private info about it*/
176 file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
177 file if we are decompressing it */
178 int encrypted;
179
180 int isZip64;
181
182#ifndef NOUNCRYPT
183 unsigned long keys[3]; /* keys defining the pseudo-random sequence */
184 const z_crc_t* pcrc_32_tab;
185#endif
186 };
187
188 /* ===========================================================================
189 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
190 for end of file.
191 IN assertion: the stream s has been sucessfully opened for reading.
192 */
193 int unz64local_getByte (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi)
194 {
195 unsigned char c;
196 int err = (int)ZREAD64 (*pzlib_filefunc_def, filestream, &c, 1);
197 if (err == 1) {
198 *pi = (int)c;
199 return UNZ_OK;
200 }
201 else {
202 if (ZERROR64 (*pzlib_filefunc_def, filestream))
203 return UNZ_ERRNO;
204 else
205 return UNZ_EOF;
206 }
207 }
208
209 /* ===========================================================================
210 Reads a long in LSB order from the given gz_stream. Sets
211 */
212 int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
213 {
214 uLong x;
215 int i = 0;
216 int err;
217
218 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
219 x = (uLong)i;
220
221 if (err == UNZ_OK)
222 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
223 x |= ((uLong)i) << 8;
224
225 if (err == UNZ_OK)
226 *pX = x;
227 else
228 *pX = 0;
229 return err;
230 }
231
232 int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
233 {
234 uLong x;
235 int i = 0;
236 int err;
237
238 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
239 x = (uLong)i;
240
241 if (err == UNZ_OK)
242 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
243 x |= ((uLong)i) << 8;
244
245 if (err == UNZ_OK)
246 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
247 x |= ((uLong)i) << 16;
248
249 if (err == UNZ_OK)
250 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
251 x += ((uLong)i) << 24;
252
253 if (err == UNZ_OK)
254 *pX = x;
255 else
256 *pX = 0;
257 return err;
258 }
259
260 int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T* pX)
261 {
262 ZPOS64_T x;
263 int i = 0;
264 int err;
265
266 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
267 x = (ZPOS64_T)i;
268
269 if (err == UNZ_OK)
270 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
271 x |= ((ZPOS64_T)i) << 8;
272
273 if (err == UNZ_OK)
274 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
275 x |= ((ZPOS64_T)i) << 16;
276
277 if (err == UNZ_OK)
278 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
279 x |= ((ZPOS64_T)i) << 24;
280
281 if (err == UNZ_OK)
282 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
283 x |= ((ZPOS64_T)i) << 32;
284
285 if (err == UNZ_OK)
286 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
287 x |= ((ZPOS64_T)i) << 40;
288
289 if (err == UNZ_OK)
290 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
291 x |= ((ZPOS64_T)i) << 48;
292
293 if (err == UNZ_OK)
294 err = unz64local_getByte (pzlib_filefunc_def, filestream, &i);
295 x |= ((ZPOS64_T)i) << 56;
296
297 if (err == UNZ_OK)
298 *pX = x;
299 else
300 *pX = 0;
301 return err;
302 }
303
304 /* My own strcmpi / strcasecmp */
305 int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
306 {
307 for (;;) {
308 char c1 = *(fileName1++);
309 char c2 = *(fileName2++);
310 if ((c1 >= 'a') and (c1 <= 'z'))
311 c1 -= 0x20;
312 if ((c2 >= 'a') and (c2 <= 'z'))
313 c2 -= 0x20;
314 if (c1 == '\0')
315 return ((c2 == '\0') ? 0 : -1);
316 if (c2 == '\0')
317 return 1;
318 if (c1 < c2)
319 return -1;
320 if (c1 > c2)
321 return 1;
322 }
323 }
324
325#ifdef CASESENSITIVITYDEFAULT_NO
326#define CASESENSITIVITYDEFAULTVALUE 2
327#else
328#define CASESENSITIVITYDEFAULTVALUE 1
329#endif
330
331#ifndef STRCMPCASENOSENTIVEFUNCTION
332#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
333#endif
334
335}
336/*
337 Compare two filename (fileName1,fileName2).
338 If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
339 If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
340 or strcasecmp)
341 If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
342 (like 1 on Unix, 2 on Windows)
343
344 */
345int PrivateMinizip_::unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity)
346{
347 if (iCaseSensitivity == 0)
348 iCaseSensitivity = CASESENSITIVITYDEFAULTVALUE;
349
350 if (iCaseSensitivity == 1)
351 return strcmp (fileName1, fileName2);
352
353 return STRCMPCASENOSENTIVEFUNCTION (fileName1, fileName2);
354}
355
356namespace {
357
358 constexpr size_t BUFREADCOMMENT = 0x400;
359
360 /*
361 Locate the Central directory of a zipfile (at the end, just before
362 the global comment)
363 */
364 ZPOS64_T unz64local_SearchCentralDir (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
365 {
366 ZPOS64_T uPosFound = 0;
367
368 if (ZSEEK64 (*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
369 return 0;
370
371 ZPOS64_T uSizeFile = ZTELL64 (*pzlib_filefunc_def, filestream);
372
373 ZPOS64_T uMaxBack = 0xffff; /* maximum size of global comment */
374 if (uMaxBack > uSizeFile)
375 uMaxBack = uSizeFile;
376
377 unsigned char* buf = (unsigned char*)ALLOC (BUFREADCOMMENT + 4);
378 if (buf == NULL)
379 return 0;
380
381 ZPOS64_T uBackRead = 4;
382 while (uBackRead < uMaxBack) {
383 uLong uReadSize;
384 ZPOS64_T uReadPos;
385 int i;
386 if (uBackRead + BUFREADCOMMENT > uMaxBack)
387 uBackRead = uMaxBack;
388 else
389 uBackRead += BUFREADCOMMENT;
390 uReadPos = uSizeFile - uBackRead;
391
392 uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ? (BUFREADCOMMENT + 4) : (uLong)(uSizeFile - uReadPos);
393 if (ZSEEK64 (*pzlib_filefunc_def, filestream, uReadPos, ZLIB_FILEFUNC_SEEK_SET) != 0)
394 break;
395
396 if (ZREAD64 (*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize)
397 break;
398
399 for (i = (int)uReadSize - 3; i-- > 0;)
400 if (((*(buf + i)) == 0x50) and ((*(buf + i + 1)) == 0x4b) && ((*(buf + i + 2)) == 0x05) and ((*(buf + i + 3)) == 0x06)) {
401 uPosFound = uReadPos + i;
402 break;
403 }
404
405 if (uPosFound != 0)
406 break;
407 }
408 TRYFREE (buf);
409 return uPosFound;
410 }
411
412 /*
413 Locate the Central directory 64 of a zipfile (at the end, just before
414 the global comment)
415 */
416 ZPOS64_T unz64local_SearchCentralDir64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
417 {
418 unsigned char* buf;
419 ZPOS64_T uSizeFile;
420 ZPOS64_T uBackRead;
421 ZPOS64_T uMaxBack = 0xffff; /* maximum size of global comment */
422 ZPOS64_T uPosFound = 0;
423 uLong uL;
424 ZPOS64_T relativeOffset;
425
426 if (ZSEEK64 (*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
427 return 0;
428
429 uSizeFile = ZTELL64 (*pzlib_filefunc_def, filestream);
430
431 if (uMaxBack > uSizeFile)
432 uMaxBack = uSizeFile;
433
434 buf = (unsigned char*)ALLOC (BUFREADCOMMENT + 4);
435 if (buf == NULL)
436 return 0;
437
438 uBackRead = 4;
439 while (uBackRead < uMaxBack) {
440 uLong uReadSize;
441 ZPOS64_T uReadPos;
442 int i;
443 if (uBackRead + BUFREADCOMMENT > uMaxBack)
444 uBackRead = uMaxBack;
445 else
446 uBackRead += BUFREADCOMMENT;
447 uReadPos = uSizeFile - uBackRead;
448
449 uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ? (BUFREADCOMMENT + 4) : (uLong)(uSizeFile - uReadPos);
450 if (ZSEEK64 (*pzlib_filefunc_def, filestream, uReadPos, ZLIB_FILEFUNC_SEEK_SET) != 0)
451 break;
452
453 if (ZREAD64 (*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize)
454 break;
455
456 for (i = (int)uReadSize - 3; i-- > 0;)
457 if (((*(buf + i)) == 0x50) and ((*(buf + i + 1)) == 0x4b) && ((*(buf + i + 2)) == 0x06) and ((*(buf + i + 3)) == 0x07)) {
458 uPosFound = uReadPos + i;
459 break;
460 }
461
462 if (uPosFound != 0)
463 break;
464 }
465 TRYFREE (buf);
466 if (uPosFound == 0)
467 return 0;
468
469 /* Zip64 end of central directory locator */
470 if (ZSEEK64 (*pzlib_filefunc_def, filestream, uPosFound, ZLIB_FILEFUNC_SEEK_SET) != 0)
471 return 0;
472
473 /* the signature, already checked */
474 if (unz64local_getLong (pzlib_filefunc_def, filestream, &uL) != UNZ_OK)
475 return 0;
476
477 /* number of the disk with the start of the zip64 end of central directory */
478 if (unz64local_getLong (pzlib_filefunc_def, filestream, &uL) != UNZ_OK)
479 return 0;
480 if (uL != 0)
481 return 0;
482
483 /* relative offset of the zip64 end of central directory record */
484 if (unz64local_getLong64 (pzlib_filefunc_def, filestream, &relativeOffset) != UNZ_OK)
485 return 0;
486
487 /* total number of disks */
488 if (unz64local_getLong (pzlib_filefunc_def, filestream, &uL) != UNZ_OK)
489 return 0;
490 if (uL != 1)
491 return 0;
492
493 /* Goto end of central directory record */
494 if (ZSEEK64 (*pzlib_filefunc_def, filestream, relativeOffset, ZLIB_FILEFUNC_SEEK_SET) != 0)
495 return 0;
496
497 /* the signature */
498 if (unz64local_getLong (pzlib_filefunc_def, filestream, &uL) != UNZ_OK)
499 return 0;
500
501 if (uL != 0x06064b50)
502 return 0;
503
504 return relativeOffset;
505 }
506
507 /*
508 Open a Zip file. path contain the full pathname (by example,
509 on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
510 "zlib/zlib114.zip".
511 If the zipfile cannot be opened (file doesn't exist or in not valid), the
512 return value is NULL.
513 Else, the return value is a unzFile Handle, usable with other function
514 of this unzip package.
515 */
516 unzFile unzOpenInternal (const void* path, zlib_filefunc64_32_def* pzlib_filefunc64_32_def, int is64bitOpenFunction)
517 {
518 unz64_s us;
519 unz64_s* s;
520 ZPOS64_T central_pos;
521 uLong uL;
522
523 uLong number_disk; /* number of the current dist, used for
524 spaning ZIP, unsupported, always 0*/
525 uLong number_disk_with_CD; /* number the the disk with central dir, used
526 for spaning ZIP, unsupported, always 0*/
527 ZPOS64_T number_entry_CD; /* total number of entries in
528 the central dir
529 (same than number_entry on nospan) */
530
531 int err = UNZ_OK;
532
533 us.z_filefunc.zseek32_file = NULL;
534 us.z_filefunc.ztell32_file = NULL;
535
536 AssertNotNull (pzlib_filefunc64_32_def);
537 us.z_filefunc = *pzlib_filefunc64_32_def;
538 us.is64bitOpenFunction = is64bitOpenFunction;
539
540 us.filestream = ZOPEN64 (us.z_filefunc, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
541 if (us.filestream == NULL)
542 return NULL;
543
544 central_pos = unz64local_SearchCentralDir64 (&us.z_filefunc, us.filestream);
545 if (central_pos) {
546 uLong uS;
547 ZPOS64_T uL64;
548
549 us.isZip64 = 1;
550
551 if (ZSEEK64 (us.z_filefunc, us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
552 err = UNZ_ERRNO;
553
554 /* the signature, already checked */
555 if (unz64local_getLong (&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
556 err = UNZ_ERRNO;
557
558 /* size of zip64 end of central directory record */
559 if (unz64local_getLong64 (&us.z_filefunc, us.filestream, &uL64) != UNZ_OK)
560 err = UNZ_ERRNO;
561
562 /* version made by */
563 if (unz64local_getShort (&us.z_filefunc, us.filestream, &uS) != UNZ_OK)
564 err = UNZ_ERRNO;
565
566 /* version needed to extract */
567 if (unz64local_getShort (&us.z_filefunc, us.filestream, &uS) != UNZ_OK)
568 err = UNZ_ERRNO;
569
570 /* number of this disk */
571 if (unz64local_getLong (&us.z_filefunc, us.filestream, &number_disk) != UNZ_OK)
572 err = UNZ_ERRNO;
573
574 /* number of the disk with the start of the central directory */
575 if (unz64local_getLong (&us.z_filefunc, us.filestream, &number_disk_with_CD) != UNZ_OK)
576 err = UNZ_ERRNO;
577
578 /* total number of entries in the central directory on this disk */
579 if (unz64local_getLong64 (&us.z_filefunc, us.filestream, &us.gi.number_entry) != UNZ_OK)
580 err = UNZ_ERRNO;
581
582 /* total number of entries in the central directory */
583 if (unz64local_getLong64 (&us.z_filefunc, us.filestream, &number_entry_CD) != UNZ_OK)
584 err = UNZ_ERRNO;
585
586 if ((number_entry_CD != us.gi.number_entry) or (number_disk_with_CD != 0) or (number_disk != 0))
587 err = UNZ_BADZIPFILE;
588
589 /* size of the central directory */
590 if (unz64local_getLong64 (&us.z_filefunc, us.filestream, &us.size_central_dir) != UNZ_OK)
591 err = UNZ_ERRNO;
592
593 /* offset of start of central directory with respect to the
594 starting disk number */
595 if (unz64local_getLong64 (&us.z_filefunc, us.filestream, &us.offset_central_dir) != UNZ_OK)
596 err = UNZ_ERRNO;
597
598 us.gi.size_comment = 0;
599 }
600 else {
601 central_pos = unz64local_SearchCentralDir (&us.z_filefunc, us.filestream);
602 if (central_pos == 0)
603 err = UNZ_ERRNO;
604
605 us.isZip64 = 0;
606
607 if (ZSEEK64 (us.z_filefunc, us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
608 err = UNZ_ERRNO;
609
610 /* the signature, already checked */
611 if (unz64local_getLong (&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
612 err = UNZ_ERRNO;
613
614 /* number of this disk */
615 if (unz64local_getShort (&us.z_filefunc, us.filestream, &number_disk) != UNZ_OK)
616 err = UNZ_ERRNO;
617
618 /* number of the disk with the start of the central directory */
619 if (unz64local_getShort (&us.z_filefunc, us.filestream, &number_disk_with_CD) != UNZ_OK)
620 err = UNZ_ERRNO;
621
622 /* total number of entries in the central dir on this disk */
623 if (unz64local_getShort (&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
624 err = UNZ_ERRNO;
625 us.gi.number_entry = uL;
626
627 /* total number of entries in the central dir */
628 if (unz64local_getShort (&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
629 err = UNZ_ERRNO;
630 number_entry_CD = uL;
631
632 if ((number_entry_CD != us.gi.number_entry) || (number_disk_with_CD != 0) || (number_disk != 0))
633 err = UNZ_BADZIPFILE;
634
635 /* size of the central directory */
636 if (unz64local_getLong (&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
637 err = UNZ_ERRNO;
638 us.size_central_dir = uL;
639
640 /* offset of start of central directory with respect to the
641 starting disk number */
642 if (unz64local_getLong (&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
643 err = UNZ_ERRNO;
644 us.offset_central_dir = uL;
645
646 /* zipfile comment length */
647 if (unz64local_getShort (&us.z_filefunc, us.filestream, &us.gi.size_comment) != UNZ_OK)
648 err = UNZ_ERRNO;
649 }
650
651 if ((central_pos < us.offset_central_dir + us.size_central_dir) && (err == UNZ_OK))
652 err = UNZ_BADZIPFILE;
653
654 if (err != UNZ_OK) {
655 ZCLOSE64 (us.z_filefunc, us.filestream);
656 return NULL;
657 }
658
659 us.byte_before_the_zipfile = central_pos - (us.offset_central_dir + us.size_central_dir);
660 us.central_pos = central_pos;
661 us.pfile_in_zip_read = NULL;
662 us.encrypted = 0;
663
664 s = (unz64_s*)ALLOC (sizeof (unz64_s));
665 if (s != NULL) {
666 *s = us;
667 unzGoToFirstFile ((unzFile)s);
668 }
669 return (unzFile)s;
670 }
671
672 unzFile unzOpen2 (const char* path, zlib_filefunc_def* pzlib_filefunc32_def)
673 {
674 if (pzlib_filefunc32_def != NULL) {
675 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
676 fill_zlib_filefunc64_32_def_from_filefunc32 (&zlib_filefunc64_32_def_fill, pzlib_filefunc32_def);
677 return unzOpenInternal (path, &zlib_filefunc64_32_def_fill, 0);
678 }
679 else
680 return unzOpenInternal (path, NULL, 0);
681 }
682}
683
684unzFile PrivateMinizip_::unzOpen2_64 (const void* path, zlib_filefunc64_def* pzlib_filefunc_def)
685{
686 if (pzlib_filefunc_def != NULL) {
687 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
688 zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
689 zlib_filefunc64_32_def_fill.ztell32_file = NULL;
690 zlib_filefunc64_32_def_fill.zseek32_file = NULL;
691 return unzOpenInternal (path, &zlib_filefunc64_32_def_fill, 1);
692 }
693 else
694 return unzOpenInternal (path, NULL, 1);
695}
696
697unzFile PrivateMinizip_::unzOpen (const char* path)
698{
699 return unzOpenInternal (path, NULL, 0);
700}
701
702unzFile PrivateMinizip_::unzOpen64 (const void* path)
703{
704 return unzOpenInternal (path, NULL, 1);
705}
706
707/*
708 Close a ZipFile opened with unzOpen.
709 If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
710 these files MUST be closed with unzCloseCurrentFile_ before call unzClose.
711 return UNZ_OK if there is no problem. */
712int PrivateMinizip_::unzClose (unzFile file)
713{
714 unz64_s* s;
715 if (file == NULL)
716 return UNZ_PARAMERROR;
717 s = (unz64_s*)file;
718
719 if (s->pfile_in_zip_read != NULL)
720 unzCloseCurrentFile_ (file);
721
722 ZCLOSE64 (s->z_filefunc, s->filestream);
723 TRYFREE (s);
724 return UNZ_OK;
725}
726
727/*
728 Write info about the ZipFile in the *pglobal_info structure.
729 No preparation of the structure is needed
730 return UNZ_OK if there is no problem. */
731int PrivateMinizip_::unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info)
732{
733 unz64_s* s;
734 if (file == NULL)
735 return UNZ_PARAMERROR;
736 s = (unz64_s*)file;
737 *pglobal_info = s->gi;
738 return UNZ_OK;
739}
740
741int PrivateMinizip_::unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32)
742{
743 unz64_s* s;
744 if (file == NULL)
745 return UNZ_PARAMERROR;
746 s = (unz64_s*)file;
747 /* to do : check if number_entry is not truncated */
748 pglobal_info32->number_entry = (uLong)s->gi.number_entry;
749 pglobal_info32->size_comment = s->gi.size_comment;
750 return UNZ_OK;
751}
752
753namespace {
754 /*
755 Translate date/time from Dos format to tm_unz (readable more easilty)
756 */
757 void unz64local_DosDateToTmuDate_ (ZPOS64_T ulDosDate, tm_unz* ptm)
758 {
759 ZPOS64_T uDate;
760 uDate = (ZPOS64_T)(ulDosDate >> 16);
761 ptm->tm_mday = (uInt)(uDate & 0x1f);
762 ptm->tm_mon = (uInt)((((uDate) & 0x1E0) / 0x20) - 1);
763 ptm->tm_year = (uInt)(((uDate & 0x0FE00) / 0x0200) + 1980);
764
765 ptm->tm_hour = (uInt)((ulDosDate & 0xF800) / 0x800);
766 ptm->tm_min = (uInt)((ulDosDate & 0x7E0) / 0x20);
767 ptm->tm_sec = (uInt)(2 * (ulDosDate & 0x1f));
768 }
769
770 /*
771 Get Info about the current file in the zipfile, with internal only info
772 */
773 int unz64local_GetCurrentFileInfoInternal_ (unzFile file, unz_file_info64* pfile_info, unz_file_info64_internal* pfile_info_internal,
774 char* szFileName, uLong fileNameBufferSize, void* extraField, uLong extraFieldBufferSize,
775 char* szComment, uLong commentBufferSize)
776 {
777 unz64_s* s;
778 unz_file_info64 file_info;
779 unz_file_info64_internal file_info_internal;
780 int err = UNZ_OK;
781 uLong uMagic;
782 long lSeek = 0;
783
784 if (file == NULL)
785 return UNZ_PARAMERROR;
786 s = (unz64_s*)file;
787 if (ZSEEK64 (s->z_filefunc, s->filestream, s->pos_in_central_dir + s->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
788 err = UNZ_ERRNO;
789
790 /* we check the magic */
791 if (err == UNZ_OK) {
792 if (unz64local_getLong (&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK)
793 err = UNZ_ERRNO;
794 else if (uMagic != 0x02014b50)
795 err = UNZ_BADZIPFILE;
796 }
797
798 if (unz64local_getShort (&s->z_filefunc, s->filestream, &file_info.version) != UNZ_OK)
799 err = UNZ_ERRNO;
800
801 if (unz64local_getShort (&s->z_filefunc, s->filestream, &file_info.version_needed) != UNZ_OK)
802 err = UNZ_ERRNO;
803
804 if (unz64local_getShort (&s->z_filefunc, s->filestream, &file_info.flag) != UNZ_OK)
805 err = UNZ_ERRNO;
806
807 if (unz64local_getShort (&s->z_filefunc, s->filestream, &file_info.compression_method) != UNZ_OK)
808 err = UNZ_ERRNO;
809
810 if (unz64local_getLong (&s->z_filefunc, s->filestream, &file_info.dosDate) != UNZ_OK)
811 err = UNZ_ERRNO;
812
813 unz64local_DosDateToTmuDate_ (file_info.dosDate, &file_info.tmu_date);
814
815 if (unz64local_getLong (&s->z_filefunc, s->filestream, &file_info.crc) != UNZ_OK)
816 err = UNZ_ERRNO;
817
818 {
819 uLong uL;
820 if (unz64local_getLong (&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
821 err = UNZ_ERRNO;
822 file_info.compressed_size = uL;
823 }
824
825 {
826 uLong uL;
827 if (unz64local_getLong (&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
828 err = UNZ_ERRNO;
829 file_info.uncompressed_size = uL;
830 }
831
832 if (unz64local_getShort (&s->z_filefunc, s->filestream, &file_info.size_filename) != UNZ_OK)
833 err = UNZ_ERRNO;
834
835 if (unz64local_getShort (&s->z_filefunc, s->filestream, &file_info.size_file_extra) != UNZ_OK)
836 err = UNZ_ERRNO;
837
838 if (unz64local_getShort (&s->z_filefunc, s->filestream, &file_info.size_file_comment) != UNZ_OK)
839 err = UNZ_ERRNO;
840
841 if (unz64local_getShort (&s->z_filefunc, s->filestream, &file_info.disk_num_start) != UNZ_OK)
842 err = UNZ_ERRNO;
843
844 if (unz64local_getShort (&s->z_filefunc, s->filestream, &file_info.internal_fa) != UNZ_OK)
845 err = UNZ_ERRNO;
846
847 if (unz64local_getLong (&s->z_filefunc, s->filestream, &file_info.external_fa) != UNZ_OK)
848 err = UNZ_ERRNO;
849
850 // relative offset of local header
851 {
852 uLong uL;
853 if (unz64local_getLong (&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
854 err = UNZ_ERRNO;
855 file_info_internal.offset_curfile = uL;
856 }
857
858 lSeek += file_info.size_filename;
859 if ((err == UNZ_OK) and (szFileName != NULL)) {
860 uLong uSizeRead;
861 if (file_info.size_filename < fileNameBufferSize) {
862 *(szFileName + file_info.size_filename) = '\0';
863 uSizeRead = file_info.size_filename;
864 }
865 else
866 uSizeRead = fileNameBufferSize;
867
868 if ((file_info.size_filename > 0) and (fileNameBufferSize > 0))
869 if (ZREAD64 (s->z_filefunc, s->filestream, szFileName, uSizeRead) != uSizeRead)
870 err = UNZ_ERRNO;
871 lSeek -= uSizeRead;
872 }
873
874 // Read extrafield
875 if ((err == UNZ_OK) and (extraField != NULL)) {
876 ZPOS64_T uSizeRead;
877 if (file_info.size_file_extra < extraFieldBufferSize)
878 uSizeRead = file_info.size_file_extra;
879 else
880 uSizeRead = extraFieldBufferSize;
881
882 if (lSeek != 0) {
883 if (ZSEEK64 (s->z_filefunc, s->filestream, lSeek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
884 lSeek = 0;
885 else
886 err = UNZ_ERRNO;
887 }
888
889 if ((file_info.size_file_extra > 0) and (extraFieldBufferSize > 0))
890 if (ZREAD64 (s->z_filefunc, s->filestream, extraField, (uLong)uSizeRead) != uSizeRead)
891 err = UNZ_ERRNO;
892
893 lSeek += file_info.size_file_extra - (uLong)uSizeRead;
894 }
895 else
896 lSeek += file_info.size_file_extra;
897
898 if ((err == UNZ_OK) and (file_info.size_file_extra != 0)) {
899 uLong acc = 0;
900
901 // since lSeek now points to after the extra field we need to move back
902 lSeek -= file_info.size_file_extra;
903
904 if (lSeek != 0) {
905 if (ZSEEK64 (s->z_filefunc, s->filestream, lSeek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
906 lSeek = 0;
907 else
908 err = UNZ_ERRNO;
909 }
910
911 while (acc < file_info.size_file_extra) {
912 uLong headerId;
913 uLong dataSize;
914
915 if (unz64local_getShort (&s->z_filefunc, s->filestream, &headerId) != UNZ_OK)
916 err = UNZ_ERRNO;
917
918 if (unz64local_getShort (&s->z_filefunc, s->filestream, &dataSize) != UNZ_OK)
919 err = UNZ_ERRNO;
920
921 /* ZIP64 extra fields */
922 if (headerId == 0x0001) {
923 uLong uL;
924
925 if (file_info.uncompressed_size == MAXU32) {
926 if (unz64local_getLong64 (&s->z_filefunc, s->filestream, &file_info.uncompressed_size) != UNZ_OK)
927 err = UNZ_ERRNO;
928 }
929
930 if (file_info.compressed_size == MAXU32) {
931 if (unz64local_getLong64 (&s->z_filefunc, s->filestream, &file_info.compressed_size) != UNZ_OK)
932 err = UNZ_ERRNO;
933 }
934
935 if (file_info_internal.offset_curfile == MAXU32) {
936 /* Relative Header offset */
937 if (unz64local_getLong64 (&s->z_filefunc, s->filestream, &file_info_internal.offset_curfile) != UNZ_OK)
938 err = UNZ_ERRNO;
939 }
940
941 if (file_info.disk_num_start == MAXU32) {
942 /* Disk Start Number */
943 if (unz64local_getLong (&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
944 err = UNZ_ERRNO;
945 }
946 }
947 else {
948 if (ZSEEK64 (s->z_filefunc, s->filestream, dataSize, ZLIB_FILEFUNC_SEEK_CUR) != 0)
949 err = UNZ_ERRNO;
950 }
951
952 acc += 2 + 2 + dataSize;
953 }
954 }
955
956 if ((err == UNZ_OK) and (szComment != NULL)) {
957 uLong uSizeRead;
958 if (file_info.size_file_comment < commentBufferSize) {
959 *(szComment + file_info.size_file_comment) = '\0';
960 uSizeRead = file_info.size_file_comment;
961 }
962 else
963 uSizeRead = commentBufferSize;
964
965 if (lSeek != 0) {
966 if (ZSEEK64 (s->z_filefunc, s->filestream, lSeek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
967 lSeek = 0;
968 else
969 err = UNZ_ERRNO;
970 }
971
972 if ((file_info.size_file_comment > 0) and (commentBufferSize > 0))
973 if (ZREAD64 (s->z_filefunc, s->filestream, szComment, uSizeRead) != uSizeRead)
974 err = UNZ_ERRNO;
975 lSeek += file_info.size_file_comment - uSizeRead;
976 }
977 else
978 lSeek += file_info.size_file_comment;
979
980 if ((err == UNZ_OK) and (pfile_info != NULL))
981 *pfile_info = file_info;
982
983 if ((err == UNZ_OK) and (pfile_info_internal != NULL))
984 *pfile_info_internal = file_info_internal;
985
986 return err;
987 }
988}
989/*
990 Write info about the ZipFile in the *pglobal_info structure.
991 No preparation of the structure is needed
992 return UNZ_OK if there is no problem.
993 */
994int PrivateMinizip_::unzGetCurrentFileInfo64 (unzFile file, unz_file_info64* pfile_info, char* szFileName, uLong fileNameBufferSize,
995 void* extraField, uLong extraFieldBufferSize, char* szComment, uLong commentBufferSize)
996{
997 return unz64local_GetCurrentFileInfoInternal_ (file, pfile_info, NULL, szFileName, fileNameBufferSize, extraField, extraFieldBufferSize,
998 szComment, commentBufferSize);
999}
1000
1001int PrivateMinizip_::unzGetCurrentFileInfo (unzFile file, unz_file_info* pfile_info, char* szFileName, uLong fileNameBufferSize,
1002 void* extraField, uLong extraFieldBufferSize, char* szComment, uLong commentBufferSize)
1003{
1004 int err;
1005 unz_file_info64 file_info64;
1006 err = unz64local_GetCurrentFileInfoInternal_ (file, &file_info64, NULL, szFileName, fileNameBufferSize, extraField,
1007 extraFieldBufferSize, szComment, commentBufferSize);
1008 if ((err == UNZ_OK) and (pfile_info != NULL)) {
1009 pfile_info->version = file_info64.version;
1010 pfile_info->version_needed = file_info64.version_needed;
1011 pfile_info->flag = file_info64.flag;
1012 pfile_info->compression_method = file_info64.compression_method;
1013 pfile_info->dosDate = file_info64.dosDate;
1014 pfile_info->crc = file_info64.crc;
1015
1016 pfile_info->size_filename = file_info64.size_filename;
1017 pfile_info->size_file_extra = file_info64.size_file_extra;
1018 pfile_info->size_file_comment = file_info64.size_file_comment;
1019
1020 pfile_info->disk_num_start = file_info64.disk_num_start;
1021 pfile_info->internal_fa = file_info64.internal_fa;
1022 pfile_info->external_fa = file_info64.external_fa;
1023
1024 pfile_info->tmu_date = file_info64.tmu_date,
1025
1026 pfile_info->compressed_size = (uLong)file_info64.compressed_size;
1027 pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;
1028 }
1029 return err;
1030}
1031
1032/*
1033 Set the current file of the zipfile to the first file.
1034 return UNZ_OK if there is no problem
1035*/
1036int PrivateMinizip_::unzGoToFirstFile (unzFile file)
1037{
1038 int err = UNZ_OK;
1039 unz64_s* s;
1040 if (file == NULL)
1041 return UNZ_PARAMERROR;
1042 s = (unz64_s*)file;
1043 s->pos_in_central_dir = s->offset_central_dir;
1044 s->num_file = 0;
1045 err = unz64local_GetCurrentFileInfoInternal_ (file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0);
1046 s->current_file_ok = (err == UNZ_OK);
1047 return err;
1048}
1049
1050/*
1051 Set the current file of the zipfile to the next file.
1052 return UNZ_OK if there is no problem
1053 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
1054 */
1055int PrivateMinizip_::unzGoToNextFile_ (unzFile file)
1056{
1057 unz64_s* s;
1058 int err;
1059
1060 if (file == NULL)
1061 return UNZ_PARAMERROR;
1062 s = (unz64_s*)file;
1063 if (!s->current_file_ok)
1064 return UNZ_END_OF_LIST_OF_FILE;
1065 if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
1066 if (s->num_file + 1 == s->gi.number_entry)
1067 return UNZ_END_OF_LIST_OF_FILE;
1068
1069 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment;
1070 s->num_file++;
1071 err = unz64local_GetCurrentFileInfoInternal_ (file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0);
1072 s->current_file_ok = (err == UNZ_OK);
1073 return err;
1074}
1075/*
1076 Try locate the file szFileName in the zipfile.
1077 For the iCaseSensitivity signification, see unzStringFileNameCompare
1078
1079 return value :
1080 UNZ_OK if the file is found. It becomes the current file.
1081 UNZ_END_OF_LIST_OF_FILE if the file is not found
1082 */
1083int PrivateMinizip_::unzLocateFile_ (unzFile file, const char* szFileName, int iCaseSensitivity)
1084{
1085 unz64_s* s;
1086 int err;
1087
1088 /* We remember the 'current' position in the file so that we can jump
1089 * back there if we fail.
1090 */
1091 unz_file_info64 cur_file_infoSaved;
1092 unz_file_info64_internal cur_file_info_internalSaved;
1093 ZPOS64_T num_fileSaved;
1094 ZPOS64_T pos_in_central_dirSaved;
1095
1096 if (file == NULL)
1097 return UNZ_PARAMERROR;
1098
1099 if (strlen (szFileName) >= UNZ_MAXFILENAMEINZIP)
1100 return UNZ_PARAMERROR;
1101
1102 s = (unz64_s*)file;
1103 if (!s->current_file_ok)
1104 return UNZ_END_OF_LIST_OF_FILE;
1105
1106 /* Save the current state */
1107 num_fileSaved = s->num_file;
1108 pos_in_central_dirSaved = s->pos_in_central_dir;
1109 cur_file_infoSaved = s->cur_file_info;
1110 cur_file_info_internalSaved = s->cur_file_info_internal;
1111
1112 err = unzGoToFirstFile (file);
1113
1114 while (err == UNZ_OK) {
1115 char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1];
1116 err = unzGetCurrentFileInfo64 (file, NULL, szCurrentFileName, sizeof (szCurrentFileName) - 1, NULL, 0, NULL, 0);
1117 if (err == UNZ_OK) {
1118 if (unzStringFileNameCompare (szCurrentFileName, szFileName, iCaseSensitivity) == 0)
1119 return UNZ_OK;
1120 err = unzGoToNextFile_ (file);
1121 }
1122 }
1123
1124 /* We failed, so restore the state of the 'current file' to where we
1125 * were.
1126 */
1127 s->num_file = num_fileSaved;
1128 s->pos_in_central_dir = pos_in_central_dirSaved;
1129 s->cur_file_info = cur_file_infoSaved;
1130 s->cur_file_info_internal = cur_file_info_internalSaved;
1131 return err;
1132}
1133
1134namespace {
1135 /*
1136 ///////////////////////////////////////////
1137 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
1138 // I need random access
1139 //
1140 // Further optimization could be realized by adding an ability
1141 // to cache the directory in memory. The goal being a single
1142 // comprehensive file read to put the file I need in a memory.
1143 */
1144
1145 /*
1146 typedef struct unz_file_pos_s
1147 {
1148 ZPOS64_T pos_in_zip_directory; // offset in file
1149 ZPOS64_T num_of_file; // # of file
1150 } unz_file_pos;
1151 */
1152}
1153int PrivateMinizip_::unzGetFilePos64 (unzFile file, unz64_file_pos* file_pos)
1154{
1155 unz64_s* s;
1156
1157 if (file == NULL or file_pos == NULL)
1158 return UNZ_PARAMERROR;
1159 s = (unz64_s*)file;
1160 if (!s->current_file_ok)
1161 return UNZ_END_OF_LIST_OF_FILE;
1162
1163 file_pos->pos_in_zip_directory = s->pos_in_central_dir;
1164 file_pos->num_of_file = s->num_file;
1165
1166 return UNZ_OK;
1167}
1168
1169int PrivateMinizip_::unzGetFilePos (unzFile file, unz_file_pos* file_pos)
1170{
1171 unz64_file_pos file_pos64;
1172 int err = unzGetFilePos64 (file, &file_pos64);
1173 if (err == UNZ_OK) {
1174 file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;
1175 file_pos->num_of_file = (uLong)file_pos64.num_of_file;
1176 }
1177 return err;
1178}
1179
1180int PrivateMinizip_::unzGoToFilePos64 (unzFile file, const unz64_file_pos* file_pos)
1181{
1182 unz64_s* s;
1183 int err;
1184
1185 if (file == NULL or file_pos == NULL)
1186 return UNZ_PARAMERROR;
1187 s = (unz64_s*)file;
1188
1189 /* jump to the right spot */
1190 s->pos_in_central_dir = file_pos->pos_in_zip_directory;
1191 s->num_file = file_pos->num_of_file;
1192
1193 /* set the current file */
1194 err = unz64local_GetCurrentFileInfoInternal_ (file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0);
1195 /* return results */
1196 s->current_file_ok = (err == UNZ_OK);
1197 return err;
1198}
1199
1200int PrivateMinizip_::unzGoToFilePos (unzFile file, unz_file_pos* file_pos)
1201{
1202 unz64_file_pos file_pos64;
1203 if (file_pos == NULL)
1204 return UNZ_PARAMERROR;
1205
1206 file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
1207 file_pos64.num_of_file = file_pos->num_of_file;
1208 return unzGoToFilePos64 (file, &file_pos64);
1209}
1210
1211/*
1212 // Unzip Helper Functions - should be here?
1213 ///////////////////////////////////////////
1214 */
1215
1216/*
1217 Read the local header of the current zipfile
1218 Check the coherency of the local header and info in the end of central
1219 directory about this file
1220 store in *piSizeVar the size of extra info in local header
1221 (filename and size of extra field data)
1222 */
1223int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, ZPOS64_T* poffset_local_extrafield, uInt* psize_local_extrafield)
1224{
1225 uLong uMagic, uData, uFlags;
1226 uLong size_filename;
1227 uLong size_extra_field;
1228 int err = UNZ_OK;
1229
1230 *piSizeVar = 0;
1231 *poffset_local_extrafield = 0;
1232 *psize_local_extrafield = 0;
1233
1234 if (ZSEEK64 (s->z_filefunc, s->filestream, s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
1235 return UNZ_ERRNO;
1236
1237 if (err == UNZ_OK) {
1238 if (unz64local_getLong (&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK)
1239 err = UNZ_ERRNO;
1240 else if (uMagic != 0x04034b50)
1241 err = UNZ_BADZIPFILE;
1242 }
1243
1244 if (unz64local_getShort (&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
1245 err = UNZ_ERRNO;
1246 /*
1247 else if ((err==UNZ_OK) and (uData!=s->cur_file_info.wVersion))
1248 err=UNZ_BADZIPFILE;
1249 */
1250 if (unz64local_getShort (&s->z_filefunc, s->filestream, &uFlags) != UNZ_OK)
1251 err = UNZ_ERRNO;
1252
1253 if (unz64local_getShort (&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
1254 err = UNZ_ERRNO;
1255 else if ((err == UNZ_OK) and (uData != s->cur_file_info.compression_method))
1256 err = UNZ_BADZIPFILE;
1257
1258 if ((err == UNZ_OK) and (s->cur_file_info.compression_method != 0) &&
1259 /* #ifdef HAVE_BZIP2 */
1260 (s->cur_file_info.compression_method != Z_BZIP2ED) &&
1261 /* #endif */
1262 (s->cur_file_info.compression_method != Z_DEFLATED))
1263 err = UNZ_BADZIPFILE;
1264
1265 if (unz64local_getLong (&s->z_filefunc, s->filestream, &uData) != UNZ_OK) /* date/time */
1266 err = UNZ_ERRNO;
1267
1268 if (unz64local_getLong (&s->z_filefunc, s->filestream, &uData) != UNZ_OK) /* crc */
1269 err = UNZ_ERRNO;
1270 else if ((err == UNZ_OK) and (uData != s->cur_file_info.crc) and ((uFlags & 8) == 0))
1271 err = UNZ_BADZIPFILE;
1272
1273 if (unz64local_getLong (&s->z_filefunc, s->filestream, &uData) != UNZ_OK) /* size compr */
1274 err = UNZ_ERRNO;
1275 else if (uData != 0xFFFFFFFF and (err == UNZ_OK) and (uData != s->cur_file_info.compressed_size) and ((uFlags & 8) == 0))
1276 err = UNZ_BADZIPFILE;
1277
1278 if (unz64local_getLong (&s->z_filefunc, s->filestream, &uData) != UNZ_OK) /* size uncompr */
1279 err = UNZ_ERRNO;
1280 else if (uData != 0xFFFFFFFF and (err == UNZ_OK) and (uData != s->cur_file_info.uncompressed_size) and ((uFlags & 8) == 0))
1281 err = UNZ_BADZIPFILE;
1282
1283 if (unz64local_getShort (&s->z_filefunc, s->filestream, &size_filename) != UNZ_OK)
1284 err = UNZ_ERRNO;
1285 else if ((err == UNZ_OK) and (size_filename != s->cur_file_info.size_filename))
1286 err = UNZ_BADZIPFILE;
1287
1288 *piSizeVar += (uInt)size_filename;
1289
1290 if (unz64local_getShort (&s->z_filefunc, s->filestream, &size_extra_field) != UNZ_OK)
1291 err = UNZ_ERRNO;
1292 *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_filename;
1293 *psize_local_extrafield = (uInt)size_extra_field;
1294
1295 *piSizeVar += (uInt)size_extra_field;
1296
1297 return err;
1298}
1299
1300/*
1301 Open for reading data the current file in the zipfile.
1302 If there is no error and the file is opened, the return value is UNZ_OK.
1303 */
1304int PrivateMinizip_::unzOpenCurrentFile3_ (unzFile file, int* method, int* level, int raw, const char* password)
1305{
1306 int err = UNZ_OK;
1307 uInt iSizeVar;
1308 unz64_s* s;
1309 file_in_zip64_read_info_s* pfile_in_zip_read_info;
1310 ZPOS64_T offset_local_extrafield; /* offset of the local extra field */
1311 uInt size_local_extrafield; /* size of the local extra field */
1312#ifndef NOUNCRYPT
1313 char source[12];
1314#else
1315 if (password != NULL)
1316 return UNZ_PARAMERROR;
1317#endif
1318
1319 if (file == NULL)
1320 return UNZ_PARAMERROR;
1321 s = (unz64_s*)file;
1322 if (!s->current_file_ok)
1323 return UNZ_PARAMERROR;
1324
1325 if (s->pfile_in_zip_read != NULL)
1326 unzCloseCurrentFile_ (file);
1327
1328 if (unz64local_CheckCurrentFileCoherencyHeader (s, &iSizeVar, &offset_local_extrafield, &size_local_extrafield) != UNZ_OK)
1329 return UNZ_BADZIPFILE;
1330
1331 pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC (sizeof (file_in_zip64_read_info_s));
1332 if (pfile_in_zip_read_info == NULL)
1333 return UNZ_INTERNALERROR;
1334
1335 pfile_in_zip_read_info->read_buffer = (char*)ALLOC (UNZ_BUFSIZE);
1336 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1337 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1338 pfile_in_zip_read_info->pos_local_extrafield = 0;
1339 pfile_in_zip_read_info->raw = raw;
1340
1341 if (pfile_in_zip_read_info->read_buffer == NULL) {
1342 TRYFREE (pfile_in_zip_read_info);
1343 return UNZ_INTERNALERROR;
1344 }
1345
1346 pfile_in_zip_read_info->stream_initialised = 0;
1347
1348 if (method != NULL)
1349 *method = (int)s->cur_file_info.compression_method;
1350
1351 if (level != NULL) {
1352 *level = 6;
1353 switch (s->cur_file_info.flag & 0x06) {
1354 case 6:
1355 *level = 1;
1356 break;
1357 case 4:
1358 *level = 2;
1359 break;
1360 case 2:
1361 *level = 9;
1362 break;
1363 }
1364 }
1365
1366 if ((s->cur_file_info.compression_method != 0) &&
1367 /* #ifdef HAVE_BZIP2 */
1368 (s->cur_file_info.compression_method != Z_BZIP2ED) &&
1369 /* #endif */
1370 (s->cur_file_info.compression_method != Z_DEFLATED))
1371
1372 err = UNZ_BADZIPFILE;
1373
1374 pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc;
1375 pfile_in_zip_read_info->crc32 = 0;
1376 pfile_in_zip_read_info->total_out_64 = 0;
1377 pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
1378 pfile_in_zip_read_info->filestream = s->filestream;
1379 pfile_in_zip_read_info->z_filefunc = s->z_filefunc;
1380 pfile_in_zip_read_info->byte_before_the_zipfile = s->byte_before_the_zipfile;
1381
1382 pfile_in_zip_read_info->stream.total_out = 0;
1383
1384 if ((s->cur_file_info.compression_method == Z_BZIP2ED) and (!raw)) {
1385#ifdef HAVE_BZIP2
1386 pfile_in_zip_read_info->bstream.bzalloc = (void* (*)(void*, int, int))0;
1387 pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
1388 pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
1389 pfile_in_zip_read_info->bstream.state = (voidpf)0;
1390
1391 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1392 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1393 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1394 pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1395 pfile_in_zip_read_info->stream.avail_in = 0;
1396
1397 err = BZ2_bzDecompressInit (&pfile_in_zip_read_info->bstream, 0, 0);
1398 if (err == Z_OK)
1399 pfile_in_zip_read_info->stream_initialised = Z_BZIP2ED;
1400 else {
1401 TRYFREE (pfile_in_zip_read_info);
1402 return err;
1403 }
1404#else
1405 pfile_in_zip_read_info->raw = 1;
1406#endif
1407 }
1408 else if ((s->cur_file_info.compression_method == Z_DEFLATED) and (!raw)) {
1409 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1410 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1411 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1412 pfile_in_zip_read_info->stream.next_in = 0;
1413 pfile_in_zip_read_info->stream.avail_in = 0;
1414
1415 err = inflateInit2 (&pfile_in_zip_read_info->stream, -MAX_WBITS);
1416 if (err == Z_OK)
1417 pfile_in_zip_read_info->stream_initialised = Z_DEFLATED;
1418 else {
1419 TRYFREE (pfile_in_zip_read_info);
1420 return err;
1421 }
1422 /* windowBits is passed < 0 to tell that there is no zlib header.
1423 * Note that in this case inflate *requires* an extra "dummy" byte
1424 * after the compressed stream in order to complete decompression and
1425 * return Z_STREAM_END.
1426 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1427 * size of both compressed and uncompressed data
1428 */
1429 }
1430 pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size;
1431 pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size;
1432
1433 pfile_in_zip_read_info->pos_in_zipfile = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + iSizeVar;
1434
1435 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1436
1437 s->pfile_in_zip_read = pfile_in_zip_read_info;
1438 s->encrypted = 0;
1439
1440#ifndef NOUNCRYPT
1441 if (password != NULL) {
1442 int i;
1443 s->pcrc_32_tab = get_crc_table ();
1444 init_keys (password, s->keys, s->pcrc_32_tab);
1445 if (ZSEEK64 (s->z_filefunc, s->filestream, s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile, SEEK_SET) != 0)
1446 return UNZ_INTERNALERROR;
1447 if (ZREAD64 (s->z_filefunc, s->filestream, source, 12) < 12)
1448 return UNZ_INTERNALERROR;
1449
1450 for (i = 0; i < 12; ++i)
1451 zdecode (s->keys, s->pcrc_32_tab, source[i]);
1452
1453 s->pfile_in_zip_read->pos_in_zipfile += 12;
1454 s->encrypted = 1;
1455 }
1456#endif
1457
1458 return UNZ_OK;
1459}
1460
1461int PrivateMinizip_::unzOpenCurrentFile (unzFile file)
1462{
1463 return unzOpenCurrentFile3_ (file, NULL, NULL, 0, NULL);
1464}
1465
1466int PrivateMinizip_::unzOpenCurrentFilePassword (unzFile file, const char* password)
1467{
1468 return unzOpenCurrentFile3_ (file, NULL, NULL, 0, password);
1469}
1470
1471int PrivateMinizip_::unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw)
1472{
1473 return unzOpenCurrentFile3_ (file, method, level, raw, NULL);
1474}
1475
1476/** Addition for GDAL : START */
1477
1478ZPOS64_T PrivateMinizip_::unzGetCurrentFileZStreamPos64 (unzFile file)
1479{
1480 unz64_s* s;
1481 file_in_zip64_read_info_s* pfile_in_zip_read_info;
1482 s = (unz64_s*)file;
1483 if (file == NULL)
1484 return 0; //UNZ_PARAMERROR;
1485 pfile_in_zip_read_info = s->pfile_in_zip_read;
1486 if (pfile_in_zip_read_info == NULL)
1487 return 0; //UNZ_PARAMERROR;
1488 return pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile;
1489}
1490
1491/** Addition for GDAL : END */
1492
1493/*
1494 Read bytes from the current file.
1495 buf contain buffer where data must be copied
1496 len the size of buf.
1497
1498 return the number of byte copied if somes bytes are copied
1499 return 0 if the end of file was reached
1500 return <0 with error code if there is an error
1501 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1502 */
1503int PrivateMinizip_::unzReadCurrentFile_ (unzFile file, voidp buf, unsigned len)
1504{
1505 int err = UNZ_OK;
1506 uInt iRead = 0;
1507 unz64_s* s;
1508 file_in_zip64_read_info_s* pfile_in_zip_read_info;
1509 if (file == NULL)
1510 return UNZ_PARAMERROR;
1511 s = (unz64_s*)file;
1512 pfile_in_zip_read_info = s->pfile_in_zip_read;
1513
1514 if (pfile_in_zip_read_info == NULL)
1515 return UNZ_PARAMERROR;
1516
1517 if (pfile_in_zip_read_info->read_buffer == NULL)
1518 return UNZ_END_OF_LIST_OF_FILE;
1519 if (len == 0)
1520 return 0;
1521
1522 pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1523
1524 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1525
1526 if ((len > pfile_in_zip_read_info->rest_read_uncompressed) && (!(pfile_in_zip_read_info->raw)))
1527 pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1528
1529 if ((len > pfile_in_zip_read_info->rest_read_compressed + pfile_in_zip_read_info->stream.avail_in) && (pfile_in_zip_read_info->raw))
1530 pfile_in_zip_read_info->stream.avail_out = (uInt)pfile_in_zip_read_info->rest_read_compressed + pfile_in_zip_read_info->stream.avail_in;
1531
1532 while (pfile_in_zip_read_info->stream.avail_out > 0) {
1533 if ((pfile_in_zip_read_info->stream.avail_in == 0) && (pfile_in_zip_read_info->rest_read_compressed > 0)) {
1534 uInt uReadThis = UNZ_BUFSIZE;
1535 if (pfile_in_zip_read_info->rest_read_compressed < uReadThis)
1536 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1537 if (uReadThis == 0)
1538 return UNZ_EOF;
1539 if (ZSEEK64 (pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream,
1540 pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
1541 return UNZ_ERRNO;
1542 if (ZREAD64 (pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, pfile_in_zip_read_info->read_buffer, uReadThis) != uReadThis)
1543 return UNZ_ERRNO;
1544
1545#ifndef NOUNCRYPT
1546 if (s->encrypted) {
1547 uInt i;
1548 for (i = 0; i < uReadThis; i++)
1549 pfile_in_zip_read_info->read_buffer[i] = zdecode (s->keys, s->pcrc_32_tab, pfile_in_zip_read_info->read_buffer[i]);
1550 }
1551#endif
1552
1553 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1554
1555 pfile_in_zip_read_info->rest_read_compressed -= uReadThis;
1556
1557 pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->read_buffer;
1558 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1559 }
1560
1561 if ((pfile_in_zip_read_info->compression_method == 0) || (pfile_in_zip_read_info->raw)) {
1562 uInt uDoCopy, i;
1563
1564 if ((pfile_in_zip_read_info->stream.avail_in == 0) && (pfile_in_zip_read_info->rest_read_compressed == 0))
1565 return (iRead == 0) ? UNZ_EOF : iRead;
1566
1567 if (pfile_in_zip_read_info->stream.avail_out < pfile_in_zip_read_info->stream.avail_in)
1568 uDoCopy = pfile_in_zip_read_info->stream.avail_out;
1569 else
1570 uDoCopy = pfile_in_zip_read_info->stream.avail_in;
1571
1572 for (i = 0; i < uDoCopy; i++)
1573 *(pfile_in_zip_read_info->stream.next_out + i) = *(pfile_in_zip_read_info->stream.next_in + i);
1574
1575 pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;
1576
1577 pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32, pfile_in_zip_read_info->stream.next_out, uDoCopy);
1578 pfile_in_zip_read_info->rest_read_uncompressed -= uDoCopy;
1579 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1580 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1581 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1582 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1583 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1584 iRead += uDoCopy;
1585 }
1586 else if (pfile_in_zip_read_info->compression_method == Z_BZIP2ED) {
1587#ifdef HAVE_BZIP2
1588 uLong uTotalOutBefore, uTotalOutAfter;
1589 const Bytef* bufBefore;
1590 uLong uOutThis;
1591
1592 pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in;
1593 pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in;
1594 pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in;
1595 pfile_in_zip_read_info->bstream.total_in_hi32 = 0;
1596 pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out;
1597 pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out;
1598 pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
1599 pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
1600
1601 uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
1602 bufBefore = (const Bytef*)pfile_in_zip_read_info->bstream.next_out;
1603
1604 err = BZ2_bzDecompress (&pfile_in_zip_read_info->bstream);
1605
1606 uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
1607 uOutThis = uTotalOutAfter - uTotalOutBefore;
1608
1609 pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
1610
1611 pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32, bufBefore, (uInt)(uOutThis));
1612 pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
1613 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1614
1615 pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in;
1616 pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in;
1617 pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32;
1618 pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out;
1619 pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
1620 pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
1621
1622 if (err == BZ_STREAM_END)
1623 return (iRead == 0) ? UNZ_EOF : iRead;
1624 if (err != BZ_OK)
1625 break;
1626#endif
1627 } // end Z_BZIP2ED
1628 else {
1629 ZPOS64_T uTotalOutBefore, uTotalOutAfter;
1630 const Bytef* bufBefore;
1631 ZPOS64_T uOutThis;
1632 int flush = Z_SYNC_FLUSH;
1633
1634 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1635 bufBefore = pfile_in_zip_read_info->stream.next_out;
1636
1637 /*
1638 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1639 pfile_in_zip_read_info->stream.avail_out) &&
1640 (pfile_in_zip_read_info->rest_read_compressed == 0))
1641 flush = Z_FINISH;
1642 */
1643 err = inflate (&pfile_in_zip_read_info->stream, flush);
1644
1645 if ((err >= 0) and (pfile_in_zip_read_info->stream.msg != NULL))
1646 err = Z_DATA_ERROR;
1647
1648 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1649 uOutThis = uTotalOutAfter - uTotalOutBefore;
1650
1651 pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
1652
1653 pfile_in_zip_read_info->crc32 = crc32 (pfile_in_zip_read_info->crc32, bufBefore, (uInt)(uOutThis));
1654
1655 pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
1656
1657 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1658
1659 if (err == Z_STREAM_END)
1660 return (iRead == 0) ? UNZ_EOF : iRead;
1661 if (err != Z_OK)
1662 break;
1663 }
1664 }
1665
1666 if (err == Z_OK)
1667 return iRead;
1668 return err;
1669}
1670
1671/*
1672 Give the current position in uncompressed data
1673*/
1674z_off_t PrivateMinizip_::unztell (unzFile file)
1675{
1676 unz64_s* s;
1677 file_in_zip64_read_info_s* pfile_in_zip_read_info;
1678 if (file == NULL)
1679 return UNZ_PARAMERROR;
1680 s = (unz64_s*)file;
1681 pfile_in_zip_read_info = s->pfile_in_zip_read;
1682
1683 if (pfile_in_zip_read_info == NULL)
1684 return UNZ_PARAMERROR;
1685
1686 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1687}
1688
1689ZPOS64_T PrivateMinizip_::unztell64 (unzFile file)
1690{
1691
1692 unz64_s* s;
1693 file_in_zip64_read_info_s* pfile_in_zip_read_info;
1694 if (file == NULL)
1695 return (ZPOS64_T)-1;
1696 s = (unz64_s*)file;
1697 pfile_in_zip_read_info = s->pfile_in_zip_read;
1698
1699 if (pfile_in_zip_read_info == NULL)
1700 return (ZPOS64_T)-1;
1701
1702 return pfile_in_zip_read_info->total_out_64;
1703}
1704
1705/*
1706 return 1 if the end of file was reached, 0 elsewhere
1707 */
1708int PrivateMinizip_::unzeof (unzFile file)
1709{
1710 unz64_s* s;
1711 file_in_zip64_read_info_s* pfile_in_zip_read_info;
1712 if (file == NULL)
1713 return UNZ_PARAMERROR;
1714 s = (unz64_s*)file;
1715 pfile_in_zip_read_info = s->pfile_in_zip_read;
1716
1717 if (pfile_in_zip_read_info == NULL)
1718 return UNZ_PARAMERROR;
1719
1720 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1721 return 1;
1722 else
1723 return 0;
1724}
1725
1726/*
1727 Read extra field from the current file (opened by unzOpenCurrentFile)
1728 This is the local-header version of the extra field (sometimes, there is
1729 more info in the local-header version than in the central-header)
1730
1731 if buf==NULL, it return the size of the local extra field that can be read
1732
1733 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1734 buf.
1735 the return value is the number of bytes copied in buf, or (if <0)
1736 the error code
1737 */
1738int PrivateMinizip_::unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
1739{
1740 unz64_s* s;
1741 file_in_zip64_read_info_s* pfile_in_zip_read_info;
1742 uInt read_now;
1743 ZPOS64_T size_to_read;
1744
1745 if (file == NULL)
1746 return UNZ_PARAMERROR;
1747 s = (unz64_s*)file;
1748 pfile_in_zip_read_info = s->pfile_in_zip_read;
1749
1750 if (pfile_in_zip_read_info == NULL)
1751 return UNZ_PARAMERROR;
1752
1753 size_to_read = (pfile_in_zip_read_info->size_local_extrafield - pfile_in_zip_read_info->pos_local_extrafield);
1754
1755 if (buf == NULL)
1756 return (int)size_to_read;
1757
1758 if (len > size_to_read)
1759 read_now = (uInt)size_to_read;
1760 else
1761 read_now = (uInt)len;
1762
1763 if (read_now == 0)
1764 return 0;
1765
1766 if (ZSEEK64 (pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream,
1767 pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield, ZLIB_FILEFUNC_SEEK_SET) != 0)
1768 return UNZ_ERRNO;
1769
1770 if (ZREAD64 (pfile_in_zip_read_info->z_filefunc, pfile_in_zip_read_info->filestream, buf, read_now) != read_now)
1771 return UNZ_ERRNO;
1772
1773 return (int)read_now;
1774}
1775
1776/*
1777 Close the file in zip opened with unzOpenCurrentFile
1778 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1779 */
1780int PrivateMinizip_::unzCloseCurrentFile_ (unzFile file)
1781{
1782 int err = UNZ_OK;
1783
1784 unz64_s* s;
1785 file_in_zip64_read_info_s* pfile_in_zip_read_info;
1786 if (file == NULL)
1787 return UNZ_PARAMERROR;
1788 s = (unz64_s*)file;
1789 pfile_in_zip_read_info = s->pfile_in_zip_read;
1790
1791 if (pfile_in_zip_read_info == NULL)
1792 return UNZ_PARAMERROR;
1793
1794 if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && (!pfile_in_zip_read_info->raw)) {
1795 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1796 err = UNZ_CRCERROR;
1797 }
1798
1799 TRYFREE (pfile_in_zip_read_info->read_buffer);
1800 pfile_in_zip_read_info->read_buffer = NULL;
1801 if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
1802 inflateEnd (&pfile_in_zip_read_info->stream);
1803#ifdef HAVE_BZIP2
1804 else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
1805 BZ2_bzDecompressEnd (&pfile_in_zip_read_info->bstream);
1806#endif
1807
1808 pfile_in_zip_read_info->stream_initialised = 0;
1809 TRYFREE (pfile_in_zip_read_info);
1810
1811 s->pfile_in_zip_read = NULL;
1812
1813 return err;
1814}
1815
1816/*
1817 Get the global comment string of the ZipFile, in the szComment buffer.
1818 uSizeBuf is the size of the szComment buffer.
1819 return the number of byte copied or an error code <0
1820 */
1821int PrivateMinizip_::unzGetGlobalComment (unzFile file, char* szComment, uLong uSizeBuf)
1822{
1823 unz64_s* s;
1824 uLong uReadThis;
1825 if (file == NULL)
1826 return (int)UNZ_PARAMERROR;
1827 s = (unz64_s*)file;
1828
1829 uReadThis = uSizeBuf;
1830 if (uReadThis > s->gi.size_comment)
1831 uReadThis = s->gi.size_comment;
1832
1833 if (ZSEEK64 (s->z_filefunc, s->filestream, s->central_pos + 22, ZLIB_FILEFUNC_SEEK_SET) != 0)
1834 return UNZ_ERRNO;
1835
1836 if (uReadThis > 0) {
1837 *szComment = '\0';
1838 if (ZREAD64 (s->z_filefunc, s->filestream, szComment, uReadThis) != uReadThis)
1839 return UNZ_ERRNO;
1840 }
1841
1842 if ((szComment != NULL) and (uSizeBuf > s->gi.size_comment))
1843 *(szComment + s->gi.size_comment) = '\0';
1844 return (int)uReadThis;
1845}
1846
1847/* Additions by RX '2004 */
1848ZPOS64_T PrivateMinizip_::unzGetOffset64 (unzFile file)
1849{
1850 unz64_s* s;
1851
1852 if (file == NULL)
1853 return 0; //UNZ_PARAMERROR;
1854 s = (unz64_s*)file;
1855 if (!s->current_file_ok)
1856 return 0;
1857 if (s->gi.number_entry != 0 and s->gi.number_entry != 0xffff)
1858 if (s->num_file == s->gi.number_entry)
1859 return 0;
1860 return s->pos_in_central_dir;
1861}
1862
1863uLong PrivateMinizip_::unzGetOffset (unzFile file)
1864{
1865 ZPOS64_T offset64;
1866
1867 if (file == NULL)
1868 return 0; //UNZ_PARAMERROR;
1869 offset64 = unzGetOffset64 (file);
1870 return (uLong)offset64;
1871}
1872
1873int PrivateMinizip_::unzSetOffset64 (unzFile file, ZPOS64_T pos)
1874{
1875 unz64_s* s;
1876 int err;
1877
1878 if (file == NULL)
1879 return UNZ_PARAMERROR;
1880 s = (unz64_s*)file;
1881
1882 s->pos_in_central_dir = pos;
1883 s->num_file = s->gi.number_entry; /* hack */
1884 err = unz64local_GetCurrentFileInfoInternal_ (file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0);
1885 s->current_file_ok = (err == UNZ_OK);
1886 return err;
1887}
1888
1889int PrivateMinizip_::unzSetOffset (unzFile file, uLong pos)
1890{
1891 return unzSetOffset64 (file, pos);
1892}
1893///////////////////////////////// END OF unzip.c ////////////////////
1894
1895/// START OF zip.c
1896
1897#ifndef VERSIONMADEBY
1898#define VERSIONMADEBY (0x0) /* platform dependent */
1899#endif
1900
1901#ifndef Z_BUFSIZE
1902#define Z_BUFSIZE (64 * 1024) //(16384)
1903#endif
1904
1905#ifndef Z_MAXFILENAMEINZIP
1906#define Z_MAXFILENAMEINZIP (256)
1907#endif
1908
1909#ifndef ALLOC
1910#define ALLOC(size) (malloc (size))
1911#endif
1912
1913/*
1914#define SIZECENTRALDIRITEM (0x2e)
1915#define SIZEZIPLOCALHEADER (0x1e)
1916*/
1917
1918/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
1919
1920// NOT sure that this work on ALL platform
1921#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32))
1922
1923#ifndef SEEK_CUR
1924#define SEEK_CUR 1
1925#endif
1926
1927#ifndef SEEK_END
1928#define SEEK_END 2
1929#endif
1930
1931#ifndef SEEK_SET
1932#define SEEK_SET 0
1933#endif
1934
1935#ifndef DEF_MEM_LEVEL
1936#if MAX_MEM_LEVEL >= 8
1937#define DEF_MEM_LEVEL 8
1938#else
1939#define DEF_MEM_LEVEL MAX_MEM_LEVEL
1940#endif
1941#endif
1942namespace {
1943 [[maybe_unused]] const char zip_copyright[] = " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
1944
1945#define SIZEDATA_INDATABLOCK (4096 - (4 * 4))
1946
1947#define LOCALHEADERMAGIC (0x04034b50)
1948#define CENTRALHEADERMAGIC (0x02014b50)
1949#define ENDHEADERMAGIC (0x06054b50)
1950#define ZIP64ENDHEADERMAGIC (0x6064b50)
1951#define ZIP64ENDLOCHEADERMAGIC (0x7064b50)
1952
1953#define FLAG_LOCALHEADER_OFFSET (0x06)
1954#define CRC_LOCALHEADER_OFFSET (0x0e)
1955
1956#define SIZECENTRALHEADER (0x2e) /* 46 */
1957
1958 typedef struct linkedlist_datablock_internal_s {
1959 struct linkedlist_datablock_internal_s* next_datablock;
1960 uLong avail_in_this_block;
1961 uLong filled_in_this_block;
1962 uLong unused; /* for future use and alignment */
1963 unsigned char data[SIZEDATA_INDATABLOCK];
1964 } linkedlist_datablock_internal;
1965
1966 typedef struct linkedlist_data_s {
1967 linkedlist_datablock_internal* first_block;
1968 linkedlist_datablock_internal* last_block;
1969 } linkedlist_data;
1970
1971 typedef struct {
1972 z_stream stream; /* zLib stream structure for inflate */
1973#ifdef HAVE_BZIP2
1974 bz_stream bstream; /* bzLib stream structure for bziped */
1975#endif
1976
1977 int stream_initialised; /* 1 is stream is initialised */
1978 uInt pos_in_buffered_data; /* last written byte in buffered_data */
1979
1980 ZPOS64_T pos_local_header; /* offset of the local header of the file
1981 currently writing */
1982 char* central_header; /* central header data for the current file */
1983 uLong size_centralExtra;
1984 uLong size_centralheader; /* size of the central header for cur file */
1985 uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */
1986 uLong flag; /* flag of the file currently writing */
1987
1988 int method; /* compression method of file currently wr.*/
1989 int raw; /* 1 for directly writing raw data */
1990 Byte buffered_data[Z_BUFSIZE]; /* buffer contain compressed data to be writ*/
1991 uLong dosDate;
1992 uLong crc32;
1993 int encrypt;
1994 int zip64; /* Add ZIP64 extended information in the extra field */
1995 ZPOS64_T pos_zip64extrainfo;
1996 ZPOS64_T totalCompressedData;
1997 ZPOS64_T totalUncompressedData;
1998#ifndef NOCRYPT
1999 unsigned long keys[3]; /* keys defining the pseudo-random sequence */
2000 const z_crc_t* pcrc_32_tab;
2001 unsigned crypt_header_size;
2002#endif
2003 } curfile64_info;
2004
2005 typedef struct {
2006 zlib_filefunc64_32_def z_filefunc;
2007 voidpf filestream; /* io structure of the zipfile */
2008 linkedlist_data central_dir; /* datablock with central dir in construction*/
2009 int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/
2010 curfile64_info ci; /* info on the file currently writing */
2011
2012 ZPOS64_T begin_pos; /* position of the beginning of the zipfile */
2013 ZPOS64_T add_position_when_writing_offset;
2014 ZPOS64_T number_entry;
2015
2016#ifndef NO_ADDFILEINEXISTINGZIP
2017 char* globalcomment;
2018#endif
2019
2020 } zip64_internal;
2021
2022 linkedlist_datablock_internal* allocate_new_datablock (void)
2023 {
2024 linkedlist_datablock_internal* ldi;
2025 ldi = (linkedlist_datablock_internal*)ALLOC (sizeof (linkedlist_datablock_internal));
2026 if (ldi != NULL) {
2027 ldi->next_datablock = NULL;
2028 ldi->filled_in_this_block = 0;
2029 ldi->avail_in_this_block = SIZEDATA_INDATABLOCK;
2030 }
2031 return ldi;
2032 }
2033
2034 void free_datablock (linkedlist_datablock_internal* ldi)
2035 {
2036 while (ldi != NULL) {
2037 linkedlist_datablock_internal* ldinext = ldi->next_datablock;
2038 free (ldi);
2039 ldi = ldinext;
2040 }
2041 }
2042
2043 void init_linkedlist (linkedlist_data* ll)
2044 {
2045 ll->first_block = ll->last_block = NULL;
2046 }
2047
2048 void free_linkedlist (linkedlist_data* ll)
2049 {
2050 free_datablock (ll->first_block);
2051 ll->first_block = ll->last_block = NULL;
2052 }
2053
2054 int add_data_in_datablock (linkedlist_data* ll, const void* buf, uLong len)
2055 {
2056 linkedlist_datablock_internal* ldi;
2057 const unsigned char* from_copy;
2058
2059 if (ll == NULL)
2060 return ZIP_INTERNALERROR;
2061
2062 if (ll->last_block == NULL) {
2063 ll->first_block = ll->last_block = allocate_new_datablock ();
2064 if (ll->first_block == NULL)
2065 return ZIP_INTERNALERROR;
2066 }
2067
2068 ldi = ll->last_block;
2069 from_copy = (const unsigned char*)buf;
2070
2071 while (len > 0) {
2072 uInt copy_this;
2073 uInt i;
2074 unsigned char* to_copy;
2075
2076 if (ldi->avail_in_this_block == 0) {
2077 ldi->next_datablock = allocate_new_datablock ();
2078 if (ldi->next_datablock == NULL)
2079 return ZIP_INTERNALERROR;
2080 ldi = ldi->next_datablock;
2081 ll->last_block = ldi;
2082 }
2083
2084 if (ldi->avail_in_this_block < len)
2085 copy_this = (uInt)ldi->avail_in_this_block;
2086 else
2087 copy_this = (uInt)len;
2088
2089 to_copy = &(ldi->data[ldi->filled_in_this_block]);
2090
2091 for (i = 0; i < copy_this; i++)
2092 *(to_copy + i) = *(from_copy + i);
2093
2094 ldi->filled_in_this_block += copy_this;
2095 ldi->avail_in_this_block -= copy_this;
2096 from_copy += copy_this;
2097 len -= copy_this;
2098 }
2099 return ZIP_OK;
2100 }
2101
2102 /****************************************************************************/
2103
2104#ifndef NO_ADDFILEINEXISTINGZIP
2105 /* ===========================================================================
2106 Inputs a long in LSB order to the given file
2107 nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T)
2108*/
2109
2110 int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)
2111 {
2112 unsigned char buf[8];
2113 int n;
2114 for (n = 0; n < nbByte; n++) {
2115 buf[n] = (unsigned char)(x & 0xff);
2116 x >>= 8;
2117 }
2118 if (x != 0) { /* data overflow - hack for ZIP64 (X Roche) */
2119 for (n = 0; n < nbByte; n++) {
2120 buf[n] = 0xff;
2121 }
2122 }
2123
2124 if (ZWRITE64 (*pzlib_filefunc_def, filestream, buf, (uLong)nbByte) != (uLong)nbByte)
2125 return ZIP_ERRNO;
2126 else
2127 return ZIP_OK;
2128 }
2129
2130 void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte)
2131 {
2132 unsigned char* buf = (unsigned char*)dest;
2133 int n;
2134 for (n = 0; n < nbByte; n++) {
2135 buf[n] = (unsigned char)(x & 0xff);
2136 x >>= 8;
2137 }
2138
2139 if (x != 0) { /* data overflow - hack for ZIP64 */
2140 for (n = 0; n < nbByte; n++) {
2141 buf[n] = 0xff;
2142 }
2143 }
2144 }
2145
2146 /****************************************************************************/
2147
2148 uLong zip64local_TmzDateToDosDate (const tm_zip* ptm)
2149 {
2150 uLong year = (uLong)ptm->tm_year;
2151 if (year >= 1980)
2152 year -= 1980;
2153 else if (year >= 80)
2154 year -= 80;
2155 return (uLong)(((uLong)(ptm->tm_mday) + (32 * (uLong)(ptm->tm_mon + 1)) + (512 * year)) << 16) |
2156 (((uLong)ptm->tm_sec / 2) + (32 * (uLong)ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
2157 }
2158
2159 /****************************************************************************/
2160
2161 int zip64local_getByte (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi)
2162 {
2163 unsigned char c;
2164 int err = (int)ZREAD64 (*pzlib_filefunc_def, filestream, &c, 1);
2165 if (err == 1) {
2166 *pi = (int)c;
2167 return ZIP_OK;
2168 }
2169 else {
2170 if (ZERROR64 (*pzlib_filefunc_def, filestream))
2171 return ZIP_ERRNO;
2172 else
2173 return ZIP_EOF;
2174 }
2175 }
2176
2177 /* ===========================================================================
2178 Reads a long in LSB order from the given gz_stream. Sets
2179*/
2180 int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
2181 {
2182 uLong x;
2183 int i = 0;
2184 int err;
2185
2186 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2187 x = (uLong)i;
2188
2189 if (err == ZIP_OK)
2190 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2191 x += ((uLong)i) << 8;
2192
2193 if (err == ZIP_OK)
2194 *pX = x;
2195 else
2196 *pX = 0;
2197 return err;
2198 }
2199
2200 int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
2201 {
2202 uLong x;
2203 int i = 0;
2204 int err;
2205
2206 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2207 x = (uLong)i;
2208
2209 if (err == ZIP_OK)
2210 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2211 x += ((uLong)i) << 8;
2212
2213 if (err == ZIP_OK)
2214 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2215 x += ((uLong)i) << 16;
2216
2217 if (err == ZIP_OK)
2218 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2219 x += ((uLong)i) << 24;
2220
2221 if (err == ZIP_OK)
2222 *pX = x;
2223 else
2224 *pX = 0;
2225 return err;
2226 }
2227
2228 int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T* pX)
2229 {
2230 ZPOS64_T x;
2231 int i = 0;
2232 int err;
2233
2234 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2235 x = (ZPOS64_T)i;
2236
2237 if (err == ZIP_OK)
2238 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2239 x += ((ZPOS64_T)i) << 8;
2240
2241 if (err == ZIP_OK)
2242 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2243 x += ((ZPOS64_T)i) << 16;
2244
2245 if (err == ZIP_OK)
2246 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2247 x += ((ZPOS64_T)i) << 24;
2248
2249 if (err == ZIP_OK)
2250 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2251 x += ((ZPOS64_T)i) << 32;
2252
2253 if (err == ZIP_OK)
2254 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2255 x += ((ZPOS64_T)i) << 40;
2256
2257 if (err == ZIP_OK)
2258 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2259 x += ((ZPOS64_T)i) << 48;
2260
2261 if (err == ZIP_OK)
2262 err = zip64local_getByte (pzlib_filefunc_def, filestream, &i);
2263 x += ((ZPOS64_T)i) << 56;
2264
2265 if (err == ZIP_OK)
2266 *pX = x;
2267 else
2268 *pX = 0;
2269
2270 return err;
2271 }
2272
2273#ifndef BUFREADCOMMENT
2274#define BUFREADCOMMENT (0x400)
2275#endif
2276 /*
2277 Locate the Central directory of a zipfile (at the end, just before
2278 the global comment)
2279*/
2280 ZPOS64_T zip64local_SearchCentralDir (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
2281 {
2282 unsigned char* buf;
2283 ZPOS64_T uSizeFile;
2284 ZPOS64_T uBackRead;
2285 ZPOS64_T uMaxBack = 0xffff; /* maximum size of global comment */
2286 ZPOS64_T uPosFound = 0;
2287
2288 if (ZSEEK64 (*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
2289 return 0;
2290
2291 uSizeFile = ZTELL64 (*pzlib_filefunc_def, filestream);
2292
2293 if (uMaxBack > uSizeFile)
2294 uMaxBack = uSizeFile;
2295
2296 buf = (unsigned char*)ALLOC (BUFREADCOMMENT + 4);
2297 if (buf == NULL)
2298 return 0;
2299
2300 uBackRead = 4;
2301 while (uBackRead < uMaxBack) {
2302 uLong uReadSize;
2303 ZPOS64_T uReadPos;
2304 int i;
2305 if (uBackRead + BUFREADCOMMENT > uMaxBack)
2306 uBackRead = uMaxBack;
2307 else
2308 uBackRead += BUFREADCOMMENT;
2309 uReadPos = uSizeFile - uBackRead;
2310
2311 uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ? (BUFREADCOMMENT + 4) : (uLong)(uSizeFile - uReadPos);
2312 if (ZSEEK64 (*pzlib_filefunc_def, filestream, uReadPos, ZLIB_FILEFUNC_SEEK_SET) != 0)
2313 break;
2314
2315 if (ZREAD64 (*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize)
2316 break;
2317
2318 for (i = (int)uReadSize - 3; (i--) > 0;)
2319 if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) && ((*(buf + i + 2)) == 0x05) && ((*(buf + i + 3)) == 0x06)) {
2320 uPosFound = uReadPos + (unsigned)i;
2321 break;
2322 }
2323
2324 if (uPosFound != 0)
2325 break;
2326 }
2327 free (buf);
2328 return uPosFound;
2329 }
2330
2331 /*
2332Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before
2333the global comment)
2334*/
2335 ZPOS64_T zip64local_SearchCentralDir64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
2336 {
2337 unsigned char* buf;
2338 ZPOS64_T uSizeFile;
2339 ZPOS64_T uBackRead;
2340 ZPOS64_T uMaxBack = 0xffff; /* maximum size of global comment */
2341 ZPOS64_T uPosFound = 0;
2342 uLong uL;
2343 ZPOS64_T relativeOffset;
2344
2345 if (ZSEEK64 (*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
2346 return 0;
2347
2348 uSizeFile = ZTELL64 (*pzlib_filefunc_def, filestream);
2349
2350 if (uMaxBack > uSizeFile)
2351 uMaxBack = uSizeFile;
2352
2353 buf = (unsigned char*)ALLOC (BUFREADCOMMENT + 4);
2354 if (buf == NULL)
2355 return 0;
2356
2357 uBackRead = 4;
2358 while (uBackRead < uMaxBack) {
2359 uLong uReadSize;
2360 ZPOS64_T uReadPos;
2361 int i;
2362 if (uBackRead + BUFREADCOMMENT > uMaxBack)
2363 uBackRead = uMaxBack;
2364 else
2365 uBackRead += BUFREADCOMMENT;
2366 uReadPos = uSizeFile - uBackRead;
2367
2368 uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ? (BUFREADCOMMENT + 4) : (uLong)(uSizeFile - uReadPos);
2369 if (ZSEEK64 (*pzlib_filefunc_def, filestream, uReadPos, ZLIB_FILEFUNC_SEEK_SET) != 0)
2370 break;
2371
2372 if (ZREAD64 (*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize)
2373 break;
2374
2375 for (i = (int)uReadSize - 3; (i--) > 0;) {
2376 // Signature "0x07064b50" Zip64 end of central directory locater
2377 if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) && ((*(buf + i + 2)) == 0x06) && ((*(buf + i + 3)) == 0x07)) {
2378 uPosFound = uReadPos + (unsigned)i;
2379 break;
2380 }
2381 }
2382
2383 if (uPosFound != 0)
2384 break;
2385 }
2386
2387 free (buf);
2388 if (uPosFound == 0)
2389 return 0;
2390
2391 /* Zip64 end of central directory locator */
2392 if (ZSEEK64 (*pzlib_filefunc_def, filestream, uPosFound, ZLIB_FILEFUNC_SEEK_SET) != 0)
2393 return 0;
2394
2395 /* the signature, already checked */
2396 if (zip64local_getLong (pzlib_filefunc_def, filestream, &uL) != ZIP_OK)
2397 return 0;
2398
2399 /* number of the disk with the start of the zip64 end of central directory */
2400 if (zip64local_getLong (pzlib_filefunc_def, filestream, &uL) != ZIP_OK)
2401 return 0;
2402 if (uL != 0)
2403 return 0;
2404
2405 /* relative offset of the zip64 end of central directory record */
2406 if (zip64local_getLong64 (pzlib_filefunc_def, filestream, &relativeOffset) != ZIP_OK)
2407 return 0;
2408
2409 /* total number of disks */
2410 if (zip64local_getLong (pzlib_filefunc_def, filestream, &uL) != ZIP_OK)
2411 return 0;
2412 if (uL != 1)
2413 return 0;
2414
2415 /* Goto Zip64 end of central directory record */
2416 if (ZSEEK64 (*pzlib_filefunc_def, filestream, relativeOffset, ZLIB_FILEFUNC_SEEK_SET) != 0)
2417 return 0;
2418
2419 /* the signature */
2420 if (zip64local_getLong (pzlib_filefunc_def, filestream, &uL) != ZIP_OK)
2421 return 0;
2422
2423 if (uL != 0x06064b50) // signature of 'Zip64 end of central directory'
2424 return 0;
2425
2426 return relativeOffset;
2427 }
2428
2429 int LoadCentralDirectoryRecord (zip64_internal* pziinit)
2430 {
2431 int err = ZIP_OK;
2432 ZPOS64_T byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/
2433
2434 ZPOS64_T size_central_dir; /* size of the central directory */
2435 ZPOS64_T offset_central_dir; /* offset of start of central directory */
2436 ZPOS64_T central_pos;
2437 uLong uL;
2438
2439 uLong number_disk; /* number of the current disk, used for
2440 spanning ZIP, unsupported, always 0*/
2441 uLong number_disk_with_CD; /* number of the disk with central dir, used
2442 for spanning ZIP, unsupported, always 0*/
2443 ZPOS64_T number_entry;
2444 ZPOS64_T number_entry_CD; /* total number of entries in
2445 the central dir
2446 (same than number_entry on nospan) */
2447 uLong VersionMadeBy;
2448 uLong VersionNeeded;
2449 uLong size_comment;
2450
2451 int hasZIP64Record = 0;
2452
2453 // check first if we find a ZIP64 record
2454 central_pos = zip64local_SearchCentralDir64 (&pziinit->z_filefunc, pziinit->filestream);
2455 if (central_pos > 0) {
2456 hasZIP64Record = 1;
2457 }
2458 else if (central_pos == 0) {
2459 central_pos = zip64local_SearchCentralDir (&pziinit->z_filefunc, pziinit->filestream);
2460 }
2461
2462 /* disable to allow appending to empty ZIP archive
2463 if (central_pos==0)
2464 err=ZIP_ERRNO;
2465*/
2466
2467 if (hasZIP64Record) {
2468 ZPOS64_T sizeEndOfCentralDirectory;
2469 if (ZSEEK64 (pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
2470 err = ZIP_ERRNO;
2471
2472 /* the signature, already checked */
2473 if (zip64local_getLong (&pziinit->z_filefunc, pziinit->filestream, &uL) != ZIP_OK)
2474 err = ZIP_ERRNO;
2475
2476 /* size of zip64 end of central directory record */
2477 if (zip64local_getLong64 (&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory) != ZIP_OK)
2478 err = ZIP_ERRNO;
2479
2480 /* version made by */
2481 if (zip64local_getShort (&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy) != ZIP_OK)
2482 err = ZIP_ERRNO;
2483
2484 /* version needed to extract */
2485 if (zip64local_getShort (&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded) != ZIP_OK)
2486 err = ZIP_ERRNO;
2487
2488 /* number of this disk */
2489 if (zip64local_getLong (&pziinit->z_filefunc, pziinit->filestream, &number_disk) != ZIP_OK)
2490 err = ZIP_ERRNO;
2491
2492 /* number of the disk with the start of the central directory */
2493 if (zip64local_getLong (&pziinit->z_filefunc, pziinit->filestream, &number_disk_with_CD) != ZIP_OK)
2494 err = ZIP_ERRNO;
2495
2496 /* total number of entries in the central directory on this disk */
2497 if (zip64local_getLong64 (&pziinit->z_filefunc, pziinit->filestream, &number_entry) != ZIP_OK)
2498 err = ZIP_ERRNO;
2499
2500 /* total number of entries in the central directory */
2501 if (zip64local_getLong64 (&pziinit->z_filefunc, pziinit->filestream, &number_entry_CD) != ZIP_OK)
2502 err = ZIP_ERRNO;
2503
2504 if ((number_entry_CD != number_entry) || (number_disk_with_CD != 0) || (number_disk != 0))
2505 err = ZIP_BADZIPFILE;
2506
2507 /* size of the central directory */
2508 if (zip64local_getLong64 (&pziinit->z_filefunc, pziinit->filestream, &size_central_dir) != ZIP_OK)
2509 err = ZIP_ERRNO;
2510
2511 /* offset of start of central directory with respect to the
2512 starting disk number */
2513 if (zip64local_getLong64 (&pziinit->z_filefunc, pziinit->filestream, &offset_central_dir) != ZIP_OK)
2514 err = ZIP_ERRNO;
2515
2516 // TODO..
2517 // read the comment from the standard central header.
2518 size_comment = 0;
2519 }
2520 else {
2521 // Read End of central Directory info
2522 if (ZSEEK64 (pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
2523 err = ZIP_ERRNO;
2524
2525 /* the signature, already checked */
2526 if (zip64local_getLong (&pziinit->z_filefunc, pziinit->filestream, &uL) != ZIP_OK)
2527 err = ZIP_ERRNO;
2528
2529 /* number of this disk */
2530 if (zip64local_getShort (&pziinit->z_filefunc, pziinit->filestream, &number_disk) != ZIP_OK)
2531 err = ZIP_ERRNO;
2532
2533 /* number of the disk with the start of the central directory */
2534 if (zip64local_getShort (&pziinit->z_filefunc, pziinit->filestream, &number_disk_with_CD) != ZIP_OK)
2535 err = ZIP_ERRNO;
2536
2537 /* total number of entries in the central dir on this disk */
2538 number_entry = 0;
2539 if (zip64local_getShort (&pziinit->z_filefunc, pziinit->filestream, &uL) != ZIP_OK)
2540 err = ZIP_ERRNO;
2541 else
2542 number_entry = uL;
2543
2544 /* total number of entries in the central dir */
2545 number_entry_CD = 0;
2546 if (zip64local_getShort (&pziinit->z_filefunc, pziinit->filestream, &uL) != ZIP_OK)
2547 err = ZIP_ERRNO;
2548 else
2549 number_entry_CD = uL;
2550
2551 if ((number_entry_CD != number_entry) || (number_disk_with_CD != 0) || (number_disk != 0))
2552 err = ZIP_BADZIPFILE;
2553
2554 /* size of the central directory */
2555 size_central_dir = 0;
2556 if (zip64local_getLong (&pziinit->z_filefunc, pziinit->filestream, &uL) != ZIP_OK)
2557 err = ZIP_ERRNO;
2558 else
2559 size_central_dir = uL;
2560
2561 /* offset of start of central directory with respect to the starting disk number */
2562 offset_central_dir = 0;
2563 if (zip64local_getLong (&pziinit->z_filefunc, pziinit->filestream, &uL) != ZIP_OK)
2564 err = ZIP_ERRNO;
2565 else
2566 offset_central_dir = uL;
2567
2568 /* zipfile global comment length */
2569 if (zip64local_getShort (&pziinit->z_filefunc, pziinit->filestream, &size_comment) != ZIP_OK)
2570 err = ZIP_ERRNO;
2571 }
2572
2573 if ((central_pos < offset_central_dir + size_central_dir) && (err == ZIP_OK))
2574 err = ZIP_BADZIPFILE;
2575
2576 if (err != ZIP_OK) {
2577 ZCLOSE64 (pziinit->z_filefunc, pziinit->filestream);
2578 return ZIP_ERRNO;
2579 }
2580
2581 if (size_comment > 0) {
2582 pziinit->globalcomment = (char*)ALLOC (size_comment + 1);
2583 if (pziinit->globalcomment) {
2584 size_comment = ZREAD64 (pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment, size_comment);
2585 pziinit->globalcomment[size_comment] = 0;
2586 }
2587 }
2588
2589 byte_before_the_zipfile = central_pos - (offset_central_dir + size_central_dir);
2590 pziinit->add_position_when_writing_offset = byte_before_the_zipfile;
2591
2592 {
2593 ZPOS64_T size_central_dir_to_read = size_central_dir;
2594 size_t buf_size = SIZEDATA_INDATABLOCK;
2595 void* buf_read = (void*)ALLOC (buf_size);
2596 if (ZSEEK64 (pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
2597 err = ZIP_ERRNO;
2598
2599 while ((size_central_dir_to_read > 0) && (err == ZIP_OK)) {
2600 ZPOS64_T read_this = SIZEDATA_INDATABLOCK;
2601 if (read_this > size_central_dir_to_read)
2602 read_this = size_central_dir_to_read;
2603
2604 if (ZREAD64 (pziinit->z_filefunc, pziinit->filestream, buf_read, (uLong)read_this) != read_this)
2605 err = ZIP_ERRNO;
2606
2607 if (err == ZIP_OK)
2608 err = add_data_in_datablock (&pziinit->central_dir, buf_read, (uLong)read_this);
2609
2610 size_central_dir_to_read -= read_this;
2611 }
2612 free (buf_read);
2613 }
2614 pziinit->begin_pos = byte_before_the_zipfile;
2615 pziinit->number_entry = number_entry_CD;
2616
2617 if (ZSEEK64 (pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
2618 err = ZIP_ERRNO;
2619
2620 return err;
2621 }
2622
2623#endif /* !NO_ADDFILEINEXISTINGZIP*/
2624}
2625
2626/************************************************************/
2627zipFile PrivateMinizip_::zipOpen3 (const void* pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def)
2628{
2629 zip64_internal ziinit;
2630 zip64_internal* zi;
2631 int err = ZIP_OK;
2632
2633 ziinit.z_filefunc.zseek32_file = NULL;
2634 ziinit.z_filefunc.ztell32_file = NULL;
2635
2636#if 1
2637 Require (pzlib_filefunc64_32_def != NULL);
2638 ziinit.z_filefunc = *pzlib_filefunc64_32_def; // avoid importing fill_fopen64_filefunc if we can
2639#else
2640 if (pzlib_filefunc64_32_def == NULL)
2641 fill_fopen64_filefunc (&ziinit.z_filefunc.zfile_func64);
2642 else
2643 ziinit.z_filefunc = *pzlib_filefunc64_32_def;
2644#endif
2645
2646 ziinit.filestream =
2647 ZOPEN64 (ziinit.z_filefunc, pathname,
2648 (append == APPEND_STATUS_CREATE) ? (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE)
2649 : (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
2650
2651 if (ziinit.filestream == NULL)
2652 return NULL;
2653
2654 if (append == APPEND_STATUS_CREATEAFTER)
2655 ZSEEK64 (ziinit.z_filefunc, ziinit.filestream, 0, SEEK_END);
2656
2657 ziinit.begin_pos = ZTELL64 (ziinit.z_filefunc, ziinit.filestream);
2658 ziinit.in_opened_file_inzip = 0;
2659 ziinit.ci.stream_initialised = 0;
2660 ziinit.number_entry = 0;
2661 ziinit.add_position_when_writing_offset = 0;
2662 init_linkedlist (&(ziinit.central_dir));
2663
2664 zi = (zip64_internal*)ALLOC (sizeof (zip64_internal));
2665 if (zi == NULL) {
2666 ZCLOSE64 (ziinit.z_filefunc, ziinit.filestream);
2667 return NULL;
2668 }
2669
2670 /* now we add file in a zipfile */
2671#ifndef NO_ADDFILEINEXISTINGZIP
2672 ziinit.globalcomment = NULL;
2673 if (append == APPEND_STATUS_ADDINZIP) {
2674 // Read and Cache Central Directory Records
2675 err = LoadCentralDirectoryRecord (&ziinit);
2676 }
2677
2678 if (globalcomment) {
2679 *globalcomment = ziinit.globalcomment;
2680 }
2681#endif /* !NO_ADDFILEINEXISTINGZIP*/
2682
2683 if (err != ZIP_OK) {
2684#ifndef NO_ADDFILEINEXISTINGZIP
2685 free (ziinit.globalcomment);
2686#endif /* !NO_ADDFILEINEXISTINGZIP*/
2687 free (zi);
2688 return NULL;
2689 }
2690 else {
2691 *zi = ziinit;
2692 return (zipFile)zi;
2693 }
2694}
2695
2696zipFile PrivateMinizip_::zipOpen2 (const char* pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def)
2697{
2698 if (pzlib_filefunc32_def != NULL) {
2699 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
2700 fill_zlib_filefunc64_32_def_from_filefunc32 (&zlib_filefunc64_32_def_fill, pzlib_filefunc32_def);
2701 return zipOpen3 (pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
2702 }
2703 else
2704 return zipOpen3 (pathname, append, globalcomment, NULL);
2705}
2706
2707zipFile PrivateMinizip_::zipOpen2_64 (const void* pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def)
2708{
2709 if (pzlib_filefunc_def != NULL) {
2710 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
2711 zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
2712 zlib_filefunc64_32_def_fill.ztell32_file = NULL;
2713 zlib_filefunc64_32_def_fill.zseek32_file = NULL;
2714 return zipOpen3 (pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
2715 }
2716 else
2717 return zipOpen3 (pathname, append, globalcomment, NULL);
2718}
2719
2720zipFile PrivateMinizip_::zipOpen (const char* pathname, int append)
2721{
2722 return zipOpen3 ((const void*)pathname, append, NULL, NULL);
2723}
2724
2725zipFile PrivateMinizip_::zipOpen64 (const void* pathname, int append)
2726{
2727 return zipOpen3 (pathname, append, NULL, NULL);
2728}
2729
2730namespace {
2731
2732 int Write_LocalFileHeader (zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local)
2733 {
2734 /* write the local header */
2735 int err;
2736 uInt size_filename = (uInt)strlen (filename);
2737 uInt size_extrafield = size_extrafield_local;
2738
2739 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)LOCALHEADERMAGIC, 4);
2740
2741 if (err == ZIP_OK) {
2742 if (zi->ci.zip64)
2743 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)45, 2); /* version needed to extract */
2744 else
2745 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)20, 2); /* version needed to extract */
2746 }
2747
2748 if (err == ZIP_OK)
2749 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)zi->ci.flag, 2);
2750
2751 if (err == ZIP_OK)
2752 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)zi->ci.method, 2);
2753
2754 if (err == ZIP_OK)
2755 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)zi->ci.dosDate, 4);
2756
2757 // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
2758 if (err == ZIP_OK)
2759 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0, 4); /* crc 32, unknown */
2760 if (err == ZIP_OK) {
2761 if (zi->ci.zip64)
2762 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0xFFFFFFFF, 4); /* compressed size, unknown */
2763 else
2764 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0, 4); /* compressed size, unknown */
2765 }
2766 if (err == ZIP_OK) {
2767 if (zi->ci.zip64)
2768 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0xFFFFFFFF, 4); /* uncompressed size, unknown */
2769 else
2770 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0, 4); /* uncompressed size, unknown */
2771 }
2772
2773 if (err == ZIP_OK)
2774 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)size_filename, 2);
2775
2776 if (zi->ci.zip64) {
2777 size_extrafield += 20;
2778 }
2779
2780 if (err == ZIP_OK)
2781 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)size_extrafield, 2);
2782
2783 if ((err == ZIP_OK) && (size_filename > 0)) {
2784 if (ZWRITE64 (zi->z_filefunc, zi->filestream, filename, size_filename) != size_filename)
2785 err = ZIP_ERRNO;
2786 }
2787
2788 if ((err == ZIP_OK) && (size_extrafield_local > 0)) {
2789 if (ZWRITE64 (zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local)
2790 err = ZIP_ERRNO;
2791 }
2792
2793 if ((err == ZIP_OK) && (zi->ci.zip64)) {
2794 // write the Zip64 extended info
2795 constexpr short HeaderID = 1;
2796 constexpr short DataSize = 16;
2797 constexpr ZPOS64_T CompressedSize = 0;
2798 constexpr ZPOS64_T UncompressedSize = 0;
2799
2800 // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file)
2801 zi->ci.pos_zip64extrainfo = ZTELL64 (zi->z_filefunc, zi->filestream);
2802
2803 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID, 2);
2804 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (ZPOS64_T)DataSize, 2);
2805
2806 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize, 8);
2807 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize, 8);
2808 }
2809
2810 return err;
2811 }
2812}
2813/*
2814 NOTE.
2815 When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped
2816 before calling this function it can be done with zipRemoveExtraInfoBlock
2817
2818 It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize
2819 unnecessary allocations.
2820 */
2821int PrivateMinizip_::zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local,
2822 uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global,
2823 const char* comment, int method, int level, int raw, int windowBits, int memLevel, int strategy,
2824 const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase, int zip64)
2825{
2826 zip64_internal* zi;
2827 uInt size_filename;
2828 uInt size_comment;
2829 uInt i;
2830 int err = ZIP_OK;
2831
2832#ifdef NOCRYPT
2833 (crcForCrypting);
2834 if (password != NULL)
2835 return ZIP_PARAMERROR;
2836#endif
2837
2838 if (file == NULL)
2839 return ZIP_PARAMERROR;
2840
2841#ifdef HAVE_BZIP2
2842 if ((method != 0) && (method != Z_DEFLATED) && (method != Z_BZIP2ED))
2843 return ZIP_PARAMERROR;
2844#else
2845 if ((method != 0) && (method != Z_DEFLATED))
2846 return ZIP_PARAMERROR;
2847#endif
2848
2849 // The filename and comment length must fit in 16 bits.
2850 if ((filename != NULL) && (strlen (filename) > 0xffff))
2851 return ZIP_PARAMERROR;
2852 if ((comment != NULL) && (strlen (comment) > 0xffff))
2853 return ZIP_PARAMERROR;
2854 // The extra field length must fit in 16 bits. If the member also requires
2855 // a Zip64 extra block, that will also need to fit within that 16-bit
2856 // length, but that will be checked for later.
2857 if ((size_extrafield_local > 0xffff) || (size_extrafield_global > 0xffff))
2858 return ZIP_PARAMERROR;
2859
2860 zi = (zip64_internal*)file;
2861
2862 if (zi->in_opened_file_inzip == 1) {
2863 err = zipCloseFileInZip (file);
2864 if (err != ZIP_OK)
2865 return err;
2866 }
2867
2868 if (filename == NULL)
2869 filename = "-";
2870
2871 if (comment == NULL)
2872 size_comment = 0;
2873 else
2874 size_comment = (uInt)strlen (comment);
2875
2876 size_filename = (uInt)strlen (filename);
2877
2878 if (zipfi == NULL)
2879 zi->ci.dosDate = 0;
2880 else {
2881 if (zipfi->dosDate != 0)
2882 zi->ci.dosDate = zipfi->dosDate;
2883 else
2884 zi->ci.dosDate = zip64local_TmzDateToDosDate (&zipfi->tmz_date);
2885 }
2886
2887 zi->ci.flag = flagBase;
2888 if ((level == 8) || (level == 9))
2889 zi->ci.flag |= 2;
2890 if (level == 2)
2891 zi->ci.flag |= 4;
2892 if (level == 1)
2893 zi->ci.flag |= 6;
2894 if (password != NULL)
2895 zi->ci.flag |= 1;
2896
2897 zi->ci.crc32 = 0;
2898 zi->ci.method = method;
2899 zi->ci.encrypt = 0;
2900 zi->ci.stream_initialised = 0;
2901 zi->ci.pos_in_buffered_data = 0;
2902 zi->ci.raw = raw;
2903 zi->ci.pos_local_header = ZTELL64 (zi->z_filefunc, zi->filestream);
2904
2905 zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment;
2906 zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data
2907
2908 zi->ci.central_header = (char*)ALLOC ((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree);
2909
2910 zi->ci.size_centralExtra = size_extrafield_global;
2911 zip64local_putValue_inmemory (zi->ci.central_header, (uLong)CENTRALHEADERMAGIC, 4);
2912 /* version info */
2913 zip64local_putValue_inmemory (zi->ci.central_header + 4, (uLong)versionMadeBy, 2);
2914 zip64local_putValue_inmemory (zi->ci.central_header + 6, (uLong)20, 2);
2915 zip64local_putValue_inmemory (zi->ci.central_header + 8, (uLong)zi->ci.flag, 2);
2916 zip64local_putValue_inmemory (zi->ci.central_header + 10, (uLong)zi->ci.method, 2);
2917 zip64local_putValue_inmemory (zi->ci.central_header + 12, (uLong)zi->ci.dosDate, 4);
2918 zip64local_putValue_inmemory (zi->ci.central_header + 16, (uLong)0, 4); /*crc*/
2919 zip64local_putValue_inmemory (zi->ci.central_header + 20, (uLong)0, 4); /*compr size*/
2920 zip64local_putValue_inmemory (zi->ci.central_header + 24, (uLong)0, 4); /*uncompr size*/
2921 zip64local_putValue_inmemory (zi->ci.central_header + 28, (uLong)size_filename, 2);
2922 zip64local_putValue_inmemory (zi->ci.central_header + 30, (uLong)size_extrafield_global, 2);
2923 zip64local_putValue_inmemory (zi->ci.central_header + 32, (uLong)size_comment, 2);
2924 zip64local_putValue_inmemory (zi->ci.central_header + 34, (uLong)0, 2); /*disk nm start*/
2925
2926 if (zipfi == NULL)
2927 zip64local_putValue_inmemory (zi->ci.central_header + 36, (uLong)0, 2);
2928 else
2929 zip64local_putValue_inmemory (zi->ci.central_header + 36, (uLong)zipfi->internal_fa, 2);
2930
2931 if (zipfi == NULL)
2932 zip64local_putValue_inmemory (zi->ci.central_header + 38, (uLong)0, 4);
2933 else
2934 zip64local_putValue_inmemory (zi->ci.central_header + 38, (uLong)zipfi->external_fa, 4);
2935
2936 if (zi->ci.pos_local_header >= 0xffffffff)
2937 zip64local_putValue_inmemory (zi->ci.central_header + 42, (uLong)0xffffffff, 4);
2938 else
2939 zip64local_putValue_inmemory (zi->ci.central_header + 42, (uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset, 4);
2940
2941 for (i = 0; i < size_filename; i++)
2942 *(zi->ci.central_header + SIZECENTRALHEADER + i) = *(filename + i);
2943
2944 for (i = 0; i < size_extrafield_global; i++)
2945 *(zi->ci.central_header + SIZECENTRALHEADER + size_filename + i) = *(((const char*)extrafield_global) + i);
2946
2947 for (i = 0; i < size_comment; i++)
2948 *(zi->ci.central_header + SIZECENTRALHEADER + size_filename + size_extrafield_global + i) = *(comment + i);
2949 if (zi->ci.central_header == NULL)
2950 return ZIP_INTERNALERROR;
2951
2952 zi->ci.zip64 = zip64;
2953 zi->ci.totalCompressedData = 0;
2954 zi->ci.totalUncompressedData = 0;
2955 zi->ci.pos_zip64extrainfo = 0;
2956
2957 err = Write_LocalFileHeader (zi, filename, size_extrafield_local, extrafield_local);
2958
2959#ifdef HAVE_BZIP2
2960 zi->ci.bstream.avail_in = (uInt)0;
2961 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
2962 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
2963 zi->ci.bstream.total_in_hi32 = 0;
2964 zi->ci.bstream.total_in_lo32 = 0;
2965 zi->ci.bstream.total_out_hi32 = 0;
2966 zi->ci.bstream.total_out_lo32 = 0;
2967#endif
2968
2969 zi->ci.stream.avail_in = (uInt)0;
2970 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
2971 zi->ci.stream.next_out = zi->ci.buffered_data;
2972 zi->ci.stream.total_in = 0;
2973 zi->ci.stream.total_out = 0;
2974 zi->ci.stream.data_type = Z_BINARY;
2975
2976#ifdef HAVE_BZIP2
2977 if ((err == ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
2978#else
2979 if ((err == ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
2980#endif
2981 {
2982 if (zi->ci.method == Z_DEFLATED) {
2983 zi->ci.stream.zalloc = (alloc_func)0;
2984 zi->ci.stream.zfree = (free_func)0;
2985 zi->ci.stream.opaque = (voidpf)0;
2986
2987 if (windowBits > 0)
2988 windowBits = -windowBits;
2989
2990 err = deflateInit2 (&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy);
2991
2992 if (err == Z_OK)
2993 zi->ci.stream_initialised = Z_DEFLATED;
2994 }
2995 else if (zi->ci.method == Z_BZIP2ED) {
2996#ifdef HAVE_BZIP2
2997 // Init BZip stuff here
2998 zi->ci.bstream.bzalloc = 0;
2999 zi->ci.bstream.bzfree = 0;
3000 zi->ci.bstream.opaque = (voidpf)0;
3001
3002 err = BZ2_bzCompressInit (&zi->ci.bstream, level, 0, 35);
3003 if (err == BZ_OK)
3004 zi->ci.stream_initialised = Z_BZIP2ED;
3005#endif
3006 }
3007 }
3008
3009#ifndef NOCRYPT
3010 zi->ci.crypt_header_size = 0;
3011 if ((err == Z_OK) && (password != NULL)) {
3012 unsigned char bufHead[RAND_HEAD_LEN];
3013 unsigned int sizeHead;
3014 zi->ci.encrypt = 1;
3015 zi->ci.pcrc_32_tab = get_crc_table ();
3016 /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
3017
3018 sizeHead = crypthead (password, bufHead, RAND_HEAD_LEN, zi->ci.keys, zi->ci.pcrc_32_tab, crcForCrypting);
3019 zi->ci.crypt_header_size = sizeHead;
3020
3021 if (ZWRITE64 (zi->z_filefunc, zi->filestream, bufHead, sizeHead) != sizeHead)
3022 err = ZIP_ERRNO;
3023 }
3024#endif
3025
3026 if (err == Z_OK)
3027 zi->in_opened_file_inzip = 1;
3028 return err;
3029}
3030
3031int PrivateMinizip_::zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local,
3032 uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global,
3033 const char* comment, int method, int level, int raw, int windowBits, int memLevel, int strategy,
3034 const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase)
3035{
3036 return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment,
3037 method, level, raw, windowBits, memLevel, strategy, password, crcForCrypting, versionMadeBy, flagBase, 0);
3038}
3039
3040int PrivateMinizip_::zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local,
3041 uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global,
3042 const char* comment, int method, int level, int raw, int windowBits, int memLevel, int strategy,
3043 const char* password, uLong crcForCrypting)
3044{
3045 return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global,
3046 comment, method, level, raw, windowBits, memLevel, strategy, password, crcForCrypting, VERSIONMADEBY, 0, 0);
3047}
3048
3049int PrivateMinizip_::zipOpenNewFileInZip3_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local,
3050 uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global,
3051 const char* comment, int method, int level, int raw, int windowBits, int memLevel,
3052 int strategy, const char* password, uLong crcForCrypting, int zip64)
3053{
3054 return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global,
3055 comment, method, level, raw, windowBits, memLevel, strategy, password, crcForCrypting, VERSIONMADEBY, 0, zip64);
3056}
3057
3058int PrivateMinizip_::zipOpenNewFileInZip2 (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local,
3059 uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global,
3060 const char* comment, int method, int level, int raw)
3061{
3062 return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global,
3063 comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, 0);
3064}
3065
3066int PrivateMinizip_::zipOpenNewFileInZip2_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local,
3067 uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global,
3068 const char* comment, int method, int level, int raw, int zip64)
3069{
3070 return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global,
3071 comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, zip64);
3072}
3073
3074int PrivateMinizip_::zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local,
3075 uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global,
3076 const char* comment, int method, int level, int zip64)
3077{
3078 return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global,
3079 comment, method, level, 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, zip64);
3080}
3081
3082int PrivateMinizip_::zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local,
3083 uInt size_extrafield_local, const void* extrafield_global, uInt size_extrafield_global,
3084 const char* comment, int method, int level)
3085{
3086 return zipOpenNewFileInZip4_64 (file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global,
3087 comment, method, level, 0, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, 0);
3088}
3089
3090namespace {
3091
3092 int zip64FlushWriteBuffer (zip64_internal* zi)
3093 {
3094 int err = ZIP_OK;
3095
3096 if (zi->ci.encrypt != 0) {
3097#ifndef NOCRYPT
3098 uInt i;
3099 int t;
3100 DISABLE_COMPILER_MSC_WARNING_START (4244) // warning C4244: '=': conversion from 'int' to 'Byte', possible loss of data
3101 for (i = 0; i < zi->ci.pos_in_buffered_data; i++)
3102 zi->ci.buffered_data[i] = zencode (zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i], t);
3103 DISABLE_COMPILER_MSC_WARNING_END (4244)
3104#endif
3105 }
3106
3107 if (ZWRITE64 (zi->z_filefunc, zi->filestream, zi->ci.buffered_data, zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data)
3108 err = ZIP_ERRNO;
3109
3110 zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data;
3111
3112#ifdef HAVE_BZIP2
3113 if (zi->ci.method == Z_BZIP2ED) {
3114 zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32;
3115 zi->ci.bstream.total_in_lo32 = 0;
3116 zi->ci.bstream.total_in_hi32 = 0;
3117 }
3118 else
3119#endif
3120 {
3121 zi->ci.totalUncompressedData += zi->ci.stream.total_in;
3122 zi->ci.stream.total_in = 0;
3123 }
3124
3125 zi->ci.pos_in_buffered_data = 0;
3126
3127 return err;
3128 }
3129}
3130
3131int PrivateMinizip_::zipWriteInFileInZip (zipFile file, const void* buf, unsigned int len)
3132{
3133 zip64_internal* zi;
3134 int err = ZIP_OK;
3135
3136 if (file == NULL)
3137 return ZIP_PARAMERROR;
3138 zi = (zip64_internal*)file;
3139
3140 if (zi->in_opened_file_inzip == 0)
3141 return ZIP_PARAMERROR;
3142
3143 zi->ci.crc32 = crc32 (zi->ci.crc32, reinterpret_cast<const Bytef*> (buf), (uInt)len);
3144
3145#ifdef HAVE_BZIP2
3146 if (zi->ci.method == Z_BZIP2ED && (!zi->ci.raw)) {
3147 zi->ci.bstream.next_in = (void*)buf;
3148 zi->ci.bstream.avail_in = len;
3149 err = BZ_RUN_OK;
3150
3151 while ((err == BZ_RUN_OK) && (zi->ci.bstream.avail_in > 0)) {
3152 if (zi->ci.bstream.avail_out == 0) {
3153 if (zip64FlushWriteBuffer (zi) == ZIP_ERRNO)
3154 err = ZIP_ERRNO;
3155 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
3156 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
3157 }
3158
3159 if (err != BZ_RUN_OK)
3160 break;
3161
3162 if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) {
3163 uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32;
3164 // uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32;
3165 err = BZ2_bzCompress (&zi->ci.bstream, BZ_RUN);
3166
3167 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo);
3168 }
3169 }
3170
3171 if (err == BZ_RUN_OK)
3172 err = ZIP_OK;
3173 }
3174 else
3175#endif
3176 {
3177 zi->ci.stream.next_in = (Bytef*)(uintptr_t)buf;
3178 zi->ci.stream.avail_in = len;
3179
3180 while ((err == ZIP_OK) && (zi->ci.stream.avail_in > 0)) {
3181 if (zi->ci.stream.avail_out == 0) {
3182 if (zip64FlushWriteBuffer (zi) == ZIP_ERRNO)
3183 err = ZIP_ERRNO;
3184 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
3185 zi->ci.stream.next_out = zi->ci.buffered_data;
3186 }
3187
3188 if (err != ZIP_OK)
3189 break;
3190
3191 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) {
3192 uLong uTotalOutBefore = zi->ci.stream.total_out;
3193 err = deflate (&zi->ci.stream, Z_NO_FLUSH);
3194
3195 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore);
3196 }
3197 else {
3198 uInt copy_this, i;
3199 if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
3200 copy_this = zi->ci.stream.avail_in;
3201 else
3202 copy_this = zi->ci.stream.avail_out;
3203
3204 for (i = 0; i < copy_this; i++)
3205 *(((char*)zi->ci.stream.next_out) + i) = *(((const char*)zi->ci.stream.next_in) + i);
3206 {
3207 zi->ci.stream.avail_in -= copy_this;
3208 zi->ci.stream.avail_out -= copy_this;
3209 zi->ci.stream.next_in += copy_this;
3210 zi->ci.stream.next_out += copy_this;
3211 zi->ci.stream.total_in += copy_this;
3212 zi->ci.stream.total_out += copy_this;
3213 zi->ci.pos_in_buffered_data += copy_this;
3214 }
3215 }
3216 } // while(...)
3217 }
3218
3219 return err;
3220}
3221
3222int PrivateMinizip_::zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32)
3223{
3224 return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32);
3225}
3226
3227int PrivateMinizip_::zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32)
3228{
3229 zip64_internal* zi;
3230 ZPOS64_T compressed_size;
3231 uLong invalidValue = 0xffffffff;
3232 unsigned datasize = 0;
3233 int err = ZIP_OK;
3234
3235 if (file == NULL)
3236 return ZIP_PARAMERROR;
3237 zi = (zip64_internal*)file;
3238
3239 if (zi->in_opened_file_inzip == 0)
3240 return ZIP_PARAMERROR;
3241 zi->ci.stream.avail_in = 0;
3242
3243 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) {
3244 while (err == ZIP_OK) {
3245 uLong uTotalOutBefore;
3246 if (zi->ci.stream.avail_out == 0) {
3247 if (zip64FlushWriteBuffer (zi) == ZIP_ERRNO)
3248 err = ZIP_ERRNO;
3249 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
3250 zi->ci.stream.next_out = zi->ci.buffered_data;
3251 }
3252 uTotalOutBefore = zi->ci.stream.total_out;
3253 err = deflate (&zi->ci.stream, Z_FINISH);
3254 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore);
3255 }
3256 }
3257 else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) {
3258#ifdef HAVE_BZIP2
3259 err = BZ_FINISH_OK;
3260 while (err == BZ_FINISH_OK) {
3261 uLong uTotalOutBefore;
3262 if (zi->ci.bstream.avail_out == 0) {
3263 if (zip64FlushWriteBuffer (zi) == ZIP_ERRNO)
3264 err = ZIP_ERRNO;
3265 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
3266 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
3267 }
3268 uTotalOutBefore = zi->ci.bstream.total_out_lo32;
3269 err = BZ2_bzCompress (&zi->ci.bstream, BZ_FINISH);
3270 if (err == BZ_STREAM_END)
3271 err = Z_STREAM_END;
3272
3273 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore);
3274 }
3275
3276 if (err == BZ_FINISH_OK)
3277 err = ZIP_OK;
3278#endif
3279 }
3280
3281 if (err == Z_STREAM_END)
3282 err = ZIP_OK; /* this is normal */
3283
3284 if ((zi->ci.pos_in_buffered_data > 0) && (err == ZIP_OK)) {
3285 if (zip64FlushWriteBuffer (zi) == ZIP_ERRNO)
3286 err = ZIP_ERRNO;
3287 }
3288
3289 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) {
3290 int tmp_err = deflateEnd (&zi->ci.stream);
3291 if (err == ZIP_OK)
3292 err = tmp_err;
3293 zi->ci.stream_initialised = 0;
3294 }
3295#ifdef HAVE_BZIP2
3296 else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) {
3297 int tmperr = BZ2_bzCompressEnd (&zi->ci.bstream);
3298 if (err == ZIP_OK)
3299 err = tmperr;
3300 zi->ci.stream_initialised = 0;
3301 }
3302#endif
3303
3304 if (!zi->ci.raw) {
3305 crc32 = (uLong)zi->ci.crc32;
3306 uncompressed_size = zi->ci.totalUncompressedData;
3307 }
3308 compressed_size = zi->ci.totalCompressedData;
3309
3310#ifndef NOCRYPT
3311 compressed_size += zi->ci.crypt_header_size;
3312#endif
3313
3314 // update Current Item crc and sizes,
3315 if (compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) {
3316 /*version Made by*/
3317 zip64local_putValue_inmemory (zi->ci.central_header + 4, (uLong)45, 2);
3318 /*version needed*/
3319 zip64local_putValue_inmemory (zi->ci.central_header + 6, (uLong)45, 2);
3320 }
3321
3322 zip64local_putValue_inmemory (zi->ci.central_header + 16, crc32, 4); /*crc*/
3323
3324 if (compressed_size >= 0xffffffff)
3325 zip64local_putValue_inmemory (zi->ci.central_header + 20, invalidValue, 4); /*compr size*/
3326 else
3327 zip64local_putValue_inmemory (zi->ci.central_header + 20, compressed_size, 4); /*compr size*/
3328
3329 /// set internal file attributes field
3330 if (zi->ci.stream.data_type == Z_ASCII)
3331 zip64local_putValue_inmemory (zi->ci.central_header + 36, (uLong)Z_ASCII, 2);
3332
3333 if (uncompressed_size >= 0xffffffff)
3334 zip64local_putValue_inmemory (zi->ci.central_header + 24, invalidValue, 4); /*uncompr size*/
3335 else
3336 zip64local_putValue_inmemory (zi->ci.central_header + 24, uncompressed_size, 4); /*uncompr size*/
3337
3338 // Add ZIP64 extra info field for uncompressed size
3339 if (uncompressed_size >= 0xffffffff)
3340 datasize += 8;
3341
3342 // Add ZIP64 extra info field for compressed size
3343 if (compressed_size >= 0xffffffff)
3344 datasize += 8;
3345
3346 // Add ZIP64 extra info field for relative offset to local file header of current file
3347 if (zi->ci.pos_local_header >= 0xffffffff)
3348 datasize += 8;
3349
3350 if (datasize > 0) {
3351 char* p = NULL;
3352
3353 if ((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) {
3354 // we cannot write more data to the buffer that we have room for.
3355 return ZIP_BADZIPFILE;
3356 }
3357
3358 p = zi->ci.central_header + zi->ci.size_centralheader;
3359
3360 // Add Extra Information Header for 'ZIP64 information'
3361 zip64local_putValue_inmemory (p, 0x0001, 2); // HeaderID
3362 p += 2;
3363 zip64local_putValue_inmemory (p, datasize, 2); // DataSize
3364 p += 2;
3365
3366 if (uncompressed_size >= 0xffffffff) {
3367 zip64local_putValue_inmemory (p, uncompressed_size, 8);
3368 p += 8;
3369 }
3370
3371 if (compressed_size >= 0xffffffff) {
3372 zip64local_putValue_inmemory (p, compressed_size, 8);
3373 p += 8;
3374 }
3375
3376 if (zi->ci.pos_local_header >= 0xffffffff) {
3377 zip64local_putValue_inmemory (p, zi->ci.pos_local_header, 8);
3378 p += 8;
3379 }
3380
3381 // Update how much extra free space we got in the memory buffer
3382 // and increase the centralheader size so the new ZIP64 fields are included
3383 // ( 4 below is the size of HeaderID and DataSize field )
3384 zi->ci.size_centralExtraFree -= datasize + 4;
3385 zi->ci.size_centralheader += datasize + 4;
3386
3387 // Update the extra info size field
3388 zi->ci.size_centralExtra += datasize + 4;
3389 zip64local_putValue_inmemory (zi->ci.central_header + 30, (uLong)zi->ci.size_centralExtra, 2);
3390 }
3391
3392 if (err == ZIP_OK)
3393 err = add_data_in_datablock (&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader);
3394
3395 free (zi->ci.central_header);
3396
3397 if (err == ZIP_OK) {
3398 // Update the LocalFileHeader with the new values.
3399
3400 ZPOS64_T cur_pos_inzip = ZTELL64 (zi->z_filefunc, zi->filestream);
3401
3402 if (ZSEEK64 (zi->z_filefunc, zi->filestream, zi->ci.pos_local_header + 14, ZLIB_FILEFUNC_SEEK_SET) != 0)
3403 err = ZIP_ERRNO;
3404
3405 if (err == ZIP_OK)
3406 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, crc32, 4); /* crc 32, unknown */
3407
3408 if (uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff) {
3409 if (zi->ci.pos_zip64extrainfo > 0) {
3410 // Update the size in the ZIP64 extended field.
3411 if (ZSEEK64 (zi->z_filefunc, zi->filestream, zi->ci.pos_zip64extrainfo + 4, ZLIB_FILEFUNC_SEEK_SET) != 0)
3412 err = ZIP_ERRNO;
3413
3414 if (err == ZIP_OK) /* compressed size, unknown */
3415 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, uncompressed_size, 8);
3416
3417 if (err == ZIP_OK) /* uncompressed size, unknown */
3418 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, compressed_size, 8);
3419 }
3420 else
3421 err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal
3422 }
3423 else {
3424 if (err == ZIP_OK) /* compressed size, unknown */
3425 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, compressed_size, 4);
3426
3427 if (err == ZIP_OK) /* uncompressed size, unknown */
3428 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, uncompressed_size, 4);
3429 }
3430
3431 if (ZSEEK64 (zi->z_filefunc, zi->filestream, cur_pos_inzip, ZLIB_FILEFUNC_SEEK_SET) != 0)
3432 err = ZIP_ERRNO;
3433 }
3434
3435 zi->number_entry++;
3436 zi->in_opened_file_inzip = 0;
3437
3438 return err;
3439}
3440
3441int PrivateMinizip_::zipCloseFileInZip (zipFile file)
3442{
3443 return zipCloseFileInZipRaw (file, 0, 0);
3444}
3445
3446namespace {
3447
3448 int Write_Zip64EndOfCentralDirectoryLocator (zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip)
3449 {
3450 int err = ZIP_OK;
3451 ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset;
3452
3453 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)ZIP64ENDLOCHEADERMAGIC, 4);
3454
3455 /*num disks*/
3456 if (err == ZIP_OK) /* number of the disk with the start of the central directory */
3457 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0, 4);
3458
3459 /*relative offset*/
3460 if (err == ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */
3461 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, pos, 8);
3462
3463 /*total disks*/ /* Do not support spawning of disk so always say 1 here*/
3464 if (err == ZIP_OK) /* number of the disk with the start of the central directory */
3465 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)1, 4);
3466
3467 return err;
3468 }
3469
3470 int Write_Zip64EndOfCentralDirectoryRecord (zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
3471 {
3472 int err = ZIP_OK;
3473
3474 uLong Zip64DataSize = 44;
3475
3476 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)ZIP64ENDHEADERMAGIC, 4);
3477
3478 if (err == ZIP_OK) /* size of this 'zip64 end of central directory' */
3479 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (ZPOS64_T)Zip64DataSize, 8); // why ZPOS64_T of this ?
3480
3481 if (err == ZIP_OK) /* version made by */
3482 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)45, 2);
3483
3484 if (err == ZIP_OK) /* version needed */
3485 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)45, 2);
3486
3487 if (err == ZIP_OK) /* number of this disk */
3488 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0, 4);
3489
3490 if (err == ZIP_OK) /* number of the disk with the start of the central directory */
3491 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0, 4);
3492
3493 if (err == ZIP_OK) /* total number of entries in the central dir on this disk */
3494 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
3495
3496 if (err == ZIP_OK) /* total number of entries in the central dir */
3497 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
3498
3499 if (err == ZIP_OK) /* size of the central directory */
3500 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (ZPOS64_T)size_centraldir, 8);
3501
3502 if (err == ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
3503 {
3504 ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
3505 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (ZPOS64_T)pos, 8);
3506 }
3507 return err;
3508 }
3509
3510 int Write_EndOfCentralDirectoryRecord (zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
3511 {
3512 int err = ZIP_OK;
3513
3514 /*signature*/
3515 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)ENDHEADERMAGIC, 4);
3516
3517 if (err == ZIP_OK) /* number of this disk */
3518 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0, 2);
3519
3520 if (err == ZIP_OK) /* number of the disk with the start of the central directory */
3521 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0, 2);
3522
3523 if (err == ZIP_OK) /* total number of entries in the central dir on this disk */
3524 {
3525 {
3526 if (zi->number_entry >= 0xFFFF)
3527 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0xffff, 2); // use value in ZIP64 record
3528 else
3529 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)zi->number_entry, 2);
3530 }
3531 }
3532
3533 if (err == ZIP_OK) /* total number of entries in the central dir */
3534 {
3535 if (zi->number_entry >= 0xFFFF)
3536 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0xffff, 2); // use value in ZIP64 record
3537 else
3538 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)zi->number_entry, 2);
3539 }
3540
3541 if (err == ZIP_OK) /* size of the central directory */
3542 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)size_centraldir, 4);
3543
3544 if (err == ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
3545 {
3546 ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
3547 if (pos >= 0xffffffff) {
3548 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)0xffffffff, 4);
3549 }
3550 else
3551 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset), 4);
3552 }
3553
3554 return err;
3555 }
3556
3557 int Write_GlobalComment (zip64_internal* zi, const char* global_comment)
3558 {
3559 int err = ZIP_OK;
3560 uInt size_global_comment = 0;
3561
3562 if (global_comment != NULL)
3563 size_global_comment = (uInt)strlen (global_comment);
3564
3565 err = zip64local_putValue (&zi->z_filefunc, zi->filestream, (uLong)size_global_comment, 2);
3566
3567 if (err == ZIP_OK && size_global_comment > 0) {
3568 if (ZWRITE64 (zi->z_filefunc, zi->filestream, global_comment, size_global_comment) != size_global_comment)
3569 err = ZIP_ERRNO;
3570 }
3571 return err;
3572 }
3573}
3574
3575int PrivateMinizip_::zipClose (zipFile file, const char* global_comment)
3576{
3577 zip64_internal* zi;
3578 int err = 0;
3579 uLong size_centraldir = 0;
3580 ZPOS64_T centraldir_pos_inzip;
3581 ZPOS64_T pos;
3582
3583 if (file == NULL)
3584 return ZIP_PARAMERROR;
3585
3586 zi = (zip64_internal*)file;
3587
3588 if (zi->in_opened_file_inzip == 1) {
3589 err = zipCloseFileInZip (file);
3590 }
3591
3592#ifndef NO_ADDFILEINEXISTINGZIP
3593 if (global_comment == NULL)
3594 global_comment = zi->globalcomment;
3595#endif
3596
3597 centraldir_pos_inzip = ZTELL64 (zi->z_filefunc, zi->filestream);
3598
3599 if (err == ZIP_OK) {
3600 linkedlist_datablock_internal* ldi = zi->central_dir.first_block;
3601 while (ldi != NULL) {
3602 if ((err == ZIP_OK) && (ldi->filled_in_this_block > 0)) {
3603 if (ZWRITE64 (zi->z_filefunc, zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block)
3604 err = ZIP_ERRNO;
3605 }
3606
3607 size_centraldir += ldi->filled_in_this_block;
3608 ldi = ldi->next_datablock;
3609 }
3610 }
3611 free_linkedlist (&(zi->central_dir));
3612
3613 pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
3614 if (pos >= 0xffffffff || zi->number_entry >= 0xFFFF) {
3615 ZPOS64_T Zip64EOCDpos = ZTELL64 (zi->z_filefunc, zi->filestream);
3616 Write_Zip64EndOfCentralDirectoryRecord (zi, size_centraldir, centraldir_pos_inzip);
3617
3618 Write_Zip64EndOfCentralDirectoryLocator (zi, Zip64EOCDpos);
3619 }
3620
3621 if (err == ZIP_OK)
3622 err = Write_EndOfCentralDirectoryRecord (zi, size_centraldir, centraldir_pos_inzip);
3623
3624 if (err == ZIP_OK)
3625 err = Write_GlobalComment (zi, global_comment);
3626
3627 if (ZCLOSE64 (zi->z_filefunc, zi->filestream) != 0)
3628 if (err == ZIP_OK)
3629 err = ZIP_ERRNO;
3630
3631#ifndef NO_ADDFILEINEXISTINGZIP
3632 free (zi->globalcomment);
3633#endif
3634 free (zi);
3635
3636 return err;
3637}
3638
3639int PrivateMinizip_::zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader)
3640{
3641 char* p = pData;
3642 int size = 0;
3643 char* pNewHeader;
3644 char* pTmp;
3645 short header;
3646 short dataSize;
3647
3648 int retVal = ZIP_OK;
3649
3650 if (pData == NULL || dataLen == NULL || *dataLen < 4)
3651 return ZIP_PARAMERROR;
3652
3653 pNewHeader = (char*)ALLOC ((unsigned)*dataLen);
3654 pTmp = pNewHeader;
3655
3656 while (p < (pData + *dataLen)) {
3657 header = *(short*)p;
3658 dataSize = *(((short*)p) + 1);
3659
3660 if (header == sHeader) // Header found.
3661 {
3662 p += dataSize + 4; // skip it. do not copy to temp buffer
3663 }
3664 else {
3665 // Extra Info block should not be removed, So copy it to the temp buffer.
3666 memcpy (pTmp, p, dataSize + 4);
3667 p += dataSize + 4;
3668 size += dataSize + 4;
3669 }
3670 }
3671
3672 if (size < *dataLen) {
3673 // clean old extra info block.
3674 memset (pData, 0, *dataLen);
3675
3676 // copy the new extra info block over the old
3677 if (size > 0)
3678 memcpy (pData, pNewHeader, size);
3679
3680 // set the new extra info size
3681 *dataLen = size;
3682
3683 retVal = ZIP_OK;
3684 }
3685 else
3686 retVal = ZIP_ERRNO;
3687
3688 free (pNewHeader);
3689
3690 return retVal;
3691}
3692
3693/// END OF zip.c
3694#endif
#define AssertNotNull(p)
Definition Assertions.h:333