1 /* zip.c -- IO on .zip files using zlib
2 Version 1.1, February 14h, 2010
3 part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
4
5 Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
6
7 Modifications for Zip64 support
8 Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
9
10 For more info read MiniZip_info.txt
11
12 Changes
13 Oct-2009 - Mathias Svensson - Remove old C style function prototypes
14 Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives
15 Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions.
16 Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data
17 It is used when recreating zip archive with RAW when deleting items from a zip.
18 ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed.
19 Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required)
20 Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
21
22 */
23
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdint.h>
29 #include <time.h>
30 #include "zlib.h"
31 #include "zip.h"
32
33 #ifdef STDC
34 # include <stddef.h>
35 #endif
36 #ifdef NO_ERRNO_H
37 extern int errno;
38 #else
39 # include <errno.h>
40 #endif
41
42
43 #ifndef local
44 # define local static
45 #endif
46 /* compile with -Dlocal if your debugger can't find static symbols */
47
48 #ifndef VERSIONMADEBY
49 # define VERSIONMADEBY (0x0) /* platform dependent */
50 #endif
51
52 #ifndef Z_BUFSIZE
53 #define Z_BUFSIZE (64*1024) //(16384)
54 #endif
55
56 #ifndef Z_MAXFILENAMEINZIP
57 #define Z_MAXFILENAMEINZIP (256)
58 #endif
59
60 #ifndef ALLOC
61 # define ALLOC(size) (malloc(size))
62 #endif
63
64 /*
65 #define SIZECENTRALDIRITEM (0x2e)
66 #define SIZEZIPLOCALHEADER (0x1e)
67 */
68
69 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
70
71
72 // NOT sure that this work on ALL platform
73 #define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32))
74
75 #ifndef SEEK_CUR
76 #define SEEK_CUR 1
77 #endif
78
79 #ifndef SEEK_END
80 #define SEEK_END 2
81 #endif
82
83 #ifndef SEEK_SET
84 #define SEEK_SET 0
85 #endif
86
87 #ifndef DEF_MEM_LEVEL
88 #if MAX_MEM_LEVEL >= 8
89 # define DEF_MEM_LEVEL 8
90 #else
91 # define DEF_MEM_LEVEL MAX_MEM_LEVEL
92 #endif
93 #endif
94 const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
95
96
97 #define SIZEDATA_INDATABLOCK (4096-(4*4))
98
99 #define LOCALHEADERMAGIC (0x04034b50)
100 #define CENTRALHEADERMAGIC (0x02014b50)
101 #define ENDHEADERMAGIC (0x06054b50)
102 #define ZIP64ENDHEADERMAGIC (0x6064b50)
103 #define ZIP64ENDLOCHEADERMAGIC (0x7064b50)
104
105 #define FLAG_LOCALHEADER_OFFSET (0x06)
106 #define CRC_LOCALHEADER_OFFSET (0x0e)
107
108 #define SIZECENTRALHEADER (0x2e) /* 46 */
109
110 typedef struct linkedlist_datablock_internal_s
111 {
112 struct linkedlist_datablock_internal_s* next_datablock;
113 uLong avail_in_this_block;
114 uLong filled_in_this_block;
115 uLong unused; /* for future use and alignment */
116 unsigned char data[SIZEDATA_INDATABLOCK];
117 } linkedlist_datablock_internal;
118
119 typedef struct linkedlist_data_s
120 {
121 linkedlist_datablock_internal* first_block;
122 linkedlist_datablock_internal* last_block;
123 } linkedlist_data;
124
125
126 typedef struct
127 {
128 z_stream stream; /* zLib stream structure for inflate */
129 #ifdef HAVE_BZIP2
130 bz_stream bstream; /* bzLib stream structure for bziped */
131 #endif
132
133 int stream_initialised; /* 1 is stream is initialised */
134 uInt pos_in_buffered_data; /* last written byte in buffered_data */
135
136 ZPOS64_T pos_local_header; /* offset of the local header of the file
137 currently writing */
138 char* central_header; /* central header data for the current file */
139 uLong size_centralExtra;
140 uLong size_centralheader; /* size of the central header for cur file */
141 uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */
142 uLong flag; /* flag of the file currently writing */
143
144 int method; /* compression method of file currently wr.*/
145 int raw; /* 1 for directly writing raw data */
146 Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
147 uLong dosDate;
148 uLong crc32;
149 int encrypt;
150 int zip64; /* Add ZIP64 extended information in the extra field */
151 ZPOS64_T pos_zip64extrainfo;
152 ZPOS64_T totalCompressedData;
153 ZPOS64_T totalUncompressedData;
154 #ifndef NOCRYPT
155 unsigned long keys[3]; /* keys defining the pseudo-random sequence */
156 const z_crc_t* pcrc_32_tab;
157 unsigned crypt_header_size;
158 #endif
159 } curfile64_info;
160
161 typedef struct
162 {
163 zlib_filefunc64_32_def z_filefunc;
164 voidpf filestream; /* io structure of the zipfile */
165 linkedlist_data central_dir;/* datablock with central dir in construction*/
166 int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/
167 curfile64_info ci; /* info on the file currently writing */
168
169 ZPOS64_T begin_pos; /* position of the beginning of the zipfile */
170 ZPOS64_T add_position_when_writing_offset;
171 ZPOS64_T number_entry;
172
173 #ifndef NO_ADDFILEINEXISTINGZIP
174 char *globalcomment;
175 #endif
176
177 } zip64_internal;
178
179
180 #ifndef NOCRYPT
181 #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
182 #include "crypt.h"
183 #endif
184
allocate_new_datablock(void)185 local linkedlist_datablock_internal* allocate_new_datablock(void)
186 {
187 linkedlist_datablock_internal* ldi;
188 ldi = (linkedlist_datablock_internal*)
189 ALLOC(sizeof(linkedlist_datablock_internal));
190 if (ldi != NULL)
191 {
192 ldi->next_datablock = NULL ;
193 ldi->filled_in_this_block = 0 ;
194 ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
195 }
196 return ldi;
197 }
198
free_datablock(linkedlist_datablock_internal * ldi)199 local void free_datablock(linkedlist_datablock_internal* ldi)
200 {
201 while (ldi != NULL)
202 {
203 linkedlist_datablock_internal* ldinext = ldi->next_datablock;
204 free(ldi);
205 ldi = ldinext;
206 }
207 }
208
init_linkedlist(linkedlist_data * ll)209 local void init_linkedlist(linkedlist_data* ll)
210 {
211 ll->first_block = ll->last_block = NULL;
212 }
213
free_linkedlist(linkedlist_data * ll)214 local void free_linkedlist(linkedlist_data* ll)
215 {
216 free_datablock(ll->first_block);
217 ll->first_block = ll->last_block = NULL;
218 }
219
220
add_data_in_datablock(linkedlist_data * ll,const void * buf,uLong len)221 local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len)
222 {
223 linkedlist_datablock_internal* ldi;
224 const unsigned char* from_copy;
225
226 if (ll == NULL)
227 {
228 return ZIP_INTERNALERROR;
229 }
230
231 if (ll->last_block == NULL)
232 {
233 ll->first_block = ll->last_block = allocate_new_datablock();
234 if (ll->first_block == NULL)
235 return ZIP_INTERNALERROR;
236 }
237
238 ldi = ll->last_block;
239 from_copy = (const unsigned char*)buf;
240
241 while (len>0)
242 {
243 uInt copy_this;
244 uInt i;
245 unsigned char* to_copy;
246
247 if (ldi->avail_in_this_block == 0)
248 {
249 ldi->next_datablock = allocate_new_datablock();
250 if (ldi->next_datablock == NULL)
251 return ZIP_INTERNALERROR;
252 ldi = ldi->next_datablock ;
253 ll->last_block = ldi;
254 }
255
256 if (ldi->avail_in_this_block < len)
257 {
258 copy_this = (uInt)ldi->avail_in_this_block;
259 }
260 else
261 {
262 copy_this = (uInt)len;
263 }
264
265 to_copy = &(ldi->data[ldi->filled_in_this_block]);
266
267 for (i = 0;i < copy_this; i++) {
268 *(to_copy+i) = *(from_copy+i);
269 }
270
271 ldi->filled_in_this_block += copy_this;
272 ldi->avail_in_this_block -= copy_this;
273 from_copy += copy_this ;
274 len -= copy_this;
275 }
276 return ZIP_OK;
277 }
278
279
280
281 /****************************************************************************/
282
283 #ifndef NO_ADDFILEINEXISTINGZIP
284 /* ===========================================================================
285 Inputs a long in LSB order to the given file
286 nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T)
287 */
288
zip64local_putValue(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,ZPOS64_T x,int nbByte)289 local int zip64local_putValue(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)
290 {
291 unsigned char buf[8];
292 int n;
293 for (n = 0; n < nbByte; n++)
294 {
295 buf[n] = (unsigned char)(x & 0xff);
296 x >>= 8;
297 }
298 if (x != 0)
299 { /* data overflow - hack for ZIP64 (X Roche) */
300 for (n = 0; n < nbByte; n++) {
301 buf[n] = 0xff;
302 }
303 }
304
305 if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,(uLong)nbByte) != (uLong)nbByte)
306 {
307 return ZIP_ERRNO;
308 }
309 else
310 {
311 return ZIP_OK;
312 }
313 }
314
zip64local_putValue_inmemory(void * dest,ZPOS64_T x,int nbByte)315 local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte)
316 {
317 unsigned char* buf = (unsigned char*)dest;
318 int n;
319 for (n = 0; n < nbByte; n++) {
320 buf[n] = (unsigned char)(x & 0xff);
321 x >>= 8;
322 }
323
324 if (x != 0)
325 { /* data overflow - hack for ZIP64 */
326 for (n = 0; n < nbByte; n++)
327 {
328 buf[n] = 0xff;
329 }
330 }
331 }
332
333 /****************************************************************************/
334
335
zip64local_TmzDateToDosDate(const tm_zip * ptm)336 local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm)
337 {
338 uLong year = (uLong)ptm->tm_year;
339 if (year >= 1980)
340 {
341 year -= 1980;
342 }
343 else if (year >= 80)
344 {
345 year -= 80;
346 }
347 return
348 (uLong) (((uLong)(ptm->tm_mday) + (32 * (uLong)(ptm->tm_mon + 1)) + (512 * year)) << 16) |
349 (((uLong)ptm->tm_sec / 2) + (32 * (uLong)ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
350 }
351
352
353 /****************************************************************************/
354
zip64local_getByte(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,int * pi)355 local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi)
356 {
357 unsigned char c;
358 int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
359 if (err == 1)
360 {
361 *pi = (int)c;
362 return ZIP_OK;
363 }
364 else
365 {
366 if (ZERROR64(*pzlib_filefunc_def,filestream))
367 {
368 return ZIP_ERRNO;
369 }
370 else
371 {
372 return ZIP_EOF;
373 }
374 }
375 }
376
377
378 /* ===========================================================================
379 Reads a long in LSB order from the given gz_stream. Sets
380 */
zip64local_getShort(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,uLong * pX)381 local int zip64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
382 {
383 uLong x ;
384 int i = 0;
385 int err;
386
387 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
388 x = (uLong)i;
389
390 if (err == ZIP_OK)
391 {
392 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
393 }
394 x += ((uLong)i) << 8;
395
396 if (err == ZIP_OK)
397 {
398 *pX = x;
399 }
400 else
401 {
402 *pX = 0;
403 }
404 return err;
405 }
406
zip64local_getLong(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,uLong * pX)407 local int zip64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
408 {
409 uLong x ;
410 int i = 0;
411 int err;
412
413 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
414 x = (uLong)i;
415
416 if (err == ZIP_OK)
417 {
418 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
419 }
420 x += ((uLong)i) << 8;
421
422 if (err == ZIP_OK)
423 {
424 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
425 }
426 x += ((uLong)i) << 16;
427
428 if (err == ZIP_OK)
429 {
430 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
431 }
432 x += ((uLong)i) << 24;
433
434 if (err == ZIP_OK)
435 {
436 *pX = x;
437 }
438 else
439 {
440 *pX = 0;
441 }
442 return err;
443 }
444
445
zip64local_getLong64(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,ZPOS64_T * pX)446 local int zip64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)
447 {
448 ZPOS64_T x;
449 int i = 0;
450 int err;
451
452 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
453 x = (ZPOS64_T)i;
454
455 if (err == ZIP_OK)
456 {
457 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
458 }
459 x += ((ZPOS64_T)i) << 8;
460
461 if (err == ZIP_OK)
462 {
463 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
464 }
465 x += ((ZPOS64_T)i) << 16;
466
467 if (err==ZIP_OK)
468 {
469 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
470 }
471 x += ((ZPOS64_T)i) << 24;
472
473 if (err == ZIP_OK)
474 {
475 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
476 }
477 x += ((ZPOS64_T)i) << 32;
478
479 if (err == ZIP_OK)
480 {
481 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
482 }
483 x += ((ZPOS64_T)i) << 40;
484
485 if (err == ZIP_OK)
486 {
487 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
488 }
489 x += ((ZPOS64_T)i) << 48;
490
491 if (err == ZIP_OK)
492 {
493 err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
494 }
495 x += ((ZPOS64_T)i) << 56;
496
497 if (err == ZIP_OK)
498 {
499 *pX = x;
500 }
501 else
502 {
503 *pX = 0;
504 }
505
506 return err;
507 }
508
509 #ifndef BUFREADCOMMENT
510 #define BUFREADCOMMENT (0x400)
511 #endif
512 /*
513 Locate the Central directory of a zipfile (at the end, just before
514 the global comment)
515 */
zip64local_SearchCentralDir(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream)516 local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
517 {
518 unsigned char* buf;
519 ZPOS64_T uSizeFile;
520 ZPOS64_T uBackRead;
521 ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
522 ZPOS64_T uPosFound=0;
523
524 if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
525 {
526 return 0;
527 }
528
529
530 uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
531
532 if (uMaxBack > uSizeFile)
533 {
534 uMaxBack = uSizeFile;
535 }
536
537 buf = (unsigned char*)ALLOC(BUFREADCOMMENT + 4);
538 if (buf == NULL)
539 {
540 return 0;
541 }
542
543 uBackRead = 4;
544 while (uBackRead<uMaxBack)
545 {
546 uLong uReadSize;
547 ZPOS64_T uReadPos ;
548 int i;
549 if (uBackRead + BUFREADCOMMENT > uMaxBack)
550 {
551 uBackRead = uMaxBack;
552 }
553 else
554 {
555 uBackRead += BUFREADCOMMENT;
556 }
557 uReadPos = uSizeFile - uBackRead ;
558
559 uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ?
560 (BUFREADCOMMENT + 4) : (uLong)(uSizeFile-uReadPos);
561 if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET) != 0)
562 {
563 break;
564 }
565
566 if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize) != uReadSize)
567 {
568 break;
569 }
570
571 for (i = (int)uReadSize - 3; (i--) > 0;) {
572 if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) &&
573 ((*(buf + i + 2)) == 0x05) && ((*(buf + i + 3)) == 0x06))
574 {
575 uPosFound = uReadPos + (unsigned)i;
576 break;
577 }
578 }
579
580 if (uPosFound != 0)
581 {
582 break;
583 }
584 }
585 free(buf);
586 return uPosFound;
587 }
588
589 /*
590 Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before
591 the global comment)
592 */
zip64local_SearchCentralDir64(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream)593 local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
594 {
595 unsigned char* buf;
596 ZPOS64_T uSizeFile;
597 ZPOS64_T uBackRead;
598 ZPOS64_T uMaxBack = 0xffff; /* maximum size of global comment */
599 ZPOS64_T uPosFound = 0;
600 uLong uL;
601 ZPOS64_T relativeOffset;
602
603 if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
604 {
605 return 0;
606 }
607
608 uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
609
610 if (uMaxBack > uSizeFile)
611 {
612 uMaxBack = uSizeFile;
613 }
614
615 buf = (unsigned char*)ALLOC(BUFREADCOMMENT + 4);
616 if (buf == NULL)
617 {
618 return 0;
619 }
620
621 uBackRead = 4;
622 while (uBackRead < uMaxBack)
623 {
624 uLong uReadSize;
625 ZPOS64_T uReadPos;
626 int i;
627 if (uBackRead + BUFREADCOMMENT > uMaxBack)
628 {
629 uBackRead = uMaxBack;
630 }
631 else
632 {
633 uBackRead += BUFREADCOMMENT;
634 }
635 uReadPos = uSizeFile - uBackRead ;
636
637 uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos)) ?
638 (BUFREADCOMMENT + 4) : (uLong)(uSizeFile - uReadPos);
639 if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET) != 0)
640 {
641 break;
642 }
643
644 if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize) != uReadSize)
645 {
646 break;
647 }
648
649 for (i = (int)uReadSize - 3; (i--) > 0;)
650 {
651 // Signature "0x07064b50" Zip64 end of central directory locater
652 if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) && ((*(buf + i + 2)) == 0x06) && ((*(buf + i + 3)) == 0x07))
653 {
654 uPosFound = uReadPos + (unsigned)i;
655 break;
656 }
657 }
658
659 if (uPosFound != 0)
660 {
661 break;
662 }
663 }
664
665 free(buf);
666 if (uPosFound == 0)
667 {
668 return 0;
669 }
670
671 /* Zip64 end of central directory locator */
672 if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET) != 0)
673 {
674 return 0;
675 }
676
677 /* the signature, already checked */
678 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL) != ZIP_OK)
679 {
680 return 0;
681 }
682
683 /* number of the disk with the start of the zip64 end of central directory */
684 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL) != ZIP_OK)
685 {
686 return 0;
687 }
688 if (uL != 0)
689 {
690 return 0;
691 }
692
693 /* relative offset of the zip64 end of central directory record */
694 if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset) != ZIP_OK)
695 {
696 return 0;
697 }
698
699 /* total number of disks */
700 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL) != ZIP_OK)
701 {
702 return 0;
703 }
704 if (uL != 1)
705 {
706 return 0;
707 }
708
709 /* Goto Zip64 end of central directory record */
710 if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET) != 0)
711 {
712 return 0;
713 }
714
715 /* the signature */
716 if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL) != ZIP_OK)
717 {
718 return 0;
719 }
720
721 if (uL != 0x06064b50) // signature of 'Zip64 end of central directory'
722 {
723 return 0;
724 }
725
726 return relativeOffset;
727 }
728
LoadCentralDirectoryRecord(zip64_internal * pziinit)729 local int LoadCentralDirectoryRecord(zip64_internal* pziinit)
730 {
731 int err = ZIP_OK;
732 ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
733
734 ZPOS64_T size_central_dir; /* size of the central directory */
735 ZPOS64_T offset_central_dir; /* offset of start of central directory */
736 ZPOS64_T central_pos;
737 uLong uL;
738
739 uLong number_disk; /* number of the current disk, used for
740 spanning ZIP, unsupported, always 0*/
741 uLong number_disk_with_CD; /* number of the disk with central dir, used
742 for spanning ZIP, unsupported, always 0*/
743 ZPOS64_T number_entry;
744 ZPOS64_T number_entry_CD; /* total number of entries in
745 the central dir
746 (same than number_entry on nospan) */
747 uLong VersionMadeBy;
748 uLong VersionNeeded;
749 uLong size_comment;
750
751 int hasZIP64Record = 0;
752
753 // check first if we find a ZIP64 record
754 central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream);
755 if(central_pos > 0)
756 {
757 hasZIP64Record = 1;
758 }
759 else if(central_pos == 0)
760 {
761 central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream);
762 }
763
764 /* disable to allow appending to empty ZIP archive
765 if (central_pos==0)
766 err=ZIP_ERRNO;
767 */
768
769 if(hasZIP64Record)
770 {
771 ZPOS64_T sizeEndOfCentralDirectory;
772 if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
773 {
774 err = ZIP_ERRNO;
775 }
776
777 /* the signature, already checked */
778 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL) != ZIP_OK)
779 {
780 err = ZIP_ERRNO;
781 }
782
783 /* size of zip64 end of central directory record */
784 if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory) != ZIP_OK)
785 {
786 err = ZIP_ERRNO;
787 }
788
789 /* version made by */
790 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy) != ZIP_OK)
791 {
792 err = ZIP_ERRNO;
793 }
794
795 /* version needed to extract */
796 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded) != ZIP_OK)
797 {
798 err = ZIP_ERRNO;
799 }
800
801 /* number of this disk */
802 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk) != ZIP_OK)
803 {
804 err = ZIP_ERRNO;
805 }
806
807 /* number of the disk with the start of the central directory */
808 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD) != ZIP_OK)
809 {
810 err = ZIP_ERRNO;
811 }
812
813 /* total number of entries in the central directory on this disk */
814 if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry) != ZIP_OK)
815 {
816 err = ZIP_ERRNO;
817 }
818
819 /* total number of entries in the central directory */
820 if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD) != ZIP_OK)
821 {
822 err = ZIP_ERRNO;
823 }
824
825 if ((number_entry_CD != number_entry) || (number_disk_with_CD != 0) || (number_disk != 0))
826 {
827 err = ZIP_BADZIPFILE;
828 }
829
830 /* size of the central directory */
831 if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir) != ZIP_OK)
832 {
833 err = ZIP_ERRNO;
834 }
835
836 /* offset of start of central directory with respect to the
837 starting disk number */
838 if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir) != ZIP_OK)
839 {
840 err = ZIP_ERRNO;
841 }
842
843 // TODO..
844 // read the comment from the standard central header.
845 size_comment = 0;
846 }
847 else
848 {
849 // Read End of central Directory info
850 if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET) != 0)
851 {
852 err = ZIP_ERRNO;
853 }
854
855 /* the signature, already checked */
856 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL) != ZIP_OK)
857 {
858 err = ZIP_ERRNO;
859 }
860
861 /* number of this disk */
862 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk) != ZIP_OK)
863 {
864 err = ZIP_ERRNO;
865 }
866
867 /* number of the disk with the start of the central directory */
868 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD) != ZIP_OK)
869 {
870 err = ZIP_ERRNO;
871 }
872
873 /* total number of entries in the central dir on this disk */
874 number_entry = 0;
875 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL) != ZIP_OK)
876 {
877 err = ZIP_ERRNO;
878 }
879 else
880 {
881 number_entry = uL;
882 }
883
884 /* total number of entries in the central dir */
885 number_entry_CD = 0;
886 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL) != ZIP_OK)
887 {
888 err = ZIP_ERRNO;
889 }
890 else
891 {
892 number_entry_CD = uL;
893 }
894
895 if ((number_entry_CD != number_entry) || (number_disk_with_CD != 0) || (number_disk != 0))
896 {
897 err = ZIP_BADZIPFILE;
898 }
899
900 /* size of the central directory */
901 size_central_dir = 0;
902 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL) != ZIP_OK)
903 {
904 err = ZIP_ERRNO;
905 }
906 else
907 {
908 size_central_dir = uL;
909 }
910
911 /* offset of start of central directory with respect to the starting disk number */
912 offset_central_dir = 0;
913 if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL) != ZIP_OK)
914 {
915 err = ZIP_ERRNO;
916 }
917 else
918 {
919 offset_central_dir = uL;
920 }
921
922
923 /* zipfile global comment length */
924 if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment) != ZIP_OK)
925 {
926 err = ZIP_ERRNO;
927 }
928 }
929
930 if ((central_pos<offset_central_dir+size_central_dir) &&
931 (err == ZIP_OK))
932 {
933 err = ZIP_BADZIPFILE;
934 }
935
936 if (err != ZIP_OK)
937 {
938 ZCLOSE64(pziinit->z_filefunc, pziinit->filestream);
939 return ZIP_ERRNO;
940 }
941
942 if (size_comment > 0)
943 {
944 pziinit->globalcomment = (char*)ALLOC(size_comment + 1);
945 if (pziinit->globalcomment)
946 {
947 size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment);
948 pziinit->globalcomment[size_comment] = 0;
949 }
950 }
951
952 byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir);
953 pziinit->add_position_when_writing_offset = byte_before_the_zipfile;
954
955 {
956 ZPOS64_T size_central_dir_to_read = size_central_dir;
957 size_t buf_size = SIZEDATA_INDATABLOCK;
958 void* buf_read = (void*)ALLOC(buf_size);
959 if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
960 {
961 err = ZIP_ERRNO;
962 }
963
964 while ((size_central_dir_to_read>0) && (err == ZIP_OK))
965 {
966 ZPOS64_T read_this = SIZEDATA_INDATABLOCK;
967 if (read_this > size_central_dir_to_read)
968 {
969 read_this = size_central_dir_to_read;
970 }
971
972 if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this)
973 {
974 err = ZIP_ERRNO;
975 }
976
977 if (err == ZIP_OK)
978 {
979 err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this);
980 }
981
982 size_central_dir_to_read -= read_this;
983 }
984 free(buf_read);
985 }
986 pziinit->begin_pos = byte_before_the_zipfile;
987 pziinit->number_entry = number_entry_CD;
988
989 if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0)
990 {
991 err = ZIP_ERRNO;
992 }
993
994 return err;
995 }
996
997
998 #endif /* !NO_ADDFILEINEXISTINGZIP*/
999
1000
1001 /************************************************************/
zipOpen3(const void * pathname,int append,zipcharpc * globalcomment,zlib_filefunc64_32_def * pzlib_filefunc64_32_def)1002 extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def)
1003 {
1004 zip64_internal ziinit;
1005 zip64_internal* zi;
1006 int err = ZIP_OK;
1007
1008 ziinit.z_filefunc.zseek32_file = NULL;
1009 ziinit.z_filefunc.ztell32_file = NULL;
1010 if (pzlib_filefunc64_32_def == NULL)
1011 {
1012 fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);
1013 }
1014 else
1015 {
1016 ziinit.z_filefunc = *pzlib_filefunc64_32_def;
1017 }
1018
1019 ziinit.filestream = ZOPEN64(ziinit.z_filefunc,
1020 pathname,
1021 (append == APPEND_STATUS_CREATE) ?
1022 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
1023 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
1024
1025 if (ziinit.filestream == NULL)
1026 {
1027 return NULL;
1028 }
1029
1030 if (append == APPEND_STATUS_CREATEAFTER)
1031 {
1032 ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END);
1033 }
1034
1035 ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream);
1036 ziinit.in_opened_file_inzip = 0;
1037 ziinit.ci.stream_initialised = 0;
1038 ziinit.number_entry = 0;
1039 ziinit.add_position_when_writing_offset = 0;
1040 init_linkedlist(&(ziinit.central_dir));
1041
1042
1043
1044 zi = (zip64_internal*)ALLOC(sizeof(zip64_internal));
1045 if (zi == NULL)
1046 {
1047 ZCLOSE64(ziinit.z_filefunc,ziinit.filestream);
1048 return NULL;
1049 }
1050
1051 /* now we add file in a zipfile */
1052 # ifndef NO_ADDFILEINEXISTINGZIP
1053 ziinit.globalcomment = NULL;
1054 if (append == APPEND_STATUS_ADDINZIP)
1055 {
1056 // Read and Cache Central Directory Records
1057 err = LoadCentralDirectoryRecord(&ziinit);
1058 }
1059
1060 if (globalcomment)
1061 {
1062 *globalcomment = ziinit.globalcomment;
1063 }
1064 # endif /* !NO_ADDFILEINEXISTINGZIP*/
1065
1066 if (err != ZIP_OK)
1067 {
1068 # ifndef NO_ADDFILEINEXISTINGZIP
1069 free(ziinit.globalcomment);
1070 # endif /* !NO_ADDFILEINEXISTINGZIP*/
1071 free(zi);
1072 return NULL;
1073 }
1074 else
1075 {
1076 *zi = ziinit;
1077 return (zipFile)zi;
1078 }
1079 }
1080
zipOpen2(const char * pathname,int append,zipcharpc * globalcomment,zlib_filefunc_def * pzlib_filefunc32_def)1081 extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def)
1082 {
1083 if (pzlib_filefunc32_def != NULL)
1084 {
1085 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
1086 fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
1087 return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
1088 }
1089 else
1090 {
1091 return zipOpen3(pathname, append, globalcomment, NULL);
1092 }
1093 }
1094
zipOpen2_64(const void * pathname,int append,zipcharpc * globalcomment,zlib_filefunc64_def * pzlib_filefunc_def)1095 extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def)
1096 {
1097 if (pzlib_filefunc_def != NULL)
1098 {
1099 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
1100 zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
1101 zlib_filefunc64_32_def_fill.ztell32_file = NULL;
1102 zlib_filefunc64_32_def_fill.zseek32_file = NULL;
1103 return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
1104 }
1105 else
1106 {
1107 return zipOpen3(pathname, append, globalcomment, NULL);
1108 }
1109 }
1110
1111
1112
zipOpen(const char * pathname,int append)1113 extern zipFile ZEXPORT zipOpen(const char* pathname, int append)
1114 {
1115 return zipOpen3((const void*)pathname,append,NULL,NULL);
1116 }
1117
zipOpen64(const void * pathname,int append)1118 extern zipFile ZEXPORT zipOpen64(const void* pathname, int append)
1119 {
1120 return zipOpen3(pathname,append,NULL,NULL);
1121 }
1122
Write_LocalFileHeader(zip64_internal * zi,const char * filename,uInt size_extrafield_local,const void * extrafield_local)1123 local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local)
1124 {
1125 /* write the local header */
1126 int err;
1127 uInt size_filename = (uInt)strlen(filename);
1128 uInt size_extrafield = size_extrafield_local;
1129
1130 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4);
1131
1132 if (err == ZIP_OK)
1133 {
1134 if(zi->ci.zip64)
1135 {
1136 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */
1137 }
1138 else
1139 {
1140 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
1141 }
1142 }
1143
1144 if (err == ZIP_OK)
1145 {
1146 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
1147 }
1148
1149 if (err == ZIP_OK)
1150 {
1151 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
1152 }
1153
1154 if (err == ZIP_OK)
1155 {
1156 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
1157 }
1158
1159 // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
1160 if (err == ZIP_OK)
1161 {
1162 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
1163 }
1164 if (err == ZIP_OK)
1165 {
1166 if(zi->ci.zip64)
1167 {
1168 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */
1169 }
1170 else
1171 {
1172 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
1173 }
1174 }
1175 if (err == ZIP_OK)
1176 {
1177 if(zi->ci.zip64)
1178 {
1179 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */
1180 }
1181 else
1182 {
1183 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
1184 }
1185 }
1186
1187 if (err == ZIP_OK)
1188 {
1189 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
1190 }
1191
1192 if(zi->ci.zip64)
1193 {
1194 size_extrafield += 20;
1195 }
1196
1197 if (err == ZIP_OK)
1198 {
1199 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2);
1200 }
1201
1202 if ((err == ZIP_OK) && (size_filename > 0))
1203 {
1204 if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename) != size_filename)
1205 {
1206 err = ZIP_ERRNO;
1207 }
1208 }
1209
1210 if ((err == ZIP_OK) && (size_extrafield_local > 0))
1211 {
1212 if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local)
1213 {
1214 err = ZIP_ERRNO;
1215 }
1216 }
1217
1218
1219 if ((err == ZIP_OK) && (zi->ci.zip64))
1220 {
1221 // write the Zip64 extended info
1222 short HeaderID = 1;
1223 short DataSize = 16;
1224 ZPOS64_T CompressedSize = 0;
1225 ZPOS64_T UncompressedSize = 0;
1226
1227 // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file)
1228 zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream);
1229
1230 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID,2);
1231 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)DataSize,2);
1232
1233 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8);
1234 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8);
1235 }
1236
1237 return err;
1238 }
1239
1240 /*
1241 NOTE.
1242 When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped
1243 before calling this function it can be done with zipRemoveExtraInfoBlock
1244
1245 It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize
1246 unnecessary allocations.
1247 */
zipOpenNewFileInZip4_64(zipFile file,const char * filename,const zip_fileinfo * zipfi,const void * extrafield_local,uInt size_extrafield_local,const void * extrafield_global,uInt size_extrafield_global,const char * comment,int method,int level,int raw,int windowBits,int memLevel,int strategy,const char * password,uLong crcForCrypting,uLong versionMadeBy,uLong flagBase,int zip64)1248 extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1249 const void* extrafield_local, uInt size_extrafield_local,
1250 const void* extrafield_global, uInt size_extrafield_global,
1251 const char* comment, int method, int level, int raw,
1252 int windowBits,int memLevel, int strategy,
1253 const char* password, uLong crcForCrypting,
1254 uLong versionMadeBy, uLong flagBase, int zip64) {
1255 zip64_internal* zi;
1256 uInt size_filename;
1257 uInt size_comment;
1258 uInt i;
1259 int err = ZIP_OK;
1260
1261 # ifdef NOCRYPT
1262 (crcForCrypting);
1263 if (password != NULL)
1264 {
1265 return ZIP_PARAMERROR;
1266 }
1267 # endif
1268
1269 if (file == NULL)
1270 {
1271 return ZIP_PARAMERROR;
1272 }
1273
1274 #ifdef HAVE_BZIP2
1275 if ((method != 0) && (method != Z_DEFLATED) && (method != Z_BZIP2ED))
1276 {
1277 return ZIP_PARAMERROR;
1278 }
1279 #else
1280 if ((method != 0) && (method != Z_DEFLATED))
1281 {
1282 return ZIP_PARAMERROR;
1283 }
1284 #endif
1285
1286 // The filename and comment length must fit in 16 bits.
1287 if ((filename != NULL) && (strlen(filename) > 0xffff))
1288 {
1289 return ZIP_PARAMERROR;
1290 }
1291 if ((comment != NULL) && (strlen(comment) > 0xffff))
1292 {
1293 return ZIP_PARAMERROR;
1294 }
1295 // The extra field length must fit in 16 bits. If the member also requires
1296 // a Zip64 extra block, that will also need to fit within that 16-bit
1297 // length, but that will be checked for later.
1298 if ((size_extrafield_local > 0xffff) || (size_extrafield_global > 0xffff))
1299 {
1300 return ZIP_PARAMERROR;
1301 }
1302
1303 zi = (zip64_internal*)file;
1304
1305 if (zi->in_opened_file_inzip == 1)
1306 {
1307 err = zipCloseFileInZip (file);
1308 if (err != ZIP_OK)
1309 {
1310 return err;
1311 }
1312 }
1313
1314 if (filename == NULL)
1315 {
1316 filename = "-";
1317 }
1318
1319 if (comment == NULL)
1320 {
1321 size_comment = 0;
1322 }
1323 else
1324 {
1325 size_comment = (uInt)strlen(comment);
1326 }
1327
1328 size_filename = (uInt)strlen(filename);
1329
1330 if (zipfi == NULL)
1331 {
1332 zi->ci.dosDate = 0;
1333 }
1334 else
1335 {
1336 if (zipfi->dosDate != 0)
1337 {
1338 zi->ci.dosDate = zipfi->dosDate;
1339 }
1340 else
1341 {
1342 zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date);
1343 }
1344 }
1345
1346 zi->ci.flag = flagBase;
1347 if ((level == 8) || (level == 9))
1348 {
1349 zi->ci.flag |= 2;
1350 }
1351 if (level == 2)
1352 {
1353 zi->ci.flag |= 4;
1354 }
1355 if (level == 1)
1356 {
1357 zi->ci.flag |= 6;
1358 }
1359 if (password != NULL)
1360 {
1361 zi->ci.flag |= 1;
1362 }
1363
1364 zi->ci.crc32 = 0;
1365 zi->ci.method = method;
1366 zi->ci.encrypt = 0;
1367 zi->ci.stream_initialised = 0;
1368 zi->ci.pos_in_buffered_data = 0;
1369 zi->ci.raw = raw;
1370 zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream);
1371
1372 zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment;
1373 zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data
1374
1375 zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree);
1376
1377 zi->ci.size_centralExtra = size_extrafield_global;
1378 zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
1379 /* version info */
1380 zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2);
1381 zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
1382 zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
1383 zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
1384 zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
1385 zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
1386 zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
1387 zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
1388 zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
1389 zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
1390 zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
1391 zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
1392
1393 if (zipfi == NULL)
1394 {
1395 zip64local_putValue_inmemory(zi->ci.central_header + 36,(uLong)0,2);
1396 }
1397 else
1398 {
1399 zip64local_putValue_inmemory(zi->ci.central_header + 36,(uLong)zipfi->internal_fa,2);
1400 }
1401
1402 if (zipfi == NULL)
1403 {
1404 zip64local_putValue_inmemory(zi->ci.central_header + 38,(uLong)0,4);
1405 }
1406 else
1407 {
1408 zip64local_putValue_inmemory(zi->ci.central_header + 38,(uLong)zipfi->external_fa,4);
1409 }
1410
1411 if(zi->ci.pos_local_header >= 0xffffffff)
1412 {
1413 zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4);
1414 }
1415 else
1416 {
1417 zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4);
1418 }
1419
1420 for (i = 0;i < size_filename; i++){
1421 *(zi->ci.central_header + SIZECENTRALHEADER + i) = *(filename + i);
1422 }
1423
1424 for (i = 0;i < size_extrafield_global; i++){
1425 *(zi->ci.central_header + SIZECENTRALHEADER + size_filename + i) =
1426 *(((const char*)extrafield_global) + i);
1427 }
1428
1429 for (i = 0;i < size_comment; i++){
1430 *(zi->ci.central_header + SIZECENTRALHEADER + size_filename +
1431 size_extrafield_global + i) = *(comment + i);
1432 }
1433 if (zi->ci.central_header == NULL)
1434 {
1435 return ZIP_INTERNALERROR;
1436 }
1437
1438 zi->ci.zip64 = zip64;
1439 zi->ci.totalCompressedData = 0;
1440 zi->ci.totalUncompressedData = 0;
1441 zi->ci.pos_zip64extrainfo = 0;
1442
1443 err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local);
1444
1445 #ifdef HAVE_BZIP2
1446 zi->ci.bstream.avail_in = (uInt)0;
1447 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1448 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1449 zi->ci.bstream.total_in_hi32 = 0;
1450 zi->ci.bstream.total_in_lo32 = 0;
1451 zi->ci.bstream.total_out_hi32 = 0;
1452 zi->ci.bstream.total_out_lo32 = 0;
1453 #endif
1454
1455 zi->ci.stream.avail_in = (uInt)0;
1456 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1457 zi->ci.stream.next_out = zi->ci.buffered_data;
1458 zi->ci.stream.total_in = 0;
1459 zi->ci.stream.total_out = 0;
1460 zi->ci.stream.data_type = Z_BINARY;
1461
1462 #ifdef HAVE_BZIP2
1463 if ((err == ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1464 #else
1465 if ((err == ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1466 #endif
1467 {
1468 if(zi->ci.method == Z_DEFLATED)
1469 {
1470 zi->ci.stream.zalloc = (alloc_func)0;
1471 zi->ci.stream.zfree = (free_func)0;
1472 zi->ci.stream.opaque = (voidpf)0;
1473
1474 if (windowBits>0)
1475 windowBits = -windowBits;
1476
1477 err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy);
1478
1479 if (err == Z_OK)
1480 {
1481 zi->ci.stream_initialised = Z_DEFLATED;
1482 }
1483 }
1484 else if(zi->ci.method == Z_BZIP2ED)
1485 {
1486 #ifdef HAVE_BZIP2
1487 // Init BZip stuff here
1488 zi->ci.bstream.bzalloc = 0;
1489 zi->ci.bstream.bzfree = 0;
1490 zi->ci.bstream.opaque = (voidpf)0;
1491
1492 err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35);
1493 if(err == BZ_OK)
1494 {
1495 zi->ci.stream_initialised = Z_BZIP2ED;
1496 }
1497 #endif
1498 }
1499
1500 }
1501
1502 # ifndef NOCRYPT
1503 zi->ci.crypt_header_size = 0;
1504 if ((err == Z_OK) && (password != NULL))
1505 {
1506 unsigned char bufHead[RAND_HEAD_LEN];
1507 unsigned int sizeHead;
1508 zi->ci.encrypt = 1;
1509 zi->ci.pcrc_32_tab = get_crc_table();
1510 /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
1511
1512 sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
1513 zi->ci.crypt_header_size = sizeHead;
1514
1515 if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
1516 {
1517 err = ZIP_ERRNO;
1518 }
1519 }
1520 # endif
1521
1522 if (err == Z_OK)
1523 {
1524 zi->in_opened_file_inzip = 1;
1525 }
1526 return err;
1527 }
1528
zipOpenNewFileInZip4(zipFile file,const char * filename,const zip_fileinfo * zipfi,const void * extrafield_local,uInt size_extrafield_local,const void * extrafield_global,uInt size_extrafield_global,const char * comment,int method,int level,int raw,int windowBits,int memLevel,int strategy,const char * password,uLong crcForCrypting,uLong versionMadeBy,uLong flagBase)1529 extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1530 const void* extrafield_local, uInt size_extrafield_local,
1531 const void* extrafield_global, uInt size_extrafield_global,
1532 const char* comment, int method, int level, int raw,
1533 int windowBits,int memLevel, int strategy,
1534 const char* password, uLong crcForCrypting,
1535 uLong versionMadeBy, uLong flagBase)
1536 {
1537 return zipOpenNewFileInZip4_64(file, filename, zipfi,
1538 extrafield_local, size_extrafield_local,
1539 extrafield_global, size_extrafield_global,
1540 comment, method, level, raw,
1541 windowBits, memLevel, strategy,
1542 password, crcForCrypting, versionMadeBy, flagBase, 0);
1543 }
1544
zipOpenNewFileInZip3(zipFile file,const char * filename,const zip_fileinfo * zipfi,const void * extrafield_local,uInt size_extrafield_local,const void * extrafield_global,uInt size_extrafield_global,const char * comment,int method,int level,int raw,int windowBits,int memLevel,int strategy,const char * password,uLong crcForCrypting)1545 extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1546 const void* extrafield_local, uInt size_extrafield_local,
1547 const void* extrafield_global, uInt size_extrafield_global,
1548 const char* comment, int method, int level, int raw,
1549 int windowBits,int memLevel, int strategy,
1550 const char* password, uLong crcForCrypting)
1551 {
1552 return zipOpenNewFileInZip4_64(file, filename, zipfi,
1553 extrafield_local, size_extrafield_local,
1554 extrafield_global, size_extrafield_global,
1555 comment, method, level, raw,
1556 windowBits, memLevel, strategy,
1557 password, crcForCrypting, VERSIONMADEBY, 0, 0);
1558 }
1559
zipOpenNewFileInZip3_64(zipFile file,const char * filename,const zip_fileinfo * zipfi,const void * extrafield_local,uInt size_extrafield_local,const void * extrafield_global,uInt size_extrafield_global,const char * comment,int method,int level,int raw,int windowBits,int memLevel,int strategy,const char * password,uLong crcForCrypting,int zip64)1560 extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1561 const void* extrafield_local, uInt size_extrafield_local,
1562 const void* extrafield_global, uInt size_extrafield_global,
1563 const char* comment, int method, int level, int raw,
1564 int windowBits,int memLevel, int strategy,
1565 const char* password, uLong crcForCrypting, int zip64)
1566 {
1567 return zipOpenNewFileInZip4_64(file, filename, zipfi,
1568 extrafield_local, size_extrafield_local,
1569 extrafield_global, size_extrafield_global,
1570 comment, method, level, raw,
1571 windowBits, memLevel, strategy,
1572 password, crcForCrypting, VERSIONMADEBY, 0, zip64);
1573 }
1574
zipOpenNewFileInZip2(zipFile file,const char * filename,const zip_fileinfo * zipfi,const void * extrafield_local,uInt size_extrafield_local,const void * extrafield_global,uInt size_extrafield_global,const char * comment,int method,int level,int raw)1575 extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1576 const void* extrafield_local, uInt size_extrafield_local,
1577 const void* extrafield_global, uInt size_extrafield_global,
1578 const char* comment, int method, int level, int raw)
1579 {
1580 return zipOpenNewFileInZip4_64(file, filename, zipfi,
1581 extrafield_local, size_extrafield_local,
1582 extrafield_global, size_extrafield_global,
1583 comment, method, level, raw,
1584 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1585 NULL, 0, VERSIONMADEBY, 0, 0);
1586 }
1587
zipOpenNewFileInZip2_64(zipFile file,const char * filename,const zip_fileinfo * zipfi,const void * extrafield_local,uInt size_extrafield_local,const void * extrafield_global,uInt size_extrafield_global,const char * comment,int method,int level,int raw,int zip64)1588 extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1589 const void* extrafield_local, uInt size_extrafield_local,
1590 const void* extrafield_global, uInt size_extrafield_global,
1591 const char* comment, int method, int level, int raw, int zip64)
1592 {
1593 return zipOpenNewFileInZip4_64(file, filename, zipfi,
1594 extrafield_local, size_extrafield_local,
1595 extrafield_global, size_extrafield_global,
1596 comment, method, level, raw,
1597 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1598 NULL, 0, VERSIONMADEBY, 0, zip64);
1599 }
1600
zipOpenNewFileInZip64(zipFile file,const char * filename,const zip_fileinfo * zipfi,const void * extrafield_local,uInt size_extrafield_local,const void * extrafield_global,uInt size_extrafield_global,const char * comment,int method,int level,int zip64)1601 extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1602 const void* extrafield_local, uInt size_extrafield_local,
1603 const void*extrafield_global, uInt size_extrafield_global,
1604 const char* comment, int method, int level, int zip64)
1605 {
1606 return zipOpenNewFileInZip4_64(file, filename, zipfi,
1607 extrafield_local, size_extrafield_local,
1608 extrafield_global, size_extrafield_global,
1609 comment, method, level, 0,
1610 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1611 NULL, 0, VERSIONMADEBY, 0, zip64);
1612 }
1613
zipOpenNewFileInZip(zipFile file,const char * filename,const zip_fileinfo * zipfi,const void * extrafield_local,uInt size_extrafield_local,const void * extrafield_global,uInt size_extrafield_global,const char * comment,int method,int level)1614 extern int ZEXPORT zipOpenNewFileInZip(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1615 const void* extrafield_local, uInt size_extrafield_local,
1616 const void*extrafield_global, uInt size_extrafield_global,
1617 const char* comment, int method, int level)
1618 {
1619 return zipOpenNewFileInZip4_64(file, filename, zipfi,
1620 extrafield_local, size_extrafield_local,
1621 extrafield_global, size_extrafield_global,
1622 comment, method, level, 0,
1623 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
1624 NULL, 0, VERSIONMADEBY, 0, 0);
1625 }
1626
zip64FlushWriteBuffer(zip64_internal * zi)1627 local int zip64FlushWriteBuffer(zip64_internal* zi)
1628 {
1629 int err = ZIP_OK;
1630
1631 if (zi->ci.encrypt != 0)
1632 {
1633 #ifndef NOCRYPT
1634 uInt i;
1635 int t;
1636 for (i = 0;i < zi->ci.pos_in_buffered_data; i++){
1637 zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t);
1638 }
1639 #endif
1640 }
1641
1642 if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data)
1643 {
1644 err = ZIP_ERRNO;
1645 }
1646
1647 zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data;
1648
1649 #ifdef HAVE_BZIP2
1650 if(zi->ci.method == Z_BZIP2ED)
1651 {
1652 zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32;
1653 zi->ci.bstream.total_in_lo32 = 0;
1654 zi->ci.bstream.total_in_hi32 = 0;
1655 }
1656 else
1657 #endif
1658 {
1659 zi->ci.totalUncompressedData += zi->ci.stream.total_in;
1660 zi->ci.stream.total_in = 0;
1661 }
1662
1663
1664 zi->ci.pos_in_buffered_data = 0;
1665
1666 return err;
1667 }
1668
zipWriteInFileInZip(zipFile file,const void * buf,unsigned int len)1669 extern int ZEXPORT zipWriteInFileInZip(zipFile file, const void* buf, unsigned int len) {
1670 zip64_internal* zi;
1671 int err = ZIP_OK;
1672
1673 if (file == NULL)
1674 {
1675 return ZIP_PARAMERROR;
1676 }
1677 zi = (zip64_internal*)file;
1678
1679 if (zi->in_opened_file_inzip == 0)
1680 {
1681 return ZIP_PARAMERROR;
1682 }
1683
1684 zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len);
1685
1686 #ifdef HAVE_BZIP2
1687 if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw))
1688 {
1689 zi->ci.bstream.next_in = (void*)buf;
1690 zi->ci.bstream.avail_in = len;
1691 err = BZ_RUN_OK;
1692
1693 while ((err == BZ_RUN_OK) && (zi->ci.bstream.avail_in > 0))
1694 {
1695 if (zi->ci.bstream.avail_out == 0)
1696 {
1697 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1698 {
1699 err = ZIP_ERRNO;
1700 }
1701 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1702 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1703 }
1704
1705
1706 if(err != BZ_RUN_OK)
1707 {
1708 break;
1709 }
1710
1711 if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1712 {
1713 uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32;
1714 // uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32;
1715 err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN);
1716
1717 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ;
1718 }
1719 }
1720
1721 if(err == BZ_RUN_OK)
1722 {
1723 err = ZIP_OK;
1724 }
1725 }
1726 else
1727 #endif
1728 {
1729 zi->ci.stream.next_in = (Bytef*)(uintptr_t)buf;
1730 zi->ci.stream.avail_in = len;
1731
1732 while ((err == ZIP_OK) && (zi->ci.stream.avail_in > 0))
1733 {
1734 if (zi->ci.stream.avail_out == 0)
1735 {
1736 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1737 {
1738 err = ZIP_ERRNO;
1739 }
1740 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1741 zi->ci.stream.next_out = zi->ci.buffered_data;
1742 }
1743
1744
1745 if(err != ZIP_OK)
1746 break;
1747
1748 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1749 {
1750 uLong uTotalOutBefore = zi->ci.stream.total_out;
1751 err = deflate(&zi->ci.stream, Z_NO_FLUSH);
1752
1753 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
1754 }
1755 else
1756 {
1757 uInt copy_this,i;
1758 if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
1759 copy_this = zi->ci.stream.avail_in;
1760 else
1761 copy_this = zi->ci.stream.avail_out;
1762
1763 for (i = 0; i < copy_this; i++){
1764 *(((char*)zi->ci.stream.next_out) + i) =
1765 *(((const char*)zi->ci.stream.next_in) + i);
1766 }
1767 {
1768 zi->ci.stream.avail_in -= copy_this;
1769 zi->ci.stream.avail_out -= copy_this;
1770 zi->ci.stream.next_in += copy_this;
1771 zi->ci.stream.next_out += copy_this;
1772 zi->ci.stream.total_in += copy_this;
1773 zi->ci.stream.total_out += copy_this;
1774 zi->ci.pos_in_buffered_data += copy_this;
1775 }
1776 }
1777 }// while(...)
1778 }
1779
1780 return err;
1781 }
1782
zipCloseFileInZipRaw(zipFile file,uLong uncompressed_size,uLong crc32)1783 extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32)
1784 {
1785 return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32);
1786 }
1787
zipCloseFileInZipRaw64(zipFile file,ZPOS64_T uncompressed_size,uLong crc32)1788 extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32)
1789 {
1790 zip64_internal* zi;
1791 ZPOS64_T compressed_size;
1792 uLong invalidValue = 0xffffffff;
1793 unsigned datasize = 0;
1794 int err = ZIP_OK;
1795
1796 if (file == NULL)
1797 {
1798 return ZIP_PARAMERROR;
1799 }
1800 zi = (zip64_internal*)file;
1801
1802 if (zi->in_opened_file_inzip == 0)
1803 {
1804 return ZIP_PARAMERROR;
1805 }
1806 zi->ci.stream.avail_in = 0;
1807
1808 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1809 {
1810 while (err == ZIP_OK)
1811 {
1812 uLong uTotalOutBefore;
1813 if (zi->ci.stream.avail_out == 0)
1814 {
1815 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1816 err = ZIP_ERRNO;
1817 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1818 zi->ci.stream.next_out = zi->ci.buffered_data;
1819 }
1820 uTotalOutBefore = zi->ci.stream.total_out;
1821 err=deflate(&zi->ci.stream, Z_FINISH);
1822 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
1823 }
1824 }
1825 else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1826 {
1827 #ifdef HAVE_BZIP2
1828 err = BZ_FINISH_OK;
1829 while (err == BZ_FINISH_OK)
1830 {
1831 uLong uTotalOutBefore;
1832 if (zi->ci.bstream.avail_out == 0)
1833 {
1834 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1835 {
1836 err = ZIP_ERRNO;
1837 }
1838 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1839 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1840 }
1841 uTotalOutBefore = zi->ci.bstream.total_out_lo32;
1842 err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH);
1843 if(err == BZ_STREAM_END)
1844 {
1845 err = Z_STREAM_END;
1846 }
1847
1848 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore);
1849 }
1850
1851 if(err == BZ_FINISH_OK)
1852 {
1853 err = ZIP_OK;
1854 }
1855 #endif
1856 }
1857
1858 if (err == Z_STREAM_END)
1859 {
1860 err = ZIP_OK; /* this is normal */
1861 }
1862
1863 if ((zi->ci.pos_in_buffered_data>0) && (err == ZIP_OK))
1864 {
1865 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1866 {
1867 err = ZIP_ERRNO;
1868 }
1869 }
1870
1871 if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
1872 {
1873 int tmp_err = deflateEnd(&zi->ci.stream);
1874 if (err == ZIP_OK)
1875 {
1876 err = tmp_err;
1877 }
1878 zi->ci.stream_initialised = 0;
1879 }
1880 #ifdef HAVE_BZIP2
1881 else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
1882 {
1883 int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream);
1884 if (err == ZIP_OK)
1885 {
1886 err = tmperr;
1887 }
1888 zi->ci.stream_initialised = 0;
1889 }
1890 #endif
1891
1892 if (!zi->ci.raw)
1893 {
1894 crc32 = (uLong)zi->ci.crc32;
1895 uncompressed_size = zi->ci.totalUncompressedData;
1896 }
1897 compressed_size = zi->ci.totalCompressedData;
1898
1899 # ifndef NOCRYPT
1900 compressed_size += zi->ci.crypt_header_size;
1901 # endif
1902
1903 // update Current Item crc and sizes,
1904 if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff)
1905 {
1906 /*version Made by*/
1907 zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2);
1908 /*version needed*/
1909 zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2);
1910
1911 }
1912
1913 zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
1914
1915
1916 if(compressed_size >= 0xffffffff)
1917 {
1918 zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/
1919 }
1920 else
1921 {
1922 zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/
1923 }
1924
1925 /// set internal file attributes field
1926 if (zi->ci.stream.data_type == Z_ASCII)
1927 {
1928 zip64local_putValue_inmemory(zi->ci.central_header + 36,(uLong)Z_ASCII,2);
1929 }
1930
1931 if(uncompressed_size >= 0xffffffff)
1932 {
1933 zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/
1934 }
1935 else
1936 {
1937 zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/
1938 }
1939
1940 // Add ZIP64 extra info field for uncompressed size
1941 if(uncompressed_size >= 0xffffffff)
1942 {
1943 datasize += 8;
1944 }
1945
1946 // Add ZIP64 extra info field for compressed size
1947 if(compressed_size >= 0xffffffff)
1948 {
1949 datasize += 8;
1950 }
1951
1952 // Add ZIP64 extra info field for relative offset to local file header of current file
1953 if(zi->ci.pos_local_header >= 0xffffffff)
1954 {
1955 datasize += 8;
1956 }
1957
1958 if(datasize > 0)
1959 {
1960 char* p = NULL;
1961
1962 if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
1963 {
1964 // we cannot write more data to the buffer that we have room for.
1965 return ZIP_BADZIPFILE;
1966 }
1967
1968 p = zi->ci.central_header + zi->ci.size_centralheader;
1969
1970 // Add Extra Information Header for 'ZIP64 information'
1971 zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID
1972 p += 2;
1973 zip64local_putValue_inmemory(p, datasize, 2); // DataSize
1974 p += 2;
1975
1976 if(uncompressed_size >= 0xffffffff)
1977 {
1978 zip64local_putValue_inmemory(p, uncompressed_size, 8);
1979 p += 8;
1980 }
1981
1982 if(compressed_size >= 0xffffffff)
1983 {
1984 zip64local_putValue_inmemory(p, compressed_size, 8);
1985 p += 8;
1986 }
1987
1988 if(zi->ci.pos_local_header >= 0xffffffff)
1989 {
1990 zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8);
1991 p += 8;
1992 }
1993
1994 // Update how much extra free space we got in the memory buffer
1995 // and increase the centralheader size so the new ZIP64 fields are included
1996 // ( 4 below is the size of HeaderID and DataSize field )
1997 zi->ci.size_centralExtraFree -= datasize + 4;
1998 zi->ci.size_centralheader += datasize + 4;
1999
2000 // Update the extra info size field
2001 zi->ci.size_centralExtra += datasize + 4;
2002 zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2);
2003 }
2004
2005 if (err == ZIP_OK)
2006 {
2007 err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader);
2008 }
2009
2010 free(zi->ci.central_header);
2011
2012 if (err == ZIP_OK)
2013 {
2014 // Update the LocalFileHeader with the new values.
2015
2016 ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);
2017
2018 if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET) != 0)
2019 {
2020 err = ZIP_ERRNO;
2021 }
2022
2023 if (err==ZIP_OK)
2024 {
2025 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
2026 }
2027
2028 if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff )
2029 {
2030 if(zi->ci.pos_zip64extrainfo > 0)
2031 {
2032 // Update the size in the ZIP64 extended field.
2033 if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0)
2034 {
2035 err = ZIP_ERRNO;
2036 }
2037
2038 if (err == ZIP_OK) /* compressed size, unknown */
2039 {
2040 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8);
2041 }
2042
2043 if (err == ZIP_OK) /* uncompressed size, unknown */
2044 {
2045 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8);
2046 }
2047 }
2048 else
2049 {
2050 err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal
2051 }
2052 }
2053 else
2054 {
2055 if (err == ZIP_OK) /* compressed size, unknown */
2056 {
2057 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
2058 }
2059
2060 if (err == ZIP_OK) /* uncompressed size, unknown */
2061 {
2062 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
2063 }
2064 }
2065
2066 if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET) != 0)
2067 {
2068 err = ZIP_ERRNO;
2069 }
2070 }
2071
2072 zi->number_entry ++;
2073 zi->in_opened_file_inzip = 0;
2074
2075 return err;
2076 }
2077
zipCloseFileInZip(zipFile file)2078 extern int ZEXPORT zipCloseFileInZip(zipFile file)
2079 {
2080 return zipCloseFileInZipRaw (file,0,0);
2081 }
2082
Write_Zip64EndOfCentralDirectoryLocator(zip64_internal * zi,ZPOS64_T zip64eocd_pos_inzip)2083 local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip)
2084 {
2085 int err = ZIP_OK;
2086 ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset;
2087
2088 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4);
2089
2090 /*num disks*/
2091 if (err == ZIP_OK) /* number of the disk with the start of the central directory */
2092 {
2093 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
2094 }
2095
2096
2097 /*relative offset*/
2098 if (err == ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */
2099 {
2100 err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8);
2101 }
2102
2103 /*total disks*/ /* Do not support spawning of disk so always say 1 here*/
2104 if (err == ZIP_OK) /* number of the disk with the start of the central directory */
2105 {
2106 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4);
2107 }
2108
2109 return err;
2110 }
2111
Write_Zip64EndOfCentralDirectoryRecord(zip64_internal * zi,uLong size_centraldir,ZPOS64_T centraldir_pos_inzip)2112 local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
2113 {
2114 int err = ZIP_OK;
2115
2116 uLong Zip64DataSize = 44;
2117
2118 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4);
2119
2120 if (err == ZIP_OK) /* size of this 'zip64 end of central directory' */
2121 {
2122 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ?
2123 }
2124
2125 if (err == ZIP_OK) /* version made by */
2126 {
2127 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
2128 }
2129
2130 if (err == ZIP_OK) /* version needed */
2131 {
2132 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
2133 }
2134
2135 if (err == ZIP_OK) /* number of this disk */
2136 {
2137 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
2138 }
2139
2140 if (err == ZIP_OK) /* number of the disk with the start of the central directory */
2141 {
2142 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
2143 }
2144
2145 if (err == ZIP_OK) /* total number of entries in the central dir on this disk */
2146 {
2147 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
2148 }
2149
2150 if (err == ZIP_OK) /* total number of entries in the central dir */
2151 {
2152 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
2153 }
2154
2155 if (err == ZIP_OK) /* size of the central directory */
2156 {
2157 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8);
2158 }
2159
2160 if (err == ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
2161 {
2162 ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
2163 err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8);
2164 }
2165 return err;
2166 }
2167
Write_EndOfCentralDirectoryRecord(zip64_internal * zi,uLong size_centraldir,ZPOS64_T centraldir_pos_inzip)2168 local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
2169 {
2170 int err = ZIP_OK;
2171
2172 /*signature*/
2173 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
2174
2175 if (err == ZIP_OK) /* number of this disk */
2176 {
2177 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
2178 }
2179
2180 if (err == ZIP_OK) /* number of the disk with the start of the central directory */
2181 {
2182 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
2183 }
2184
2185 if (err == ZIP_OK) /* total number of entries in the central dir on this disk */
2186 {
2187 {
2188 if(zi->number_entry >= 0xFFFF)
2189 {
2190 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record
2191 }
2192 else
2193 {
2194 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
2195 }
2196 }
2197 }
2198
2199 if (err == ZIP_OK) /* total number of entries in the central dir */
2200 {
2201 if(zi->number_entry >= 0xFFFF)
2202 {
2203 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record
2204 }
2205 else
2206 {
2207 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
2208 }
2209 }
2210
2211 if (err == ZIP_OK) /* size of the central directory */
2212 {
2213 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
2214 }
2215
2216 if (err == ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
2217 {
2218 ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
2219 if(pos >= 0xffffffff)
2220 {
2221 err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4);
2222 }
2223 else
2224 err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4);
2225 }
2226
2227 return err;
2228 }
2229
Write_GlobalComment(zip64_internal * zi,const char * global_comment)2230 local int Write_GlobalComment(zip64_internal* zi, const char* global_comment)
2231 {
2232 int err = ZIP_OK;
2233 uInt size_global_comment = 0;
2234
2235 if(global_comment != NULL)
2236 {
2237 size_global_comment = (uInt)strlen(global_comment);
2238 }
2239
2240 err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
2241
2242 if (err == ZIP_OK && size_global_comment > 0)
2243 {
2244 if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment)
2245 {
2246 err = ZIP_ERRNO;
2247 }
2248 }
2249 return err;
2250 }
2251
zipClose(zipFile file,const char * global_comment)2252 extern int ZEXPORT zipClose(zipFile file, const char* global_comment)
2253 {
2254 zip64_internal* zi;
2255 int err = 0;
2256 uLong size_centraldir = 0;
2257 ZPOS64_T centraldir_pos_inzip;
2258 ZPOS64_T pos;
2259
2260 if (file == NULL)
2261 {
2262 return ZIP_PARAMERROR;
2263 }
2264
2265 zi = (zip64_internal*)file;
2266
2267 if (zi->in_opened_file_inzip == 1)
2268 {
2269 err = zipCloseFileInZip (file);
2270 }
2271
2272 #ifndef NO_ADDFILEINEXISTINGZIP
2273 if (global_comment == NULL)
2274 {
2275 global_comment = zi->globalcomment;
2276 }
2277 #endif
2278
2279 centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);
2280
2281 if (err == ZIP_OK)
2282 {
2283 linkedlist_datablock_internal* ldi = zi->central_dir.first_block;
2284 while (ldi != NULL)
2285 {
2286 if ((err == ZIP_OK) && (ldi->filled_in_this_block>0))
2287 {
2288 if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block)
2289 {
2290 err = ZIP_ERRNO;
2291 }
2292 }
2293
2294 size_centraldir += ldi->filled_in_this_block;
2295 ldi = ldi->next_datablock;
2296 }
2297 }
2298 free_linkedlist(&(zi->central_dir));
2299
2300 pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
2301 if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF)
2302 {
2303 ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
2304 Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
2305
2306 Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos);
2307 }
2308
2309 if (err == ZIP_OK)
2310 {
2311 err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
2312 }
2313
2314 if(err == ZIP_OK)
2315 {
2316 err = Write_GlobalComment(zi, global_comment);
2317 }
2318
2319 if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0)
2320 {
2321 if (err == ZIP_OK)
2322 {
2323 err = ZIP_ERRNO;
2324 }
2325 }
2326
2327 #ifndef NO_ADDFILEINEXISTINGZIP
2328 free(zi->globalcomment);
2329 #endif
2330 free(zi);
2331
2332 return err;
2333 }
2334
zipRemoveExtraInfoBlock(char * pData,int * dataLen,short sHeader)2335 extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader)
2336 {
2337 char* p = pData;
2338 int size = 0;
2339 char* pNewHeader;
2340 char* pTmp;
2341 short header;
2342 short dataSize;
2343
2344 int retVal = ZIP_OK;
2345
2346 if(pData == NULL || dataLen == NULL || *dataLen < 4)
2347 {
2348 return ZIP_PARAMERROR;
2349 }
2350
2351 pNewHeader = (char*)ALLOC((unsigned)*dataLen);
2352 pTmp = pNewHeader;
2353
2354 while(p < (pData + *dataLen))
2355 {
2356 header = *(short*)p;
2357 dataSize = *(((short*)p) + 1);
2358
2359 if( header == sHeader ) // Header found.
2360 {
2361 p += dataSize + 4; // skip it. do not copy to temp buffer
2362 }
2363 else
2364 {
2365 // Extra Info block should not be removed, So copy it to the temp buffer.
2366 memcpy(pTmp, p, dataSize + 4);
2367 p += dataSize + 4;
2368 size += dataSize + 4;
2369 }
2370
2371 }
2372
2373 if(size < *dataLen)
2374 {
2375 // clean old extra info block.
2376 memset(pData,0, *dataLen);
2377
2378 // copy the new extra info block over the old
2379 if(size > 0)
2380 {
2381 memcpy(pData, pNewHeader, size);
2382 }
2383
2384 // set the new extra info size
2385 *dataLen = size;
2386
2387 retVal = ZIP_OK;
2388 }
2389 else
2390 {
2391 retVal = ZIP_ERRNO;
2392 }
2393
2394 free(pNewHeader);
2395
2396 return retVal;
2397 }
2398