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