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