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