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 
72 #include "zlib.h"
73 #include "unzip.h"
74 
75 #ifdef STDC
76 #  include <stddef.h>
77 #  include <string.h>
78 #  include <stdlib.h>
79 #endif
80 #ifdef NO_ERRNO_H
81     extern int errno;
82 #else
83 #   include <errno.h>
84 #endif
85 
86 
87 #ifndef local
88 #  define local static
89 #endif
90 /* compile with -Dlocal if your debugger can't find static symbols */
91 
92 
93 #ifndef CASESENSITIVITYDEFAULT_NO
94 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
95 #    define CASESENSITIVITYDEFAULT_NO
96 #  endif
97 #endif
98 
99 
100 #ifndef UNZ_BUFSIZE
101 #define UNZ_BUFSIZE (16384)
102 #endif
103 
104 #ifndef UNZ_MAXFILENAMEINZIP
105 #define UNZ_MAXFILENAMEINZIP (256)
106 #endif
107 
108 #ifndef ALLOC
109 # define ALLOC(size) (malloc(size))
110 #endif
111 #ifndef TRYFREE
112 # define TRYFREE(p) {if (p) free(p);}
113 #endif
114 
115 #define SIZECENTRALDIRITEM (0x2e)
116 #define SIZEZIPLOCALHEADER (0x1e)
117 
118 
119 const char unz_copyright[] =
120    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
121 
122 /* unz_file_info_interntal contain internal info about a file in zipfile*/
123 typedef struct unz_file_info64_internal_s
124 {
125     ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
126 } unz_file_info64_internal;
127 
128 
129 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
130     when reading and decompress it */
131 typedef struct
132 {
133     char  *read_buffer;         /* internal buffer for compressed data */
134     z_stream stream;            /* zLib stream structure for inflate */
135 
136 #ifdef HAVE_BZIP2
137     bz_stream bstream;          /* bzLib stream structure for bziped */
138 #endif
139 
140     ZPOS64_T pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
141     uLong stream_initialised;   /* flag set if stream structure is initialised*/
142 
143     ZPOS64_T offset_local_extrafield;/* offset of the local extra field */
144     uInt  size_local_extrafield;/* size of the local extra field */
145     ZPOS64_T pos_local_extrafield;   /* position in the local extra field in read*/
146     ZPOS64_T total_out_64;
147 
148     uLong crc32;                /* crc32 of all data uncompressed */
149     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
150     ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
151     ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
152     zlib_filefunc64_32_def z_filefunc;
153     voidpf filestream;        /* io structore of the zipfile */
154     uLong compression_method;   /* compression method (0==store) */
155     ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
156     int   raw;
157 } file_in_zip64_read_info_s;
158 
159 
160 /* unz64_s contain internal information about the zipfile
161 */
162 typedef struct
163 {
164     zlib_filefunc64_32_def z_filefunc;
165     int is64bitOpenFunction;
166     voidpf filestream;        /* io structore of the zipfile */
167     unz_global_info64 gi;       /* public global information */
168     ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
169     ZPOS64_T num_file;             /* number of the current file in the zipfile*/
170     ZPOS64_T pos_in_central_dir;   /* pos of the current file in the central dir*/
171     ZPOS64_T current_file_ok;      /* flag about the usability of the current file*/
172     ZPOS64_T central_pos;          /* position of the beginning of the central dir*/
173 
174     ZPOS64_T size_central_dir;     /* size of the central directory  */
175     ZPOS64_T offset_central_dir;   /* offset of start of central directory with
176                                    respect to the starting disk number */
177 
178     unz_file_info64 cur_file_info; /* public info about the current file in zip*/
179     unz_file_info64_internal cur_file_info_internal; /* private info about it*/
180     file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
181                                         file if we are decompressing it */
182     int encrypted;
183 
184     int isZip64;
185 
186 #    ifndef NOUNCRYPT
187     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
188     const z_crc_t* pcrc_32_tab;
189 #    endif
190 } unz64_s;
191 
192 
193 #ifndef NOUNCRYPT
194 #include "crypt.h"
195 #endif
196 
197 /* ===========================================================================
198      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
199    for end of file.
200    IN assertion: the stream s has been successfully opened for reading.
201 */
202 
203 
204 local int unz64local_getByte OF((
205     const zlib_filefunc64_32_def* pzlib_filefunc_def,
206     voidpf filestream,
207     int *pi));
208 
209 local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)
210 {
211     unsigned char c;
212     int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
213     if (err==1)
214     {
215         *pi = (int)c;
216         return UNZ_OK;
217     }
218     else
219     {
220         if (ZERROR64(*pzlib_filefunc_def,filestream))
221             return UNZ_ERRNO;
222         else
223             return UNZ_EOF;
224     }
225 }
226 
227 
228 /* ===========================================================================
229    Reads a long in LSB order from the given gz_stream. Sets
230 */
231 local int unz64local_getShort OF((
232     const zlib_filefunc64_32_def* pzlib_filefunc_def,
233     voidpf filestream,
234     uLong *pX));
235 
236 local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def,
237                              voidpf filestream,
238                              uLong *pX)
239 {
240     uLong x ;
241     int i = 0;
242     int err;
243 
244     err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
245     x = (uLong)i;
246 
247     if (err==UNZ_OK)
248         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
249     x |= ((uLong)i)<<8;
250 
251     if (err==UNZ_OK)
252         *pX = x;
253     else
254         *pX = 0;
255     return err;
256 }
257 
258 local int unz64local_getLong OF((
259     const zlib_filefunc64_32_def* pzlib_filefunc_def,
260     voidpf filestream,
261     uLong *pX));
262 
263 local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def,
264                             voidpf filestream,
265                             uLong *pX)
266 {
267     uLong x ;
268     int i = 0;
269     int err;
270 
271     err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
272     x = (uLong)i;
273 
274     if (err==UNZ_OK)
275         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
276     x |= ((uLong)i)<<8;
277 
278     if (err==UNZ_OK)
279         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
280     x |= ((uLong)i)<<16;
281 
282     if (err==UNZ_OK)
283         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
284     x += ((uLong)i)<<24;
285 
286     if (err==UNZ_OK)
287         *pX = x;
288     else
289         *pX = 0;
290     return err;
291 }
292 
293 local int unz64local_getLong64 OF((
294     const zlib_filefunc64_32_def* pzlib_filefunc_def,
295     voidpf filestream,
296     ZPOS64_T *pX));
297 
298 
299 local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def,
300                             voidpf filestream,
301                             ZPOS64_T *pX)
302 {
303     ZPOS64_T x ;
304     int i = 0;
305     int err;
306 
307     err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
308     x = (ZPOS64_T)i;
309 
310     if (err==UNZ_OK)
311         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
312     x |= ((ZPOS64_T)i)<<8;
313 
314     if (err==UNZ_OK)
315         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
316     x |= ((ZPOS64_T)i)<<16;
317 
318     if (err==UNZ_OK)
319         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
320     x |= ((ZPOS64_T)i)<<24;
321 
322     if (err==UNZ_OK)
323         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
324     x |= ((ZPOS64_T)i)<<32;
325 
326     if (err==UNZ_OK)
327         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
328     x |= ((ZPOS64_T)i)<<40;
329 
330     if (err==UNZ_OK)
331         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
332     x |= ((ZPOS64_T)i)<<48;
333 
334     if (err==UNZ_OK)
335         err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);
336     x |= ((ZPOS64_T)i)<<56;
337 
338     if (err==UNZ_OK)
339         *pX = x;
340     else
341         *pX = 0;
342     return err;
343 }
344 
345 /* My own strcmpi / strcasecmp */
346 local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
347 {
348     for (;;)
349     {
350         char c1=*(fileName1++);
351         char c2=*(fileName2++);
352         if ((c1>='a') && (c1<='z'))
353             c1 -= 0x20;
354         if ((c2>='a') && (c2<='z'))
355             c2 -= 0x20;
356         if (c1=='\0')
357             return ((c2=='\0') ? 0 : -1);
358         if (c2=='\0')
359             return 1;
360         if (c1<c2)
361             return -1;
362         if (c1>c2)
363             return 1;
364     }
365 }
366 
367 
368 #ifdef  CASESENSITIVITYDEFAULT_NO
369 #define CASESENSITIVITYDEFAULTVALUE 2
370 #else
371 #define CASESENSITIVITYDEFAULTVALUE 1
372 #endif
373 
374 #ifndef STRCMPCASENOSENTIVEFUNCTION
375 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
376 #endif
377 
378 /*
379    Compare two filename (fileName1,fileName2).
380    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
381    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
382                                                                 or strcasecmp)
383    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
384         (like 1 on Unix, 2 on Windows)
385 
386 */
387 extern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,
388                                                  const char*  fileName2,
389                                                  int iCaseSensitivity)
390 
391 {
392     if (iCaseSensitivity==0)
393         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
394 
395     if (iCaseSensitivity==1)
396         return strcmp(fileName1,fileName2);
397 
398     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
399 }
400 
401 #ifndef BUFREADCOMMENT
402 #define BUFREADCOMMENT (0x400)
403 #endif
404 
405 /*
406   Locate the Central directory of a zipfile (at the end, just before
407     the global comment)
408 */
409 local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
410 local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)
411 {
412     unsigned char* buf;
413     ZPOS64_T uSizeFile;
414     ZPOS64_T uBackRead;
415     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
416     ZPOS64_T uPosFound=0;
417 
418     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
419         return 0;
420 
421 
422     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
423 
424     if (uMaxBack>uSizeFile)
425         uMaxBack = uSizeFile;
426 
427     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
428     if (buf==NULL)
429         return 0;
430 
431     uBackRead = 4;
432     while (uBackRead<uMaxBack)
433     {
434         uLong uReadSize;
435         ZPOS64_T uReadPos ;
436         int i;
437         if (uBackRead+BUFREADCOMMENT>uMaxBack)
438             uBackRead = uMaxBack;
439         else
440             uBackRead+=BUFREADCOMMENT;
441         uReadPos = uSizeFile-uBackRead ;
442 
443         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
444                      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
445         if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
446             break;
447 
448         if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
449             break;
450 
451         for (i=(int)uReadSize-3; (i--)>0;)
452             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
453                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
454             {
455                 uPosFound = uReadPos+i;
456                 break;
457             }
458 
459         if (uPosFound!=0)
460             break;
461     }
462     TRYFREE(buf);
463     return uPosFound;
464 }
465 
466 
467 /*
468   Locate the Central directory 64 of a zipfile (at the end, just before
469     the global comment)
470 */
471 local ZPOS64_T unz64local_SearchCentralDir64 OF((
472     const zlib_filefunc64_32_def* pzlib_filefunc_def,
473     voidpf filestream));
474 
475 local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
476                                       voidpf filestream)
477 {
478     unsigned char* buf;
479     ZPOS64_T uSizeFile;
480     ZPOS64_T uBackRead;
481     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
482     ZPOS64_T uPosFound=0;
483     uLong uL;
484                 ZPOS64_T relativeOffset;
485 
486     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
487         return 0;
488 
489 
490     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
491 
492     if (uMaxBack>uSizeFile)
493         uMaxBack = uSizeFile;
494 
495     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
496     if (buf==NULL)
497         return 0;
498 
499     uBackRead = 4;
500     while (uBackRead<uMaxBack)
501     {
502         uLong uReadSize;
503         ZPOS64_T uReadPos;
504         int i;
505         if (uBackRead+BUFREADCOMMENT>uMaxBack)
506             uBackRead = uMaxBack;
507         else
508             uBackRead+=BUFREADCOMMENT;
509         uReadPos = uSizeFile-uBackRead ;
510 
511         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
512                      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
513         if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
514             break;
515 
516         if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
517             break;
518 
519         for (i=(int)uReadSize-3; (i--)>0;)
520             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
521                 ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
522             {
523                 uPosFound = uReadPos+i;
524                 break;
525             }
526 
527         if (uPosFound!=0)
528             break;
529     }
530     TRYFREE(buf);
531     if (uPosFound == 0)
532         return 0;
533 
534     /* Zip64 end of central directory locator */
535     if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
536         return 0;
537 
538     /* the signature, already checked */
539     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
540         return 0;
541 
542     /* number of the disk with the start of the zip64 end of  central directory */
543     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
544         return 0;
545     if (uL != 0)
546         return 0;
547 
548     /* relative offset of the zip64 end of central directory record */
549     if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
550         return 0;
551 
552     /* total number of disks */
553     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
554         return 0;
555     if (uL != 1)
556         return 0;
557 
558     /* Goto end of central directory record */
559     if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
560         return 0;
561 
562      /* the signature */
563     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
564         return 0;
565 
566     if (uL != 0x06064b50)
567         return 0;
568 
569     return relativeOffset;
570 }
571 
572 /*
573   Open a Zip file. path contain the full pathname (by example,
574      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
575      "zlib/zlib114.zip".
576      If the zipfile cannot be opened (file doesn't exist or in not valid), the
577        return value is NULL.
578      Else, the return value is a unzFile Handle, usable with other function
579        of this unzip package.
580 */
581 local unzFile unzOpenInternal (const void *path,
582                                zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
583                                int is64bitOpenFunction)
584 {
585     unz64_s us;
586     unz64_s *s;
587     ZPOS64_T central_pos;
588     uLong   uL;
589 
590     uLong number_disk;          /* number of the current dist, used for
591                                    spaning ZIP, unsupported, always 0*/
592     uLong number_disk_with_CD;  /* number the the disk with central dir, used
593                                    for spaning ZIP, unsupported, always 0*/
594     ZPOS64_T number_entry_CD;      /* total number of entries in
595                                    the central dir
596                                    (same than number_entry on nospan) */
597 
598     int err=UNZ_OK;
599 
600     if (unz_copyright[0]!=' ')
601         return NULL;
602 
603     us.z_filefunc.zseek32_file = NULL;
604     us.z_filefunc.ztell32_file = NULL;
605 #ifndef __REACTOS__
606     if (pzlib_filefunc64_32_def==NULL)
607         fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
608     else
609 #endif
610         us.z_filefunc = *pzlib_filefunc64_32_def;
611     us.is64bitOpenFunction = is64bitOpenFunction;
612 
613 
614 
615     us.filestream = ZOPEN64(us.z_filefunc,
616                                                  path,
617                                                  ZLIB_FILEFUNC_MODE_READ |
618                                                  ZLIB_FILEFUNC_MODE_EXISTING);
619     if (us.filestream==NULL)
620         return NULL;
621 
622     central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
623     if (central_pos)
624     {
625         uLong uS;
626         ZPOS64_T uL64;
627 
628         us.isZip64 = 1;
629 
630         if (ZSEEK64(us.z_filefunc, us.filestream,
631                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
632         err=UNZ_ERRNO;
633 
634         /* the signature, already checked */
635         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
636             err=UNZ_ERRNO;
637 
638         /* size of zip64 end of central directory record */
639         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)
640             err=UNZ_ERRNO;
641 
642         /* version made by */
643         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
644             err=UNZ_ERRNO;
645 
646         /* version needed to extract */
647         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
648             err=UNZ_ERRNO;
649 
650         /* number of this disk */
651         if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
652             err=UNZ_ERRNO;
653 
654         /* number of the disk with the start of the central directory */
655         if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
656             err=UNZ_ERRNO;
657 
658         /* total number of entries in the central directory on this disk */
659         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
660             err=UNZ_ERRNO;
661 
662         /* total number of entries in the central directory */
663         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
664             err=UNZ_ERRNO;
665 
666         if ((number_entry_CD!=us.gi.number_entry) ||
667             (number_disk_with_CD!=0) ||
668             (number_disk!=0))
669             err=UNZ_BADZIPFILE;
670 
671         /* size of the central directory */
672         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
673             err=UNZ_ERRNO;
674 
675         /* offset of start of central directory with respect to the
676           starting disk number */
677         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
678             err=UNZ_ERRNO;
679 
680         us.gi.size_comment = 0;
681     }
682     else
683     {
684         central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
685         if (central_pos==0)
686             err=UNZ_ERRNO;
687 
688         us.isZip64 = 0;
689 
690         if (ZSEEK64(us.z_filefunc, us.filestream,
691                                         central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
692             err=UNZ_ERRNO;
693 
694         /* the signature, already checked */
695         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
696             err=UNZ_ERRNO;
697 
698         /* number of this disk */
699         if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
700             err=UNZ_ERRNO;
701 
702         /* number of the disk with the start of the central directory */
703         if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
704             err=UNZ_ERRNO;
705 
706         /* total number of entries in the central dir on this disk */
707         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
708             err=UNZ_ERRNO;
709         us.gi.number_entry = uL;
710 
711         /* total number of entries in the central dir */
712         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
713             err=UNZ_ERRNO;
714         number_entry_CD = uL;
715 
716         if ((number_entry_CD!=us.gi.number_entry) ||
717             (number_disk_with_CD!=0) ||
718             (number_disk!=0))
719             err=UNZ_BADZIPFILE;
720 
721         /* size of the central directory */
722         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
723             err=UNZ_ERRNO;
724         us.size_central_dir = uL;
725 
726         /* offset of start of central directory with respect to the
727             starting disk number */
728         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
729             err=UNZ_ERRNO;
730         us.offset_central_dir = uL;
731 
732         /* zipfile comment length */
733         if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
734             err=UNZ_ERRNO;
735     }
736 
737     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
738         (err==UNZ_OK))
739         err=UNZ_BADZIPFILE;
740 
741     if (err!=UNZ_OK)
742     {
743         ZCLOSE64(us.z_filefunc, us.filestream);
744         return NULL;
745     }
746 
747     us.byte_before_the_zipfile = central_pos -
748                             (us.offset_central_dir+us.size_central_dir);
749     us.central_pos = central_pos;
750     us.pfile_in_zip_read = NULL;
751     us.encrypted = 0;
752 
753 
754     s=(unz64_s*)ALLOC(sizeof(unz64_s));
755     if( s != NULL)
756     {
757         *s=us;
758         unzGoToFirstFile((unzFile)s);
759     }
760     return (unzFile)s;
761 }
762 
763 #ifndef __REACTOS__
764 extern unzFile ZEXPORT unzOpen2 (const char *path,
765                                         zlib_filefunc_def* pzlib_filefunc32_def)
766 {
767     if (pzlib_filefunc32_def != NULL)
768     {
769         zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
770         fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
771         return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
772     }
773     else
774         return unzOpenInternal(path, NULL, 0);
775 }
776 #endif
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 = (uInt)(uDate&0x1f) ;
857     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
858     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
859 
860     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
861     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
862     ptm->tm_sec =  (uInt) (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,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,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,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);
1570         return err;
1571       }
1572 #else
1573       pfile_in_zip_read_info->raw=1;
1574 #endif
1575     }
1576     else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
1577     {
1578       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1579       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1580       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1581       pfile_in_zip_read_info->stream.next_in = 0;
1582       pfile_in_zip_read_info->stream.avail_in = 0;
1583 
1584       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1585       if (err == Z_OK)
1586         pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
1587       else
1588       {
1589         TRYFREE(pfile_in_zip_read_info);
1590         return err;
1591       }
1592         /* windowBits is passed < 0 to tell that there is no zlib header.
1593          * Note that in this case inflate *requires* an extra "dummy" byte
1594          * after the compressed stream in order to complete decompression and
1595          * return Z_STREAM_END.
1596          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1597          * size of both compressed and uncompressed data
1598          */
1599     }
1600     pfile_in_zip_read_info->rest_read_compressed =
1601             s->cur_file_info.compressed_size ;
1602     pfile_in_zip_read_info->rest_read_uncompressed =
1603             s->cur_file_info.uncompressed_size ;
1604 
1605 
1606     pfile_in_zip_read_info->pos_in_zipfile =
1607             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1608               iSizeVar;
1609 
1610     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1611 
1612     s->pfile_in_zip_read = pfile_in_zip_read_info;
1613                 s->encrypted = 0;
1614 
1615 #    ifndef NOUNCRYPT
1616     if (password != NULL)
1617     {
1618         int i;
1619         s->pcrc_32_tab = get_crc_table();
1620         init_keys(password,s->keys,s->pcrc_32_tab);
1621         if (ZSEEK64(s->z_filefunc, s->filestream,
1622                   s->pfile_in_zip_read->pos_in_zipfile +
1623                      s->pfile_in_zip_read->byte_before_the_zipfile,
1624                   SEEK_SET)!=0)
1625             return UNZ_INTERNALERROR;
1626         if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12)
1627             return UNZ_INTERNALERROR;
1628 
1629         for (i = 0; i<12; i++)
1630             zdecode(s->keys,s->pcrc_32_tab,source[i]);
1631 
1632         s->pfile_in_zip_read->pos_in_zipfile+=12;
1633         s->encrypted=1;
1634     }
1635 #    endif
1636 
1637 
1638     return UNZ_OK;
1639 }
1640 
1641 extern int ZEXPORT unzOpenCurrentFile (unzFile file)
1642 {
1643     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1644 }
1645 
1646 extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char*  password)
1647 {
1648     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1649 }
1650 
1651 extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw)
1652 {
1653     return unzOpenCurrentFile3(file, method, level, raw, NULL);
1654 }
1655 
1656 /** Addition for GDAL : START */
1657 
1658 extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file)
1659 {
1660     unz64_s* s;
1661     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1662     s=(unz64_s*)file;
1663     if (file==NULL)
1664         return 0; //UNZ_PARAMERROR;
1665     pfile_in_zip_read_info=s->pfile_in_zip_read;
1666     if (pfile_in_zip_read_info==NULL)
1667         return 0; //UNZ_PARAMERROR;
1668     return pfile_in_zip_read_info->pos_in_zipfile +
1669                          pfile_in_zip_read_info->byte_before_the_zipfile;
1670 }
1671 
1672 /** Addition for GDAL : END */
1673 
1674 /*
1675   Read bytes from the current file.
1676   buf contain buffer where data must be copied
1677   len the size of buf.
1678 
1679   return the number of byte copied if somes bytes are copied
1680   return 0 if the end of file was reached
1681   return <0 with error code if there is an error
1682     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1683 */
1684 extern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)
1685 {
1686     int err=UNZ_OK;
1687     uInt iRead = 0;
1688     unz64_s* s;
1689     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1690     if (file==NULL)
1691         return UNZ_PARAMERROR;
1692     s=(unz64_s*)file;
1693     pfile_in_zip_read_info=s->pfile_in_zip_read;
1694 
1695     if (pfile_in_zip_read_info==NULL)
1696         return UNZ_PARAMERROR;
1697 
1698 
1699     if (pfile_in_zip_read_info->read_buffer == NULL)
1700         return UNZ_END_OF_LIST_OF_FILE;
1701     if (len==0)
1702         return 0;
1703 
1704     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1705 
1706     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1707 
1708     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1709         (!(pfile_in_zip_read_info->raw)))
1710         pfile_in_zip_read_info->stream.avail_out =
1711             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1712 
1713     if ((len>pfile_in_zip_read_info->rest_read_compressed+
1714            pfile_in_zip_read_info->stream.avail_in) &&
1715          (pfile_in_zip_read_info->raw))
1716         pfile_in_zip_read_info->stream.avail_out =
1717             (uInt)pfile_in_zip_read_info->rest_read_compressed+
1718             pfile_in_zip_read_info->stream.avail_in;
1719 
1720     while (pfile_in_zip_read_info->stream.avail_out>0)
1721     {
1722         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1723             (pfile_in_zip_read_info->rest_read_compressed>0))
1724         {
1725             uInt uReadThis = UNZ_BUFSIZE;
1726             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1727                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1728             if (uReadThis == 0)
1729                 return UNZ_EOF;
1730             if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
1731                       pfile_in_zip_read_info->filestream,
1732                       pfile_in_zip_read_info->pos_in_zipfile +
1733                          pfile_in_zip_read_info->byte_before_the_zipfile,
1734                          ZLIB_FILEFUNC_SEEK_SET)!=0)
1735                 return UNZ_ERRNO;
1736             if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
1737                       pfile_in_zip_read_info->filestream,
1738                       pfile_in_zip_read_info->read_buffer,
1739                       uReadThis)!=uReadThis)
1740                 return UNZ_ERRNO;
1741 
1742 
1743 #            ifndef NOUNCRYPT
1744             if(s->encrypted)
1745             {
1746                 uInt i;
1747                 for(i=0;i<uReadThis;i++)
1748                   pfile_in_zip_read_info->read_buffer[i] =
1749                       zdecode(s->keys,s->pcrc_32_tab,
1750                               pfile_in_zip_read_info->read_buffer[i]);
1751             }
1752 #            endif
1753 
1754 
1755             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1756 
1757             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1758 
1759             pfile_in_zip_read_info->stream.next_in =
1760                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1761             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1762         }
1763 
1764         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1765         {
1766             uInt uDoCopy,i ;
1767 
1768             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1769                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1770                 return (iRead==0) ? UNZ_EOF : iRead;
1771 
1772             if (pfile_in_zip_read_info->stream.avail_out <
1773                             pfile_in_zip_read_info->stream.avail_in)
1774                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1775             else
1776                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1777 
1778             for (i=0;i<uDoCopy;i++)
1779                 *(pfile_in_zip_read_info->stream.next_out+i) =
1780                         *(pfile_in_zip_read_info->stream.next_in+i);
1781 
1782             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;
1783 
1784             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1785                                 pfile_in_zip_read_info->stream.next_out,
1786                                 uDoCopy);
1787             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1788             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1789             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1790             pfile_in_zip_read_info->stream.next_out += uDoCopy;
1791             pfile_in_zip_read_info->stream.next_in += uDoCopy;
1792             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1793             iRead += uDoCopy;
1794         }
1795         else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)
1796         {
1797 #ifdef HAVE_BZIP2
1798             uLong uTotalOutBefore,uTotalOutAfter;
1799             const Bytef *bufBefore;
1800             uLong uOutThis;
1801 
1802             pfile_in_zip_read_info->bstream.next_in        = (char*)pfile_in_zip_read_info->stream.next_in;
1803             pfile_in_zip_read_info->bstream.avail_in       = pfile_in_zip_read_info->stream.avail_in;
1804             pfile_in_zip_read_info->bstream.total_in_lo32  = pfile_in_zip_read_info->stream.total_in;
1805             pfile_in_zip_read_info->bstream.total_in_hi32  = 0;
1806             pfile_in_zip_read_info->bstream.next_out       = (char*)pfile_in_zip_read_info->stream.next_out;
1807             pfile_in_zip_read_info->bstream.avail_out      = pfile_in_zip_read_info->stream.avail_out;
1808             pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
1809             pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
1810 
1811             uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
1812             bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;
1813 
1814             err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
1815 
1816             uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
1817             uOutThis = uTotalOutAfter-uTotalOutBefore;
1818 
1819             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
1820 
1821             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis));
1822             pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
1823             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1824 
1825             pfile_in_zip_read_info->stream.next_in   = (Bytef*)pfile_in_zip_read_info->bstream.next_in;
1826             pfile_in_zip_read_info->stream.avail_in  = pfile_in_zip_read_info->bstream.avail_in;
1827             pfile_in_zip_read_info->stream.total_in  = pfile_in_zip_read_info->bstream.total_in_lo32;
1828             pfile_in_zip_read_info->stream.next_out  = (Bytef*)pfile_in_zip_read_info->bstream.next_out;
1829             pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
1830             pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
1831 
1832             if (err==BZ_STREAM_END)
1833               return (iRead==0) ? UNZ_EOF : iRead;
1834             if (err!=BZ_OK)
1835               break;
1836 #endif
1837         } // end Z_BZIP2ED
1838         else
1839         {
1840             ZPOS64_T uTotalOutBefore,uTotalOutAfter;
1841             const Bytef *bufBefore;
1842             ZPOS64_T uOutThis;
1843             int flush=Z_SYNC_FLUSH;
1844 
1845             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1846             bufBefore = pfile_in_zip_read_info->stream.next_out;
1847 
1848             /*
1849             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1850                      pfile_in_zip_read_info->stream.avail_out) &&
1851                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1852                 flush = Z_FINISH;
1853             */
1854             err=inflate(&pfile_in_zip_read_info->stream,flush);
1855 
1856             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1857               err = Z_DATA_ERROR;
1858 
1859             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1860             uOutThis = uTotalOutAfter-uTotalOutBefore;
1861 
1862             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
1863 
1864             pfile_in_zip_read_info->crc32 =
1865                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1866                         (uInt)(uOutThis));
1867 
1868             pfile_in_zip_read_info->rest_read_uncompressed -=
1869                 uOutThis;
1870 
1871             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1872 
1873             if (err==Z_STREAM_END)
1874                 return (iRead==0) ? UNZ_EOF : iRead;
1875             if (err!=Z_OK)
1876                 break;
1877         }
1878     }
1879 
1880     if (err==Z_OK)
1881         return iRead;
1882     return err;
1883 }
1884 
1885 
1886 /*
1887   Give the current position in uncompressed data
1888 */
1889 extern z_off_t ZEXPORT unztell (unzFile file)
1890 {
1891     unz64_s* s;
1892     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1893     if (file==NULL)
1894         return UNZ_PARAMERROR;
1895     s=(unz64_s*)file;
1896     pfile_in_zip_read_info=s->pfile_in_zip_read;
1897 
1898     if (pfile_in_zip_read_info==NULL)
1899         return UNZ_PARAMERROR;
1900 
1901     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1902 }
1903 
1904 extern ZPOS64_T ZEXPORT unztell64 (unzFile file)
1905 {
1906 
1907     unz64_s* s;
1908     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1909     if (file==NULL)
1910         return (ZPOS64_T)-1;
1911     s=(unz64_s*)file;
1912     pfile_in_zip_read_info=s->pfile_in_zip_read;
1913 
1914     if (pfile_in_zip_read_info==NULL)
1915         return (ZPOS64_T)-1;
1916 
1917     return pfile_in_zip_read_info->total_out_64;
1918 }
1919 
1920 
1921 /*
1922   return 1 if the end of file was reached, 0 elsewhere
1923 */
1924 extern int ZEXPORT unzeof (unzFile file)
1925 {
1926     unz64_s* s;
1927     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1928     if (file==NULL)
1929         return UNZ_PARAMERROR;
1930     s=(unz64_s*)file;
1931     pfile_in_zip_read_info=s->pfile_in_zip_read;
1932 
1933     if (pfile_in_zip_read_info==NULL)
1934         return UNZ_PARAMERROR;
1935 
1936     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1937         return 1;
1938     else
1939         return 0;
1940 }
1941 
1942 
1943 
1944 /*
1945 Read extra field from the current file (opened by unzOpenCurrentFile)
1946 This is the local-header version of the extra field (sometimes, there is
1947 more info in the local-header version than in the central-header)
1948 
1949   if buf==NULL, it return the size of the local extra field that can be read
1950 
1951   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1952     buf.
1953   the return value is the number of bytes copied in buf, or (if <0)
1954     the error code
1955 */
1956 extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
1957 {
1958     unz64_s* s;
1959     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1960     uInt read_now;
1961     ZPOS64_T size_to_read;
1962 
1963     if (file==NULL)
1964         return UNZ_PARAMERROR;
1965     s=(unz64_s*)file;
1966     pfile_in_zip_read_info=s->pfile_in_zip_read;
1967 
1968     if (pfile_in_zip_read_info==NULL)
1969         return UNZ_PARAMERROR;
1970 
1971     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1972                 pfile_in_zip_read_info->pos_local_extrafield);
1973 
1974     if (buf==NULL)
1975         return (int)size_to_read;
1976 
1977     if (len>size_to_read)
1978         read_now = (uInt)size_to_read;
1979     else
1980         read_now = (uInt)len ;
1981 
1982     if (read_now==0)
1983         return 0;
1984 
1985     if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
1986               pfile_in_zip_read_info->filestream,
1987               pfile_in_zip_read_info->offset_local_extrafield +
1988               pfile_in_zip_read_info->pos_local_extrafield,
1989               ZLIB_FILEFUNC_SEEK_SET)!=0)
1990         return UNZ_ERRNO;
1991 
1992     if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
1993               pfile_in_zip_read_info->filestream,
1994               buf,read_now)!=read_now)
1995         return UNZ_ERRNO;
1996 
1997     return (int)read_now;
1998 }
1999 
2000 /*
2001   Close the file in zip opened with unzOpenCurrentFile
2002   Return UNZ_CRCERROR if all the file was read but the CRC is not good
2003 */
2004 extern int ZEXPORT unzCloseCurrentFile (unzFile file)
2005 {
2006     int err=UNZ_OK;
2007 
2008     unz64_s* s;
2009     file_in_zip64_read_info_s* pfile_in_zip_read_info;
2010     if (file==NULL)
2011         return UNZ_PARAMERROR;
2012     s=(unz64_s*)file;
2013     pfile_in_zip_read_info=s->pfile_in_zip_read;
2014 
2015     if (pfile_in_zip_read_info==NULL)
2016         return UNZ_PARAMERROR;
2017 
2018 
2019     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
2020         (!pfile_in_zip_read_info->raw))
2021     {
2022         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
2023             err=UNZ_CRCERROR;
2024     }
2025 
2026 
2027     TRYFREE(pfile_in_zip_read_info->read_buffer);
2028     pfile_in_zip_read_info->read_buffer = NULL;
2029     if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
2030         inflateEnd(&pfile_in_zip_read_info->stream);
2031 #ifdef HAVE_BZIP2
2032     else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
2033         BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
2034 #endif
2035 
2036 
2037     pfile_in_zip_read_info->stream_initialised = 0;
2038     TRYFREE(pfile_in_zip_read_info);
2039 
2040     s->pfile_in_zip_read=NULL;
2041 
2042     return err;
2043 }
2044 
2045 
2046 /*
2047   Get the global comment string of the ZipFile, in the szComment buffer.
2048   uSizeBuf is the size of the szComment buffer.
2049   return the number of byte copied or an error code <0
2050 */
2051 extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf)
2052 {
2053     unz64_s* s;
2054     uLong uReadThis ;
2055     if (file==NULL)
2056         return (int)UNZ_PARAMERROR;
2057     s=(unz64_s*)file;
2058 
2059     uReadThis = uSizeBuf;
2060     if (uReadThis>s->gi.size_comment)
2061         uReadThis = s->gi.size_comment;
2062 
2063     if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
2064         return UNZ_ERRNO;
2065 
2066     if (uReadThis>0)
2067     {
2068       *szComment='\0';
2069       if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
2070         return UNZ_ERRNO;
2071     }
2072 
2073     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
2074         *(szComment+s->gi.size_comment)='\0';
2075     return (int)uReadThis;
2076 }
2077 
2078 /* Additions by RX '2004 */
2079 extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file)
2080 {
2081     unz64_s* s;
2082 
2083     if (file==NULL)
2084           return 0; //UNZ_PARAMERROR;
2085     s=(unz64_s*)file;
2086     if (!s->current_file_ok)
2087       return 0;
2088     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
2089       if (s->num_file==s->gi.number_entry)
2090          return 0;
2091     return s->pos_in_central_dir;
2092 }
2093 
2094 extern uLong ZEXPORT unzGetOffset (unzFile file)
2095 {
2096     ZPOS64_T offset64;
2097 
2098     if (file==NULL)
2099           return 0; //UNZ_PARAMERROR;
2100     offset64 = unzGetOffset64(file);
2101     return (uLong)offset64;
2102 }
2103 
2104 extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos)
2105 {
2106     unz64_s* s;
2107     int err;
2108 
2109     if (file==NULL)
2110         return UNZ_PARAMERROR;
2111     s=(unz64_s*)file;
2112 
2113     s->pos_in_central_dir = pos;
2114     s->num_file = s->gi.number_entry;      /* hack */
2115     err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
2116                                               &s->cur_file_info_internal,
2117                                               NULL,0,NULL,0,NULL,0);
2118     s->current_file_ok = (err == UNZ_OK);
2119     return err;
2120 }
2121 
2122 extern int ZEXPORT unzSetOffset (unzFile file, uLong pos)
2123 {
2124     return unzSetOffset64(file,pos);
2125 }
2126