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
122const 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*/
126typedef 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 */
134typedef 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*/
165typedef struct
166{
167    zlib_filefunc64_32_def z_filefunc;
168    int is64bitOpenFunction;
169    voidpf filestream;        /* io structore of the zipfile */
170    unz_global_info64 gi;       /* public global information */
171    ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
172    ZPOS64_T num_file;             /* number of the current file in the zipfile*/
173    ZPOS64_T pos_in_central_dir;   /* pos of the current file in the central dir*/
174    ZPOS64_T current_file_ok;      /* flag about the usability of the current file*/
175    ZPOS64_T central_pos;          /* position of the beginning of the central dir*/
176
177    ZPOS64_T size_central_dir;     /* size of the central directory  */
178    ZPOS64_T offset_central_dir;   /* offset of start of central directory with
179                                   respect to the starting disk number */
180
181    unz_file_info64 cur_file_info; /* public info about the current file in zip*/
182    unz_file_info64_internal cur_file_info_internal; /* private info about it*/
183    file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
184                                        file if we are decompressing it */
185    int encrypted;
186
187    int isZip64;
188
189#    ifndef NOUNCRYPT
190    unsigned long keys[3];     /* keys defining the pseudo-random sequence */
191    const z_crc_t* pcrc_32_tab;
192#    endif
193} unz64_s;
194
195
196#ifndef NOUNCRYPT
197#include "crypt.h"
198#endif
199
200/* ===========================================================================
201     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
202   for end of file.
203   IN assertion: the stream s has been sucessfully opened for reading.
204*/
205
206
207local int unz64local_getByte OF((
208    const zlib_filefunc64_32_def* pzlib_filefunc_def,
209    voidpf filestream,
210    int *pi));
211
212local 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*/
234local int unz64local_getShort OF((
235    const zlib_filefunc64_32_def* pzlib_filefunc_def,
236    voidpf filestream,
237    uLong *pX));
238
239local 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
261local int unz64local_getLong OF((
262    const zlib_filefunc64_32_def* pzlib_filefunc_def,
263    voidpf filestream,
264    uLong *pX));
265
266local 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
296local int unz64local_getLong64 OF((
297    const zlib_filefunc64_32_def* pzlib_filefunc_def,
298    voidpf filestream,
299    ZPOS64_T *pX));
300
301
302local 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 */
349local 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*/
390extern 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*/
412local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));
413local 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*/
474local ZPOS64_T unz64local_SearchCentralDir64 OF((
475    const zlib_filefunc64_32_def* pzlib_filefunc_def,
476    voidpf filestream));
477
478local 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*/
584local unzFile unzOpenInternal (const void *path,
585                               zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
586                               int is64bitOpenFunction)
587{
588    unz64_s us;
589    unz64_s *s;
590    ZPOS64_T central_pos;
591    uLong   uL;
592
593    uLong number_disk;          /* number of the current dist, used for
594                                   spaning ZIP, unsupported, always 0*/
595    uLong number_disk_with_CD;  /* number the the disk with central dir, used
596                                   for spaning ZIP, unsupported, always 0*/
597    ZPOS64_T number_entry_CD;      /* total number of entries in
598                                   the central dir
599                                   (same than number_entry on nospan) */
600
601    int err=UNZ_OK;
602
603    if (unz_copyright[0]!=' ')
604        return NULL;
605
606    us.z_filefunc.zseek32_file = NULL;
607    us.z_filefunc.ztell32_file = NULL;
608    if (pzlib_filefunc64_32_def==NULL)
609        fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
610    else
611        us.z_filefunc = *pzlib_filefunc64_32_def;
612    us.is64bitOpenFunction = is64bitOpenFunction;
613
614
615
616    us.filestream = ZOPEN64(us.z_filefunc,
617                                                 path,
618                                                 ZLIB_FILEFUNC_MODE_READ |
619                                                 ZLIB_FILEFUNC_MODE_EXISTING);
620    if (us.filestream==NULL)
621        return NULL;
622
623    central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
624    if (central_pos)
625    {
626        uLong uS;
627        ZPOS64_T uL64;
628
629        us.isZip64 = 1;
630
631        if (ZSEEK64(us.z_filefunc, us.filestream,
632                                      central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
633        err=UNZ_ERRNO;
634
635        /* the signature, already checked */
636        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
637            err=UNZ_ERRNO;
638
639        /* size of zip64 end of central directory record */
640        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)
641            err=UNZ_ERRNO;
642
643        /* version made by */
644        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
645            err=UNZ_ERRNO;
646
647        /* version needed to extract */
648        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
649            err=UNZ_ERRNO;
650
651        /* number of this disk */
652        if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
653            err=UNZ_ERRNO;
654
655        /* number of the disk with the start of the central directory */
656        if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
657            err=UNZ_ERRNO;
658
659        /* total number of entries in the central directory on this disk */
660        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
661            err=UNZ_ERRNO;
662
663        /* total number of entries in the central directory */
664        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
665            err=UNZ_ERRNO;
666
667        if ((number_entry_CD!=us.gi.number_entry) ||
668            (number_disk_with_CD!=0) ||
669            (number_disk!=0))
670            err=UNZ_BADZIPFILE;
671
672        /* size of the central directory */
673        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
674            err=UNZ_ERRNO;
675
676        /* offset of start of central directory with respect to the
677          starting disk number */
678        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
679            err=UNZ_ERRNO;
680
681        us.gi.size_comment = 0;
682    }
683    else
684    {
685        central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
686        if (central_pos==0)
687            err=UNZ_ERRNO;
688
689        us.isZip64 = 0;
690
691        if (ZSEEK64(us.z_filefunc, us.filestream,
692                                        central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
693            err=UNZ_ERRNO;
694
695        /* the signature, already checked */
696        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
697            err=UNZ_ERRNO;
698
699        /* number of this disk */
700        if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
701            err=UNZ_ERRNO;
702
703        /* number of the disk with the start of the central directory */
704        if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
705            err=UNZ_ERRNO;
706
707        /* total number of entries in the central dir on this disk */
708        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
709            err=UNZ_ERRNO;
710        us.gi.number_entry = uL;
711
712        /* total number of entries in the central dir */
713        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
714            err=UNZ_ERRNO;
715        number_entry_CD = uL;
716
717        if ((number_entry_CD!=us.gi.number_entry) ||
718            (number_disk_with_CD!=0) ||
719            (number_disk!=0))
720            err=UNZ_BADZIPFILE;
721
722        /* size of the central directory */
723        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
724            err=UNZ_ERRNO;
725        us.size_central_dir = uL;
726
727        /* offset of start of central directory with respect to the
728            starting disk number */
729        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
730            err=UNZ_ERRNO;
731        us.offset_central_dir = uL;
732
733        /* zipfile comment length */
734        if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
735            err=UNZ_ERRNO;
736    }
737
738    if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
739        (err==UNZ_OK))
740        err=UNZ_BADZIPFILE;
741
742    if (err!=UNZ_OK)
743    {
744        ZCLOSE64(us.z_filefunc, us.filestream);
745        return NULL;
746    }
747
748    us.byte_before_the_zipfile = central_pos -
749                            (us.offset_central_dir+us.size_central_dir);
750    us.central_pos = central_pos;
751    us.pfile_in_zip_read = NULL;
752    us.encrypted = 0;
753
754
755    s=(unz64_s*)ALLOC(sizeof(unz64_s));
756    if( s != NULL)
757    {
758        *s=us;
759        unzGoToFirstFile((unzFile)s);
760    }
761    return (unzFile)s;
762}
763
764
765extern unzFile ZEXPORT unzOpen2 (const char *path,
766                                        zlib_filefunc_def* pzlib_filefunc32_def)
767{
768    if (pzlib_filefunc32_def != NULL)
769    {
770        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
771        fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
772        return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
773    }
774    else
775        return unzOpenInternal(path, NULL, 0);
776}
777
778extern unzFile ZEXPORT unzOpen2_64 (const void *path,
779                                     zlib_filefunc64_def* pzlib_filefunc_def)
780{
781    if (pzlib_filefunc_def != NULL)
782    {
783        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
784        zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
785        zlib_filefunc64_32_def_fill.ztell32_file = NULL;
786        zlib_filefunc64_32_def_fill.zseek32_file = NULL;
787        return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);
788    }
789    else
790        return unzOpenInternal(path, NULL, 1);
791}
792
793extern unzFile ZEXPORT unzOpen (const char *path)
794{
795    return unzOpenInternal(path, NULL, 0);
796}
797
798extern unzFile ZEXPORT unzOpen64 (const void *path)
799{
800    return unzOpenInternal(path, NULL, 1);
801}
802
803/*
804  Close a ZipFile opened with unzOpen.
805  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
806    these files MUST be closed with unzCloseCurrentFile before call unzClose.
807  return UNZ_OK if there is no problem. */
808extern int ZEXPORT unzClose (unzFile file)
809{
810    unz64_s* s;
811    if (file==NULL)
812        return UNZ_PARAMERROR;
813    s=(unz64_s*)file;
814
815    if (s->pfile_in_zip_read!=NULL)
816        unzCloseCurrentFile(file);
817
818    ZCLOSE64(s->z_filefunc, s->filestream);
819    TRYFREE(s);
820    return UNZ_OK;
821}
822
823
824/*
825  Write info about the ZipFile in the *pglobal_info structure.
826  No preparation of the structure is needed
827  return UNZ_OK if there is no problem. */
828extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info)
829{
830    unz64_s* s;
831    if (file==NULL)
832        return UNZ_PARAMERROR;
833    s=(unz64_s*)file;
834    *pglobal_info=s->gi;
835    return UNZ_OK;
836}
837
838extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32)
839{
840    unz64_s* s;
841    if (file==NULL)
842        return UNZ_PARAMERROR;
843    s=(unz64_s*)file;
844    /* to do : check if number_entry is not truncated */
845    pglobal_info32->number_entry = (uLong)s->gi.number_entry;
846    pglobal_info32->size_comment = s->gi.size_comment;
847    return UNZ_OK;
848}
849/*
850   Translate date/time from Dos format to tm_unz (readable more easilty)
851*/
852local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)
853{
854    ZPOS64_T uDate;
855    uDate = (ZPOS64_T)(ulDosDate>>16);
856    ptm->tm_mday = (uInt)(uDate&0x1f) ;
857    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
858    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
859
860    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
861    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
862    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
863}
864
865/*
866  Get Info about the current file in the zipfile, with internal only info
867*/
868local int unz64local_GetCurrentFileInfoInternal OF((unzFile file,
869                                                  unz_file_info64 *pfile_info,
870                                                  unz_file_info64_internal
871                                                  *pfile_info_internal,
872                                                  char *szFileName,
873                                                  uLong fileNameBufferSize,
874                                                  void *extraField,
875                                                  uLong extraFieldBufferSize,
876                                                  char *szComment,
877                                                  uLong commentBufferSize));
878
879local int unz64local_GetCurrentFileInfoInternal (unzFile file,
880                                                  unz_file_info64 *pfile_info,
881                                                  unz_file_info64_internal
882                                                  *pfile_info_internal,
883                                                  char *szFileName,
884                                                  uLong fileNameBufferSize,
885                                                  void *extraField,
886                                                  uLong extraFieldBufferSize,
887                                                  char *szComment,
888                                                  uLong commentBufferSize)
889{
890    unz64_s* s;
891    unz_file_info64 file_info;
892    unz_file_info64_internal file_info_internal;
893    int err=UNZ_OK;
894    uLong uMagic;
895    long lSeek=0;
896    uLong uL;
897
898    if (file==NULL)
899        return UNZ_PARAMERROR;
900    s=(unz64_s*)file;
901    if (ZSEEK64(s->z_filefunc, s->filestream,
902              s->pos_in_central_dir+s->byte_before_the_zipfile,
903              ZLIB_FILEFUNC_SEEK_SET)!=0)
904        err=UNZ_ERRNO;
905
906
907    /* we check the magic */
908    if (err==UNZ_OK)
909    {
910        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
911            err=UNZ_ERRNO;
912        else if (uMagic!=0x02014b50)
913            err=UNZ_BADZIPFILE;
914    }
915
916    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
917        err=UNZ_ERRNO;
918
919    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
920        err=UNZ_ERRNO;
921
922    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
923        err=UNZ_ERRNO;
924
925    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
926        err=UNZ_ERRNO;
927
928    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
929        err=UNZ_ERRNO;
930
931    unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
932
933    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
934        err=UNZ_ERRNO;
935
936    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
937        err=UNZ_ERRNO;
938    file_info.compressed_size = uL;
939
940    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
941        err=UNZ_ERRNO;
942    file_info.uncompressed_size = uL;
943
944    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
945        err=UNZ_ERRNO;
946
947    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
948        err=UNZ_ERRNO;
949
950    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
951        err=UNZ_ERRNO;
952
953    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
954        err=UNZ_ERRNO;
955
956    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
957        err=UNZ_ERRNO;
958
959    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
960        err=UNZ_ERRNO;
961
962                // relative offset of local header
963    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
964        err=UNZ_ERRNO;
965    file_info_internal.offset_curfile = uL;
966
967    lSeek+=file_info.size_filename;
968    if ((err==UNZ_OK) && (szFileName!=NULL))
969    {
970        uLong uSizeRead ;
971        if (file_info.size_filename<fileNameBufferSize)
972        {
973            *(szFileName+file_info.size_filename)='\0';
974            uSizeRead = file_info.size_filename;
975        }
976        else
977            uSizeRead = fileNameBufferSize;
978
979        if ((file_info.size_filename>0) && (fileNameBufferSize>0))
980            if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
981                err=UNZ_ERRNO;
982        lSeek -= uSizeRead;
983    }
984
985    // Read extrafield
986    if ((err==UNZ_OK) && (extraField!=NULL))
987    {
988        ZPOS64_T uSizeRead ;
989        if (file_info.size_file_extra<extraFieldBufferSize)
990            uSizeRead = file_info.size_file_extra;
991        else
992            uSizeRead = extraFieldBufferSize;
993
994        if (lSeek!=0)
995        {
996            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
997                lSeek=0;
998            else
999                err=UNZ_ERRNO;
1000        }
1001
1002        if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
1003            if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead)
1004                err=UNZ_ERRNO;
1005
1006        lSeek += file_info.size_file_extra - (uLong)uSizeRead;
1007    }
1008    else
1009        lSeek += file_info.size_file_extra;
1010
1011
1012    if ((err==UNZ_OK) && (file_info.size_file_extra != 0))
1013    {
1014                                uLong acc = 0;
1015
1016        // since lSeek now points to after the extra field we need to move back
1017        lSeek -= file_info.size_file_extra;
1018
1019        if (lSeek!=0)
1020        {
1021            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
1022                lSeek=0;
1023            else
1024                err=UNZ_ERRNO;
1025        }
1026
1027        while(acc < file_info.size_file_extra)
1028        {
1029            uLong headerId;
1030                                                uLong dataSize;
1031
1032            if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
1033                err=UNZ_ERRNO;
1034
1035            if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
1036                err=UNZ_ERRNO;
1037
1038            /* ZIP64 extra fields */
1039            if (headerId == 0x0001)
1040            {
1041                                                        uLong uL;
1042
1043                                                                if(file_info.uncompressed_size == MAXU32)
1044                                                                {
1045                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
1046                                                                                        err=UNZ_ERRNO;
1047                                                                }
1048
1049                                                                if(file_info.compressed_size == MAXU32)
1050                                                                {
1051                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
1052                                                                                  err=UNZ_ERRNO;
1053                                                                }
1054
1055                                                                if(file_info_internal.offset_curfile == MAXU32)
1056                                                                {
1057                                                                        /* Relative Header offset */
1058                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
1059                                                                                err=UNZ_ERRNO;
1060                                                                }
1061
1062                                                                if(file_info.disk_num_start == MAXU32)
1063                                                                {
1064                                                                        /* Disk Start Number */
1065                                                                        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
1066                                                                                err=UNZ_ERRNO;
1067                                                                }
1068
1069            }
1070            else
1071            {
1072                if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
1073                    err=UNZ_ERRNO;
1074            }
1075
1076            acc += 2 + 2 + dataSize;
1077        }
1078    }
1079
1080    if ((err==UNZ_OK) && (szComment!=NULL))
1081    {
1082        uLong uSizeRead ;
1083        if (file_info.size_file_comment<commentBufferSize)
1084        {
1085            *(szComment+file_info.size_file_comment)='\0';
1086            uSizeRead = file_info.size_file_comment;
1087        }
1088        else
1089            uSizeRead = commentBufferSize;
1090
1091        if (lSeek!=0)
1092        {
1093            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
1094                lSeek=0;
1095            else
1096                err=UNZ_ERRNO;
1097        }
1098
1099        if ((file_info.size_file_comment>0) && (commentBufferSize>0))
1100            if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
1101                err=UNZ_ERRNO;
1102        lSeek+=file_info.size_file_comment - uSizeRead;
1103    }
1104    else
1105        lSeek+=file_info.size_file_comment;
1106
1107
1108    if ((err==UNZ_OK) && (pfile_info!=NULL))
1109        *pfile_info=file_info;
1110
1111    if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
1112        *pfile_info_internal=file_info_internal;
1113
1114    return err;
1115}
1116
1117
1118
1119/*
1120  Write info about the ZipFile in the *pglobal_info structure.
1121  No preparation of the structure is needed
1122  return UNZ_OK if there is no problem.
1123*/
1124extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file,
1125                                          unz_file_info64 * pfile_info,
1126                                          char * szFileName, uLong fileNameBufferSize,
1127                                          void *extraField, uLong extraFieldBufferSize,
1128                                          char* szComment,  uLong commentBufferSize)
1129{
1130    return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
1131                                                szFileName,fileNameBufferSize,
1132                                                extraField,extraFieldBufferSize,
1133                                                szComment,commentBufferSize);
1134}
1135
1136extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
1137                                          unz_file_info * pfile_info,
1138                                          char * szFileName, uLong fileNameBufferSize,
1139                                          void *extraField, uLong extraFieldBufferSize,
1140                                          char* szComment,  uLong commentBufferSize)
1141{
1142    int err;
1143    unz_file_info64 file_info64;
1144    err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL,
1145                                                szFileName,fileNameBufferSize,
1146                                                extraField,extraFieldBufferSize,
1147                                                szComment,commentBufferSize);
1148    if ((err==UNZ_OK) && (pfile_info != NULL))
1149    {
1150        pfile_info->version = file_info64.version;
1151        pfile_info->version_needed = file_info64.version_needed;
1152        pfile_info->flag = file_info64.flag;
1153        pfile_info->compression_method = file_info64.compression_method;
1154        pfile_info->dosDate = file_info64.dosDate;
1155        pfile_info->crc = file_info64.crc;
1156
1157        pfile_info->size_filename = file_info64.size_filename;
1158        pfile_info->size_file_extra = file_info64.size_file_extra;
1159        pfile_info->size_file_comment = file_info64.size_file_comment;
1160
1161        pfile_info->disk_num_start = file_info64.disk_num_start;
1162        pfile_info->internal_fa = file_info64.internal_fa;
1163        pfile_info->external_fa = file_info64.external_fa;
1164
1165        pfile_info->tmu_date = file_info64.tmu_date,
1166
1167
1168        pfile_info->compressed_size = (uLong)file_info64.compressed_size;
1169        pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;
1170
1171    }
1172    return err;
1173}
1174/*
1175  Set the current file of the zipfile to the first file.
1176  return UNZ_OK if there is no problem
1177*/
1178extern int ZEXPORT unzGoToFirstFile (unzFile file)
1179{
1180    int err=UNZ_OK;
1181    unz64_s* s;
1182    if (file==NULL)
1183        return UNZ_PARAMERROR;
1184    s=(unz64_s*)file;
1185    s->pos_in_central_dir=s->offset_central_dir;
1186    s->num_file=0;
1187    err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1188                                             &s->cur_file_info_internal,
1189                                             NULL,0,NULL,0,NULL,0);
1190    s->current_file_ok = (err == UNZ_OK);
1191    return err;
1192}
1193
1194/*
1195  Set the current file of the zipfile to the next file.
1196  return UNZ_OK if there is no problem
1197  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
1198*/
1199extern int ZEXPORT unzGoToNextFile (unzFile  file)
1200{
1201    unz64_s* s;
1202    int err;
1203
1204    if (file==NULL)
1205        return UNZ_PARAMERROR;
1206    s=(unz64_s*)file;
1207    if (!s->current_file_ok)
1208        return UNZ_END_OF_LIST_OF_FILE;
1209    if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
1210      if (s->num_file+1==s->gi.number_entry)
1211        return UNZ_END_OF_LIST_OF_FILE;
1212
1213    s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
1214            s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
1215    s->num_file++;
1216    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1217                                               &s->cur_file_info_internal,
1218                                               NULL,0,NULL,0,NULL,0);
1219    s->current_file_ok = (err == UNZ_OK);
1220    return err;
1221}
1222
1223
1224/*
1225  Try locate the file szFileName in the zipfile.
1226  For the iCaseSensitivity signification, see unzStringFileNameCompare
1227
1228  return value :
1229  UNZ_OK if the file is found. It becomes the current file.
1230  UNZ_END_OF_LIST_OF_FILE if the file is not found
1231*/
1232extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
1233{
1234    unz64_s* s;
1235    int err;
1236
1237    /* We remember the 'current' position in the file so that we can jump
1238     * back there if we fail.
1239     */
1240    unz_file_info64 cur_file_infoSaved;
1241    unz_file_info64_internal cur_file_info_internalSaved;
1242    ZPOS64_T num_fileSaved;
1243    ZPOS64_T pos_in_central_dirSaved;
1244
1245
1246    if (file==NULL)
1247        return UNZ_PARAMERROR;
1248
1249    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
1250        return UNZ_PARAMERROR;
1251
1252    s=(unz64_s*)file;
1253    if (!s->current_file_ok)
1254        return UNZ_END_OF_LIST_OF_FILE;
1255
1256    /* Save the current state */
1257    num_fileSaved = s->num_file;
1258    pos_in_central_dirSaved = s->pos_in_central_dir;
1259    cur_file_infoSaved = s->cur_file_info;
1260    cur_file_info_internalSaved = s->cur_file_info_internal;
1261
1262    err = unzGoToFirstFile(file);
1263
1264    while (err == UNZ_OK)
1265    {
1266        char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
1267        err = unzGetCurrentFileInfo64(file,NULL,
1268                                    szCurrentFileName,sizeof(szCurrentFileName)-1,
1269                                    NULL,0,NULL,0);
1270        if (err == UNZ_OK)
1271        {
1272            if (unzStringFileNameCompare(szCurrentFileName,
1273                                            szFileName,iCaseSensitivity)==0)
1274                return UNZ_OK;
1275            err = unzGoToNextFile(file);
1276        }
1277    }
1278
1279    /* We failed, so restore the state of the 'current file' to where we
1280     * were.
1281     */
1282    s->num_file = num_fileSaved ;
1283    s->pos_in_central_dir = pos_in_central_dirSaved ;
1284    s->cur_file_info = cur_file_infoSaved;
1285    s->cur_file_info_internal = cur_file_info_internalSaved;
1286    return err;
1287}
1288
1289
1290/*
1291///////////////////////////////////////////
1292// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
1293// I need random access
1294//
1295// Further optimization could be realized by adding an ability
1296// to cache the directory in memory. The goal being a single
1297// comprehensive file read to put the file I need in a memory.
1298*/
1299
1300/*
1301typedef struct unz_file_pos_s
1302{
1303    ZPOS64_T pos_in_zip_directory;   // offset in file
1304    ZPOS64_T num_of_file;            // # of file
1305} unz_file_pos;
1306*/
1307
1308extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos*  file_pos)
1309{
1310    unz64_s* s;
1311
1312    if (file==NULL || file_pos==NULL)
1313        return UNZ_PARAMERROR;
1314    s=(unz64_s*)file;
1315    if (!s->current_file_ok)
1316        return UNZ_END_OF_LIST_OF_FILE;
1317
1318    file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
1319    file_pos->num_of_file           = s->num_file;
1320
1321    return UNZ_OK;
1322}
1323
1324extern int ZEXPORT unzGetFilePos(
1325    unzFile file,
1326    unz_file_pos* file_pos)
1327{
1328    unz64_file_pos file_pos64;
1329    int err = unzGetFilePos64(file,&file_pos64);
1330    if (err==UNZ_OK)
1331    {
1332        file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;
1333        file_pos->num_of_file = (uLong)file_pos64.num_of_file;
1334    }
1335    return err;
1336}
1337
1338extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos)
1339{
1340    unz64_s* s;
1341    int err;
1342
1343    if (file==NULL || file_pos==NULL)
1344        return UNZ_PARAMERROR;
1345    s=(unz64_s*)file;
1346
1347    /* jump to the right spot */
1348    s->pos_in_central_dir = file_pos->pos_in_zip_directory;
1349    s->num_file           = file_pos->num_of_file;
1350
1351    /* set the current file */
1352    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1353                                               &s->cur_file_info_internal,
1354                                               NULL,0,NULL,0,NULL,0);
1355    /* return results */
1356    s->current_file_ok = (err == UNZ_OK);
1357    return err;
1358}
1359
1360extern int ZEXPORT unzGoToFilePos(
1361    unzFile file,
1362    unz_file_pos* file_pos)
1363{
1364    unz64_file_pos file_pos64;
1365    if (file_pos == NULL)
1366        return UNZ_PARAMERROR;
1367
1368    file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
1369    file_pos64.num_of_file = file_pos->num_of_file;
1370    return unzGoToFilePos64(file,&file_pos64);
1371}
1372
1373/*
1374// Unzip Helper Functions - should be here?
1375///////////////////////////////////////////
1376*/
1377
1378/*
1379  Read the local header of the current zipfile
1380  Check the coherency of the local header and info in the end of central
1381        directory about this file
1382  store in *piSizeVar the size of extra info in local header
1383        (filename and size of extra field data)
1384*/
1385local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar,
1386                                                    ZPOS64_T * poffset_local_extrafield,
1387                                                    uInt  * psize_local_extrafield)
1388{
1389    uLong uMagic,uData,uFlags;
1390    uLong size_filename;
1391    uLong size_extra_field;
1392    int err=UNZ_OK;
1393
1394    *piSizeVar = 0;
1395    *poffset_local_extrafield = 0;
1396    *psize_local_extrafield = 0;
1397
1398    if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
1399                                s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
1400        return UNZ_ERRNO;
1401
1402
1403    if (err==UNZ_OK)
1404    {
1405        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
1406            err=UNZ_ERRNO;
1407        else if (uMagic!=0x04034b50)
1408            err=UNZ_BADZIPFILE;
1409    }
1410
1411    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1412        err=UNZ_ERRNO;
1413/*
1414    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1415        err=UNZ_BADZIPFILE;
1416*/
1417    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
1418        err=UNZ_ERRNO;
1419
1420    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1421        err=UNZ_ERRNO;
1422    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1423        err=UNZ_BADZIPFILE;
1424
1425    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1426/* #ifdef HAVE_BZIP2 */
1427                         (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
1428/* #endif */
1429                         (s->cur_file_info.compression_method!=Z_DEFLATED))
1430        err=UNZ_BADZIPFILE;
1431
1432    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1433        err=UNZ_ERRNO;
1434
1435    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1436        err=UNZ_ERRNO;
1437    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0))
1438        err=UNZ_BADZIPFILE;
1439
1440    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1441        err=UNZ_ERRNO;
1442    else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0))
1443        err=UNZ_BADZIPFILE;
1444
1445    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1446        err=UNZ_ERRNO;
1447    else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0))
1448        err=UNZ_BADZIPFILE;
1449
1450    if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1451        err=UNZ_ERRNO;
1452    else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1453        err=UNZ_BADZIPFILE;
1454
1455    *piSizeVar += (uInt)size_filename;
1456
1457    if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1458        err=UNZ_ERRNO;
1459    *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1460                                    SIZEZIPLOCALHEADER + size_filename;
1461    *psize_local_extrafield = (uInt)size_extra_field;
1462
1463    *piSizeVar += (uInt)size_extra_field;
1464
1465    return err;
1466}
1467
1468/*
1469  Open for reading data the current file in the zipfile.
1470  If there is no error and the file is opened, the return value is UNZ_OK.
1471*/
1472extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
1473                                            int* level, int raw, const char* password)
1474{
1475    int err=UNZ_OK;
1476    uInt iSizeVar;
1477    unz64_s* s;
1478    file_in_zip64_read_info_s* pfile_in_zip_read_info;
1479    ZPOS64_T offset_local_extrafield;  /* offset of the local extra field */
1480    uInt  size_local_extrafield;    /* size of the local extra field */
1481#    ifndef NOUNCRYPT
1482    char source[12];
1483#    else
1484    if (password != NULL)
1485        return UNZ_PARAMERROR;
1486#    endif
1487
1488    if (file==NULL)
1489        return UNZ_PARAMERROR;
1490    s=(unz64_s*)file;
1491    if (!s->current_file_ok)
1492        return UNZ_PARAMERROR;
1493
1494    if (s->pfile_in_zip_read != NULL)
1495        unzCloseCurrentFile(file);
1496
1497    if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1498        return UNZ_BADZIPFILE;
1499
1500    pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
1501    if (pfile_in_zip_read_info==NULL)
1502        return UNZ_INTERNALERROR;
1503
1504    pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1505    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1506    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1507    pfile_in_zip_read_info->pos_local_extrafield=0;
1508    pfile_in_zip_read_info->raw=raw;
1509
1510    if (pfile_in_zip_read_info->read_buffer==NULL)
1511    {
1512        TRYFREE(pfile_in_zip_read_info);
1513        return UNZ_INTERNALERROR;
1514    }
1515
1516    pfile_in_zip_read_info->stream_initialised=0;
1517
1518    if (method!=NULL)
1519        *method = (int)s->cur_file_info.compression_method;
1520
1521    if (level!=NULL)
1522    {
1523        *level = 6;
1524        switch (s->cur_file_info.flag & 0x06)
1525        {
1526          case 6 : *level = 1; break;
1527          case 4 : *level = 2; break;
1528          case 2 : *level = 9; break;
1529        }
1530    }
1531
1532    if ((s->cur_file_info.compression_method!=0) &&
1533/* #ifdef HAVE_BZIP2 */
1534        (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
1535/* #endif */
1536        (s->cur_file_info.compression_method!=Z_DEFLATED))
1537
1538        err=UNZ_BADZIPFILE;
1539
1540    pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1541    pfile_in_zip_read_info->crc32=0;
1542    pfile_in_zip_read_info->total_out_64=0;
1543    pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
1544    pfile_in_zip_read_info->filestream=s->filestream;
1545    pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1546    pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1547
1548    pfile_in_zip_read_info->stream.total_out = 0;
1549
1550    if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw))
1551    {
1552#ifdef HAVE_BZIP2
1553      pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
1554      pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
1555      pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
1556      pfile_in_zip_read_info->bstream.state = (voidpf)0;
1557
1558      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1559      pfile_in_zip_read_info->stream.zfree = (free_func)0;
1560      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1561      pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1562      pfile_in_zip_read_info->stream.avail_in = 0;
1563
1564      err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
1565      if (err == Z_OK)
1566        pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;
1567      else
1568      {
1569        TRYFREE(pfile_in_zip_read_info);
1570        return err;
1571      }
1572#else
1573      pfile_in_zip_read_info->raw=1;
1574#endif
1575    }
1576    else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
1577    {
1578      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1579      pfile_in_zip_read_info->stream.zfree = (free_func)0;
1580      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1581      pfile_in_zip_read_info->stream.next_in = 0;
1582      pfile_in_zip_read_info->stream.avail_in = 0;
1583
1584      err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1585      if (err == Z_OK)
1586        pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
1587      else
1588      {
1589        TRYFREE(pfile_in_zip_read_info);
1590        return err;
1591      }
1592        /* windowBits is passed < 0 to tell that there is no zlib header.
1593         * Note that in this case inflate *requires* an extra "dummy" byte
1594         * after the compressed stream in order to complete decompression and
1595         * return Z_STREAM_END.
1596         * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1597         * size of both compressed and uncompressed data
1598         */
1599    }
1600    pfile_in_zip_read_info->rest_read_compressed =
1601            s->cur_file_info.compressed_size ;
1602    pfile_in_zip_read_info->rest_read_uncompressed =
1603            s->cur_file_info.uncompressed_size ;
1604
1605
1606    pfile_in_zip_read_info->pos_in_zipfile =
1607            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1608              iSizeVar;
1609
1610    pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1611
1612    s->pfile_in_zip_read = pfile_in_zip_read_info;
1613                s->encrypted = 0;
1614
1615#    ifndef NOUNCRYPT
1616    if (password != NULL)
1617    {
1618        int i;
1619        s->pcrc_32_tab = get_crc_table();
1620        init_keys(password,s->keys,s->pcrc_32_tab);
1621        if (ZSEEK64(s->z_filefunc, s->filestream,
1622                  s->pfile_in_zip_read->pos_in_zipfile +
1623                     s->pfile_in_zip_read->byte_before_the_zipfile,
1624                  SEEK_SET)!=0)
1625            return UNZ_INTERNALERROR;
1626        if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12)
1627            return UNZ_INTERNALERROR;
1628
1629        for (i = 0; i<12; i++)
1630            zdecode(s->keys,s->pcrc_32_tab,source[i]);
1631
1632        s->pfile_in_zip_read->pos_in_zipfile+=12;
1633        s->encrypted=1;
1634    }
1635#    endif
1636
1637
1638    return UNZ_OK;
1639}
1640
1641extern int ZEXPORT unzOpenCurrentFile (unzFile file)
1642{
1643    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1644}
1645
1646extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char*  password)
1647{
1648    return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1649}
1650
1651extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw)
1652{
1653    return unzOpenCurrentFile3(file, method, level, raw, NULL);
1654}
1655
1656/** Addition for GDAL : START */
1657
1658extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file)
1659{
1660    unz64_s* s;
1661    file_in_zip64_read_info_s* pfile_in_zip_read_info;
1662    s=(unz64_s*)file;
1663    if (file==NULL)
1664        return 0; //UNZ_PARAMERROR;
1665    pfile_in_zip_read_info=s->pfile_in_zip_read;
1666    if (pfile_in_zip_read_info==NULL)
1667        return 0; //UNZ_PARAMERROR;
1668    return pfile_in_zip_read_info->pos_in_zipfile +
1669                         pfile_in_zip_read_info->byte_before_the_zipfile;
1670}
1671
1672/** Addition for GDAL : END */
1673
1674/*
1675  Read bytes from the current file.
1676  buf contain buffer where data must be copied
1677  len the size of buf.
1678
1679  return the number of byte copied if somes bytes are copied
1680  return 0 if the end of file was reached
1681  return <0 with error code if there is an error
1682    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1683*/
1684extern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)
1685{
1686    int err=UNZ_OK;
1687    uInt iRead = 0;
1688    unz64_s* s;
1689    file_in_zip64_read_info_s* pfile_in_zip_read_info;
1690    if (file==NULL)
1691        return UNZ_PARAMERROR;
1692    s=(unz64_s*)file;
1693    pfile_in_zip_read_info=s->pfile_in_zip_read;
1694
1695    if (pfile_in_zip_read_info==NULL)
1696        return UNZ_PARAMERROR;
1697
1698
1699    if (pfile_in_zip_read_info->read_buffer == NULL)
1700        return UNZ_END_OF_LIST_OF_FILE;
1701    if (len==0)
1702        return 0;
1703
1704    pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1705
1706    pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1707
1708    if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1709        (!(pfile_in_zip_read_info->raw)))
1710        pfile_in_zip_read_info->stream.avail_out =
1711            (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1712
1713    if ((len>pfile_in_zip_read_info->rest_read_compressed+
1714           pfile_in_zip_read_info->stream.avail_in) &&
1715         (pfile_in_zip_read_info->raw))
1716        pfile_in_zip_read_info->stream.avail_out =
1717            (uInt)pfile_in_zip_read_info->rest_read_compressed+
1718            pfile_in_zip_read_info->stream.avail_in;
1719
1720    while (pfile_in_zip_read_info->stream.avail_out>0)
1721    {
1722        if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1723            (pfile_in_zip_read_info->rest_read_compressed>0))
1724        {
1725            uInt uReadThis = UNZ_BUFSIZE;
1726            if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1727                uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1728            if (uReadThis == 0)
1729                return UNZ_EOF;
1730            if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
1731                      pfile_in_zip_read_info->filestream,
1732                      pfile_in_zip_read_info->pos_in_zipfile +
1733                         pfile_in_zip_read_info->byte_before_the_zipfile,
1734                         ZLIB_FILEFUNC_SEEK_SET)!=0)
1735                return UNZ_ERRNO;
1736            if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
1737                      pfile_in_zip_read_info->filestream,
1738                      pfile_in_zip_read_info->read_buffer,
1739                      uReadThis)!=uReadThis)
1740                return UNZ_ERRNO;
1741
1742
1743#            ifndef NOUNCRYPT
1744            if(s->encrypted)
1745            {
1746                uInt i;
1747                for(i=0;i<uReadThis;i++)
1748                  pfile_in_zip_read_info->read_buffer[i] =
1749                      zdecode(s->keys,s->pcrc_32_tab,
1750                              pfile_in_zip_read_info->read_buffer[i]);
1751            }
1752#            endif
1753
1754
1755            pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1756
1757            pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1758
1759            pfile_in_zip_read_info->stream.next_in =
1760                (Bytef*)pfile_in_zip_read_info->read_buffer;
1761            pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1762        }
1763
1764        if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1765        {
1766            uInt uDoCopy,i ;
1767
1768            if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1769                (pfile_in_zip_read_info->rest_read_compressed == 0))
1770                return (iRead==0) ? UNZ_EOF : iRead;
1771
1772            if (pfile_in_zip_read_info->stream.avail_out <
1773                            pfile_in_zip_read_info->stream.avail_in)
1774                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1775            else
1776                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1777
1778            for (i=0;i<uDoCopy;i++)
1779                *(pfile_in_zip_read_info->stream.next_out+i) =
1780                        *(pfile_in_zip_read_info->stream.next_in+i);
1781
1782            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;
1783
1784            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1785                                pfile_in_zip_read_info->stream.next_out,
1786                                uDoCopy);
1787            pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1788            pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1789            pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1790            pfile_in_zip_read_info->stream.next_out += uDoCopy;
1791            pfile_in_zip_read_info->stream.next_in += uDoCopy;
1792            pfile_in_zip_read_info->stream.total_out += uDoCopy;
1793            iRead += uDoCopy;
1794        }
1795        else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)
1796        {
1797#ifdef HAVE_BZIP2
1798            uLong uTotalOutBefore,uTotalOutAfter;
1799            const Bytef *bufBefore;
1800            uLong uOutThis;
1801
1802            pfile_in_zip_read_info->bstream.next_in        = (char*)pfile_in_zip_read_info->stream.next_in;
1803            pfile_in_zip_read_info->bstream.avail_in       = pfile_in_zip_read_info->stream.avail_in;
1804            pfile_in_zip_read_info->bstream.total_in_lo32  = pfile_in_zip_read_info->stream.total_in;
1805            pfile_in_zip_read_info->bstream.total_in_hi32  = 0;
1806            pfile_in_zip_read_info->bstream.next_out       = (char*)pfile_in_zip_read_info->stream.next_out;
1807            pfile_in_zip_read_info->bstream.avail_out      = pfile_in_zip_read_info->stream.avail_out;
1808            pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
1809            pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
1810
1811            uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
1812            bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;
1813
1814            err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
1815
1816            uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
1817            uOutThis = uTotalOutAfter-uTotalOutBefore;
1818
1819            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
1820
1821            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis));
1822            pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
1823            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1824
1825            pfile_in_zip_read_info->stream.next_in   = (Bytef*)pfile_in_zip_read_info->bstream.next_in;
1826            pfile_in_zip_read_info->stream.avail_in  = pfile_in_zip_read_info->bstream.avail_in;
1827            pfile_in_zip_read_info->stream.total_in  = pfile_in_zip_read_info->bstream.total_in_lo32;
1828            pfile_in_zip_read_info->stream.next_out  = (Bytef*)pfile_in_zip_read_info->bstream.next_out;
1829            pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
1830            pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
1831
1832            if (err==BZ_STREAM_END)
1833              return (iRead==0) ? UNZ_EOF : iRead;
1834            if (err!=BZ_OK)
1835              break;
1836#endif
1837        } // end Z_BZIP2ED
1838        else
1839        {
1840            ZPOS64_T uTotalOutBefore,uTotalOutAfter;
1841            const Bytef *bufBefore;
1842            ZPOS64_T uOutThis;
1843            int flush=Z_SYNC_FLUSH;
1844
1845            uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1846            bufBefore = pfile_in_zip_read_info->stream.next_out;
1847
1848            /*
1849            if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1850                     pfile_in_zip_read_info->stream.avail_out) &&
1851                (pfile_in_zip_read_info->rest_read_compressed == 0))
1852                flush = Z_FINISH;
1853            */
1854            err=inflate(&pfile_in_zip_read_info->stream,flush);
1855
1856            if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1857              err = Z_DATA_ERROR;
1858
1859            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1860            uOutThis = uTotalOutAfter-uTotalOutBefore;
1861
1862            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
1863
1864            pfile_in_zip_read_info->crc32 =
1865                crc32(pfile_in_zip_read_info->crc32,bufBefore,
1866                        (uInt)(uOutThis));
1867
1868            pfile_in_zip_read_info->rest_read_uncompressed -=
1869                uOutThis;
1870
1871            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1872
1873            if (err==Z_STREAM_END)
1874                return (iRead==0) ? UNZ_EOF : iRead;
1875            if (err!=Z_OK)
1876                break;
1877        }
1878    }
1879
1880    if (err==Z_OK)
1881        return iRead;
1882    return err;
1883}
1884
1885
1886/*
1887  Give the current position in uncompressed data
1888*/
1889extern z_off_t ZEXPORT unztell (unzFile file)
1890{
1891    unz64_s* s;
1892    file_in_zip64_read_info_s* pfile_in_zip_read_info;
1893    if (file==NULL)
1894        return UNZ_PARAMERROR;
1895    s=(unz64_s*)file;
1896    pfile_in_zip_read_info=s->pfile_in_zip_read;
1897
1898    if (pfile_in_zip_read_info==NULL)
1899        return UNZ_PARAMERROR;
1900
1901    return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1902}
1903
1904extern ZPOS64_T ZEXPORT unztell64 (unzFile file)
1905{
1906
1907    unz64_s* s;
1908    file_in_zip64_read_info_s* pfile_in_zip_read_info;
1909    if (file==NULL)
1910        return (ZPOS64_T)-1;
1911    s=(unz64_s*)file;
1912    pfile_in_zip_read_info=s->pfile_in_zip_read;
1913
1914    if (pfile_in_zip_read_info==NULL)
1915        return (ZPOS64_T)-1;
1916
1917    return pfile_in_zip_read_info->total_out_64;
1918}
1919
1920
1921/*
1922  return 1 if the end of file was reached, 0 elsewhere
1923*/
1924extern int ZEXPORT unzeof (unzFile file)
1925{
1926    unz64_s* s;
1927    file_in_zip64_read_info_s* pfile_in_zip_read_info;
1928    if (file==NULL)
1929        return UNZ_PARAMERROR;
1930    s=(unz64_s*)file;
1931    pfile_in_zip_read_info=s->pfile_in_zip_read;
1932
1933    if (pfile_in_zip_read_info==NULL)
1934        return UNZ_PARAMERROR;
1935
1936    if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1937        return 1;
1938    else
1939        return 0;
1940}
1941
1942
1943
1944/*
1945Read extra field from the current file (opened by unzOpenCurrentFile)
1946This is the local-header version of the extra field (sometimes, there is
1947more info in the local-header version than in the central-header)
1948
1949  if buf==NULL, it return the size of the local extra field that can be read
1950
1951  if buf!=NULL, len is the size of the buffer, the extra header is copied in
1952    buf.
1953  the return value is the number of bytes copied in buf, or (if <0)
1954    the error code
1955*/
1956extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)
1957{
1958    unz64_s* s;
1959    file_in_zip64_read_info_s* pfile_in_zip_read_info;
1960    uInt read_now;
1961    ZPOS64_T size_to_read;
1962
1963    if (file==NULL)
1964        return UNZ_PARAMERROR;
1965    s=(unz64_s*)file;
1966    pfile_in_zip_read_info=s->pfile_in_zip_read;
1967
1968    if (pfile_in_zip_read_info==NULL)
1969        return UNZ_PARAMERROR;
1970
1971    size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1972                pfile_in_zip_read_info->pos_local_extrafield);
1973
1974    if (buf==NULL)
1975        return (int)size_to_read;
1976
1977    if (len>size_to_read)
1978        read_now = (uInt)size_to_read;
1979    else
1980        read_now = (uInt)len ;
1981
1982    if (read_now==0)
1983        return 0;
1984
1985    if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
1986              pfile_in_zip_read_info->filestream,
1987              pfile_in_zip_read_info->offset_local_extrafield +
1988              pfile_in_zip_read_info->pos_local_extrafield,
1989              ZLIB_FILEFUNC_SEEK_SET)!=0)
1990        return UNZ_ERRNO;
1991
1992    if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
1993              pfile_in_zip_read_info->filestream,
1994              buf,read_now)!=read_now)
1995        return UNZ_ERRNO;
1996
1997    return (int)read_now;
1998}
1999
2000/*
2001  Close the file in zip opened with unzOpenCurrentFile
2002  Return UNZ_CRCERROR if all the file was read but the CRC is not good
2003*/
2004extern int ZEXPORT unzCloseCurrentFile (unzFile file)
2005{
2006    int err=UNZ_OK;
2007
2008    unz64_s* s;
2009    file_in_zip64_read_info_s* pfile_in_zip_read_info;
2010    if (file==NULL)
2011        return UNZ_PARAMERROR;
2012    s=(unz64_s*)file;
2013    pfile_in_zip_read_info=s->pfile_in_zip_read;
2014
2015    if (pfile_in_zip_read_info==NULL)
2016        return UNZ_PARAMERROR;
2017
2018
2019    if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
2020        (!pfile_in_zip_read_info->raw))
2021    {
2022        if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
2023            err=UNZ_CRCERROR;
2024    }
2025
2026
2027    TRYFREE(pfile_in_zip_read_info->read_buffer);
2028    pfile_in_zip_read_info->read_buffer = NULL;
2029    if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
2030        inflateEnd(&pfile_in_zip_read_info->stream);
2031#ifdef HAVE_BZIP2
2032    else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
2033        BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
2034#endif
2035
2036
2037    pfile_in_zip_read_info->stream_initialised = 0;
2038    TRYFREE(pfile_in_zip_read_info);
2039
2040    s->pfile_in_zip_read=NULL;
2041
2042    return err;
2043}
2044
2045
2046/*
2047  Get the global comment string of the ZipFile, in the szComment buffer.
2048  uSizeBuf is the size of the szComment buffer.
2049  return the number of byte copied or an error code <0
2050*/
2051extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf)
2052{
2053    unz64_s* s;
2054    uLong uReadThis ;
2055    if (file==NULL)
2056        return (int)UNZ_PARAMERROR;
2057    s=(unz64_s*)file;
2058
2059    uReadThis = uSizeBuf;
2060    if (uReadThis>s->gi.size_comment)
2061        uReadThis = s->gi.size_comment;
2062
2063    if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
2064        return UNZ_ERRNO;
2065
2066    if (uReadThis>0)
2067    {
2068      *szComment='\0';
2069      if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
2070        return UNZ_ERRNO;
2071    }
2072
2073    if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
2074        *(szComment+s->gi.size_comment)='\0';
2075    return (int)uReadThis;
2076}
2077
2078/* Additions by RX '2004 */
2079extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file)
2080{
2081    unz64_s* s;
2082
2083    if (file==NULL)
2084          return 0; //UNZ_PARAMERROR;
2085    s=(unz64_s*)file;
2086    if (!s->current_file_ok)
2087      return 0;
2088    if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
2089      if (s->num_file==s->gi.number_entry)
2090         return 0;
2091    return s->pos_in_central_dir;
2092}
2093
2094extern uLong ZEXPORT unzGetOffset (unzFile file)
2095{
2096    ZPOS64_T offset64;
2097
2098    if (file==NULL)
2099          return 0; //UNZ_PARAMERROR;
2100    offset64 = unzGetOffset64(file);
2101    return (uLong)offset64;
2102}
2103
2104extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos)
2105{
2106    unz64_s* s;
2107    int err;
2108
2109    if (file==NULL)
2110        return UNZ_PARAMERROR;
2111    s=(unz64_s*)file;
2112
2113    s->pos_in_central_dir = pos;
2114    s->num_file = s->gi.number_entry;      /* hack */
2115    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
2116                                              &s->cur_file_info_internal,
2117                                              NULL,0,NULL,0,NULL,0);
2118    s->current_file_ok = (err == UNZ_OK);
2119    return err;
2120}
2121
2122extern int ZEXPORT unzSetOffset (unzFile file, uLong pos)
2123{
2124    return unzSetOffset64(file,pos);
2125}
2126