1 /* zip.c -- IO on .zip files using zlib
2 Version 1.1, February 14h, 2010
3 part of the MiniZip project
4
5 Copyright (C) 1998-2010 Gilles Vollant
6 http://www.winimage.com/zLibDll/minizip.html
7 Modifications for Zip64 support
8 Copyright (C) 2009-2010 Mathias Svensson
9 http://result42.com
10 Modifications for AES, PKWARE disk spanning
11 Copyright (C) 2010-2014 Nathan Moinvaziri
12
13 This program is distributed under the terms of the same license as zlib.
14 See the accompanying LICENSE file for the full text of the license.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
21 #include "zlib.h"
22 #include "zip.h"
23
24 #ifdef STDC
25 # include <stddef.h>
26 # include <string.h>
27 # include <stdlib.h>
28 #endif
29 #ifdef NO_ERRNO_H
30 extern int errno;
31 #else
32 # include <errno.h>
33 #endif
34
35
36 #ifndef NOCRYPT
37 # define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
38 # include "crypt.h"
39 #endif
40
41 #ifndef local
42 # define local static
43 #endif
44 /* compile with -Dlocal if your debugger can't find static symbols */
45
46 #define SIZEDATA_INDATABLOCK (4096-(4*4))
47
48 #define DISKHEADERMAGIC (0x08074b50)
49 #define LOCALHEADERMAGIC (0x04034b50)
50 #define CENTRALHEADERMAGIC (0x02014b50)
51 #define ENDHEADERMAGIC (0x06054b50)
52 #define ZIP64ENDHEADERMAGIC (0x06064b50)
53 #define ZIP64ENDLOCHEADERMAGIC (0x07064b50)
54
55 #define FLAG_LOCALHEADER_OFFSET (0x06)
56 #define CRC_LOCALHEADER_OFFSET (0x0e)
57
58 #define SIZECENTRALHEADER (0x2e) /* 46 */
59 #define SIZECENTRALHEADERLOCATOR (0x14) /* 20 */
60 #define SIZECENTRALDIRITEM (0x2e)
61 #define SIZEZIPLOCALHEADER (0x1e)
62
63 #ifndef BUFREADCOMMENT
64 # define BUFREADCOMMENT (0x400)
65 #endif
66 #ifndef VERSIONMADEBY
67 # define VERSIONMADEBY (0x0) /* platform dependent */
68 #endif
69
70 #ifndef Z_BUFSIZE
71 # define Z_BUFSIZE (64*1024)
72 #endif
73 #ifndef Z_MAXFILENAMEINZIP
74 # define Z_MAXFILENAMEINZIP (256)
75 #endif
76
77 #ifndef ALLOC
78 # define ALLOC(size) (malloc(size))
79 #endif
80 #ifndef TRYFREE
81 # define TRYFREE(p) {if (p) free(p);}
82 #endif
83
84 /* NOT sure that this work on ALL platform */
85 #define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32))
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
95 const char zip_copyright[] = " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
96
97 typedef struct linkedlist_datablock_internal_s
98 {
99 struct linkedlist_datablock_internal_s* next_datablock;
100 uLong avail_in_this_block;
101 uLong filled_in_this_block;
102 uLong unused; /* for future use and alignment */
103 unsigned char data[SIZEDATA_INDATABLOCK];
104 } linkedlist_datablock_internal;
105
106 typedef struct linkedlist_data_s
107 {
108 linkedlist_datablock_internal* first_block;
109 linkedlist_datablock_internal* last_block;
110 } linkedlist_data;
111
112 typedef struct
113 {
114 z_stream stream; /* zLib stream structure for inflate */
115 #ifdef HAVE_BZIP2
116 bz_stream bstream; /* bzLib stream structure for bziped */
117 #endif
118 #ifdef HAVE_AES
119 fcrypt_ctx aes_ctx;
120 prng_ctx aes_rng[1];
121 #endif
122 int stream_initialised; /* 1 is stream is initialized */
123 uInt pos_in_buffered_data; /* last written byte in buffered_data */
124
125 ZPOS64_T pos_local_header; /* offset of the local header of the file currently writing */
126 char* central_header; /* central header data for the current file */
127 uLong size_centralextra;
128 uLong size_centralheader; /* size of the central header for cur file */
129 uLong size_centralextrafree; /* Extra bytes allocated to the central header but that are not used */
130 uLong size_comment;
131 uLong flag; /* flag of the file currently writing */
132
133 int method; /* compression method written to file.*/
134 int compression_method; /* compression method to use */
135 int raw; /* 1 for directly writing raw data */
136 Byte buffered_data[Z_BUFSIZE]; /* buffer contain compressed data to be writ*/
137 uLong dosDate;
138 uLong crc32;
139 int zip64; /* Add ZIP64 extended information in the extra field */
140 uLong number_disk; /* number of current disk used for spanning ZIP */
141 ZPOS64_T pos_zip64extrainfo;
142 ZPOS64_T total_compressed;
143 ZPOS64_T total_uncompressed;
144 #ifndef NOCRYPT
145 unsigned long keys[3]; /* keys defining the pseudo-random sequence */
146 const unsigned long* pcrc_32_tab;
147 int crypt_header_size;
148 #endif
149 } curfile64_info;
150
151 typedef struct
152 {
153 zlib_filefunc64_32_def z_filefunc;
154 voidpf filestream; /* io structure of the zipfile */
155 voidpf filestream_with_CD; /* io structure of the zipfile with the central dir */
156 linkedlist_data central_dir; /* datablock with central dir in construction*/
157 int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/
158 int append; /* append mode */
159 curfile64_info ci; /* info on the file currently writing */
160
161 ZPOS64_T begin_pos; /* position of the beginning of the zipfile */
162 ZPOS64_T add_position_when_writting_offset;
163 ZPOS64_T number_entry;
164 ZPOS64_T disk_size; /* size of each disk */
165 uLong number_disk; /* number of the current disk, used for spanning ZIP */
166 uLong number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP */
167 #ifndef NO_ADDFILEINEXISTINGZIP
168 char *globalcomment;
169 #endif
170 } zip64_internal;
171
172 /* Allocate a new data block */
173 local linkedlist_datablock_internal* allocate_new_datablock OF(());
allocate_new_datablock()174 local linkedlist_datablock_internal* allocate_new_datablock()
175 {
176 linkedlist_datablock_internal* ldi;
177
178 ldi = (linkedlist_datablock_internal*)ALLOC(sizeof(linkedlist_datablock_internal));
179
180 if (ldi != NULL)
181 {
182 ldi->next_datablock = NULL;
183 ldi->filled_in_this_block = 0;
184 ldi->avail_in_this_block = SIZEDATA_INDATABLOCK;
185 }
186 return ldi;
187 }
188
189 /* Free data block in linked list */
190 local void free_datablock OF((linkedlist_datablock_internal* ldi));
free_datablock(linkedlist_datablock_internal * ldi)191 local void free_datablock(linkedlist_datablock_internal* ldi)
192 {
193 while (ldi != NULL)
194 {
195 linkedlist_datablock_internal* ldinext = ldi->next_datablock;
196 TRYFREE(ldi);
197 ldi = ldinext;
198 }
199 }
200
201 /* Initialize linked list */
202 local void init_linkedlist OF((linkedlist_data* ll));
init_linkedlist(linkedlist_data * ll)203 local void init_linkedlist(linkedlist_data* ll)
204 {
205 ll->first_block = ll->last_block = NULL;
206 }
207
208 /* Free entire linked list and all data blocks */
209 local void free_linkedlist OF((linkedlist_data* ll));
free_linkedlist(linkedlist_data * ll)210 local void free_linkedlist(linkedlist_data* ll)
211 {
212 free_datablock(ll->first_block);
213 ll->first_block = ll->last_block = NULL;
214 }
215
216 /* Add data to linked list data block */
217 local int add_data_in_datablock OF((linkedlist_data* ll, const void* buf, uLong len));
add_data_in_datablock(linkedlist_data * ll,const void * buf,uLong len)218 local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len)
219 {
220 linkedlist_datablock_internal* ldi;
221 const unsigned char* from_copy;
222
223 if (ll == NULL)
224 return ZIP_INTERNALERROR;
225
226 if (ll->last_block == NULL)
227 {
228 ll->first_block = ll->last_block = allocate_new_datablock();
229 if (ll->first_block == NULL)
230 return ZIP_INTERNALERROR;
231 }
232
233 ldi = ll->last_block;
234 from_copy = (unsigned char*)buf;
235
236 while (len>0)
237 {
238 uInt copy_this;
239 uInt i;
240 unsigned char* to_copy;
241
242 if (ldi->avail_in_this_block == 0)
243 {
244 ldi->next_datablock = allocate_new_datablock();
245 if (ldi->next_datablock == NULL)
246 return ZIP_INTERNALERROR;
247 ldi = ldi->next_datablock ;
248 ll->last_block = ldi;
249 }
250
251 if (ldi->avail_in_this_block < len)
252 copy_this = (uInt)ldi->avail_in_this_block;
253 else
254 copy_this = (uInt)len;
255
256 to_copy = &(ldi->data[ldi->filled_in_this_block]);
257
258 for (i=0;i<copy_this;i++)
259 *(to_copy+i)=*(from_copy+i);
260
261 ldi->filled_in_this_block += copy_this;
262 ldi->avail_in_this_block -= copy_this;
263 from_copy += copy_this ;
264 len -= copy_this;
265 }
266 return ZIP_OK;
267 }
268
269 local uLong zip64local_TmzDateToDosDate OF((const tm_zip* ptm));
zip64local_TmzDateToDosDate(const tm_zip * ptm)270 local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm)
271 {
272 uLong year;
273 #define zip64local_in_range(min, max, value) ((min) <= (value) && (value) <= (max))
274 /* Years supported:
275 * [00, 79] (assumed to be between 2000 and 2079)
276 * [80, 207] (assumed to be between 1980 and 2107, typical output of old
277 software that does 'year-1900' to get a double digit year)
278 * [1980, 2107]
279 Due to the date format limitations, only years between 1980 and 2107 can be stored.
280 */
281 if (!(zip64local_in_range(1980, 2107, ptm->tm_year) || zip64local_in_range(0, 207, ptm->tm_year)) ||
282 !zip64local_in_range(0, 11, ptm->tm_mon) ||
283 !zip64local_in_range(1, 31, ptm->tm_mday) ||
284 !zip64local_in_range(0, 23, ptm->tm_hour) ||
285 !zip64local_in_range(0, 59, ptm->tm_min) ||
286 !zip64local_in_range(0, 59, ptm->tm_sec))
287 return 0;
288 #undef zip64local_in_range
289
290 year = (uLong)ptm->tm_year;
291 if (year >= 1980) /* range [1980, 2107] */
292 year -= 1980;
293 else if (year >= 80) /* range [80, 99] */
294 year -= 80;
295 else /* range [00, 79] */
296 year += 20;
297
298 return
299 (uLong)(((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
300 ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
301 }
302
303 /* Inputs a long in LSB order to the given file: nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) */
304 local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream,
305 ZPOS64_T x, int nbByte));
zip64local_putValue(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,ZPOS64_T x,int nbByte)306 local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream,
307 ZPOS64_T x, int nbByte)
308 {
309 unsigned char buf[8];
310 int n;
311 for (n = 0; n < nbByte; n++)
312 {
313 buf[n] = (unsigned char)(x & 0xff);
314 x >>= 8;
315 }
316 if (x != 0)
317 {
318 /* data overflow - hack for ZIP64 (X Roche) */
319 for (n = 0; n < nbByte; n++)
320 {
321 buf[n] = 0xff;
322 }
323 }
324
325 if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
326 return ZIP_ERRNO;
327
328 return ZIP_OK;
329 }
330
331 local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte));
zip64local_putValue_inmemory(void * dest,ZPOS64_T x,int nbByte)332 local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte)
333 {
334 unsigned char* buf =(unsigned char*)dest;
335 int n;
336 for (n = 0; n < nbByte; n++) {
337 buf[n] = (unsigned char)(x & 0xff);
338 x >>= 8;
339 }
340
341 if (x != 0)
342 {
343 /* data overflow - hack for ZIP64 */
344 for (n = 0; n < nbByte; n++)
345 {
346 buf[n] = 0xff;
347 }
348 }
349 }
350
351 local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi));
zip64local_getByte(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,int * pi)352 local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi)
353 {
354 unsigned char c;
355 int err = (int)ZREAD64(*pzlib_filefunc_def, filestream, &c,1);
356 if (err == 1)
357 {
358 *pi = (int)c;
359 return ZIP_OK;
360 }
361 if (ZERROR64(*pzlib_filefunc_def, filestream))
362 return ZIP_ERRNO;
363 return ZIP_EOF;
364 }
365
366 local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX));
zip64local_getShort(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,uLong * pX)367 local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
368 {
369 uLong x;
370 int i = 0;
371 int err;
372
373 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
374 x = (uLong)i;
375 if (err == ZIP_OK)
376 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
377 x += ((uLong)i) << 8;
378
379 if (err == ZIP_OK)
380 *pX = x;
381 else
382 *pX = 0;
383 return err;
384 }
385
386 local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX));
zip64local_getLong(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,uLong * pX)387 local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)
388 {
389 uLong x;
390 int i = 0;
391 int err;
392
393 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
394 x = (uLong)i;
395 if (err == ZIP_OK)
396 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
397 x += ((uLong)i)<<8;
398 if (err == ZIP_OK)
399 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
400 x += ((uLong)i)<<16;
401 if (err == ZIP_OK)
402 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
403 x += ((uLong)i)<<24;
404
405 if (err == ZIP_OK)
406 *pX = x;
407 else
408 *pX = 0;
409 return err;
410 }
411
412 local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX));
zip64local_getLong64(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,ZPOS64_T * pX)413 local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)
414 {
415 ZPOS64_T x;
416 int i = 0;
417 int err;
418
419 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
420 x = (ZPOS64_T)i;
421 if (err == ZIP_OK)
422 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
423 x += ((ZPOS64_T)i)<<8;
424 if (err == ZIP_OK)
425 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
426 x += ((ZPOS64_T)i)<<16;
427 if (err == ZIP_OK)
428 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
429 x += ((ZPOS64_T)i)<<24;
430 if (err == ZIP_OK)
431 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
432 x += ((ZPOS64_T)i)<<32;
433 if (err == ZIP_OK)
434 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
435 x += ((ZPOS64_T)i)<<40;
436 if (err == ZIP_OK)
437 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
438 x += ((ZPOS64_T)i)<<48;
439 if (err == ZIP_OK)
440 err = zip64local_getByte(pzlib_filefunc_def, filestream, &i);
441 x += ((ZPOS64_T)i)<<56;
442
443 if (err == ZIP_OK)
444 *pX = x;
445 else
446 *pX = 0;
447
448 return err;
449 }
450
451 /* Gets the amount of bytes left to write to the current disk for spanning archives */
452 local int zipGetDiskSizeAvailable OF((zipFile file, ZPOS64_T *size_available));
zipGetDiskSizeAvailable(zipFile file,ZPOS64_T * size_available)453 local int zipGetDiskSizeAvailable(zipFile file, ZPOS64_T *size_available)
454 {
455 zip64_internal* zi;
456 ZPOS64_T current_disk_size;
457
458 zi = (zip64_internal*)file;
459 ZSEEK64(zi->z_filefunc, zi->filestream, 0, ZLIB_FILEFUNC_SEEK_END);
460 current_disk_size = ZTELL64(zi->z_filefunc, zi->filestream);
461 *size_available = zi->disk_size - current_disk_size;
462 return ZIP_OK;
463 }
464
465 /* Goes to a specific disk number for spanning archives */
466 local int zipGoToSpecificDisk OF((zipFile file, int number_disk, int open_existing));
zipGoToSpecificDisk(zipFile file,int number_disk,int open_existing)467 local int zipGoToSpecificDisk(zipFile file, int number_disk, int open_existing)
468 {
469 zip64_internal* zi;
470 int err = ZIP_OK;
471
472 zi = (zip64_internal*)file;
473 if (zi->disk_size == 0)
474 return err;
475
476 if ((zi->filestream != NULL) && (zi->filestream != zi->filestream_with_CD))
477 ZCLOSE64(zi->z_filefunc, zi->filestream);
478
479 zi->filestream = ZOPENDISK64(zi->z_filefunc, zi->filestream_with_CD, number_disk, (open_existing == 1) ?
480 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING) :
481 (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE));
482
483 if (zi->filestream == NULL)
484 err = ZIP_ERRNO;
485
486 return err;
487 }
488
489 /* Goes to the first disk in a spanned archive */
490 local int zipGoToFirstDisk OF((zipFile file));
zipGoToFirstDisk(zipFile file)491 local int zipGoToFirstDisk(zipFile file)
492 {
493 zip64_internal* zi;
494 int number_disk_next;
495 int err = ZIP_OK;
496
497 zi = (zip64_internal*)file;
498
499 if (zi->disk_size == 0)
500 return err;
501 number_disk_next = 0;
502 if (zi->number_disk_with_CD > 0)
503 number_disk_next = zi->number_disk_with_CD - 1;
504 err = zipGoToSpecificDisk(file, number_disk_next, (zi->append == APPEND_STATUS_ADDINZIP));
505 if ((err == ZIP_ERRNO) && (zi->append == APPEND_STATUS_ADDINZIP))
506 err = zipGoToSpecificDisk(file, number_disk_next, 0);
507 if (err == ZIP_OK)
508 zi->number_disk = number_disk_next;
509 ZSEEK64(zi->z_filefunc, zi->filestream, 0, ZLIB_FILEFUNC_SEEK_END);
510 return err;
511 }
512
513 /* Goes to the next disk in a spanned archive */
514 local int zipGoToNextDisk OF((zipFile file));
zipGoToNextDisk(zipFile file)515 local int zipGoToNextDisk(zipFile file)
516 {
517 zip64_internal* zi;
518 ZPOS64_T size_available_in_disk;
519 int err = ZIP_OK;
520 int number_disk_next;
521
522 zi = (zip64_internal*)file;
523
524 if (zi->disk_size == 0)
525 return err;
526
527 number_disk_next = zi->number_disk + 1;
528
529 do
530 {
531 err = zipGoToSpecificDisk(file, number_disk_next, (zi->append == APPEND_STATUS_ADDINZIP));
532 if ((err == ZIP_ERRNO) && (zi->append == APPEND_STATUS_ADDINZIP))
533 err = zipGoToSpecificDisk(file, number_disk_next, 0);
534 if (err != ZIP_OK)
535 break;
536 err = zipGetDiskSizeAvailable(file, &size_available_in_disk);
537 if (err != ZIP_OK)
538 break;
539 zi->number_disk = number_disk_next;
540 zi->number_disk_with_CD = zi->number_disk + 1;
541
542 number_disk_next += 1;
543 }
544 while (size_available_in_disk <= 0);
545
546 return err;
547 }
548
549 /* Locate the Central directory of a zipfile (at the end, just before the global comment) */
550 local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
zip64local_SearchCentralDir(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream)551 local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
552 {
553 unsigned char* buf;
554 ZPOS64_T file_size;
555 ZPOS64_T back_read = 4;
556 ZPOS64_T max_back=0xffff; /* maximum size of global comment */
557 ZPOS64_T pos_found=0;
558 uLong read_size;
559 ZPOS64_T read_pos;
560 int i;
561
562 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
563 if (buf == NULL)
564 return 0;
565
566 if (ZSEEK64(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
567 {
568 TRYFREE(buf);
569 return 0;
570 }
571
572 file_size = ZTELL64(*pzlib_filefunc_def, filestream);
573
574 if (max_back > file_size)
575 max_back = file_size;
576
577 while (back_read < max_back)
578 {
579 if (back_read + BUFREADCOMMENT > max_back)
580 back_read = max_back;
581 else
582 back_read += BUFREADCOMMENT;
583
584 read_pos = file_size-back_read;
585 read_size = ((BUFREADCOMMENT+4) < (file_size-read_pos)) ?
586 (BUFREADCOMMENT+4) : (uLong)(file_size-read_pos);
587
588 if (ZSEEK64(*pzlib_filefunc_def, filestream, read_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
589 break;
590 if (ZREAD64(*pzlib_filefunc_def, filestream, buf, read_size) != read_size)
591 break;
592
593 for (i = (int)read_size-3; (i--) > 0;)
594 if ((*(buf+i)) == (ENDHEADERMAGIC & 0xff) &&
595 (*(buf+i+1)) == (ENDHEADERMAGIC >> 8 & 0xff) &&
596 (*(buf+i+2)) == (ENDHEADERMAGIC >> 16 & 0xff) &&
597 (*(buf+i+3)) == (ENDHEADERMAGIC >> 24 & 0xff))
598 {
599 pos_found = read_pos+i;
600 break;
601 }
602
603 if (pos_found != 0)
604 break;
605 }
606 TRYFREE(buf);
607 return pos_found;
608 }
609
610 /* Locate the Central directory 64 of a zipfile (at the end, just before the global comment) */
611 local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream,
612 const ZPOS64_T endcentraloffset));
zip64local_SearchCentralDir64(const zlib_filefunc64_32_def * pzlib_filefunc_def,voidpf filestream,const ZPOS64_T endcentraloffset)613 local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream,
614 const ZPOS64_T endcentraloffset)
615 {
616 ZPOS64_T offset;
617 uLong uL;
618
619 /* Zip64 end of central directory locator */
620 if (ZSEEK64(*pzlib_filefunc_def, filestream, endcentraloffset - SIZECENTRALHEADERLOCATOR, ZLIB_FILEFUNC_SEEK_SET) != 0)
621 return 0;
622
623 /* read locator signature */
624 if (zip64local_getLong(pzlib_filefunc_def, filestream, &uL) != ZIP_OK)
625 return 0;
626 if (uL != ZIP64ENDLOCHEADERMAGIC)
627 return 0;
628 /* number of the disk with the start of the zip64 end of central directory */
629 if (zip64local_getLong(pzlib_filefunc_def, filestream, &uL) != ZIP_OK)
630 return 0;
631 /* relative offset of the zip64 end of central directory record */
632 if (zip64local_getLong64(pzlib_filefunc_def, filestream, &offset) != ZIP_OK)
633 return 0;
634 /* total number of disks */
635 if (zip64local_getLong(pzlib_filefunc_def, filestream, &uL) != ZIP_OK)
636 return 0;
637 /* Goto end of central directory record */
638 if (ZSEEK64(*pzlib_filefunc_def,filestream, offset, ZLIB_FILEFUNC_SEEK_SET) != 0)
639 return 0;
640 /* the signature */
641 if (zip64local_getLong(pzlib_filefunc_def, filestream, &uL) != ZIP_OK)
642 return 0;
643 if (uL != ZIP64ENDHEADERMAGIC)
644 return 0;
645
646 return offset;
647 }
648
zipOpen4(const void * pathname,int append,ZPOS64_T disk_size,zipcharpc * globalcomment,zlib_filefunc64_32_def * pzlib_filefunc64_32_def)649 extern zipFile ZEXPORT zipOpen4(const void *pathname, int append, ZPOS64_T disk_size, zipcharpc* globalcomment,
650 zlib_filefunc64_32_def* pzlib_filefunc64_32_def)
651 {
652 zip64_internal ziinit;
653 zip64_internal* zi;
654 #ifndef NO_ADDFILEINEXISTINGZIP
655 ZPOS64_T byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx)*/
656 ZPOS64_T size_central_dir; /* size of the central directory */
657 ZPOS64_T offset_central_dir; /* offset of start of central directory */
658 ZPOS64_T number_entry_CD; /* total number of entries in the central dir */
659 ZPOS64_T number_entry;
660 ZPOS64_T central_pos;
661 ZPOS64_T size_central_dir_to_read;
662 uLong uL;
663 uLong size_comment;
664 size_t buf_size = SIZEDATA_INDATABLOCK;
665 void* buf_read;
666 #endif
667 int err = ZIP_OK;
668 int mode;
669
670 ziinit.z_filefunc.zseek32_file = NULL;
671 ziinit.z_filefunc.ztell32_file = NULL;
672 if (pzlib_filefunc64_32_def == NULL)
673 fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);
674 else
675 ziinit.z_filefunc = *pzlib_filefunc64_32_def;
676
677 if (append == APPEND_STATUS_CREATE)
678 mode = (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE);
679 else
680 mode = (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING);
681
682 ziinit.filestream = ZOPEN64(ziinit.z_filefunc, pathname, mode);
683 if (ziinit.filestream == NULL)
684 return NULL;
685
686 if (append == APPEND_STATUS_CREATEAFTER)
687 {
688 /* Don't support spanning ZIP with APPEND_STATUS_CREATEAFTER */
689 if (disk_size > 0)
690 return NULL;
691
692 ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END);
693 }
694
695 ziinit.filestream_with_CD = ziinit.filestream;
696 ziinit.append = append;
697 ziinit.number_disk = 0;
698 ziinit.number_disk_with_CD = 0;
699 ziinit.disk_size = disk_size;
700 ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream);
701 ziinit.in_opened_file_inzip = 0;
702 ziinit.ci.stream_initialised = 0;
703 ziinit.number_entry = 0;
704 ziinit.add_position_when_writting_offset = 0;
705 init_linkedlist(&(ziinit.central_dir));
706
707 zi = (zip64_internal*)ALLOC(sizeof(zip64_internal));
708 if (zi == NULL)
709 {
710 ZCLOSE64(ziinit.z_filefunc,ziinit.filestream);
711 return NULL;
712 }
713
714 #ifndef NO_ADDFILEINEXISTINGZIP
715 /* Add file in a zipfile */
716 ziinit.globalcomment = NULL;
717 if (append == APPEND_STATUS_ADDINZIP)
718 {
719 /* Read and Cache Central Directory Records */
720 central_pos = zip64local_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);
721 /* disable to allow appending to empty ZIP archive (must be standard zip, not zip64)
722 if (central_pos == 0)
723 err = ZIP_ERRNO;
724 */
725
726 if (err == ZIP_OK)
727 {
728 /* read end of central directory info */
729 if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET) != 0)
730 err = ZIP_ERRNO;
731
732 /* the signature, already checked */
733 if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
734 err = ZIP_ERRNO;
735 /* number of this disk */
736 if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk) != ZIP_OK)
737 err = ZIP_ERRNO;
738 /* number of the disk with the start of the central directory */
739 if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk_with_CD) != ZIP_OK)
740 err = ZIP_ERRNO;
741 /* total number of entries in the central dir on this disk */
742 number_entry = 0;
743 if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
744 err = ZIP_ERRNO;
745 else
746 number_entry = uL;
747 /* total number of entries in the central dir */
748 number_entry_CD = 0;
749 if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
750 err = ZIP_ERRNO;
751 else
752 number_entry_CD = uL;
753 if (number_entry_CD!=number_entry)
754 err = ZIP_BADZIPFILE;
755 /* size of the central directory */
756 size_central_dir = 0;
757 if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
758 err = ZIP_ERRNO;
759 else
760 size_central_dir = uL;
761 /* offset of start of central directory with respect to the starting disk number */
762 offset_central_dir = 0;
763 if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
764 err = ZIP_ERRNO;
765 else
766 offset_central_dir = uL;
767 /* zipfile global comment length */
768 if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &size_comment) != ZIP_OK)
769 err = ZIP_ERRNO;
770
771 if ((err == ZIP_OK) && ((number_entry_CD == 0xffff) || (offset_central_dir == 0xffffffff)))
772 {
773 /* Format should be Zip64, as the central directory or file size is too large */
774 central_pos = zip64local_SearchCentralDir64(&ziinit.z_filefunc, ziinit.filestream, central_pos);
775
776 if (central_pos)
777 {
778 ZPOS64_T sizeEndOfCentralDirectory;
779
780 if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
781 err = ZIP_ERRNO;
782
783 /* the signature, already checked */
784 if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
785 err = ZIP_ERRNO;
786 /* size of zip64 end of central directory record */
787 if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &sizeEndOfCentralDirectory) != ZIP_OK)
788 err = ZIP_ERRNO;
789 /* version made by */
790 if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
791 err = ZIP_ERRNO;
792 /* version needed to extract */
793 if (zip64local_getShort(&ziinit.z_filefunc, ziinit.filestream, &uL) != ZIP_OK)
794 err = ZIP_ERRNO;
795 /* number of this disk */
796 if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk) != ZIP_OK)
797 err = ZIP_ERRNO;
798 /* number of the disk with the start of the central directory */
799 if (zip64local_getLong(&ziinit.z_filefunc, ziinit.filestream, &ziinit.number_disk_with_CD) != ZIP_OK)
800 err = ZIP_ERRNO;
801 /* total number of entries in the central directory on this disk */
802 if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &number_entry) != ZIP_OK)
803 err = ZIP_ERRNO;
804 /* total number of entries in the central directory */
805 if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &number_entry_CD) != ZIP_OK)
806 err = ZIP_ERRNO;
807 if (number_entry_CD!=number_entry)
808 err = ZIP_BADZIPFILE;
809 /* size of the central directory */
810 if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &size_central_dir) != ZIP_OK)
811 err = ZIP_ERRNO;
812 /* offset of start of central directory with respect to the starting disk number */
813 if (zip64local_getLong64(&ziinit.z_filefunc, ziinit.filestream, &offset_central_dir) != ZIP_OK)
814 err = ZIP_ERRNO;
815 }
816 else
817 err = ZIP_BADZIPFILE;
818 }
819 }
820
821 if ((err == ZIP_OK) && (central_pos<offset_central_dir+size_central_dir))
822 err = ZIP_BADZIPFILE;
823
824 if (err != ZIP_OK)
825 {
826 ZCLOSE64(ziinit.z_filefunc, ziinit.filestream);
827 TRYFREE(zi);
828 return NULL;
829 }
830
831 if (size_comment > 0)
832 {
833 ziinit.globalcomment = (char*)ALLOC(size_comment+1);
834 if (ziinit.globalcomment)
835 {
836 size_comment = ZREAD64(ziinit.z_filefunc, ziinit.filestream, ziinit.globalcomment, size_comment);
837 ziinit.globalcomment[size_comment] = 0;
838 }
839 }
840
841 byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir);
842 ziinit.add_position_when_writting_offset = byte_before_the_zipfile;
843
844 /* Store central directory in memory */
845 size_central_dir_to_read = size_central_dir;
846 buf_size = SIZEDATA_INDATABLOCK;
847 buf_read = (void*)ALLOC(buf_size);
848
849 if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream,
850 offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
851 err = ZIP_ERRNO;
852
853 while ((size_central_dir_to_read > 0) && (err == ZIP_OK))
854 {
855 ZPOS64_T read_this = SIZEDATA_INDATABLOCK;
856 if (read_this > size_central_dir_to_read)
857 read_this = size_central_dir_to_read;
858
859 if (ZREAD64(ziinit.z_filefunc, ziinit.filestream, buf_read, (uLong)read_this) != read_this)
860 err = ZIP_ERRNO;
861
862 if (err == ZIP_OK)
863 err = add_data_in_datablock(&ziinit.central_dir, buf_read, (uLong)read_this);
864
865 size_central_dir_to_read -= read_this;
866 }
867 TRYFREE(buf_read);
868
869 ziinit.begin_pos = byte_before_the_zipfile;
870 ziinit.number_entry = number_entry_CD;
871
872 if (ZSEEK64(ziinit.z_filefunc, ziinit.filestream,
873 offset_central_dir+byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
874 err = ZIP_ERRNO;
875 }
876
877 if (globalcomment)
878 *globalcomment = ziinit.globalcomment;
879 #endif
880
881 if (err != ZIP_OK)
882 {
883 #ifndef NO_ADDFILEINEXISTINGZIP
884 TRYFREE(ziinit.globalcomment);
885 #endif
886 TRYFREE(zi);
887 return NULL;
888 }
889
890 *zi = ziinit;
891 zipGoToFirstDisk((zipFile)zi);
892 return(zipFile)zi;
893 }
894
zipOpen2(const char * pathname,int append,zipcharpc * globalcomment,zlib_filefunc_def * pzlib_filefunc32_def)895 extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc* globalcomment,
896 zlib_filefunc_def* pzlib_filefunc32_def)
897 {
898 if (pzlib_filefunc32_def != NULL)
899 {
900 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
901 fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
902 return zipOpen4(pathname, append, 0, globalcomment, &zlib_filefunc64_32_def_fill);
903 }
904 return zipOpen4(pathname, append, 0, globalcomment, NULL);
905 }
906
zipOpen2_64(const void * pathname,int append,zipcharpc * globalcomment,zlib_filefunc64_def * pzlib_filefunc_def)907 extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment,
908 zlib_filefunc64_def* pzlib_filefunc_def)
909 {
910 if (pzlib_filefunc_def != NULL)
911 {
912 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
913 zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
914 zlib_filefunc64_32_def_fill.ztell32_file = NULL;
915 zlib_filefunc64_32_def_fill.zseek32_file = NULL;
916 return zipOpen4(pathname, append, 0, globalcomment, &zlib_filefunc64_32_def_fill);
917 }
918 return zipOpen4(pathname, append, 0, globalcomment, NULL);
919 }
920
zipOpen3(const char * pathname,int append,ZPOS64_T disk_size,zipcharpc * globalcomment,zlib_filefunc_def * pzlib_filefunc32_def)921 extern zipFile ZEXPORT zipOpen3(const char *pathname, int append, ZPOS64_T disk_size, zipcharpc* globalcomment,
922 zlib_filefunc_def* pzlib_filefunc32_def)
923 {
924 if (pzlib_filefunc32_def != NULL)
925 {
926 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
927 fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
928 return zipOpen4(pathname, append, disk_size, globalcomment, &zlib_filefunc64_32_def_fill);
929 }
930 return zipOpen4(pathname, append, disk_size, globalcomment, NULL);
931 }
932
zipOpen3_64(const void * pathname,int append,ZPOS64_T disk_size,zipcharpc * globalcomment,zlib_filefunc64_def * pzlib_filefunc_def)933 extern zipFile ZEXPORT zipOpen3_64(const void *pathname, int append, ZPOS64_T disk_size, zipcharpc* globalcomment,
934 zlib_filefunc64_def* pzlib_filefunc_def)
935 {
936 if (pzlib_filefunc_def != NULL)
937 {
938 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
939 zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
940 zlib_filefunc64_32_def_fill.ztell32_file = NULL;
941 zlib_filefunc64_32_def_fill.zseek32_file = NULL;
942 return zipOpen4(pathname, append, disk_size, globalcomment, &zlib_filefunc64_32_def_fill);
943 }
944 return zipOpen4(pathname, append, disk_size, globalcomment, NULL);
945 }
946
zipOpen(const char * pathname,int append)947 extern zipFile ZEXPORT zipOpen(const char* pathname, int append)
948 {
949 return zipOpen3((const void*)pathname,append,0,NULL,NULL);
950 }
951
zipOpen64(const void * pathname,int append)952 extern zipFile ZEXPORT zipOpen64(const void* pathname, int append)
953 {
954 return zipOpen3(pathname,append,0,NULL,NULL);
955 }
956
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)957 extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
958 const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
959 uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel,
960 int strategy, const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase, int zip64)
961 {
962 zip64_internal* zi;
963 uInt size_filename;
964 uInt size_comment = 0;
965 uInt i;
966 int err = ZIP_OK;
967 ZPOS64_T size_available;
968 ZPOS64_T size_needed;
969
970 #ifdef NOCRYPT
971 (crcForCrypting);
972 if (password != NULL)
973 return ZIP_PARAMERROR;
974 #endif
975
976 if (file == NULL)
977 return ZIP_PARAMERROR;
978
979 if ((method != 0) &&
980 #ifdef HAVE_BZIP2
981 (method != Z_BZIP2ED) &&
982 #endif
983 (method != Z_DEFLATED))
984 return ZIP_PARAMERROR;
985
986 zi = (zip64_internal*)file;
987
988 if (zi->in_opened_file_inzip == 1)
989 {
990 err = zipCloseFileInZip (file);
991 if (err != ZIP_OK)
992 return err;
993 }
994
995 if (filename == NULL)
996 filename = "-";
997 if (comment != NULL)
998 size_comment = (uInt)strlen(comment);
999
1000 size_filename = (uInt)strlen(filename);
1001
1002 if (zipfi == NULL)
1003 zi->ci.dosDate = 0;
1004 else
1005 {
1006 if (zipfi->dosDate != 0)
1007 zi->ci.dosDate = zipfi->dosDate;
1008 else
1009 zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date);
1010 }
1011
1012 zi->ci.method = method;
1013 zi->ci.compression_method = method;
1014 zi->ci.crc32 = 0;
1015 zi->ci.stream_initialised = 0;
1016 zi->ci.pos_in_buffered_data = 0;
1017 zi->ci.raw = raw;
1018 zi->ci.flag = flagBase;
1019 if ((level == 8) || (level == 9))
1020 zi->ci.flag |= 2;
1021 if (level == 2)
1022 zi->ci.flag |= 4;
1023 if (level == 1)
1024 zi->ci.flag |= 6;
1025 if (password != NULL)
1026 {
1027 zi->ci.flag |= 1;
1028 #ifdef HAVE_AES
1029 zi->ci.method = AES_METHOD;
1030 #endif
1031 }
1032
1033 if (zi->disk_size > 0)
1034 {
1035 if ((zi->number_disk == 0) && (zi->number_entry == 0))
1036 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)DISKHEADERMAGIC, 4);
1037
1038 /* Make sure enough space available on current disk for local header */
1039 zipGetDiskSizeAvailable((zipFile)zi, &size_available);
1040 size_needed = 30 + size_filename + size_extrafield_local;
1041 if (zi->ci.zip64)
1042 size_needed += 20;
1043 #ifdef HAVE_AES
1044 if (zi->ci.method == AES_METHOD)
1045 size_needed += 11;
1046 #endif
1047 if (size_available < size_needed)
1048 zipGoToNextDisk((zipFile)zi);
1049 }
1050
1051 zi->ci.pos_local_header = ZTELL64(zi->z_filefunc, zi->filestream);
1052 zi->ci.size_comment = size_comment;
1053 zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global;
1054 zi->ci.size_centralextra = size_extrafield_global;
1055 zi->ci.size_centralextrafree = 32; /* Extra space reserved for ZIP64 extra info */
1056 #ifdef HAVE_AES
1057 if (zi->ci.method == AES_METHOD)
1058 zi->ci.size_centralextrafree += 11; /* Extra space reserved for AES extra info */
1059 #endif
1060 zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralextrafree + size_comment);
1061 zi->ci.number_disk = zi->number_disk;
1062
1063 /* Write central directory header */
1064 zip64local_putValue_inmemory(zi->ci.central_header, (uLong)CENTRALHEADERMAGIC, 4);
1065 zip64local_putValue_inmemory(zi->ci.central_header+4, (uLong)versionMadeBy, 2);
1066 zip64local_putValue_inmemory(zi->ci.central_header+6, (uLong)20, 2);
1067 zip64local_putValue_inmemory(zi->ci.central_header+8, (uLong)zi->ci.flag, 2);
1068 zip64local_putValue_inmemory(zi->ci.central_header+10, (uLong)zi->ci.method, 2);
1069 zip64local_putValue_inmemory(zi->ci.central_header+12, (uLong)zi->ci.dosDate, 4);
1070 zip64local_putValue_inmemory(zi->ci.central_header+16, (uLong)0, 4); /*crc*/
1071 zip64local_putValue_inmemory(zi->ci.central_header+20, (uLong)0, 4); /*compr size*/
1072 zip64local_putValue_inmemory(zi->ci.central_header+24, (uLong)0, 4); /*uncompr size*/
1073 zip64local_putValue_inmemory(zi->ci.central_header+28, (uLong)size_filename, 2);
1074 zip64local_putValue_inmemory(zi->ci.central_header+30, (uLong)size_extrafield_global, 2);
1075 zip64local_putValue_inmemory(zi->ci.central_header+32, (uLong)size_comment, 2);
1076 zip64local_putValue_inmemory(zi->ci.central_header+34, (uLong)zi->ci.number_disk, 2); /*disk nm start*/
1077
1078 if (zipfi == NULL)
1079 zip64local_putValue_inmemory(zi->ci.central_header+36, (uLong)0, 2);
1080 else
1081 zip64local_putValue_inmemory(zi->ci.central_header+36, (uLong)zipfi->internal_fa, 2);
1082 if (zipfi == NULL)
1083 zip64local_putValue_inmemory(zi->ci.central_header+38, (uLong)0, 4);
1084 else
1085 zip64local_putValue_inmemory(zi->ci.central_header+38, (uLong)zipfi->external_fa, 4);
1086 if (zi->ci.pos_local_header >= 0xffffffff)
1087 zip64local_putValue_inmemory(zi->ci.central_header+42, (uLong)0xffffffff, 4);
1088 else
1089 zip64local_putValue_inmemory(zi->ci.central_header+42,
1090 (uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset, 4);
1091
1092 for (i = 0; i < size_filename; i++)
1093 zi->ci.central_header[SIZECENTRALHEADER+i] = filename[i];
1094 for (i = 0; i < size_extrafield_global; i++)
1095 zi->ci.central_header[SIZECENTRALHEADER+size_filename+i] =
1096 ((const char*)extrafield_global)[i];
1097 /* Store comment at the end for later repositioning */
1098 for (i = 0; i < size_comment; i++)
1099 zi->ci.central_header[zi->ci.size_centralheader+
1100 zi->ci.size_centralextrafree+i] = comment[i];
1101
1102 if (zi->ci.central_header == NULL)
1103 return ZIP_INTERNALERROR;
1104
1105 zi->ci.zip64 = zip64;
1106 zi->ci.total_compressed = 0;
1107 zi->ci.total_uncompressed = 0;
1108 zi->ci.pos_zip64extrainfo = 0;
1109
1110 /* Write the local header */
1111 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)LOCALHEADERMAGIC, 4);
1112
1113 if (err == ZIP_OK)
1114 {
1115 if (zi->ci.zip64)
1116 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)45, 2); /* version needed to extract */
1117 else
1118 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)20, 2); /* version needed to extract */
1119 }
1120 if (err == ZIP_OK)
1121 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->ci.flag, 2);
1122 if (err == ZIP_OK)
1123 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->ci.method, 2);
1124 if (err == ZIP_OK)
1125 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->ci.dosDate, 4);
1126
1127 /* CRC & compressed size & uncompressed size will be filled in later and rewritten later */
1128
1129 if (err == ZIP_OK)
1130 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0, 4); /* crc 32, unknown */
1131 if (err == ZIP_OK)
1132 {
1133 if (zi->ci.zip64)
1134 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xFFFFFFFF, 4); /* compressed size, unknown */
1135 else
1136 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0, 4); /* compressed size, unknown */
1137 }
1138 if (err == ZIP_OK)
1139 {
1140 if (zi->ci.zip64) /* uncompressed size, unknown */
1141 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xFFFFFFFF, 4);
1142 else /* uncompressed size, unknown */
1143 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0, 4);
1144 }
1145 if (err == ZIP_OK)
1146 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)size_filename, 2);
1147 if (err == ZIP_OK)
1148 {
1149 ZPOS64_T size_extrafield = size_extrafield_local;
1150 if (zi->ci.zip64)
1151 size_extrafield += 20;
1152 #ifdef HAVE_AES
1153 if (zi->ci.method == AES_METHOD)
1154 size_extrafield += 11;
1155 #endif
1156 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)size_extrafield,2);
1157 }
1158 if ((err == ZIP_OK) && (size_filename > 0))
1159 {
1160 if (ZWRITE64(zi->z_filefunc, zi->filestream, filename, size_filename) != size_filename)
1161 err = ZIP_ERRNO;
1162 }
1163 if ((err == ZIP_OK) && (size_extrafield_local > 0))
1164 {
1165 if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local)
1166 err = ZIP_ERRNO;
1167 }
1168
1169 /* Write the Zip64 extended info */
1170 if ((err == ZIP_OK) && (zi->ci.zip64))
1171 {
1172 short headerid = 1;
1173 short datasize = 16;
1174 ZPOS64_T compressed_size = 0;
1175 ZPOS64_T uncompressed_size = 0;
1176
1177 /* Remember position of Zip64 extended info for the local file header.
1178 (needed when we update size after done with file) */
1179 zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc, zi->filestream);
1180
1181 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)headerid, 2);
1182 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)datasize, 2);
1183
1184 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)uncompressed_size, 8);
1185 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)compressed_size, 8);
1186 }
1187 #ifdef HAVE_AES
1188 /* Write the AES extended info */
1189 if ((err == ZIP_OK) && (zi->ci.method == AES_METHOD))
1190 {
1191 int headerid = 0x9901;
1192 short datasize = 7;
1193
1194 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, headerid, 2);
1195 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, datasize, 2);
1196
1197 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, AES_VERSION, 2);
1198 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, 'A', 1);
1199 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, 'E', 1);
1200 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, AES_ENCRYPTIONMODE, 1);
1201 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->ci.compression_method, 2);
1202 }
1203 #endif
1204
1205 #ifdef HAVE_BZIP2
1206 zi->ci.bstream.avail_in = (uInt)0;
1207 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1208 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1209 zi->ci.bstream.total_in_hi32 = 0;
1210 zi->ci.bstream.total_in_lo32 = 0;
1211 zi->ci.bstream.total_out_hi32 = 0;
1212 zi->ci.bstream.total_out_lo32 = 0;
1213 #endif
1214
1215 zi->ci.stream.avail_in = (uInt)0;
1216 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1217 zi->ci.stream.next_out = zi->ci.buffered_data;
1218 zi->ci.stream.total_in = 0;
1219 zi->ci.stream.total_out = 0;
1220 zi->ci.stream.data_type = Z_BINARY;
1221
1222 if ((err == ZIP_OK) && (!zi->ci.raw))
1223 {
1224 if (method == Z_DEFLATED)
1225 {
1226 zi->ci.stream.zalloc = (alloc_func)0;
1227 zi->ci.stream.zfree = (free_func)0;
1228 zi->ci.stream.opaque = (voidpf)zi;
1229
1230 if (windowBits > 0)
1231 windowBits = -windowBits;
1232
1233 err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy);
1234
1235 if (err == Z_OK)
1236 zi->ci.stream_initialised = Z_DEFLATED;
1237 }
1238 else if (method == Z_BZIP2ED)
1239 {
1240 #ifdef HAVE_BZIP2
1241 zi->ci.bstream.bzalloc = 0;
1242 zi->ci.bstream.bzfree = 0;
1243 zi->ci.bstream.opaque = (voidpf)0;
1244
1245 err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0, 35);
1246 if (err == BZ_OK)
1247 zi->ci.stream_initialised = Z_BZIP2ED;
1248 #endif
1249 }
1250 }
1251
1252 #ifndef NOCRYPT
1253 zi->ci.crypt_header_size = 0;
1254 if ((err == Z_OK) && ((zi->ci.flag & 1) != 0))
1255 {
1256 #ifdef HAVE_AES
1257 if (zi->ci.method == AES_METHOD)
1258 {
1259 unsigned char passverify[AES_PWVERIFYSIZE];
1260 unsigned char saltvalue[AES_MAXSALTLENGTH];
1261 uInt saltlength;
1262
1263 if ((AES_ENCRYPTIONMODE < 1) || (AES_ENCRYPTIONMODE > 3))
1264 return Z_ERRNO;
1265
1266 saltlength = SALT_LENGTH(AES_ENCRYPTIONMODE);
1267
1268 prng_init(entropy_fun, zi->ci.aes_rng);
1269 prng_rand(saltvalue, saltlength, zi->ci.aes_rng);
1270 prng_end(zi->ci.aes_rng);
1271
1272 fcrypt_init(AES_ENCRYPTIONMODE, password, strlen(password), saltvalue, passverify, &zi->ci.aes_ctx);
1273
1274 if (ZWRITE64(zi->z_filefunc, zi->filestream, saltvalue, saltlength) != saltlength)
1275 err = ZIP_ERRNO;
1276 if (ZWRITE64(zi->z_filefunc, zi->filestream, passverify, AES_PWVERIFYSIZE) != AES_PWVERIFYSIZE)
1277 err = ZIP_ERRNO;
1278
1279 zi->ci.crypt_header_size = saltlength + AES_PWVERIFYSIZE + AES_AUTHCODESIZE;
1280 }
1281 else
1282 #endif
1283 {
1284 unsigned char bufHead[RAND_HEAD_LEN];
1285 unsigned int sizeHead;
1286
1287 zi->ci.pcrc_32_tab = (const unsigned long *)get_crc_table();
1288 /*init_keys(password, zi->ci.keys, zi->ci.pcrc_32_tab);*/
1289
1290 sizeHead = crypthead(password, bufHead, RAND_HEAD_LEN, zi->ci.keys, zi->ci.pcrc_32_tab, crcForCrypting);
1291 zi->ci.crypt_header_size = sizeHead;
1292
1293 if (ZWRITE64(zi->z_filefunc, zi->filestream, bufHead, sizeHead) != sizeHead)
1294 err = ZIP_ERRNO;
1295 }
1296 }
1297 #endif
1298
1299 if (err == Z_OK)
1300 zi->in_opened_file_inzip = 1;
1301 return err;
1302 }
1303
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)1304 extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1305 const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
1306 uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits,
1307 int memLevel, int strategy, const char* password, uLong crcForCrypting, uLong versionMadeBy, uLong flagBase)
1308 {
1309 return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local,
1310 extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel,
1311 strategy, password, crcForCrypting, versionMadeBy, flagBase, 0);
1312 }
1313
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)1314 extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1315 const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
1316 uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits,
1317 int memLevel, int strategy, const char* password, uLong crcForCrypting)
1318 {
1319 return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local,
1320 extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel,
1321 strategy, password, crcForCrypting, VERSIONMADEBY, 0, 0);
1322 }
1323
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)1324 extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1325 const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
1326 uInt size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits,
1327 int memLevel, int strategy, const char* password, uLong crcForCrypting, int zip64)
1328 {
1329 return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local,
1330 extrafield_global, size_extrafield_global, comment, method, level, raw, windowBits, memLevel, strategy,
1331 password, crcForCrypting, VERSIONMADEBY, 0, zip64);
1332 }
1333
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)1334 extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1335 const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
1336 uInt size_extrafield_global, const char* comment, int method, int level, int raw)
1337 {
1338 return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local,
1339 extrafield_global, size_extrafield_global, comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL,
1340 Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, 0);
1341 }
1342
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)1343 extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1344 const void* extrafield_local, uInt size_extrafield_local, const void* extrafield_global,
1345 uInt size_extrafield_global, const char* comment, int method, int level, int raw, int zip64)
1346 {
1347 return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local,
1348 extrafield_global, size_extrafield_global, comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL,
1349 Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, zip64);
1350 }
1351
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)1352 extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1353 const void* extrafield_local, uInt size_extrafield_local, const void*extrafield_global,
1354 uInt size_extrafield_global, const char* comment, int method, int level, int zip64)
1355 {
1356 return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local,
1357 extrafield_global, size_extrafield_global, comment, method, level, 0, -MAX_WBITS, DEF_MEM_LEVEL,
1358 Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, zip64);
1359 }
1360
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)1361 extern int ZEXPORT zipOpenNewFileInZip(zipFile file, const char* filename, const zip_fileinfo* zipfi,
1362 const void* extrafield_local, uInt size_extrafield_local, const void*extrafield_global,
1363 uInt size_extrafield_global, const char* comment, int method, int level)
1364 {
1365 return zipOpenNewFileInZip4_64(file, filename, zipfi, extrafield_local, size_extrafield_local,
1366 extrafield_global, size_extrafield_global, comment, method, level, 0, -MAX_WBITS, DEF_MEM_LEVEL,
1367 Z_DEFAULT_STRATEGY, NULL, 0, VERSIONMADEBY, 0, 0);
1368 }
1369
1370 /* Flushes the write buffer to disk */
1371 local int zip64FlushWriteBuffer OF((zip64_internal* zi));
zip64FlushWriteBuffer(zip64_internal * zi)1372 local int zip64FlushWriteBuffer(zip64_internal* zi)
1373 {
1374 int err = ZIP_OK;
1375 uInt written = 0;
1376 uInt total_written = 0;
1377 uInt write = 0;
1378 uInt max_write = 0;
1379 ZPOS64_T size_available = 0;
1380
1381 if ((zi->ci.flag & 1) != 0)
1382 {
1383 #ifndef NOCRYPT
1384 #ifdef HAVE_AES
1385 if (zi->ci.method == AES_METHOD)
1386 {
1387 fcrypt_encrypt(zi->ci.buffered_data, zi->ci.pos_in_buffered_data, &zi->ci.aes_ctx);
1388 }
1389 else
1390 #endif
1391 {
1392 uInt i;
1393 int t;
1394 for (i = 0;i < zi->ci.pos_in_buffered_data; i++)
1395 zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t);
1396 }
1397 #endif
1398 }
1399
1400 write = zi->ci.pos_in_buffered_data;
1401
1402 do
1403 {
1404 max_write = write;
1405
1406 if (zi->disk_size > 0)
1407 {
1408 err = zipGetDiskSizeAvailable((zipFile)zi, &size_available);
1409 if (err != ZIP_OK)
1410 return err;
1411
1412 if (size_available == 0)
1413 {
1414 err = zipGoToNextDisk((zipFile)zi);
1415 if (err != ZIP_OK)
1416 return err;
1417 }
1418
1419 if (size_available < (ZPOS64_T)max_write)
1420 max_write = (uInt)size_available;
1421 }
1422
1423 written = ZWRITE64(zi->z_filefunc, zi->filestream, zi->ci.buffered_data + total_written, max_write);
1424
1425 if (ZERROR64(zi->z_filefunc, zi->filestream))
1426 {
1427 err = ZIP_ERRNO;
1428 break;
1429 }
1430
1431 total_written += written;
1432 write -= written;
1433 }
1434 while (write > 0);
1435
1436 zi->ci.total_compressed += zi->ci.pos_in_buffered_data;
1437
1438 #ifdef HAVE_BZIP2
1439 if (zi->ci.compression_method == Z_BZIP2ED)
1440 {
1441 zi->ci.total_uncompressed += zi->ci.bstream.total_in_lo32;
1442 zi->ci.bstream.total_in_lo32 = 0;
1443 zi->ci.bstream.total_in_hi32 = 0;
1444 }
1445 else
1446 #endif
1447 {
1448 zi->ci.total_uncompressed += zi->ci.stream.total_in;
1449 zi->ci.stream.total_in = 0;
1450 }
1451
1452 zi->ci.pos_in_buffered_data = 0;
1453
1454 return err;
1455 }
1456
zipWriteInFileInZip(zipFile file,const void * buf,unsigned int len)1457 extern int ZEXPORT zipWriteInFileInZip(zipFile file,const void* buf,unsigned int len)
1458 {
1459 zip64_internal* zi;
1460 int err = ZIP_OK;
1461
1462 if (file == NULL)
1463 return ZIP_PARAMERROR;
1464 zi = (zip64_internal*)file;
1465
1466 if (zi->in_opened_file_inzip == 0)
1467 return ZIP_PARAMERROR;
1468
1469 zi->ci.crc32 = crc32(zi->ci.crc32, buf, (uInt)len);
1470
1471 #ifdef HAVE_BZIP2
1472 if ((zi->ci.compression_method == Z_BZIP2ED) && (!zi->ci.raw))
1473 {
1474 zi->ci.bstream.next_in = (void*)buf;
1475 zi->ci.bstream.avail_in = len;
1476 err = BZ_RUN_OK;
1477
1478 while ((err == BZ_RUN_OK) && (zi->ci.bstream.avail_in > 0))
1479 {
1480 if (zi->ci.bstream.avail_out == 0)
1481 {
1482 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1483 err = ZIP_ERRNO;
1484 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1485 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1486 }
1487 else
1488 {
1489 uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32;
1490 uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32;
1491
1492 err = BZ2_bzCompress(&zi->ci.bstream, BZ_RUN);
1493
1494 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo);
1495 }
1496 }
1497
1498 if (err == BZ_RUN_OK)
1499 err = ZIP_OK;
1500 }
1501 else
1502 #endif
1503 {
1504 zi->ci.stream.next_in = (Bytef*)buf;
1505 zi->ci.stream.avail_in = len;
1506
1507 while ((err == ZIP_OK) && (zi->ci.stream.avail_in > 0))
1508 {
1509 if (zi->ci.stream.avail_out == 0)
1510 {
1511 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1512 err = ZIP_ERRNO;
1513 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1514 zi->ci.stream.next_out = zi->ci.buffered_data;
1515 }
1516
1517 if (err != ZIP_OK)
1518 break;
1519
1520 if ((zi->ci.compression_method == Z_DEFLATED) && (!zi->ci.raw))
1521 {
1522 uLong total_out_before = zi->ci.stream.total_out;
1523 err = deflate(&zi->ci.stream, Z_NO_FLUSH);
1524 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - total_out_before);
1525 }
1526 else
1527 {
1528 uInt copy_this,i;
1529 if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
1530 copy_this = zi->ci.stream.avail_in;
1531 else
1532 copy_this = zi->ci.stream.avail_out;
1533
1534 for (i = 0; i < copy_this; i++)
1535 *(((char*)zi->ci.stream.next_out)+i) =
1536 *(((const char*)zi->ci.stream.next_in)+i);
1537
1538 zi->ci.stream.avail_in -= copy_this;
1539 zi->ci.stream.avail_out -= copy_this;
1540 zi->ci.stream.next_in += copy_this;
1541 zi->ci.stream.next_out += copy_this;
1542 zi->ci.stream.total_in += copy_this;
1543 zi->ci.stream.total_out += copy_this;
1544 zi->ci.pos_in_buffered_data += copy_this;
1545 }
1546 }
1547 }
1548
1549 return err;
1550 }
1551
zipCloseFileInZipRaw(zipFile file,uLong uncompressed_size,uLong crc32)1552 extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32)
1553 {
1554 return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32);
1555 }
1556
zipCloseFileInZipRaw64(zipFile file,ZPOS64_T uncompressed_size,uLong crc32)1557 extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32)
1558 {
1559 zip64_internal* zi;
1560 ZPOS64_T compressed_size;
1561 uLong invalidValue = 0xffffffff;
1562 uLong i = 0;
1563 short datasize = 0;
1564 int err = ZIP_OK;
1565
1566 if (file == NULL)
1567 return ZIP_PARAMERROR;
1568 zi = (zip64_internal*)file;
1569
1570 if (zi->in_opened_file_inzip == 0)
1571 return ZIP_PARAMERROR;
1572 zi->ci.stream.avail_in = 0;
1573
1574 if (!zi->ci.raw)
1575 {
1576 if (zi->ci.compression_method == Z_DEFLATED)
1577 {
1578 while (err == ZIP_OK)
1579 {
1580 uLong total_out_before;
1581 if (zi->ci.stream.avail_out == 0)
1582 {
1583 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1584 err = ZIP_ERRNO;
1585 zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
1586 zi->ci.stream.next_out = zi->ci.buffered_data;
1587 }
1588 total_out_before = zi->ci.stream.total_out;
1589 err = deflate(&zi->ci.stream, Z_FINISH);
1590 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - total_out_before);
1591 }
1592 }
1593 else if (zi->ci.compression_method == Z_BZIP2ED)
1594 {
1595 #ifdef HAVE_BZIP2
1596 err = BZ_FINISH_OK;
1597 while (err == BZ_FINISH_OK)
1598 {
1599 uLong total_out_before;
1600 if (zi->ci.bstream.avail_out == 0)
1601 {
1602 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1603 err = ZIP_ERRNO;
1604 zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
1605 zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
1606 }
1607 total_out_before = zi->ci.bstream.total_out_lo32;
1608 err = BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH);
1609 if (err == BZ_STREAM_END)
1610 err = Z_STREAM_END;
1611 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - total_out_before);
1612 }
1613
1614 if (err == BZ_FINISH_OK)
1615 err = ZIP_OK;
1616 #endif
1617 }
1618 }
1619
1620 if (err == Z_STREAM_END)
1621 err = ZIP_OK; /* this is normal */
1622
1623 if ((zi->ci.pos_in_buffered_data>0) && (err == ZIP_OK))
1624 {
1625 if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
1626 err = ZIP_ERRNO;
1627 }
1628
1629 #ifdef HAVE_AES
1630 if (zi->ci.method == AES_METHOD)
1631 {
1632 unsigned char authcode[AES_AUTHCODESIZE];
1633
1634 fcrypt_end(authcode, &zi->ci.aes_ctx);
1635
1636 if (ZWRITE64(zi->z_filefunc, zi->filestream, authcode, AES_AUTHCODESIZE) != AES_AUTHCODESIZE)
1637 err = ZIP_ERRNO;
1638 }
1639 #endif
1640
1641 if (!zi->ci.raw)
1642 {
1643 if (zi->ci.compression_method == Z_DEFLATED)
1644 {
1645 int tmp_err = deflateEnd(&zi->ci.stream);
1646 if (err == ZIP_OK)
1647 err = tmp_err;
1648 zi->ci.stream_initialised = 0;
1649 }
1650 #ifdef HAVE_BZIP2
1651 else if (zi->ci.compression_method == Z_BZIP2ED)
1652 {
1653 int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream);
1654 if (err == ZIP_OK)
1655 err = tmperr;
1656 zi->ci.stream_initialised = 0;
1657 }
1658 #endif
1659
1660 crc32 = (uLong)zi->ci.crc32;
1661 uncompressed_size = zi->ci.total_uncompressed;
1662 }
1663
1664 compressed_size = zi->ci.total_compressed;
1665 #ifndef NOCRYPT
1666 compressed_size += zi->ci.crypt_header_size;
1667 #endif
1668
1669 /* Update current item crc and sizes */
1670 if (compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff)
1671 {
1672 zip64local_putValue_inmemory(zi->ci.central_header+4, (uLong)45, 2); /* version made by */
1673 zip64local_putValue_inmemory(zi->ci.central_header+6, (uLong)45, 2); /* version needed */
1674 }
1675 zip64local_putValue_inmemory(zi->ci.central_header+16, crc32, 4); /* crc */
1676 if (compressed_size >= 0xffffffff)
1677 zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue, 4); /* compr size */
1678 else
1679 zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size, 4); /* compr size */
1680 if (zi->ci.stream.data_type == Z_ASCII)
1681 zip64local_putValue_inmemory(zi->ci.central_header+36, (uLong)Z_ASCII, 2); /* internal file attrib */
1682 if (uncompressed_size >= 0xffffffff)
1683 zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue, 4); /* uncompr size */
1684 else
1685 zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size, 4); /* uncompr size */
1686
1687 /* Add ZIP64 extra info field for uncompressed size */
1688 if (uncompressed_size >= 0xffffffff)
1689 datasize += 8;
1690 /* Add ZIP64 extra info field for compressed size */
1691 if (compressed_size >= 0xffffffff)
1692 datasize += 8;
1693 /* Add ZIP64 extra info field for relative offset to local file header of current file */
1694 if (zi->ci.pos_local_header >= 0xffffffff)
1695 datasize += 8;
1696
1697 /* Add Extra Information Header for 'ZIP64 information' */
1698 if (datasize > 0)
1699 {
1700 char* p = zi->ci.central_header + zi->ci.size_centralheader;
1701
1702 if ((uLong)(datasize + 4) > zi->ci.size_centralextrafree)
1703 return ZIP_BADZIPFILE;
1704
1705 zip64local_putValue_inmemory(p, 0x0001, 2);
1706 p += 2;
1707 zip64local_putValue_inmemory(p, datasize, 2);
1708 p += 2;
1709
1710 if (uncompressed_size >= 0xffffffff)
1711 {
1712 zip64local_putValue_inmemory(p, uncompressed_size, 8);
1713 p += 8;
1714 }
1715 if (compressed_size >= 0xffffffff)
1716 {
1717 zip64local_putValue_inmemory(p, compressed_size, 8);
1718 p += 8;
1719 }
1720 if (zi->ci.pos_local_header >= 0xffffffff)
1721 {
1722 zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8);
1723 p += 8;
1724 }
1725
1726 zi->ci.size_centralextrafree -= datasize + 4;
1727 zi->ci.size_centralheader += datasize + 4;
1728 zi->ci.size_centralextra += datasize + 4;
1729
1730 zip64local_putValue_inmemory(zi->ci.central_header+30, (uLong)zi->ci.size_centralextra, 2);
1731 }
1732
1733 #ifdef HAVE_AES
1734 /* Write the AES extended info */
1735 if (zi->ci.method == AES_METHOD)
1736 {
1737 char* p = zi->ci.central_header + zi->ci.size_centralheader;
1738
1739 datasize = 7;
1740
1741 if ((uLong)(datasize + 4) > zi->ci.size_centralextrafree)
1742 return ZIP_BADZIPFILE;
1743
1744 zip64local_putValue_inmemory(p, 0x9901, 2);
1745 p += 2;
1746 zip64local_putValue_inmemory(p, datasize, 2);
1747 p += 2;
1748 zip64local_putValue_inmemory(p, AES_VERSION, 2);
1749 p += 2;
1750 zip64local_putValue_inmemory(p, 'A', 1);
1751 p += 1;
1752 zip64local_putValue_inmemory(p, 'E', 1);
1753 p += 1;
1754 zip64local_putValue_inmemory(p, AES_ENCRYPTIONMODE, 1);
1755 p += 1;
1756 zip64local_putValue_inmemory(p, zi->ci.compression_method, 2);
1757 p += 2;
1758
1759 zi->ci.size_centralextrafree -= datasize + 4;
1760 zi->ci.size_centralheader += datasize + 4;
1761 zi->ci.size_centralextra += datasize + 4;
1762
1763 zip64local_putValue_inmemory(zi->ci.central_header+30, (uLong)zi->ci.size_centralextra, 2);
1764 }
1765 #endif
1766 /* Restore comment to correct position */
1767 for (i = 0; i < zi->ci.size_comment; i++)
1768 zi->ci.central_header[zi->ci.size_centralheader+i] =
1769 zi->ci.central_header[zi->ci.size_centralheader+zi->ci.size_centralextrafree+i];
1770 zi->ci.size_centralheader += zi->ci.size_comment;
1771
1772 if (err == ZIP_OK)
1773 err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader);
1774
1775 free(zi->ci.central_header);
1776
1777 if (err == ZIP_OK)
1778 {
1779 /* Update the LocalFileHeader with the new values. */
1780 ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc, zi->filestream);
1781 uLong cur_number_disk = zi->number_disk;
1782
1783 /* Local file header is stored on previous disk, switch to make edits */
1784 if (zi->ci.number_disk != cur_number_disk)
1785 err = zipGoToSpecificDisk(file, zi->ci.number_disk, 1);
1786
1787 if (ZSEEK64(zi->z_filefunc, zi->filestream, zi->ci.pos_local_header + 14, ZLIB_FILEFUNC_SEEK_SET) != 0)
1788 err = ZIP_ERRNO;
1789 if (err == ZIP_OK)
1790 err = zip64local_putValue(&zi->z_filefunc, zi->filestream,crc32,4); /* crc 32, unknown */
1791
1792 if (uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff)
1793 {
1794 if (zi->ci.pos_zip64extrainfo > 0)
1795 {
1796 /* Update the size in the ZIP64 extended field. */
1797 if (ZSEEK64(zi->z_filefunc, zi->filestream, zi->ci.pos_zip64extrainfo + 4, ZLIB_FILEFUNC_SEEK_SET) != 0)
1798 err = ZIP_ERRNO;
1799
1800 if (err == ZIP_OK) /* compressed size, unknown */
1801 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8);
1802 if (err == ZIP_OK) /* uncompressed size, unknown */
1803 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8);
1804 }
1805 else
1806 err = ZIP_BADZIPFILE; /* Caller passed zip64 = 0, so no room for zip64 info -> fatal */
1807 }
1808 else
1809 {
1810 if (err == ZIP_OK) /* compressed size, unknown */
1811 err = zip64local_putValue(&zi->z_filefunc, zi->filestream,compressed_size, 4);
1812 if (err == ZIP_OK) /* uncompressed size, unknown */
1813 err = zip64local_putValue(&zi->z_filefunc, zi->filestream,uncompressed_size, 4);
1814 }
1815
1816 /* Now switch back again to the disk we were on before */
1817 if (zi->ci.number_disk != cur_number_disk)
1818 err = zipGoToSpecificDisk(file, cur_number_disk, 1);
1819
1820 if (ZSEEK64(zi->z_filefunc, zi->filestream, cur_pos_inzip, ZLIB_FILEFUNC_SEEK_SET) != 0)
1821 err = ZIP_ERRNO;
1822 }
1823
1824 zi->number_entry++;
1825 zi->in_opened_file_inzip = 0;
1826
1827 return err;
1828 }
1829
zipCloseFileInZip(zipFile file)1830 extern int ZEXPORT zipCloseFileInZip(zipFile file)
1831 {
1832 return zipCloseFileInZipRaw(file, 0, 0);
1833 }
1834
zipClose(zipFile file,const char * global_comment)1835 extern int ZEXPORT zipClose(zipFile file, const char* global_comment)
1836 {
1837 zip64_internal* zi;
1838 int err = 0;
1839 uLong size_centraldir = 0;
1840 uInt size_global_comment = 0;
1841 ZPOS64_T centraldir_pos_inzip;
1842 ZPOS64_T pos = 0;
1843 uLong write = 0;
1844
1845 if (file == NULL)
1846 return ZIP_PARAMERROR;
1847
1848 zi = (zip64_internal*)file;
1849
1850 if (zi->in_opened_file_inzip == 1)
1851 err = zipCloseFileInZip(file);
1852
1853 #ifndef NO_ADDFILEINEXISTINGZIP
1854 if (global_comment == NULL)
1855 global_comment = zi->globalcomment;
1856 #endif
1857
1858 if (zi->filestream != zi->filestream_with_CD)
1859 {
1860 if (ZCLOSE64(zi->z_filefunc, zi->filestream) != 0)
1861 if (err == ZIP_OK)
1862 err = ZIP_ERRNO;
1863 if (zi->disk_size > 0)
1864 zi->number_disk_with_CD = zi->number_disk + 1;
1865 zi->filestream = zi->filestream_with_CD;
1866 }
1867
1868 centraldir_pos_inzip = ZTELL64(zi->z_filefunc, zi->filestream);
1869
1870 if (err == ZIP_OK)
1871 {
1872 linkedlist_datablock_internal* ldi = zi->central_dir.first_block;
1873 while (ldi!= NULL)
1874 {
1875 if ((err == ZIP_OK) && (ldi->filled_in_this_block > 0))
1876 {
1877 write = ZWRITE64(zi->z_filefunc, zi->filestream, ldi->data, ldi->filled_in_this_block);
1878 if (write != ldi->filled_in_this_block)
1879 err = ZIP_ERRNO;
1880 }
1881
1882 size_centraldir += ldi->filled_in_this_block;
1883 ldi = ldi->next_datablock;
1884 }
1885 }
1886
1887 free_linkedlist(&(zi->central_dir));
1888
1889 pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;
1890
1891 /* Write the ZIP64 central directory header */
1892 if (pos >= 0xffffffff || zi->number_entry > 0xffff)
1893 {
1894 ZPOS64_T zip64eocd_pos_inzip = ZTELL64(zi->z_filefunc, zi->filestream);
1895 uLong zip64datasize = 44;
1896
1897 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)ZIP64ENDHEADERMAGIC, 4);
1898
1899 /* size of this 'zip64 end of central directory' */
1900 if (err == ZIP_OK)
1901 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)zip64datasize, 8);
1902 /* version made by */
1903 if (err == ZIP_OK)
1904 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)45, 2);
1905 /* version needed */
1906 if (err == ZIP_OK)
1907 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)45, 2);
1908 /* number of this disk */
1909 if (err == ZIP_OK)
1910 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD, 4);
1911 /* number of the disk with the start of the central directory */
1912 if (err == ZIP_OK)
1913 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD, 4);
1914 /* total number of entries in the central dir on this disk */
1915 if (err == ZIP_OK)
1916 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
1917 /* total number of entries in the central dir */
1918 if (err == ZIP_OK)
1919 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
1920 /* size of the central directory */
1921 if (err == ZIP_OK)
1922 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)size_centraldir, 8);
1923
1924 if (err == ZIP_OK)
1925 {
1926 /* offset of start of central directory with respect to the starting disk number */
1927 ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;
1928 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)pos, 8);
1929 }
1930 if (err == ZIP_OK)
1931 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)ZIP64ENDLOCHEADERMAGIC, 4);
1932
1933 /* number of the disk with the start of the central directory */
1934 if (err == ZIP_OK)
1935 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD, 4);
1936 /*relative offset to the Zip64EndOfCentralDirectory */
1937 if (err == ZIP_OK)
1938 {
1939 ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset;
1940 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, pos, 8);
1941 }
1942 /* number of the disk with the start of the central directory */
1943 if (err == ZIP_OK)
1944 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD+1, 4);
1945 }
1946
1947 /* Write the central directory header */
1948
1949 /* signature */
1950 if (err == ZIP_OK)
1951 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)ENDHEADERMAGIC, 4);
1952 /* number of this disk */
1953 if (err == ZIP_OK)
1954 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD, 2);
1955 /* number of the disk with the start of the central directory */
1956 if (err == ZIP_OK)
1957 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_disk_with_CD, 2);
1958 /* total number of entries in the central dir on this disk */
1959 if (err == ZIP_OK)
1960 {
1961 if (zi->number_entry >= 0xffff)
1962 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xffff, 2); /* use value in ZIP64 record */
1963 else
1964 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_entry, 2);
1965 }
1966 /* total number of entries in the central dir */
1967 if (err == ZIP_OK)
1968 {
1969 if (zi->number_entry >= 0xffff)
1970 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xffff, 2); /* use value in ZIP64 record */
1971 else
1972 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)zi->number_entry, 2);
1973 }
1974 /* size of the central directory */
1975 if (err == ZIP_OK)
1976 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)size_centraldir,4);
1977 /* offset of start of central directory with respect to the starting disk number */
1978 if (err == ZIP_OK)
1979 {
1980 ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;
1981 if (pos >= 0xffffffff)
1982 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)0xffffffff, 4);
1983 else
1984 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)pos, 4);
1985 }
1986
1987 /* Write global comment */
1988
1989 if (global_comment != NULL)
1990 size_global_comment = (uInt)strlen(global_comment);
1991 if (err == ZIP_OK)
1992 err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (uLong)size_global_comment, 2);
1993 if (err == ZIP_OK && size_global_comment > 0)
1994 {
1995 if (ZWRITE64(zi->z_filefunc, zi->filestream, global_comment, size_global_comment) != size_global_comment)
1996 err = ZIP_ERRNO;
1997 }
1998
1999 if ((ZCLOSE64(zi->z_filefunc, zi->filestream) != 0) && (err == ZIP_OK))
2000 err = ZIP_ERRNO;
2001
2002 #ifndef NO_ADDFILEINEXISTINGZIP
2003 TRYFREE(zi->globalcomment);
2004 #endif
2005 TRYFREE(zi);
2006
2007 return err;
2008 }
2009