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