Back to index

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