misc/quazip/unzip.c
branchwebgl
changeset 8096 453917e94e55
parent 8053 2e836bebb518
parent 8093 2286a39140da
child 8099 a7f02b902b6f
equal deleted inserted replaced
8053:2e836bebb518 8096:453917e94e55
     1 /* unzip.c -- IO for uncompress .zip files using zlib
       
     2    Version 1.01e, February 12th, 2005
       
     3 
       
     4    Copyright (C) 1998-2005 Gilles Vollant
       
     5 
       
     6    Read unzip.h for more info
       
     7 
       
     8    Modified by Sergey A. Tachenov to integrate with Qt.
       
     9 */
       
    10 
       
    11 /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
       
    12 compatibility with older software. The following is from the original crypt.c. Code
       
    13 woven in by Terry Thorsen 1/2003.
       
    14 */
       
    15 /*
       
    16   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
       
    17 
       
    18   See the accompanying file LICENSE, version 2000-Apr-09 or later
       
    19   (the contents of which are also included in zip.h) for terms of use.
       
    20   If, for some reason, all these files are missing, the Info-ZIP license
       
    21   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
       
    22 */
       
    23 /*
       
    24   crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
       
    25 
       
    26   The encryption/decryption parts of this source code (as opposed to the
       
    27   non-echoing password parts) were originally written in Europe.  The
       
    28   whole source package can be freely distributed, including from the USA.
       
    29   (Prior to January 2000, re-export from the US was a violation of US law.)
       
    30  */
       
    31 
       
    32 /*
       
    33   This encryption code is a direct transcription of the algorithm from
       
    34   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
       
    35   file (appnote.txt) is distributed with the PKZIP program (even in the
       
    36   version without encryption capabilities).
       
    37  */
       
    38 
       
    39 
       
    40 #include <stdio.h>
       
    41 #include <stdlib.h>
       
    42 #include <string.h>
       
    43 #include "zlib.h"
       
    44 #include "unzip.h"
       
    45 
       
    46 #ifdef STDC
       
    47 #  include <stddef.h>
       
    48 #  include <string.h>
       
    49 #  include <stdlib.h>
       
    50 #endif
       
    51 #ifdef NO_ERRNO_H
       
    52     extern int errno;
       
    53 #else
       
    54 #   include <errno.h>
       
    55 #endif
       
    56 
       
    57 
       
    58 #ifndef local
       
    59 #  define local static
       
    60 #endif
       
    61 /* compile with -Dlocal if your debugger can't find static symbols */
       
    62 
       
    63 
       
    64 #ifndef CASESENSITIVITYDEFAULT_NO
       
    65 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
       
    66 #    define CASESENSITIVITYDEFAULT_NO
       
    67 #  endif
       
    68 #endif
       
    69 
       
    70 
       
    71 #ifndef UNZ_BUFSIZE
       
    72 #define UNZ_BUFSIZE (16384)
       
    73 #endif
       
    74 
       
    75 #ifndef UNZ_MAXFILENAMEINZIP
       
    76 #define UNZ_MAXFILENAMEINZIP (256)
       
    77 #endif
       
    78 
       
    79 #ifndef ALLOC
       
    80 # define ALLOC(size) (malloc(size))
       
    81 #endif
       
    82 #ifndef TRYFREE
       
    83 # define TRYFREE(p) {if (p) free(p);}
       
    84 #endif
       
    85 
       
    86 #define SIZECENTRALDIRITEM (0x2e)
       
    87 #define SIZEZIPLOCALHEADER (0x1e)
       
    88 
       
    89 
       
    90 
       
    91 
       
    92 const char unz_copyright[] =
       
    93    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
       
    94 
       
    95 /* unz_file_info_interntal contain internal info about a file in zipfile*/
       
    96 typedef struct unz_file_info_internal_s
       
    97 {
       
    98     uLong offset_curfile;/* relative offset of local header 4 bytes */
       
    99 } unz_file_info_internal;
       
   100 
       
   101 
       
   102 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
       
   103     when reading and decompress it */
       
   104 typedef struct
       
   105 {
       
   106     char  *read_buffer;         /* internal buffer for compressed data */
       
   107     z_stream stream;            /* zLib stream structure for inflate */
       
   108 
       
   109     uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
       
   110     uLong stream_initialised;   /* flag set if stream structure is initialised*/
       
   111 
       
   112     uLong offset_local_extrafield;/* offset of the local extra field */
       
   113     uInt  size_local_extrafield;/* size of the local extra field */
       
   114     uLong pos_local_extrafield;   /* position in the local extra field in read*/
       
   115 
       
   116     uLong crc32;                /* crc32 of all data uncompressed */
       
   117     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
       
   118     uLong rest_read_compressed; /* number of byte to be decompressed */
       
   119     uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
       
   120     zlib_filefunc_def z_filefunc;
       
   121     voidpf filestream;        /* io structore of the zipfile */
       
   122     uLong compression_method;   /* compression method (0==store) */
       
   123     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
       
   124     int   raw;
       
   125 } file_in_zip_read_info_s;
       
   126 
       
   127 
       
   128 /* unz_s contain internal information about the zipfile
       
   129 */
       
   130 typedef struct
       
   131 {
       
   132     zlib_filefunc_def z_filefunc;
       
   133     voidpf filestream;        /* io structore of the zipfile */
       
   134     unz_global_info gi;       /* public global information */
       
   135     uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
       
   136     uLong num_file;             /* number of the current file in the zipfile*/
       
   137     uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
       
   138     uLong current_file_ok;      /* flag about the usability of the current file*/
       
   139     uLong central_pos;          /* position of the beginning of the central dir*/
       
   140 
       
   141     uLong size_central_dir;     /* size of the central directory  */
       
   142     uLong offset_central_dir;   /* offset of start of central directory with
       
   143                                    respect to the starting disk number */
       
   144 
       
   145     unz_file_info cur_file_info; /* public info about the current file in zip*/
       
   146     unz_file_info_internal cur_file_info_internal; /* private info about it*/
       
   147     file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
       
   148                                         file if we are decompressing it */
       
   149     int encrypted;
       
   150 #    ifndef NOUNCRYPT
       
   151     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
       
   152     const unsigned long* pcrc_32_tab;
       
   153 #    endif
       
   154 } unz_s;
       
   155 
       
   156 
       
   157 #ifndef NOUNCRYPT
       
   158 #include "crypt.h"
       
   159 #endif
       
   160 
       
   161 /* ===========================================================================
       
   162      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
       
   163    for end of file.
       
   164    IN assertion: the stream s has been sucessfully opened for reading.
       
   165 */
       
   166 
       
   167 
       
   168 local int unzlocal_getByte OF((
       
   169     const zlib_filefunc_def* pzlib_filefunc_def,
       
   170     voidpf filestream,
       
   171     int *pi));
       
   172 
       
   173 local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi)
       
   174     const zlib_filefunc_def* pzlib_filefunc_def;
       
   175     voidpf filestream;
       
   176     int *pi;
       
   177 {
       
   178     unsigned char c;
       
   179     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
       
   180     if (err==1)
       
   181     {
       
   182         *pi = (int)c;
       
   183         return UNZ_OK;
       
   184     }
       
   185     else
       
   186     {
       
   187         if (ZERROR(*pzlib_filefunc_def,filestream))
       
   188             return UNZ_ERRNO;
       
   189         else
       
   190             return UNZ_EOF;
       
   191     }
       
   192 }
       
   193 
       
   194 
       
   195 /* ===========================================================================
       
   196    Reads a long in LSB order from the given gz_stream. Sets
       
   197 */
       
   198 local int unzlocal_getShort OF((
       
   199     const zlib_filefunc_def* pzlib_filefunc_def,
       
   200     voidpf filestream,
       
   201     uLong *pX));
       
   202 
       
   203 local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX)
       
   204     const zlib_filefunc_def* pzlib_filefunc_def;
       
   205     voidpf filestream;
       
   206     uLong *pX;
       
   207 {
       
   208     uLong x ;
       
   209     int i;
       
   210     int err;
       
   211 
       
   212     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
       
   213     x = (uLong)i;
       
   214 
       
   215     if (err==UNZ_OK)
       
   216         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
       
   217     x += ((uLong)i)<<8;
       
   218 
       
   219     if (err==UNZ_OK)
       
   220         *pX = x;
       
   221     else
       
   222         *pX = 0;
       
   223     return err;
       
   224 }
       
   225 
       
   226 local int unzlocal_getLong OF((
       
   227     const zlib_filefunc_def* pzlib_filefunc_def,
       
   228     voidpf filestream,
       
   229     uLong *pX));
       
   230 
       
   231 local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX)
       
   232     const zlib_filefunc_def* pzlib_filefunc_def;
       
   233     voidpf filestream;
       
   234     uLong *pX;
       
   235 {
       
   236     uLong x ;
       
   237     int i;
       
   238     int err;
       
   239 
       
   240     err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
       
   241     x = (uLong)i;
       
   242 
       
   243     if (err==UNZ_OK)
       
   244         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
       
   245     x += ((uLong)i)<<8;
       
   246 
       
   247     if (err==UNZ_OK)
       
   248         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
       
   249     x += ((uLong)i)<<16;
       
   250 
       
   251     if (err==UNZ_OK)
       
   252         err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i);
       
   253     x += ((uLong)i)<<24;
       
   254 
       
   255     if (err==UNZ_OK)
       
   256         *pX = x;
       
   257     else
       
   258         *pX = 0;
       
   259     return err;
       
   260 }
       
   261 
       
   262 
       
   263 /* My own strcmpi / strcasecmp */
       
   264 local int strcmpcasenosensitive_internal (fileName1,fileName2)
       
   265     const char* fileName1;
       
   266     const char* fileName2;
       
   267 {
       
   268     for (;;)
       
   269     {
       
   270         char c1=*(fileName1++);
       
   271         char c2=*(fileName2++);
       
   272         if ((c1>='a') && (c1<='z'))
       
   273             c1 -= 0x20;
       
   274         if ((c2>='a') && (c2<='z'))
       
   275             c2 -= 0x20;
       
   276         if (c1=='\0')
       
   277             return ((c2=='\0') ? 0 : -1);
       
   278         if (c2=='\0')
       
   279             return 1;
       
   280         if (c1<c2)
       
   281             return -1;
       
   282         if (c1>c2)
       
   283             return 1;
       
   284     }
       
   285 }
       
   286 
       
   287 
       
   288 #ifdef  CASESENSITIVITYDEFAULT_NO
       
   289 #define CASESENSITIVITYDEFAULTVALUE 2
       
   290 #else
       
   291 #define CASESENSITIVITYDEFAULTVALUE 1
       
   292 #endif
       
   293 
       
   294 #ifndef STRCMPCASENOSENTIVEFUNCTION
       
   295 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
       
   296 #endif
       
   297 
       
   298 /*
       
   299    Compare two filename (fileName1,fileName2).
       
   300    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
       
   301    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
       
   302                                                                 or strcasecmp)
       
   303    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
       
   304         (like 1 on Unix, 2 on Windows)
       
   305 
       
   306 */
       
   307 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
       
   308     const char* fileName1;
       
   309     const char* fileName2;
       
   310     int iCaseSensitivity;
       
   311 {
       
   312     if (iCaseSensitivity==0)
       
   313         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
       
   314 
       
   315     if (iCaseSensitivity==1)
       
   316         return strcmp(fileName1,fileName2);
       
   317 
       
   318     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
       
   319 }
       
   320 
       
   321 #ifndef BUFREADCOMMENT
       
   322 #define BUFREADCOMMENT (0x400)
       
   323 #endif
       
   324 
       
   325 /*
       
   326   Locate the Central directory of a zipfile (at the end, just before
       
   327     the global comment)
       
   328 */
       
   329 local uLong unzlocal_SearchCentralDir OF((
       
   330     const zlib_filefunc_def* pzlib_filefunc_def,
       
   331     voidpf filestream));
       
   332 
       
   333 local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream)
       
   334     const zlib_filefunc_def* pzlib_filefunc_def;
       
   335     voidpf filestream;
       
   336 {
       
   337     unsigned char* buf;
       
   338     uLong uSizeFile;
       
   339     uLong uBackRead;
       
   340     uLong uMaxBack=0xffff; /* maximum size of global comment */
       
   341     uLong uPosFound=0;
       
   342 
       
   343     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
       
   344         return 0;
       
   345 
       
   346 
       
   347     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
       
   348 
       
   349     if (uMaxBack>uSizeFile)
       
   350         uMaxBack = uSizeFile;
       
   351 
       
   352     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
       
   353     if (buf==NULL)
       
   354         return 0;
       
   355 
       
   356     uBackRead = 4;
       
   357     while (uBackRead<uMaxBack)
       
   358     {
       
   359         uLong uReadSize,uReadPos ;
       
   360         int i;
       
   361         if (uBackRead+BUFREADCOMMENT>uMaxBack)
       
   362             uBackRead = uMaxBack;
       
   363         else
       
   364             uBackRead+=BUFREADCOMMENT;
       
   365         uReadPos = uSizeFile-uBackRead ;
       
   366 
       
   367         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
       
   368                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
       
   369         if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
       
   370             break;
       
   371 
       
   372         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
       
   373             break;
       
   374 
       
   375         for (i=(int)uReadSize-3; (i--)>0;)
       
   376             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
       
   377                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
       
   378             {
       
   379                 uPosFound = uReadPos+i;
       
   380                 break;
       
   381             }
       
   382 
       
   383         if (uPosFound!=0)
       
   384             break;
       
   385     }
       
   386     TRYFREE(buf);
       
   387     return uPosFound;
       
   388 }
       
   389 
       
   390 /*
       
   391   Open a Zip file. path contain the full pathname (by example,
       
   392      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
       
   393      "zlib/zlib114.zip".
       
   394      If the zipfile cannot be opened (file doesn't exist or in not valid), the
       
   395        return value is NULL.
       
   396      Else, the return value is a unzFile Handle, usable with other function
       
   397        of this unzip package.
       
   398 */
       
   399 extern unzFile ZEXPORT unzOpen2 (file, pzlib_filefunc_def)
       
   400     voidpf file;
       
   401     zlib_filefunc_def* pzlib_filefunc_def;
       
   402 {
       
   403     unz_s us;
       
   404     unz_s *s;
       
   405     uLong central_pos,uL;
       
   406 
       
   407     uLong number_disk;          /* number of the current dist, used for
       
   408                                    spaning ZIP, unsupported, always 0*/
       
   409     uLong number_disk_with_CD;  /* number the the disk with central dir, used
       
   410                                    for spaning ZIP, unsupported, always 0*/
       
   411     uLong number_entry_CD;      /* total number of entries in
       
   412                                    the central dir
       
   413                                    (same than number_entry on nospan) */
       
   414 
       
   415     int err=UNZ_OK;
       
   416 
       
   417     if (unz_copyright[0]!=' ')
       
   418         return NULL;
       
   419 
       
   420     if (pzlib_filefunc_def==NULL)
       
   421         fill_qiodevice_filefunc(&us.z_filefunc);
       
   422     else
       
   423         us.z_filefunc = *pzlib_filefunc_def;
       
   424 
       
   425     us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque,
       
   426                                                  file,
       
   427                                                  ZLIB_FILEFUNC_MODE_READ |
       
   428                                                  ZLIB_FILEFUNC_MODE_EXISTING);
       
   429     if (us.filestream==NULL)
       
   430         return NULL;
       
   431 
       
   432     central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream);
       
   433     if (central_pos==0)
       
   434         err=UNZ_ERRNO;
       
   435 
       
   436     if (ZSEEK(us.z_filefunc, us.filestream,
       
   437                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
       
   438         err=UNZ_ERRNO;
       
   439 
       
   440     /* the signature, already checked */
       
   441     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
       
   442         err=UNZ_ERRNO;
       
   443 
       
   444     /* number of this disk */
       
   445     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
       
   446         err=UNZ_ERRNO;
       
   447 
       
   448     /* number of the disk with the start of the central directory */
       
   449     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
       
   450         err=UNZ_ERRNO;
       
   451 
       
   452     /* total number of entries in the central dir on this disk */
       
   453     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
       
   454         err=UNZ_ERRNO;
       
   455 
       
   456     /* total number of entries in the central dir */
       
   457     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
       
   458         err=UNZ_ERRNO;
       
   459 
       
   460     if ((number_entry_CD!=us.gi.number_entry) ||
       
   461         (number_disk_with_CD!=0) ||
       
   462         (number_disk!=0))
       
   463         err=UNZ_BADZIPFILE;
       
   464 
       
   465     /* size of the central directory */
       
   466     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
       
   467         err=UNZ_ERRNO;
       
   468 
       
   469     /* offset of start of central directory with respect to the
       
   470           starting disk number */
       
   471     if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
       
   472         err=UNZ_ERRNO;
       
   473 
       
   474     /* zipfile comment length */
       
   475     if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
       
   476         err=UNZ_ERRNO;
       
   477 
       
   478     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
       
   479         (err==UNZ_OK))
       
   480         err=UNZ_BADZIPFILE;
       
   481 
       
   482     if (err!=UNZ_OK)
       
   483     {
       
   484         ZCLOSE(us.z_filefunc, us.filestream);
       
   485         return NULL;
       
   486     }
       
   487 
       
   488     us.byte_before_the_zipfile = central_pos -
       
   489                             (us.offset_central_dir+us.size_central_dir);
       
   490     us.central_pos = central_pos;
       
   491     us.pfile_in_zip_read = NULL;
       
   492     us.encrypted = 0;
       
   493 
       
   494 
       
   495     s=(unz_s*)ALLOC(sizeof(unz_s));
       
   496     *s=us;
       
   497     unzGoToFirstFile((unzFile)s);
       
   498     return (unzFile)s;
       
   499 }
       
   500 
       
   501 
       
   502 extern unzFile ZEXPORT unzOpen (file)
       
   503     voidpf file;
       
   504 {
       
   505     return unzOpen2(file, NULL);
       
   506 }
       
   507 
       
   508 /*
       
   509   Close a ZipFile opened with unzipOpen.
       
   510   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
       
   511     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
       
   512   return UNZ_OK if there is no problem. */
       
   513 extern int ZEXPORT unzClose (file)
       
   514     unzFile file;
       
   515 {
       
   516     unz_s* s;
       
   517     if (file==NULL)
       
   518         return UNZ_PARAMERROR;
       
   519     s=(unz_s*)file;
       
   520 
       
   521     if (s->pfile_in_zip_read!=NULL)
       
   522         unzCloseCurrentFile(file);
       
   523 
       
   524     ZCLOSE(s->z_filefunc, s->filestream);
       
   525     TRYFREE(s);
       
   526     return UNZ_OK;
       
   527 }
       
   528 
       
   529 
       
   530 /*
       
   531   Write info about the ZipFile in the *pglobal_info structure.
       
   532   No preparation of the structure is needed
       
   533   return UNZ_OK if there is no problem. */
       
   534 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
       
   535     unzFile file;
       
   536     unz_global_info *pglobal_info;
       
   537 {
       
   538     unz_s* s;
       
   539     if (file==NULL)
       
   540         return UNZ_PARAMERROR;
       
   541     s=(unz_s*)file;
       
   542     *pglobal_info=s->gi;
       
   543     return UNZ_OK;
       
   544 }
       
   545 
       
   546 
       
   547 /*
       
   548    Translate date/time from Dos format to tm_unz (readable more easilty)
       
   549 */
       
   550 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
       
   551     uLong ulDosDate;
       
   552     tm_unz* ptm;
       
   553 {
       
   554     uLong uDate;
       
   555     uDate = (uLong)(ulDosDate>>16);
       
   556     ptm->tm_mday = (uInt)(uDate&0x1f) ;
       
   557     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
       
   558     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
       
   559 
       
   560     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
       
   561     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
       
   562     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
       
   563 }
       
   564 
       
   565 /*
       
   566   Get Info about the current file in the zipfile, with internal only info
       
   567 */
       
   568 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
       
   569                                                   unz_file_info *pfile_info,
       
   570                                                   unz_file_info_internal
       
   571                                                   *pfile_info_internal,
       
   572                                                   char *szFileName,
       
   573                                                   uLong fileNameBufferSize,
       
   574                                                   void *extraField,
       
   575                                                   uLong extraFieldBufferSize,
       
   576                                                   char *szComment,
       
   577                                                   uLong commentBufferSize));
       
   578 
       
   579 local int unzlocal_GetCurrentFileInfoInternal (file,
       
   580                                               pfile_info,
       
   581                                               pfile_info_internal,
       
   582                                               szFileName, fileNameBufferSize,
       
   583                                               extraField, extraFieldBufferSize,
       
   584                                               szComment,  commentBufferSize)
       
   585     unzFile file;
       
   586     unz_file_info *pfile_info;
       
   587     unz_file_info_internal *pfile_info_internal;
       
   588     char *szFileName;
       
   589     uLong fileNameBufferSize;
       
   590     void *extraField;
       
   591     uLong extraFieldBufferSize;
       
   592     char *szComment;
       
   593     uLong commentBufferSize;
       
   594 {
       
   595     unz_s* s;
       
   596     unz_file_info file_info;
       
   597     unz_file_info_internal file_info_internal;
       
   598     int err=UNZ_OK;
       
   599     uLong uMagic;
       
   600     uLong uSeek=0;
       
   601 
       
   602     if (file==NULL)
       
   603         return UNZ_PARAMERROR;
       
   604     s=(unz_s*)file;
       
   605     if (ZSEEK(s->z_filefunc, s->filestream,
       
   606               s->pos_in_central_dir+s->byte_before_the_zipfile,
       
   607               ZLIB_FILEFUNC_SEEK_SET)!=0)
       
   608         err=UNZ_ERRNO;
       
   609 
       
   610 
       
   611     /* we check the magic */
       
   612     if (err==UNZ_OK) {
       
   613         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
       
   614             err=UNZ_ERRNO;
       
   615         else if (uMagic!=0x02014b50)
       
   616             err=UNZ_BADZIPFILE;
       
   617     }
       
   618 
       
   619     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
       
   620         err=UNZ_ERRNO;
       
   621 
       
   622     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
       
   623         err=UNZ_ERRNO;
       
   624 
       
   625     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
       
   626         err=UNZ_ERRNO;
       
   627 
       
   628     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
       
   629         err=UNZ_ERRNO;
       
   630 
       
   631     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
       
   632         err=UNZ_ERRNO;
       
   633 
       
   634     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
       
   635 
       
   636     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
       
   637         err=UNZ_ERRNO;
       
   638 
       
   639     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
       
   640         err=UNZ_ERRNO;
       
   641 
       
   642     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
       
   643         err=UNZ_ERRNO;
       
   644 
       
   645     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
       
   646         err=UNZ_ERRNO;
       
   647 
       
   648     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
       
   649         err=UNZ_ERRNO;
       
   650 
       
   651     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
       
   652         err=UNZ_ERRNO;
       
   653 
       
   654     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
       
   655         err=UNZ_ERRNO;
       
   656 
       
   657     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
       
   658         err=UNZ_ERRNO;
       
   659 
       
   660     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
       
   661         err=UNZ_ERRNO;
       
   662 
       
   663     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
       
   664         err=UNZ_ERRNO;
       
   665 
       
   666     uSeek+=file_info.size_filename;
       
   667     if ((err==UNZ_OK) && (szFileName!=NULL))
       
   668     {
       
   669         uLong uSizeRead ;
       
   670         if (file_info.size_filename<fileNameBufferSize)
       
   671         {
       
   672             *(szFileName+file_info.size_filename)='\0';
       
   673             uSizeRead = file_info.size_filename;
       
   674         }
       
   675         else
       
   676             uSizeRead = fileNameBufferSize;
       
   677 
       
   678         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
       
   679             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
       
   680                 err=UNZ_ERRNO;
       
   681         uSeek -= uSizeRead;
       
   682     }
       
   683 
       
   684 
       
   685     if ((err==UNZ_OK) && (extraField!=NULL))
       
   686     {
       
   687         uLong uSizeRead ;
       
   688         if (file_info.size_file_extra<extraFieldBufferSize)
       
   689             uSizeRead = file_info.size_file_extra;
       
   690         else
       
   691             uSizeRead = extraFieldBufferSize;
       
   692 
       
   693         if (uSeek!=0) {
       
   694             if (ZSEEK(s->z_filefunc, s->filestream,uSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
       
   695                 uSeek=0;
       
   696             else
       
   697                 err=UNZ_ERRNO;
       
   698         }
       
   699         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
       
   700             if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
       
   701                 err=UNZ_ERRNO;
       
   702         uSeek += file_info.size_file_extra - uSizeRead;
       
   703     }
       
   704     else
       
   705         uSeek+=file_info.size_file_extra;
       
   706 
       
   707 
       
   708     if ((err==UNZ_OK) && (szComment!=NULL))
       
   709     {
       
   710         uLong uSizeRead ;
       
   711         if (file_info.size_file_comment<commentBufferSize)
       
   712         {
       
   713             *(szComment+file_info.size_file_comment)='\0';
       
   714             uSizeRead = file_info.size_file_comment;
       
   715         }
       
   716         else
       
   717             uSizeRead = commentBufferSize;
       
   718 
       
   719         if (uSeek!=0) {
       
   720             if (ZSEEK(s->z_filefunc, s->filestream,uSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
       
   721                 uSeek=0;
       
   722             else
       
   723                 err=UNZ_ERRNO;
       
   724         }
       
   725         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
       
   726             if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
       
   727                 err=UNZ_ERRNO;
       
   728         uSeek+=file_info.size_file_comment - uSizeRead;
       
   729     }
       
   730     else
       
   731         uSeek+=file_info.size_file_comment;
       
   732 
       
   733     if ((err==UNZ_OK) && (pfile_info!=NULL))
       
   734         *pfile_info=file_info;
       
   735 
       
   736     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
       
   737         *pfile_info_internal=file_info_internal;
       
   738 
       
   739     return err;
       
   740 }
       
   741 
       
   742 
       
   743 
       
   744 /*
       
   745   Write info about the ZipFile in the *pglobal_info structure.
       
   746   No preparation of the structure is needed
       
   747   return UNZ_OK if there is no problem.
       
   748 */
       
   749 extern int ZEXPORT unzGetCurrentFileInfo (file,
       
   750                                           pfile_info,
       
   751                                           szFileName, fileNameBufferSize,
       
   752                                           extraField, extraFieldBufferSize,
       
   753                                           szComment,  commentBufferSize)
       
   754     unzFile file;
       
   755     unz_file_info *pfile_info;
       
   756     char *szFileName;
       
   757     uLong fileNameBufferSize;
       
   758     void *extraField;
       
   759     uLong extraFieldBufferSize;
       
   760     char *szComment;
       
   761     uLong commentBufferSize;
       
   762 {
       
   763     return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
       
   764                                                 szFileName,fileNameBufferSize,
       
   765                                                 extraField,extraFieldBufferSize,
       
   766                                                 szComment,commentBufferSize);
       
   767 }
       
   768 
       
   769 /*
       
   770   Set the current file of the zipfile to the first file.
       
   771   return UNZ_OK if there is no problem
       
   772 */
       
   773 extern int ZEXPORT unzGoToFirstFile (file)
       
   774     unzFile file;
       
   775 {
       
   776     int err=UNZ_OK;
       
   777     unz_s* s;
       
   778     if (file==NULL)
       
   779         return UNZ_PARAMERROR;
       
   780     s=(unz_s*)file;
       
   781     s->pos_in_central_dir=s->offset_central_dir;
       
   782     s->num_file=0;
       
   783     err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
       
   784                                              &s->cur_file_info_internal,
       
   785                                              NULL,0,NULL,0,NULL,0);
       
   786     s->current_file_ok = (err == UNZ_OK);
       
   787     return err;
       
   788 }
       
   789 
       
   790 /*
       
   791   Set the current file of the zipfile to the next file.
       
   792   return UNZ_OK if there is no problem
       
   793   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
       
   794 */
       
   795 extern int ZEXPORT unzGoToNextFile (file)
       
   796     unzFile file;
       
   797 {
       
   798     unz_s* s;
       
   799     int err;
       
   800 
       
   801     if (file==NULL)
       
   802         return UNZ_PARAMERROR;
       
   803     s=(unz_s*)file;
       
   804     if (!s->current_file_ok)
       
   805         return UNZ_END_OF_LIST_OF_FILE;
       
   806     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
       
   807       if (s->num_file+1==s->gi.number_entry)
       
   808         return UNZ_END_OF_LIST_OF_FILE;
       
   809 
       
   810     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
       
   811             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
       
   812     s->num_file++;
       
   813     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
       
   814                                                &s->cur_file_info_internal,
       
   815                                                NULL,0,NULL,0,NULL,0);
       
   816     s->current_file_ok = (err == UNZ_OK);
       
   817     return err;
       
   818 }
       
   819 
       
   820 
       
   821 /*
       
   822   Try locate the file szFileName in the zipfile.
       
   823   For the iCaseSensitivity signification, see unzipStringFileNameCompare
       
   824 
       
   825   return value :
       
   826   UNZ_OK if the file is found. It becomes the current file.
       
   827   UNZ_END_OF_LIST_OF_FILE if the file is not found
       
   828 */
       
   829 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
       
   830     unzFile file;
       
   831     const char *szFileName;
       
   832     int iCaseSensitivity;
       
   833 {
       
   834     unz_s* s;
       
   835     int err;
       
   836 
       
   837     /* We remember the 'current' position in the file so that we can jump
       
   838      * back there if we fail.
       
   839      */
       
   840     unz_file_info cur_file_infoSaved;
       
   841     unz_file_info_internal cur_file_info_internalSaved;
       
   842     uLong num_fileSaved;
       
   843     uLong pos_in_central_dirSaved;
       
   844 
       
   845 
       
   846     if (file==NULL)
       
   847         return UNZ_PARAMERROR;
       
   848 
       
   849     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
       
   850         return UNZ_PARAMERROR;
       
   851 
       
   852     s=(unz_s*)file;
       
   853     if (!s->current_file_ok)
       
   854         return UNZ_END_OF_LIST_OF_FILE;
       
   855 
       
   856     /* Save the current state */
       
   857     num_fileSaved = s->num_file;
       
   858     pos_in_central_dirSaved = s->pos_in_central_dir;
       
   859     cur_file_infoSaved = s->cur_file_info;
       
   860     cur_file_info_internalSaved = s->cur_file_info_internal;
       
   861 
       
   862     err = unzGoToFirstFile(file);
       
   863 
       
   864     while (err == UNZ_OK)
       
   865     {
       
   866         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
       
   867         err = unzGetCurrentFileInfo(file,NULL,
       
   868                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
       
   869                                     NULL,0,NULL,0);
       
   870         if (err == UNZ_OK)
       
   871         {
       
   872             if (unzStringFileNameCompare(szCurrentFileName,
       
   873                                             szFileName,iCaseSensitivity)==0)
       
   874                 return UNZ_OK;
       
   875             err = unzGoToNextFile(file);
       
   876         }
       
   877     }
       
   878 
       
   879     /* We failed, so restore the state of the 'current file' to where we
       
   880      * were.
       
   881      */
       
   882     s->num_file = num_fileSaved ;
       
   883     s->pos_in_central_dir = pos_in_central_dirSaved ;
       
   884     s->cur_file_info = cur_file_infoSaved;
       
   885     s->cur_file_info_internal = cur_file_info_internalSaved;
       
   886     return err;
       
   887 }
       
   888 
       
   889 
       
   890 /*
       
   891 ///////////////////////////////////////////
       
   892 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
       
   893 // I need random access
       
   894 //
       
   895 // Further optimization could be realized by adding an ability
       
   896 // to cache the directory in memory. The goal being a single
       
   897 // comprehensive file read to put the file I need in a memory.
       
   898 */
       
   899 
       
   900 /*
       
   901 typedef struct unz_file_pos_s
       
   902 {
       
   903     uLong pos_in_zip_directory;   // offset in file
       
   904     uLong num_of_file;            // # of file
       
   905 } unz_file_pos;
       
   906 */
       
   907 
       
   908 extern int ZEXPORT unzGetFilePos(file, file_pos)
       
   909     unzFile file;
       
   910     unz_file_pos* file_pos;
       
   911 {
       
   912     unz_s* s;
       
   913 
       
   914     if (file==NULL || file_pos==NULL)
       
   915         return UNZ_PARAMERROR;
       
   916     s=(unz_s*)file;
       
   917     if (!s->current_file_ok)
       
   918         return UNZ_END_OF_LIST_OF_FILE;
       
   919 
       
   920     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
       
   921     file_pos->num_of_file           = s->num_file;
       
   922 
       
   923     return UNZ_OK;
       
   924 }
       
   925 
       
   926 extern int ZEXPORT unzGoToFilePos(file, file_pos)
       
   927     unzFile file;
       
   928     unz_file_pos* file_pos;
       
   929 {
       
   930     unz_s* s;
       
   931     int err;
       
   932 
       
   933     if (file==NULL || file_pos==NULL)
       
   934         return UNZ_PARAMERROR;
       
   935     s=(unz_s*)file;
       
   936 
       
   937     /* jump to the right spot */
       
   938     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
       
   939     s->num_file           = file_pos->num_of_file;
       
   940 
       
   941     /* set the current file */
       
   942     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
       
   943                                                &s->cur_file_info_internal,
       
   944                                                NULL,0,NULL,0,NULL,0);
       
   945     /* return results */
       
   946     s->current_file_ok = (err == UNZ_OK);
       
   947     return err;
       
   948 }
       
   949 
       
   950 /*
       
   951 // Unzip Helper Functions - should be here?
       
   952 ///////////////////////////////////////////
       
   953 */
       
   954 
       
   955 /*
       
   956   Read the local header of the current zipfile
       
   957   Check the coherency of the local header and info in the end of central
       
   958         directory about this file
       
   959   store in *piSizeVar the size of extra info in local header
       
   960         (filename and size of extra field data)
       
   961 */
       
   962 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
       
   963                                                     poffset_local_extrafield,
       
   964                                                     psize_local_extrafield)
       
   965     unz_s* s;
       
   966     uInt* piSizeVar;
       
   967     uLong *poffset_local_extrafield;
       
   968     uInt  *psize_local_extrafield;
       
   969 {
       
   970     uLong uMagic,uData,uFlags;
       
   971     uLong size_filename;
       
   972     uLong size_extra_field;
       
   973     int err=UNZ_OK;
       
   974 
       
   975     *piSizeVar = 0;
       
   976     *poffset_local_extrafield = 0;
       
   977     *psize_local_extrafield = 0;
       
   978 
       
   979     if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
       
   980                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
       
   981         return UNZ_ERRNO;
       
   982 
       
   983 
       
   984     if (err==UNZ_OK) {
       
   985         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
       
   986             err=UNZ_ERRNO;
       
   987         else if (uMagic!=0x04034b50)
       
   988             err=UNZ_BADZIPFILE;
       
   989     }
       
   990 
       
   991     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
       
   992         err=UNZ_ERRNO;
       
   993 /*
       
   994     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
       
   995         err=UNZ_BADZIPFILE;
       
   996 */
       
   997     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
       
   998         err=UNZ_ERRNO;
       
   999 
       
  1000     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
       
  1001         err=UNZ_ERRNO;
       
  1002     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
       
  1003         err=UNZ_BADZIPFILE;
       
  1004 
       
  1005     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
       
  1006                          (s->cur_file_info.compression_method!=Z_DEFLATED))
       
  1007         err=UNZ_BADZIPFILE;
       
  1008 
       
  1009     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
       
  1010         err=UNZ_ERRNO;
       
  1011 
       
  1012     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
       
  1013         err=UNZ_ERRNO;
       
  1014     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
       
  1015                               ((uFlags & 8)==0))
       
  1016         err=UNZ_BADZIPFILE;
       
  1017 
       
  1018     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
       
  1019         err=UNZ_ERRNO;
       
  1020     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
       
  1021                               ((uFlags & 8)==0))
       
  1022         err=UNZ_BADZIPFILE;
       
  1023 
       
  1024     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
       
  1025         err=UNZ_ERRNO;
       
  1026     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
       
  1027                               ((uFlags & 8)==0))
       
  1028         err=UNZ_BADZIPFILE;
       
  1029 
       
  1030 
       
  1031     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
       
  1032         err=UNZ_ERRNO;
       
  1033     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
       
  1034         err=UNZ_BADZIPFILE;
       
  1035 
       
  1036     *piSizeVar += (uInt)size_filename;
       
  1037 
       
  1038     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
       
  1039         err=UNZ_ERRNO;
       
  1040     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
       
  1041                                     SIZEZIPLOCALHEADER + size_filename;
       
  1042     *psize_local_extrafield = (uInt)size_extra_field;
       
  1043 
       
  1044     *piSizeVar += (uInt)size_extra_field;
       
  1045 
       
  1046     return err;
       
  1047 }
       
  1048 
       
  1049 /*
       
  1050   Open for reading data the current file in the zipfile.
       
  1051   If there is no error and the file is opened, the return value is UNZ_OK.
       
  1052 */
       
  1053 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
       
  1054     unzFile file;
       
  1055     int* method;
       
  1056     int* level;
       
  1057     int raw;
       
  1058     const char* password;
       
  1059 {
       
  1060     int err=UNZ_OK;
       
  1061     uInt iSizeVar;
       
  1062     unz_s* s;
       
  1063     file_in_zip_read_info_s* pfile_in_zip_read_info;
       
  1064     uLong offset_local_extrafield;  /* offset of the local extra field */
       
  1065     uInt  size_local_extrafield;    /* size of the local extra field */
       
  1066 #    ifndef NOUNCRYPT
       
  1067     char source[12];
       
  1068 #    else
       
  1069     if (password != NULL)
       
  1070         return UNZ_PARAMERROR;
       
  1071 #    endif
       
  1072 
       
  1073     if (file==NULL)
       
  1074         return UNZ_PARAMERROR;
       
  1075     s=(unz_s*)file;
       
  1076     if (!s->current_file_ok)
       
  1077         return UNZ_PARAMERROR;
       
  1078 
       
  1079     if (s->pfile_in_zip_read != NULL)
       
  1080         unzCloseCurrentFile(file);
       
  1081 
       
  1082     if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
       
  1083                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
       
  1084         return UNZ_BADZIPFILE;
       
  1085 
       
  1086     pfile_in_zip_read_info = (file_in_zip_read_info_s*)
       
  1087                                         ALLOC(sizeof(file_in_zip_read_info_s));
       
  1088     if (pfile_in_zip_read_info==NULL)
       
  1089         return UNZ_INTERNALERROR;
       
  1090 
       
  1091     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
       
  1092     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
       
  1093     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
       
  1094     pfile_in_zip_read_info->pos_local_extrafield=0;
       
  1095     pfile_in_zip_read_info->raw=raw;
       
  1096 
       
  1097     if (pfile_in_zip_read_info->read_buffer==NULL)
       
  1098     {
       
  1099         TRYFREE(pfile_in_zip_read_info);
       
  1100         return UNZ_INTERNALERROR;
       
  1101     }
       
  1102 
       
  1103     pfile_in_zip_read_info->stream_initialised=0;
       
  1104 
       
  1105     if (method!=NULL)
       
  1106         *method = (int)s->cur_file_info.compression_method;
       
  1107 
       
  1108     if (level!=NULL)
       
  1109     {
       
  1110         *level = 6;
       
  1111         switch (s->cur_file_info.flag & 0x06)
       
  1112         {
       
  1113           case 6 : *level = 1; break;
       
  1114           case 4 : *level = 2; break;
       
  1115           case 2 : *level = 9; break;
       
  1116         }
       
  1117     }
       
  1118 
       
  1119     if ((s->cur_file_info.compression_method!=0) &&
       
  1120         (s->cur_file_info.compression_method!=Z_DEFLATED))
       
  1121         err=UNZ_BADZIPFILE;
       
  1122 
       
  1123     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
       
  1124     pfile_in_zip_read_info->crc32=0;
       
  1125     pfile_in_zip_read_info->compression_method =
       
  1126             s->cur_file_info.compression_method;
       
  1127     pfile_in_zip_read_info->filestream=s->filestream;
       
  1128     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
       
  1129     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
       
  1130 
       
  1131     pfile_in_zip_read_info->stream.total_out = 0;
       
  1132 
       
  1133     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
       
  1134         (!raw))
       
  1135     {
       
  1136       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
       
  1137       pfile_in_zip_read_info->stream.zfree = (free_func)0;
       
  1138       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
       
  1139       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
       
  1140       pfile_in_zip_read_info->stream.avail_in = 0;
       
  1141 
       
  1142       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
       
  1143       if (err == Z_OK)
       
  1144         pfile_in_zip_read_info->stream_initialised=1;
       
  1145       else
       
  1146       {
       
  1147         TRYFREE(pfile_in_zip_read_info);
       
  1148         return err;
       
  1149       }
       
  1150         /* windowBits is passed < 0 to tell that there is no zlib header.
       
  1151          * Note that in this case inflate *requires* an extra "dummy" byte
       
  1152          * after the compressed stream in order to complete decompression and
       
  1153          * return Z_STREAM_END.
       
  1154          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
       
  1155          * size of both compressed and uncompressed data
       
  1156          */
       
  1157     }
       
  1158     pfile_in_zip_read_info->rest_read_compressed =
       
  1159             s->cur_file_info.compressed_size ;
       
  1160     pfile_in_zip_read_info->rest_read_uncompressed =
       
  1161             s->cur_file_info.uncompressed_size ;
       
  1162 
       
  1163 
       
  1164     pfile_in_zip_read_info->pos_in_zipfile =
       
  1165             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
       
  1166               iSizeVar;
       
  1167 
       
  1168     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
       
  1169 
       
  1170     s->pfile_in_zip_read = pfile_in_zip_read_info;
       
  1171 
       
  1172 #    ifndef NOUNCRYPT
       
  1173     if (password != NULL)
       
  1174     {
       
  1175         int i;
       
  1176         s->pcrc_32_tab = get_crc_table();
       
  1177         init_keys(password,s->keys,s->pcrc_32_tab);
       
  1178         if (ZSEEK(s->z_filefunc, s->filestream,
       
  1179                   s->pfile_in_zip_read->pos_in_zipfile +
       
  1180                      s->pfile_in_zip_read->byte_before_the_zipfile,
       
  1181                   SEEK_SET)!=0)
       
  1182             return UNZ_INTERNALERROR;
       
  1183         if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
       
  1184             return UNZ_INTERNALERROR;
       
  1185 
       
  1186         for (i = 0; i<12; i++)
       
  1187             zdecode(s->keys,s->pcrc_32_tab,source[i]);
       
  1188 
       
  1189         s->pfile_in_zip_read->pos_in_zipfile+=12;
       
  1190         s->encrypted=1;
       
  1191     }
       
  1192 #    endif
       
  1193 
       
  1194 
       
  1195     return UNZ_OK;
       
  1196 }
       
  1197 
       
  1198 extern int ZEXPORT unzOpenCurrentFile (file)
       
  1199     unzFile file;
       
  1200 {
       
  1201     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
       
  1202 }
       
  1203 
       
  1204 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
       
  1205     unzFile file;
       
  1206     const char* password;
       
  1207 {
       
  1208     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
       
  1209 }
       
  1210 
       
  1211 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
       
  1212     unzFile file;
       
  1213     int* method;
       
  1214     int* level;
       
  1215     int raw;
       
  1216 {
       
  1217     return unzOpenCurrentFile3(file, method, level, raw, NULL);
       
  1218 }
       
  1219 
       
  1220 /*
       
  1221   Read bytes from the current file.
       
  1222   buf contain buffer where data must be copied
       
  1223   len the size of buf.
       
  1224 
       
  1225   return the number of byte copied if somes bytes are copied
       
  1226   return 0 if the end of file was reached
       
  1227   return <0 with error code if there is an error
       
  1228     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
       
  1229 */
       
  1230 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
       
  1231     unzFile file;
       
  1232     voidp buf;
       
  1233     unsigned len;
       
  1234 {
       
  1235     int err=UNZ_OK;
       
  1236     uInt iRead = 0;
       
  1237     unz_s* s;
       
  1238     file_in_zip_read_info_s* pfile_in_zip_read_info;
       
  1239     if (file==NULL)
       
  1240         return UNZ_PARAMERROR;
       
  1241     s=(unz_s*)file;
       
  1242     pfile_in_zip_read_info=s->pfile_in_zip_read;
       
  1243 
       
  1244     if (pfile_in_zip_read_info==NULL)
       
  1245         return UNZ_PARAMERROR;
       
  1246 
       
  1247 
       
  1248     if ((pfile_in_zip_read_info->read_buffer == NULL))
       
  1249         return UNZ_END_OF_LIST_OF_FILE;
       
  1250     if (len==0)
       
  1251         return 0;
       
  1252 
       
  1253     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
       
  1254 
       
  1255     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
       
  1256 
       
  1257     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
       
  1258         (!(pfile_in_zip_read_info->raw)))
       
  1259         pfile_in_zip_read_info->stream.avail_out =
       
  1260             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
       
  1261 
       
  1262     if ((len>pfile_in_zip_read_info->rest_read_compressed+
       
  1263            pfile_in_zip_read_info->stream.avail_in) &&
       
  1264          (pfile_in_zip_read_info->raw))
       
  1265         pfile_in_zip_read_info->stream.avail_out =
       
  1266             (uInt)pfile_in_zip_read_info->rest_read_compressed+
       
  1267             pfile_in_zip_read_info->stream.avail_in;
       
  1268 
       
  1269     while (pfile_in_zip_read_info->stream.avail_out>0)
       
  1270     {
       
  1271         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
       
  1272             (pfile_in_zip_read_info->rest_read_compressed>0))
       
  1273         {
       
  1274             uInt uReadThis = UNZ_BUFSIZE;
       
  1275             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
       
  1276                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
       
  1277             if (uReadThis == 0)
       
  1278                 return UNZ_EOF;
       
  1279             if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
       
  1280                       pfile_in_zip_read_info->filestream,
       
  1281                       pfile_in_zip_read_info->pos_in_zipfile +
       
  1282                          pfile_in_zip_read_info->byte_before_the_zipfile,
       
  1283                          ZLIB_FILEFUNC_SEEK_SET)!=0)
       
  1284                 return UNZ_ERRNO;
       
  1285             if (ZREAD(pfile_in_zip_read_info->z_filefunc,
       
  1286                       pfile_in_zip_read_info->filestream,
       
  1287                       pfile_in_zip_read_info->read_buffer,
       
  1288                       uReadThis)!=uReadThis)
       
  1289                 return UNZ_ERRNO;
       
  1290 
       
  1291 
       
  1292 #            ifndef NOUNCRYPT
       
  1293             if(s->encrypted)
       
  1294             {
       
  1295                 uInt i;
       
  1296                 for(i=0;i<uReadThis;i++)
       
  1297                   pfile_in_zip_read_info->read_buffer[i] =
       
  1298                       zdecode(s->keys,s->pcrc_32_tab,
       
  1299                               pfile_in_zip_read_info->read_buffer[i]);
       
  1300             }
       
  1301 #            endif
       
  1302 
       
  1303 
       
  1304             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
       
  1305 
       
  1306             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
       
  1307 
       
  1308             pfile_in_zip_read_info->stream.next_in =
       
  1309                 (Bytef*)pfile_in_zip_read_info->read_buffer;
       
  1310             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
       
  1311         }
       
  1312 
       
  1313         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
       
  1314         {
       
  1315             uInt uDoCopy,i ;
       
  1316 
       
  1317             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
       
  1318                 (pfile_in_zip_read_info->rest_read_compressed == 0))
       
  1319                 return (iRead==0) ? UNZ_EOF : iRead;
       
  1320 
       
  1321             if (pfile_in_zip_read_info->stream.avail_out <
       
  1322                             pfile_in_zip_read_info->stream.avail_in)
       
  1323                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
       
  1324             else
       
  1325                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
       
  1326 
       
  1327             for (i=0;i<uDoCopy;i++)
       
  1328                 *(pfile_in_zip_read_info->stream.next_out+i) =
       
  1329                         *(pfile_in_zip_read_info->stream.next_in+i);
       
  1330 
       
  1331             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
       
  1332                                 pfile_in_zip_read_info->stream.next_out,
       
  1333                                 uDoCopy);
       
  1334             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
       
  1335             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
       
  1336             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
       
  1337             pfile_in_zip_read_info->stream.next_out += uDoCopy;
       
  1338             pfile_in_zip_read_info->stream.next_in += uDoCopy;
       
  1339             pfile_in_zip_read_info->stream.total_out += uDoCopy;
       
  1340             iRead += uDoCopy;
       
  1341         }
       
  1342         else
       
  1343         {
       
  1344             uLong uTotalOutBefore,uTotalOutAfter;
       
  1345             const Bytef *bufBefore;
       
  1346             uLong uOutThis;
       
  1347             int flush=Z_SYNC_FLUSH;
       
  1348 
       
  1349             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
       
  1350             bufBefore = pfile_in_zip_read_info->stream.next_out;
       
  1351 
       
  1352             /*
       
  1353             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
       
  1354                      pfile_in_zip_read_info->stream.avail_out) &&
       
  1355                 (pfile_in_zip_read_info->rest_read_compressed == 0))
       
  1356                 flush = Z_FINISH;
       
  1357             */
       
  1358             err=inflate(&pfile_in_zip_read_info->stream,flush);
       
  1359 
       
  1360             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
       
  1361               err = Z_DATA_ERROR;
       
  1362 
       
  1363             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
       
  1364             uOutThis = uTotalOutAfter-uTotalOutBefore;
       
  1365 
       
  1366             pfile_in_zip_read_info->crc32 =
       
  1367                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
       
  1368                         (uInt)(uOutThis));
       
  1369 
       
  1370             pfile_in_zip_read_info->rest_read_uncompressed -=
       
  1371                 uOutThis;
       
  1372 
       
  1373             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
       
  1374 
       
  1375             if (err==Z_STREAM_END)
       
  1376                 return (iRead==0) ? UNZ_EOF : iRead;
       
  1377             if (err!=Z_OK)
       
  1378                 break;
       
  1379         }
       
  1380     }
       
  1381 
       
  1382     if (err==Z_OK)
       
  1383         return iRead;
       
  1384     return err;
       
  1385 }
       
  1386 
       
  1387 
       
  1388 /*
       
  1389   Give the current position in uncompressed data
       
  1390 */
       
  1391 extern z_off_t ZEXPORT unztell (file)
       
  1392     unzFile file;
       
  1393 {
       
  1394     unz_s* s;
       
  1395     file_in_zip_read_info_s* pfile_in_zip_read_info;
       
  1396     if (file==NULL)
       
  1397         return UNZ_PARAMERROR;
       
  1398     s=(unz_s*)file;
       
  1399     pfile_in_zip_read_info=s->pfile_in_zip_read;
       
  1400 
       
  1401     if (pfile_in_zip_read_info==NULL)
       
  1402         return UNZ_PARAMERROR;
       
  1403 
       
  1404     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
       
  1405 }
       
  1406 
       
  1407 
       
  1408 /*
       
  1409   return 1 if the end of file was reached, 0 elsewhere
       
  1410 */
       
  1411 extern int ZEXPORT unzeof (file)
       
  1412     unzFile file;
       
  1413 {
       
  1414     unz_s* s;
       
  1415     file_in_zip_read_info_s* pfile_in_zip_read_info;
       
  1416     if (file==NULL)
       
  1417         return UNZ_PARAMERROR;
       
  1418     s=(unz_s*)file;
       
  1419     pfile_in_zip_read_info=s->pfile_in_zip_read;
       
  1420 
       
  1421     if (pfile_in_zip_read_info==NULL)
       
  1422         return UNZ_PARAMERROR;
       
  1423 
       
  1424     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
       
  1425         return 1;
       
  1426     else
       
  1427         return 0;
       
  1428 }
       
  1429 
       
  1430 
       
  1431 
       
  1432 /*
       
  1433   Read extra field from the current file (opened by unzOpenCurrentFile)
       
  1434   This is the local-header version of the extra field (sometimes, there is
       
  1435     more info in the local-header version than in the central-header)
       
  1436 
       
  1437   if buf==NULL, it return the size of the local extra field that can be read
       
  1438 
       
  1439   if buf!=NULL, len is the size of the buffer, the extra header is copied in
       
  1440     buf.
       
  1441   the return value is the number of bytes copied in buf, or (if <0)
       
  1442     the error code
       
  1443 */
       
  1444 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
       
  1445     unzFile file;
       
  1446     voidp buf;
       
  1447     unsigned len;
       
  1448 {
       
  1449     unz_s* s;
       
  1450     file_in_zip_read_info_s* pfile_in_zip_read_info;
       
  1451     uInt read_now;
       
  1452     uLong size_to_read;
       
  1453 
       
  1454     if (file==NULL)
       
  1455         return UNZ_PARAMERROR;
       
  1456     s=(unz_s*)file;
       
  1457     pfile_in_zip_read_info=s->pfile_in_zip_read;
       
  1458 
       
  1459     if (pfile_in_zip_read_info==NULL)
       
  1460         return UNZ_PARAMERROR;
       
  1461 
       
  1462     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
       
  1463                 pfile_in_zip_read_info->pos_local_extrafield);
       
  1464 
       
  1465     if (buf==NULL)
       
  1466         return (int)size_to_read;
       
  1467 
       
  1468     if (len>size_to_read)
       
  1469         read_now = (uInt)size_to_read;
       
  1470     else
       
  1471         read_now = (uInt)len ;
       
  1472 
       
  1473     if (read_now==0)
       
  1474         return 0;
       
  1475 
       
  1476     if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
       
  1477               pfile_in_zip_read_info->filestream,
       
  1478               pfile_in_zip_read_info->offset_local_extrafield +
       
  1479               pfile_in_zip_read_info->pos_local_extrafield,
       
  1480               ZLIB_FILEFUNC_SEEK_SET)!=0)
       
  1481         return UNZ_ERRNO;
       
  1482 
       
  1483     if (ZREAD(pfile_in_zip_read_info->z_filefunc,
       
  1484               pfile_in_zip_read_info->filestream,
       
  1485               buf,read_now)!=read_now)
       
  1486         return UNZ_ERRNO;
       
  1487 
       
  1488     return (int)read_now;
       
  1489 }
       
  1490 
       
  1491 /*
       
  1492   Close the file in zip opened with unzipOpenCurrentFile
       
  1493   Return UNZ_CRCERROR if all the file was read but the CRC is not good
       
  1494 */
       
  1495 extern int ZEXPORT unzCloseCurrentFile (file)
       
  1496     unzFile file;
       
  1497 {
       
  1498     int err=UNZ_OK;
       
  1499 
       
  1500     unz_s* s;
       
  1501     file_in_zip_read_info_s* pfile_in_zip_read_info;
       
  1502     if (file==NULL)
       
  1503         return UNZ_PARAMERROR;
       
  1504     s=(unz_s*)file;
       
  1505     pfile_in_zip_read_info=s->pfile_in_zip_read;
       
  1506 
       
  1507     if (pfile_in_zip_read_info==NULL)
       
  1508         return UNZ_PARAMERROR;
       
  1509 
       
  1510 
       
  1511     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
       
  1512         (!pfile_in_zip_read_info->raw))
       
  1513     {
       
  1514         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
       
  1515             err=UNZ_CRCERROR;
       
  1516     }
       
  1517 
       
  1518 
       
  1519     TRYFREE(pfile_in_zip_read_info->read_buffer);
       
  1520     pfile_in_zip_read_info->read_buffer = NULL;
       
  1521     if (pfile_in_zip_read_info->stream_initialised)
       
  1522         inflateEnd(&pfile_in_zip_read_info->stream);
       
  1523 
       
  1524     pfile_in_zip_read_info->stream_initialised = 0;
       
  1525     TRYFREE(pfile_in_zip_read_info);
       
  1526 
       
  1527     s->pfile_in_zip_read=NULL;
       
  1528 
       
  1529     return err;
       
  1530 }
       
  1531 
       
  1532 
       
  1533 /*
       
  1534   Get the global comment string of the ZipFile, in the szComment buffer.
       
  1535   uSizeBuf is the size of the szComment buffer.
       
  1536   return the number of byte copied or an error code <0
       
  1537 */
       
  1538 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
       
  1539     unzFile file;
       
  1540     char *szComment;
       
  1541     uLong uSizeBuf;
       
  1542 {
       
  1543     unz_s* s;
       
  1544     uLong uReadThis ;
       
  1545     if (file==NULL)
       
  1546         return UNZ_PARAMERROR;
       
  1547     s=(unz_s*)file;
       
  1548 
       
  1549     uReadThis = uSizeBuf;
       
  1550     if (uReadThis>s->gi.size_comment)
       
  1551         uReadThis = s->gi.size_comment;
       
  1552 
       
  1553     if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
       
  1554         return UNZ_ERRNO;
       
  1555 
       
  1556     if (uReadThis>0)
       
  1557     {
       
  1558       *szComment='\0';
       
  1559       if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
       
  1560         return UNZ_ERRNO;
       
  1561     }
       
  1562 
       
  1563     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
       
  1564         *(szComment+s->gi.size_comment)='\0';
       
  1565     return (int)uReadThis;
       
  1566 }
       
  1567 
       
  1568 /* Additions by RX '2004 */
       
  1569 extern uLong ZEXPORT unzGetOffset (file)
       
  1570     unzFile file;
       
  1571 {
       
  1572     unz_s* s;
       
  1573 
       
  1574     if (file==NULL)
       
  1575           return UNZ_PARAMERROR;
       
  1576     s=(unz_s*)file;
       
  1577     if (!s->current_file_ok)
       
  1578       return 0;
       
  1579     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
       
  1580       if (s->num_file==s->gi.number_entry)
       
  1581          return 0;
       
  1582     return s->pos_in_central_dir;
       
  1583 }
       
  1584 
       
  1585 extern int ZEXPORT unzSetOffset (file, pos)
       
  1586         unzFile file;
       
  1587         uLong pos;
       
  1588 {
       
  1589     unz_s* s;
       
  1590     int err;
       
  1591 
       
  1592     if (file==NULL)
       
  1593         return UNZ_PARAMERROR;
       
  1594     s=(unz_s*)file;
       
  1595 
       
  1596     s->pos_in_central_dir = pos;
       
  1597     s->num_file = s->gi.number_entry;      /* hack */
       
  1598     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
       
  1599                                               &s->cur_file_info_internal,
       
  1600                                               NULL,0,NULL,0,NULL,0);
       
  1601     s->current_file_ok = (err == UNZ_OK);
       
  1602     return err;
       
  1603 }