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