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