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