xref: /netbsd-src/common/dist/zlib/contrib/minizip/unzip.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /* unzip.c -- IO for uncompress .zip files using zlib
2    Version 1.1, February 14h, 2010
3    part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
4 
5          Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
6 
7          Modifications of Unzip for Zip64
8          Copyright (C) 2007-2008 Even Rouault
9 
10          Modifications for Zip64 support on both zip and unzip
11          Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
12 
13          For more info read MiniZip_info.txt
14 
15 
16   ------------------------------------------------------------------------------------
17   Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
18   compatibility with older software. The following is from the original crypt.c.
19   Code woven in by Terry Thorsen 1/2003.
20 
21   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
22 
23   See the accompanying file LICENSE, version 2000-Apr-09 or later
24   (the contents of which are also included in zip.h) for terms of use.
25   If, for some reason, all these files are missing, the Info-ZIP license
26   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
27 
28         crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
29 
30   The encryption/decryption parts of this source code (as opposed to the
31   non-echoing password parts) were originally written in Europe.  The
32   whole source package can be freely distributed, including from the USA.
33   (Prior to January 2000, re-export from the US was a violation of US law.)
34 
35         This encryption code is a direct transcription of the algorithm from
36   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
37   file (appnote.txt) is distributed with the PKZIP program (even in the
38   version without encryption capabilities).
39 
40         ------------------------------------------------------------------------------------
41 
42         Changes in unzip.c
43 
44         2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos
45   2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz*
46   2007-2008 - Even Rouault - Remove old C style function prototypes
47   2007-2008 - Even Rouault - Add unzip support for ZIP64
48 
49         Copyright (C) 2007-2008 Even Rouault
50 
51 
52         Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
53   Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G
54                                 should only read the compressed/uncompressed size from the Zip64 format if
55                                 the size from normal header was 0xFFFFFFFF
56   Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant
57         Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required)
58                                 Patch created by Daniel Borca
59 
60   Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
61 
62   Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson
63 
64 */
65 
66 
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 
71 #ifndef NOUNCRYPT
72         #define NOUNCRYPT
73 #endif
74 
75 #include "zlib.h"
76 #include "unzip.h"
77 
78 #ifdef STDC
79 #  include <stddef.h>
80 #  include <string.h>
81 #  include <stdlib.h>
82 #endif
83 #ifdef NO_ERRNO_H
84     extern int errno;
85 #else
86 #   include <errno.h>
87 #endif
88 
89 
90 #ifndef local
91 #  define local static
92 #endif
93 /* compile with -Dlocal if your debugger can't find static symbols */
94 
95 
96 #ifndef CASESENSITIVITYDEFAULT_NO
97 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
98 #    define CASESENSITIVITYDEFAULT_NO
99 #  endif
100 #endif
101 
102 
103 #ifndef UNZ_BUFSIZE
104 #define UNZ_BUFSIZE (16384)
105 #endif
106 
107 #ifndef UNZ_MAXFILENAMEINZIP
108 #define UNZ_MAXFILENAMEINZIP (256)
109 #endif
110 
111 #ifndef ALLOC
112 # define ALLOC(size) (malloc(size))
113 #endif
114 #ifndef TRYFREE
115 # define TRYFREE(p) { free(p);}
116 #endif
117 
118 #define SIZECENTRALDIRITEM (0x2e)
119 #define SIZEZIPLOCALHEADER (0x1e)
120 
121 
122 const char unz_copyright[] =
123    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
124 
125 /* unz_file_info_interntal contain internal info about a file in zipfile*/
126 typedef struct unz_file_info64_internal_s
127 {
128     ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
129 } unz_file_info64_internal;
130 
131 
132 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
133     when reading and decompress it */
134 typedef struct
135 {
136     char  *read_buffer;         /* internal buffer for compressed data */
137     z_stream stream;            /* zLib stream structure for inflate */
138 
139 #ifdef HAVE_BZIP2
140     bz_stream bstream;          /* bzLib stream structure for bziped */
141 #endif
142 
143     ZPOS64_T pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
144     uLong stream_initialised;   /* flag set if stream structure is initialised*/
145 
146     ZPOS64_T offset_local_extrafield;/* offset of the local extra field */
147     uInt  size_local_extrafield;/* size of the local extra field */
148     ZPOS64_T pos_local_extrafield;   /* position in the local extra field in read*/
149     ZPOS64_T total_out_64;
150 
151     uLong crc32;                /* crc32 of all data uncompressed */
152     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
153     ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
154     ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
155     zlib_filefunc64_32_def z_filefunc;
156     voidpf filestream;        /* io structore of the zipfile */
157     uLong compression_method;   /* compression method (0==store) */
158     ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
159     int   raw;
160 } file_in_zip64_read_info_s;
161 
162 
163 /* unz64_s contain internal information about the zipfile
164 */
165 typedef struct
166 {
167     zlib_filefunc64_32_def z_filefunc;
168     int is64bitOpenFunction;
169     voidpf filestream;        /* io structore of the zipfile */
170     unz_global_info64 gi;       /* public global information */
171     ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
172     ZPOS64_T num_file;             /* number of the current file in the zipfile*/
173     ZPOS64_T pos_in_central_dir;   /* pos of the current file in the central dir*/
174     ZPOS64_T current_file_ok;      /* flag about the usability of the current file*/
175     ZPOS64_T central_pos;          /* position of the beginning of the central dir*/
176 
177     ZPOS64_T size_central_dir;     /* size of the central directory  */
178     ZPOS64_T offset_central_dir;   /* offset of start of central directory with
179                                    respect to the starting disk number */
180 
181     unz_file_info64 cur_file_info; /* public info about the current file in zip*/
182     unz_file_info64_internal cur_file_info_internal; /* private info about it*/
183     file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
184                                         file if we are decompressing it */
185     int encrypted;
186 
187     int isZip64;
188 
189 #    ifndef NOUNCRYPT
190     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
191     const z_crc_t* pcrc_32_tab;
192 #    endif
193 } unz64_s;
194 
195 
196 #ifndef NOUNCRYPT
197 #include "crypt.h"
198 #endif
199 
200 /* ===========================================================================
201      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
202    for end of file.
203    IN assertion: the stream s has been successfully opened for reading.
204 */
205 
206 
207 local int unz64local_getByte OF((
208     const zlib_filefunc64_32_def* pzlib_filefunc_def,
209     voidpf filestream,
210     int *pi));
211 
212 local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)
213 {
214     unsigned char c;
215     int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
216     if (err==1)
217     {
218         *pi = (int)c;
219         return UNZ_OK;
220     }
221     else
222     {
223         if (ZERROR64(*pzlib_filefunc_def,filestream))
224             return UNZ_ERRNO;
225         else
226             return UNZ_EOF;
227     }
228 }
229 
230 
231 /* ===========================================================================
232    Reads a long in LSB order from the given gz_stream. Sets
233 */
234 local int unz64local_getShort OF((
235     const zlib_filefunc64_32_def* pzlib_filefunc_def,
236     voidpf filestream,
237     uLong *pX));
238 
239 local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def,
240                              voidpf filestream,
241                              uLong *pX)
242 {
243     uLong x ;
244     int i = 0;
245     int err;
246 
247     err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
248     x = (uLong)i;
249 
250     if (err==UNZ_OK)
251         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
252     x |= ((uLong)i)<<8;
253 
254     if (err==UNZ_OK)
255         *pX = x;
256     else
257         *pX = 0;
258     return err;
259 }
260 
261 local int unz64local_getLong OF((
262     const zlib_filefunc64_32_def* pzlib_filefunc_def,
263     voidpf filestream,
264     uLong *pX));
265 
266 local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def,
267                             voidpf filestream,
268                             uLong *pX)
269 {
270     uLong x ;
271     int i = 0;
272     int err;
273 
274     err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
275     x = (uLong)i;
276 
277     if (err==UNZ_OK)
278         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
279     x |= ((uLong)i)<<8;
280 
281     if (err==UNZ_OK)
282         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
283     x |= ((uLong)i)<<16;
284 
285     if (err==UNZ_OK)
286         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
287     x += ((uLong)i)<<24;
288 
289     if (err==UNZ_OK)
290         *pX = x;
291     else
292         *pX = 0;
293     return err;
294 }
295 
296 local int unz64local_getLong64 OF((
297     const zlib_filefunc64_32_def* pzlib_filefunc_def,
298     voidpf filestream,
299     ZPOS64_T *pX));
300 
301 
302 local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def,
303                             voidpf filestream,
304                             ZPOS64_T *pX)
305 {
306     ZPOS64_T x ;
307     int i = 0;
308     int err;
309 
310     err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
311     x = (ZPOS64_T)i;
312 
313     if (err==UNZ_OK)
314         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
315     x |= ((ZPOS64_T)i)<<8;
316 
317     if (err==UNZ_OK)
318         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
319     x |= ((ZPOS64_T)i)<<16;
320 
321     if (err==UNZ_OK)
322         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
323     x |= ((ZPOS64_T)i)<<24;
324 
325     if (err==UNZ_OK)
326         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
327     x |= ((ZPOS64_T)i)<<32;
328 
329     if (err==UNZ_OK)
330         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
331     x |= ((ZPOS64_T)i)<<40;
332 
333     if (err==UNZ_OK)
334         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
335     x |= ((ZPOS64_T)i)<<48;
336 
337     if (err==UNZ_OK)
338         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
339     x |= ((ZPOS64_T)i)<<56;
340 
341     if (err==UNZ_OK)
342         *pX = x;
343     else
344         *pX = 0;
345     return err;
346 }
347 
348 /* My own strcmpi / strcasecmp */
349 local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
350 {
351     for (;;)
352     {
353         char c1=*(fileName1++);
354         char c2=*(fileName2++);
355         if ((c1>='a') && (c1<='z'))
356             c1 -= 0x20;
357         if ((c2>='a') && (c2<='z'))
358             c2 -= 0x20;
359         if (c1=='\0')
360             return ((c2=='\0') ? 0 : -1);
361         if (c2=='\0')
362             return 1;
363         if (c1<c2)
364             return -1;
365         if (c1>c2)
366             return 1;
367     }
368 }
369 
370 
371 #ifdef  CASESENSITIVITYDEFAULT_NO
372 #define CASESENSITIVITYDEFAULTVALUE 2
373 #else
374 #define CASESENSITIVITYDEFAULTVALUE 1
375 #endif
376 
377 #ifndef STRCMPCASENOSENTIVEFUNCTION
378 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
379 #endif
380 
381 /*
382    Compare two filename (fileName1,fileName2).
383    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
384    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
385                                                                 or strcasecmp)
386    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
387         (like 1 on Unix, 2 on Windows)
388 
389 */
390 extern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,
391                                                  const char*  fileName2,
392                                                  int iCaseSensitivity)
393 
394 {
395     if (iCaseSensitivity==0)
396         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
397 
398     if (iCaseSensitivity==1)
399         return strcmp(fileName1,fileName2);
400 
401     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
402 }
403 
404 #ifndef BUFREADCOMMENT
405 #define BUFREADCOMMENT (0x400)
406 #endif
407 
408 /*
409   Locate the Central directory of a zipfile (at the end, just before
410     the global comment)
411 */
412 local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
413 local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
414 {
415     unsigned char* buf;
416     ZPOS64_T uSizeFile;
417     ZPOS64_T uBackRead;
418     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
419     ZPOS64_T uPosFound=0;
420 
421     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
422         return 0;
423 
424 
425     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
426 
427     if (uMaxBack>uSizeFile)
428         uMaxBack = uSizeFile;
429 
430     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
431     if (buf==NULL)
432         return 0;
433 
434     uBackRead = 4;
435     while (uBackRead<uMaxBack)
436     {
437         uLong uReadSize;
438         ZPOS64_T uReadPos ;
439         int i;
440         if (uBackRead+BUFREADCOMMENT>uMaxBack)
441             uBackRead = uMaxBack;
442         else
443             uBackRead+=BUFREADCOMMENT;
444         uReadPos = uSizeFile-uBackRead ;
445 
446         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
447                      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
448         if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
449             break;
450 
451         if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
452             break;
453 
454         for (i=(int)uReadSize-3; (i--)>0;)
455             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
456                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
457             {
458                 uPosFound = uReadPos+(unsigned)i;
459                 break;
460             }
461 
462         if (uPosFound!=0)
463             break;
464     }
465     TRYFREE(buf);
466     return uPosFound;
467 }
468 
469 
470 /*
471   Locate the Central directory 64 of a zipfile (at the end, just before
472     the global comment)
473 */
474 local ZPOS64_T unz64local_SearchCentralDir64 OF((
475     const zlib_filefunc64_32_def* pzlib_filefunc_def,
476     voidpf filestream));
477 
478 local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
479                                       voidpf filestream)
480 {
481     unsigned char* buf;
482     ZPOS64_T uSizeFile;
483     ZPOS64_T uBackRead;
484     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
485     ZPOS64_T uPosFound=0;
486     uLong uL;
487                 ZPOS64_T relativeOffset;
488 
489     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
490         return 0;
491 
492 
493     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
494 
495     if (uMaxBack>uSizeFile)
496         uMaxBack = uSizeFile;
497 
498     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
499     if (buf==NULL)
500         return 0;
501 
502     uBackRead = 4;
503     while (uBackRead<uMaxBack)
504     {
505         uLong uReadSize;
506         ZPOS64_T uReadPos;
507         int i;
508         if (uBackRead+BUFREADCOMMENT>uMaxBack)
509             uBackRead = uMaxBack;
510         else
511             uBackRead+=BUFREADCOMMENT;
512         uReadPos = uSizeFile-uBackRead ;
513 
514         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
515                      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
516         if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
517             break;
518 
519         if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
520             break;
521 
522         for (i=(int)uReadSize-3; (i--)>0;)
523             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
524                 ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
525             {
526                 uPosFound = uReadPos+(unsigned)i;
527                 break;
528             }
529 
530         if (uPosFound!=0)
531             break;
532     }
533     TRYFREE(buf);
534     if (uPosFound == 0)
535         return 0;
536 
537     /* Zip64 end of central directory locator */
538     if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
539         return 0;
540 
541     /* the signature, already checked */
542     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
543         return 0;
544 
545     /* number of the disk with the start of the zip64 end of  central directory */
546     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
547         return 0;
548     if (uL != 0)
549         return 0;
550 
551     /* relative offset of the zip64 end of central directory record */
552     if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
553         return 0;
554 
555     /* total number of disks */
556     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
557         return 0;
558     if (uL != 1)
559         return 0;
560 
561     /* Goto end of central directory record */
562     if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
563         return 0;
564 
565      /* the signature */
566     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
567         return 0;
568 
569     if (uL != 0x06064b50)
570         return 0;
571 
572     return relativeOffset;
573 }
574 
575 /*
576   Open a Zip file. path contain the full pathname (by example,
577      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
578      "zlib/zlib114.zip".
579      If the zipfile cannot be opened (file doesn't exist or in not valid), the
580        return value is NULL.
581      Else, the return value is a unzFile Handle, usable with other function
582        of this unzip package.
583 */
584 local unzFile unzOpenInternal (const void *path,
585                                zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
586                                int is64bitOpenFunction)
587 {
588     unz64_s us;
589     unz64_s *s;
590     ZPOS64_T central_pos;
591     uLong   uL;
592 
593     uLong number_disk;          /* number of the current dist, used for
594                                    spaning ZIP, unsupported, always 0*/
595     uLong number_disk_with_CD;  /* number the the disk with central dir, used
596                                    for spaning ZIP, unsupported, always 0*/
597     ZPOS64_T number_entry_CD;      /* total number of entries in
598                                    the central dir
599                                    (same than number_entry on nospan) */
600 
601     int err=UNZ_OK;
602 
603     if (unz_copyright[0]!=' ')
604         return NULL;
605 
606     us.z_filefunc.zseek32_file = NULL;
607     us.z_filefunc.ztell32_file = NULL;
608     if (pzlib_filefunc64_32_def==NULL)
609         fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
610     else
611         us.z_filefunc = *pzlib_filefunc64_32_def;
612     us.is64bitOpenFunction = is64bitOpenFunction;
613 
614 
615 
616     us.filestream = ZOPEN64(us.z_filefunc,
617                                                  path,
618                                                  ZLIB_FILEFUNC_MODE_READ |
619                                                  ZLIB_FILEFUNC_MODE_EXISTING);
620     if (us.filestream==NULL)
621         return NULL;
622 
623     central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
624     if (central_pos)
625     {
626         uLong uS;
627         ZPOS64_T uL64;
628 
629         us.isZip64 = 1;
630 
631         if (ZSEEK64(us.z_filefunc, us.filestream,
632                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
633         err=UNZ_ERRNO;
634 
635         /* the signature, already checked */
636         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
637             err=UNZ_ERRNO;
638 
639         /* size of zip64 end of central directory record */
640         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)
641             err=UNZ_ERRNO;
642 
643         /* version made by */
644         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
645             err=UNZ_ERRNO;
646 
647         /* version needed to extract */
648         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
649             err=UNZ_ERRNO;
650 
651         /* number of this disk */
652         if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
653             err=UNZ_ERRNO;
654 
655         /* number of the disk with the start of the central directory */
656         if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
657             err=UNZ_ERRNO;
658 
659         /* total number of entries in the central directory on this disk */
660         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
661             err=UNZ_ERRNO;
662 
663         /* total number of entries in the central directory */
664         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
665             err=UNZ_ERRNO;
666 
667         if ((number_entry_CD!=us.gi.number_entry) ||
668             (number_disk_with_CD!=0) ||
669             (number_disk!=0))
670             err=UNZ_BADZIPFILE;
671 
672         /* size of the central directory */
673         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
674             err=UNZ_ERRNO;
675 
676         /* offset of start of central directory with respect to the
677           starting disk number */
678         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
679             err=UNZ_ERRNO;
680 
681         us.gi.size_comment = 0;
682     }
683     else
684     {
685         central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
686         if (central_pos==0)
687             err=UNZ_ERRNO;
688 
689         us.isZip64 = 0;
690 
691         if (ZSEEK64(us.z_filefunc, us.filestream,
692                                         central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
693             err=UNZ_ERRNO;
694 
695         /* the signature, already checked */
696         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
697             err=UNZ_ERRNO;
698 
699         /* number of this disk */
700         if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
701             err=UNZ_ERRNO;
702 
703         /* number of the disk with the start of the central directory */
704         if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
705             err=UNZ_ERRNO;
706 
707         /* total number of entries in the central dir on this disk */
708         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
709             err=UNZ_ERRNO;
710         us.gi.number_entry = uL;
711 
712         /* total number of entries in the central dir */
713         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
714             err=UNZ_ERRNO;
715         number_entry_CD = uL;
716 
717         if ((number_entry_CD!=us.gi.number_entry) ||
718             (number_disk_with_CD!=0) ||
719             (number_disk!=0))
720             err=UNZ_BADZIPFILE;
721 
722         /* size of the central directory */
723         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
724             err=UNZ_ERRNO;
725         us.size_central_dir = uL;
726 
727         /* offset of start of central directory with respect to the
728             starting disk number */
729         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
730             err=UNZ_ERRNO;
731         us.offset_central_dir = uL;
732 
733         /* zipfile comment length */
734         if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
735             err=UNZ_ERRNO;
736     }
737 
738     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
739         (err==UNZ_OK))
740         err=UNZ_BADZIPFILE;
741 
742     if (err!=UNZ_OK)
743     {
744         ZCLOSE64(us.z_filefunc, us.filestream);
745         return NULL;
746     }
747 
748     us.byte_before_the_zipfile = central_pos -
749                             (us.offset_central_dir+us.size_central_dir);
750     us.central_pos = central_pos;
751     us.pfile_in_zip_read = NULL;
752     us.encrypted = 0;
753 
754 
755     s=(unz64_s*)ALLOC(sizeof(unz64_s));
756     if( s != NULL)
757     {
758         *s=us;
759         unzGoToFirstFile((unzFile)s);
760     }
761     return (unzFile)s;
762 }
763 
764 
765 extern unzFile ZEXPORT unzOpen2 (const char *path,
766                                         zlib_filefunc_def* pzlib_filefunc32_def)
767 {
768     if (pzlib_filefunc32_def != NULL)
769     {
770         zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
771         fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
772         return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
773     }
774     else
775         return unzOpenInternal(path, NULL, 0);
776 }
777 
778 extern unzFile ZEXPORT unzOpen2_64 (const void *path,
779                                      zlib_filefunc64_def* pzlib_filefunc_def)
780 {
781     if (pzlib_filefunc_def != NULL)
782     {
783         zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
784         zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
785         zlib_filefunc64_32_def_fill.ztell32_file = NULL;
786         zlib_filefunc64_32_def_fill.zseek32_file = NULL;
787         return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);
788     }
789     else
790         return unzOpenInternal(path, NULL, 1);
791 }
792 
793 extern unzFile ZEXPORT unzOpen (const char *path)
794 {
795     return unzOpenInternal(path, NULL, 0);
796 }
797 
798 extern unzFile ZEXPORT unzOpen64 (const void *path)
799 {
800     return unzOpenInternal(path, NULL, 1);
801 }
802 
803 /*
804   Close a ZipFile opened with unzOpen.
805   If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
806     these files MUST be closed with unzCloseCurrentFile before call unzClose.
807   return UNZ_OK if there is no problem. */
808 extern int ZEXPORT unzClose (unzFile file)
809 {
810     unz64_s* s;
811     if (file==NULL)
812         return UNZ_PARAMERROR;
813     s=(unz64_s*)file;
814 
815     if (s->pfile_in_zip_read!=NULL)
816         unzCloseCurrentFile(file);
817 
818     ZCLOSE64(s->z_filefunc, s->filestream);
819     TRYFREE(s);
820     return UNZ_OK;
821 }
822 
823 
824 /*
825   Write info about the ZipFile in the *pglobal_info structure.
826   No preparation of the structure is needed
827   return UNZ_OK if there is no problem. */
828 extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info)
829 {
830     unz64_s* s;
831     if (file==NULL)
832         return UNZ_PARAMERROR;
833     s=(unz64_s*)file;
834     *pglobal_info=s->gi;
835     return UNZ_OK;
836 }
837 
838 extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32)
839 {
840     unz64_s* s;
841     if (file==NULL)
842         return UNZ_PARAMERROR;
843     s=(unz64_s*)file;
844     /* to do : check if number_entry is not truncated */
845     pglobal_info32->number_entry = (uLong)s->gi.number_entry;
846     pglobal_info32->size_comment = s->gi.size_comment;
847     return UNZ_OK;
848 }
849 /*
850    Translate date/time from Dos format to tm_unz (readable more easilty)
851 */
852 local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)
853 {
854     ZPOS64_T uDate;
855     uDate = (ZPOS64_T)(ulDosDate>>16);
856     ptm->tm_mday = (int)(uDate&0x1f) ;
857     ptm->tm_mon =  (int)((((uDate)&0x1E0)/0x20)-1) ;
858     ptm->tm_year = (int)(((uDate&0x0FE00)/0x0200)+1980) ;
859 
860     ptm->tm_hour = (int) ((ulDosDate &0xF800)/0x800);
861     ptm->tm_min =  (int) ((ulDosDate&0x7E0)/0x20) ;
862     ptm->tm_sec =  (int) (2*(ulDosDate&0x1f)) ;
863 }
864 
865 /*
866   Get Info about the current file in the zipfile, with internal only info
867 */
868 local int unz64local_GetCurrentFileInfoInternal OF((unzFile file,
869                                                   unz_file_info64 *pfile_info,
870                                                   unz_file_info64_internal
871                                                   *pfile_info_internal,
872                                                   char *szFileName,
873                                                   uLong fileNameBufferSize,
874                                                   void *extraField,
875                                                   uLong extraFieldBufferSize,
876                                                   char *szComment,
877                                                   uLong commentBufferSize));
878 
879 local int unz64local_GetCurrentFileInfoInternal (unzFile file,
880                                                   unz_file_info64 *pfile_info,
881                                                   unz_file_info64_internal
882                                                   *pfile_info_internal,
883                                                   char *szFileName,
884                                                   uLong fileNameBufferSize,
885                                                   void *extraField,
886                                                   uLong extraFieldBufferSize,
887                                                   char *szComment,
888                                                   uLong commentBufferSize)
889 {
890     unz64_s* s;
891     unz_file_info64 file_info;
892     unz_file_info64_internal file_info_internal;
893     int err=UNZ_OK;
894     uLong uMagic;
895     long lSeek=0;
896     uLong uL;
897 
898     if (file==NULL)
899         return UNZ_PARAMERROR;
900     s=(unz64_s*)file;
901     if (ZSEEK64(s->z_filefunc, s->filestream,
902               s->pos_in_central_dir+s->byte_before_the_zipfile,
903               ZLIB_FILEFUNC_SEEK_SET)!=0)
904         err=UNZ_ERRNO;
905 
906 
907     /* we check the magic */
908     if (err==UNZ_OK)
909     {
910         if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
911             err=UNZ_ERRNO;
912         else if (uMagic!=0x02014b50)
913             err=UNZ_BADZIPFILE;
914     }
915 
916     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
917         err=UNZ_ERRNO;
918 
919     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
920         err=UNZ_ERRNO;
921 
922     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
923         err=UNZ_ERRNO;
924 
925     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
926         err=UNZ_ERRNO;
927 
928     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
929         err=UNZ_ERRNO;
930 
931     unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
932 
933     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
934         err=UNZ_ERRNO;
935 
936     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
937         err=UNZ_ERRNO;
938     file_info.compressed_size = uL;
939 
940     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
941         err=UNZ_ERRNO;
942     file_info.uncompressed_size = uL;
943 
944     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
945         err=UNZ_ERRNO;
946 
947     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
948         err=UNZ_ERRNO;
949 
950     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
951         err=UNZ_ERRNO;
952 
953     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
954         err=UNZ_ERRNO;
955 
956     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
957         err=UNZ_ERRNO;
958 
959     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
960         err=UNZ_ERRNO;
961 
962                 // relative offset of local header
963     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
964         err=UNZ_ERRNO;
965     file_info_internal.offset_curfile = uL;
966 
967     lSeek+=file_info.size_filename;
968     if ((err==UNZ_OK) && (szFileName!=NULL))
969     {
970         uLong uSizeRead ;
971         if (file_info.size_filename<fileNameBufferSize)
972         {
973             *(szFileName+file_info.size_filename)='\0';
974             uSizeRead = file_info.size_filename;
975         }
976         else
977             uSizeRead = fileNameBufferSize;
978 
979         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
980             if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
981                 err=UNZ_ERRNO;
982         lSeek -= uSizeRead;
983     }
984 
985     // Read extrafield
986     if ((err==UNZ_OK) && (extraField!=NULL))
987     {
988         ZPOS64_T uSizeRead ;
989         if (file_info.size_file_extra<extraFieldBufferSize)
990             uSizeRead = file_info.size_file_extra;
991         else
992             uSizeRead = extraFieldBufferSize;
993 
994         if (lSeek!=0)
995         {
996             if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
997                 lSeek=0;
998             else
999                 err=UNZ_ERRNO;
1000         }
1001 
1002         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
1003             if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead)
1004                 err=UNZ_ERRNO;
1005 
1006         lSeek += file_info.size_file_extra - (uLong)uSizeRead;
1007     }
1008     else
1009         lSeek += file_info.size_file_extra;
1010 
1011 
1012     if ((err==UNZ_OK) && (file_info.size_file_extra != 0))
1013     {
1014                                 uLong acc = 0;
1015 
1016         // since lSeek now points to after the extra field we need to move back
1017         lSeek -= file_info.size_file_extra;
1018 
1019         if (lSeek!=0)
1020         {
1021             if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
1022                 lSeek=0;
1023             else
1024                 err=UNZ_ERRNO;
1025         }
1026 
1027         while(acc < file_info.size_file_extra)
1028         {
1029             uLong headerId;
1030                                                 uLong dataSize;
1031 
1032             if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
1033                 err=UNZ_ERRNO;
1034 
1035             if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
1036                 err=UNZ_ERRNO;
1037 
1038             /* ZIP64 extra fields */
1039             if (headerId == 0x0001)
1040             {
1041                                                         uLong uL;
1042 
1043                                                                 if(file_info.uncompressed_size == MAXU32)
1044                                                                 {
1045                                                                         if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
1046                                                                                         err=UNZ_ERRNO;
1047                                                                 }
1048 
1049                                                                 if(file_info.compressed_size == MAXU32)
1050                                                                 {
1051                                                                         if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
1052                                                                                   err=UNZ_ERRNO;
1053                                                                 }
1054 
1055                                                                 if(file_info_internal.offset_curfile == MAXU32)
1056                                                                 {
1057                                                                         /* Relative Header offset */
1058                                                                         if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
1059                                                                                 err=UNZ_ERRNO;
1060                                                                 }
1061 
1062                                                                 if(file_info.disk_num_start == MAXU32)
1063                                                                 {
1064                                                                         /* Disk Start Number */
1065                                                                         if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
1066                                                                                 err=UNZ_ERRNO;
1067                                                                 }
1068 
1069             }
1070             else
1071             {
1072                 if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
1073                     err=UNZ_ERRNO;
1074             }
1075 
1076             acc += 2 + 2 + dataSize;
1077         }
1078     }
1079 
1080     if ((err==UNZ_OK) && (szComment!=NULL))
1081     {
1082         uLong uSizeRead ;
1083         if (file_info.size_file_comment<commentBufferSize)
1084         {
1085             *(szComment+file_info.size_file_comment)='\0';
1086             uSizeRead = file_info.size_file_comment;
1087         }
1088         else
1089             uSizeRead = commentBufferSize;
1090 
1091         if (lSeek!=0)
1092         {
1093             if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
1094                 lSeek=0;
1095             else
1096                 err=UNZ_ERRNO;
1097         }
1098 
1099         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
1100             if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
1101                 err=UNZ_ERRNO;
1102         lSeek+=file_info.size_file_comment - uSizeRead;
1103     }
1104     else
1105         lSeek+=file_info.size_file_comment;
1106 
1107 
1108     if ((err==UNZ_OK) && (pfile_info!=NULL))
1109         *pfile_info=file_info;
1110 
1111     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
1112         *pfile_info_internal=file_info_internal;
1113 
1114     return err;
1115 }
1116 
1117 
1118 
1119 /*
1120   Write info about the ZipFile in the *pglobal_info structure.
1121   No preparation of the structure is needed
1122   return UNZ_OK if there is no problem.
1123 */
1124 extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file,
1125                                           unz_file_info64 * pfile_info,
1126                                           char * szFileName, uLong fileNameBufferSize,
1127                                           void *extraField, uLong extraFieldBufferSize,
1128                                           char* szComment,  uLong commentBufferSize)
1129 {
1130     return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
1131                                                 szFileName,fileNameBufferSize,
1132                                                 extraField,extraFieldBufferSize,
1133                                                 szComment,commentBufferSize);
1134 }
1135 
1136 extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
1137                                           unz_file_info * pfile_info,
1138                                           char * szFileName, uLong fileNameBufferSize,
1139                                           void *extraField, uLong extraFieldBufferSize,
1140                                           char* szComment,  uLong commentBufferSize)
1141 {
1142     int err;
1143     unz_file_info64 file_info64;
1144     err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL,
1145                                                 szFileName,fileNameBufferSize,
1146                                                 extraField,extraFieldBufferSize,
1147                                                 szComment,commentBufferSize);
1148     if ((err==UNZ_OK) && (pfile_info != NULL))
1149     {
1150         pfile_info->version = file_info64.version;
1151         pfile_info->version_needed = file_info64.version_needed;
1152         pfile_info->flag = file_info64.flag;
1153         pfile_info->compression_method = file_info64.compression_method;
1154         pfile_info->dosDate = file_info64.dosDate;
1155         pfile_info->crc = file_info64.crc;
1156 
1157         pfile_info->size_filename = file_info64.size_filename;
1158         pfile_info->size_file_extra = file_info64.size_file_extra;
1159         pfile_info->size_file_comment = file_info64.size_file_comment;
1160 
1161         pfile_info->disk_num_start = file_info64.disk_num_start;
1162         pfile_info->internal_fa = file_info64.internal_fa;
1163         pfile_info->external_fa = file_info64.external_fa;
1164 
1165         pfile_info->tmu_date = file_info64.tmu_date,
1166 
1167 
1168         pfile_info->compressed_size = (uLong)file_info64.compressed_size;
1169         pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;
1170 
1171     }
1172     return err;
1173 }
1174 /*
1175   Set the current file of the zipfile to the first file.
1176   return UNZ_OK if there is no problem
1177 */
1178 extern int ZEXPORT unzGoToFirstFile (unzFile file)
1179 {
1180     int err=UNZ_OK;
1181     unz64_s* s;
1182     if (file==NULL)
1183         return UNZ_PARAMERROR;
1184     s=(unz64_s*)file;
1185     s->pos_in_central_dir=s->offset_central_dir;
1186     s->num_file=0;
1187     err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1188                                              &s->cur_file_info_internal,
1189                                              NULL,0,NULL,0,NULL,0);
1190     s->current_file_ok = (err == UNZ_OK);
1191     return err;
1192 }
1193 
1194 /*
1195   Set the current file of the zipfile to the next file.
1196   return UNZ_OK if there is no problem
1197   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
1198 */
1199 extern int ZEXPORT unzGoToNextFile (unzFile  file)
1200 {
1201     unz64_s* s;
1202     int err;
1203 
1204     if (file==NULL)
1205         return UNZ_PARAMERROR;
1206     s=(unz64_s*)file;
1207     if (!s->current_file_ok)
1208         return UNZ_END_OF_LIST_OF_FILE;
1209     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
1210       if (s->num_file+1==s->gi.number_entry)
1211         return UNZ_END_OF_LIST_OF_FILE;
1212 
1213     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
1214             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
1215     s->num_file++;
1216     err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1217                                                &s->cur_file_info_internal,
1218                                                NULL,0,NULL,0,NULL,0);
1219     s->current_file_ok = (err == UNZ_OK);
1220     return err;
1221 }
1222 
1223 
1224 /*
1225   Try locate the file szFileName in the zipfile.
1226   For the iCaseSensitivity signification, see unzStringFileNameCompare
1227 
1228   return value :
1229   UNZ_OK if the file is found. It becomes the current file.
1230   UNZ_END_OF_LIST_OF_FILE if the file is not found
1231 */
1232 extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
1233 {
1234     unz64_s* s;
1235     int err;
1236 
1237     /* We remember the 'current' position in the file so that we can jump
1238      * back there if we fail.
1239      */
1240     unz_file_info64 cur_file_infoSaved;
1241     unz_file_info64_internal cur_file_info_internalSaved;
1242     ZPOS64_T num_fileSaved;
1243     ZPOS64_T pos_in_central_dirSaved;
1244 
1245 
1246     if (file==NULL)
1247         return UNZ_PARAMERROR;
1248 
1249     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
1250         return UNZ_PARAMERROR;
1251 
1252     s=(unz64_s*)file;
1253     if (!s->current_file_ok)
1254         return UNZ_END_OF_LIST_OF_FILE;
1255 
1256     /* Save the current state */
1257     num_fileSaved = s->num_file;
1258     pos_in_central_dirSaved = s->pos_in_central_dir;
1259     cur_file_infoSaved = s->cur_file_info;
1260     cur_file_info_internalSaved = s->cur_file_info_internal;
1261 
1262     err = unzGoToFirstFile(file);
1263 
1264     while (err == UNZ_OK)
1265     {
1266         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
1267         err = unzGetCurrentFileInfo64(file,NULL,
1268                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
1269                                     NULL,0,NULL,0);
1270         if (err == UNZ_OK)
1271         {
1272             if (unzStringFileNameCompare(szCurrentFileName,
1273                                             szFileName,iCaseSensitivity)==0)
1274                 return UNZ_OK;
1275             err = unzGoToNextFile(file);
1276         }
1277     }
1278 
1279     /* We failed, so restore the state of the 'current file' to where we
1280      * were.
1281      */
1282     s->num_file = num_fileSaved ;
1283     s->pos_in_central_dir = pos_in_central_dirSaved ;
1284     s->cur_file_info = cur_file_infoSaved;
1285     s->cur_file_info_internal = cur_file_info_internalSaved;
1286     return err;
1287 }
1288 
1289 
1290 /*
1291 ///////////////////////////////////////////
1292 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
1293 // I need random access
1294 //
1295 // Further optimization could be realized by adding an ability
1296 // to cache the directory in memory. The goal being a single
1297 // comprehensive file read to put the file I need in a memory.
1298 */
1299 
1300 /*
1301 typedef struct unz_file_pos_s
1302 {
1303     ZPOS64_T pos_in_zip_directory;   // offset in file
1304     ZPOS64_T num_of_file;            // # of file
1305 } unz_file_pos;
1306 */
1307 
1308 extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos*  file_pos)
1309 {
1310     unz64_s* s;
1311 
1312     if (file==NULL || file_pos==NULL)
1313         return UNZ_PARAMERROR;
1314     s=(unz64_s*)file;
1315     if (!s->current_file_ok)
1316         return UNZ_END_OF_LIST_OF_FILE;
1317 
1318     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
1319     file_pos->num_of_file           = s->num_file;
1320 
1321     return UNZ_OK;
1322 }
1323 
1324 extern int ZEXPORT unzGetFilePos(
1325     unzFile file,
1326     unz_file_pos* file_pos)
1327 {
1328     unz64_file_pos file_pos64;
1329     int err = unzGetFilePos64(file,&file_pos64);
1330     if (err==UNZ_OK)
1331     {
1332         file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;
1333         file_pos->num_of_file = (uLong)file_pos64.num_of_file;
1334     }
1335     return err;
1336 }
1337 
1338 extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos)
1339 {
1340     unz64_s* s;
1341     int err;
1342 
1343     if (file==NULL || file_pos==NULL)
1344         return UNZ_PARAMERROR;
1345     s=(unz64_s*)file;
1346 
1347     /* jump to the right spot */
1348     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
1349     s->num_file           = file_pos->num_of_file;
1350 
1351     /* set the current file */
1352     err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1353                                                &s->cur_file_info_internal,
1354                                                NULL,0,NULL,0,NULL,0);
1355     /* return results */
1356     s->current_file_ok = (err == UNZ_OK);
1357     return err;
1358 }
1359 
1360 extern int ZEXPORT unzGoToFilePos(
1361     unzFile file,
1362     unz_file_pos* file_pos)
1363 {
1364     unz64_file_pos file_pos64;
1365     if (file_pos == NULL)
1366         return UNZ_PARAMERROR;
1367 
1368     file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
1369     file_pos64.num_of_file = file_pos->num_of_file;
1370     return unzGoToFilePos64(file,&file_pos64);
1371 }
1372 
1373 /*
1374 // Unzip Helper Functions - should be here?
1375 ///////////////////////////////////////////
1376 */
1377 
1378 /*
1379   Read the local header of the current zipfile
1380   Check the coherency of the local header and info in the end of central
1381         directory about this file
1382   store in *piSizeVar the size of extra info in local header
1383         (filename and size of extra field data)
1384 */
1385 local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar,
1386                                                     ZPOS64_T * poffset_local_extrafield,
1387                                                     uInt  * psize_local_extrafield)
1388 {
1389     uLong uMagic,uData,uFlags;
1390     uLong size_filename;
1391     uLong size_extra_field;
1392     int err=UNZ_OK;
1393 
1394     *piSizeVar = 0;
1395     *poffset_local_extrafield = 0;
1396     *psize_local_extrafield = 0;
1397 
1398     if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
1399                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
1400         return UNZ_ERRNO;
1401 
1402 
1403     if (err==UNZ_OK)
1404     {
1405         if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
1406             err=UNZ_ERRNO;
1407         else if (uMagic!=0x04034b50)
1408             err=UNZ_BADZIPFILE;
1409     }
1410 
1411     if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1412         err=UNZ_ERRNO;
1413 /*
1414     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1415         err=UNZ_BADZIPFILE;
1416 */
1417     if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
1418         err=UNZ_ERRNO;
1419 
1420     if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1421         err=UNZ_ERRNO;
1422     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1423         err=UNZ_BADZIPFILE;
1424 
1425     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1426 /* #ifdef HAVE_BZIP2 */
1427                          (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
1428 /* #endif */
1429                          (s->cur_file_info.compression_method!=Z_DEFLATED))
1430         err=UNZ_BADZIPFILE;
1431 
1432     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1433         err=UNZ_ERRNO;
1434 
1435     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1436         err=UNZ_ERRNO;
1437     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0))
1438         err=UNZ_BADZIPFILE;
1439 
1440     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1441         err=UNZ_ERRNO;
1442     else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0))
1443         err=UNZ_BADZIPFILE;
1444 
1445     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1446         err=UNZ_ERRNO;
1447     else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0))
1448         err=UNZ_BADZIPFILE;
1449 
1450     if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1451         err=UNZ_ERRNO;
1452     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1453         err=UNZ_BADZIPFILE;
1454 
1455     *piSizeVar += (uInt)size_filename;
1456 
1457     if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1458         err=UNZ_ERRNO;
1459     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1460                                     SIZEZIPLOCALHEADER + size_filename;
1461     *psize_local_extrafield = (uInt)size_extra_field;
1462 
1463     *piSizeVar += (uInt)size_extra_field;
1464 
1465     return err;
1466 }
1467 
1468 /*
1469   Open for reading data the current file in the zipfile.
1470   If there is no error and the file is opened, the return value is UNZ_OK.
1471 */
1472 extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
1473                                             int* level, int raw, const char* password)
1474 {
1475     int err=UNZ_OK;
1476     uInt iSizeVar;
1477     unz64_s* s;
1478     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1479     ZPOS64_T offset_local_extrafield;  /* offset of the local extra field */
1480     uInt  size_local_extrafield;    /* size of the local extra field */
1481 #    ifndef NOUNCRYPT
1482     char source[12];
1483 #    else
1484     if (password != NULL)
1485         return UNZ_PARAMERROR;
1486 #    endif
1487 
1488     if (file==NULL)
1489         return UNZ_PARAMERROR;
1490     s=(unz64_s*)file;
1491     if (!s->current_file_ok)
1492         return UNZ_PARAMERROR;
1493 
1494     if (s->pfile_in_zip_read != NULL)
1495         unzCloseCurrentFile(file);
1496 
1497     if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1498         return UNZ_BADZIPFILE;
1499 
1500     pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
1501     if (pfile_in_zip_read_info==NULL)
1502         return UNZ_INTERNALERROR;
1503 
1504     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1505     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1506     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1507     pfile_in_zip_read_info->pos_local_extrafield=0;
1508     pfile_in_zip_read_info->raw=raw;
1509 
1510     if (pfile_in_zip_read_info->read_buffer==NULL)
1511     {
1512         TRYFREE(pfile_in_zip_read_info);
1513         return UNZ_INTERNALERROR;
1514     }
1515 
1516     pfile_in_zip_read_info->stream_initialised=0;
1517 
1518     if (method!=NULL)
1519         *method = (int)s->cur_file_info.compression_method;
1520 
1521     if (level!=NULL)
1522     {
1523         *level = 6;
1524         switch (s->cur_file_info.flag & 0x06)
1525         {
1526           case 6 : *level = 1; break;
1527           case 4 : *level = 2; break;
1528           case 2 : *level = 9; break;
1529         }
1530     }
1531 
1532     if ((s->cur_file_info.compression_method!=0) &&
1533 /* #ifdef HAVE_BZIP2 */
1534         (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
1535 /* #endif */
1536         (s->cur_file_info.compression_method!=Z_DEFLATED))
1537 
1538         err=UNZ_BADZIPFILE;
1539 
1540     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1541     pfile_in_zip_read_info->crc32=0;
1542     pfile_in_zip_read_info->total_out_64=0;
1543     pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
1544     pfile_in_zip_read_info->filestream=s->filestream;
1545     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1546     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1547 
1548     pfile_in_zip_read_info->stream.total_out = 0;
1549 
1550     if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw))
1551     {
1552 #ifdef HAVE_BZIP2
1553       pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
1554       pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
1555       pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
1556       pfile_in_zip_read_info->bstream.state = (voidpf)0;
1557 
1558       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1559       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1560       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1561       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1562       pfile_in_zip_read_info->stream.avail_in = 0;
1563 
1564       err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
1565       if (err == Z_OK)
1566         pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;
1567       else
1568       {
1569         TRYFREE(pfile_in_zip_read_info->read_buffer);
1570         TRYFREE(pfile_in_zip_read_info);
1571         return err;
1572       }
1573 #else
1574       pfile_in_zip_read_info->raw=1;
1575 #endif
1576     }
1577     else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
1578     {
1579       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1580       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1581       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1582       pfile_in_zip_read_info->stream.next_in = 0;
1583       pfile_in_zip_read_info->stream.avail_in = 0;
1584 
1585       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1586       if (err == Z_OK)
1587         pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
1588       else
1589       {
1590         TRYFREE(pfile_in_zip_read_info->read_buffer);
1591         TRYFREE(pfile_in_zip_read_info);
1592         return err;
1593       }
1594         /* windowBits is passed < 0 to tell that there is no zlib header.
1595          * Note that in this case inflate *requires* an extra "dummy" byte
1596          * after the compressed stream in order to complete decompression and
1597          * return Z_STREAM_END.
1598          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1599          * size of both compressed and uncompressed data
1600          */
1601     }
1602     pfile_in_zip_read_info->rest_read_compressed =
1603             s->cur_file_info.compressed_size ;
1604     pfile_in_zip_read_info->rest_read_uncompressed =
1605             s->cur_file_info.uncompressed_size ;
1606 
1607 
1608     pfile_in_zip_read_info->pos_in_zipfile =
1609             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1610               iSizeVar;
1611 
1612     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1613 
1614     s->pfile_in_zip_read = pfile_in_zip_read_info;
1615                 s->encrypted = 0;
1616 
1617 #    ifndef NOUNCRYPT
1618     if (password != NULL)
1619     {
1620         int i;
1621         s->pcrc_32_tab = get_crc_table();
1622         init_keys(password,s->keys,s->pcrc_32_tab);
1623         if (ZSEEK64(s->z_filefunc, s->filestream,
1624                   s->pfile_in_zip_read->pos_in_zipfile +
1625                      s->pfile_in_zip_read->byte_before_the_zipfile,
1626                   SEEK_SET)!=0)
1627             return UNZ_INTERNALERROR;
1628         if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12)
1629             return UNZ_INTERNALERROR;
1630 
1631         for (i = 0; i<12; i++)
1632             zdecode(s->keys,s->pcrc_32_tab,source[i]);
1633 
1634         s->pfile_in_zip_read->pos_in_zipfile+=12;
1635         s->encrypted=1;
1636     }
1637 #    endif
1638 
1639 
1640     return UNZ_OK;
1641 }
1642 
1643 extern int ZEXPORT unzOpenCurrentFile (unzFile file)
1644 {
1645     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1646 }
1647 
1648 extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char*  password)
1649 {
1650     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1651 }
1652 
1653 extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw)
1654 {
1655     return unzOpenCurrentFile3(file, method, level, raw, NULL);
1656 }
1657 
1658 /** Addition for GDAL : START */
1659 
1660 extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file)
1661 {
1662     unz64_s* s;
1663     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1664     s=(unz64_s*)file;
1665     if (file==NULL)
1666         return 0; //UNZ_PARAMERROR;
1667     pfile_in_zip_read_info=s->pfile_in_zip_read;
1668     if (pfile_in_zip_read_info==NULL)
1669         return 0; //UNZ_PARAMERROR;
1670     return pfile_in_zip_read_info->pos_in_zipfile +
1671                          pfile_in_zip_read_info->byte_before_the_zipfile;
1672 }
1673 
1674 /** Addition for GDAL : END */
1675 
1676 /*
1677   Read bytes from the current file.
1678   buf contain buffer where data must be copied
1679   len the size of buf.
1680 
1681   return the number of byte copied if somes bytes are copied
1682   return 0 if the end of file was reached
1683   return <0 with error code if there is an error
1684     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1685 */
1686 extern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)
1687 {
1688     int err=UNZ_OK;
1689     uInt iRead = 0;
1690     unz64_s* s;
1691     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1692     if (file==NULL)
1693         return UNZ_PARAMERROR;
1694     s=(unz64_s*)file;
1695     pfile_in_zip_read_info=s->pfile_in_zip_read;
1696 
1697     if (pfile_in_zip_read_info==NULL)
1698         return UNZ_PARAMERROR;
1699 
1700 
1701     if (pfile_in_zip_read_info->read_buffer == NULL)
1702         return UNZ_END_OF_LIST_OF_FILE;
1703     if (len==0)
1704         return 0;
1705 
1706     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1707 
1708     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1709 
1710     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1711         (!(pfile_in_zip_read_info->raw)))
1712         pfile_in_zip_read_info->stream.avail_out =
1713             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1714 
1715     if ((len>pfile_in_zip_read_info->rest_read_compressed+
1716            pfile_in_zip_read_info->stream.avail_in) &&
1717          (pfile_in_zip_read_info->raw))
1718         pfile_in_zip_read_info->stream.avail_out =
1719             (uInt)pfile_in_zip_read_info->rest_read_compressed+
1720             pfile_in_zip_read_info->stream.avail_in;
1721 
1722     while (pfile_in_zip_read_info->stream.avail_out>0)
1723     {
1724         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1725             (pfile_in_zip_read_info->rest_read_compressed>0))
1726         {
1727             uInt uReadThis = UNZ_BUFSIZE;
1728             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1729                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1730             if (uReadThis == 0)
1731                 return UNZ_EOF;
1732             if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
1733                       pfile_in_zip_read_info->filestream,
1734                       pfile_in_zip_read_info->pos_in_zipfile +
1735                          pfile_in_zip_read_info->byte_before_the_zipfile,
1736                          ZLIB_FILEFUNC_SEEK_SET)!=0)
1737                 return UNZ_ERRNO;
1738             if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
1739                       pfile_in_zip_read_info->filestream,
1740                       pfile_in_zip_read_info->read_buffer,
1741                       uReadThis)!=uReadThis)
1742                 return UNZ_ERRNO;
1743 
1744 
1745 #            ifndef NOUNCRYPT
1746             if(s->encrypted)
1747             {
1748                 uInt i;
1749                 for(i=0;i<uReadThis;i++)
1750                   pfile_in_zip_read_info->read_buffer[i] =
1751                       zdecode(s->keys,s->pcrc_32_tab,
1752                               pfile_in_zip_read_info->read_buffer[i]);
1753             }
1754 #            endif
1755 
1756 
1757             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1758 
1759             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1760 
1761             pfile_in_zip_read_info->stream.next_in =
1762                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1763             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1764         }
1765 
1766         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1767         {
1768             uInt uDoCopy,i ;
1769 
1770             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1771                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1772                 return (iRead==0) ? UNZ_EOF : (int)iRead;
1773 
1774             if (pfile_in_zip_read_info->stream.avail_out <
1775                             pfile_in_zip_read_info->stream.avail_in)
1776                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1777             else
1778                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1779 
1780             for (i=0;i<uDoCopy;i++)
1781                 *(pfile_in_zip_read_info->stream.next_out+i) =
1782                         *(pfile_in_zip_read_info->stream.next_in+i);
1783 
1784             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;
1785 
1786             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1787                                 pfile_in_zip_read_info->stream.next_out,
1788                                 uDoCopy);
1789             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1790             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1791             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1792             pfile_in_zip_read_info->stream.next_out += uDoCopy;
1793             pfile_in_zip_read_info->stream.next_in += uDoCopy;
1794             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1795             iRead += uDoCopy;
1796         }
1797         else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)
1798         {
1799 #ifdef HAVE_BZIP2
1800             uLong uTotalOutBefore,uTotalOutAfter;
1801             const Bytef *bufBefore;
1802             uLong uOutThis;
1803 
1804             pfile_in_zip_read_info->bstream.next_in        = (char*)pfile_in_zip_read_info->stream.next_in;
1805             pfile_in_zip_read_info->bstream.avail_in       = pfile_in_zip_read_info->stream.avail_in;
1806             pfile_in_zip_read_info->bstream.total_in_lo32  = pfile_in_zip_read_info->stream.total_in;
1807             pfile_in_zip_read_info->bstream.total_in_hi32  = 0;
1808             pfile_in_zip_read_info->bstream.next_out       = (char*)pfile_in_zip_read_info->stream.next_out;
1809             pfile_in_zip_read_info->bstream.avail_out      = pfile_in_zip_read_info->stream.avail_out;
1810             pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
1811             pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
1812 
1813             uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
1814             bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;
1815 
1816             err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
1817 
1818             uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
1819             uOutThis = uTotalOutAfter-uTotalOutBefore;
1820 
1821             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
1822 
1823             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis));
1824             pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
1825             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1826 
1827             pfile_in_zip_read_info->stream.next_in   = (Bytef*)pfile_in_zip_read_info->bstream.next_in;
1828             pfile_in_zip_read_info->stream.avail_in  = pfile_in_zip_read_info->bstream.avail_in;
1829             pfile_in_zip_read_info->stream.total_in  = pfile_in_zip_read_info->bstream.total_in_lo32;
1830             pfile_in_zip_read_info->stream.next_out  = (Bytef*)pfile_in_zip_read_info->bstream.next_out;
1831             pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
1832             pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
1833 
1834             if (err==BZ_STREAM_END)
1835               return (iRead==0) ? UNZ_EOF : iRead;
1836             if (err!=BZ_OK)
1837               break;
1838 #endif
1839         } // end Z_BZIP2ED
1840         else
1841         {
1842             ZPOS64_T uTotalOutBefore,uTotalOutAfter;
1843             const Bytef *bufBefore;
1844             ZPOS64_T uOutThis;
1845             int flush=Z_SYNC_FLUSH;
1846 
1847             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1848             bufBefore = pfile_in_zip_read_info->stream.next_out;
1849 
1850             /*
1851             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1852                      pfile_in_zip_read_info->stream.avail_out) &&
1853                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1854                 flush = Z_FINISH;
1855             */
1856             err=inflate(&pfile_in_zip_read_info->stream,flush);
1857 
1858             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1859               err = Z_DATA_ERROR;
1860 
1861             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1862             /* Detect overflow, because z_stream.total_out is uLong (32 bits) */
1863             if (uTotalOutAfter<uTotalOutBefore)
1864                 uTotalOutAfter += 1LL << 32; /* Add maximum value of uLong + 1 */
1865             uOutThis = uTotalOutAfter-uTotalOutBefore;
1866 
1867             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
1868 
1869             pfile_in_zip_read_info->crc32 =
1870                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1871                         (uInt)(uOutThis));
1872 
1873             pfile_in_zip_read_info->rest_read_uncompressed -=
1874                 uOutThis;
1875 
1876             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1877 
1878             if (err==Z_STREAM_END)
1879                 return (iRead==0) ? UNZ_EOF : (int)iRead;
1880             if (err!=Z_OK)
1881                 break;
1882         }
1883     }
1884 
1885     if (err==Z_OK)
1886         return (int)iRead;
1887     return err;
1888 }
1889 
1890 
1891 /*
1892   Give the current position in uncompressed data
1893 */
1894 extern z_off_t ZEXPORT unztell (unzFile file)
1895 {
1896     unz64_s* s;
1897     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1898     if (file==NULL)
1899         return UNZ_PARAMERROR;
1900     s=(unz64_s*)file;
1901     pfile_in_zip_read_info=s->pfile_in_zip_read;
1902 
1903     if (pfile_in_zip_read_info==NULL)
1904         return UNZ_PARAMERROR;
1905 
1906     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1907 }
1908 
1909 extern ZPOS64_T ZEXPORT unztell64 (unzFile file)
1910 {
1911 
1912     unz64_s* s;
1913     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1914     if (file==NULL)
1915         return (ZPOS64_T)-1;
1916     s=(unz64_s*)file;
1917     pfile_in_zip_read_info=s->pfile_in_zip_read;
1918 
1919     if (pfile_in_zip_read_info==NULL)
1920         return (ZPOS64_T)-1;
1921 
1922     return pfile_in_zip_read_info->total_out_64;
1923 }
1924 
1925 
1926 /*
1927   return 1 if the end of file was reached, 0 elsewhere
1928 */
1929 extern int ZEXPORT unzeof (unzFile file)
1930 {
1931     unz64_s* s;
1932     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1933     if (file==NULL)
1934         return UNZ_PARAMERROR;
1935     s=(unz64_s*)file;
1936     pfile_in_zip_read_info=s->pfile_in_zip_read;
1937 
1938     if (pfile_in_zip_read_info==NULL)
1939         return UNZ_PARAMERROR;
1940 
1941     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1942         return 1;
1943     else
1944         return 0;
1945 }
1946 
1947 
1948 
1949 /*
1950 Read extra field from the current file (opened by unzOpenCurrentFile)
1951 This is the local-header version of the extra field (sometimes, there is
1952 more info in the local-header version than in the central-header)
1953 
1954   if buf==NULL, it return the size of the local extra field that can be read
1955 
1956   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1957     buf.
1958   the return value is the number of bytes copied in buf, or (if <0)
1959     the error code
1960 */
1961 extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
1962 {
1963     unz64_s* s;
1964     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1965     uInt read_now;
1966     ZPOS64_T size_to_read;
1967 
1968     if (file==NULL)
1969         return UNZ_PARAMERROR;
1970     s=(unz64_s*)file;
1971     pfile_in_zip_read_info=s->pfile_in_zip_read;
1972 
1973     if (pfile_in_zip_read_info==NULL)
1974         return UNZ_PARAMERROR;
1975 
1976     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1977                 pfile_in_zip_read_info->pos_local_extrafield);
1978 
1979     if (buf==NULL)
1980         return (int)size_to_read;
1981 
1982     if (len>size_to_read)
1983         read_now = (uInt)size_to_read;
1984     else
1985         read_now = (uInt)len ;
1986 
1987     if (read_now==0)
1988         return 0;
1989 
1990     if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
1991               pfile_in_zip_read_info->filestream,
1992               pfile_in_zip_read_info->offset_local_extrafield +
1993               pfile_in_zip_read_info->pos_local_extrafield,
1994               ZLIB_FILEFUNC_SEEK_SET)!=0)
1995         return UNZ_ERRNO;
1996 
1997     if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
1998               pfile_in_zip_read_info->filestream,
1999               buf,read_now)!=read_now)
2000         return UNZ_ERRNO;
2001 
2002     return (int)read_now;
2003 }
2004 
2005 /*
2006   Close the file in zip opened with unzOpenCurrentFile
2007   Return UNZ_CRCERROR if all the file was read but the CRC is not good
2008 */
2009 extern int ZEXPORT unzCloseCurrentFile (unzFile file)
2010 {
2011     int err=UNZ_OK;
2012 
2013     unz64_s* s;
2014     file_in_zip64_read_info_s* pfile_in_zip_read_info;
2015     if (file==NULL)
2016         return UNZ_PARAMERROR;
2017     s=(unz64_s*)file;
2018     pfile_in_zip_read_info=s->pfile_in_zip_read;
2019 
2020     if (pfile_in_zip_read_info==NULL)
2021         return UNZ_PARAMERROR;
2022 
2023 
2024     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
2025         (!pfile_in_zip_read_info->raw))
2026     {
2027         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
2028             err=UNZ_CRCERROR;
2029     }
2030 
2031 
2032     TRYFREE(pfile_in_zip_read_info->read_buffer);
2033     pfile_in_zip_read_info->read_buffer = NULL;
2034     if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
2035         inflateEnd(&pfile_in_zip_read_info->stream);
2036 #ifdef HAVE_BZIP2
2037     else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
2038         BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
2039 #endif
2040 
2041 
2042     pfile_in_zip_read_info->stream_initialised = 0;
2043     TRYFREE(pfile_in_zip_read_info);
2044 
2045     s->pfile_in_zip_read=NULL;
2046 
2047     return err;
2048 }
2049 
2050 
2051 /*
2052   Get the global comment string of the ZipFile, in the szComment buffer.
2053   uSizeBuf is the size of the szComment buffer.
2054   return the number of byte copied or an error code <0
2055 */
2056 extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf)
2057 {
2058     unz64_s* s;
2059     uLong uReadThis ;
2060     if (file==NULL)
2061         return (int)UNZ_PARAMERROR;
2062     s=(unz64_s*)file;
2063 
2064     uReadThis = uSizeBuf;
2065     if (uReadThis>s->gi.size_comment)
2066         uReadThis = s->gi.size_comment;
2067 
2068     if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
2069         return UNZ_ERRNO;
2070 
2071     if (uReadThis>0)
2072     {
2073       *szComment='\0';
2074       if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
2075         return UNZ_ERRNO;
2076     }
2077 
2078     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
2079         *(szComment+s->gi.size_comment)='\0';
2080     return (int)uReadThis;
2081 }
2082 
2083 /* Additions by RX '2004 */
2084 extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file)
2085 {
2086     unz64_s* s;
2087 
2088     if (file==NULL)
2089           return 0; //UNZ_PARAMERROR;
2090     s=(unz64_s*)file;
2091     if (!s->current_file_ok)
2092       return 0;
2093     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
2094       if (s->num_file==s->gi.number_entry)
2095          return 0;
2096     return s->pos_in_central_dir;
2097 }
2098 
2099 extern uLong ZEXPORT unzGetOffset (unzFile file)
2100 {
2101     ZPOS64_T offset64;
2102 
2103     if (file==NULL)
2104           return 0; //UNZ_PARAMERROR;
2105     offset64 = unzGetOffset64(file);
2106     return (uLong)offset64;
2107 }
2108 
2109 extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos)
2110 {
2111     unz64_s* s;
2112     int err;
2113 
2114     if (file==NULL)
2115         return UNZ_PARAMERROR;
2116     s=(unz64_s*)file;
2117 
2118     s->pos_in_central_dir = pos;
2119     s->num_file = s->gi.number_entry;      /* hack */
2120     err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
2121                                               &s->cur_file_info_internal,
2122                                               NULL,0,NULL,0,NULL,0);
2123     s->current_file_ok = (err == UNZ_OK);
2124     return err;
2125 }
2126 
2127 extern int ZEXPORT unzSetOffset (unzFile file, uLong pos)
2128 {
2129     return unzSetOffset64(file,pos);
2130 }
2131