Home | History | Annotate | Line # | Download | only in minizip
unzip.c revision 1.1
      1 /*	$NetBSD: unzip.c,v 1.1 2006/01/14 20:10:59 christos Exp $	*/
      2 
      3 /* unzip.c -- IO for uncompress .zip files using zlib
      4    Version 1.01e, February 12th, 2005
      5 
      6    Copyright (C) 1998-2005 Gilles Vollant
      7 
      8    Read unzip.h for more info
      9 */
     10 
     11 /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
     12 compatibility with older software. The following is from the original crypt.c. Code
     13 woven in by Terry Thorsen 1/2003.
     14 */
     15 /*
     16   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
     17 
     18   See the accompanying file LICENSE, version 2000-Apr-09 or later
     19   (the contents of which are also included in zip.h) for terms of use.
     20   If, for some reason, all these files are missing, the Info-ZIP license
     21   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
     22 */
     23 /*
     24   crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
     25 
     26   The encryption/decryption parts of this source code (as opposed to the
     27   non-echoing password parts) were originally written in Europe.  The
     28   whole source package can be freely distributed, including from the USA.
     29   (Prior to January 2000, re-export from the US was a violation of US law.)
     30  */
     31 
     32 /*
     33   This encryption code is a direct transcription of the algorithm from
     34   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
     35   file (appnote.txt) is distributed with the PKZIP program (even in the
     36   version without encryption capabilities).
     37  */
     38 
     39 
     40 #include <stdio.h>
     41 #include <stdlib.h>
     42 #include <string.h>
     43 #include "zlib.h"
     44 #include "unzip.h"
     45 
     46 #ifdef STDC
     47 #  include <stddef.h>
     48 #  include <string.h>
     49 #  include <stdlib.h>
     50 #endif
     51 #ifdef NO_ERRNO_H
     52     extern int errno;
     53 #else
     54 #   include <errno.h>
     55 #endif
     56 
     57 
     58 #ifndef local
     59 #  define local static
     60 #endif
     61 /* compile with -Dlocal if your debugger can't find static symbols */
     62 
     63 
     64 #ifndef CASESENSITIVITYDEFAULT_NO
     65 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
     66 #    define CASESENSITIVITYDEFAULT_NO
     67 #  endif
     68 #endif
     69 
     70 
     71 #ifndef UNZ_BUFSIZE
     72 #define UNZ_BUFSIZE (16384)
     73 #endif
     74 
     75 #ifndef UNZ_MAXFILENAMEINZIP
     76 #define UNZ_MAXFILENAMEINZIP (256)
     77 #endif
     78 
     79 #ifndef ALLOC
     80 # define ALLOC(size) (malloc(size))
     81 #endif
     82 #ifndef TRYFREE
     83 # define TRYFREE(p) {if (p) free(p);}
     84 #endif
     85 
     86 #define SIZECENTRALDIRITEM (0x2e)
     87 #define SIZEZIPLOCALHEADER (0x1e)
     88 
     89 
     90 
     91 
     92 const char unz_copyright[] =
     93    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
     94 
     95 /* unz_file_info_interntal contain internal info about a file in zipfile*/
     96 typedef struct unz_file_info_internal_s
     97 {
     98     uLong offset_curfile;/* relative offset of local header 4 bytes */
     99 } unz_file_info_internal;
    100 
    101 
    102 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
    103     when reading and decompress it */
    104 typedef struct
    105 {
    106     char  *read_buffer;         /* internal buffer for compressed data */
    107     z_stream stream;            /* zLib stream structure for inflate */
    108 
    109     uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
    110     uLong stream_initialised;   /* flag set if stream structure is initialised*/
    111 
    112     uLong offset_local_extrafield;/* offset of the local extra field */
    113     uInt  size_local_extrafield;/* size of the local extra field */
    114     uLong pos_local_extrafield;   /* position in the local extra field in read*/
    115 
    116     uLong crc32;                /* crc32 of all data uncompressed */
    117     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
    118     uLong rest_read_compressed; /* number of byte to be decompressed */
    119     uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
    120     zlib_filefunc_def z_filefunc;
    121     voidpf filestream;        /* io structore of the zipfile */
    122     uLong compression_method;   /* compression method (0==store) */
    123     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
    124     int   raw;
    125 } file_in_zip_read_info_s;
    126 
    127 
    128 /* unz_s contain internal information about the zipfile
    129 */
    130 typedef struct
    131 {
    132     zlib_filefunc_def z_filefunc;
    133     voidpf filestream;        /* io structore of the zipfile */
    134     unz_global_info gi;       /* public global information */
    135     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
    136     uLong num_file;             /* number of the current file in the zipfile*/
    137     uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
    138     uLong current_file_ok;      /* flag about the usability of the current file*/
    139     uLong central_pos;          /* position of the beginning of the central dir*/
    140 
    141     uLong size_central_dir;     /* size of the central directory  */
    142     uLong offset_central_dir;   /* offset of start of central directory with
    143                                    respect to the starting disk number */
    144 
    145     unz_file_info cur_file_info; /* public info about the current file in zip*/
    146     unz_file_info_internal cur_file_info_internal; /* private info about it*/
    147     file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
    148                                         file if we are decompressing it */
    149     int encrypted;
    150 #    ifndef NOUNCRYPT
    151     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
    152     const unsigned long* pcrc_32_tab;
    153 #    endif
    154 } unz_s;
    155 
    156 
    157 #ifndef NOUNCRYPT
    158 #include "crypt.h"
    159 #endif
    160 
    161 /* ===========================================================================
    162      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
    163    for end of file.
    164    IN assertion: the stream s has been sucessfully opened for reading.
    165 */
    166 
    167 
    168 local int unzlocal_getByte OF((
    169     const zlib_filefunc_def* pzlib_filefunc_def,
    170     voidpf filestream,
    171     int *pi));
    172 
    173 local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
    174     const zlib_filefunc_def* pzlib_filefunc_def;
    175     voidpf filestream;
    176     int *pi;
    177 {
    178     unsigned char c;
    179     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
    180     if (err==1)
    181     {
    182         *pi = (int)c;
    183         return UNZ_OK;
    184     }
    185     else
    186     {
    187         if (ZERROR(*pzlib_filefunc_def,filestream))
    188             return UNZ_ERRNO;
    189         else
    190             return UNZ_EOF;
    191     }
    192 }
    193 
    194 
    195 /* ===========================================================================
    196    Reads a long in LSB order from the given gz_stream. Sets
    197 */
    198 local int unzlocal_getShort OF((
    199     const zlib_filefunc_def* pzlib_filefunc_def,
    200     voidpf filestream,
    201     uLong *pX));
    202 
    203 local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
    204     const zlib_filefunc_def* pzlib_filefunc_def;
    205     voidpf filestream;
    206     uLong *pX;
    207 {
    208     uLong x ;
    209     int i;
    210     int err;
    211 
    212     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
    213     x = (uLong)i;
    214 
    215     if (err==UNZ_OK)
    216         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
    217     x += ((uLong)i)<<8;
    218 
    219     if (err==UNZ_OK)
    220         *pX = x;
    221     else
    222         *pX = 0;
    223     return err;
    224 }
    225 
    226 local int unzlocal_getLong OF((
    227     const zlib_filefunc_def* pzlib_filefunc_def,
    228     voidpf filestream,
    229     uLong *pX));
    230 
    231 local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
    232     const zlib_filefunc_def* pzlib_filefunc_def;
    233     voidpf filestream;
    234     uLong *pX;
    235 {
    236     uLong x ;
    237     int i;
    238     int err;
    239 
    240     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
    241     x = (uLong)i;
    242 
    243     if (err==UNZ_OK)
    244         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
    245     x += ((uLong)i)<<8;
    246 
    247     if (err==UNZ_OK)
    248         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
    249     x += ((uLong)i)<<16;
    250 
    251     if (err==UNZ_OK)
    252         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
    253     x += ((uLong)i)<<24;
    254 
    255     if (err==UNZ_OK)
    256         *pX = x;
    257     else
    258         *pX = 0;
    259     return err;
    260 }
    261 
    262 
    263 /* My own strcmpi / strcasecmp */
    264 local int strcmpcasenosensitive_internal (fileName1,fileName2)
    265     const char* fileName1;
    266     const char* fileName2;
    267 {
    268     for (;;)
    269     {
    270         char c1=*(fileName1++);
    271         char c2=*(fileName2++);
    272         if ((c1>='a') && (c1<='z'))
    273             c1 -= 0x20;
    274         if ((c2>='a') && (c2<='z'))
    275             c2 -= 0x20;
    276         if (c1=='\0')
    277             return ((c2=='\0') ? 0 : -1);
    278         if (c2=='\0')
    279             return 1;
    280         if (c1<c2)
    281             return -1;
    282         if (c1>c2)
    283             return 1;
    284     }
    285 }
    286 
    287 
    288 #ifdef  CASESENSITIVITYDEFAULT_NO
    289 #define CASESENSITIVITYDEFAULTVALUE 2
    290 #else
    291 #define CASESENSITIVITYDEFAULTVALUE 1
    292 #endif
    293 
    294 #ifndef STRCMPCASENOSENTIVEFUNCTION
    295 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
    296 #endif
    297 
    298 /*
    299    Compare two filename (fileName1,fileName2).
    300    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
    301    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
    302                                                                 or strcasecmp)
    303    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
    304         (like 1 on Unix, 2 on Windows)
    305 
    306 */
    307 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
    308     const char* fileName1;
    309     const char* fileName2;
    310     int iCaseSensitivity;
    311 {
    312     if (iCaseSensitivity==0)
    313         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
    314 
    315     if (iCaseSensitivity==1)
    316         return strcmp(fileName1,fileName2);
    317 
    318     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
    319 }
    320 
    321 #ifndef BUFREADCOMMENT
    322 #define BUFREADCOMMENT (0x400)
    323 #endif
    324 
    325 /*
    326   Locate the Central directory of a zipfile (at the end, just before
    327     the global comment)
    328 */
    329 local uLong unzlocal_SearchCentralDir OF((
    330     const zlib_filefunc_def* pzlib_filefunc_def,
    331     voidpf filestream));
    332 
    333 local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
    334     const zlib_filefunc_def* pzlib_filefunc_def;
    335     voidpf filestream;
    336 {
    337     unsigned char* buf;
    338     uLong uSizeFile;
    339     uLong uBackRead;
    340     uLong uMaxBack=0xffff; /* maximum size of global comment */
    341     uLong uPosFound=0;
    342 
    343     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
    344         return 0;
    345 
    346 
    347     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
    348 
    349     if (uMaxBack>uSizeFile)
    350         uMaxBack = uSizeFile;
    351 
    352     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    353     if (buf==NULL)
    354         return 0;
    355 
    356     uBackRead = 4;
    357     while (uBackRead<uMaxBack)
    358     {
    359         uLong uReadSize,uReadPos ;
    360         int i;
    361         if (uBackRead+BUFREADCOMMENT>uMaxBack)
    362             uBackRead = uMaxBack;
    363         else
    364             uBackRead+=BUFREADCOMMENT;
    365         uReadPos = uSizeFile-uBackRead ;
    366 
    367         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
    368                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
    369         if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
    370             break;
    371 
    372         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
    373             break;
    374 
    375         for (i=(int)uReadSize-3; (i--)>0;)
    376             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
    377                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
    378             {
    379                 uPosFound = uReadPos+i;
    380                 break;
    381             }
    382 
    383         if (uPosFound!=0)
    384             break;
    385     }
    386     TRYFREE(buf);
    387     return uPosFound;
    388 }
    389 
    390 /*
    391   Open a Zip file. path contain the full pathname (by example,
    392      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
    393      "zlib/zlib114.zip".
    394      If the zipfile cannot be opened (file doesn't exist or in not valid), the
    395        return value is NULL.
    396      Else, the return value is a unzFile Handle, usable with other function
    397        of this unzip package.
    398 */
    399 extern unzFile ZEXPORT unzOpen2 (path, pzlib_filefunc_def)
    400     const char *path;
    401     zlib_filefunc_def* pzlib_filefunc_def;
    402 {
    403     unz_s us;
    404     unz_s *s;
    405     uLong central_pos,uL;
    406 
    407     uLong number_disk;          /* number of the current dist, used for
    408                                    spaning ZIP, unsupported, always 0*/
    409     uLong number_disk_with_CD;  /* number the the disk with central dir, used
    410                                    for spaning ZIP, unsupported, always 0*/
    411     uLong number_entry_CD;      /* total number of entries in
    412                                    the central dir
    413                                    (same than number_entry on nospan) */
    414 
    415     int err=UNZ_OK;
    416 
    417     if (unz_copyright[0]!=' ')
    418         return NULL;
    419 
    420     if (pzlib_filefunc_def==NULL)
    421         fill_fopen_filefunc(&us.z_filefunc);
    422     else
    423         us.z_filefunc = *pzlib_filefunc_def;
    424 
    425     us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
    426                                                  path,
    427                                                  ZLIB_FILEFUNC_MODE_READ |
    428                                                  ZLIB_FILEFUNC_MODE_EXISTING);
    429     if (us.filestream==NULL)
    430         return NULL;
    431 
    432     central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
    433     if (central_pos==0)
    434         err=UNZ_ERRNO;
    435 
    436     if (ZSEEK(us.z_filefunc, us.filestream,
    437                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
    438         err=UNZ_ERRNO;
    439 
    440     /* the signature, already checked */
    441     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
    442         err=UNZ_ERRNO;
    443 
    444     /* number of this disk */
    445     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
    446         err=UNZ_ERRNO;
    447 
    448     /* number of the disk with the start of the central directory */
    449     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
    450         err=UNZ_ERRNO;
    451 
    452     /* total number of entries in the central dir on this disk */
    453     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
    454         err=UNZ_ERRNO;
    455 
    456     /* total number of entries in the central dir */
    457     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
    458         err=UNZ_ERRNO;
    459 
    460     if ((number_entry_CD!=us.gi.number_entry) ||
    461         (number_disk_with_CD!=0) ||
    462         (number_disk!=0))
    463         err=UNZ_BADZIPFILE;
    464 
    465     /* size of the central directory */
    466     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
    467         err=UNZ_ERRNO;
    468 
    469     /* offset of start of central directory with respect to the
    470           starting disk number */
    471     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
    472         err=UNZ_ERRNO;
    473 
    474     /* zipfile comment length */
    475     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
    476         err=UNZ_ERRNO;
    477 
    478     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
    479         (err==UNZ_OK))
    480         err=UNZ_BADZIPFILE;
    481 
    482     if (err!=UNZ_OK)
    483     {
    484         ZCLOSE(us.z_filefunc, us.filestream);
    485         return NULL;
    486     }
    487 
    488     us.byte_before_the_zipfile = central_pos -
    489                             (us.offset_central_dir+us.size_central_dir);
    490     us.central_pos = central_pos;
    491     us.pfile_in_zip_read = NULL;
    492     us.encrypted = 0;
    493 
    494 
    495     s=(unz_s*)ALLOC(sizeof(unz_s));
    496     *s=us;
    497     unzGoToFirstFile((unzFile)s);
    498     return (unzFile)s;
    499 }
    500 
    501 
    502 extern unzFile ZEXPORT unzOpen (path)
    503     const char *path;
    504 {
    505     return unzOpen2(path, NULL);
    506 }
    507 
    508 /*
    509   Close a ZipFile opened with unzipOpen.
    510   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
    511     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
    512   return UNZ_OK if there is no problem. */
    513 extern int ZEXPORT unzClose (file)
    514     unzFile file;
    515 {
    516     unz_s* s;
    517     if (file==NULL)
    518         return UNZ_PARAMERROR;
    519     s=(unz_s*)file;
    520 
    521     if (s->pfile_in_zip_read!=NULL)
    522         unzCloseCurrentFile(file);
    523 
    524     ZCLOSE(s->z_filefunc, s->filestream);
    525     TRYFREE(s);
    526     return UNZ_OK;
    527 }
    528 
    529 
    530 /*
    531   Write info about the ZipFile in the *pglobal_info structure.
    532   No preparation of the structure is needed
    533   return UNZ_OK if there is no problem. */
    534 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
    535     unzFile file;
    536     unz_global_info *pglobal_info;
    537 {
    538     unz_s* s;
    539     if (file==NULL)
    540         return UNZ_PARAMERROR;
    541     s=(unz_s*)file;
    542     *pglobal_info=s->gi;
    543     return UNZ_OK;
    544 }
    545 
    546 
    547 /*
    548    Translate date/time from Dos format to tm_unz (readable more easilty)
    549 */
    550 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
    551     uLong ulDosDate;
    552     tm_unz* ptm;
    553 {
    554     uLong uDate;
    555     uDate = (uLong)(ulDosDate>>16);
    556     ptm->tm_mday = (uInt)(uDate&0x1f) ;
    557     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
    558     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
    559 
    560     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
    561     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
    562     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
    563 }
    564 
    565 /*
    566   Get Info about the current file in the zipfile, with internal only info
    567 */
    568 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
    569                                                   unz_file_info *pfile_info,
    570                                                   unz_file_info_internal
    571                                                   *pfile_info_internal,
    572                                                   char *szFileName,
    573                                                   uLong fileNameBufferSize,
    574                                                   void *extraField,
    575                                                   uLong extraFieldBufferSize,
    576                                                   char *szComment,
    577                                                   uLong commentBufferSize));
    578 
    579 local int unzlocal_GetCurrentFileInfoInternal (file,
    580                                               pfile_info,
    581                                               pfile_info_internal,
    582                                               szFileName, fileNameBufferSize,
    583                                               extraField, extraFieldBufferSize,
    584                                               szComment,  commentBufferSize)
    585     unzFile file;
    586     unz_file_info *pfile_info;
    587     unz_file_info_internal *pfile_info_internal;
    588     char *szFileName;
    589     uLong fileNameBufferSize;
    590     void *extraField;
    591     uLong extraFieldBufferSize;
    592     char *szComment;
    593     uLong commentBufferSize;
    594 {
    595     unz_s* s;
    596     unz_file_info file_info;
    597     unz_file_info_internal file_info_internal;
    598     int err=UNZ_OK;
    599     uLong uMagic;
    600     long lSeek=0;
    601 
    602     if (file==NULL)
    603         return UNZ_PARAMERROR;
    604     s=(unz_s*)file;
    605     if (ZSEEK(s->z_filefunc, s->filestream,
    606               s->pos_in_central_dir+s->byte_before_the_zipfile,
    607               ZLIB_FILEFUNC_SEEK_SET)!=0)
    608         err=UNZ_ERRNO;
    609 
    610 
    611     /* we check the magic */
    612     if (err==UNZ_OK)
    613         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
    614             err=UNZ_ERRNO;
    615         else if (uMagic!=0x02014b50)
    616             err=UNZ_BADZIPFILE;
    617 
    618     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
    619         err=UNZ_ERRNO;
    620 
    621     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
    622         err=UNZ_ERRNO;
    623 
    624     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
    625         err=UNZ_ERRNO;
    626 
    627     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
    628         err=UNZ_ERRNO;
    629 
    630     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
    631         err=UNZ_ERRNO;
    632 
    633     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
    634 
    635     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
    636         err=UNZ_ERRNO;
    637 
    638     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
    639         err=UNZ_ERRNO;
    640 
    641     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
    642         err=UNZ_ERRNO;
    643 
    644     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
    645         err=UNZ_ERRNO;
    646 
    647     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
    648         err=UNZ_ERRNO;
    649 
    650     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
    651         err=UNZ_ERRNO;
    652 
    653     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
    654         err=UNZ_ERRNO;
    655 
    656     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
    657         err=UNZ_ERRNO;
    658 
    659     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
    660         err=UNZ_ERRNO;
    661 
    662     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
    663         err=UNZ_ERRNO;
    664 
    665     lSeek+=file_info.size_filename;
    666     if ((err==UNZ_OK) && (szFileName!=NULL))
    667     {
    668         uLong uSizeRead ;
    669         if (file_info.size_filename<fileNameBufferSize)
    670         {
    671             *(szFileName+file_info.size_filename)='\0';
    672             uSizeRead = file_info.size_filename;
    673         }
    674         else
    675             uSizeRead = fileNameBufferSize;
    676 
    677         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
    678             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
    679                 err=UNZ_ERRNO;
    680         lSeek -= uSizeRead;
    681     }
    682 
    683 
    684     if ((err==UNZ_OK) && (extraField!=NULL))
    685     {
    686         uLong uSizeRead ;
    687         if (file_info.size_file_extra<extraFieldBufferSize)
    688             uSizeRead = file_info.size_file_extra;
    689         else
    690             uSizeRead = extraFieldBufferSize;
    691 
    692         if (lSeek!=0)
    693             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
    694                 lSeek=0;
    695             else
    696                 err=UNZ_ERRNO;
    697         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
    698             if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
    699                 err=UNZ_ERRNO;
    700         lSeek += file_info.size_file_extra - uSizeRead;
    701     }
    702     else
    703         lSeek+=file_info.size_file_extra;
    704 
    705 
    706     if ((err==UNZ_OK) && (szComment!=NULL))
    707     {
    708         uLong uSizeRead ;
    709         if (file_info.size_file_comment<commentBufferSize)
    710         {
    711             *(szComment+file_info.size_file_comment)='\0';
    712             uSizeRead = file_info.size_file_comment;
    713         }
    714         else
    715             uSizeRead = commentBufferSize;
    716 
    717         if (lSeek!=0)
    718             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
    719                 lSeek=0;
    720             else
    721                 err=UNZ_ERRNO;
    722         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
    723             if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
    724                 err=UNZ_ERRNO;
    725         lSeek+=file_info.size_file_comment - uSizeRead;
    726     }
    727     else
    728         lSeek+=file_info.size_file_comment;
    729 
    730     if ((err==UNZ_OK) && (pfile_info!=NULL))
    731         *pfile_info=file_info;
    732 
    733     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
    734         *pfile_info_internal=file_info_internal;
    735 
    736     return err;
    737 }
    738 
    739 
    740 
    741 /*
    742   Write info about the ZipFile in the *pglobal_info structure.
    743   No preparation of the structure is needed
    744   return UNZ_OK if there is no problem.
    745 */
    746 extern int ZEXPORT unzGetCurrentFileInfo (file,
    747                                           pfile_info,
    748                                           szFileName, fileNameBufferSize,
    749                                           extraField, extraFieldBufferSize,
    750                                           szComment,  commentBufferSize)
    751     unzFile file;
    752     unz_file_info *pfile_info;
    753     char *szFileName;
    754     uLong fileNameBufferSize;
    755     void *extraField;
    756     uLong extraFieldBufferSize;
    757     char *szComment;
    758     uLong commentBufferSize;
    759 {
    760     return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
    761                                                 szFileName,fileNameBufferSize,
    762                                                 extraField,extraFieldBufferSize,
    763                                                 szComment,commentBufferSize);
    764 }
    765 
    766 /*
    767   Set the current file of the zipfile to the first file.
    768   return UNZ_OK if there is no problem
    769 */
    770 extern int ZEXPORT unzGoToFirstFile (file)
    771     unzFile file;
    772 {
    773     int err=UNZ_OK;
    774     unz_s* s;
    775     if (file==NULL)
    776         return UNZ_PARAMERROR;
    777     s=(unz_s*)file;
    778     s->pos_in_central_dir=s->offset_central_dir;
    779     s->num_file=0;
    780     err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
    781                                              &s->cur_file_info_internal,
    782                                              NULL,0,NULL,0,NULL,0);
    783     s->current_file_ok = (err == UNZ_OK);
    784     return err;
    785 }
    786 
    787 /*
    788   Set the current file of the zipfile to the next file.
    789   return UNZ_OK if there is no problem
    790   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
    791 */
    792 extern int ZEXPORT unzGoToNextFile (file)
    793     unzFile file;
    794 {
    795     unz_s* s;
    796     int err;
    797 
    798     if (file==NULL)
    799         return UNZ_PARAMERROR;
    800     s=(unz_s*)file;
    801     if (!s->current_file_ok)
    802         return UNZ_END_OF_LIST_OF_FILE;
    803     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
    804       if (s->num_file+1==s->gi.number_entry)
    805         return UNZ_END_OF_LIST_OF_FILE;
    806 
    807     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
    808             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
    809     s->num_file++;
    810     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
    811                                                &s->cur_file_info_internal,
    812                                                NULL,0,NULL,0,NULL,0);
    813     s->current_file_ok = (err == UNZ_OK);
    814     return err;
    815 }
    816 
    817 
    818 /*
    819   Try locate the file szFileName in the zipfile.
    820   For the iCaseSensitivity signification, see unzipStringFileNameCompare
    821 
    822   return value :
    823   UNZ_OK if the file is found. It becomes the current file.
    824   UNZ_END_OF_LIST_OF_FILE if the file is not found
    825 */
    826 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
    827     unzFile file;
    828     const char *szFileName;
    829     int iCaseSensitivity;
    830 {
    831     unz_s* s;
    832     int err;
    833 
    834     /* We remember the 'current' position in the file so that we can jump
    835      * back there if we fail.
    836      */
    837     unz_file_info cur_file_infoSaved;
    838     unz_file_info_internal cur_file_info_internalSaved;
    839     uLong num_fileSaved;
    840     uLong pos_in_central_dirSaved;
    841 
    842 
    843     if (file==NULL)
    844         return UNZ_PARAMERROR;
    845 
    846     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
    847         return UNZ_PARAMERROR;
    848 
    849     s=(unz_s*)file;
    850     if (!s->current_file_ok)
    851         return UNZ_END_OF_LIST_OF_FILE;
    852 
    853     /* Save the current state */
    854     num_fileSaved = s->num_file;
    855     pos_in_central_dirSaved = s->pos_in_central_dir;
    856     cur_file_infoSaved = s->cur_file_info;
    857     cur_file_info_internalSaved = s->cur_file_info_internal;
    858 
    859     err = unzGoToFirstFile(file);
    860 
    861     while (err == UNZ_OK)
    862     {
    863         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
    864         err = unzGetCurrentFileInfo(file,NULL,
    865                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
    866                                     NULL,0,NULL,0);
    867         if (err == UNZ_OK)
    868         {
    869             if (unzStringFileNameCompare(szCurrentFileName,
    870                                             szFileName,iCaseSensitivity)==0)
    871                 return UNZ_OK;
    872             err = unzGoToNextFile(file);
    873         }
    874     }
    875 
    876     /* We failed, so restore the state of the 'current file' to where we
    877      * were.
    878      */
    879     s->num_file = num_fileSaved ;
    880     s->pos_in_central_dir = pos_in_central_dirSaved ;
    881     s->cur_file_info = cur_file_infoSaved;
    882     s->cur_file_info_internal = cur_file_info_internalSaved;
    883     return err;
    884 }
    885 
    886 
    887 /*
    888 ///////////////////////////////////////////
    889 // Contributed by Ryan Haksi (mailto://cryogen (at) infoserve.net)
    890 // I need random access
    891 //
    892 // Further optimization could be realized by adding an ability
    893 // to cache the directory in memory. The goal being a single
    894 // comprehensive file read to put the file I need in a memory.
    895 */
    896 
    897 /*
    898 typedef struct unz_file_pos_s
    899 {
    900     uLong pos_in_zip_directory;   // offset in file
    901     uLong num_of_file;            // # of file
    902 } unz_file_pos;
    903 */
    904 
    905 extern int ZEXPORT unzGetFilePos(file, file_pos)
    906     unzFile file;
    907     unz_file_pos* file_pos;
    908 {
    909     unz_s* s;
    910 
    911     if (file==NULL || file_pos==NULL)
    912         return UNZ_PARAMERROR;
    913     s=(unz_s*)file;
    914     if (!s->current_file_ok)
    915         return UNZ_END_OF_LIST_OF_FILE;
    916 
    917     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
    918     file_pos->num_of_file           = s->num_file;
    919 
    920     return UNZ_OK;
    921 }
    922 
    923 extern int ZEXPORT unzGoToFilePos(file, file_pos)
    924     unzFile file;
    925     unz_file_pos* file_pos;
    926 {
    927     unz_s* s;
    928     int err;
    929 
    930     if (file==NULL || file_pos==NULL)
    931         return UNZ_PARAMERROR;
    932     s=(unz_s*)file;
    933 
    934     /* jump to the right spot */
    935     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
    936     s->num_file           = file_pos->num_of_file;
    937 
    938     /* set the current file */
    939     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
    940                                                &s->cur_file_info_internal,
    941                                                NULL,0,NULL,0,NULL,0);
    942     /* return results */
    943     s->current_file_ok = (err == UNZ_OK);
    944     return err;
    945 }
    946 
    947 /*
    948 // Unzip Helper Functions - should be here?
    949 ///////////////////////////////////////////
    950 */
    951 
    952 /*
    953   Read the local header of the current zipfile
    954   Check the coherency of the local header and info in the end of central
    955         directory about this file
    956   store in *piSizeVar the size of extra info in local header
    957         (filename and size of extra field data)
    958 */
    959 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
    960                                                     poffset_local_extrafield,
    961                                                     psize_local_extrafield)
    962     unz_s* s;
    963     uInt* piSizeVar;
    964     uLong *poffset_local_extrafield;
    965     uInt  *psize_local_extrafield;
    966 {
    967     uLong uMagic,uData,uFlags;
    968     uLong size_filename;
    969     uLong size_extra_field;
    970     int err=UNZ_OK;
    971 
    972     *piSizeVar = 0;
    973     *poffset_local_extrafield = 0;
    974     *psize_local_extrafield = 0;
    975 
    976     if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
    977                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
    978         return UNZ_ERRNO;
    979 
    980 
    981     if (err==UNZ_OK)
    982         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
    983             err=UNZ_ERRNO;
    984         else if (uMagic!=0x04034b50)
    985             err=UNZ_BADZIPFILE;
    986 
    987     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
    988         err=UNZ_ERRNO;
    989 /*
    990     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
    991         err=UNZ_BADZIPFILE;
    992 */
    993     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
    994         err=UNZ_ERRNO;
    995 
    996     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
    997         err=UNZ_ERRNO;
    998     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
    999         err=UNZ_BADZIPFILE;
   1000 
   1001     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
   1002                          (s->cur_file_info.compression_method!=Z_DEFLATED))
   1003         err=UNZ_BADZIPFILE;
   1004 
   1005     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
   1006         err=UNZ_ERRNO;
   1007 
   1008     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
   1009         err=UNZ_ERRNO;
   1010     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
   1011                               ((uFlags & 8)==0))
   1012         err=UNZ_BADZIPFILE;
   1013 
   1014     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
   1015         err=UNZ_ERRNO;
   1016     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
   1017                               ((uFlags & 8)==0))
   1018         err=UNZ_BADZIPFILE;
   1019 
   1020     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
   1021         err=UNZ_ERRNO;
   1022     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
   1023                               ((uFlags & 8)==0))
   1024         err=UNZ_BADZIPFILE;
   1025 
   1026 
   1027     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
   1028         err=UNZ_ERRNO;
   1029     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
   1030         err=UNZ_BADZIPFILE;
   1031 
   1032     *piSizeVar += (uInt)size_filename;
   1033 
   1034     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
   1035         err=UNZ_ERRNO;
   1036     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
   1037                                     SIZEZIPLOCALHEADER + size_filename;
   1038     *psize_local_extrafield = (uInt)size_extra_field;
   1039 
   1040     *piSizeVar += (uInt)size_extra_field;
   1041 
   1042     return err;
   1043 }
   1044 
   1045 /*
   1046   Open for reading data the current file in the zipfile.
   1047   If there is no error and the file is opened, the return value is UNZ_OK.
   1048 */
   1049 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
   1050     unzFile file;
   1051     int* method;
   1052     int* level;
   1053     int raw;
   1054     const char* password;
   1055 {
   1056     int err=UNZ_OK;
   1057     uInt iSizeVar;
   1058     unz_s* s;
   1059     file_in_zip_read_info_s* pfile_in_zip_read_info;
   1060     uLong offset_local_extrafield;  /* offset of the local extra field */
   1061     uInt  size_local_extrafield;    /* size of the local extra field */
   1062 #    ifndef NOUNCRYPT
   1063     char source[12];
   1064 #    else
   1065     if (password != NULL)
   1066         return UNZ_PARAMERROR;
   1067 #    endif
   1068 
   1069     if (file==NULL)
   1070         return UNZ_PARAMERROR;
   1071     s=(unz_s*)file;
   1072     if (!s->current_file_ok)
   1073         return UNZ_PARAMERROR;
   1074 
   1075     if (s->pfile_in_zip_read != NULL)
   1076         unzCloseCurrentFile(file);
   1077 
   1078     if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
   1079                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
   1080         return UNZ_BADZIPFILE;
   1081 
   1082     pfile_in_zip_read_info = (file_in_zip_read_info_s*)
   1083                                         ALLOC(sizeof(file_in_zip_read_info_s));
   1084     if (pfile_in_zip_read_info==NULL)
   1085         return UNZ_INTERNALERROR;
   1086 
   1087     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
   1088     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
   1089     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
   1090     pfile_in_zip_read_info->pos_local_extrafield=0;
   1091     pfile_in_zip_read_info->raw=raw;
   1092 
   1093     if (pfile_in_zip_read_info->read_buffer==NULL)
   1094     {
   1095         TRYFREE(pfile_in_zip_read_info);
   1096         return UNZ_INTERNALERROR;
   1097     }
   1098 
   1099     pfile_in_zip_read_info->stream_initialised=0;
   1100 
   1101     if (method!=NULL)
   1102         *method = (int)s->cur_file_info.compression_method;
   1103 
   1104     if (level!=NULL)
   1105     {
   1106         *level = 6;
   1107         switch (s->cur_file_info.flag & 0x06)
   1108         {
   1109           case 6 : *level = 1; break;
   1110           case 4 : *level = 2; break;
   1111           case 2 : *level = 9; break;
   1112         }
   1113     }
   1114 
   1115     if ((s->cur_file_info.compression_method!=0) &&
   1116         (s->cur_file_info.compression_method!=Z_DEFLATED))
   1117         err=UNZ_BADZIPFILE;
   1118 
   1119     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
   1120     pfile_in_zip_read_info->crc32=0;
   1121     pfile_in_zip_read_info->compression_method =
   1122             s->cur_file_info.compression_method;
   1123     pfile_in_zip_read_info->filestream=s->filestream;
   1124     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
   1125     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
   1126 
   1127     pfile_in_zip_read_info->stream.total_out = 0;
   1128 
   1129     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
   1130         (!raw))
   1131     {
   1132       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
   1133       pfile_in_zip_read_info->stream.zfree = (free_func)0;
   1134       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
   1135       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
   1136       pfile_in_zip_read_info->stream.avail_in = 0;
   1137 
   1138       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
   1139       if (err == Z_OK)
   1140         pfile_in_zip_read_info->stream_initialised=1;
   1141       else
   1142       {
   1143         TRYFREE(pfile_in_zip_read_info);
   1144         return err;
   1145       }
   1146         /* windowBits is passed < 0 to tell that there is no zlib header.
   1147          * Note that in this case inflate *requires* an extra "dummy" byte
   1148          * after the compressed stream in order to complete decompression and
   1149          * return Z_STREAM_END.
   1150          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
   1151          * size of both compressed and uncompressed data
   1152          */
   1153     }
   1154     pfile_in_zip_read_info->rest_read_compressed =
   1155             s->cur_file_info.compressed_size ;
   1156     pfile_in_zip_read_info->rest_read_uncompressed =
   1157             s->cur_file_info.uncompressed_size ;
   1158 
   1159 
   1160     pfile_in_zip_read_info->pos_in_zipfile =
   1161             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
   1162               iSizeVar;
   1163 
   1164     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
   1165 
   1166     s->pfile_in_zip_read = pfile_in_zip_read_info;
   1167 
   1168 #    ifndef NOUNCRYPT
   1169     if (password != NULL)
   1170     {
   1171         int i;
   1172         s->pcrc_32_tab = get_crc_table();
   1173         init_keys(password,s->keys,s->pcrc_32_tab);
   1174         if (ZSEEK(s->z_filefunc, s->filestream,
   1175                   s->pfile_in_zip_read->pos_in_zipfile +
   1176                      s->pfile_in_zip_read->byte_before_the_zipfile,
   1177                   SEEK_SET)!=0)
   1178             return UNZ_INTERNALERROR;
   1179         if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
   1180             return UNZ_INTERNALERROR;
   1181 
   1182         for (i = 0; i<12; i++)
   1183             zdecode(s->keys,s->pcrc_32_tab,source[i]);
   1184 
   1185         s->pfile_in_zip_read->pos_in_zipfile+=12;
   1186         s->encrypted=1;
   1187     }
   1188 #    endif
   1189 
   1190 
   1191     return UNZ_OK;
   1192 }
   1193 
   1194 extern int ZEXPORT unzOpenCurrentFile (file)
   1195     unzFile file;
   1196 {
   1197     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
   1198 }
   1199 
   1200 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
   1201     unzFile file;
   1202     const char* password;
   1203 {
   1204     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
   1205 }
   1206 
   1207 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
   1208     unzFile file;
   1209     int* method;
   1210     int* level;
   1211     int raw;
   1212 {
   1213     return unzOpenCurrentFile3(file, method, level, raw, NULL);
   1214 }
   1215 
   1216 /*
   1217   Read bytes from the current file.
   1218   buf contain buffer where data must be copied
   1219   len the size of buf.
   1220 
   1221   return the number of byte copied if somes bytes are copied
   1222   return 0 if the end of file was reached
   1223   return <0 with error code if there is an error
   1224     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
   1225 */
   1226 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
   1227     unzFile file;
   1228     voidp buf;
   1229     unsigned len;
   1230 {
   1231     int err=UNZ_OK;
   1232     uInt iRead = 0;
   1233     unz_s* s;
   1234     file_in_zip_read_info_s* pfile_in_zip_read_info;
   1235     if (file==NULL)
   1236         return UNZ_PARAMERROR;
   1237     s=(unz_s*)file;
   1238     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1239 
   1240     if (pfile_in_zip_read_info==NULL)
   1241         return UNZ_PARAMERROR;
   1242 
   1243 
   1244     if ((pfile_in_zip_read_info->read_buffer == NULL))
   1245         return UNZ_END_OF_LIST_OF_FILE;
   1246     if (len==0)
   1247         return 0;
   1248 
   1249     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
   1250 
   1251     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
   1252 
   1253     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
   1254         (!(pfile_in_zip_read_info->raw)))
   1255         pfile_in_zip_read_info->stream.avail_out =
   1256             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
   1257 
   1258     if ((len>pfile_in_zip_read_info->rest_read_compressed+
   1259            pfile_in_zip_read_info->stream.avail_in) &&
   1260          (pfile_in_zip_read_info->raw))
   1261         pfile_in_zip_read_info->stream.avail_out =
   1262             (uInt)pfile_in_zip_read_info->rest_read_compressed+
   1263             pfile_in_zip_read_info->stream.avail_in;
   1264 
   1265     while (pfile_in_zip_read_info->stream.avail_out>0)
   1266     {
   1267         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
   1268             (pfile_in_zip_read_info->rest_read_compressed>0))
   1269         {
   1270             uInt uReadThis = UNZ_BUFSIZE;
   1271             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
   1272                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
   1273             if (uReadThis == 0)
   1274                 return UNZ_EOF;
   1275             if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
   1276                       pfile_in_zip_read_info->filestream,
   1277                       pfile_in_zip_read_info->pos_in_zipfile +
   1278                          pfile_in_zip_read_info->byte_before_the_zipfile,
   1279                          ZLIB_FILEFUNC_SEEK_SET)!=0)
   1280                 return UNZ_ERRNO;
   1281             if (ZREAD(pfile_in_zip_read_info->z_filefunc,
   1282                       pfile_in_zip_read_info->filestream,
   1283                       pfile_in_zip_read_info->read_buffer,
   1284                       uReadThis)!=uReadThis)
   1285                 return UNZ_ERRNO;
   1286 
   1287 
   1288 #            ifndef NOUNCRYPT
   1289             if(s->encrypted)
   1290             {
   1291                 uInt i;
   1292                 for(i=0;i<uReadThis;i++)
   1293                   pfile_in_zip_read_info->read_buffer[i] =
   1294                       zdecode(s->keys,s->pcrc_32_tab,
   1295                               pfile_in_zip_read_info->read_buffer[i]);
   1296             }
   1297 #            endif
   1298 
   1299 
   1300             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
   1301 
   1302             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
   1303 
   1304             pfile_in_zip_read_info->stream.next_in =
   1305                 (Bytef*)pfile_in_zip_read_info->read_buffer;
   1306             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
   1307         }
   1308 
   1309         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
   1310         {
   1311             uInt uDoCopy,i ;
   1312 
   1313             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
   1314                 (pfile_in_zip_read_info->rest_read_compressed == 0))
   1315                 return (iRead==0) ? UNZ_EOF : iRead;
   1316 
   1317             if (pfile_in_zip_read_info->stream.avail_out <
   1318                             pfile_in_zip_read_info->stream.avail_in)
   1319                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
   1320             else
   1321                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
   1322 
   1323             for (i=0;i<uDoCopy;i++)
   1324                 *(pfile_in_zip_read_info->stream.next_out+i) =
   1325                         *(pfile_in_zip_read_info->stream.next_in+i);
   1326 
   1327             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
   1328                                 pfile_in_zip_read_info->stream.next_out,
   1329                                 uDoCopy);
   1330             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
   1331             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
   1332             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
   1333             pfile_in_zip_read_info->stream.next_out += uDoCopy;
   1334             pfile_in_zip_read_info->stream.next_in += uDoCopy;
   1335             pfile_in_zip_read_info->stream.total_out += uDoCopy;
   1336             iRead += uDoCopy;
   1337         }
   1338         else
   1339         {
   1340             uLong uTotalOutBefore,uTotalOutAfter;
   1341             const Bytef *bufBefore;
   1342             uLong uOutThis;
   1343             int flush=Z_SYNC_FLUSH;
   1344 
   1345             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
   1346             bufBefore = pfile_in_zip_read_info->stream.next_out;
   1347 
   1348             /*
   1349             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
   1350                      pfile_in_zip_read_info->stream.avail_out) &&
   1351                 (pfile_in_zip_read_info->rest_read_compressed == 0))
   1352                 flush = Z_FINISH;
   1353             */
   1354             err=inflate(&pfile_in_zip_read_info->stream,flush);
   1355 
   1356             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
   1357               err = Z_DATA_ERROR;
   1358 
   1359             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
   1360             uOutThis = uTotalOutAfter-uTotalOutBefore;
   1361 
   1362             pfile_in_zip_read_info->crc32 =
   1363                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
   1364                         (uInt)(uOutThis));
   1365 
   1366             pfile_in_zip_read_info->rest_read_uncompressed -=
   1367                 uOutThis;
   1368 
   1369             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
   1370 
   1371             if (err==Z_STREAM_END)
   1372                 return (iRead==0) ? UNZ_EOF : iRead;
   1373             if (err!=Z_OK)
   1374                 break;
   1375         }
   1376     }
   1377 
   1378     if (err==Z_OK)
   1379         return iRead;
   1380     return err;
   1381 }
   1382 
   1383 
   1384 /*
   1385   Give the current position in uncompressed data
   1386 */
   1387 extern z_off_t ZEXPORT unztell (file)
   1388     unzFile file;
   1389 {
   1390     unz_s* s;
   1391     file_in_zip_read_info_s* pfile_in_zip_read_info;
   1392     if (file==NULL)
   1393         return UNZ_PARAMERROR;
   1394     s=(unz_s*)file;
   1395     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1396 
   1397     if (pfile_in_zip_read_info==NULL)
   1398         return UNZ_PARAMERROR;
   1399 
   1400     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
   1401 }
   1402 
   1403 
   1404 /*
   1405   return 1 if the end of file was reached, 0 elsewhere
   1406 */
   1407 extern int ZEXPORT unzeof (file)
   1408     unzFile file;
   1409 {
   1410     unz_s* s;
   1411     file_in_zip_read_info_s* pfile_in_zip_read_info;
   1412     if (file==NULL)
   1413         return UNZ_PARAMERROR;
   1414     s=(unz_s*)file;
   1415     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1416 
   1417     if (pfile_in_zip_read_info==NULL)
   1418         return UNZ_PARAMERROR;
   1419 
   1420     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
   1421         return 1;
   1422     else
   1423         return 0;
   1424 }
   1425 
   1426 
   1427 
   1428 /*
   1429   Read extra field from the current file (opened by unzOpenCurrentFile)
   1430   This is the local-header version of the extra field (sometimes, there is
   1431     more info in the local-header version than in the central-header)
   1432 
   1433   if buf==NULL, it return the size of the local extra field that can be read
   1434 
   1435   if buf!=NULL, len is the size of the buffer, the extra header is copied in
   1436     buf.
   1437   the return value is the number of bytes copied in buf, or (if <0)
   1438     the error code
   1439 */
   1440 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
   1441     unzFile file;
   1442     voidp buf;
   1443     unsigned len;
   1444 {
   1445     unz_s* s;
   1446     file_in_zip_read_info_s* pfile_in_zip_read_info;
   1447     uInt read_now;
   1448     uLong size_to_read;
   1449 
   1450     if (file==NULL)
   1451         return UNZ_PARAMERROR;
   1452     s=(unz_s*)file;
   1453     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1454 
   1455     if (pfile_in_zip_read_info==NULL)
   1456         return UNZ_PARAMERROR;
   1457 
   1458     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
   1459                 pfile_in_zip_read_info->pos_local_extrafield);
   1460 
   1461     if (buf==NULL)
   1462         return (int)size_to_read;
   1463 
   1464     if (len>size_to_read)
   1465         read_now = (uInt)size_to_read;
   1466     else
   1467         read_now = (uInt)len ;
   1468 
   1469     if (read_now==0)
   1470         return 0;
   1471 
   1472     if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
   1473               pfile_in_zip_read_info->filestream,
   1474               pfile_in_zip_read_info->offset_local_extrafield +
   1475               pfile_in_zip_read_info->pos_local_extrafield,
   1476               ZLIB_FILEFUNC_SEEK_SET)!=0)
   1477         return UNZ_ERRNO;
   1478 
   1479     if (ZREAD(pfile_in_zip_read_info->z_filefunc,
   1480               pfile_in_zip_read_info->filestream,
   1481               buf,read_now)!=read_now)
   1482         return UNZ_ERRNO;
   1483 
   1484     return (int)read_now;
   1485 }
   1486 
   1487 /*
   1488   Close the file in zip opened with unzipOpenCurrentFile
   1489   Return UNZ_CRCERROR if all the file was read but the CRC is not good
   1490 */
   1491 extern int ZEXPORT unzCloseCurrentFile (file)
   1492     unzFile file;
   1493 {
   1494     int err=UNZ_OK;
   1495 
   1496     unz_s* s;
   1497     file_in_zip_read_info_s* pfile_in_zip_read_info;
   1498     if (file==NULL)
   1499         return UNZ_PARAMERROR;
   1500     s=(unz_s*)file;
   1501     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1502 
   1503     if (pfile_in_zip_read_info==NULL)
   1504         return UNZ_PARAMERROR;
   1505 
   1506 
   1507     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
   1508         (!pfile_in_zip_read_info->raw))
   1509     {
   1510         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
   1511             err=UNZ_CRCERROR;
   1512     }
   1513 
   1514 
   1515     TRYFREE(pfile_in_zip_read_info->read_buffer);
   1516     pfile_in_zip_read_info->read_buffer = NULL;
   1517     if (pfile_in_zip_read_info->stream_initialised)
   1518         inflateEnd(&pfile_in_zip_read_info->stream);
   1519 
   1520     pfile_in_zip_read_info->stream_initialised = 0;
   1521     TRYFREE(pfile_in_zip_read_info);
   1522 
   1523     s->pfile_in_zip_read=NULL;
   1524 
   1525     return err;
   1526 }
   1527 
   1528 
   1529 /*
   1530   Get the global comment string of the ZipFile, in the szComment buffer.
   1531   uSizeBuf is the size of the szComment buffer.
   1532   return the number of byte copied or an error code <0
   1533 */
   1534 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
   1535     unzFile file;
   1536     char *szComment;
   1537     uLong uSizeBuf;
   1538 {
   1539     int err=UNZ_OK;
   1540     unz_s* s;
   1541     uLong uReadThis ;
   1542     if (file==NULL)
   1543         return UNZ_PARAMERROR;
   1544     s=(unz_s*)file;
   1545 
   1546     uReadThis = uSizeBuf;
   1547     if (uReadThis>s->gi.size_comment)
   1548         uReadThis = s->gi.size_comment;
   1549 
   1550     if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
   1551         return UNZ_ERRNO;
   1552 
   1553     if (uReadThis>0)
   1554     {
   1555       *szComment='\0';
   1556       if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
   1557         return UNZ_ERRNO;
   1558     }
   1559 
   1560     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
   1561         *(szComment+s->gi.size_comment)='\0';
   1562     return (int)uReadThis;
   1563 }
   1564 
   1565 /* Additions by RX '2004 */
   1566 extern uLong ZEXPORT unzGetOffset (file)
   1567     unzFile file;
   1568 {
   1569     unz_s* s;
   1570 
   1571     if (file==NULL)
   1572           return UNZ_PARAMERROR;
   1573     s=(unz_s*)file;
   1574     if (!s->current_file_ok)
   1575       return 0;
   1576     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
   1577       if (s->num_file==s->gi.number_entry)
   1578          return 0;
   1579     return s->pos_in_central_dir;
   1580 }
   1581 
   1582 extern int ZEXPORT unzSetOffset (file, pos)
   1583         unzFile file;
   1584         uLong pos;
   1585 {
   1586     unz_s* s;
   1587     int err;
   1588 
   1589     if (file==NULL)
   1590         return UNZ_PARAMERROR;
   1591     s=(unz_s*)file;
   1592 
   1593     s->pos_in_central_dir = pos;
   1594     s->num_file = s->gi.number_entry;      /* hack */
   1595     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
   1596                                               &s->cur_file_info_internal,
   1597                                               NULL,0,NULL,0,NULL,0);
   1598     s->current_file_ok = (err == UNZ_OK);
   1599     return err;
   1600 }
   1601