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