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