diff options
Diffstat (limited to 'plugins/FTPFileYM/src/zip/zip.c')
| -rw-r--r-- | plugins/FTPFileYM/src/zip/zip.c | 2004 | 
1 files changed, 2004 insertions, 0 deletions
diff --git a/plugins/FTPFileYM/src/zip/zip.c b/plugins/FTPFileYM/src/zip/zip.c new file mode 100644 index 0000000000..3c34fc8bd4 --- /dev/null +++ b/plugins/FTPFileYM/src/zip/zip.c @@ -0,0 +1,2004 @@ +/* zip.c -- IO on .zip files using zlib +   Version 1.1, February 14h, 2010 +   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + +         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + +         Modifications for Zip64 support +         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + +         For more info read MiniZip_info.txt + +         Changes +   Oct-2009 - Mathias Svensson - Remove old C style function prototypes +   Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives +   Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. +   Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data +                                 It is used when recreting zip archive with RAW when deleting items from a zip. +                                 ZIP64 data is automaticly added to items that needs it, and existing ZIP64 data need to be removed. +   Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) +   Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "zlib.h" +#include "zip.h" + +#ifdef STDC +#  include <stddef.h> +#  include <string.h> +#  include <stdlib.h> +#endif +#ifdef NO_ERRNO_H +    extern int errno; +#else +#   include <errno.h> +#endif + + +#ifndef local +#  define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY   (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (64*1024) //(16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + + +// NOT sure that this work on ALL platform +#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) + +#ifndef SEEK_CUR +#define SEEK_CUR    1 +#endif + +#ifndef SEEK_END +#define SEEK_END    2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET    0 +#endif + +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +#  define DEF_MEM_LEVEL 8 +#else +#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL +#endif +#endif +const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC    (0x04034b50) +#define CENTRALHEADERMAGIC  (0x02014b50) +#define ENDHEADERMAGIC      (0x06054b50) +#define ZIP64ENDHEADERMAGIC      (0x6064b50) +#define ZIP64ENDLOCHEADERMAGIC   (0x7064b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET  (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ +  struct linkedlist_datablock_internal_s* next_datablock; +  uLong  avail_in_this_block; +  uLong  filled_in_this_block; +  uLong  unused; /* for future use and alignement */ +  unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ +    linkedlist_datablock_internal* first_block; +    linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ +    z_stream stream;            /* zLib stream structure for inflate */ +#ifdef HAVE_BZIP2 +    bz_stream bstream;          /* bzLib stream structure for bziped */ +#endif + +    int  stream_initialised;    /* 1 is stream is initialised */ +    uInt pos_in_buffered_data;  /* last written byte in buffered_data */ + +    ZPOS64_T pos_local_header;     /* offset of the local header of the file +                                     currenty writing */ +    char* central_header;       /* central header data for the current file */ +    uLong size_centralExtra; +    uLong size_centralheader;   /* size of the central header for cur file */ +    uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ +    uLong flag;                 /* flag of the file currently writing */ + +    int  method;                /* compression method of file currenty wr.*/ +    int  raw;                   /* 1 for directly writing raw data */ +    Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ +    uLong dosDate; +    uLong crc32; +    int  encrypt; +    int  zip64;               /* Add ZIP64 extened information in the extra field */ +    ZPOS64_T pos_zip64extrainfo; +    ZPOS64_T totalCompressedData; +    ZPOS64_T totalUncompressedData; +#ifndef NOCRYPT +    unsigned long keys[3];     /* keys defining the pseudo-random sequence */ +    const unsigned long* pcrc_32_tab; +    int crypt_header_size; +#endif +} curfile64_info; + +typedef struct +{ +    zlib_filefunc64_32_def z_filefunc; +    voidpf filestream;        /* io structore of the zipfile */ +    linkedlist_data central_dir;/* datablock with central dir in construction*/ +    int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/ +    curfile64_info ci;            /* info on the file curretly writing */ + +    ZPOS64_T begin_pos;            /* position of the beginning of the zipfile */ +    ZPOS64_T add_position_when_writting_offset; +    ZPOS64_T number_entry; + +#ifndef NO_ADDFILEINEXISTINGZIP +    char *globalcomment; +#endif + +} zip64_internal; + + +#ifndef NOCRYPT +#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED +#include "crypt.h" +#endif + +local linkedlist_datablock_internal* allocate_new_datablock() +{ +    linkedlist_datablock_internal* ldi; +    ldi = (linkedlist_datablock_internal*) +                 ALLOC(sizeof(linkedlist_datablock_internal)); +    if (ldi!=NULL) +    { +        ldi->next_datablock = NULL ; +        ldi->filled_in_this_block = 0 ; +        ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; +    } +    return ldi; +} + +local void free_datablock(linkedlist_datablock_internal* ldi) +{ +    while (ldi!=NULL) +    { +        linkedlist_datablock_internal* ldinext = ldi->next_datablock; +        TRYFREE(ldi); +        ldi = ldinext; +    } +} + +local void init_linkedlist(linkedlist_data* ll) +{ +    ll->first_block = ll->last_block = NULL; +} + +local void free_linkedlist(linkedlist_data* ll) +{ +    free_datablock(ll->first_block); +    ll->first_block = ll->last_block = NULL; +} + + +local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) +{ +    linkedlist_datablock_internal* ldi; +    const unsigned char* from_copy; + +    if (ll==NULL) +        return ZIP_INTERNALERROR; + +    if (ll->last_block == NULL) +    { +        ll->first_block = ll->last_block = allocate_new_datablock(); +        if (ll->first_block == NULL) +            return ZIP_INTERNALERROR; +    } + +    ldi = ll->last_block; +    from_copy = (unsigned char*)buf; + +    while (len>0) +    { +        uInt copy_this; +        uInt i; +        unsigned char* to_copy; + +        if (ldi->avail_in_this_block==0) +        { +            ldi->next_datablock = allocate_new_datablock(); +            if (ldi->next_datablock == NULL) +                return ZIP_INTERNALERROR; +            ldi = ldi->next_datablock ; +            ll->last_block = ldi; +        } + +        if (ldi->avail_in_this_block < len) +            copy_this = (uInt)ldi->avail_in_this_block; +        else +            copy_this = (uInt)len; + +        to_copy = &(ldi->data[ldi->filled_in_this_block]); + +        for (i=0;i<copy_this;i++) +            *(to_copy+i)=*(from_copy+i); + +        ldi->filled_in_this_block += copy_this; +        ldi->avail_in_this_block -= copy_this; +        from_copy += copy_this ; +        len -= copy_this; +    } +    return ZIP_OK; +} + + + +/****************************************************************************/ + +#ifndef NO_ADDFILEINEXISTINGZIP +/* =========================================================================== +   Inputs a long in LSB order to the given file +   nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) +*/ + +local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); +local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) +{ +    unsigned char buf[8]; +    int n; +    for (n = 0; n < nbByte; n++) +    { +        buf[n] = (unsigned char)(x & 0xff); +        x >>= 8; +    } +    if (x != 0) +      {     /* data overflow - hack for ZIP64 (X Roche) */ +      for (n = 0; n < nbByte; n++) +        { +          buf[n] = 0xff; +        } +      } + +    if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) +        return ZIP_ERRNO; +    else +        return ZIP_OK; +} + +local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); +local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) +{ +    unsigned char* buf=(unsigned char*)dest; +    int n; +    for (n = 0; n < nbByte; n++) { +        buf[n] = (unsigned char)(x & 0xff); +        x >>= 8; +    } + +    if (x != 0) +    {     /* data overflow - hack for ZIP64 */ +       for (n = 0; n < nbByte; n++) +       { +          buf[n] = 0xff; +       } +    } +} + +/****************************************************************************/ + + +local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) +{ +    uLong year = (uLong)ptm->tm_year; +    if (year>=1980) +        year-=1980; +    else if (year>=80) +        year-=80; +    return +      (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | +        ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); + +local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) +{ +    unsigned char c; +    int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); +    if (err==1) +    { +        *pi = (int)c; +        return ZIP_OK; +    } +    else +    { +        if (ZERROR64(*pzlib_filefunc_def,filestream)) +            return ZIP_ERRNO; +        else +            return ZIP_EOF; +    } +} + + +/* =========================================================================== +   Reads a long in LSB order from the given gz_stream. Sets +*/ +local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ +    uLong x ; +    int i = 0; +    int err; + +    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +    x = (uLong)i; + +    if (err==ZIP_OK) +        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +    x += ((uLong)i)<<8; + +    if (err==ZIP_OK) +        *pX = x; +    else +        *pX = 0; +    return err; +} + +local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ +    uLong x ; +    int i = 0; +    int err; + +    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +    x = (uLong)i; + +    if (err==ZIP_OK) +        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +    x += ((uLong)i)<<8; + +    if (err==ZIP_OK) +        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +    x += ((uLong)i)<<16; + +    if (err==ZIP_OK) +        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +    x += ((uLong)i)<<24; + +    if (err==ZIP_OK) +        *pX = x; +    else +        *pX = 0; +    return err; +} + +local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); + + +local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) +{ +  ZPOS64_T x; +  int i = 0; +  int err; + +  err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +  x = (ZPOS64_T)i; + +  if (err==ZIP_OK) +    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +  x += ((ZPOS64_T)i)<<8; + +  if (err==ZIP_OK) +    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +  x += ((ZPOS64_T)i)<<16; + +  if (err==ZIP_OK) +    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +  x += ((ZPOS64_T)i)<<24; + +  if (err==ZIP_OK) +    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +  x += ((ZPOS64_T)i)<<32; + +  if (err==ZIP_OK) +    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +  x += ((ZPOS64_T)i)<<40; + +  if (err==ZIP_OK) +    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +  x += ((ZPOS64_T)i)<<48; + +  if (err==ZIP_OK) +    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); +  x += ((ZPOS64_T)i)<<56; + +  if (err==ZIP_OK) +    *pX = x; +  else +    *pX = 0; + +  return err; +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif +/* +  Locate the Central directory of a zipfile (at the end, just before +    the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ +  unsigned char* buf; +  ZPOS64_T uSizeFile; +  ZPOS64_T uBackRead; +  ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ +  ZPOS64_T uPosFound=0; + +  if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) +    return 0; + + +  uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + +  if (uMaxBack>uSizeFile) +    uMaxBack = uSizeFile; + +  buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); +  if (buf==NULL) +    return 0; + +  uBackRead = 4; +  while (uBackRead<uMaxBack) +  { +    uLong uReadSize; +    ZPOS64_T uReadPos ; +    int i; +    if (uBackRead+BUFREADCOMMENT>uMaxBack) +      uBackRead = uMaxBack; +    else +      uBackRead+=BUFREADCOMMENT; +    uReadPos = uSizeFile-uBackRead ; + +    uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? +      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); +    if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) +      break; + +    if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) +      break; + +    for (i=(int)uReadSize-3; (i--)>0;) +      if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && +        ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) +      { +        uPosFound = uReadPos+i; +        break; +      } + +      if (uPosFound!=0) +        break; +  } +  TRYFREE(buf); +  return uPosFound; +} + +/* +Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before +the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ +  unsigned char* buf; +  ZPOS64_T uSizeFile; +  ZPOS64_T uBackRead; +  ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ +  ZPOS64_T uPosFound=0; +  uLong uL; +  ZPOS64_T relativeOffset; + +  if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) +    return 0; + +  uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + +  if (uMaxBack>uSizeFile) +    uMaxBack = uSizeFile; + +  buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); +  if (buf==NULL) +    return 0; + +  uBackRead = 4; +  while (uBackRead<uMaxBack) +  { +    uLong uReadSize; +    ZPOS64_T uReadPos; +    int i; +    if (uBackRead+BUFREADCOMMENT>uMaxBack) +      uBackRead = uMaxBack; +    else +      uBackRead+=BUFREADCOMMENT; +    uReadPos = uSizeFile-uBackRead ; + +    uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? +      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); +    if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) +      break; + +    if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) +      break; + +    for (i=(int)uReadSize-3; (i--)>0;) +    { +      // Signature "0x07064b50" Zip64 end of central directory locater +      if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) +      { +        uPosFound = uReadPos+i; +        break; +      } +    } + +      if (uPosFound!=0) +        break; +  } + +  TRYFREE(buf); +  if (uPosFound == 0) +    return 0; + +  /* Zip64 end of central directory locator */ +  if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) +    return 0; + +  /* the signature, already checked */ +  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) +    return 0; + +  /* number of the disk with the start of the zip64 end of  central directory */ +  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) +    return 0; +  if (uL != 0) +    return 0; + +  /* relative offset of the zip64 end of central directory record */ +  if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) +    return 0; + +  /* total number of disks */ +  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) +    return 0; +  if (uL != 1) +    return 0; + +  /* Goto Zip64 end of central directory record */ +  if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) +    return 0; + +  /* the signature */ +  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) +    return 0; + +  if (uL != 0x06064b50) // signature of 'Zip64 end of central directory' +    return 0; + +  return relativeOffset; +} + +int LoadCentralDirectoryRecord(zip64_internal* pziinit) +{ +  int err=ZIP_OK; +  ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + +  ZPOS64_T size_central_dir;     /* size of the central directory  */ +  ZPOS64_T offset_central_dir;   /* offset of start of central directory */ +  ZPOS64_T central_pos; +  uLong uL; + +  uLong number_disk;          /* number of the current dist, used for +                              spaning ZIP, unsupported, always 0*/ +  uLong number_disk_with_CD;  /* number the the disk with central dir, used +                              for spaning ZIP, unsupported, always 0*/ +  ZPOS64_T number_entry; +  ZPOS64_T number_entry_CD;      /* total number of entries in +                                the central dir +                                (same than number_entry on nospan) */ +  uLong VersionMadeBy; +  uLong VersionNeeded; +  uLong size_comment; + +  int hasZIP64Record = 0; + +  // check first if we find a ZIP64 record +  central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); +  if(central_pos > 0) +  { +    hasZIP64Record = 1; +  } +  else if(central_pos == 0) +  { +    central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream); +  } + +/* disable to allow appending to empty ZIP archive +        if (central_pos==0) +            err=ZIP_ERRNO; +*/ + +  if(hasZIP64Record) +  { +    ZPOS64_T sizeEndOfCentralDirectory; +    if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) +      err=ZIP_ERRNO; + +    /* the signature, already checked */ +    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) +      err=ZIP_ERRNO; + +    /* size of zip64 end of central directory record */ +    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK) +      err=ZIP_ERRNO; + +    /* version made by */ +    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK) +      err=ZIP_ERRNO; + +    /* version needed to extract */ +    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK) +      err=ZIP_ERRNO; + +    /* number of this disk */ +    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) +      err=ZIP_ERRNO; + +    /* number of the disk with the start of the central directory */ +    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) +      err=ZIP_ERRNO; + +    /* total number of entries in the central directory on this disk */ +    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK) +      err=ZIP_ERRNO; + +    /* total number of entries in the central directory */ +    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK) +      err=ZIP_ERRNO; + +    if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) +      err=ZIP_BADZIPFILE; + +    /* size of the central directory */ +    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK) +      err=ZIP_ERRNO; + +    /* offset of start of central directory with respect to the +    starting disk number */ +    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) +      err=ZIP_ERRNO; + +    // TODO.. +    // read the comment from the standard central header. +    size_comment = 0; +  } +  else +  { +    // Read End of central Directory info +    if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) +      err=ZIP_ERRNO; + +    /* the signature, already checked */ +    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) +      err=ZIP_ERRNO; + +    /* number of this disk */ +    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) +      err=ZIP_ERRNO; + +    /* number of the disk with the start of the central directory */ +    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) +      err=ZIP_ERRNO; + +    /* total number of entries in the central dir on this disk */ +    number_entry = 0; +    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) +      err=ZIP_ERRNO; +    else +      number_entry = uL; + +    /* total number of entries in the central dir */ +    number_entry_CD = 0; +    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) +      err=ZIP_ERRNO; +    else +      number_entry_CD = uL; + +    if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) +      err=ZIP_BADZIPFILE; + +    /* size of the central directory */ +    size_central_dir = 0; +    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) +      err=ZIP_ERRNO; +    else +      size_central_dir = uL; + +    /* offset of start of central directory with respect to the starting disk number */ +    offset_central_dir = 0; +    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) +      err=ZIP_ERRNO; +    else +      offset_central_dir = uL; + + +    /* zipfile global comment length */ +    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK) +      err=ZIP_ERRNO; +  } + +  if ((central_pos<offset_central_dir+size_central_dir) && +    (err==ZIP_OK)) +    err=ZIP_BADZIPFILE; + +  if (err!=ZIP_OK) +  { +    ZCLOSE64(pziinit->z_filefunc, pziinit->filestream); +    return ZIP_ERRNO; +  } + +  if (size_comment>0) +  { +    pziinit->globalcomment = (char*)ALLOC(size_comment+1); +    if (pziinit->globalcomment) +    { +      size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment); +      pziinit->globalcomment[size_comment]=0; +    } +  } + +  byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); +  pziinit->add_position_when_writting_offset = byte_before_the_zipfile; + +  { +    ZPOS64_T size_central_dir_to_read = size_central_dir; +    size_t buf_size = SIZEDATA_INDATABLOCK; +    void* buf_read = (void*)ALLOC(buf_size); +    if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) +      err=ZIP_ERRNO; + +    while ((size_central_dir_to_read>0) && (err==ZIP_OK)) +    { +      ZPOS64_T read_this = SIZEDATA_INDATABLOCK; +      if (read_this > size_central_dir_to_read) +        read_this = size_central_dir_to_read; + +      if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this) +        err=ZIP_ERRNO; + +      if (err==ZIP_OK) +        err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); + +      size_central_dir_to_read-=read_this; +    } +    TRYFREE(buf_read); +  } +  pziinit->begin_pos = byte_before_the_zipfile; +  pziinit->number_entry = number_entry_CD; + +  if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) +    err=ZIP_ERRNO; + +  return err; +} + + +#endif /* !NO_ADDFILEINEXISTINGZIP*/ + + +/************************************************************/ +extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) +{ +    zip64_internal ziinit; +    zip64_internal* zi; +    int err=ZIP_OK; + +    ziinit.z_filefunc.zseek32_file = NULL; +    ziinit.z_filefunc.ztell32_file = NULL; +    if (pzlib_filefunc64_32_def==NULL) +        fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); +    else +        ziinit.z_filefunc = *pzlib_filefunc64_32_def; + +    ziinit.filestream = ZOPEN64(ziinit.z_filefunc, +                  pathname, +                  (append == APPEND_STATUS_CREATE) ? +                  (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : +                    (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); + +    if (ziinit.filestream == NULL) +        return NULL; + +    if (append == APPEND_STATUS_CREATEAFTER) +        ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); + +    ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream); +    ziinit.in_opened_file_inzip = 0; +    ziinit.ci.stream_initialised = 0; +    ziinit.number_entry = 0; +    ziinit.add_position_when_writting_offset = 0; +    init_linkedlist(&(ziinit.central_dir)); + + + +    zi = (zip64_internal*)ALLOC(sizeof(zip64_internal)); +    if (zi==NULL) +    { +        ZCLOSE64(ziinit.z_filefunc,ziinit.filestream); +        return NULL; +    } + +    /* now we add file in a zipfile */ +#    ifndef NO_ADDFILEINEXISTINGZIP +    ziinit.globalcomment = NULL; +    if (append == APPEND_STATUS_ADDINZIP) +    { +      // Read and Cache Central Directory Records +      err = LoadCentralDirectoryRecord(&ziinit); +    } + +    if (globalcomment) +    { +      *globalcomment = ziinit.globalcomment; +    } +#    endif /* !NO_ADDFILEINEXISTINGZIP*/ + +    if (err != ZIP_OK) +    { +#    ifndef NO_ADDFILEINEXISTINGZIP +        TRYFREE(ziinit.globalcomment); +#    endif /* !NO_ADDFILEINEXISTINGZIP*/ +        TRYFREE(zi); +        return NULL; +    } +    else +    { +        *zi = ziinit; +        return (zipFile)zi; +    } +} + +extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) +{ +    if (pzlib_filefunc32_def != NULL) +    { +        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; +        fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); +        return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); +    } +    else +        return zipOpen3(pathname, append, globalcomment, NULL); +} + +extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) +{ +    if (pzlib_filefunc_def != NULL) +    { +        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; +        zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; +        zlib_filefunc64_32_def_fill.ztell32_file = NULL; +        zlib_filefunc64_32_def_fill.zseek32_file = NULL; +        return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); +    } +    else +        return zipOpen3(pathname, append, globalcomment, NULL); +} + + + +extern zipFile ZEXPORT zipOpen (const char* pathname, int append) +{ +    return zipOpen3((const void*)pathname,append,NULL,NULL); +} + +extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) +{ +    return zipOpen3(pathname,append,NULL,NULL); +} + +int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) +{ +  /* write the local header */ +  int err; +  uInt size_filename = (uInt)strlen(filename); +  uInt size_extrafield = size_extrafield_local; + +  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4); + +  if (err==ZIP_OK) +  { +    if(zi->ci.zip64) +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ +    else +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ +  } + +  if (err==ZIP_OK) +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); + +  if (err==ZIP_OK) +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); + +  if (err==ZIP_OK) +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); + +  // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later +  if (err==ZIP_OK) +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ +  if (err==ZIP_OK) +  { +    if(zi->ci.zip64) +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ +    else +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ +  } +  if (err==ZIP_OK) +  { +    if(zi->ci.zip64) +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ +    else +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ +  } + +  if (err==ZIP_OK) +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); + +  if(zi->ci.zip64) +  { +    size_extrafield += 20; +  } + +  if (err==ZIP_OK) +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2); + +  if ((err==ZIP_OK) && (size_filename > 0)) +  { +    if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) +      err = ZIP_ERRNO; +  } + +  if ((err==ZIP_OK) && (size_extrafield_local > 0)) +  { +    if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) +      err = ZIP_ERRNO; +  } + + +  if ((err==ZIP_OK) && (zi->ci.zip64)) +  { +      // write the Zip64 extended info +      short HeaderID = 1; +      short DataSize = 16; +      ZPOS64_T CompressedSize = 0; +      ZPOS64_T UncompressedSize = 0; + +      // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) +      zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); + +      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); +      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); + +      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); +      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); +  } + +  return err; +} + +/* + NOTE. + When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped + before calling this function it can be done with zipRemoveExtraInfoBlock + + It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize + unnecessary allocations. + */ +extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, +                                         const void* extrafield_local, uInt size_extrafield_local, +                                         const void* extrafield_global, uInt size_extrafield_global, +                                         const char* comment, int method, int level, int raw, +                                         int windowBits,int memLevel, int strategy, +                                         const char* password, uLong crcForCrypting, +                                         uLong versionMadeBy, uLong flagBase, int zip64) +{ +    zip64_internal* zi; +    uInt size_filename; +    uInt size_comment; +    uInt i; +    int err = ZIP_OK; + +#    ifdef NOCRYPT +    if (password != NULL) +        return ZIP_PARAMERROR; +#    endif + +    if (file == NULL) +        return ZIP_PARAMERROR; + +#ifdef HAVE_BZIP2 +    if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) +      return ZIP_PARAMERROR; +#else +    if ((method!=0) && (method!=Z_DEFLATED)) +      return ZIP_PARAMERROR; +#endif + +    zi = (zip64_internal*)file; + +    if (zi->in_opened_file_inzip == 1) +    { +        err = zipCloseFileInZip (file); +        if (err != ZIP_OK) +            return err; +    } + +    if (filename==NULL) +        filename="-"; + +    if (comment==NULL) +        size_comment = 0; +    else +        size_comment = (uInt)strlen(comment); + +    size_filename = (uInt)strlen(filename); + +    if (zipfi == NULL) +        zi->ci.dosDate = 0; +    else +    { +        if (zipfi->dosDate != 0) +            zi->ci.dosDate = zipfi->dosDate; +        else +          zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); +    } + +    zi->ci.flag = flagBase; +    if ((level==8) || (level==9)) +      zi->ci.flag |= 2; +    if ((level==2)) +      zi->ci.flag |= 4; +    if ((level==1)) +      zi->ci.flag |= 6; +    if (password != NULL) +      zi->ci.flag |= 1; + +    zi->ci.crc32 = 0; +    zi->ci.method = method; +    zi->ci.encrypt = 0; +    zi->ci.stream_initialised = 0; +    zi->ci.pos_in_buffered_data = 0; +    zi->ci.raw = raw; +    zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); + +    zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; +    zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data + +    zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); + +    zi->ci.size_centralExtra = size_extrafield_global; +    zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); +    /* version info */ +    zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); +    zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); +    zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); +    zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); +    zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); +    zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ +    zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ +    zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ +    zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); +    zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); +    zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); +    zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + +    if (zipfi==NULL) +        zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); +    else +        zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + +    if (zipfi==NULL) +        zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); +    else +        zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + +    if(zi->ci.pos_local_header >= 0xffffffff) +      zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); +    else +      zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset,4); + +    for (i=0;i<size_filename;i++) +        *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i); + +    for (i=0;i<size_extrafield_global;i++) +        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) = +              *(((const char*)extrafield_global)+i); + +    for (i=0;i<size_comment;i++) +        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+ +              size_extrafield_global+i) = *(comment+i); +    if (zi->ci.central_header == NULL) +        return ZIP_INTERNALERROR; + +    zi->ci.zip64 = zip64; +    zi->ci.totalCompressedData = 0; +    zi->ci.totalUncompressedData = 0; +    zi->ci.pos_zip64extrainfo = 0; + +    err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local); + +#ifdef HAVE_BZIP2 +    zi->ci.bstream.avail_in = (uInt)0; +    zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; +    zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; +    zi->ci.bstream.total_in_hi32 = 0; +    zi->ci.bstream.total_in_lo32 = 0; +    zi->ci.bstream.total_out_hi32 = 0; +    zi->ci.bstream.total_out_lo32 = 0; +#endif + +    zi->ci.stream.avail_in = (uInt)0; +    zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; +    zi->ci.stream.next_out = zi->ci.buffered_data; +    zi->ci.stream.total_in = 0; +    zi->ci.stream.total_out = 0; +    zi->ci.stream.data_type = Z_BINARY; + +#ifdef HAVE_BZIP2 +    if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) +#else +    if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) +#endif +    { +        if(zi->ci.method == Z_DEFLATED) +        { +          zi->ci.stream.zalloc = (alloc_func)0; +          zi->ci.stream.zfree = (free_func)0; +          zi->ci.stream.opaque = (voidpf)0; + +          if (windowBits>0) +              windowBits = -windowBits; + +          err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); + +          if (err==Z_OK) +              zi->ci.stream_initialised = Z_DEFLATED; +        } +        else if(zi->ci.method == Z_BZIP2ED) +        { +#ifdef HAVE_BZIP2 +            // Init BZip stuff here +          zi->ci.bstream.bzalloc = 0; +          zi->ci.bstream.bzfree = 0; +          zi->ci.bstream.opaque = (voidpf)0; + +          err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35); +          if(err == BZ_OK) +            zi->ci.stream_initialised = Z_BZIP2ED; +#endif +        } + +    } + +#    ifndef NOCRYPT +    zi->ci.crypt_header_size = 0; +    if ((err==Z_OK) && (password != NULL)) +    { +        unsigned char bufHead[RAND_HEAD_LEN]; +        unsigned int sizeHead; +        zi->ci.encrypt = 1; +        zi->ci.pcrc_32_tab = get_crc_table(); +        /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ + +        sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); +        zi->ci.crypt_header_size = sizeHead; + +        if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) +                err = ZIP_ERRNO; +    } +#    endif + +    if (err==Z_OK) +        zi->in_opened_file_inzip = 1; +    return err; +} + +extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, +                                         const void* extrafield_local, uInt size_extrafield_local, +                                         const void* extrafield_global, uInt size_extrafield_global, +                                         const char* comment, int method, int level, int raw, +                                         int windowBits,int memLevel, int strategy, +                                         const char* password, uLong crcForCrypting, +                                         uLong versionMadeBy, uLong flagBase) +{ +    return zipOpenNewFileInZip4_64 (file, filename, zipfi, +                                 extrafield_local, size_extrafield_local, +                                 extrafield_global, size_extrafield_global, +                                 comment, method, level, raw, +                                 windowBits, memLevel, strategy, +                                 password, crcForCrypting, versionMadeBy, flagBase, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, +                                         const void* extrafield_local, uInt size_extrafield_local, +                                         const void* extrafield_global, uInt size_extrafield_global, +                                         const char* comment, int method, int level, int raw, +                                         int windowBits,int memLevel, int strategy, +                                         const char* password, uLong crcForCrypting) +{ +    return zipOpenNewFileInZip4_64 (file, filename, zipfi, +                                 extrafield_local, size_extrafield_local, +                                 extrafield_global, size_extrafield_global, +                                 comment, method, level, raw, +                                 windowBits, memLevel, strategy, +                                 password, crcForCrypting, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, +                                         const void* extrafield_local, uInt size_extrafield_local, +                                         const void* extrafield_global, uInt size_extrafield_global, +                                         const char* comment, int method, int level, int raw, +                                         int windowBits,int memLevel, int strategy, +                                         const char* password, uLong crcForCrypting, int zip64) +{ +    return zipOpenNewFileInZip4_64 (file, filename, zipfi, +                                 extrafield_local, size_extrafield_local, +                                 extrafield_global, size_extrafield_global, +                                 comment, method, level, raw, +                                 windowBits, memLevel, strategy, +                                 password, crcForCrypting, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, +                                        const void* extrafield_local, uInt size_extrafield_local, +                                        const void* extrafield_global, uInt size_extrafield_global, +                                        const char* comment, int method, int level, int raw) +{ +    return zipOpenNewFileInZip4_64 (file, filename, zipfi, +                                 extrafield_local, size_extrafield_local, +                                 extrafield_global, size_extrafield_global, +                                 comment, method, level, raw, +                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, +                                 NULL, 0, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, +                                        const void* extrafield_local, uInt size_extrafield_local, +                                        const void* extrafield_global, uInt size_extrafield_global, +                                        const char* comment, int method, int level, int raw, int zip64) +{ +    return zipOpenNewFileInZip4_64 (file, filename, zipfi, +                                 extrafield_local, size_extrafield_local, +                                 extrafield_global, size_extrafield_global, +                                 comment, method, level, raw, +                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, +                                 NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, +                                        const void* extrafield_local, uInt size_extrafield_local, +                                        const void*extrafield_global, uInt size_extrafield_global, +                                        const char* comment, int method, int level, int zip64) +{ +    return zipOpenNewFileInZip4_64 (file, filename, zipfi, +                                 extrafield_local, size_extrafield_local, +                                 extrafield_global, size_extrafield_global, +                                 comment, method, level, 0, +                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, +                                 NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, +                                        const void* extrafield_local, uInt size_extrafield_local, +                                        const void*extrafield_global, uInt size_extrafield_global, +                                        const char* comment, int method, int level) +{ +    return zipOpenNewFileInZip4_64 (file, filename, zipfi, +                                 extrafield_local, size_extrafield_local, +                                 extrafield_global, size_extrafield_global, +                                 comment, method, level, 0, +                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, +                                 NULL, 0, VERSIONMADEBY, 0, 0); +} + +local int zip64FlushWriteBuffer(zip64_internal* zi) +{ +    int err=ZIP_OK; + +    if (zi->ci.encrypt != 0) +    { +#ifndef NOCRYPT +        uInt i; +        int t; +        for (i=0;i<zi->ci.pos_in_buffered_data;i++) +            zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t); +#endif +    } + +    if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data) +      err = ZIP_ERRNO; + +    zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data; + +#ifdef HAVE_BZIP2 +    if(zi->ci.method == Z_BZIP2ED) +    { +      zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32; +      zi->ci.bstream.total_in_lo32 = 0; +      zi->ci.bstream.total_in_hi32 = 0; +    } +    else +#endif +    { +      zi->ci.totalUncompressedData += zi->ci.stream.total_in; +      zi->ci.stream.total_in = 0; +    } + + +    zi->ci.pos_in_buffered_data = 0; + +    return err; +} + +extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) +{ +    zip64_internal* zi; +    int err=ZIP_OK; + +    if (file == NULL) +        return ZIP_PARAMERROR; +    zi = (zip64_internal*)file; + +    if (zi->in_opened_file_inzip == 0) +        return ZIP_PARAMERROR; + +    zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len); + +#ifdef HAVE_BZIP2 +    if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw)) +    { +      zi->ci.bstream.next_in = (void*)buf; +      zi->ci.bstream.avail_in = len; +      err = BZ_RUN_OK; + +      while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0)) +      { +        if (zi->ci.bstream.avail_out == 0) +        { +          if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) +            err = ZIP_ERRNO; +          zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; +          zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; +        } + + +        if(err != BZ_RUN_OK) +          break; + +        if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) +        { +          uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; +//          uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; +          err=BZ2_bzCompress(&zi->ci.bstream,  BZ_RUN); + +          zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ; +        } +      } + +      if(err == BZ_RUN_OK) +        err = ZIP_OK; +    } +    else +#endif +    { +      zi->ci.stream.next_in = (Bytef*)buf; +      zi->ci.stream.avail_in = len; + +      while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) +      { +          if (zi->ci.stream.avail_out == 0) +          { +              if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) +                  err = ZIP_ERRNO; +              zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; +              zi->ci.stream.next_out = zi->ci.buffered_data; +          } + + +          if(err != ZIP_OK) +              break; + +          if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) +          { +              uLong uTotalOutBefore = zi->ci.stream.total_out; +              err=deflate(&zi->ci.stream,  Z_NO_FLUSH); +              if(uTotalOutBefore > zi->ci.stream.total_out) +              { +                int bBreak = 0; +                bBreak++; +              } + +              zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; +          } +          else +          { +              uInt copy_this,i; +              if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) +                  copy_this = zi->ci.stream.avail_in; +              else +                  copy_this = zi->ci.stream.avail_out; + +              for (i = 0; i < copy_this; i++) +                  *(((char*)zi->ci.stream.next_out)+i) = +                      *(((const char*)zi->ci.stream.next_in)+i); +              { +                  zi->ci.stream.avail_in -= copy_this; +                  zi->ci.stream.avail_out-= copy_this; +                  zi->ci.stream.next_in+= copy_this; +                  zi->ci.stream.next_out+= copy_this; +                  zi->ci.stream.total_in+= copy_this; +                  zi->ci.stream.total_out+= copy_this; +                  zi->ci.pos_in_buffered_data += copy_this; +              } +          } +      }// while(...) +    } + +    return err; +} + +extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) +{ +    return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); +} + +extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) +{ +    zip64_internal* zi; +    ZPOS64_T compressed_size; +    uLong invalidValue = 0xffffffff; +    short datasize = 0; +    int err=ZIP_OK; + +    if (file == NULL) +        return ZIP_PARAMERROR; +    zi = (zip64_internal*)file; + +    if (zi->in_opened_file_inzip == 0) +        return ZIP_PARAMERROR; +    zi->ci.stream.avail_in = 0; + +    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) +                { +                        while (err==ZIP_OK) +                        { +                                uLong uTotalOutBefore; +                                if (zi->ci.stream.avail_out == 0) +                                { +                                        if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) +                                                err = ZIP_ERRNO; +                                        zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; +                                        zi->ci.stream.next_out = zi->ci.buffered_data; +                                } +                                uTotalOutBefore = zi->ci.stream.total_out; +                                err=deflate(&zi->ci.stream,  Z_FINISH); +                                zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; +                        } +                } +    else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) +    { +#ifdef HAVE_BZIP2 +      err = BZ_FINISH_OK; +      while (err==BZ_FINISH_OK) +      { +        uLong uTotalOutBefore; +        if (zi->ci.bstream.avail_out == 0) +        { +          if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) +            err = ZIP_ERRNO; +          zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; +          zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; +        } +        uTotalOutBefore = zi->ci.bstream.total_out_lo32; +        err=BZ2_bzCompress(&zi->ci.bstream,  BZ_FINISH); +        if(err == BZ_STREAM_END) +          err = Z_STREAM_END; + +        zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore); +      } + +      if(err == BZ_FINISH_OK) +        err = ZIP_OK; +#endif +    } + +    if (err==Z_STREAM_END) +        err=ZIP_OK; /* this is normal */ + +    if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) +                { +        if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO) +            err = ZIP_ERRNO; +                } + +    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) +    { +        int tmp_err = deflateEnd(&zi->ci.stream); +        if (err == ZIP_OK) +            err = tmp_err; +        zi->ci.stream_initialised = 0; +    } +#ifdef HAVE_BZIP2 +    else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) +    { +      int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream); +                        if (err==ZIP_OK) +                                err = tmperr; +                        zi->ci.stream_initialised = 0; +    } +#endif + +    if (!zi->ci.raw) +    { +        crc32 = (uLong)zi->ci.crc32; +        uncompressed_size = zi->ci.totalUncompressedData; +    } +    compressed_size = zi->ci.totalCompressedData; + +#    ifndef NOCRYPT +    compressed_size += zi->ci.crypt_header_size; +#    endif + +    // update Current Item crc and sizes, +    if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) +    { +      /*version Made by*/ +      zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2); +      /*version needed*/ +      zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2); + +    } + +    zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ + + +    if(compressed_size >= 0xffffffff) +      zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/ +    else +      zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ + +    /// set internal file attributes field +    if (zi->ci.stream.data_type == Z_ASCII) +        zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); + +    if(uncompressed_size >= 0xffffffff) +      zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/ +    else +      zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ + +    // Add ZIP64 extra info field for uncompressed size +    if(uncompressed_size >= 0xffffffff) +      datasize += 8; + +    // Add ZIP64 extra info field for compressed size +    if(compressed_size >= 0xffffffff) +      datasize += 8; + +    // Add ZIP64 extra info field for relative offset to local file header of current file +    if(zi->ci.pos_local_header >= 0xffffffff) +      datasize += 8; + +    if(datasize > 0) +    { +      char* p = NULL; + +      if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) +      { +        // we can not write more data to the buffer that we have room for. +        return ZIP_BADZIPFILE; +      } + +      p = zi->ci.central_header + zi->ci.size_centralheader; + +      // Add Extra Information Header for 'ZIP64 information' +      zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID +      p += 2; +      zip64local_putValue_inmemory(p, datasize, 2); // DataSize +      p += 2; + +      if(uncompressed_size >= 0xffffffff) +      { +        zip64local_putValue_inmemory(p, uncompressed_size, 8); +        p += 8; +      } + +      if(compressed_size >= 0xffffffff) +      { +        zip64local_putValue_inmemory(p, compressed_size, 8); +        p += 8; +      } + +      if(zi->ci.pos_local_header >= 0xffffffff) +      { +        zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8); +        p += 8; +      } + +      // Update how much extra free space we got in the memory buffer +      // and increase the centralheader size so the new ZIP64 fields are included +      // ( 4 below is the size of HeaderID and DataSize field ) +      zi->ci.size_centralExtraFree -= datasize + 4; +      zi->ci.size_centralheader += datasize + 4; + +      // Update the extra info size field +      zi->ci.size_centralExtra += datasize + 4; +      zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2); +    } + +    if (err==ZIP_OK) +        err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader); + +    free(zi->ci.central_header); + +    if (err==ZIP_OK) +    { +        // Update the LocalFileHeader with the new values. + +        ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); + +        if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) +            err = ZIP_ERRNO; + +        if (err==ZIP_OK) +            err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ + +        if(uncompressed_size >= 0xffffffff) +        { +          if(zi->ci.pos_zip64extrainfo > 0) +          { +            // Update the size in the ZIP64 extended field. +            if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0) +              err = ZIP_ERRNO; + +            if (err==ZIP_OK) /* compressed size, unknown */ +              err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8); + +            if (err==ZIP_OK) /* uncompressed size, unknown */ +              err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); +          } +        } +        else +        { +          if (err==ZIP_OK) /* compressed size, unknown */ +              err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); + +          if (err==ZIP_OK) /* uncompressed size, unknown */ +              err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); +        } + +        if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) +            err = ZIP_ERRNO; +    } + +    zi->number_entry ++; +    zi->in_opened_file_inzip = 0; + +    return err; +} + +extern int ZEXPORT zipCloseFileInZip (zipFile file) +{ +    return zipCloseFileInZipRaw (file,0,0); +} + +int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) +{ +  int err = ZIP_OK; +  ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset; + +  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); + +  /*num disks*/ +    if (err==ZIP_OK) /* number of the disk with the start of the central directory */ +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + +  /*relative offset*/ +    if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */ +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8); + +  /*total disks*/ /* Do not support spawning of disk so always say 1 here*/ +    if (err==ZIP_OK) /* number of the disk with the start of the central directory */ +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4); + +    return err; +} + +int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +{ +  int err = ZIP_OK; + +  uLong Zip64DataSize = 44; + +  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); + +  if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */ +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ? + +  if (err==ZIP_OK) /* version made by */ +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); + +  if (err==ZIP_OK) /* version needed */ +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); + +  if (err==ZIP_OK) /* number of this disk */ +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + +  if (err==ZIP_OK) /* number of the disk with the start of the central directory */ +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + +  if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ +    err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + +  if (err==ZIP_OK) /* total number of entries in the central dir */ +    err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + +  if (err==ZIP_OK) /* size of the central directory */ +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8); + +  if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ +  { +    ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); +  } +  return err; +} +int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +{ +  int err = ZIP_OK; + +  /*signature*/ +  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); + +  if (err==ZIP_OK) /* number of this disk */ +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + +  if (err==ZIP_OK) /* number of the disk with the start of the central directory */ +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + +  if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ +  { +    { +      if(zi->number_entry >= 0xFFFF) +        err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record +      else +        err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); +    } +  } + +  if (err==ZIP_OK) /* total number of entries in the central dir */ +  { +    if(zi->number_entry >= 0xFFFF) +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record +    else +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); +  } + +  if (err==ZIP_OK) /* size of the central directory */ +    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); + +  if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ +  { +    ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; +    if(pos >= 0xffffffff) +    { +      err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); +    } +    else +                  err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4); +  } + +   return err; +} + +int Write_GlobalComment(zip64_internal* zi, const char* global_comment) +{ +  int err = ZIP_OK; +  uInt size_global_comment = 0; + +  if(global_comment != NULL) +    size_global_comment = (uInt)strlen(global_comment); + +  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); + +  if (err == ZIP_OK && size_global_comment > 0) +  { +    if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment) +      err = ZIP_ERRNO; +  } +  return err; +} + +extern int ZEXPORT zipClose (zipFile file, const char* global_comment) +{ +    zip64_internal* zi; +    int err = 0; +    uLong size_centraldir = 0; +    ZPOS64_T centraldir_pos_inzip; +    ZPOS64_T pos; + +    if (file == NULL) +        return ZIP_PARAMERROR; + +    zi = (zip64_internal*)file; + +    if (zi->in_opened_file_inzip == 1) +    { +        err = zipCloseFileInZip (file); +    } + +#ifndef NO_ADDFILEINEXISTINGZIP +    if (global_comment==NULL) +        global_comment = zi->globalcomment; +#endif + +    centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); + +    if (err==ZIP_OK) +    { +        linkedlist_datablock_internal* ldi = zi->central_dir.first_block; +        while (ldi!=NULL) +        { +            if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) +            { +                if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block) +                    err = ZIP_ERRNO; +            } + +            size_centraldir += ldi->filled_in_this_block; +            ldi = ldi->next_datablock; +        } +    } +    free_linkedlist(&(zi->central_dir)); + +    pos = centraldir_pos_inzip - zi->add_position_when_writting_offset; +    if(pos >= 0xffffffff) +    { +      ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); +      Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); + +      Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos); +    } + +    if (err==ZIP_OK) +      err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); + +    if(err == ZIP_OK) +      err = Write_GlobalComment(zi, global_comment); + +    if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0) +        if (err == ZIP_OK) +            err = ZIP_ERRNO; + +#ifndef NO_ADDFILEINEXISTINGZIP +    TRYFREE(zi->globalcomment); +#endif +    TRYFREE(zi); + +    return err; +} + +extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) +{ +  char* p = pData; +  int size = 0; +  char* pNewHeader; +  char* pTmp; +  short header; +  short dataSize; + +  int retVal = ZIP_OK; + +  if(pData == NULL || *dataLen < 4) +    return ZIP_PARAMERROR; + +  pNewHeader = (char*)ALLOC(*dataLen); +  pTmp = pNewHeader; + +  while(p < (pData + *dataLen)) +  { +    header = *(short*)p; +    dataSize = *(((short*)p)+1); + +    if( header == sHeader ) // Header found. +    { +      p += dataSize + 4; // skip it. do not copy to temp buffer +    } +    else +    { +      // Extra Info block should not be removed, So copy it to the temp buffer. +      memcpy(pTmp, p, dataSize + 4); +      p += dataSize + 4; +      size += dataSize + 4; +    } + +  } + +  if(size < *dataLen) +  { +    // clean old extra info block. +    memset(pData,0, *dataLen); + +    // copy the new extra info block over the old +    if(size > 0) +      memcpy(pData, pNewHeader, size); + +    // set the new extra info size +    *dataLen = size; + +    retVal = ZIP_OK; +  } +  else +    retVal = ZIP_ERRNO; + +  TRYFREE(pNewHeader); + +  return retVal; +}  | 
