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