unzip.cpp

Go to the documentation of this file.
00001 /* unzip.c -- IO for uncompress .zip files using zlib
00002    Version 1.01d, September 22th, 2004
00003 
00004    Copyright (C) 1998-2004 Gilles Vollant
00005    Small modifications (C) 2005 The Pentagram Team
00006    Converted to more modern C by the Pentagram team.
00007 
00008    Read unzip.h for more info
00009 */
00010 
00011 /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
00012 compatibility with older software. The following is from the original crypt.c. Code
00013 woven in by Terry Thorsen 1/2003.
00014 */
00015 /*
00016   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
00017 
00018   See the accompanying file LICENSE, version 2000-Apr-09 or later
00019   (the contents of which are also included in zip.h) for terms of use.
00020   If, for some reason, all these files are missing, the Info-ZIP license
00021   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
00022 */
00023 /*
00024   crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
00025 
00026   The encryption/decryption parts of this source code (as opposed to the
00027   non-echoing password parts) were originally written in Europe.  The
00028   whole source package can be freely distributed, including from the USA.
00029   (Prior to January 2000, re-export from the US was a violation of US law.)
00030  */
00031 
00032 /*
00033   This encryption code is a direct transcription of the algorithm from
00034   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
00035   file (appnote.txt) is distributed with the PKZIP program (even in the
00036   version without encryption capabilities).
00037  */
00038 
00039 #include "pent_include.h"
00040 #define NOUNCRYPT
00041 
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <string.h>
00045 #include "zlib.h"
00046 #include "unzip.h"
00047 
00048 #ifdef STDC
00049 #  include <stddef.h>
00050 #  include <string.h>
00051 #  include <stdlib.h>
00052 #endif
00053 #ifdef NO_ERRNO_H
00054     extern int errno;
00055 #else
00056 #   include <errno.h>
00057 #endif
00058 
00059 
00060 
00061 #ifndef local
00062 #  define local static
00063 #endif
00064 /* compile with -Dlocal if your debugger can't find static symbols */
00065 
00066 
00067 #ifndef CASESENSITIVITYDEFAULT_NO
00068 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
00069 #    define CASESENSITIVITYDEFAULT_NO
00070 #  endif
00071 #endif
00072 
00073 
00074 #ifndef UNZ_BUFSIZE
00075 #define UNZ_BUFSIZE (16384)
00076 #endif
00077 
00078 #ifndef UNZ_MAXFILENAMEINZIP
00079 #define UNZ_MAXFILENAMEINZIP (256)
00080 #endif
00081 
00082 #ifndef ALLOC
00083 # define ALLOC(size) (malloc(size))
00084 #endif
00085 #ifndef TRYFREE
00086 # define TRYFREE(p) {if (p) free(p);}
00087 #endif
00088 
00089 #define SIZECENTRALDIRITEM (0x2e)
00090 #define SIZEZIPLOCALHEADER (0x1e)
00091 
00092 namespace PentZip {
00093 
00094 
00095 const char unz_copyright[] =
00096    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
00097 
00098 /* unz_file_info_interntal contain internal info about a file in zipfile*/
00099 typedef struct unz_file_info_internal_s
00100 {
00101     uLong offset_curfile;/* relative offset of local header 4 bytes */
00102 } unz_file_info_internal;
00103 
00104 
00105 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
00106     when reading and decompress it */
00107 typedef struct
00108 {
00109     char  *read_buffer;         /* internal buffer for compressed data */
00110     z_stream stream;            /* zLib stream structure for inflate */
00111 
00112     uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
00113     uLong stream_initialised;   /* flag set if stream structure is initialised*/
00114 
00115     uLong offset_local_extrafield;/* offset of the local extra field */
00116     uInt  size_local_extrafield;/* size of the local extra field */
00117     uLong pos_local_extrafield;   /* position in the local extra field in read*/
00118 
00119     uLong crc32;                /* crc32 of all data uncompressed */
00120     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
00121     uLong rest_read_compressed; /* number of byte to be decompressed */
00122     uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
00123     zlib_filefunc_def z_filefunc;
00124     voidpf filestream;        /* io structore of the zipfile */
00125     uLong compression_method;   /* compression method (0==store) */
00126     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
00127     int   raw;
00128 } file_in_zip_read_info_s;
00129 
00130 
00131 /* unz_s contain internal information about the zipfile
00132 */
00133 typedef struct
00134 {
00135     zlib_filefunc_def z_filefunc;
00136     voidpf filestream;        /* io structore of the zipfile */
00137     unz_global_info gi;       /* public global information */
00138     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
00139     uLong num_file;             /* number of the current file in the zipfile*/
00140     uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
00141     uLong current_file_ok;      /* flag about the usability of the current file*/
00142     uLong central_pos;          /* position of the beginning of the central dir*/
00143 
00144     uLong size_central_dir;     /* size of the central directory  */
00145     uLong offset_central_dir;   /* offset of start of central directory with
00146                                    respect to the starting disk number */
00147 
00148     unz_file_info cur_file_info; /* public info about the current file in zip*/
00149     unz_file_info_internal cur_file_info_internal; /* private info about it*/
00150     file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
00151                                         file if we are decompressing it */
00152     int encrypted;
00153 #    ifndef NOUNCRYPT
00154     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
00155     const unsigned long* pcrc_32_tab;
00156 #    endif
00157 } unz_s;
00158 
00159 
00160 #ifndef NOUNCRYPT
00161 #include "crypt.h"
00162 #endif
00163 
00164 /* ===========================================================================
00165      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
00166    for end of file.
00167    IN assertion: the stream s has been sucessfully opened for reading.
00168 */
00169 
00170 
00171 local int unzlocal_getByte OF((
00172     const zlib_filefunc_def* pzlib_filefunc_def,
00173     voidpf filestream,
00174     int *pi));
00175 
00176 local int unzlocal_getByte(const zlib_filefunc_def* pzlib_filefunc_def,
00177                                                    voidpf filestream, int *pi)
00178 {
00179     unsigned char c;
00180     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
00181     if (err==1)
00182     {
00183         *pi = (int)c;
00184         return UNZ_OK;
00185     }
00186     else
00187     {
00188         if (ZERROR(*pzlib_filefunc_def,filestream))
00189             return UNZ_ERRNO;
00190         else
00191             return UNZ_EOF;
00192     }
00193 }
00194 
00195 
00196 /* ===========================================================================
00197    Reads a long in LSB order from the given gz_stream. Sets
00198 */
00199 local int unzlocal_getShort OF((
00200     const zlib_filefunc_def* pzlib_filefunc_def,
00201     voidpf filestream,
00202     uLong *pX));
00203 
00204 local int unzlocal_getShort (const zlib_filefunc_def* pzlib_filefunc_def,
00205                                                          voidpf filestream, uLong *pX)
00206 {
00207     uLong x ;
00208     int i;
00209     int err;
00210 
00211     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
00212     x = (uLong)i;
00213 
00214     if (err==UNZ_OK)
00215         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
00216     x += ((uLong)i)<<8;
00217 
00218     if (err==UNZ_OK)
00219         *pX = x;
00220     else
00221         *pX = 0;
00222     return err;
00223 }
00224 
00225 local int unzlocal_getLong OF((
00226     const zlib_filefunc_def* pzlib_filefunc_def,
00227     voidpf filestream,
00228     uLong *pX));
00229 
00230 local int unzlocal_getLong (const zlib_filefunc_def* pzlib_filefunc_def,
00231                                                         voidpf filestream, uLong *pX)
00232 {
00233     uLong x ;
00234     int i;
00235     int err;
00236 
00237     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
00238     x = (uLong)i;
00239 
00240     if (err==UNZ_OK)
00241         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
00242     x += ((uLong)i)<<8;
00243 
00244     if (err==UNZ_OK)
00245         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
00246     x += ((uLong)i)<<16;
00247 
00248     if (err==UNZ_OK)
00249         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
00250     x += ((uLong)i)<<24;
00251 
00252     if (err==UNZ_OK)
00253         *pX = x;
00254     else
00255         *pX = 0;
00256     return err;
00257 }
00258 
00259 
00260 /* My own strcmpi / strcasecmp */
00261 local int strcmpcasenosensitive_internal (const char* fileName1,
00262                                                                                   const char* fileName2)
00263 {
00264     for (;;)
00265     {
00266         char c1=*(fileName1++);
00267         char c2=*(fileName2++);
00268         if ((c1>='a') && (c1<='z'))
00269             c1 -= 0x20;
00270         if ((c2>='a') && (c2<='z'))
00271             c2 -= 0x20;
00272         if (c1=='\0')
00273             return ((c2=='\0') ? 0 : -1);
00274         if (c2=='\0')
00275             return 1;
00276         if (c1<c2)
00277             return -1;
00278         if (c1>c2)
00279             return 1;
00280     }
00281 }
00282 
00283 
00284 #ifdef  CASESENSITIVITYDEFAULT_NO
00285 #define CASESENSITIVITYDEFAULTVALUE 2
00286 #else
00287 #define CASESENSITIVITYDEFAULTVALUE 1
00288 #endif
00289 
00290 #ifndef STRCMPCASENOSENTIVEFUNCTION
00291 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
00292 #endif
00293 
00294 /*
00295    Compare two filename (fileName1,fileName2).
00296    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
00297    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
00298                                                                 or strcasecmp)
00299    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
00300         (like 1 on Unix, 2 on Windows)
00301 
00302 */
00303 extern int ZEXPORT unzStringFileNameCompare (const char* fileName1,
00304                                                                                          const char* fileName2,
00305                                                                                          int iCaseSensitivity)
00306 {
00307     if (iCaseSensitivity==0)
00308         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
00309 
00310     if (iCaseSensitivity==1)
00311         return strcmp(fileName1,fileName2);
00312 
00313     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
00314 }
00315 
00316 #ifndef BUFREADCOMMENT
00317 #define BUFREADCOMMENT (0x400)
00318 #endif
00319 
00320 /*
00321   Locate the Central directory of a zipfile (at the end, just before
00322     the global comment)
00323 */
00324 local uLong unzlocal_SearchCentralDir OF((
00325     const zlib_filefunc_def* pzlib_filefunc_def,
00326     voidpf filestream));
00327 
00328 local uLong unzlocal_SearchCentralDir(const zlib_filefunc_def* pzlib_filefunc_def, voidpf filestream)
00329 {
00330     unsigned char* buf;
00331     uLong uSizeFile;
00332     uLong uBackRead;
00333     uLong uMaxBack=0xffff; /* maximum size of global comment */
00334     uLong uPosFound=0;
00335 
00336     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
00337         return 0;
00338 
00339 
00340     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
00341 
00342     if (uMaxBack>uSizeFile)
00343         uMaxBack = uSizeFile;
00344 
00345     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
00346     if (buf==NULL)
00347         return 0;
00348 
00349     uBackRead = 4;
00350     while (uBackRead<uMaxBack)
00351     {
00352         uLong uReadSize,uReadPos ;
00353         int i;
00354         if (uBackRead+BUFREADCOMMENT>uMaxBack)
00355             uBackRead = uMaxBack;
00356         else
00357             uBackRead+=BUFREADCOMMENT;
00358         uReadPos = uSizeFile-uBackRead ;
00359 
00360         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
00361                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
00362         if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
00363             break;
00364 
00365         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
00366             break;
00367 
00368         for (i=(int)uReadSize-3; (i--)>0;)
00369             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
00370                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
00371             {
00372                 uPosFound = uReadPos+i;
00373                 break;
00374             }
00375 
00376         if (uPosFound!=0)
00377             break;
00378     }
00379     TRYFREE(buf);
00380     return uPosFound;
00381 }
00382 
00383 /*
00384   Open a Zip file. path contain the full pathname (by example,
00385      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
00386      "zlib/zlib114.zip".
00387      If the zipfile cannot be opened (file doesn't exist or in not valid), the
00388        return value is NULL.
00389      Else, the return value is a unzFile Handle, usable with other function
00390        of this unzip package.
00391 */
00392 extern unzFile ZEXPORT unzOpen2 (const char *path,
00393                                                                  zlib_filefunc_def* pzlib_filefunc_def)
00394 {
00395     unz_s us;
00396     unz_s *s;
00397     uLong central_pos,uL;
00398 
00399     uLong number_disk;          /* number of the current dist, used for
00400                                    spaning ZIP, unsupported, always 0*/
00401     uLong number_disk_with_CD;  /* number the the disk with central dir, used
00402                                    for spaning ZIP, unsupported, always 0*/
00403     uLong number_entry_CD;      /* total number of entries in
00404                                    the central dir
00405                                    (same than number_entry on nospan) */
00406 
00407     int err=UNZ_OK;
00408 
00409     if (unz_copyright[0]!=' ')
00410         return NULL;
00411 
00412     if (pzlib_filefunc_def==NULL)
00413         fill_fopen_filefunc(&us.z_filefunc);
00414     else
00415         us.z_filefunc = *pzlib_filefunc_def;
00416 
00417     us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
00418                                                  path,
00419                                                  ZLIB_FILEFUNC_MODE_READ |
00420                                                  ZLIB_FILEFUNC_MODE_EXISTING);
00421     if (us.filestream==NULL)
00422         return NULL;
00423 
00424     central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
00425     if (central_pos==0)
00426         err=UNZ_ERRNO;
00427 
00428     if (ZSEEK(us.z_filefunc, us.filestream,
00429                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
00430         err=UNZ_ERRNO;
00431 
00432     /* the signature, already checked */
00433     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
00434         err=UNZ_ERRNO;
00435 
00436     /* number of this disk */
00437     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
00438         err=UNZ_ERRNO;
00439 
00440     /* number of the disk with the start of the central directory */
00441     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
00442         err=UNZ_ERRNO;
00443 
00444     /* total number of entries in the central dir on this disk */
00445     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
00446         err=UNZ_ERRNO;
00447 
00448     /* total number of entries in the central dir */
00449     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
00450         err=UNZ_ERRNO;
00451 
00452     if ((number_entry_CD!=us.gi.number_entry) ||
00453         (number_disk_with_CD!=0) ||
00454         (number_disk!=0))
00455         err=UNZ_BADZIPFILE;
00456 
00457     /* size of the central directory */
00458     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
00459         err=UNZ_ERRNO;
00460 
00461     /* offset of start of central directory with respect to the
00462           starting disk number */
00463     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
00464         err=UNZ_ERRNO;
00465 
00466     /* zipfile comment length */
00467     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
00468         err=UNZ_ERRNO;
00469 
00470     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
00471         (err==UNZ_OK))
00472         err=UNZ_BADZIPFILE;
00473 
00474     if (err!=UNZ_OK)
00475     {
00476         ZCLOSE(us.z_filefunc, us.filestream);
00477         return NULL;
00478     }
00479 
00480     us.byte_before_the_zipfile = central_pos -
00481                             (us.offset_central_dir+us.size_central_dir);
00482     us.central_pos = central_pos;
00483     us.pfile_in_zip_read = NULL;
00484     us.encrypted = 0;
00485 
00486 
00487     s=(unz_s*)ALLOC(sizeof(unz_s));
00488     *s=us;
00489     unzGoToFirstFile((unzFile)s);
00490     return (unzFile)s;
00491 }
00492 
00493 
00494 extern unzFile ZEXPORT unzOpen (const char *path)
00495 {
00496     return unzOpen2(path, NULL);
00497 }
00498 
00499 /*
00500   Close a ZipFile opened with unzipOpen.
00501   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
00502     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
00503   return UNZ_OK if there is no problem. */
00504 extern int ZEXPORT unzClose (unzFile file)
00505 {
00506     unz_s* s;
00507     if (file==NULL)
00508         return UNZ_PARAMERROR;
00509     s=(unz_s*)file;
00510 
00511     if (s->pfile_in_zip_read!=NULL)
00512         unzCloseCurrentFile(file);
00513 
00514     ZCLOSE(s->z_filefunc, s->filestream);
00515     TRYFREE(s);
00516     return UNZ_OK;
00517 }
00518 
00519 
00520 /*
00521   Write info about the ZipFile in the *pglobal_info structure.
00522   No preparation of the structure is needed
00523   return UNZ_OK if there is no problem. */
00524 extern int ZEXPORT unzGetGlobalInfo (unzFile file,
00525                                                                          unz_global_info *pglobal_info)
00526 {
00527     unz_s* s;
00528     if (file==NULL)
00529         return UNZ_PARAMERROR;
00530     s=(unz_s*)file;
00531     *pglobal_info=s->gi;
00532     return UNZ_OK;
00533 }
00534 
00535 
00536 /*
00537    Translate date/time from Dos format to tm_unz (readable more easilty)
00538 */
00539 local void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm)
00540 {
00541     uLong uDate;
00542     uDate = (uLong)(ulDosDate>>16);
00543     ptm->tm_mday = (uInt)(uDate&0x1f) ;
00544     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
00545     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
00546 
00547     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
00548     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
00549     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
00550 }
00551 
00552 /*
00553   Get Info about the current file in the zipfile, with internal only info
00554 */
00555 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
00556                                                   unz_file_info *pfile_info,
00557                                                   unz_file_info_internal
00558                                                   *pfile_info_internal,
00559                                                   char *szFileName,
00560                                                   uLong fileNameBufferSize,
00561                                                   void *extraField,
00562                                                   uLong extraFieldBufferSize,
00563                                                   char *szComment,
00564                                                   uLong commentBufferSize));
00565 
00566 local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
00567                                                                                            unz_file_info *pfile_info,
00568                                                                                            unz_file_info_internal *pfile_info_internal,
00569                                                                                            char *szFileName,
00570                                                                                            uLong fileNameBufferSize,
00571                                                                                            void *extraField,
00572                                                                                            uLong extraFieldBufferSize,
00573                                                                                            char *szComment,
00574                                                                                            uLong commentBufferSize)
00575 {
00576     unz_s* s;
00577     unz_file_info file_info;
00578     unz_file_info_internal file_info_internal;
00579     int err=UNZ_OK;
00580     uLong uMagic;
00581     long lSeek=0;
00582 
00583     if (file==NULL)
00584         return UNZ_PARAMERROR;
00585     s=(unz_s*)file;
00586     if (ZSEEK(s->z_filefunc, s->filestream,
00587               s->pos_in_central_dir+s->byte_before_the_zipfile,
00588               ZLIB_FILEFUNC_SEEK_SET)!=0)
00589         err=UNZ_ERRNO;
00590 
00591 
00592     /* we check the magic */
00593     if (err==UNZ_OK)
00594         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
00595             err=UNZ_ERRNO;
00596         else if (uMagic!=0x02014b50)
00597             err=UNZ_BADZIPFILE;
00598 
00599     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
00600         err=UNZ_ERRNO;
00601 
00602     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
00603         err=UNZ_ERRNO;
00604 
00605     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
00606         err=UNZ_ERRNO;
00607 
00608     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
00609         err=UNZ_ERRNO;
00610 
00611     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
00612         err=UNZ_ERRNO;
00613 
00614     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
00615 
00616     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
00617         err=UNZ_ERRNO;
00618 
00619     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
00620         err=UNZ_ERRNO;
00621 
00622     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
00623         err=UNZ_ERRNO;
00624 
00625     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
00626         err=UNZ_ERRNO;
00627 
00628     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
00629         err=UNZ_ERRNO;
00630 
00631     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
00632         err=UNZ_ERRNO;
00633 
00634     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
00635         err=UNZ_ERRNO;
00636 
00637     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
00638         err=UNZ_ERRNO;
00639 
00640     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
00641         err=UNZ_ERRNO;
00642 
00643     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
00644         err=UNZ_ERRNO;
00645 
00646     lSeek+=file_info.size_filename;
00647     if ((err==UNZ_OK) && (szFileName!=NULL))
00648     {
00649         uLong uSizeRead ;
00650         if (file_info.size_filename<fileNameBufferSize)
00651         {
00652             *(szFileName+file_info.size_filename)='\0';
00653             uSizeRead = file_info.size_filename;
00654         }
00655         else
00656             uSizeRead = fileNameBufferSize;
00657 
00658         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
00659             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
00660                 err=UNZ_ERRNO;
00661         lSeek -= uSizeRead;
00662     }
00663 
00664 
00665     if ((err==UNZ_OK) && (extraField!=NULL))
00666     {
00667         uLong uSizeRead ;
00668         if (file_info.size_file_extra<extraFieldBufferSize)
00669             uSizeRead = file_info.size_file_extra;
00670         else
00671             uSizeRead = extraFieldBufferSize;
00672 
00673         if (lSeek!=0)
00674             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
00675                 lSeek=0;
00676             else
00677                 err=UNZ_ERRNO;
00678         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
00679             if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
00680                 err=UNZ_ERRNO;
00681         lSeek += file_info.size_file_extra - uSizeRead;
00682     }
00683     else
00684         lSeek+=file_info.size_file_extra;
00685 
00686 
00687     if ((err==UNZ_OK) && (szComment!=NULL))
00688     {
00689         uLong uSizeRead ;
00690         if (file_info.size_file_comment<commentBufferSize)
00691         {
00692             *(szComment+file_info.size_file_comment)='\0';
00693             uSizeRead = file_info.size_file_comment;
00694         }
00695         else
00696             uSizeRead = commentBufferSize;
00697 
00698         if (lSeek!=0)
00699             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
00700                 lSeek=0;
00701             else
00702                 err=UNZ_ERRNO;
00703         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
00704             if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
00705                 err=UNZ_ERRNO;
00706         lSeek+=file_info.size_file_comment - uSizeRead;
00707     }
00708     else
00709         lSeek+=file_info.size_file_comment;
00710 
00711     if ((err==UNZ_OK) && (pfile_info!=NULL))
00712         *pfile_info=file_info;
00713 
00714     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
00715         *pfile_info_internal=file_info_internal;
00716 
00717     return err;
00718 }
00719 
00720 
00721 
00722 /*
00723   Write info about the ZipFile in the *pglobal_info structure.
00724   No preparation of the structure is needed
00725   return UNZ_OK if there is no problem.
00726 */
00727 extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
00728                                                                                   unz_file_info *pfile_info,
00729                                                                                   char *szFileName,
00730                                                                                   uLong fileNameBufferSize,
00731                                                                                   void *extraField,
00732                                                                                   uLong extraFieldBufferSize,
00733                                                                                   char *szComment,
00734                                                                                   uLong commentBufferSize)
00735 {
00736     return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
00737                                                 szFileName,fileNameBufferSize,
00738                                                 extraField,extraFieldBufferSize,
00739                                                 szComment,commentBufferSize);
00740 }
00741 
00742 /*
00743   Set the current file of the zipfile to the first file.
00744   return UNZ_OK if there is no problem
00745 */
00746 extern int ZEXPORT unzGoToFirstFile (unzFile file)
00747 {
00748     int err=UNZ_OK;
00749     unz_s* s;
00750     if (file==NULL)
00751         return UNZ_PARAMERROR;
00752     s=(unz_s*)file;
00753     s->pos_in_central_dir=s->offset_central_dir;
00754     s->num_file=0;
00755     err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
00756                                              &s->cur_file_info_internal,
00757                                              NULL,0,NULL,0,NULL,0);
00758     s->current_file_ok = (err == UNZ_OK);
00759     return err;
00760 }
00761 
00762 /*
00763   Set the current file of the zipfile to the next file.
00764   return UNZ_OK if there is no problem
00765   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
00766 */
00767 extern int ZEXPORT unzGoToNextFile (unzFile file)
00768 {
00769     unz_s* s;
00770     int err;
00771 
00772     if (file==NULL)
00773         return UNZ_PARAMERROR;
00774     s=(unz_s*)file;
00775     if (!s->current_file_ok)
00776         return UNZ_END_OF_LIST_OF_FILE;
00777     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
00778       if (s->num_file+1==s->gi.number_entry)
00779         return UNZ_END_OF_LIST_OF_FILE;
00780 
00781     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
00782             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
00783     s->num_file++;
00784     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
00785                                                &s->cur_file_info_internal,
00786                                                NULL,0,NULL,0,NULL,0);
00787     s->current_file_ok = (err == UNZ_OK);
00788     return err;
00789 }
00790 
00791 
00792 /*
00793   Try locate the file szFileName in the zipfile.
00794   For the iCaseSensitivity signification, see unzipStringFileNameCompare
00795 
00796   return value :
00797   UNZ_OK if the file is found. It becomes the current file.
00798   UNZ_END_OF_LIST_OF_FILE if the file is not found
00799 */
00800 extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName,
00801                                                                   int iCaseSensitivity)
00802 {
00803     unz_s* s;
00804     int err;
00805 
00806     /* We remember the 'current' position in the file so that we can jump
00807      * back there if we fail.
00808      */
00809     unz_file_info cur_file_infoSaved;
00810     unz_file_info_internal cur_file_info_internalSaved;
00811     uLong num_fileSaved;
00812     uLong pos_in_central_dirSaved;
00813 
00814 
00815     if (file==NULL)
00816         return UNZ_PARAMERROR;
00817 
00818     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
00819         return UNZ_PARAMERROR;
00820 
00821     s=(unz_s*)file;
00822     if (!s->current_file_ok)
00823         return UNZ_END_OF_LIST_OF_FILE;
00824 
00825     /* Save the current state */
00826     num_fileSaved = s->num_file;
00827     pos_in_central_dirSaved = s->pos_in_central_dir;
00828     cur_file_infoSaved = s->cur_file_info;
00829     cur_file_info_internalSaved = s->cur_file_info_internal;
00830 
00831     err = unzGoToFirstFile(file);
00832 
00833     while (err == UNZ_OK)
00834     {
00835         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
00836         err = unzGetCurrentFileInfo(file,NULL,
00837                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
00838                                     NULL,0,NULL,0);
00839         if (err == UNZ_OK)
00840         {
00841             if (unzStringFileNameCompare(szCurrentFileName,
00842                                             szFileName,iCaseSensitivity)==0)
00843                 return UNZ_OK;
00844             err = unzGoToNextFile(file);
00845         }
00846     }
00847 
00848     /* We failed, so restore the state of the 'current file' to where we
00849      * were.
00850      */
00851     s->num_file = num_fileSaved ;
00852     s->pos_in_central_dir = pos_in_central_dirSaved ;
00853     s->cur_file_info = cur_file_infoSaved;
00854     s->cur_file_info_internal = cur_file_info_internalSaved;
00855     return err;
00856 }
00857 
00858 
00859 /*
00861 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
00862 // I need random access
00863 //
00864 // Further optimization could be realized by adding an ability
00865 // to cache the directory in memory. The goal being a single
00866 // comprehensive file read to put the file I need in a memory.
00867 */
00868 
00869 /*
00870 typedef struct unz_file_pos_s
00871 {
00872     uLong pos_in_zip_directory;   // offset in file
00873     uLong num_of_file;            // # of file
00874 } unz_file_pos;
00875 */
00876 
00877 extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos* file_pos)
00878 {
00879     unz_s* s;
00880 
00881     if (file==NULL || file_pos==NULL)
00882         return UNZ_PARAMERROR;
00883     s=(unz_s*)file;
00884     if (!s->current_file_ok)
00885         return UNZ_END_OF_LIST_OF_FILE;
00886 
00887     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
00888     file_pos->num_of_file           = s->num_file;
00889 
00890     return UNZ_OK;
00891 }
00892 
00893 extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos* file_pos)
00894 {
00895     unz_s* s;
00896     int err;
00897 
00898     if (file==NULL || file_pos==NULL)
00899         return UNZ_PARAMERROR;
00900     s=(unz_s*)file;
00901 
00902     /* jump to the right spot */
00903     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
00904     s->num_file           = file_pos->num_of_file;
00905 
00906     /* set the current file */
00907     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
00908                                                &s->cur_file_info_internal,
00909                                                NULL,0,NULL,0,NULL,0);
00910     /* return results */
00911     s->current_file_ok = (err == UNZ_OK);
00912     return err;
00913 }
00914 
00915 /*
00916 // Unzip Helper Functions - should be here?
00918 */
00919 
00920 /*
00921   Read the local header of the current zipfile
00922   Check the coherency of the local header and info in the end of central
00923         directory about this file
00924   store in *piSizeVar the size of extra info in local header
00925         (filename and size of extra field data)
00926 */
00927 local int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s,
00928                                                                                                         uInt* piSizeVar,
00929                                                                                                         uLong *poffset_local_extrafield,
00930                                                                                                         uInt  *psize_local_extrafield)
00931 {
00932     uLong uMagic,uData,uFlags;
00933     uLong size_filename;
00934     uLong size_extra_field;
00935     int err=UNZ_OK;
00936 
00937     *piSizeVar = 0;
00938     *poffset_local_extrafield = 0;
00939     *psize_local_extrafield = 0;
00940 
00941     if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
00942                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
00943         return UNZ_ERRNO;
00944 
00945 
00946     if (err==UNZ_OK)
00947         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
00948             err=UNZ_ERRNO;
00949         else if (uMagic!=0x04034b50)
00950             err=UNZ_BADZIPFILE;
00951 
00952     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
00953         err=UNZ_ERRNO;
00954 /*
00955     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
00956         err=UNZ_BADZIPFILE;
00957 */
00958     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
00959         err=UNZ_ERRNO;
00960 
00961     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
00962         err=UNZ_ERRNO;
00963     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
00964         err=UNZ_BADZIPFILE;
00965 
00966     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
00967                          (s->cur_file_info.compression_method!=Z_DEFLATED))
00968         err=UNZ_BADZIPFILE;
00969 
00970     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
00971         err=UNZ_ERRNO;
00972 
00973     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
00974         err=UNZ_ERRNO;
00975     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
00976                               ((uFlags & 8)==0))
00977         err=UNZ_BADZIPFILE;
00978 
00979     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
00980         err=UNZ_ERRNO;
00981     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
00982                               ((uFlags & 8)==0))
00983         err=UNZ_BADZIPFILE;
00984 
00985     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
00986         err=UNZ_ERRNO;
00987     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
00988                               ((uFlags & 8)==0))
00989         err=UNZ_BADZIPFILE;
00990 
00991 
00992     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
00993         err=UNZ_ERRNO;
00994     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
00995         err=UNZ_BADZIPFILE;
00996 
00997     *piSizeVar += (uInt)size_filename;
00998 
00999     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
01000         err=UNZ_ERRNO;
01001     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
01002                                     SIZEZIPLOCALHEADER + size_filename;
01003     *psize_local_extrafield = (uInt)size_extra_field;
01004 
01005     *piSizeVar += (uInt)size_extra_field;
01006 
01007     return err;
01008 }
01009 
01010 /*
01011   Open for reading data the current file in the zipfile.
01012   If there is no error and the file is opened, the return value is UNZ_OK.
01013 */
01014 extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, int* level,
01015                                                                                 int raw, const char* password)
01016 {
01017     int err=UNZ_OK;
01018     uInt iSizeVar;
01019     unz_s* s;
01020     file_in_zip_read_info_s* pfile_in_zip_read_info;
01021     uLong offset_local_extrafield;  /* offset of the local extra field */
01022     uInt  size_local_extrafield;    /* size of the local extra field */
01023 #    ifndef NOUNCRYPT
01024     char source[12];
01025 #    else
01026     if (password != NULL)
01027         return UNZ_PARAMERROR;
01028 #    endif
01029 
01030     if (file==NULL)
01031         return UNZ_PARAMERROR;
01032     s=(unz_s*)file;
01033     if (!s->current_file_ok)
01034         return UNZ_PARAMERROR;
01035 
01036     if (s->pfile_in_zip_read != NULL)
01037         unzCloseCurrentFile(file);
01038 
01039     if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
01040                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
01041         return UNZ_BADZIPFILE;
01042 
01043     pfile_in_zip_read_info = (file_in_zip_read_info_s*)
01044                                         ALLOC(sizeof(file_in_zip_read_info_s));
01045     if (pfile_in_zip_read_info==NULL)
01046         return UNZ_INTERNALERROR;
01047 
01048     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
01049     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
01050     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
01051     pfile_in_zip_read_info->pos_local_extrafield=0;
01052     pfile_in_zip_read_info->raw=raw;
01053 
01054     if (pfile_in_zip_read_info->read_buffer==NULL)
01055     {
01056         TRYFREE(pfile_in_zip_read_info);
01057         return UNZ_INTERNALERROR;
01058     }
01059 
01060     pfile_in_zip_read_info->stream_initialised=0;
01061 
01062     if (method!=NULL)
01063         *method = (int)s->cur_file_info.compression_method;
01064 
01065     if (level!=NULL)
01066     {
01067         *level = 6;
01068         switch (s->cur_file_info.flag & 0x06)
01069         {
01070           case 6 : *level = 1; break;
01071           case 4 : *level = 2; break;
01072           case 2 : *level = 9; break;
01073         }
01074     }
01075 
01076     if ((s->cur_file_info.compression_method!=0) &&
01077         (s->cur_file_info.compression_method!=Z_DEFLATED))
01078         err=UNZ_BADZIPFILE;
01079 
01080     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
01081     pfile_in_zip_read_info->crc32=0;
01082     pfile_in_zip_read_info->compression_method =
01083             s->cur_file_info.compression_method;
01084     pfile_in_zip_read_info->filestream=s->filestream;
01085     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
01086     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
01087 
01088     pfile_in_zip_read_info->stream.total_out = 0;
01089 
01090     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
01091         (!raw))
01092     {
01093       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
01094       pfile_in_zip_read_info->stream.zfree = (free_func)0;
01095       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
01096       pfile_in_zip_read_info->stream.next_in = (Bytef*)0;
01097       pfile_in_zip_read_info->stream.avail_in = 0;
01098 
01099       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
01100       if (err == Z_OK)
01101         pfile_in_zip_read_info->stream_initialised=1;
01102       else
01103         return err;
01104         /* windowBits is passed < 0 to tell that there is no zlib header.
01105          * Note that in this case inflate *requires* an extra "dummy" byte
01106          * after the compressed stream in order to complete decompression and
01107          * return Z_STREAM_END.
01108          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
01109          * size of both compressed and uncompressed data
01110          */
01111     }
01112     pfile_in_zip_read_info->rest_read_compressed =
01113             s->cur_file_info.compressed_size ;
01114     pfile_in_zip_read_info->rest_read_uncompressed =
01115             s->cur_file_info.uncompressed_size ;
01116 
01117 
01118     pfile_in_zip_read_info->pos_in_zipfile =
01119             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
01120               iSizeVar;
01121 
01122     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
01123 
01124     s->pfile_in_zip_read = pfile_in_zip_read_info;
01125 
01126 #    ifndef NOUNCRYPT
01127     if (password != NULL)
01128     {
01129         int i;
01130         s->pcrc_32_tab = get_crc_table();
01131         init_keys(password,s->keys,s->pcrc_32_tab);
01132         if (ZSEEK(s->z_filefunc, s->filestream,
01133                   s->pfile_in_zip_read->pos_in_zipfile +
01134                      s->pfile_in_zip_read->byte_before_the_zipfile,
01135                   SEEK_SET)!=0)
01136             return UNZ_INTERNALERROR;
01137         if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
01138             return UNZ_INTERNALERROR;
01139 
01140         for (i = 0; i<12; i++)
01141             zdecode(s->keys,s->pcrc_32_tab,source[i]);
01142 
01143         s->pfile_in_zip_read->pos_in_zipfile+=12;
01144         s->encrypted=1;
01145     }
01146 #    endif
01147 
01148 
01149     return UNZ_OK;
01150 }
01151 
01152 extern int ZEXPORT unzOpenCurrentFile (unzFile file)
01153 {
01154     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
01155 }
01156 
01157 extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file,
01158                                                                                            const char* password)
01159 {
01160     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
01161 }
01162 
01163 extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method,
01164                                                                                 int* level, int raw)
01165 {
01166     return unzOpenCurrentFile3(file, method, level, raw, NULL);
01167 }
01168 
01169 /*
01170   Read bytes from the current file.
01171   buf contain buffer where data must be copied
01172   len the size of buf.
01173 
01174   return the number of byte copied if somes bytes are copied
01175   return 0 if the end of file was reached
01176   return <0 with error code if there is an error
01177     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
01178 */
01179 extern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)
01180 {
01181     int err=UNZ_OK;
01182     uInt iRead = 0;
01183     unz_s* s;
01184     file_in_zip_read_info_s* pfile_in_zip_read_info;
01185     if (file==NULL)
01186         return UNZ_PARAMERROR;
01187     s=(unz_s*)file;
01188     pfile_in_zip_read_info=s->pfile_in_zip_read;
01189 
01190     if (pfile_in_zip_read_info==NULL)
01191         return UNZ_PARAMERROR;
01192 
01193 
01194     if ((pfile_in_zip_read_info->read_buffer == NULL))
01195         return UNZ_END_OF_LIST_OF_FILE;
01196     if (len==0)
01197         return 0;
01198 
01199     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
01200 
01201     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
01202 
01203     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
01204         (!(pfile_in_zip_read_info->raw)))
01205         pfile_in_zip_read_info->stream.avail_out =
01206             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
01207 
01208     if ((len>pfile_in_zip_read_info->rest_read_compressed+
01209            pfile_in_zip_read_info->stream.avail_in) &&
01210          (pfile_in_zip_read_info->raw))
01211         pfile_in_zip_read_info->stream.avail_out =
01212             (uInt)pfile_in_zip_read_info->rest_read_compressed+
01213             pfile_in_zip_read_info->stream.avail_in;
01214 
01215     while (pfile_in_zip_read_info->stream.avail_out>0)
01216     {
01217         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
01218             (pfile_in_zip_read_info->rest_read_compressed>0))
01219         {
01220             uInt uReadThis = UNZ_BUFSIZE;
01221             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
01222                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
01223             if (uReadThis == 0)
01224                 return UNZ_EOF;
01225             if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
01226                       pfile_in_zip_read_info->filestream,
01227                       pfile_in_zip_read_info->pos_in_zipfile +
01228                          pfile_in_zip_read_info->byte_before_the_zipfile,
01229                          ZLIB_FILEFUNC_SEEK_SET)!=0)
01230                 return UNZ_ERRNO;
01231             if (ZREAD(pfile_in_zip_read_info->z_filefunc,
01232                       pfile_in_zip_read_info->filestream,
01233                       pfile_in_zip_read_info->read_buffer,
01234                       uReadThis)!=uReadThis)
01235                 return UNZ_ERRNO;
01236 
01237 
01238 #            ifndef NOUNCRYPT
01239             if(s->encrypted)
01240             {
01241                 uInt i;
01242                 for(i=0;i<uReadThis;i++)
01243                   pfile_in_zip_read_info->read_buffer[i] =
01244                       zdecode(s->keys,s->pcrc_32_tab,
01245                               pfile_in_zip_read_info->read_buffer[i]);
01246             }
01247 #            endif
01248 
01249 
01250             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
01251 
01252             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
01253 
01254             pfile_in_zip_read_info->stream.next_in =
01255                 (Bytef*)pfile_in_zip_read_info->read_buffer;
01256             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
01257         }
01258 
01259         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
01260         {
01261             uInt uDoCopy,i ;
01262 
01263             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
01264                 (pfile_in_zip_read_info->rest_read_compressed == 0))
01265                 return (iRead==0) ? UNZ_EOF : iRead;
01266 
01267             if (pfile_in_zip_read_info->stream.avail_out <
01268                             pfile_in_zip_read_info->stream.avail_in)
01269                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
01270             else
01271                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
01272 
01273             for (i=0;i<uDoCopy;i++)
01274                 *(pfile_in_zip_read_info->stream.next_out+i) =
01275                         *(pfile_in_zip_read_info->stream.next_in+i);
01276 
01277             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
01278                                 pfile_in_zip_read_info->stream.next_out,
01279                                 uDoCopy);
01280             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
01281             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
01282             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
01283             pfile_in_zip_read_info->stream.next_out += uDoCopy;
01284             pfile_in_zip_read_info->stream.next_in += uDoCopy;
01285             pfile_in_zip_read_info->stream.total_out += uDoCopy;
01286             iRead += uDoCopy;
01287         }
01288         else
01289         {
01290             uLong uTotalOutBefore,uTotalOutAfter;
01291             const Bytef *bufBefore;
01292             uLong uOutThis;
01293             int flush=Z_SYNC_FLUSH;
01294 
01295             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
01296             bufBefore = pfile_in_zip_read_info->stream.next_out;
01297 
01298             /*
01299             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
01300                      pfile_in_zip_read_info->stream.avail_out) &&
01301                 (pfile_in_zip_read_info->rest_read_compressed == 0))
01302                 flush = Z_FINISH;
01303             */
01304             err=inflate(&pfile_in_zip_read_info->stream,flush);
01305 
01306             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
01307               err = Z_DATA_ERROR;
01308 
01309             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
01310             uOutThis = uTotalOutAfter-uTotalOutBefore;
01311 
01312             pfile_in_zip_read_info->crc32 =
01313                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
01314                         (uInt)(uOutThis));
01315 
01316             pfile_in_zip_read_info->rest_read_uncompressed -=
01317                 uOutThis;
01318 
01319             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
01320 
01321             if (err==Z_STREAM_END)
01322                 return (iRead==0) ? UNZ_EOF : iRead;
01323             if (err!=Z_OK)
01324                 break;
01325         }
01326     }
01327 
01328     if (err==Z_OK)
01329         return iRead;
01330     return err;
01331 }
01332 
01333 
01334 /*
01335   Give the current position in uncompressed data
01336 */
01337 extern z_off_t ZEXPORT unztell (unzFile file)
01338 {
01339     unz_s* s;
01340     file_in_zip_read_info_s* pfile_in_zip_read_info;
01341     if (file==NULL)
01342         return UNZ_PARAMERROR;
01343     s=(unz_s*)file;
01344     pfile_in_zip_read_info=s->pfile_in_zip_read;
01345 
01346     if (pfile_in_zip_read_info==NULL)
01347         return UNZ_PARAMERROR;
01348 
01349     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
01350 }
01351 
01352 
01353 /*
01354   return 1 if the end of file was reached, 0 elsewhere
01355 */
01356 extern int ZEXPORT unzeof (unzFile file)
01357 {
01358     unz_s* s;
01359     file_in_zip_read_info_s* pfile_in_zip_read_info;
01360     if (file==NULL)
01361         return UNZ_PARAMERROR;
01362     s=(unz_s*)file;
01363     pfile_in_zip_read_info=s->pfile_in_zip_read;
01364 
01365     if (pfile_in_zip_read_info==NULL)
01366         return UNZ_PARAMERROR;
01367 
01368     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
01369         return 1;
01370     else
01371         return 0;
01372 }
01373 
01374 
01375 
01376 /*
01377   Read extra field from the current file (opened by unzOpenCurrentFile)
01378   This is the local-header version of the extra field (sometimes, there is
01379     more info in the local-header version than in the central-header)
01380 
01381   if buf==NULL, it return the size of the local extra field that can be read
01382 
01383   if buf!=NULL, len is the size of the buffer, the extra header is copied in
01384     buf.
01385   the return value is the number of bytes copied in buf, or (if <0)
01386     the error code
01387 */
01388 extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf,
01389                                                                                   unsigned len)
01390 {
01391     unz_s* s;
01392     file_in_zip_read_info_s* pfile_in_zip_read_info;
01393     uInt read_now;
01394     uLong size_to_read;
01395 
01396     if (file==NULL)
01397         return UNZ_PARAMERROR;
01398     s=(unz_s*)file;
01399     pfile_in_zip_read_info=s->pfile_in_zip_read;
01400 
01401     if (pfile_in_zip_read_info==NULL)
01402         return UNZ_PARAMERROR;
01403 
01404     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
01405                 pfile_in_zip_read_info->pos_local_extrafield);
01406 
01407     if (buf==NULL)
01408         return (int)size_to_read;
01409 
01410     if (len>size_to_read)
01411         read_now = (uInt)size_to_read;
01412     else
01413         read_now = (uInt)len ;
01414 
01415     if (read_now==0)
01416         return 0;
01417 
01418     if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
01419               pfile_in_zip_read_info->filestream,
01420               pfile_in_zip_read_info->offset_local_extrafield +
01421               pfile_in_zip_read_info->pos_local_extrafield,
01422               ZLIB_FILEFUNC_SEEK_SET)!=0)
01423         return UNZ_ERRNO;
01424 
01425     if (ZREAD(pfile_in_zip_read_info->z_filefunc,
01426               pfile_in_zip_read_info->filestream,
01427               buf,read_now)!=read_now)
01428         return UNZ_ERRNO;
01429 
01430     return (int)read_now;
01431 }
01432 
01433 /*
01434   Close the file in zip opened with unzipOpenCurrentFile
01435   Return UNZ_CRCERROR if all the file was read but the CRC is not good
01436 */
01437 extern int ZEXPORT unzCloseCurrentFile (unzFile file)
01438 {
01439     int err=UNZ_OK;
01440 
01441     unz_s* s;
01442     file_in_zip_read_info_s* pfile_in_zip_read_info;
01443     if (file==NULL)
01444         return UNZ_PARAMERROR;
01445     s=(unz_s*)file;
01446     pfile_in_zip_read_info=s->pfile_in_zip_read;
01447 
01448     if (pfile_in_zip_read_info==NULL)
01449         return UNZ_PARAMERROR;
01450 
01451 
01452     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
01453         (!pfile_in_zip_read_info->raw))
01454     {
01455         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
01456             err=UNZ_CRCERROR;
01457     }
01458 
01459 
01460     TRYFREE(pfile_in_zip_read_info->read_buffer);
01461     pfile_in_zip_read_info->read_buffer = NULL;
01462     if (pfile_in_zip_read_info->stream_initialised)
01463         inflateEnd(&pfile_in_zip_read_info->stream);
01464 
01465     pfile_in_zip_read_info->stream_initialised = 0;
01466     TRYFREE(pfile_in_zip_read_info);
01467 
01468     s->pfile_in_zip_read=NULL;
01469 
01470     return err;
01471 }
01472 
01473 
01474 /*
01475   Get the global comment string of the ZipFile, in the szComment buffer.
01476   uSizeBuf is the size of the szComment buffer.
01477   return the number of byte copied or an error code <0
01478 */
01479 extern int ZEXPORT unzGetGlobalComment (unzFile file, char *szComment,
01480                                                                                 uLong uSizeBuf)
01481 {
01482     // int err=UNZ_OK;
01483     unz_s* s;
01484     uLong uReadThis ;
01485     if (file==NULL)
01486         return UNZ_PARAMERROR;
01487     s=(unz_s*)file;
01488 
01489     uReadThis = uSizeBuf;
01490     if (uReadThis>s->gi.size_comment)
01491         uReadThis = s->gi.size_comment;
01492 
01493     if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
01494         return UNZ_ERRNO;
01495 
01496     if (uReadThis>0)
01497     {
01498       *szComment='\0';
01499       if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
01500         return UNZ_ERRNO;
01501     }
01502 
01503     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
01504         *(szComment+s->gi.size_comment)='\0';
01505     return (int)uReadThis;
01506 }
01507 
01508 /* Additions by RX '2004 */
01509 extern uLong ZEXPORT unzGetOffset (unzFile file)
01510 {
01511     unz_s* s;
01512 
01513     if (file==NULL)
01514           return (uLong)UNZ_PARAMERROR;
01515     s=(unz_s*)file;
01516     if (!s->current_file_ok)
01517       return 0;
01518     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
01519       if (s->num_file==s->gi.number_entry)
01520          return 0;
01521     return s->pos_in_central_dir;
01522 }
01523 
01524 extern int ZEXPORT unzSetOffset (unzFile file, uLong pos)
01525 {
01526     unz_s* s;
01527     int err;
01528 
01529     if (file==NULL)
01530         return UNZ_PARAMERROR;
01531     s=(unz_s*)file;
01532 
01533     s->pos_in_central_dir = pos;
01534     s->num_file = s->gi.number_entry;      /* hack */
01535     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
01536                                               &s->cur_file_info_internal,
01537                                               NULL,0,NULL,0,NULL,0);
01538     s->current_file_ok = (err == UNZ_OK);
01539     return err;
01540 }
01541 
01542 
01543 }

Generated on Fri Jul 27 22:27:51 2007 for pentagram by  doxygen 1.4.7