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

Generated by  doxygen 1.6.2