• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #if defined(USE_SYSTEM_ZLIB)
42 #include <zlib.h>
43 #else
44 #include "third_party/zlib/zlib.h"
45 #endif
46 #include "unzip.h"
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 unsigned long* 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;
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;
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         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
616             err=UNZ_ERRNO;
617         else if (uMagic!=0x02014b50)
618             err=UNZ_BADZIPFILE;
619     }
620 
621     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
622         err=UNZ_ERRNO;
623 
624     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
625         err=UNZ_ERRNO;
626 
627     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
628         err=UNZ_ERRNO;
629 
630     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
631         err=UNZ_ERRNO;
632 
633     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
634         err=UNZ_ERRNO;
635 
636     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
637 
638     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
639         err=UNZ_ERRNO;
640 
641     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
642         err=UNZ_ERRNO;
643 
644     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
645         err=UNZ_ERRNO;
646 
647     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
648         err=UNZ_ERRNO;
649 
650     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
651         err=UNZ_ERRNO;
652 
653     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
654         err=UNZ_ERRNO;
655 
656     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
657         err=UNZ_ERRNO;
658 
659     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
660         err=UNZ_ERRNO;
661 
662     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
663         err=UNZ_ERRNO;
664 
665     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
666         err=UNZ_ERRNO;
667 
668     lSeek+=file_info.size_filename;
669     if ((err==UNZ_OK) && (szFileName!=NULL))
670     {
671         uLong uSizeRead ;
672         if (file_info.size_filename<fileNameBufferSize)
673         {
674             *(szFileName+file_info.size_filename)='\0';
675             uSizeRead = file_info.size_filename;
676         }
677         else
678             uSizeRead = fileNameBufferSize;
679 
680         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
681             if (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
682                 err=UNZ_ERRNO;
683         lSeek -= uSizeRead;
684     }
685 
686 
687     if ((err==UNZ_OK) && (extraField!=NULL))
688     {
689         uLong uSizeRead ;
690         if (file_info.size_file_extra<extraFieldBufferSize)
691             uSizeRead = file_info.size_file_extra;
692         else
693             uSizeRead = extraFieldBufferSize;
694 
695         if (lSeek!=0) {
696             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
697                 lSeek=0;
698             else
699                 err=UNZ_ERRNO;
700         }
701         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
702             if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
703                 err=UNZ_ERRNO;
704         lSeek += file_info.size_file_extra - uSizeRead;
705     }
706     else
707         lSeek+=file_info.size_file_extra;
708 
709 
710     if ((err==UNZ_OK) && (szComment!=NULL))
711     {
712         uLong uSizeRead ;
713         if (file_info.size_file_comment<commentBufferSize)
714         {
715             *(szComment+file_info.size_file_comment)='\0';
716             uSizeRead = file_info.size_file_comment;
717         }
718         else
719             uSizeRead = commentBufferSize;
720 
721         if (lSeek!=0) {
722             if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
723                 lSeek=0;
724             else
725                 err=UNZ_ERRNO;
726         }
727         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
728             if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
729                 err=UNZ_ERRNO;
730         lSeek+=file_info.size_file_comment - uSizeRead;
731     }
732     else
733         lSeek+=file_info.size_file_comment;
734 
735     if ((err==UNZ_OK) && (pfile_info!=NULL))
736         *pfile_info=file_info;
737 
738     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
739         *pfile_info_internal=file_info_internal;
740 
741     return err;
742 }
743 
744 
745 
746 /*
747   Write info about the ZipFile in the *pglobal_info structure.
748   No preparation of the structure is needed
749   return UNZ_OK if there is no problem.
750 */
751 extern int ZEXPORT unzGetCurrentFileInfo (file,
752                                           pfile_info,
753                                           szFileName, fileNameBufferSize,
754                                           extraField, extraFieldBufferSize,
755                                           szComment,  commentBufferSize)
756     unzFile file;
757     unz_file_info *pfile_info;
758     char *szFileName;
759     uLong fileNameBufferSize;
760     void *extraField;
761     uLong extraFieldBufferSize;
762     char *szComment;
763     uLong commentBufferSize;
764 {
765     return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
766                                                 szFileName,fileNameBufferSize,
767                                                 extraField,extraFieldBufferSize,
768                                                 szComment,commentBufferSize);
769 }
770 
771 /*
772   Set the current file of the zipfile to the first file.
773   return UNZ_OK if there is no problem
774 */
775 extern int ZEXPORT unzGoToFirstFile (file)
776     unzFile file;
777 {
778     int err=UNZ_OK;
779     unz_s* s;
780     if (file==NULL)
781         return UNZ_PARAMERROR;
782     s=(unz_s*)file;
783     s->pos_in_central_dir=s->offset_central_dir;
784     s->num_file=0;
785     err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
786                                              &s->cur_file_info_internal,
787                                              NULL,0,NULL,0,NULL,0);
788     s->current_file_ok = (err == UNZ_OK);
789     return err;
790 }
791 
792 /*
793   Set the current file of the zipfile to the next file.
794   return UNZ_OK if there is no problem
795   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
796 */
797 extern int ZEXPORT unzGoToNextFile (file)
798     unzFile file;
799 {
800     unz_s* s;
801     int err;
802 
803     if (file==NULL)
804         return UNZ_PARAMERROR;
805     s=(unz_s*)file;
806     if (!s->current_file_ok)
807         return UNZ_END_OF_LIST_OF_FILE;
808     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
809       if (s->num_file+1==s->gi.number_entry)
810         return UNZ_END_OF_LIST_OF_FILE;
811 
812     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
813             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
814     s->num_file++;
815     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
816                                                &s->cur_file_info_internal,
817                                                NULL,0,NULL,0,NULL,0);
818     s->current_file_ok = (err == UNZ_OK);
819     return err;
820 }
821 
822 
823 /*
824   Try locate the file szFileName in the zipfile.
825   For the iCaseSensitivity signification, see unzipStringFileNameCompare
826 
827   return value :
828   UNZ_OK if the file is found. It becomes the current file.
829   UNZ_END_OF_LIST_OF_FILE if the file is not found
830 */
831 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
832     unzFile file;
833     const char *szFileName;
834     int iCaseSensitivity;
835 {
836     unz_s* s;
837     int err;
838 
839     /* We remember the 'current' position in the file so that we can jump
840      * back there if we fail.
841      */
842     unz_file_info cur_file_infoSaved;
843     unz_file_info_internal cur_file_info_internalSaved;
844     uLong num_fileSaved;
845     uLong pos_in_central_dirSaved;
846 
847 
848     if (file==NULL)
849         return UNZ_PARAMERROR;
850 
851     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
852         return UNZ_PARAMERROR;
853 
854     s=(unz_s*)file;
855     if (!s->current_file_ok)
856         return UNZ_END_OF_LIST_OF_FILE;
857 
858     /* Save the current state */
859     num_fileSaved = s->num_file;
860     pos_in_central_dirSaved = s->pos_in_central_dir;
861     cur_file_infoSaved = s->cur_file_info;
862     cur_file_info_internalSaved = s->cur_file_info_internal;
863 
864     err = unzGoToFirstFile(file);
865 
866     while (err == UNZ_OK)
867     {
868         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
869         err = unzGetCurrentFileInfo(file,NULL,
870                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
871                                     NULL,0,NULL,0);
872         if (err == UNZ_OK)
873         {
874             if (unzStringFileNameCompare(szCurrentFileName,
875                                             szFileName,iCaseSensitivity)==0)
876                 return UNZ_OK;
877             err = unzGoToNextFile(file);
878         }
879     }
880 
881     /* We failed, so restore the state of the 'current file' to where we
882      * were.
883      */
884     s->num_file = num_fileSaved ;
885     s->pos_in_central_dir = pos_in_central_dirSaved ;
886     s->cur_file_info = cur_file_infoSaved;
887     s->cur_file_info_internal = cur_file_info_internalSaved;
888     return err;
889 }
890 
891 
892 /*
893 ///////////////////////////////////////////
894 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
895 // I need random access
896 //
897 // Further optimization could be realized by adding an ability
898 // to cache the directory in memory. The goal being a single
899 // comprehensive file read to put the file I need in a memory.
900 */
901 
902 /*
903 typedef struct unz_file_pos_s
904 {
905     uLong pos_in_zip_directory;   // offset in file
906     uLong num_of_file;            // # of file
907 } unz_file_pos;
908 */
909 
910 extern int ZEXPORT unzGetFilePos(file, file_pos)
911     unzFile file;
912     unz_file_pos* file_pos;
913 {
914     unz_s* s;
915 
916     if (file==NULL || file_pos==NULL)
917         return UNZ_PARAMERROR;
918     s=(unz_s*)file;
919     if (!s->current_file_ok)
920         return UNZ_END_OF_LIST_OF_FILE;
921 
922     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
923     file_pos->num_of_file           = s->num_file;
924 
925     return UNZ_OK;
926 }
927 
928 extern int ZEXPORT unzGoToFilePos(file, file_pos)
929     unzFile file;
930     unz_file_pos* file_pos;
931 {
932     unz_s* s;
933     int err;
934 
935     if (file==NULL || file_pos==NULL)
936         return UNZ_PARAMERROR;
937     s=(unz_s*)file;
938 
939     /* jump to the right spot */
940     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
941     s->num_file           = file_pos->num_of_file;
942 
943     /* set the current file */
944     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
945                                                &s->cur_file_info_internal,
946                                                NULL,0,NULL,0,NULL,0);
947     /* return results */
948     s->current_file_ok = (err == UNZ_OK);
949     return err;
950 }
951 
952 /*
953 // Unzip Helper Functions - should be here?
954 ///////////////////////////////////////////
955 */
956 
957 /*
958   Read the local header of the current zipfile
959   Check the coherency of the local header and info in the end of central
960         directory about this file
961   store in *piSizeVar the size of extra info in local header
962         (filename and size of extra field data)
963 */
unzlocal_CheckCurrentFileCoherencyHeader(s,piSizeVar,poffset_local_extrafield,psize_local_extrafield)964 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
965                                                     poffset_local_extrafield,
966                                                     psize_local_extrafield)
967     unz_s* s;
968     uInt* piSizeVar;
969     uLong *poffset_local_extrafield;
970     uInt  *psize_local_extrafield;
971 {
972     uLong uMagic,uData,uFlags;
973     uLong size_filename;
974     uLong size_extra_field;
975     int err=UNZ_OK;
976 
977     *piSizeVar = 0;
978     *poffset_local_extrafield = 0;
979     *psize_local_extrafield = 0;
980 
981     if (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
982                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
983         return UNZ_ERRNO;
984 
985 
986     if (err==UNZ_OK) {
987         if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
988             err=UNZ_ERRNO;
989         else if (uMagic!=0x04034b50)
990             err=UNZ_BADZIPFILE;
991     }
992 
993     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
994         err=UNZ_ERRNO;
995 /*
996     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
997         err=UNZ_BADZIPFILE;
998 */
999     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
1000         err=UNZ_ERRNO;
1001 
1002     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1003         err=UNZ_ERRNO;
1004     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1005         err=UNZ_BADZIPFILE;
1006 
1007     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1008                          (s->cur_file_info.compression_method!=Z_DEFLATED))
1009         err=UNZ_BADZIPFILE;
1010 
1011     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1012         err=UNZ_ERRNO;
1013 
1014     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1015         err=UNZ_ERRNO;
1016     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
1017                               ((uFlags & 8)==0))
1018         err=UNZ_BADZIPFILE;
1019 
1020     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1021         err=UNZ_ERRNO;
1022     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
1023                               ((uFlags & 8)==0))
1024         err=UNZ_BADZIPFILE;
1025 
1026     if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1027         err=UNZ_ERRNO;
1028     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
1029                               ((uFlags & 8)==0))
1030         err=UNZ_BADZIPFILE;
1031 
1032 
1033     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1034         err=UNZ_ERRNO;
1035     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1036         err=UNZ_BADZIPFILE;
1037 
1038     *piSizeVar += (uInt)size_filename;
1039 
1040     if (unzlocal_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1041         err=UNZ_ERRNO;
1042     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1043                                     SIZEZIPLOCALHEADER + size_filename;
1044     *psize_local_extrafield = (uInt)size_extra_field;
1045 
1046     *piSizeVar += (uInt)size_extra_field;
1047 
1048     return err;
1049 }
1050 
1051 /*
1052   Open for reading data the current file in the zipfile.
1053   If there is no error and the file is opened, the return value is UNZ_OK.
1054 */
1055 extern int ZEXPORT unzOpenCurrentFile3 (file, method, level, raw, password)
1056     unzFile file;
1057     int* method;
1058     int* level;
1059     int raw;
1060     const char* password;
1061 {
1062     int err=UNZ_OK;
1063     uInt iSizeVar;
1064     unz_s* s;
1065     file_in_zip_read_info_s* pfile_in_zip_read_info;
1066     uLong offset_local_extrafield;  /* offset of the local extra field */
1067     uInt  size_local_extrafield;    /* size of the local extra field */
1068 #    ifndef NOUNCRYPT
1069     char source[12];
1070 #    else
1071     if (password != NULL)
1072         return UNZ_PARAMERROR;
1073 #    endif
1074 
1075     if (file==NULL)
1076         return UNZ_PARAMERROR;
1077     s=(unz_s*)file;
1078     if (!s->current_file_ok)
1079         return UNZ_PARAMERROR;
1080 
1081     if (s->pfile_in_zip_read != NULL)
1082         unzCloseCurrentFile(file);
1083 
1084     if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1085                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1086         return UNZ_BADZIPFILE;
1087 
1088     pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1089                                         ALLOC(sizeof(file_in_zip_read_info_s));
1090     if (pfile_in_zip_read_info==NULL)
1091         return UNZ_INTERNALERROR;
1092 
1093     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1094     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1095     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1096     pfile_in_zip_read_info->pos_local_extrafield=0;
1097     pfile_in_zip_read_info->raw=raw;
1098 
1099     if (pfile_in_zip_read_info->read_buffer==NULL)
1100     {
1101         TRYFREE(pfile_in_zip_read_info);
1102         return UNZ_INTERNALERROR;
1103     }
1104 
1105     pfile_in_zip_read_info->stream_initialised=0;
1106 
1107     if (method!=NULL)
1108         *method = (int)s->cur_file_info.compression_method;
1109 
1110     if (level!=NULL)
1111     {
1112         *level = 6;
1113         switch (s->cur_file_info.flag & 0x06)
1114         {
1115           case 6 : *level = 1; break;
1116           case 4 : *level = 2; break;
1117           case 2 : *level = 9; break;
1118         }
1119     }
1120 
1121     if ((s->cur_file_info.compression_method!=0) &&
1122         (s->cur_file_info.compression_method!=Z_DEFLATED))
1123         err=UNZ_BADZIPFILE;
1124 
1125     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1126     pfile_in_zip_read_info->crc32=0;
1127     pfile_in_zip_read_info->compression_method =
1128             s->cur_file_info.compression_method;
1129     pfile_in_zip_read_info->filestream=s->filestream;
1130     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1131     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1132 
1133     pfile_in_zip_read_info->stream.total_out = 0;
1134 
1135     if ((s->cur_file_info.compression_method==Z_DEFLATED) &&
1136         (!raw))
1137     {
1138       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1139       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1140       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1141       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1142       pfile_in_zip_read_info->stream.avail_in = 0;
1143 
1144       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1145       if (err == Z_OK)
1146         pfile_in_zip_read_info->stream_initialised=1;
1147       else
1148       {
1149         TRYFREE(pfile_in_zip_read_info);
1150         return err;
1151       }
1152         /* windowBits is passed < 0 to tell that there is no zlib header.
1153          * Note that in this case inflate *requires* an extra "dummy" byte
1154          * after the compressed stream in order to complete decompression and
1155          * return Z_STREAM_END.
1156          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1157          * size of both compressed and uncompressed data
1158          */
1159     }
1160     pfile_in_zip_read_info->rest_read_compressed =
1161             s->cur_file_info.compressed_size ;
1162     pfile_in_zip_read_info->rest_read_uncompressed =
1163             s->cur_file_info.uncompressed_size ;
1164 
1165 
1166     pfile_in_zip_read_info->pos_in_zipfile =
1167             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1168               iSizeVar;
1169 
1170     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1171 
1172     s->pfile_in_zip_read = pfile_in_zip_read_info;
1173 
1174 #    ifndef NOUNCRYPT
1175     if (password != NULL)
1176     {
1177         int i;
1178         s->pcrc_32_tab = get_crc_table();
1179         init_keys(password,s->keys,s->pcrc_32_tab);
1180         if (ZSEEK(s->z_filefunc, s->filestream,
1181                   s->pfile_in_zip_read->pos_in_zipfile +
1182                      s->pfile_in_zip_read->byte_before_the_zipfile,
1183                   SEEK_SET)!=0)
1184             return UNZ_INTERNALERROR;
1185         if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12)
1186             return UNZ_INTERNALERROR;
1187 
1188         for (i = 0; i<12; i++)
1189             zdecode(s->keys,s->pcrc_32_tab,source[i]);
1190 
1191         s->pfile_in_zip_read->pos_in_zipfile+=12;
1192         s->encrypted=1;
1193     }
1194 #    endif
1195 
1196 
1197     return UNZ_OK;
1198 }
1199 
1200 extern int ZEXPORT unzOpenCurrentFile (file)
1201     unzFile file;
1202 {
1203     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1204 }
1205 
1206 extern int ZEXPORT unzOpenCurrentFilePassword (file, password)
1207     unzFile file;
1208     const char* password;
1209 {
1210     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1211 }
1212 
1213 extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw)
1214     unzFile file;
1215     int* method;
1216     int* level;
1217     int raw;
1218 {
1219     return unzOpenCurrentFile3(file, method, level, raw, NULL);
1220 }
1221 
1222 /*
1223   Read bytes from the current file.
1224   buf contain buffer where data must be copied
1225   len the size of buf.
1226 
1227   return the number of byte copied if somes bytes are copied
1228   return 0 if the end of file was reached
1229   return <0 with error code if there is an error
1230     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1231 */
1232 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
1233     unzFile file;
1234     voidp buf;
1235     unsigned len;
1236 {
1237     int err=UNZ_OK;
1238     uInt iRead = 0;
1239     unz_s* s;
1240     file_in_zip_read_info_s* pfile_in_zip_read_info;
1241     if (file==NULL)
1242         return UNZ_PARAMERROR;
1243     s=(unz_s*)file;
1244     pfile_in_zip_read_info=s->pfile_in_zip_read;
1245 
1246     if (pfile_in_zip_read_info==NULL)
1247         return UNZ_PARAMERROR;
1248 
1249 
1250     if ((pfile_in_zip_read_info->read_buffer == NULL))
1251         return UNZ_END_OF_LIST_OF_FILE;
1252     if (len==0)
1253         return 0;
1254 
1255     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1256 
1257     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1258 
1259     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1260         (!(pfile_in_zip_read_info->raw)))
1261         pfile_in_zip_read_info->stream.avail_out =
1262             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1263 
1264     if ((len>pfile_in_zip_read_info->rest_read_compressed+
1265            pfile_in_zip_read_info->stream.avail_in) &&
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_compressed+
1269             pfile_in_zip_read_info->stream.avail_in;
1270 
1271     while (pfile_in_zip_read_info->stream.avail_out>0)
1272     {
1273         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1274             (pfile_in_zip_read_info->rest_read_compressed>0))
1275         {
1276             uInt uReadThis = UNZ_BUFSIZE;
1277             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1278                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1279             if (uReadThis == 0)
1280                 return UNZ_EOF;
1281             if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1282                       pfile_in_zip_read_info->filestream,
1283                       pfile_in_zip_read_info->pos_in_zipfile +
1284                          pfile_in_zip_read_info->byte_before_the_zipfile,
1285                          ZLIB_FILEFUNC_SEEK_SET)!=0)
1286                 return UNZ_ERRNO;
1287             if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1288                       pfile_in_zip_read_info->filestream,
1289                       pfile_in_zip_read_info->read_buffer,
1290                       uReadThis)!=uReadThis)
1291                 return UNZ_ERRNO;
1292 
1293 
1294 #            ifndef NOUNCRYPT
1295             if(s->encrypted)
1296             {
1297                 uInt i;
1298                 for(i=0;i<uReadThis;i++)
1299                   pfile_in_zip_read_info->read_buffer[i] =
1300                       zdecode(s->keys,s->pcrc_32_tab,
1301                               pfile_in_zip_read_info->read_buffer[i]);
1302             }
1303 #            endif
1304 
1305 
1306             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1307 
1308             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1309 
1310             pfile_in_zip_read_info->stream.next_in =
1311                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1312             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1313         }
1314 
1315         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1316         {
1317             uInt uDoCopy,i ;
1318 
1319             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1320                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1321                 return (iRead==0) ? UNZ_EOF : iRead;
1322 
1323             if (pfile_in_zip_read_info->stream.avail_out <
1324                             pfile_in_zip_read_info->stream.avail_in)
1325                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1326             else
1327                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1328 
1329             for (i=0;i<uDoCopy;i++)
1330                 *(pfile_in_zip_read_info->stream.next_out+i) =
1331                         *(pfile_in_zip_read_info->stream.next_in+i);
1332 
1333             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1334                                 pfile_in_zip_read_info->stream.next_out,
1335                                 uDoCopy);
1336             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1337             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1338             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1339             pfile_in_zip_read_info->stream.next_out += uDoCopy;
1340             pfile_in_zip_read_info->stream.next_in += uDoCopy;
1341             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1342             iRead += uDoCopy;
1343         }
1344         else
1345         {
1346             uLong uTotalOutBefore,uTotalOutAfter;
1347             const Bytef *bufBefore;
1348             uLong uOutThis;
1349             int flush=Z_SYNC_FLUSH;
1350 
1351             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1352             bufBefore = pfile_in_zip_read_info->stream.next_out;
1353 
1354             /*
1355             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1356                      pfile_in_zip_read_info->stream.avail_out) &&
1357                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1358                 flush = Z_FINISH;
1359             */
1360             err=inflate(&pfile_in_zip_read_info->stream,flush);
1361 
1362             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1363               err = Z_DATA_ERROR;
1364 
1365             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1366             uOutThis = uTotalOutAfter-uTotalOutBefore;
1367 
1368             pfile_in_zip_read_info->crc32 =
1369                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1370                         (uInt)(uOutThis));
1371 
1372             pfile_in_zip_read_info->rest_read_uncompressed -=
1373                 uOutThis;
1374 
1375             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1376 
1377             if (err==Z_STREAM_END)
1378                 return (iRead==0) ? UNZ_EOF : iRead;
1379             if (err!=Z_OK)
1380                 break;
1381         }
1382     }
1383 
1384     if (err==Z_OK)
1385         return iRead;
1386     return err;
1387 }
1388 
1389 
1390 /*
1391   Give the current position in uncompressed data
1392 */
1393 extern z_off_t ZEXPORT unztell (file)
1394     unzFile file;
1395 {
1396     unz_s* s;
1397     file_in_zip_read_info_s* pfile_in_zip_read_info;
1398     if (file==NULL)
1399         return UNZ_PARAMERROR;
1400     s=(unz_s*)file;
1401     pfile_in_zip_read_info=s->pfile_in_zip_read;
1402 
1403     if (pfile_in_zip_read_info==NULL)
1404         return UNZ_PARAMERROR;
1405 
1406     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1407 }
1408 
1409 
1410 /*
1411   return 1 if the end of file was reached, 0 elsewhere
1412 */
1413 extern int ZEXPORT unzeof (file)
1414     unzFile file;
1415 {
1416     unz_s* s;
1417     file_in_zip_read_info_s* pfile_in_zip_read_info;
1418     if (file==NULL)
1419         return UNZ_PARAMERROR;
1420     s=(unz_s*)file;
1421     pfile_in_zip_read_info=s->pfile_in_zip_read;
1422 
1423     if (pfile_in_zip_read_info==NULL)
1424         return UNZ_PARAMERROR;
1425 
1426     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1427         return 1;
1428     else
1429         return 0;
1430 }
1431 
1432 
1433 
1434 /*
1435   Read extra field from the current file (opened by unzOpenCurrentFile)
1436   This is the local-header version of the extra field (sometimes, there is
1437     more info in the local-header version than in the central-header)
1438 
1439   if buf==NULL, it return the size of the local extra field that can be read
1440 
1441   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1442     buf.
1443   the return value is the number of bytes copied in buf, or (if <0)
1444     the error code
1445 */
1446 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1447     unzFile file;
1448     voidp buf;
1449     unsigned len;
1450 {
1451     unz_s* s;
1452     file_in_zip_read_info_s* pfile_in_zip_read_info;
1453     uInt read_now;
1454     uLong size_to_read;
1455 
1456     if (file==NULL)
1457         return UNZ_PARAMERROR;
1458     s=(unz_s*)file;
1459     pfile_in_zip_read_info=s->pfile_in_zip_read;
1460 
1461     if (pfile_in_zip_read_info==NULL)
1462         return UNZ_PARAMERROR;
1463 
1464     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1465                 pfile_in_zip_read_info->pos_local_extrafield);
1466 
1467     if (buf==NULL)
1468         return (int)size_to_read;
1469 
1470     if (len>size_to_read)
1471         read_now = (uInt)size_to_read;
1472     else
1473         read_now = (uInt)len ;
1474 
1475     if (read_now==0)
1476         return 0;
1477 
1478     if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1479               pfile_in_zip_read_info->filestream,
1480               pfile_in_zip_read_info->offset_local_extrafield +
1481               pfile_in_zip_read_info->pos_local_extrafield,
1482               ZLIB_FILEFUNC_SEEK_SET)!=0)
1483         return UNZ_ERRNO;
1484 
1485     if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1486               pfile_in_zip_read_info->filestream,
1487               buf,read_now)!=read_now)
1488         return UNZ_ERRNO;
1489 
1490     return (int)read_now;
1491 }
1492 
1493 /*
1494   Close the file in zip opened with unzipOpenCurrentFile
1495   Return UNZ_CRCERROR if all the file was read but the CRC is not good
1496 */
1497 extern int ZEXPORT unzCloseCurrentFile (file)
1498     unzFile file;
1499 {
1500     int err=UNZ_OK;
1501 
1502     unz_s* s;
1503     file_in_zip_read_info_s* pfile_in_zip_read_info;
1504     if (file==NULL)
1505         return UNZ_PARAMERROR;
1506     s=(unz_s*)file;
1507     pfile_in_zip_read_info=s->pfile_in_zip_read;
1508 
1509     if (pfile_in_zip_read_info==NULL)
1510         return UNZ_PARAMERROR;
1511 
1512 
1513     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1514         (!pfile_in_zip_read_info->raw))
1515     {
1516         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1517             err=UNZ_CRCERROR;
1518     }
1519 
1520 
1521     TRYFREE(pfile_in_zip_read_info->read_buffer);
1522     pfile_in_zip_read_info->read_buffer = NULL;
1523     if (pfile_in_zip_read_info->stream_initialised)
1524         inflateEnd(&pfile_in_zip_read_info->stream);
1525 
1526     pfile_in_zip_read_info->stream_initialised = 0;
1527     TRYFREE(pfile_in_zip_read_info);
1528 
1529     s->pfile_in_zip_read=NULL;
1530 
1531     return err;
1532 }
1533 
1534 
1535 /*
1536   Get the global comment string of the ZipFile, in the szComment buffer.
1537   uSizeBuf is the size of the szComment buffer.
1538   return the number of byte copied or an error code <0
1539 */
1540 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1541     unzFile file;
1542     char *szComment;
1543     uLong uSizeBuf;
1544 {
1545     //int err=UNZ_OK;
1546     unz_s* s;
1547     uLong uReadThis ;
1548     if (file==NULL)
1549         return UNZ_PARAMERROR;
1550     s=(unz_s*)file;
1551 
1552     uReadThis = uSizeBuf;
1553     if (uReadThis>s->gi.size_comment)
1554         uReadThis = s->gi.size_comment;
1555 
1556     if (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1557         return UNZ_ERRNO;
1558 
1559     if (uReadThis>0)
1560     {
1561       *szComment='\0';
1562       if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1563         return UNZ_ERRNO;
1564     }
1565 
1566     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1567         *(szComment+s->gi.size_comment)='\0';
1568     return (int)uReadThis;
1569 }
1570 
1571 /* Additions by RX '2004 */
1572 extern uLong ZEXPORT unzGetOffset (file)
1573     unzFile file;
1574 {
1575     unz_s* s;
1576 
1577     if (file==NULL)
1578           return UNZ_PARAMERROR;
1579     s=(unz_s*)file;
1580     if (!s->current_file_ok)
1581       return 0;
1582     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1583       if (s->num_file==s->gi.number_entry)
1584          return 0;
1585     return s->pos_in_central_dir;
1586 }
1587 
1588 extern int ZEXPORT unzSetOffset (file, pos)
1589         unzFile file;
1590         uLong pos;
1591 {
1592     unz_s* s;
1593     int err;
1594 
1595     if (file==NULL)
1596         return UNZ_PARAMERROR;
1597     s=(unz_s*)file;
1598 
1599     s->pos_in_central_dir = pos;
1600     s->num_file = s->gi.number_entry;      /* hack */
1601     err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1602                                               &s->cur_file_info_internal,
1603                                               NULL,0,NULL,0,NULL,0);
1604     s->current_file_ok = (err == UNZ_OK);
1605     return err;
1606 }
1607