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