Home | History | Annotate | Line # | Download | only in minizip
      1 /* unzip.c -- IO for uncompress .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 of Unzip for Zip64
      8          Copyright (C) 2007-2008 Even Rouault
      9 
     10          Modifications for Zip64 support on both zip and unzip
     11          Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
     12 
     13          For more info read MiniZip_info.txt
     14 
     15 
     16   ------------------------------------------------------------------------------------
     17   Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
     18   compatibility with older software. The following is from the original crypt.c.
     19   Code woven in by Terry Thorsen 1/2003.
     20 
     21   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
     22 
     23   See the accompanying file LICENSE, version 2000-Apr-09 or later
     24   (the contents of which are also included in zip.h) for terms of use.
     25   If, for some reason, all these files are missing, the Info-ZIP license
     26   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
     27 
     28         crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
     29 
     30   The encryption/decryption parts of this source code (as opposed to the
     31   non-echoing password parts) were originally written in Europe.  The
     32   whole source package can be freely distributed, including from the USA.
     33   (Prior to January 2000, re-export from the US was a violation of US law.)
     34 
     35         This encryption code is a direct transcription of the algorithm from
     36   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
     37   file (appnote.txt) is distributed with the PKZIP program (even in the
     38   version without encryption capabilities).
     39 
     40         ------------------------------------------------------------------------------------
     41 
     42         Changes in unzip.c
     43 
     44         2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos
     45   2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz*
     46   2007-2008 - Even Rouault - Remove old C style function prototypes
     47   2007-2008 - Even Rouault - Add unzip support for ZIP64
     48 
     49         Copyright (C) 2007-2008 Even Rouault
     50 
     51 
     52   Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
     53   Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G
     54                                 should only read the compressed/uncompressed size from the Zip64 format if
     55                                 the size from normal header was 0xFFFFFFFF
     56   Oct-2009 - Mathias Svensson - Applied some bug fixes from patches received from Gilles Vollant
     57   Oct-2009 - Mathias Svensson - Applied support to unzip files with compression method BZIP2 (bzip2 lib is required)
     58                                 Patch created by Daniel Borca
     59 
     60   Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
     61 
     62   Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson
     63 
     64 */
     65 
     66 
     67 #include <stdio.h>
     68 #include <stdlib.h>
     69 #include <string.h>
     70 
     71 #ifndef NOUNCRYPT
     72         #define NOUNCRYPT
     73 #endif
     74 
     75 #include "zlib.h"
     76 #include "unzip.h"
     77 
     78 #ifdef STDC
     79 #  include <stddef.h>
     80 #endif
     81 #ifdef NO_ERRNO_H
     82     extern int errno;
     83 #else
     84 #   include <errno.h>
     85 #endif
     86 
     87 
     88 #ifndef local
     89 #  define local static
     90 #endif
     91 /* compile with -Dlocal if your debugger can't find static symbols */
     92 
     93 
     94 #ifndef CASESENSITIVITYDEFAULT_NO
     95 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
     96 #    define CASESENSITIVITYDEFAULT_NO
     97 #  endif
     98 #endif
     99 
    100 
    101 #ifndef UNZ_BUFSIZE
    102 #define UNZ_BUFSIZE (16384)
    103 #endif
    104 
    105 #ifndef UNZ_MAXFILENAMEINZIP
    106 #define UNZ_MAXFILENAMEINZIP (256)
    107 #endif
    108 
    109 #ifndef ALLOC
    110 # define ALLOC(size) (malloc(size))
    111 #endif
    112 
    113 #define SIZECENTRALDIRITEM (0x2e)
    114 #define SIZEZIPLOCALHEADER (0x1e)
    115 
    116 
    117 const char unz_copyright[] =
    118    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
    119 
    120 /* unz_file_info64_internal contain internal info about a file in zipfile*/
    121 typedef struct unz_file_info64_internal_s
    122 {
    123     ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
    124 } unz_file_info64_internal;
    125 
    126 
    127 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
    128     when reading and decompress it */
    129 typedef struct
    130 {
    131     char  *read_buffer;         /* internal buffer for compressed data */
    132     z_stream stream;            /* zLib stream structure for inflate */
    133 
    134 #ifdef HAVE_BZIP2
    135     bz_stream bstream;          /* bzLib stream structure for bziped */
    136 #endif
    137 
    138     ZPOS64_T pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
    139     uLong stream_initialised;   /* flag set if stream structure is initialised*/
    140 
    141     ZPOS64_T offset_local_extrafield;/* offset of the local extra field */
    142     uInt  size_local_extrafield;/* size of the local extra field */
    143     ZPOS64_T pos_local_extrafield;   /* position in the local extra field in read*/
    144     ZPOS64_T total_out_64;
    145 
    146     uLong crc32;                /* crc32 of all data uncompressed */
    147     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
    148     ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
    149     ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
    150     zlib_filefunc64_32_def z_filefunc;
    151     voidpf filestream;        /* io structure of the zipfile */
    152     uLong compression_method;   /* compression method (0==store) */
    153     ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
    154     int   raw;
    155 } file_in_zip64_read_info_s;
    156 
    157 
    158 /* unz64_s contain internal information about the zipfile
    159 */
    160 typedef struct
    161 {
    162     zlib_filefunc64_32_def z_filefunc;
    163     int is64bitOpenFunction;
    164     voidpf filestream;        /* io structure of the zipfile */
    165     unz_global_info64 gi;       /* public global information */
    166     ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
    167     ZPOS64_T num_file;             /* number of the current file in the zipfile*/
    168     ZPOS64_T pos_in_central_dir;   /* pos of the current file in the central dir*/
    169     ZPOS64_T current_file_ok;      /* flag about the usability of the current file*/
    170     ZPOS64_T central_pos;          /* position of the beginning of the central dir*/
    171 
    172     ZPOS64_T size_central_dir;     /* size of the central directory  */
    173     ZPOS64_T offset_central_dir;   /* offset of start of central directory with
    174                                    respect to the starting disk number */
    175 
    176     unz_file_info64 cur_file_info; /* public info about the current file in zip*/
    177     unz_file_info64_internal cur_file_info_internal; /* private info about it*/
    178     file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
    179                                         file if we are decompressing it */
    180     int encrypted;
    181 
    182     int isZip64;
    183 
    184 #    ifndef NOUNCRYPT
    185     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
    186     const z_crc_t* pcrc_32_tab;
    187 #    endif
    188 } unz64_s;
    189 
    190 
    191 #ifndef NOUNCRYPT
    192 #include "crypt.h"
    193 #endif
    194 
    195 
    196 /* ===========================================================================
    197    Reads a long in LSB order from the given gz_stream. Sets
    198 */
    199 
    200 local int unz64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def,
    201                               voidpf filestream,
    202                               uLong *pX) {
    203     unsigned char c[2];
    204     int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,2);
    205     if (err==2)
    206     {
    207         *pX = c[0] | ((uLong)c[1] << 8);
    208         return UNZ_OK;
    209     }
    210     else
    211     {
    212         *pX = 0;
    213         if (ZERROR64(*pzlib_filefunc_def,filestream))
    214             return UNZ_ERRNO;
    215         else
    216             return UNZ_EOF;
    217     }
    218 }
    219 
    220 local int unz64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def,
    221                              voidpf filestream,
    222                              uLong *pX) {
    223     unsigned char c[4];
    224     int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,4);
    225     if (err==4)
    226     {
    227         *pX = c[0] | ((uLong)c[1] << 8) | ((uLong)c[2] << 16) | ((uLong)c[3] << 24);
    228         return UNZ_OK;
    229     }
    230     else
    231     {
    232         *pX = 0;
    233         if (ZERROR64(*pzlib_filefunc_def,filestream))
    234             return UNZ_ERRNO;
    235         else
    236             return UNZ_EOF;
    237     }
    238 }
    239 
    240 
    241 local int unz64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
    242                                voidpf filestream,
    243                                ZPOS64_T *pX) {
    244     unsigned char c[8];
    245     int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,8);
    246     if (err==8)
    247     {
    248         *pX = c[0] | ((ZPOS64_T)c[1] << 8) | ((ZPOS64_T)c[2] << 16) | ((ZPOS64_T)c[3] << 24)
    249             | ((ZPOS64_T)c[4] << 32) | ((ZPOS64_T)c[5] << 40) | ((ZPOS64_T)c[6] << 48) | ((ZPOS64_T)c[7] << 56);
    250         return UNZ_OK;
    251     }
    252     else
    253     {
    254         *pX = 0;
    255         if (ZERROR64(*pzlib_filefunc_def,filestream))
    256             return UNZ_ERRNO;
    257         else
    258             return UNZ_EOF;
    259     }
    260 }
    261 
    262 /* My own strcmpi / strcasecmp */
    263 local int strcmpcasenosensitive_internal(const char* fileName1, const char* fileName2) {
    264     for (;;)
    265     {
    266         char c1=*(fileName1++);
    267         char c2=*(fileName2++);
    268         if ((c1>='a') && (c1<='z'))
    269             c1 -= 0x20;
    270         if ((c2>='a') && (c2<='z'))
    271             c2 -= 0x20;
    272         if (c1=='\0')
    273             return ((c2=='\0') ? 0 : -1);
    274         if (c2=='\0')
    275             return 1;
    276         if (c1<c2)
    277             return -1;
    278         if (c1>c2)
    279             return 1;
    280     }
    281 }
    282 
    283 
    284 #ifdef  CASESENSITIVITYDEFAULT_NO
    285 #define CASESENSITIVITYDEFAULTVALUE 2
    286 #else
    287 #define CASESENSITIVITYDEFAULTVALUE 1
    288 #endif
    289 
    290 #ifndef STRCMPCASENOSENTIVEFUNCTION
    291 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
    292 #endif
    293 
    294 /*
    295    Compare two filenames (fileName1,fileName2).
    296    If iCaseSensitivity = 1, comparison is case sensitive (like strcmp)
    297    If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi
    298                                                                 or strcasecmp)
    299    If iCaseSensitivity = 0, case sensitivity is default of your operating system
    300         (like 1 on Unix, 2 on Windows)
    301 
    302 */
    303 extern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,
    304                                              const char*  fileName2,
    305                                              int iCaseSensitivity) {
    306     if (iCaseSensitivity==0)
    307         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
    308 
    309     if (iCaseSensitivity==1)
    310         return strcmp(fileName1,fileName2);
    311 
    312     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
    313 }
    314 
    315 #ifndef BUFREADCOMMENT
    316 #define BUFREADCOMMENT (0x400)
    317 #endif
    318 
    319 #ifndef CENTRALDIRINVALID
    320 #define CENTRALDIRINVALID ((ZPOS64_T)(-1))
    321 #endif
    322 
    323 /*
    324   Locate the Central directory of a zipfile (at the end, just before
    325     the global comment)
    326 */
    327 local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
    328     unsigned char* buf;
    329     ZPOS64_T uSizeFile;
    330     ZPOS64_T uBackRead;
    331     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
    332     ZPOS64_T uPosFound=CENTRALDIRINVALID;
    333 
    334     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
    335         return CENTRALDIRINVALID;
    336 
    337 
    338     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
    339 
    340     if (uMaxBack>uSizeFile)
    341         uMaxBack = uSizeFile;
    342 
    343     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    344     if (buf==NULL)
    345         return CENTRALDIRINVALID;
    346 
    347     uBackRead = 4;
    348     while (uBackRead<uMaxBack)
    349     {
    350         uLong uReadSize;
    351         ZPOS64_T uReadPos ;
    352         int i;
    353         if (uBackRead+BUFREADCOMMENT>uMaxBack)
    354             uBackRead = uMaxBack;
    355         else
    356             uBackRead+=BUFREADCOMMENT;
    357         uReadPos = uSizeFile-uBackRead ;
    358 
    359         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
    360                      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
    361         if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
    362             break;
    363 
    364         if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
    365             break;
    366 
    367         for (i=(int)uReadSize-3; (i--)>0;)
    368             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
    369                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
    370             {
    371                 uPosFound = uReadPos+(unsigned)i;
    372                 break;
    373             }
    374 
    375         if (uPosFound!=CENTRALDIRINVALID)
    376             break;
    377     }
    378     free(buf);
    379     return uPosFound;
    380 }
    381 
    382 
    383 /*
    384   Locate the Central directory 64 of a zipfile (at the end, just before
    385     the global comment)
    386 */
    387 local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
    388                                              voidpf filestream) {
    389     unsigned char* buf;
    390     ZPOS64_T uSizeFile;
    391     ZPOS64_T uBackRead;
    392     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
    393     ZPOS64_T uPosFound=CENTRALDIRINVALID;
    394     uLong uL;
    395                 ZPOS64_T relativeOffset;
    396 
    397     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
    398         return CENTRALDIRINVALID;
    399 
    400 
    401     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
    402 
    403     if (uMaxBack>uSizeFile)
    404         uMaxBack = uSizeFile;
    405 
    406     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    407     if (buf==NULL)
    408         return CENTRALDIRINVALID;
    409 
    410     uBackRead = 4;
    411     while (uBackRead<uMaxBack)
    412     {
    413         uLong uReadSize;
    414         ZPOS64_T uReadPos;
    415         int i;
    416         if (uBackRead+BUFREADCOMMENT>uMaxBack)
    417             uBackRead = uMaxBack;
    418         else
    419             uBackRead+=BUFREADCOMMENT;
    420         uReadPos = uSizeFile-uBackRead ;
    421 
    422         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
    423                      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
    424         if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
    425             break;
    426 
    427         if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
    428             break;
    429 
    430         for (i=(int)uReadSize-3; (i--)>0;)
    431             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
    432                 ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
    433             {
    434                 uPosFound = uReadPos+(unsigned)i;
    435                 break;
    436             }
    437 
    438         if (uPosFound!=CENTRALDIRINVALID)
    439             break;
    440     }
    441     free(buf);
    442     if (uPosFound == CENTRALDIRINVALID)
    443         return CENTRALDIRINVALID;
    444 
    445     /* Zip64 end of central directory locator */
    446     if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
    447         return CENTRALDIRINVALID;
    448 
    449     /* the signature, already checked */
    450     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
    451         return CENTRALDIRINVALID;
    452 
    453     /* number of the disk with the start of the zip64 end of central directory */
    454     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
    455         return CENTRALDIRINVALID;
    456     if (uL != 0)
    457         return CENTRALDIRINVALID;
    458 
    459     /* relative offset of the zip64 end of central directory record */
    460     if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
    461         return CENTRALDIRINVALID;
    462 
    463     /* total number of disks */
    464     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
    465         return CENTRALDIRINVALID;
    466     if (uL != 1)
    467         return CENTRALDIRINVALID;
    468 
    469     /* Goto end of central directory record */
    470     if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
    471         return CENTRALDIRINVALID;
    472 
    473      /* the signature */
    474     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
    475         return CENTRALDIRINVALID;
    476 
    477     if (uL != 0x06064b50)
    478         return CENTRALDIRINVALID;
    479 
    480     return relativeOffset;
    481 }
    482 
    483 /*
    484   Open a Zip file. path contain the full pathname (by example,
    485      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
    486      "zlib/zlib114.zip".
    487      If the zipfile cannot be opened (file doesn't exist or in not valid), the
    488        return value is NULL.
    489      Else, the return value is a unzFile Handle, usable with other function
    490        of this unzip package.
    491 */
    492 local unzFile unzOpenInternal(const void *path,
    493                               zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
    494                               int is64bitOpenFunction) {
    495     unz64_s us;
    496     unz64_s *s;
    497     ZPOS64_T central_pos;
    498     uLong   uL;
    499 
    500     uLong number_disk;          /* number of the current disk, used for
    501                                    spanning ZIP, unsupported, always 0*/
    502     uLong number_disk_with_CD;  /* number the disk with central dir, used
    503                                    for spanning ZIP, unsupported, always 0*/
    504     ZPOS64_T number_entry_CD;      /* total number of entries in
    505                                    the central dir
    506                                    (same than number_entry on nospan) */
    507 
    508     int err=UNZ_OK;
    509 
    510     if (unz_copyright[0]!=' ')
    511         return NULL;
    512 
    513     us.z_filefunc.zseek32_file = NULL;
    514     us.z_filefunc.ztell32_file = NULL;
    515     if (pzlib_filefunc64_32_def==NULL)
    516         fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
    517     else
    518         us.z_filefunc = *pzlib_filefunc64_32_def;
    519     us.is64bitOpenFunction = is64bitOpenFunction;
    520 
    521 
    522 
    523     us.filestream = ZOPEN64(us.z_filefunc,
    524                                                  path,
    525                                                  ZLIB_FILEFUNC_MODE_READ |
    526                                                  ZLIB_FILEFUNC_MODE_EXISTING);
    527     if (us.filestream==NULL)
    528         return NULL;
    529 
    530     central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
    531     if (central_pos!=CENTRALDIRINVALID)
    532     {
    533         uLong uS;
    534         ZPOS64_T uL64;
    535 
    536         us.isZip64 = 1;
    537 
    538         if (ZSEEK64(us.z_filefunc, us.filestream,
    539                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
    540         err=UNZ_ERRNO;
    541 
    542         /* the signature, already checked */
    543         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
    544             err=UNZ_ERRNO;
    545 
    546         /* size of zip64 end of central directory record */
    547         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)
    548             err=UNZ_ERRNO;
    549 
    550         /* version made by */
    551         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
    552             err=UNZ_ERRNO;
    553 
    554         /* version needed to extract */
    555         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
    556             err=UNZ_ERRNO;
    557 
    558         /* number of this disk */
    559         if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
    560             err=UNZ_ERRNO;
    561 
    562         /* number of the disk with the start of the central directory */
    563         if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
    564             err=UNZ_ERRNO;
    565 
    566         /* total number of entries in the central directory on this disk */
    567         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
    568             err=UNZ_ERRNO;
    569 
    570         /* total number of entries in the central directory */
    571         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
    572             err=UNZ_ERRNO;
    573 
    574         if ((number_entry_CD!=us.gi.number_entry) ||
    575             (number_disk_with_CD!=0) ||
    576             (number_disk!=0))
    577             err=UNZ_BADZIPFILE;
    578 
    579         /* size of the central directory */
    580         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
    581             err=UNZ_ERRNO;
    582 
    583         /* offset of start of central directory with respect to the
    584           starting disk number */
    585         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
    586             err=UNZ_ERRNO;
    587 
    588         us.gi.size_comment = 0;
    589     }
    590     else
    591     {
    592         central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
    593         if (central_pos==CENTRALDIRINVALID)
    594             err=UNZ_ERRNO;
    595 
    596         us.isZip64 = 0;
    597 
    598         if (ZSEEK64(us.z_filefunc, us.filestream,
    599                                         central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
    600             err=UNZ_ERRNO;
    601 
    602         /* the signature, already checked */
    603         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
    604             err=UNZ_ERRNO;
    605 
    606         /* number of this disk */
    607         if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
    608             err=UNZ_ERRNO;
    609 
    610         /* number of the disk with the start of the central directory */
    611         if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
    612             err=UNZ_ERRNO;
    613 
    614         /* total number of entries in the central dir on this disk */
    615         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
    616             err=UNZ_ERRNO;
    617         us.gi.number_entry = uL;
    618 
    619         /* total number of entries in the central dir */
    620         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
    621             err=UNZ_ERRNO;
    622         number_entry_CD = uL;
    623 
    624         if ((number_entry_CD!=us.gi.number_entry) ||
    625             (number_disk_with_CD!=0) ||
    626             (number_disk!=0))
    627             err=UNZ_BADZIPFILE;
    628 
    629         /* size of the central directory */
    630         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
    631             err=UNZ_ERRNO;
    632         us.size_central_dir = uL;
    633 
    634         /* offset of start of central directory with respect to the
    635             starting disk number */
    636         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
    637             err=UNZ_ERRNO;
    638         us.offset_central_dir = uL;
    639 
    640         /* zipfile comment length */
    641         if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
    642             err=UNZ_ERRNO;
    643     }
    644 
    645     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
    646         (err==UNZ_OK))
    647         err=UNZ_BADZIPFILE;
    648 
    649     if (err!=UNZ_OK)
    650     {
    651         ZCLOSE64(us.z_filefunc, us.filestream);
    652         return NULL;
    653     }
    654 
    655     us.byte_before_the_zipfile = central_pos -
    656                             (us.offset_central_dir+us.size_central_dir);
    657     us.central_pos = central_pos;
    658     us.pfile_in_zip_read = NULL;
    659     us.encrypted = 0;
    660 
    661 
    662     s=(unz64_s*)ALLOC(sizeof(unz64_s));
    663     if( s != NULL)
    664     {
    665         *s=us;
    666         unzGoToFirstFile((unzFile)s);
    667     }
    668     return (unzFile)s;
    669 }
    670 
    671 
    672 extern unzFile ZEXPORT unzOpen2(const char *path,
    673                                 zlib_filefunc_def* pzlib_filefunc32_def) {
    674     if (pzlib_filefunc32_def != NULL)
    675     {
    676         zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
    677         fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
    678         return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
    679     }
    680     else
    681         return unzOpenInternal(path, NULL, 0);
    682 }
    683 
    684 extern unzFile ZEXPORT unzOpen2_64(const void *path,
    685                                    zlib_filefunc64_def* pzlib_filefunc_def) {
    686     if (pzlib_filefunc_def != NULL)
    687     {
    688         zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
    689         zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
    690         zlib_filefunc64_32_def_fill.ztell32_file = NULL;
    691         zlib_filefunc64_32_def_fill.zseek32_file = NULL;
    692         return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);
    693     }
    694     else
    695         return unzOpenInternal(path, NULL, 1);
    696 }
    697 
    698 extern unzFile ZEXPORT unzOpen(const char *path) {
    699     return unzOpenInternal(path, NULL, 0);
    700 }
    701 
    702 extern unzFile ZEXPORT unzOpen64(const void *path) {
    703     return unzOpenInternal(path, NULL, 1);
    704 }
    705 
    706 /*
    707   Close a ZipFile opened with unzOpen.
    708   If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
    709     these files MUST be closed with unzCloseCurrentFile before call unzClose.
    710   return UNZ_OK if there is no problem. */
    711 extern int ZEXPORT unzClose(unzFile file) {
    712     unz64_s* s;
    713     if (file==NULL)
    714         return UNZ_PARAMERROR;
    715     s=(unz64_s*)file;
    716 
    717     if (s->pfile_in_zip_read!=NULL)
    718         unzCloseCurrentFile(file);
    719 
    720     ZCLOSE64(s->z_filefunc, s->filestream);
    721     free(s);
    722     return UNZ_OK;
    723 }
    724 
    725 
    726 /*
    727   Write info about the ZipFile in the *pglobal_info structure.
    728   No preparation of the structure is needed
    729   return UNZ_OK if there is no problem. */
    730 extern int ZEXPORT unzGetGlobalInfo64(unzFile file, unz_global_info64* pglobal_info) {
    731     unz64_s* s;
    732     if (file==NULL)
    733         return UNZ_PARAMERROR;
    734     s=(unz64_s*)file;
    735     *pglobal_info=s->gi;
    736     return UNZ_OK;
    737 }
    738 
    739 extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32) {
    740     unz64_s* s;
    741     if (file==NULL)
    742         return UNZ_PARAMERROR;
    743     s=(unz64_s*)file;
    744     /* to do : check if number_entry is not truncated */
    745     pglobal_info32->number_entry = (uLong)s->gi.number_entry;
    746     pglobal_info32->size_comment = s->gi.size_comment;
    747     return UNZ_OK;
    748 }
    749 /*
    750    Translate date/time from Dos format to tm_unz (readable more easily)
    751 */
    752 local void unz64local_DosDateToTmuDate(ZPOS64_T ulDosDate, tm_unz* ptm) {
    753     ZPOS64_T uDate;
    754     uDate = (ZPOS64_T)(ulDosDate>>16);
    755     ptm->tm_mday = (int)(uDate&0x1f) ;
    756     ptm->tm_mon =  (int)((((uDate)&0x1E0)/0x20)-1) ;
    757     ptm->tm_year = (int)(((uDate&0x0FE00)/0x0200)+1980) ;
    758 
    759     ptm->tm_hour = (int) ((ulDosDate &0xF800)/0x800);
    760     ptm->tm_min =  (int) ((ulDosDate&0x7E0)/0x20) ;
    761     ptm->tm_sec =  (int) (2*(ulDosDate&0x1f)) ;
    762 }
    763 
    764 /*
    765   Get Info about the current file in the zipfile, with internal only info
    766 */
    767 local int unz64local_GetCurrentFileInfoInternal(unzFile file,
    768                                                 unz_file_info64 *pfile_info,
    769                                                 unz_file_info64_internal
    770                                                 *pfile_info_internal,
    771                                                 char *szFileName,
    772                                                 uLong fileNameBufferSize,
    773                                                 void *extraField,
    774                                                 uLong extraFieldBufferSize,
    775                                                 char *szComment,
    776                                                 uLong commentBufferSize) {
    777     unz64_s* s;
    778     unz_file_info64 file_info;
    779     unz_file_info64_internal file_info_internal;
    780     int err=UNZ_OK;
    781     uLong uMagic;
    782     long lSeek=0;
    783     uLong uL;
    784 
    785     if (file==NULL)
    786         return UNZ_PARAMERROR;
    787     s=(unz64_s*)file;
    788     if (ZSEEK64(s->z_filefunc, s->filestream,
    789               s->pos_in_central_dir+s->byte_before_the_zipfile,
    790               ZLIB_FILEFUNC_SEEK_SET)!=0)
    791         err=UNZ_ERRNO;
    792 
    793 
    794     /* we check the magic */
    795     if (err==UNZ_OK)
    796     {
    797         if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
    798             err=UNZ_ERRNO;
    799         else if (uMagic!=0x02014b50)
    800             err=UNZ_BADZIPFILE;
    801     }
    802 
    803     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
    804         err=UNZ_ERRNO;
    805 
    806     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
    807         err=UNZ_ERRNO;
    808 
    809     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
    810         err=UNZ_ERRNO;
    811 
    812     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
    813         err=UNZ_ERRNO;
    814 
    815     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
    816         err=UNZ_ERRNO;
    817 
    818     unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
    819 
    820     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
    821         err=UNZ_ERRNO;
    822 
    823     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
    824         err=UNZ_ERRNO;
    825     file_info.compressed_size = uL;
    826 
    827     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
    828         err=UNZ_ERRNO;
    829     file_info.uncompressed_size = uL;
    830 
    831     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
    832         err=UNZ_ERRNO;
    833 
    834     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
    835         err=UNZ_ERRNO;
    836 
    837     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
    838         err=UNZ_ERRNO;
    839 
    840     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
    841         err=UNZ_ERRNO;
    842 
    843     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
    844         err=UNZ_ERRNO;
    845 
    846     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
    847         err=UNZ_ERRNO;
    848 
    849                 // relative offset of local header
    850     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
    851         err=UNZ_ERRNO;
    852     file_info_internal.offset_curfile = uL;
    853 
    854     lSeek+=file_info.size_filename;
    855     if ((err==UNZ_OK) && (szFileName!=NULL))
    856     {
    857         uLong uSizeRead ;
    858         if (file_info.size_filename<fileNameBufferSize)
    859         {
    860             *(szFileName+file_info.size_filename)='\0';
    861             uSizeRead = file_info.size_filename;
    862         }
    863         else
    864             uSizeRead = fileNameBufferSize;
    865 
    866         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
    867             if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
    868                 err=UNZ_ERRNO;
    869         lSeek -= uSizeRead;
    870     }
    871 
    872     // Read extrafield
    873     if ((err==UNZ_OK) && (extraField!=NULL))
    874     {
    875         ZPOS64_T uSizeRead ;
    876         if (file_info.size_file_extra<extraFieldBufferSize)
    877             uSizeRead = file_info.size_file_extra;
    878         else
    879             uSizeRead = extraFieldBufferSize;
    880 
    881         if (lSeek!=0)
    882         {
    883             if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
    884                 lSeek=0;
    885             else
    886                 err=UNZ_ERRNO;
    887         }
    888 
    889         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
    890             if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead)
    891                 err=UNZ_ERRNO;
    892 
    893         lSeek += file_info.size_file_extra - (uLong)uSizeRead;
    894     }
    895     else
    896         lSeek += file_info.size_file_extra;
    897 
    898 
    899     if ((err==UNZ_OK) && (file_info.size_file_extra != 0))
    900     {
    901                                 uLong acc = 0;
    902 
    903         // since lSeek now points to after the extra field we need to move back
    904         lSeek -= file_info.size_file_extra;
    905 
    906         if (lSeek!=0)
    907         {
    908             if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
    909                 lSeek=0;
    910             else
    911                 err=UNZ_ERRNO;
    912         }
    913 
    914         while(acc < file_info.size_file_extra)
    915         {
    916             uLong headerId;
    917                                                 uLong dataSize;
    918 
    919             if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
    920                 err=UNZ_ERRNO;
    921 
    922             if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
    923                 err=UNZ_ERRNO;
    924 
    925             /* ZIP64 extra fields */
    926             if (headerId == 0x0001)
    927             {
    928                 if(file_info.uncompressed_size == MAXU32)
    929                 {
    930                     if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
    931                         err=UNZ_ERRNO;
    932                 }
    933 
    934                 if(file_info.compressed_size == MAXU32)
    935                 {
    936                     if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
    937                         err=UNZ_ERRNO;
    938                 }
    939 
    940                 if(file_info_internal.offset_curfile == MAXU32)
    941                 {
    942                     /* Relative Header offset */
    943                     if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
    944                         err=UNZ_ERRNO;
    945                 }
    946 
    947                 if(file_info.disk_num_start == 0xffff)
    948                 {
    949                     /* Disk Start Number */
    950                     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
    951                         err=UNZ_ERRNO;
    952                 }
    953 
    954             }
    955             else
    956             {
    957                 if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
    958                     err=UNZ_ERRNO;
    959             }
    960 
    961             acc += 2 + 2 + dataSize;
    962         }
    963     }
    964 
    965     if ((err==UNZ_OK) && (szComment!=NULL))
    966     {
    967         uLong uSizeRead ;
    968         if (file_info.size_file_comment<commentBufferSize)
    969         {
    970             *(szComment+file_info.size_file_comment)='\0';
    971             uSizeRead = file_info.size_file_comment;
    972         }
    973         else
    974             uSizeRead = commentBufferSize;
    975 
    976         if (lSeek!=0)
    977         {
    978             if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
    979                 lSeek=0;
    980             else
    981                 err=UNZ_ERRNO;
    982         }
    983 
    984         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
    985             if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
    986                 err=UNZ_ERRNO;
    987         lSeek+=file_info.size_file_comment - uSizeRead;
    988     }
    989     else
    990         lSeek+=file_info.size_file_comment;
    991 
    992 
    993     if ((err==UNZ_OK) && (pfile_info!=NULL))
    994         *pfile_info=file_info;
    995 
    996     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
    997         *pfile_info_internal=file_info_internal;
    998 
    999     return err;
   1000 }
   1001 
   1002 
   1003 
   1004 /*
   1005   Write info about the ZipFile in the *pglobal_info structure.
   1006   No preparation of the structure is needed
   1007   return UNZ_OK if there is no problem.
   1008 */
   1009 extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file,
   1010                                            unz_file_info64 * pfile_info,
   1011                                            char * szFileName, uLong fileNameBufferSize,
   1012                                            void *extraField, uLong extraFieldBufferSize,
   1013                                            char* szComment,  uLong commentBufferSize) {
   1014     return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
   1015                                                  szFileName,fileNameBufferSize,
   1016                                                  extraField,extraFieldBufferSize,
   1017                                                  szComment,commentBufferSize);
   1018 }
   1019 
   1020 extern int ZEXPORT unzGetCurrentFileInfo(unzFile file,
   1021                                          unz_file_info * pfile_info,
   1022                                          char * szFileName, uLong fileNameBufferSize,
   1023                                          void *extraField, uLong extraFieldBufferSize,
   1024                                          char* szComment,  uLong commentBufferSize) {
   1025     int err;
   1026     unz_file_info64 file_info64;
   1027     err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL,
   1028                                                 szFileName,fileNameBufferSize,
   1029                                                 extraField,extraFieldBufferSize,
   1030                                                 szComment,commentBufferSize);
   1031     if ((err==UNZ_OK) && (pfile_info != NULL))
   1032     {
   1033         pfile_info->version = file_info64.version;
   1034         pfile_info->version_needed = file_info64.version_needed;
   1035         pfile_info->flag = file_info64.flag;
   1036         pfile_info->compression_method = file_info64.compression_method;
   1037         pfile_info->dosDate = file_info64.dosDate;
   1038         pfile_info->crc = file_info64.crc;
   1039 
   1040         pfile_info->size_filename = file_info64.size_filename;
   1041         pfile_info->size_file_extra = file_info64.size_file_extra;
   1042         pfile_info->size_file_comment = file_info64.size_file_comment;
   1043 
   1044         pfile_info->disk_num_start = file_info64.disk_num_start;
   1045         pfile_info->internal_fa = file_info64.internal_fa;
   1046         pfile_info->external_fa = file_info64.external_fa;
   1047 
   1048         pfile_info->tmu_date = file_info64.tmu_date;
   1049 
   1050 
   1051         pfile_info->compressed_size = (uLong)file_info64.compressed_size;
   1052         pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;
   1053 
   1054     }
   1055     return err;
   1056 }
   1057 /*
   1058   Set the current file of the zipfile to the first file.
   1059   return UNZ_OK if there is no problem
   1060 */
   1061 extern int ZEXPORT unzGoToFirstFile(unzFile file) {
   1062     int err=UNZ_OK;
   1063     unz64_s* s;
   1064     if (file==NULL)
   1065         return UNZ_PARAMERROR;
   1066     s=(unz64_s*)file;
   1067     s->pos_in_central_dir=s->offset_central_dir;
   1068     s->num_file=0;
   1069     err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
   1070                                              &s->cur_file_info_internal,
   1071                                              NULL,0,NULL,0,NULL,0);
   1072     s->current_file_ok = (err == UNZ_OK);
   1073     return err;
   1074 }
   1075 
   1076 /*
   1077   Set the current file of the zipfile to the next file.
   1078   return UNZ_OK if there is no problem
   1079   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
   1080 */
   1081 extern int ZEXPORT unzGoToNextFile(unzFile file) {
   1082     unz64_s* s;
   1083     int err;
   1084 
   1085     if (file==NULL)
   1086         return UNZ_PARAMERROR;
   1087     s=(unz64_s*)file;
   1088     if (!s->current_file_ok)
   1089         return UNZ_END_OF_LIST_OF_FILE;
   1090     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
   1091       if (s->num_file+1==s->gi.number_entry)
   1092         return UNZ_END_OF_LIST_OF_FILE;
   1093 
   1094     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
   1095             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
   1096     s->num_file++;
   1097     err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
   1098                                                &s->cur_file_info_internal,
   1099                                                NULL,0,NULL,0,NULL,0);
   1100     s->current_file_ok = (err == UNZ_OK);
   1101     return err;
   1102 }
   1103 
   1104 
   1105 /*
   1106   Try locate the file szFileName in the zipfile.
   1107   For the iCaseSensitivity signification, see unzStringFileNameCompare
   1108 
   1109   return value :
   1110   UNZ_OK if the file is found. It becomes the current file.
   1111   UNZ_END_OF_LIST_OF_FILE if the file is not found
   1112 */
   1113 extern int ZEXPORT unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity) {
   1114     unz64_s* s;
   1115     int err;
   1116 
   1117     /* We remember the 'current' position in the file so that we can jump
   1118      * back there if we fail.
   1119      */
   1120     unz_file_info64 cur_file_infoSaved;
   1121     unz_file_info64_internal cur_file_info_internalSaved;
   1122     ZPOS64_T num_fileSaved;
   1123     ZPOS64_T pos_in_central_dirSaved;
   1124 
   1125 
   1126     if (file==NULL)
   1127         return UNZ_PARAMERROR;
   1128 
   1129     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
   1130         return UNZ_PARAMERROR;
   1131 
   1132     s=(unz64_s*)file;
   1133     if (!s->current_file_ok)
   1134         return UNZ_END_OF_LIST_OF_FILE;
   1135 
   1136     /* Save the current state */
   1137     num_fileSaved = s->num_file;
   1138     pos_in_central_dirSaved = s->pos_in_central_dir;
   1139     cur_file_infoSaved = s->cur_file_info;
   1140     cur_file_info_internalSaved = s->cur_file_info_internal;
   1141 
   1142     err = unzGoToFirstFile(file);
   1143 
   1144     while (err == UNZ_OK)
   1145     {
   1146         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
   1147         err = unzGetCurrentFileInfo64(file,NULL,
   1148                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
   1149                                     NULL,0,NULL,0);
   1150         if (err == UNZ_OK)
   1151         {
   1152             if (unzStringFileNameCompare(szCurrentFileName,
   1153                                             szFileName,iCaseSensitivity)==0)
   1154                 return UNZ_OK;
   1155             err = unzGoToNextFile(file);
   1156         }
   1157     }
   1158 
   1159     /* We failed, so restore the state of the 'current file' to where we
   1160      * were.
   1161      */
   1162     s->num_file = num_fileSaved ;
   1163     s->pos_in_central_dir = pos_in_central_dirSaved ;
   1164     s->cur_file_info = cur_file_infoSaved;
   1165     s->cur_file_info_internal = cur_file_info_internalSaved;
   1166     return err;
   1167 }
   1168 
   1169 
   1170 /*
   1171 ///////////////////////////////////////////
   1172 // Contributed by Ryan Haksi (mailto://cryogen (at) infoserve.net)
   1173 // I need random access
   1174 //
   1175 // Further optimization could be realized by adding an ability
   1176 // to cache the directory in memory. The goal being a single
   1177 // comprehensive file read to put the file I need in a memory.
   1178 */
   1179 
   1180 /*
   1181 typedef struct unz_file_pos_s
   1182 {
   1183     ZPOS64_T pos_in_zip_directory;   // offset in file
   1184     ZPOS64_T num_of_file;            // # of file
   1185 } unz_file_pos;
   1186 */
   1187 
   1188 extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) {
   1189     unz64_s* s;
   1190 
   1191     if (file==NULL || file_pos==NULL)
   1192         return UNZ_PARAMERROR;
   1193     s=(unz64_s*)file;
   1194     if (!s->current_file_ok)
   1195         return UNZ_END_OF_LIST_OF_FILE;
   1196 
   1197     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
   1198     file_pos->num_of_file           = s->num_file;
   1199 
   1200     return UNZ_OK;
   1201 }
   1202 
   1203 extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos* file_pos) {
   1204     unz64_file_pos file_pos64;
   1205     int err = unzGetFilePos64(file,&file_pos64);
   1206     if (err==UNZ_OK)
   1207     {
   1208         file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;
   1209         file_pos->num_of_file = (uLong)file_pos64.num_of_file;
   1210     }
   1211     return err;
   1212 }
   1213 
   1214 extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) {
   1215     unz64_s* s;
   1216     int err;
   1217 
   1218     if (file==NULL || file_pos==NULL)
   1219         return UNZ_PARAMERROR;
   1220     s=(unz64_s*)file;
   1221 
   1222     /* jump to the right spot */
   1223     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
   1224     s->num_file           = file_pos->num_of_file;
   1225 
   1226     /* set the current file */
   1227     err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
   1228                                                &s->cur_file_info_internal,
   1229                                                NULL,0,NULL,0,NULL,0);
   1230     /* return results */
   1231     s->current_file_ok = (err == UNZ_OK);
   1232     return err;
   1233 }
   1234 
   1235 extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos* file_pos) {
   1236     unz64_file_pos file_pos64;
   1237     if (file_pos == NULL)
   1238         return UNZ_PARAMERROR;
   1239 
   1240     file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
   1241     file_pos64.num_of_file = file_pos->num_of_file;
   1242     return unzGoToFilePos64(file,&file_pos64);
   1243 }
   1244 
   1245 /*
   1246 // Unzip Helper Functions - should be here?
   1247 ///////////////////////////////////////////
   1248 */
   1249 
   1250 /*
   1251   Read the local header of the current zipfile
   1252   Check the coherency of the local header and info in the end of central
   1253         directory about this file
   1254   store in *piSizeVar the size of extra info in local header
   1255         (filename and size of extra field data)
   1256 */
   1257 local int unz64local_CheckCurrentFileCoherencyHeader(unz64_s* s, uInt* piSizeVar,
   1258                                                      ZPOS64_T * poffset_local_extrafield,
   1259                                                      uInt  * psize_local_extrafield) {
   1260     uLong uMagic,uData,uFlags;
   1261     uLong size_filename;
   1262     uLong size_extra_field;
   1263     int err=UNZ_OK;
   1264 
   1265     *piSizeVar = 0;
   1266     *poffset_local_extrafield = 0;
   1267     *psize_local_extrafield = 0;
   1268 
   1269     if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
   1270                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
   1271         return UNZ_ERRNO;
   1272 
   1273 
   1274     if (err==UNZ_OK)
   1275     {
   1276         if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
   1277             err=UNZ_ERRNO;
   1278         else if (uMagic!=0x04034b50)
   1279             err=UNZ_BADZIPFILE;
   1280     }
   1281 
   1282     if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
   1283         err=UNZ_ERRNO;
   1284 /*
   1285     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
   1286         err=UNZ_BADZIPFILE;
   1287 */
   1288     if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
   1289         err=UNZ_ERRNO;
   1290 
   1291     if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
   1292         err=UNZ_ERRNO;
   1293     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
   1294         err=UNZ_BADZIPFILE;
   1295 
   1296     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
   1297 /* #ifdef HAVE_BZIP2 */
   1298                          (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
   1299 /* #endif */
   1300                          (s->cur_file_info.compression_method!=Z_DEFLATED))
   1301         err=UNZ_BADZIPFILE;
   1302 
   1303     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
   1304         err=UNZ_ERRNO;
   1305 
   1306     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
   1307         err=UNZ_ERRNO;
   1308     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0))
   1309         err=UNZ_BADZIPFILE;
   1310 
   1311     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
   1312         err=UNZ_ERRNO;
   1313     else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0))
   1314         err=UNZ_BADZIPFILE;
   1315 
   1316     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
   1317         err=UNZ_ERRNO;
   1318     else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0))
   1319         err=UNZ_BADZIPFILE;
   1320 
   1321     if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
   1322         err=UNZ_ERRNO;
   1323     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
   1324         err=UNZ_BADZIPFILE;
   1325 
   1326     *piSizeVar += (uInt)size_filename;
   1327 
   1328     if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
   1329         err=UNZ_ERRNO;
   1330     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
   1331                                     SIZEZIPLOCALHEADER + size_filename;
   1332     *psize_local_extrafield = (uInt)size_extra_field;
   1333 
   1334     *piSizeVar += (uInt)size_extra_field;
   1335 
   1336     return err;
   1337 }
   1338 
   1339 /*
   1340   Open for reading data the current file in the zipfile.
   1341   If there is no error and the file is opened, the return value is UNZ_OK.
   1342 */
   1343 extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int* method,
   1344                                        int* level, int raw, const char* password) {
   1345     int err=UNZ_OK;
   1346     uInt iSizeVar;
   1347     unz64_s* s;
   1348     file_in_zip64_read_info_s* pfile_in_zip_read_info;
   1349     ZPOS64_T offset_local_extrafield;  /* offset of the local extra field */
   1350     uInt  size_local_extrafield;    /* size of the local extra field */
   1351 #    ifndef NOUNCRYPT
   1352     char source[12];
   1353 #    else
   1354     if (password != NULL)
   1355         return UNZ_PARAMERROR;
   1356 #    endif
   1357 
   1358     if (file==NULL)
   1359         return UNZ_PARAMERROR;
   1360     s=(unz64_s*)file;
   1361     if (!s->current_file_ok)
   1362         return UNZ_PARAMERROR;
   1363 
   1364     if (s->pfile_in_zip_read != NULL)
   1365         unzCloseCurrentFile(file);
   1366 
   1367     if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
   1368         return UNZ_BADZIPFILE;
   1369 
   1370     pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
   1371     if (pfile_in_zip_read_info==NULL)
   1372         return UNZ_INTERNALERROR;
   1373 
   1374     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
   1375     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
   1376     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
   1377     pfile_in_zip_read_info->pos_local_extrafield=0;
   1378     pfile_in_zip_read_info->raw=raw;
   1379 
   1380     if (pfile_in_zip_read_info->read_buffer==NULL)
   1381     {
   1382         free(pfile_in_zip_read_info);
   1383         return UNZ_INTERNALERROR;
   1384     }
   1385 
   1386     pfile_in_zip_read_info->stream_initialised=0;
   1387 
   1388     if (method!=NULL)
   1389         *method = (int)s->cur_file_info.compression_method;
   1390 
   1391     if (level!=NULL)
   1392     {
   1393         *level = 6;
   1394         switch (s->cur_file_info.flag & 0x06)
   1395         {
   1396           case 6 : *level = 1; break;
   1397           case 4 : *level = 2; break;
   1398           case 2 : *level = 9; break;
   1399         }
   1400     }
   1401 
   1402     if ((s->cur_file_info.compression_method!=0) &&
   1403 /* #ifdef HAVE_BZIP2 */
   1404         (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
   1405 /* #endif */
   1406         (s->cur_file_info.compression_method!=Z_DEFLATED))
   1407 
   1408         err=UNZ_BADZIPFILE;
   1409 
   1410     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
   1411     pfile_in_zip_read_info->crc32=0;
   1412     pfile_in_zip_read_info->total_out_64=0;
   1413     pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
   1414     pfile_in_zip_read_info->filestream=s->filestream;
   1415     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
   1416     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
   1417 
   1418     pfile_in_zip_read_info->stream.total_out = 0;
   1419 
   1420     if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw))
   1421     {
   1422 #ifdef HAVE_BZIP2
   1423       pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
   1424       pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
   1425       pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
   1426       pfile_in_zip_read_info->bstream.state = (voidpf)0;
   1427 
   1428       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
   1429       pfile_in_zip_read_info->stream.zfree = (free_func)0;
   1430       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
   1431       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
   1432       pfile_in_zip_read_info->stream.avail_in = 0;
   1433 
   1434       err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
   1435       if (err == Z_OK)
   1436         pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;
   1437       else
   1438       {
   1439         free(pfile_in_zip_read_info->read_buffer);
   1440         free(pfile_in_zip_read_info);
   1441         return err;
   1442       }
   1443 #else
   1444       pfile_in_zip_read_info->raw=1;
   1445 #endif
   1446     }
   1447     else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
   1448     {
   1449       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
   1450       pfile_in_zip_read_info->stream.zfree = (free_func)0;
   1451       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
   1452       pfile_in_zip_read_info->stream.next_in = 0;
   1453       pfile_in_zip_read_info->stream.avail_in = 0;
   1454 
   1455       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
   1456       if (err == Z_OK)
   1457         pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
   1458       else
   1459       {
   1460         free(pfile_in_zip_read_info->read_buffer);
   1461         free(pfile_in_zip_read_info);
   1462         return err;
   1463       }
   1464         /* windowBits is passed < 0 to tell that there is no zlib header.
   1465          * Note that in this case inflate *requires* an extra "dummy" byte
   1466          * after the compressed stream in order to complete decompression and
   1467          * return Z_STREAM_END.
   1468          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
   1469          * size of both compressed and uncompressed data
   1470          */
   1471     }
   1472     pfile_in_zip_read_info->rest_read_compressed =
   1473             s->cur_file_info.compressed_size ;
   1474     pfile_in_zip_read_info->rest_read_uncompressed =
   1475             s->cur_file_info.uncompressed_size ;
   1476 
   1477 
   1478     pfile_in_zip_read_info->pos_in_zipfile =
   1479             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
   1480               iSizeVar;
   1481 
   1482     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
   1483 
   1484     s->pfile_in_zip_read = pfile_in_zip_read_info;
   1485                 s->encrypted = 0;
   1486 
   1487 #    ifndef NOUNCRYPT
   1488     if (password != NULL)
   1489     {
   1490         int i;
   1491         s->pcrc_32_tab = get_crc_table();
   1492         init_keys(password,s->keys,s->pcrc_32_tab);
   1493         if (ZSEEK64(s->z_filefunc, s->filestream,
   1494                   s->pfile_in_zip_read->pos_in_zipfile +
   1495                      s->pfile_in_zip_read->byte_before_the_zipfile,
   1496                   SEEK_SET)!=0)
   1497             return UNZ_INTERNALERROR;
   1498         if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12)
   1499             return UNZ_INTERNALERROR;
   1500 
   1501         for (i = 0; i<12; i++)
   1502             zdecode(s->keys,s->pcrc_32_tab,source[i]);
   1503 
   1504         s->pfile_in_zip_read->pos_in_zipfile+=12;
   1505         s->encrypted=1;
   1506     }
   1507 #    endif
   1508 
   1509 
   1510     return UNZ_OK;
   1511 }
   1512 
   1513 extern int ZEXPORT unzOpenCurrentFile(unzFile file) {
   1514     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
   1515 }
   1516 
   1517 extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char* password) {
   1518     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
   1519 }
   1520 
   1521 extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int* method, int* level, int raw) {
   1522     return unzOpenCurrentFile3(file, method, level, raw, NULL);
   1523 }
   1524 
   1525 /** Addition for GDAL : START */
   1526 
   1527 extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file) {
   1528     unz64_s* s;
   1529     file_in_zip64_read_info_s* pfile_in_zip_read_info;
   1530     s=(unz64_s*)file;
   1531     if (file==NULL)
   1532         return 0; //UNZ_PARAMERROR;
   1533     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1534     if (pfile_in_zip_read_info==NULL)
   1535         return 0; //UNZ_PARAMERROR;
   1536     return pfile_in_zip_read_info->pos_in_zipfile +
   1537                          pfile_in_zip_read_info->byte_before_the_zipfile;
   1538 }
   1539 
   1540 /** Addition for GDAL : END */
   1541 
   1542 /*
   1543   Read bytes from the current file.
   1544   buf contain buffer where data must be copied
   1545   len the size of buf.
   1546 
   1547   return the number of byte copied if some bytes are copied
   1548   return 0 if the end of file was reached
   1549   return <0 with error code if there is an error
   1550     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
   1551 */
   1552 extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
   1553     int err=UNZ_OK;
   1554     uInt iRead = 0;
   1555     unz64_s* s;
   1556     file_in_zip64_read_info_s* pfile_in_zip_read_info;
   1557     if (file==NULL)
   1558         return UNZ_PARAMERROR;
   1559     s=(unz64_s*)file;
   1560     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1561 
   1562     if (pfile_in_zip_read_info==NULL)
   1563         return UNZ_PARAMERROR;
   1564 
   1565 
   1566     if (pfile_in_zip_read_info->read_buffer == NULL)
   1567         return UNZ_END_OF_LIST_OF_FILE;
   1568     if (len==0)
   1569         return 0;
   1570 
   1571     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
   1572 
   1573     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
   1574 
   1575     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
   1576         (!(pfile_in_zip_read_info->raw)))
   1577         pfile_in_zip_read_info->stream.avail_out =
   1578             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
   1579 
   1580     if ((len>pfile_in_zip_read_info->rest_read_compressed+
   1581            pfile_in_zip_read_info->stream.avail_in) &&
   1582          (pfile_in_zip_read_info->raw))
   1583         pfile_in_zip_read_info->stream.avail_out =
   1584             (uInt)pfile_in_zip_read_info->rest_read_compressed+
   1585             pfile_in_zip_read_info->stream.avail_in;
   1586 
   1587     while (pfile_in_zip_read_info->stream.avail_out>0)
   1588     {
   1589         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
   1590             (pfile_in_zip_read_info->rest_read_compressed>0))
   1591         {
   1592             uInt uReadThis = UNZ_BUFSIZE;
   1593             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
   1594                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
   1595             if (uReadThis == 0)
   1596                 return UNZ_EOF;
   1597             if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
   1598                       pfile_in_zip_read_info->filestream,
   1599                       pfile_in_zip_read_info->pos_in_zipfile +
   1600                          pfile_in_zip_read_info->byte_before_the_zipfile,
   1601                          ZLIB_FILEFUNC_SEEK_SET)!=0)
   1602                 return UNZ_ERRNO;
   1603             if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
   1604                       pfile_in_zip_read_info->filestream,
   1605                       pfile_in_zip_read_info->read_buffer,
   1606                       uReadThis)!=uReadThis)
   1607                 return UNZ_ERRNO;
   1608 
   1609 
   1610 #            ifndef NOUNCRYPT
   1611             if(s->encrypted)
   1612             {
   1613                 uInt i;
   1614                 for(i=0;i<uReadThis;i++)
   1615                   pfile_in_zip_read_info->read_buffer[i] =
   1616                       zdecode(s->keys,s->pcrc_32_tab,
   1617                               pfile_in_zip_read_info->read_buffer[i]);
   1618             }
   1619 #            endif
   1620 
   1621 
   1622             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
   1623 
   1624             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
   1625 
   1626             pfile_in_zip_read_info->stream.next_in =
   1627                 (Bytef*)pfile_in_zip_read_info->read_buffer;
   1628             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
   1629         }
   1630 
   1631         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
   1632         {
   1633             uInt uDoCopy,i ;
   1634 
   1635             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
   1636                 (pfile_in_zip_read_info->rest_read_compressed == 0))
   1637                 return (iRead==0) ? UNZ_EOF : (int)iRead;
   1638 
   1639             if (pfile_in_zip_read_info->stream.avail_out <
   1640                             pfile_in_zip_read_info->stream.avail_in)
   1641                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
   1642             else
   1643                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
   1644 
   1645             for (i=0;i<uDoCopy;i++)
   1646                 *(pfile_in_zip_read_info->stream.next_out+i) =
   1647                         *(pfile_in_zip_read_info->stream.next_in+i);
   1648 
   1649             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;
   1650 
   1651             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
   1652                                 pfile_in_zip_read_info->stream.next_out,
   1653                                 uDoCopy);
   1654             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
   1655             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
   1656             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
   1657             pfile_in_zip_read_info->stream.next_out += uDoCopy;
   1658             pfile_in_zip_read_info->stream.next_in += uDoCopy;
   1659             pfile_in_zip_read_info->stream.total_out += uDoCopy;
   1660             iRead += uDoCopy;
   1661         }
   1662         else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)
   1663         {
   1664 #ifdef HAVE_BZIP2
   1665             uLong uTotalOutBefore,uTotalOutAfter;
   1666             const Bytef *bufBefore;
   1667             uLong uOutThis;
   1668 
   1669             pfile_in_zip_read_info->bstream.next_in        = (char*)pfile_in_zip_read_info->stream.next_in;
   1670             pfile_in_zip_read_info->bstream.avail_in       = pfile_in_zip_read_info->stream.avail_in;
   1671             pfile_in_zip_read_info->bstream.total_in_lo32  = pfile_in_zip_read_info->stream.total_in;
   1672             pfile_in_zip_read_info->bstream.total_in_hi32  = 0;
   1673             pfile_in_zip_read_info->bstream.next_out       = (char*)pfile_in_zip_read_info->stream.next_out;
   1674             pfile_in_zip_read_info->bstream.avail_out      = pfile_in_zip_read_info->stream.avail_out;
   1675             pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
   1676             pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
   1677 
   1678             uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
   1679             bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;
   1680 
   1681             err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
   1682 
   1683             uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
   1684             uOutThis = uTotalOutAfter-uTotalOutBefore;
   1685 
   1686             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
   1687 
   1688             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis));
   1689             pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
   1690             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
   1691 
   1692             pfile_in_zip_read_info->stream.next_in   = (Bytef*)pfile_in_zip_read_info->bstream.next_in;
   1693             pfile_in_zip_read_info->stream.avail_in  = pfile_in_zip_read_info->bstream.avail_in;
   1694             pfile_in_zip_read_info->stream.total_in  = pfile_in_zip_read_info->bstream.total_in_lo32;
   1695             pfile_in_zip_read_info->stream.next_out  = (Bytef*)pfile_in_zip_read_info->bstream.next_out;
   1696             pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
   1697             pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
   1698 
   1699             if (err==BZ_STREAM_END)
   1700               return (iRead==0) ? UNZ_EOF : iRead;
   1701             if (err!=BZ_OK)
   1702               break;
   1703 #endif
   1704         } // end Z_BZIP2ED
   1705         else
   1706         {
   1707             ZPOS64_T uTotalOutBefore,uTotalOutAfter;
   1708             const Bytef *bufBefore;
   1709             ZPOS64_T uOutThis;
   1710             int flush=Z_SYNC_FLUSH;
   1711 
   1712             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
   1713             bufBefore = pfile_in_zip_read_info->stream.next_out;
   1714 
   1715             /*
   1716             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
   1717                      pfile_in_zip_read_info->stream.avail_out) &&
   1718                 (pfile_in_zip_read_info->rest_read_compressed == 0))
   1719                 flush = Z_FINISH;
   1720             */
   1721             err=inflate(&pfile_in_zip_read_info->stream,flush);
   1722 
   1723             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
   1724               err = Z_DATA_ERROR;
   1725 
   1726             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
   1727             /* Detect overflow, because z_stream.total_out is uLong (32 bits) */
   1728             if (uTotalOutAfter<uTotalOutBefore)
   1729                 uTotalOutAfter += 1LL << 32; /* Add maximum value of uLong + 1 */
   1730             uOutThis = uTotalOutAfter-uTotalOutBefore;
   1731 
   1732             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
   1733 
   1734             pfile_in_zip_read_info->crc32 =
   1735                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
   1736                         (uInt)(uOutThis));
   1737 
   1738             pfile_in_zip_read_info->rest_read_uncompressed -=
   1739                 uOutThis;
   1740 
   1741             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
   1742 
   1743             if (err==Z_STREAM_END)
   1744                 return (iRead==0) ? UNZ_EOF : (int)iRead;
   1745             if (err!=Z_OK)
   1746                 break;
   1747         }
   1748     }
   1749 
   1750     if (err==Z_OK)
   1751         return (int)iRead;
   1752     return err;
   1753 }
   1754 
   1755 
   1756 /*
   1757   Give the current position in uncompressed data
   1758 */
   1759 extern z_off_t ZEXPORT unztell(unzFile file) {
   1760     unz64_s* s;
   1761     file_in_zip64_read_info_s* pfile_in_zip_read_info;
   1762     if (file==NULL)
   1763         return UNZ_PARAMERROR;
   1764     s=(unz64_s*)file;
   1765     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1766 
   1767     if (pfile_in_zip_read_info==NULL)
   1768         return UNZ_PARAMERROR;
   1769 
   1770     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
   1771 }
   1772 
   1773 extern ZPOS64_T ZEXPORT unztell64(unzFile file) {
   1774 
   1775     unz64_s* s;
   1776     file_in_zip64_read_info_s* pfile_in_zip_read_info;
   1777     if (file==NULL)
   1778         return (ZPOS64_T)-1;
   1779     s=(unz64_s*)file;
   1780     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1781 
   1782     if (pfile_in_zip_read_info==NULL)
   1783         return (ZPOS64_T)-1;
   1784 
   1785     return pfile_in_zip_read_info->total_out_64;
   1786 }
   1787 
   1788 
   1789 /*
   1790   return 1 if the end of file was reached, 0 elsewhere
   1791 */
   1792 extern int ZEXPORT unzeof(unzFile file) {
   1793     unz64_s* s;
   1794     file_in_zip64_read_info_s* pfile_in_zip_read_info;
   1795     if (file==NULL)
   1796         return UNZ_PARAMERROR;
   1797     s=(unz64_s*)file;
   1798     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1799 
   1800     if (pfile_in_zip_read_info==NULL)
   1801         return UNZ_PARAMERROR;
   1802 
   1803     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
   1804         return 1;
   1805     else
   1806         return 0;
   1807 }
   1808 
   1809 
   1810 
   1811 /*
   1812 Read extra field from the current file (opened by unzOpenCurrentFile)
   1813 This is the local-header version of the extra field (sometimes, there is
   1814 more info in the local-header version than in the central-header)
   1815 
   1816   if buf==NULL, it return the size of the local extra field that can be read
   1817 
   1818   if buf!=NULL, len is the size of the buffer, the extra header is copied in
   1819     buf.
   1820   the return value is the number of bytes copied in buf, or (if <0)
   1821     the error code
   1822 */
   1823 extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len) {
   1824     unz64_s* s;
   1825     file_in_zip64_read_info_s* pfile_in_zip_read_info;
   1826     uInt read_now;
   1827     ZPOS64_T size_to_read;
   1828 
   1829     if (file==NULL)
   1830         return UNZ_PARAMERROR;
   1831     s=(unz64_s*)file;
   1832     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1833 
   1834     if (pfile_in_zip_read_info==NULL)
   1835         return UNZ_PARAMERROR;
   1836 
   1837     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
   1838                 pfile_in_zip_read_info->pos_local_extrafield);
   1839 
   1840     if (buf==NULL)
   1841         return (int)size_to_read;
   1842 
   1843     if (len>size_to_read)
   1844         read_now = (uInt)size_to_read;
   1845     else
   1846         read_now = (uInt)len ;
   1847 
   1848     if (read_now==0)
   1849         return 0;
   1850 
   1851     if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
   1852               pfile_in_zip_read_info->filestream,
   1853               pfile_in_zip_read_info->offset_local_extrafield +
   1854               pfile_in_zip_read_info->pos_local_extrafield,
   1855               ZLIB_FILEFUNC_SEEK_SET)!=0)
   1856         return UNZ_ERRNO;
   1857 
   1858     if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
   1859               pfile_in_zip_read_info->filestream,
   1860               buf,read_now)!=read_now)
   1861         return UNZ_ERRNO;
   1862 
   1863     return (int)read_now;
   1864 }
   1865 
   1866 /*
   1867   Close the file in zip opened with unzOpenCurrentFile
   1868   Return UNZ_CRCERROR if all the file was read but the CRC is not good
   1869 */
   1870 extern int ZEXPORT unzCloseCurrentFile(unzFile file) {
   1871     int err=UNZ_OK;
   1872 
   1873     unz64_s* s;
   1874     file_in_zip64_read_info_s* pfile_in_zip_read_info;
   1875     if (file==NULL)
   1876         return UNZ_PARAMERROR;
   1877     s=(unz64_s*)file;
   1878     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1879 
   1880     if (pfile_in_zip_read_info==NULL)
   1881         return UNZ_PARAMERROR;
   1882 
   1883 
   1884     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
   1885         (!pfile_in_zip_read_info->raw))
   1886     {
   1887         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
   1888             err=UNZ_CRCERROR;
   1889     }
   1890 
   1891 
   1892     free(pfile_in_zip_read_info->read_buffer);
   1893     pfile_in_zip_read_info->read_buffer = NULL;
   1894     if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
   1895         inflateEnd(&pfile_in_zip_read_info->stream);
   1896 #ifdef HAVE_BZIP2
   1897     else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
   1898         BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
   1899 #endif
   1900 
   1901 
   1902     pfile_in_zip_read_info->stream_initialised = 0;
   1903     free(pfile_in_zip_read_info);
   1904 
   1905     s->pfile_in_zip_read=NULL;
   1906 
   1907     return err;
   1908 }
   1909 
   1910 
   1911 /*
   1912   Get the global comment string of the ZipFile, in the szComment buffer.
   1913   uSizeBuf is the size of the szComment buffer.
   1914   return the number of byte copied or an error code <0
   1915 */
   1916 extern int ZEXPORT unzGetGlobalComment(unzFile file, char * szComment, uLong uSizeBuf) {
   1917     unz64_s* s;
   1918     uLong uReadThis ;
   1919     if (file==NULL)
   1920         return (int)UNZ_PARAMERROR;
   1921     s=(unz64_s*)file;
   1922 
   1923     uReadThis = uSizeBuf;
   1924     if (uReadThis>s->gi.size_comment)
   1925         uReadThis = s->gi.size_comment;
   1926 
   1927     if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
   1928         return UNZ_ERRNO;
   1929 
   1930     if (uReadThis>0)
   1931     {
   1932       *szComment='\0';
   1933       if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
   1934         return UNZ_ERRNO;
   1935     }
   1936 
   1937     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
   1938         *(szComment+s->gi.size_comment)='\0';
   1939     return (int)uReadThis;
   1940 }
   1941 
   1942 /* Additions by RX '2004 */
   1943 extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) {
   1944     unz64_s* s;
   1945 
   1946     if (file==NULL)
   1947           return 0; //UNZ_PARAMERROR;
   1948     s=(unz64_s*)file;
   1949     if (!s->current_file_ok)
   1950       return 0;
   1951     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
   1952       if (s->num_file==s->gi.number_entry)
   1953          return 0;
   1954     return s->pos_in_central_dir;
   1955 }
   1956 
   1957 extern uLong ZEXPORT unzGetOffset(unzFile file) {
   1958     ZPOS64_T offset64;
   1959 
   1960     if (file==NULL)
   1961           return 0; //UNZ_PARAMERROR;
   1962     offset64 = unzGetOffset64(file);
   1963     return (uLong)offset64;
   1964 }
   1965 
   1966 extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) {
   1967     unz64_s* s;
   1968     int err;
   1969 
   1970     if (file==NULL)
   1971         return UNZ_PARAMERROR;
   1972     s=(unz64_s*)file;
   1973 
   1974     s->pos_in_central_dir = pos;
   1975     s->num_file = s->gi.number_entry;      /* hack */
   1976     err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
   1977                                               &s->cur_file_info_internal,
   1978                                               NULL,0,NULL,0,NULL,0);
   1979     s->current_file_ok = (err == UNZ_OK);
   1980     return err;
   1981 }
   1982 
   1983 extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) {
   1984     return unzSetOffset64(file,pos);
   1985 }
   1986