unzip.c

Go to the documentation of this file.
00001 /* unzip.c -- IO on .zip files using zlib 
00002    Version 0.15 beta, Mar 19th, 1998,
00003 
00004    Modified by Ryan Nunn. Nov 9th 2001
00005 
00006    Read unzip.h for more info
00007 */
00008 
00009 
00010 
00011 /* Added by Ryan Nunn */
00012 #ifdef HAVE_CONFIG_H
00013 #  include <config.h>
00014 #endif
00015 
00016 #ifdef HAVE_ZIP_SUPPORT
00017 
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #include "zlib.h"
00022 #include "unzip.h"
00023 
00024 #ifdef STDC
00025 #  include <stddef.h>
00026 #  include <string.h>
00027 #  include <stdlib.h>
00028 #endif
00029 #ifdef NO_ERRNO_H
00030     extern int errno;
00031 #else
00032 #   include <errno.h>
00033 #endif
00034 
00035 
00036 #ifndef local
00037 #  define local static
00038 #endif
00039 /* compile with -Dlocal if your debugger can't find static symbols */
00040 
00041 
00042 
00043 #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
00044                       !defined(CASESENSITIVITYDEFAULT_NO)
00045 #define CASESENSITIVITYDEFAULT_NO
00046 #endif
00047 
00048 
00049 #ifndef UNZ_BUFSIZE
00050 #define UNZ_BUFSIZE (16384)
00051 #endif
00052 
00053 #ifndef UNZ_MAXFILENAMEINZIP
00054 #define UNZ_MAXFILENAMEINZIP (256)
00055 #endif
00056 
00057 #ifndef ALLOC
00058 # define ALLOC(size) (malloc(size))
00059 #endif
00060 #ifndef TRYFREE
00061 # define TRYFREE(p) {if (p) free(p);}
00062 #endif
00063 
00064 #define SIZECENTRALDIRITEM (0x2e)
00065 #define SIZEZIPLOCALHEADER (0x1e)
00066 
00067 
00068 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
00069 
00070 #ifndef SEEK_CUR
00071 #define SEEK_CUR    1
00072 #endif
00073 
00074 #ifndef SEEK_END
00075 #define SEEK_END    2
00076 #endif
00077 
00078 #ifndef SEEK_SET
00079 #define SEEK_SET    0
00080 #endif
00081 
00082 const char unz_copyright[] =
00083    " unzip 0.15 Copyright 1998 Gilles Vollant ";
00084 
00085 /* unz_file_info_interntal contain internal info about a file in zipfile*/
00086 typedef struct unz_file_info_internal_s
00087 {
00088     uLong offset_curfile;/* relative offset of local header 4 bytes */
00089 } unz_file_info_internal;
00090 
00091 
00092 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
00093     when reading and decompress it */
00094 typedef struct
00095 {
00096   char  *read_buffer;         /* internal buffer for compressed data */
00097   z_stream stream;            /* zLib stream structure for inflate */
00098 
00099   uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
00100   uLong stream_initialised;   /* flag set if stream structure is initialised*/
00101 
00102   uLong offset_local_extrafield;/* offset of the local extra field */
00103   uInt  size_local_extrafield;/* size of the local extra field */
00104   uLong pos_local_extrafield;   /* position in the local extra field in read*/
00105 
00106   uLong crc32;                /* crc32 of all data uncompressed */
00107   uLong crc32_wait;           /* crc32 we must obtain after decompress all */
00108   uLong rest_read_compressed; /* number of byte to be decompressed */
00109   uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
00110   FILE* file;                 /* io structore of the zipfile */
00111   uLong compression_method;   /* compression method (0==store) */
00112   uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
00113 } file_in_zip_read_info_s;
00114 
00115 
00116 /* unz_s contain internal information about the zipfile
00117 */
00118 typedef struct
00119 {
00120   FILE* file;                 /* io structore of the zipfile */
00121   unz_global_info gi;       /* public global information */
00122   uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
00123   uLong num_file;             /* number of the current file in the zipfile*/
00124   uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
00125   uLong current_file_ok;      /* flag about the usability of the current file*/
00126   uLong central_pos;          /* position of the beginning of the central dir*/
00127 
00128   uLong size_central_dir;     /* size of the central directory  */
00129   uLong offset_central_dir;   /* offset of start of central directory with
00130                    respect to the starting disk number */
00131 
00132   unz_file_info cur_file_info; /* public info about the current file in zip*/
00133   unz_file_info_internal cur_file_info_internal; /* private info about it*/
00134     file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
00135                                       file if we are decompressing it */
00136 } unz_s;
00137 
00138 
00139 /* ===========================================================================
00140      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
00141    for end of file.
00142    IN assertion: the stream s has been sucessfully opened for reading.
00143 */
00144 
00145 
00146 local int unzlocal_getByte(FILE *fin, int *pi)
00147 {
00148     unsigned char c;
00149   int err = fread(&c, 1, 1, fin);
00150     if (err==1)
00151     {
00152         *pi = (int)c;
00153         return UNZ_OK;
00154     }
00155     else
00156     {
00157         if (ferror(fin)) 
00158             return UNZ_ERRNO;
00159         else
00160             return UNZ_EOF;
00161     }
00162 }
00163 
00164 
00165 /* ===========================================================================
00166    Reads a long in LSB order from the given gz_stream. Sets 
00167 */
00168 local int unzlocal_getShort (FILE*fin, uLong *pX)
00169 {
00170     uLong x ;
00171     int i;
00172     int err;
00173 
00174     err = unzlocal_getByte(fin,&i);
00175     x = (uLong)i;
00176     
00177     if (err==UNZ_OK)
00178         err = unzlocal_getByte(fin,&i);
00179     x += ((uLong)i)<<8;
00180    
00181     if (err==UNZ_OK)
00182         *pX = x;
00183     else
00184         *pX = 0;
00185     return err;
00186 }
00187 
00188 local int unzlocal_getLong (FILE*fin, uLong *pX)
00189 {
00190     uLong x ;
00191     int i;
00192     int err;
00193 
00194     err = unzlocal_getByte(fin,&i);
00195     x = (uLong)i;
00196     
00197     if (err==UNZ_OK)
00198         err = unzlocal_getByte(fin,&i);
00199     x += ((uLong)i)<<8;
00200 
00201     if (err==UNZ_OK)
00202         err = unzlocal_getByte(fin,&i);
00203     x += ((uLong)i)<<16;
00204 
00205     if (err==UNZ_OK)
00206         err = unzlocal_getByte(fin,&i);
00207     x += ((uLong)i)<<24;
00208    
00209     if (err==UNZ_OK)
00210         *pX = x;
00211     else
00212         *pX = 0;
00213     return err;
00214 }
00215 
00216 
00217 /* My own strcmpi / strcasecmp */
00218 local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
00219 {
00220   for (;;)
00221   {
00222     char c1=*(fileName1++);
00223     char c2=*(fileName2++);
00224     if ((c1>='a') && (c1<='z'))
00225       c1 -= 0x20;
00226     if ((c2>='a') && (c2<='z'))
00227       c2 -= 0x20;
00228     if (c1=='\0')
00229       return ((c2=='\0') ? 0 : -1);
00230     if (c2=='\0')
00231       return 1;
00232     if (c1<c2)
00233       return -1;
00234     if (c1>c2)
00235       return 1;
00236   }
00237 }
00238 
00239 
00240 #ifdef  CASESENSITIVITYDEFAULT_NO
00241 #define CASESENSITIVITYDEFAULTVALUE 2
00242 #else
00243 #define CASESENSITIVITYDEFAULTVALUE 1
00244 #endif
00245 
00246 #ifndef STRCMPCASENOSENTIVEFUNCTION
00247 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
00248 #endif
00249 
00250 /* 
00251    Compare two filename (fileName1,fileName2).
00252    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
00253    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
00254                                                                 or strcasecmp)
00255    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
00256         (like 1 on Unix, 2 on Windows)
00257 
00258 */
00259 extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity)
00260 {
00261   if (iCaseSensitivity==0)
00262     iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
00263 
00264   if (iCaseSensitivity==1)
00265     return strcmp(fileName1,fileName2);
00266 
00267   return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
00268 } 
00269 
00270 #define BUFREADCOMMENT (0x400)
00271 
00272 /*
00273   Locate the Central directory of a zipfile (at the end, just before
00274     the global comment)
00275 */
00276 local uLong unzlocal_SearchCentralDir(FILE *fin)
00277 {
00278   unsigned char* buf;
00279   uLong uSizeFile;
00280   uLong uBackRead;
00281   uLong uMaxBack=0xffff; /* maximum size of global comment */
00282   uLong uPosFound=0;
00283   
00284   if (fseek(fin,0,SEEK_END) != 0)
00285     return 0;
00286 
00287 
00288   uSizeFile = ftell( fin );
00289   
00290   if (uMaxBack>uSizeFile)
00291     uMaxBack = uSizeFile;
00292 
00293   buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
00294   if (buf==NULL)
00295     return 0;
00296 
00297   uBackRead = 4;
00298   while (uBackRead<uMaxBack)
00299   {
00300     uLong uReadSize,uReadPos ;
00301     int i;
00302     if (uBackRead+BUFREADCOMMENT>uMaxBack) 
00303       uBackRead = uMaxBack;
00304     else
00305       uBackRead+=BUFREADCOMMENT;
00306     uReadPos = uSizeFile-uBackRead ;
00307     
00308     uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? 
00309                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
00310     if (fseek(fin,uReadPos,SEEK_SET)!=0)
00311       break;
00312 
00313     if (fread(buf,(uInt)uReadSize,1,fin)!=1)
00314       break;
00315 
00316                 for (i=(int)uReadSize-3; (i--)>0;)
00317       if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && 
00318         ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
00319       {
00320         uPosFound = uReadPos+i;
00321         break;
00322       }
00323 
00324     if (uPosFound!=0)
00325       break;
00326   }
00327   TRYFREE(buf);
00328   return uPosFound;
00329 }
00330 
00331 /*
00332   Open a Zip file. path contain the full pathname (by example,
00333      on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
00334    "zlib/zlib109.zip".
00335    If the zipfile cannot be opened (file don't exist or in not valid), the
00336      return value is NULL.
00337      Else, the return value is a unzFile Handle, usable with other function
00338      of this unzip package.
00339 */
00340 extern unzFile ZEXPORT unzOpen (const char *path)
00341 {
00342   unz_s us;
00343   unz_s *s;
00344   uLong central_pos,uL;
00345   FILE * fin ;
00346 
00347   uLong number_disk;          /* number of the current dist, used for 
00348                    spaning ZIP, unsupported, always 0*/
00349   uLong number_disk_with_CD;  /* number the the disk with central dir, used
00350                    for spaning ZIP, unsupported, always 0*/
00351   uLong number_entry_CD;      /* total number of entries in
00352                                  the central dir 
00353                                  (same than number_entry on nospan) */
00354 
00355   int err=UNZ_OK;
00356 
00357     if (unz_copyright[0]!=' ')
00358         return NULL;
00359 
00360     fin=fopen(path,"rb");
00361   if (fin==NULL)
00362     return NULL;
00363 
00364   central_pos = unzlocal_SearchCentralDir(fin);
00365   if (central_pos==0)
00366     err=UNZ_ERRNO;
00367 
00368   if (fseek(fin,central_pos,SEEK_SET)!=0)
00369     err=UNZ_ERRNO;
00370 
00371   /* the signature, already checked */
00372   if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
00373     err=UNZ_ERRNO;
00374 
00375   /* number of this disk */
00376   if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
00377     err=UNZ_ERRNO;
00378 
00379   /* number of the disk with the start of the central directory */
00380   if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
00381     err=UNZ_ERRNO;
00382 
00383   /* total number of entries in the central dir on this disk */
00384   if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
00385     err=UNZ_ERRNO;
00386 
00387   /* total number of entries in the central dir */
00388   if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
00389     err=UNZ_ERRNO;
00390 
00391   if ((number_entry_CD!=us.gi.number_entry) ||
00392     (number_disk_with_CD!=0) ||
00393     (number_disk!=0))
00394     err=UNZ_BADZIPFILE;
00395 
00396   /* size of the central directory */
00397   if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
00398     err=UNZ_ERRNO;
00399 
00400   /* offset of start of central directory with respect to the 
00401         starting disk number */
00402   if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
00403     err=UNZ_ERRNO;
00404 
00405   /* zipfile comment length */
00406   if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
00407     err=UNZ_ERRNO;
00408 
00409   if ((central_pos<us.offset_central_dir+us.size_central_dir) && 
00410     (err==UNZ_OK))
00411     err=UNZ_BADZIPFILE;
00412 
00413   if (err!=UNZ_OK)
00414   {
00415     fclose(fin);
00416     return NULL;
00417   }
00418 
00419   us.file=fin;
00420   us.byte_before_the_zipfile = central_pos -
00421                         (us.offset_central_dir+us.size_central_dir);
00422   us.central_pos = central_pos;
00423     us.pfile_in_zip_read = NULL;
00424   
00425 
00426   s=(unz_s*)ALLOC(sizeof(unz_s));
00427   *s=us;
00428   unzGoToFirstFile((unzFile)s); 
00429   return (unzFile)s;  
00430 }
00431 
00432 
00433 /*
00434   Close a ZipFile opened with unzipOpen.
00435   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
00436     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
00437   return UNZ_OK if there is no problem. */
00438 extern int ZEXPORT unzClose (unzFile file)
00439 {
00440   unz_s* s;
00441   if (file==NULL)
00442     return UNZ_PARAMERROR;
00443   s=(unz_s*)file;
00444 
00445     if (s->pfile_in_zip_read!=NULL)
00446         unzCloseCurrentFile(file);
00447 
00448   fclose(s->file);
00449   TRYFREE(s);
00450   return UNZ_OK;
00451 }
00452 
00453 
00454 /*
00455   Write info about the ZipFile in the *pglobal_info structure.
00456   No preparation of the structure is needed
00457   return UNZ_OK if there is no problem. */
00458 extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info)
00459 {
00460   unz_s* s;
00461   if (file==NULL)
00462     return UNZ_PARAMERROR;
00463   s=(unz_s*)file;
00464   *pglobal_info=s->gi;
00465   return UNZ_OK;
00466 }
00467 
00468 
00469 /*
00470    Translate date/time from Dos format to tm_unz (readable more easilty)
00471 */
00472 local void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm)
00473 {
00474     uLong uDate;
00475     uDate = (uLong)(ulDosDate>>16);
00476     ptm->tm_mday = (uInt)(uDate&0x1f) ;
00477     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
00478     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
00479 
00480     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
00481     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
00482     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
00483 }
00484 
00485 /*
00486   Get Info about the current file in the zipfile, with internal only info
00487 */
00488 local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
00489                                                unz_file_info *pfile_info,
00490                                                unz_file_info_internal *pfile_info_internal,
00491                                                char *szFileName,
00492                          uLong fileNameBufferSize,
00493                                                void *extraField,
00494                          uLong extraFieldBufferSize,
00495                                                char *szComment,
00496                          uLong commentBufferSize);
00497 
00498 local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
00499                                                unz_file_info *pfile_info,
00500                                                unz_file_info_internal *pfile_info_internal,
00501                                                char *szFileName,
00502                          uLong fileNameBufferSize,
00503                                                void *extraField,
00504                          uLong extraFieldBufferSize,
00505                                                char *szComment,
00506                          uLong commentBufferSize)
00507 {
00508   unz_s* s;
00509   unz_file_info file_info;
00510   unz_file_info_internal file_info_internal;
00511   int err=UNZ_OK;
00512   uLong uMagic;
00513   long lSeek=0;
00514 
00515   if (file==NULL)
00516     return UNZ_PARAMERROR;
00517   s=(unz_s*)file;
00518   if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
00519     err=UNZ_ERRNO;
00520 
00521 
00522   /* we check the magic */
00523   if (err==UNZ_OK)
00524   {
00525     if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
00526       err=UNZ_ERRNO;
00527     else if (uMagic!=0x02014b50)
00528       err=UNZ_BADZIPFILE;
00529   }
00530 
00531   if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
00532     err=UNZ_ERRNO;
00533 
00534   if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
00535     err=UNZ_ERRNO;
00536 
00537   if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
00538     err=UNZ_ERRNO;
00539 
00540   if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
00541     err=UNZ_ERRNO;
00542 
00543   if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
00544     err=UNZ_ERRNO;
00545 
00546     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
00547 
00548   if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
00549     err=UNZ_ERRNO;
00550 
00551   if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
00552     err=UNZ_ERRNO;
00553 
00554   if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
00555     err=UNZ_ERRNO;
00556 
00557   if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
00558     err=UNZ_ERRNO;
00559 
00560   if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
00561     err=UNZ_ERRNO;
00562 
00563   if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
00564     err=UNZ_ERRNO;
00565 
00566   if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
00567     err=UNZ_ERRNO;
00568 
00569   if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
00570     err=UNZ_ERRNO;
00571 
00572   if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
00573     err=UNZ_ERRNO;
00574 
00575   if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
00576     err=UNZ_ERRNO;
00577 
00578   lSeek+=file_info.size_filename;
00579   if ((err==UNZ_OK) && (szFileName!=NULL))
00580   {
00581     uLong uSizeRead ;
00582     if (file_info.size_filename<fileNameBufferSize)
00583     {
00584       *(szFileName+file_info.size_filename)='\0';
00585       uSizeRead = file_info.size_filename;
00586     }
00587     else
00588       uSizeRead = fileNameBufferSize;
00589 
00590     if ((file_info.size_filename>0) && (fileNameBufferSize>0))
00591       if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
00592         err=UNZ_ERRNO;
00593     lSeek -= uSizeRead;
00594   }
00595 
00596   
00597   if ((err==UNZ_OK) && (extraField!=NULL))
00598   {
00599     uLong uSizeRead ;
00600     if (file_info.size_file_extra<extraFieldBufferSize)
00601       uSizeRead = file_info.size_file_extra;
00602     else
00603       uSizeRead = extraFieldBufferSize;
00604 
00605     if (lSeek!=0)
00606     {
00607       if (fseek(s->file,lSeek,SEEK_CUR)==0)
00608         lSeek=0;
00609       else
00610         err=UNZ_ERRNO;
00611     }
00612     if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
00613       if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
00614         err=UNZ_ERRNO;
00615     lSeek += file_info.size_file_extra - uSizeRead;
00616   }
00617   else
00618     lSeek+=file_info.size_file_extra; 
00619 
00620   
00621   if ((err==UNZ_OK) && (szComment!=NULL))
00622   {
00623     uLong uSizeRead ;
00624     if (file_info.size_file_comment<commentBufferSize)
00625     {
00626       *(szComment+file_info.size_file_comment)='\0';
00627       uSizeRead = file_info.size_file_comment;
00628     }
00629     else
00630       uSizeRead = commentBufferSize;
00631 
00632     if (lSeek!=0)
00633     {
00634       if (fseek(s->file,lSeek,SEEK_CUR)==0)
00635         lSeek=0;
00636       else
00637         err=UNZ_ERRNO;
00638     }
00639     if ((file_info.size_file_comment>0) && (commentBufferSize>0))
00640       if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
00641         err=UNZ_ERRNO;
00642     lSeek+=file_info.size_file_comment - uSizeRead;
00643   }
00644   else
00645     lSeek+=file_info.size_file_comment;
00646 
00647   if ((err==UNZ_OK) && (pfile_info!=NULL))
00648     *pfile_info=file_info;
00649 
00650   if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
00651     *pfile_info_internal=file_info_internal;
00652 
00653   return err;
00654 }
00655 
00656 
00657 
00658 /*
00659   Write info about the ZipFile in the *pglobal_info structure.
00660   No preparation of the structure is needed
00661   return UNZ_OK if there is no problem.
00662 */
00663 extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
00664                       unz_file_info *pfile_info,
00665                       char *szFileName,
00666                       uLong fileNameBufferSize,
00667                       void *extraField,
00668                       uLong extraFieldBufferSize,
00669                       char *szComment,
00670                       uLong commentBufferSize)
00671 {
00672   return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
00673                         szFileName,fileNameBufferSize,
00674                         extraField,extraFieldBufferSize,
00675                         szComment,commentBufferSize);
00676 }
00677 
00678 /*
00679   Set the current file of the zipfile to the first file.
00680   return UNZ_OK if there is no problem
00681 */
00682 extern int ZEXPORT unzGoToFirstFile (unzFile file)
00683 {
00684   int err=UNZ_OK;
00685   unz_s* s;
00686   if (file==NULL)
00687     return UNZ_PARAMERROR;
00688   s=(unz_s*)file;
00689   s->pos_in_central_dir=s->offset_central_dir;
00690   s->num_file=0;
00691   err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
00692                        &s->cur_file_info_internal,
00693                        NULL,0,NULL,0,NULL,0);
00694   s->current_file_ok = (err == UNZ_OK);
00695   return err;
00696 }
00697 
00698 
00699 /*
00700   Set the current file of the zipfile to the next file.
00701   return UNZ_OK if there is no problem
00702   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
00703 */
00704 extern int ZEXPORT unzGoToNextFile (unzFile file)
00705 {
00706   unz_s* s; 
00707   int err;
00708 
00709   if (file==NULL)
00710     return UNZ_PARAMERROR;
00711   s=(unz_s*)file;
00712   if (!s->current_file_ok)
00713     return UNZ_END_OF_LIST_OF_FILE;
00714   if (s->num_file+1==s->gi.number_entry)
00715     return UNZ_END_OF_LIST_OF_FILE;
00716 
00717   s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
00718       s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
00719   s->num_file++;
00720   err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
00721                          &s->cur_file_info_internal,
00722                          NULL,0,NULL,0,NULL,0);
00723   s->current_file_ok = (err == UNZ_OK);
00724   return err;
00725 }
00726 
00727 
00728 /*
00729   Try locate the file szFileName in the zipfile.
00730   For the iCaseSensitivity signification, see unzipStringFileNameCompare
00731 
00732   return value :
00733   UNZ_OK if the file is found. It becomes the current file.
00734   UNZ_END_OF_LIST_OF_FILE if the file is not found
00735 */
00736 extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
00737 {
00738   unz_s* s; 
00739   int err;
00740 
00741   
00742   uLong num_fileSaved;
00743   uLong pos_in_central_dirSaved;
00744 
00745 
00746   if (file==NULL)
00747     return UNZ_PARAMERROR;
00748 
00749     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
00750         return UNZ_PARAMERROR;
00751 
00752   s=(unz_s*)file;
00753   if (!s->current_file_ok)
00754     return UNZ_END_OF_LIST_OF_FILE;
00755 
00756   num_fileSaved = s->num_file;
00757   pos_in_central_dirSaved = s->pos_in_central_dir;
00758 
00759   err = unzGoToFirstFile(file);
00760 
00761   while (err == UNZ_OK)
00762   {
00763     char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
00764     unzGetCurrentFileInfo(file,NULL,
00765                 szCurrentFileName,sizeof(szCurrentFileName)-1,
00766                 NULL,0,NULL,0);
00767     if (unzStringFileNameCompare(szCurrentFileName,
00768                     szFileName,iCaseSensitivity)==0)
00769       return UNZ_OK;
00770     err = unzGoToNextFile(file);
00771   }
00772 
00773   s->num_file = num_fileSaved ;
00774   s->pos_in_central_dir = pos_in_central_dirSaved ;
00775   return err;
00776 }
00777 
00778 
00779 /*
00780   Read the local header of the current zipfile
00781   Check the coherency of the local header and info in the end of central
00782         directory about this file
00783   store in *piSizeVar the size of extra info in local header
00784         (filename and size of extra field data)
00785 */
00786 local int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s,
00787                           uInt* piSizeVar,
00788                           uLong *poffset_local_extrafield,
00789                           uInt *psize_local_extrafield)
00790 {
00791   uLong uMagic,uData,uFlags;
00792   uLong size_filename;
00793   uLong size_extra_field;
00794   int err=UNZ_OK;
00795 
00796   *piSizeVar = 0;
00797   *poffset_local_extrafield = 0;
00798   *psize_local_extrafield = 0;
00799 
00800   if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
00801                 s->byte_before_the_zipfile,SEEK_SET)!=0)
00802     return UNZ_ERRNO;
00803 
00804 
00805   if (err==UNZ_OK)
00806   {
00807     if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
00808       err=UNZ_ERRNO;
00809     else if (uMagic!=0x04034b50)
00810       err=UNZ_BADZIPFILE;
00811   }
00812 
00813   if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
00814     err=UNZ_ERRNO;
00815 /*
00816   else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
00817     err=UNZ_BADZIPFILE;
00818 */
00819   if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
00820     err=UNZ_ERRNO;
00821 
00822   if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
00823     err=UNZ_ERRNO;
00824   else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
00825     err=UNZ_BADZIPFILE;
00826 
00827     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
00828                          (s->cur_file_info.compression_method!=Z_DEFLATED))
00829         err=UNZ_BADZIPFILE;
00830 
00831   if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
00832     err=UNZ_ERRNO;
00833 
00834   if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
00835     err=UNZ_ERRNO;
00836   else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
00837                           ((uFlags & 8)==0))
00838     err=UNZ_BADZIPFILE;
00839 
00840   if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
00841     err=UNZ_ERRNO;
00842   else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
00843                 ((uFlags & 8)==0))
00844     err=UNZ_BADZIPFILE;
00845 
00846   if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
00847     err=UNZ_ERRNO;
00848   else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && 
00849                 ((uFlags & 8)==0))
00850     err=UNZ_BADZIPFILE;
00851 
00852 
00853   if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
00854     err=UNZ_ERRNO;
00855   else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
00856     err=UNZ_BADZIPFILE;
00857 
00858   *piSizeVar += (uInt)size_filename;
00859 
00860   if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
00861     err=UNZ_ERRNO;
00862   *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
00863                   SIZEZIPLOCALHEADER + size_filename;
00864   *psize_local_extrafield = (uInt)size_extra_field;
00865 
00866   *piSizeVar += (uInt)size_extra_field;
00867 
00868   return err;
00869 }
00870                         
00871 /*
00872   Open for reading data the current file in the zipfile.
00873   If there is no error and the file is opened, the return value is UNZ_OK.
00874 */
00875 extern int ZEXPORT unzOpenCurrentFile (unzFile file)
00876 {
00877   int err=UNZ_OK;
00878   int Store;
00879   uInt iSizeVar;
00880   unz_s* s;
00881   file_in_zip_read_info_s* pfile_in_zip_read_info;
00882   uLong offset_local_extrafield;  /* offset of the local extra field */
00883   uInt  size_local_extrafield;    /* size of the local extra field */
00884 
00885   if (file==NULL)
00886     return UNZ_PARAMERROR;
00887   s=(unz_s*)file;
00888   if (!s->current_file_ok)
00889     return UNZ_PARAMERROR;
00890 
00891     if (s->pfile_in_zip_read != NULL)
00892         unzCloseCurrentFile(file);
00893 
00894   if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
00895         &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
00896     return UNZ_BADZIPFILE;
00897 
00898   pfile_in_zip_read_info = (file_in_zip_read_info_s*)
00899                       ALLOC(sizeof(file_in_zip_read_info_s));
00900   if (pfile_in_zip_read_info==NULL)
00901     return UNZ_INTERNALERROR;
00902 
00903   pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
00904   pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
00905   pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
00906   pfile_in_zip_read_info->pos_local_extrafield=0;
00907 
00908   if (pfile_in_zip_read_info->read_buffer==NULL)
00909   {
00910     TRYFREE(pfile_in_zip_read_info);
00911     return UNZ_INTERNALERROR;
00912   }
00913 
00914   pfile_in_zip_read_info->stream_initialised=0;
00915   
00916   if ((s->cur_file_info.compression_method!=0) &&
00917         (s->cur_file_info.compression_method!=Z_DEFLATED))
00918     err=UNZ_BADZIPFILE;
00919   Store = s->cur_file_info.compression_method==0;
00920 
00921   pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
00922   pfile_in_zip_read_info->crc32=0;
00923   pfile_in_zip_read_info->compression_method =
00924             s->cur_file_info.compression_method;
00925   pfile_in_zip_read_info->file=s->file;
00926   pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
00927 
00928     pfile_in_zip_read_info->stream.total_out = 0;
00929 
00930   if (!Store)
00931   {
00932     pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
00933     pfile_in_zip_read_info->stream.zfree = (free_func)0;
00934     pfile_in_zip_read_info->stream.opaque = (voidpf)0; 
00935       
00936     err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
00937     if (err == Z_OK)
00938       pfile_in_zip_read_info->stream_initialised=1;
00939         /* windowBits is passed < 0 to tell that there is no zlib header.
00940          * Note that in this case inflate *requires* an extra "dummy" byte
00941          * after the compressed stream in order to complete decompression and
00942          * return Z_STREAM_END. 
00943          * In unzip, i don't wait absolutely Z_STREAM_END because I known the 
00944          * size of both compressed and uncompressed data
00945          */
00946   }
00947   pfile_in_zip_read_info->rest_read_compressed = 
00948             s->cur_file_info.compressed_size ;
00949   pfile_in_zip_read_info->rest_read_uncompressed = 
00950             s->cur_file_info.uncompressed_size ;
00951 
00952   
00953   pfile_in_zip_read_info->pos_in_zipfile = 
00954             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + 
00955         iSizeVar;
00956   
00957   pfile_in_zip_read_info->stream.avail_in = (uInt)0;
00958 
00959 
00960   s->pfile_in_zip_read = pfile_in_zip_read_info;
00961     return UNZ_OK;
00962 }
00963 
00964 
00965 /*
00966   Read bytes from the current file.
00967   buf contain buffer where data must be copied
00968   len the size of buf.
00969 
00970   return the number of byte copied if somes bytes are copied
00971   return 0 if the end of file was reached
00972   return <0 with error code if there is an error
00973     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
00974 */
00975 extern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)
00976 {
00977   int err=UNZ_OK;
00978   uInt iRead = 0;
00979   unz_s* s;
00980   file_in_zip_read_info_s* pfile_in_zip_read_info;
00981   if (file==NULL)
00982     return UNZ_PARAMERROR;
00983   s=(unz_s*)file;
00984     pfile_in_zip_read_info=s->pfile_in_zip_read;
00985 
00986   if (pfile_in_zip_read_info==NULL)
00987     return UNZ_PARAMERROR;
00988 
00989 
00990   if ((pfile_in_zip_read_info->read_buffer == NULL))
00991     return UNZ_END_OF_LIST_OF_FILE;
00992   if (len==0)
00993     return 0;
00994 
00995   pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
00996 
00997   pfile_in_zip_read_info->stream.avail_out = (uInt)len;
00998   
00999   if (len>pfile_in_zip_read_info->rest_read_uncompressed)
01000     pfile_in_zip_read_info->stream.avail_out = 
01001       (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
01002 
01003   while (pfile_in_zip_read_info->stream.avail_out>0)
01004   {
01005     if ((pfile_in_zip_read_info->stream.avail_in==0) &&
01006             (pfile_in_zip_read_info->rest_read_compressed>0))
01007     {
01008       uInt uReadThis = UNZ_BUFSIZE;
01009       if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
01010         uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
01011       if (uReadThis == 0)
01012         return UNZ_EOF;
01013       if (fseek(pfile_in_zip_read_info->file,
01014                       pfile_in_zip_read_info->pos_in_zipfile + 
01015                          pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
01016         return UNZ_ERRNO;
01017       if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
01018                          pfile_in_zip_read_info->file)!=1)
01019         return UNZ_ERRNO;
01020       pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
01021 
01022       pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
01023       
01024       pfile_in_zip_read_info->stream.next_in = 
01025                 (Bytef*)pfile_in_zip_read_info->read_buffer;
01026       pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
01027     }
01028 
01029     if (pfile_in_zip_read_info->compression_method==0)
01030     {
01031       uInt uDoCopy,i ;
01032       if (pfile_in_zip_read_info->stream.avail_out < 
01033                             pfile_in_zip_read_info->stream.avail_in)
01034         uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
01035       else
01036         uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
01037         
01038       for (i=0;i<uDoCopy;i++)
01039         *(pfile_in_zip_read_info->stream.next_out+i) =
01040                         *(pfile_in_zip_read_info->stream.next_in+i);
01041           
01042       pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
01043                 pfile_in_zip_read_info->stream.next_out,
01044                 uDoCopy);
01045       pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
01046       pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
01047       pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
01048       pfile_in_zip_read_info->stream.next_out += uDoCopy;
01049       pfile_in_zip_read_info->stream.next_in += uDoCopy;
01050             pfile_in_zip_read_info->stream.total_out += uDoCopy;
01051       iRead += uDoCopy;
01052     }
01053     else
01054     {
01055       uLong uTotalOutBefore,uTotalOutAfter;
01056       const Bytef *bufBefore;
01057       uLong uOutThis;
01058       int flush=Z_SYNC_FLUSH;
01059 
01060       uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
01061       bufBefore = pfile_in_zip_read_info->stream.next_out;
01062 
01063       /*
01064       if ((pfile_in_zip_read_info->rest_read_uncompressed ==
01065                pfile_in_zip_read_info->stream.avail_out) &&
01066         (pfile_in_zip_read_info->rest_read_compressed == 0))
01067         flush = Z_FINISH;
01068       */
01069       err=inflate(&pfile_in_zip_read_info->stream,flush);
01070 
01071       uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
01072       uOutThis = uTotalOutAfter-uTotalOutBefore;
01073       
01074       pfile_in_zip_read_info->crc32 = 
01075                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
01076                         (uInt)(uOutThis));
01077 
01078       pfile_in_zip_read_info->rest_read_uncompressed -=
01079                 uOutThis;
01080 
01081       iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
01082             
01083       if (err==Z_STREAM_END)
01084         return (iRead==0) ? UNZ_EOF : iRead;
01085       if (err!=Z_OK) 
01086         break;
01087     }
01088   }
01089 
01090   if (err==Z_OK)
01091     return iRead;
01092   return err;
01093 }
01094 
01095 
01096 /*
01097   Give the current position in uncompressed data
01098 */
01099 extern z_off_t ZEXPORT unztell (unzFile file)
01100 {
01101   unz_s* s;
01102   file_in_zip_read_info_s* pfile_in_zip_read_info;
01103   if (file==NULL)
01104     return UNZ_PARAMERROR;
01105   s=(unz_s*)file;
01106     pfile_in_zip_read_info=s->pfile_in_zip_read;
01107 
01108   if (pfile_in_zip_read_info==NULL)
01109     return UNZ_PARAMERROR;
01110 
01111   return (z_off_t)pfile_in_zip_read_info->stream.total_out;
01112 }
01113 
01114 
01115 /*
01116   return 1 if the end of file was reached, 0 elsewhere 
01117 */
01118 extern int ZEXPORT unzeof (unzFile file)
01119 {
01120   unz_s* s;
01121   file_in_zip_read_info_s* pfile_in_zip_read_info;
01122   if (file==NULL)
01123     return UNZ_PARAMERROR;
01124   s=(unz_s*)file;
01125     pfile_in_zip_read_info=s->pfile_in_zip_read;
01126 
01127   if (pfile_in_zip_read_info==NULL)
01128     return UNZ_PARAMERROR;
01129   
01130   if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
01131     return 1;
01132   else
01133     return 0;
01134 }
01135 
01136 
01137 
01138 /*
01139   Read extra field from the current file (opened by unzOpenCurrentFile)
01140   This is the local-header version of the extra field (sometimes, there is
01141     more info in the local-header version than in the central-header)
01142 
01143   if buf==NULL, it return the size of the local extra field that can be read
01144 
01145   if buf!=NULL, len is the size of the buffer, the extra header is copied in
01146   buf.
01147   the return value is the number of bytes copied in buf, or (if <0) 
01148   the error code
01149 */
01150 extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
01151 {
01152   unz_s* s;
01153   file_in_zip_read_info_s* pfile_in_zip_read_info;
01154   uInt read_now;
01155   uLong size_to_read;
01156 
01157   if (file==NULL)
01158     return UNZ_PARAMERROR;
01159   s=(unz_s*)file;
01160     pfile_in_zip_read_info=s->pfile_in_zip_read;
01161 
01162   if (pfile_in_zip_read_info==NULL)
01163     return UNZ_PARAMERROR;
01164 
01165   size_to_read = (pfile_in_zip_read_info->size_local_extrafield - 
01166         pfile_in_zip_read_info->pos_local_extrafield);
01167 
01168   if (buf==NULL)
01169     return (int)size_to_read;
01170   
01171   if (len>size_to_read)
01172     read_now = (uInt)size_to_read;
01173   else
01174     read_now = (uInt)len ;
01175 
01176   if (read_now==0)
01177     return 0;
01178   
01179   if (fseek(pfile_in_zip_read_info->file,
01180               pfile_in_zip_read_info->offset_local_extrafield + 
01181         pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
01182     return UNZ_ERRNO;
01183 
01184   if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
01185     return UNZ_ERRNO;
01186 
01187   return (int)read_now;
01188 }
01189 
01190 /*
01191   Close the file in zip opened with unzipOpenCurrentFile
01192   Return UNZ_CRCERROR if all the file was read but the CRC is not good
01193 */
01194 extern int ZEXPORT unzCloseCurrentFile (unzFile file)
01195 {
01196   int err=UNZ_OK;
01197 
01198   unz_s* s;
01199   file_in_zip_read_info_s* pfile_in_zip_read_info;
01200   if (file==NULL)
01201     return UNZ_PARAMERROR;
01202   s=(unz_s*)file;
01203     pfile_in_zip_read_info=s->pfile_in_zip_read;
01204 
01205   if (pfile_in_zip_read_info==NULL)
01206     return UNZ_PARAMERROR;
01207 
01208 
01209   if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
01210   {
01211     if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
01212       err=UNZ_CRCERROR;
01213   }
01214 
01215 
01216   TRYFREE(pfile_in_zip_read_info->read_buffer);
01217   pfile_in_zip_read_info->read_buffer = NULL;
01218   if (pfile_in_zip_read_info->stream_initialised)
01219     inflateEnd(&pfile_in_zip_read_info->stream);
01220 
01221   pfile_in_zip_read_info->stream_initialised = 0;
01222   TRYFREE(pfile_in_zip_read_info);
01223 
01224     s->pfile_in_zip_read=NULL;
01225 
01226   return err;
01227 }
01228 
01229 
01230 /*
01231   Get the global comment string of the ZipFile, in the szComment buffer.
01232   uSizeBuf is the size of the szComment buffer.
01233   return the number of byte copied or an error code <0
01234 */
01235 extern int ZEXPORT unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf)
01236 {
01237   unz_s* s;
01238   uLong uReadThis ;
01239   if (file==NULL)
01240     return UNZ_PARAMERROR;
01241   s=(unz_s*)file;
01242 
01243   uReadThis = uSizeBuf;
01244   if (uReadThis>s->gi.size_comment)
01245     uReadThis = s->gi.size_comment;
01246 
01247   if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
01248     return UNZ_ERRNO;
01249 
01250   if (uReadThis>0)
01251     {
01252       *szComment='\0';
01253     if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
01254     return UNZ_ERRNO;
01255     }
01256 
01257   if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
01258     *(szComment+s->gi.size_comment)='\0';
01259   return (int)uReadThis;
01260 }
01261 
01262 /* Added by Ryan Nunn */
01263 #endif /*HAVE_ZIP_SUPPORT*/

Generated on Mon Jul 9 14:42:45 2007 for ExultEngine by  doxygen 1.5.1