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