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