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