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