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