unzip.c

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

Generated on Fri Apr 14 22:57:28 2006 for minix by  doxygen 1.4.6