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