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