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