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 2475060 : static int unzlocal_getByte(const zlib_filefunc_def *pzlib_filefunc_def,
174 : voidpf filestream, int *pi)
175 : {
176 2475060 : unsigned char c = 0;
177 : const int err =
178 2475060 : static_cast<int>(ZREAD(*pzlib_filefunc_def, filestream, &c, 1));
179 2475060 : if (err == 1)
180 : {
181 2475040 : *pi = static_cast<int>(c);
182 2475040 : 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 558320 : static int unzlocal_getShort(const zlib_filefunc_def *pzlib_filefunc_def,
197 : voidpf filestream, uLong *pX)
198 : {
199 558320 : int i = 0;
200 558320 : int err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
201 558320 : uLong x = static_cast<uLong>(i);
202 :
203 558320 : if (err == UNZ_OK)
204 558320 : err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
205 558320 : x += static_cast<uLong>(i) << 8;
206 :
207 558320 : if (err == UNZ_OK)
208 558320 : *pX = x;
209 : else
210 0 : *pX = 0;
211 558320 : return err;
212 : }
213 :
214 339455 : static int unzlocal_getLong(const zlib_filefunc_def *pzlib_filefunc_def,
215 : voidpf filestream, uLong *pX)
216 : {
217 339455 : int i = 0;
218 339455 : int err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
219 339455 : uLong x = static_cast<uLong>(i);
220 :
221 339455 : if (err == UNZ_OK)
222 339455 : err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
223 339455 : x += static_cast<uLong>(i) << 8;
224 :
225 339455 : if (err == UNZ_OK)
226 339455 : err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
227 339455 : x += static_cast<uLong>(i) << 16;
228 :
229 339455 : if (err == UNZ_OK)
230 339455 : err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
231 339455 : x += static_cast<uLong>(i) << 24;
232 :
233 339455 : if (err == UNZ_OK)
234 339455 : *pX = x;
235 : else
236 0 : *pX = 0;
237 339455 : 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 5169 : unzlocal_SearchCentralDir(const zlib_filefunc_def *pzlib_filefunc_def,
348 : voidpf filestream)
349 : {
350 5169 : if (ZSEEK(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
351 0 : return 0;
352 :
353 : unsigned char *buf =
354 5169 : static_cast<unsigned char *>(ALLOC(BUFREADCOMMENT + 4));
355 5169 : if (buf == nullptr)
356 0 : return 0;
357 :
358 5169 : const uLong64 uSizeFile = ZTELL(*pzlib_filefunc_def, filestream);
359 :
360 5169 : uLong64 uMaxBack = 0xffff; /* maximum size of global comment */
361 5169 : if (uMaxBack > uSizeFile)
362 2053 : uMaxBack = uSizeFile;
363 :
364 5169 : uLong64 uPosFound = 0;
365 5169 : uLong64 uBackRead = 4;
366 5171 : while (uBackRead < uMaxBack)
367 : {
368 5168 : if (uBackRead + BUFREADCOMMENT > uMaxBack)
369 253 : uBackRead = uMaxBack;
370 : else
371 4915 : uBackRead += BUFREADCOMMENT;
372 5168 : const uLong64 uReadPos = uSizeFile - uBackRead;
373 :
374 5168 : const uLong uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos))
375 : ? (BUFREADCOMMENT + 4)
376 : : static_cast<uLong>(uSizeFile - uReadPos);
377 5168 : if (ZSEEK(*pzlib_filefunc_def, filestream, uReadPos,
378 5168 : ZLIB_FILEFUNC_SEEK_SET) != 0)
379 0 : break;
380 :
381 5168 : 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 98192 : for (int i = static_cast<int>(uReadSize) - 3; (i--) > 0;)
386 98192 : if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) &&
387 5168 : ((*(buf + i + 2)) == 0x05) && ((*(buf + i + 3)) == 0x06))
388 : {
389 5168 : uPosFound = uReadPos + i;
390 5168 : break;
391 : }
392 :
393 5168 : if (uPosFound != 0)
394 5166 : break;
395 : }
396 5169 : TRYFREE(buf);
397 5169 : 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 5173 : unzlocal_SearchCentralDir64(const zlib_filefunc_def *pzlib_filefunc_def,
406 : voidpf filestream)
407 : {
408 : unsigned char *buf;
409 : uLong64 uSizeFile;
410 : uLong64 uBackRead;
411 5173 : uLong64 uMaxBack = 0xffff; /* maximum size of global comment */
412 5173 : uLong64 uPosFound = 0;
413 : uLong uL;
414 :
415 5173 : if (ZSEEK(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
416 0 : return 0;
417 :
418 5173 : uSizeFile = ZTELL(*pzlib_filefunc_def, filestream);
419 :
420 5173 : if (uMaxBack > uSizeFile)
421 2053 : uMaxBack = uSizeFile;
422 :
423 5173 : buf = static_cast<unsigned char *>(ALLOC(BUFREADCOMMENT + 4));
424 5173 : if (buf == nullptr)
425 0 : return 0;
426 :
427 5173 : uBackRead = 4;
428 249567 : while (uBackRead < uMaxBack)
429 : {
430 : uLong uReadSize;
431 : uLong64 uReadPos;
432 244398 : if (uBackRead + BUFREADCOMMENT > uMaxBack)
433 5168 : uBackRead = uMaxBack;
434 : else
435 239230 : uBackRead += BUFREADCOMMENT;
436 244398 : uReadPos = uSizeFile - uBackRead;
437 :
438 244398 : uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos))
439 : ? (BUFREADCOMMENT + 4)
440 : : static_cast<uLong>(uSizeFile - uReadPos);
441 244398 : if (ZSEEK(*pzlib_filefunc_def, filestream, uReadPos,
442 244398 : ZLIB_FILEFUNC_SEEK_SET) != 0)
443 0 : break;
444 :
445 244398 : if (ZREAD(*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize)
446 0 : break;
447 :
448 250602000 : for (int i = static_cast<int>(uReadSize) - 3; (i--) > 0;)
449 250357000 : if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) &&
450 1101510 : ((*(buf + i + 2)) == 0x06) && ((*(buf + i + 3)) == 0x07))
451 : {
452 4 : uPosFound = uReadPos + i;
453 4 : break;
454 : }
455 :
456 244398 : if (uPosFound != 0)
457 4 : break;
458 : }
459 5173 : TRYFREE(buf);
460 5173 : if (uPosFound == 0)
461 5169 : 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 5173 : 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 5173 : int err = UNZ_OK;
534 :
535 5173 : 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 5173 : if (unz_copyright[0] != ' ')
540 0 : return nullptr;
541 :
542 5173 : if (pzlib_filefunc_def == nullptr)
543 5173 : cpl_fill_fopen_filefunc(&us.z_filefunc);
544 : else
545 0 : us.z_filefunc = *pzlib_filefunc_def;
546 :
547 5173 : us.filestream = (*(us.z_filefunc.zopen_file))(
548 : us.z_filefunc.opaque, path,
549 : ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
550 5173 : if (us.filestream == nullptr)
551 0 : return nullptr;
552 :
553 5173 : central_pos = unzlocal_SearchCentralDir64(&us.z_filefunc, us.filestream);
554 5173 : if (central_pos)
555 : {
556 : uLong uS;
557 : uLong64 uL64;
558 :
559 4 : us.isZip64 = 1;
560 :
561 4 : if (ZSEEK(us.z_filefunc, us.filestream, central_pos,
562 4 : ZLIB_FILEFUNC_SEEK_SET) != 0)
563 0 : err = UNZ_ERRNO;
564 :
565 : /* the signature, already checked */
566 4 : 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 4 : if (unzlocal_getLong64(&us.z_filefunc, us.filestream, &uL64) != UNZ_OK)
571 0 : err = UNZ_ERRNO;
572 :
573 : /* version made by */
574 4 : if (unzlocal_getShort(&us.z_filefunc, us.filestream, &uS) != UNZ_OK)
575 0 : err = UNZ_ERRNO;
576 :
577 : /* version needed to extract */
578 4 : if (unzlocal_getShort(&us.z_filefunc, us.filestream, &uS) != UNZ_OK)
579 0 : err = UNZ_ERRNO;
580 :
581 : /* number of this disk */
582 4 : 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 4 : if (unzlocal_getLong(&us.z_filefunc, us.filestream,
588 4 : &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 4 : if (unzlocal_getLong64(&us.z_filefunc, us.filestream,
593 4 : &us.gi.number_entry) != UNZ_OK)
594 0 : err = UNZ_ERRNO;
595 :
596 : /* total number of entries in the central directory */
597 4 : if (unzlocal_getLong64(&us.z_filefunc, us.filestream,
598 4 : &number_entry_CD) != UNZ_OK)
599 0 : err = UNZ_ERRNO;
600 :
601 4 : if ((number_entry_CD != us.gi.number_entry) ||
602 4 : (number_disk_with_CD != 0) || (number_disk != 0))
603 0 : err = UNZ_BADZIPFILE;
604 :
605 : /* size of the central directory */
606 4 : if (unzlocal_getLong64(&us.z_filefunc, us.filestream,
607 4 : &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 4 : if (unzlocal_getLong64(&us.z_filefunc, us.filestream,
613 4 : &us.offset_central_dir) != UNZ_OK)
614 0 : err = UNZ_ERRNO;
615 :
616 4 : us.gi.size_comment = 0;
617 : }
618 : else
619 : {
620 5169 : central_pos = unzlocal_SearchCentralDir(&us.z_filefunc, us.filestream);
621 5169 : if (central_pos == 0)
622 3 : err = UNZ_ERRNO;
623 :
624 5169 : us.isZip64 = 0;
625 :
626 5169 : if (ZSEEK(us.z_filefunc, us.filestream, central_pos,
627 5169 : ZLIB_FILEFUNC_SEEK_SET) != 0)
628 0 : err = UNZ_ERRNO;
629 :
630 : /* the signature, already checked */
631 5169 : if (unzlocal_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
632 0 : err = UNZ_ERRNO;
633 :
634 : /* number of this disk */
635 5169 : 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 5169 : if (unzlocal_getShort(&us.z_filefunc, us.filestream,
641 5169 : &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 5169 : if (unzlocal_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
646 0 : err = UNZ_ERRNO;
647 5169 : us.gi.number_entry = uL;
648 :
649 : /* total number of entries in the central dir */
650 5169 : if (unzlocal_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
651 0 : err = UNZ_ERRNO;
652 5169 : number_entry_CD = uL;
653 :
654 5169 : if ((number_entry_CD != us.gi.number_entry) ||
655 5169 : (number_disk_with_CD != 0) || (number_disk != 0))
656 0 : err = UNZ_BADZIPFILE;
657 :
658 : /* size of the central directory */
659 5169 : if (unzlocal_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
660 0 : err = UNZ_ERRNO;
661 5169 : us.size_central_dir = uL;
662 :
663 : /* offset of start of central directory with respect to the
664 : starting disk number */
665 5169 : if (unzlocal_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
666 0 : err = UNZ_ERRNO;
667 5169 : us.offset_central_dir = uL;
668 :
669 : /* zipfile comment length */
670 5169 : if (unzlocal_getShort(&us.z_filefunc, us.filestream,
671 5169 : &us.gi.size_comment) != UNZ_OK)
672 0 : err = UNZ_ERRNO;
673 : }
674 :
675 5173 : if ((central_pos < us.offset_central_dir + us.size_central_dir) &&
676 : (err == UNZ_OK))
677 0 : err = UNZ_BADZIPFILE;
678 :
679 5173 : if (err != UNZ_OK)
680 : {
681 3 : ZCLOSE(us.z_filefunc, us.filestream);
682 3 : return nullptr;
683 : }
684 :
685 5170 : us.byte_before_the_zipfile =
686 5170 : central_pos - (us.offset_central_dir + us.size_central_dir);
687 5170 : us.central_pos = central_pos;
688 5170 : us.pfile_in_zip_read = nullptr;
689 5170 : us.encrypted = 0;
690 5170 : us.num_file = 0;
691 5170 : us.pos_in_central_dir = 0;
692 5170 : us.current_file_ok = 0;
693 :
694 5170 : s = static_cast<unz_s *>(ALLOC(sizeof(unz_s)));
695 5170 : *s = us;
696 5170 : cpl_unzGoToFirstFile(reinterpret_cast<unzFile>(s));
697 5170 : return reinterpret_cast<unzFile>(s);
698 : }
699 :
700 5173 : extern unzFile ZEXPORT cpl_unzOpen(const char *path)
701 : {
702 5173 : return cpl_unzOpen2(path, nullptr);
703 : }
704 :
705 : /*
706 : Close a ZipFile opened with unzipOpen.
707 : If there is files inside the .Zip opened with unzipOpenCurrentFile (see
708 : later), these files MUST be closed with unzipCloseCurrentFile before call
709 : unzipClose. return UNZ_OK if there is no problem. */
710 5170 : extern int ZEXPORT cpl_unzClose(unzFile file)
711 : {
712 : unz_s *s;
713 5170 : if (file == nullptr)
714 0 : return UNZ_PARAMERROR;
715 5170 : s = reinterpret_cast<unz_s *>(file);
716 :
717 5170 : if (s->pfile_in_zip_read != nullptr)
718 0 : cpl_unzCloseCurrentFile(file);
719 :
720 5170 : ZCLOSE(s->z_filefunc, s->filestream);
721 5170 : TRYFREE(s);
722 5170 : return UNZ_OK;
723 : }
724 :
725 : /*
726 : Write info about the ZipFile in the *pglobal_info structure.
727 : No preparation of the structure is needed
728 : return UNZ_OK if there is no problem. */
729 0 : extern int ZEXPORT cpl_unzGetGlobalInfo(unzFile file,
730 : unz_global_info *pglobal_info)
731 : {
732 : unz_s *s;
733 0 : if (file == nullptr)
734 0 : return UNZ_PARAMERROR;
735 0 : s = reinterpret_cast<unz_s *>(file);
736 0 : *pglobal_info = s->gi;
737 0 : return UNZ_OK;
738 : }
739 :
740 : /*
741 : Translate date/time from Dos format to tm_unz (readable more easily).
742 : */
743 40395 : static void unzlocal_DosDateToTmuDate(uLong64 ulDosDate, tm_unz *ptm)
744 : {
745 : uLong64 uDate;
746 40395 : uDate = static_cast<uLong64>(ulDosDate >> 16);
747 40395 : ptm->tm_mday = static_cast<uInt>(uDate & 0x1f);
748 40395 : ptm->tm_mon = static_cast<uInt>(((uDate)&0x1E0) / 0x20);
749 40395 : if (ptm->tm_mon)
750 40390 : ptm->tm_mon--;
751 40395 : ptm->tm_year = static_cast<uInt>(((uDate & 0x0FE00) / 0x0200) + 1980);
752 :
753 40395 : ptm->tm_hour = static_cast<uInt>((ulDosDate & 0xF800) / 0x800);
754 40395 : ptm->tm_min = static_cast<uInt>((ulDosDate & 0x7E0) / 0x20);
755 40395 : ptm->tm_sec = static_cast<uInt>(2 * (ulDosDate & 0x1f));
756 40395 : }
757 :
758 : /*
759 : Get Info about the current file in the zipfile, with internal only info
760 : */
761 40395 : static int unzlocal_GetCurrentFileInfoInternal(
762 : unzFile file, unz_file_info *pfile_info,
763 : unz_file_info_internal *pfile_info_internal, char *szFileName,
764 : uLong fileNameBufferSize, void * /* extraField */,
765 : uLong /* extraFieldBufferSize */, char * /* szComment */,
766 : uLong /* commentBufferSize */)
767 : {
768 : unz_s *s;
769 : unz_file_info file_info;
770 : unz_file_info_internal file_info_internal;
771 40395 : int err = UNZ_OK;
772 : uLong uMagic;
773 40395 : long lSeek = 0;
774 : uLong uL;
775 40395 : bool bHasUTF8Filename = false;
776 :
777 40395 : if (file == nullptr)
778 0 : return UNZ_PARAMERROR;
779 40395 : s = reinterpret_cast<unz_s *>(file);
780 40395 : if (ZSEEK(s->z_filefunc, s->filestream,
781 : s->pos_in_central_dir + s->byte_before_the_zipfile,
782 40395 : ZLIB_FILEFUNC_SEEK_SET) != 0)
783 0 : err = UNZ_ERRNO;
784 :
785 : /* we check the magic */
786 40395 : if (err == UNZ_OK)
787 : {
788 40395 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK)
789 0 : err = UNZ_ERRNO;
790 40395 : else if (uMagic != 0x02014b50)
791 0 : err = UNZ_BADZIPFILE;
792 : }
793 :
794 40395 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.version) !=
795 : UNZ_OK)
796 0 : err = UNZ_ERRNO;
797 :
798 40395 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
799 40395 : &file_info.version_needed) != UNZ_OK)
800 0 : err = UNZ_ERRNO;
801 :
802 40395 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.flag) !=
803 : UNZ_OK)
804 0 : err = UNZ_ERRNO;
805 :
806 40395 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
807 40395 : &file_info.compression_method) != UNZ_OK)
808 0 : err = UNZ_ERRNO;
809 :
810 40395 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info.dosDate) !=
811 : UNZ_OK)
812 0 : err = UNZ_ERRNO;
813 :
814 40395 : unzlocal_DosDateToTmuDate(file_info.dosDate, &file_info.tmu_date);
815 :
816 40395 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info.crc) !=
817 : UNZ_OK)
818 0 : err = UNZ_ERRNO;
819 :
820 40395 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
821 0 : err = UNZ_ERRNO;
822 40395 : file_info.compressed_size = uL;
823 :
824 40395 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
825 0 : err = UNZ_ERRNO;
826 40395 : file_info.uncompressed_size = uL;
827 :
828 40395 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
829 40395 : &file_info.size_filename) != UNZ_OK)
830 0 : err = UNZ_ERRNO;
831 :
832 40395 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
833 40395 : &file_info.size_file_extra) != UNZ_OK)
834 0 : err = UNZ_ERRNO;
835 :
836 40395 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
837 40395 : &file_info.size_file_comment) != UNZ_OK)
838 0 : err = UNZ_ERRNO;
839 :
840 40395 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
841 40395 : &file_info.disk_num_start) != UNZ_OK)
842 0 : err = UNZ_ERRNO;
843 :
844 40395 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
845 40395 : &file_info.internal_fa) != UNZ_OK)
846 0 : err = UNZ_ERRNO;
847 :
848 40395 : if (unzlocal_getLong(&s->z_filefunc, s->filestream,
849 40395 : &file_info.external_fa) != UNZ_OK)
850 0 : err = UNZ_ERRNO;
851 :
852 40395 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
853 0 : err = UNZ_ERRNO;
854 40395 : file_info_internal.offset_curfile = uL;
855 :
856 40395 : lSeek += file_info.size_filename;
857 40395 : if ((err == UNZ_OK) && (szFileName != nullptr))
858 : {
859 15537 : uLong uSizeRead = 0;
860 15537 : if (file_info.size_filename < fileNameBufferSize)
861 : {
862 15537 : *(szFileName + file_info.size_filename) = '\0';
863 15537 : uSizeRead = file_info.size_filename;
864 : }
865 : else
866 0 : uSizeRead = fileNameBufferSize;
867 :
868 15537 : if ((file_info.size_filename > 0) && (fileNameBufferSize > 0))
869 : {
870 15535 : if (ZREAD(s->z_filefunc, s->filestream, szFileName, uSizeRead) !=
871 : uSizeRead)
872 0 : err = UNZ_ERRNO;
873 : }
874 15537 : lSeek -= uSizeRead;
875 : }
876 :
877 : #if 0
878 : if ((err==UNZ_OK) && (extraField != nullptr))
879 : {
880 : uLong64 uSizeRead = 0;
881 : if (file_info.size_file_extra<extraFieldBufferSize)
882 : uSizeRead = file_info.size_file_extra;
883 : else
884 : uSizeRead = extraFieldBufferSize;
885 :
886 : if (lSeek!=0)
887 : {
888 : if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
889 : lSeek=0;
890 : else
891 : err=UNZ_ERRNO;
892 : }
893 :
894 : if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
895 : if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead)
896 : err=UNZ_ERRNO;
897 : lSeek += file_info.size_file_extra - uSizeRead;
898 : }
899 : else
900 : lSeek+=file_info.size_file_extra;
901 : #endif
902 40395 : if ((err == UNZ_OK) && (file_info.size_file_extra != 0))
903 : {
904 32233 : if (lSeek != 0)
905 : {
906 19917 : if (ZSEEK(s->z_filefunc, s->filestream, lSeek,
907 19917 : ZLIB_FILEFUNC_SEEK_CUR) == 0)
908 : {
909 19917 : lSeek = 0;
910 19917 : CPL_IGNORE_RET_VAL(lSeek);
911 : }
912 : else
913 0 : err = UNZ_ERRNO;
914 : }
915 :
916 32233 : uLong acc = 0;
917 32233 : file_info.file_extra_abs_offset = ZTELL(s->z_filefunc, s->filestream);
918 96114 : while (acc < file_info.size_file_extra)
919 : {
920 : uLong headerId;
921 63881 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &headerId) !=
922 : UNZ_OK)
923 0 : err = UNZ_ERRNO;
924 :
925 : uLong dataSize;
926 63881 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &dataSize) !=
927 : UNZ_OK)
928 0 : err = UNZ_ERRNO;
929 :
930 : /* ZIP64 extra fields */
931 63881 : if (headerId == 0x0001)
932 : {
933 : uLong64 u64;
934 36 : if (file_info.uncompressed_size == 0xFFFFFFFF)
935 : {
936 31 : if (unzlocal_getLong64(&s->z_filefunc, s->filestream,
937 31 : &u64) != UNZ_OK)
938 0 : err = UNZ_ERRNO;
939 31 : file_info.uncompressed_size = u64;
940 : }
941 :
942 36 : if (file_info.compressed_size == 0xFFFFFFFF)
943 : {
944 14 : if (unzlocal_getLong64(&s->z_filefunc, s->filestream,
945 14 : &u64) != UNZ_OK)
946 0 : err = UNZ_ERRNO;
947 14 : file_info.compressed_size = u64;
948 : }
949 :
950 : /* Relative Header offset */
951 36 : if (file_info_internal.offset_curfile == 0xFFFFFFFF)
952 : {
953 5 : if (unzlocal_getLong64(&s->z_filefunc, s->filestream,
954 5 : &u64) != UNZ_OK)
955 0 : err = UNZ_ERRNO;
956 5 : file_info_internal.offset_curfile = u64;
957 : }
958 :
959 : /* Disk Start Number */
960 36 : if (file_info.disk_num_start == 0xFFFF)
961 : {
962 : uLong uLstart;
963 0 : if (unzlocal_getLong(&s->z_filefunc, s->filestream,
964 0 : &uLstart) != UNZ_OK)
965 0 : err = UNZ_ERRNO;
966 0 : file_info.disk_num_start = uLstart;
967 : }
968 : }
969 : /* Info-ZIP Unicode Path Extra Field (0x7075) */
970 63845 : else if (headerId == 0x7075 && dataSize > 5 &&
971 12 : file_info.size_filename <= fileNameBufferSize &&
972 : szFileName != nullptr)
973 : {
974 5 : int version = 0;
975 5 : if (unzlocal_getByte(&s->z_filefunc, s->filestream, &version) !=
976 : UNZ_OK)
977 0 : err = UNZ_ERRNO;
978 5 : if (version != 1)
979 : {
980 : /* If version != 1, ignore that extra field */
981 0 : if (ZSEEK(s->z_filefunc, s->filestream, dataSize - 1,
982 0 : ZLIB_FILEFUNC_SEEK_CUR) != 0)
983 0 : err = UNZ_ERRNO;
984 : }
985 : else
986 : {
987 : uLong nameCRC32;
988 5 : if (unzlocal_getLong(&s->z_filefunc, s->filestream,
989 5 : &nameCRC32) != UNZ_OK)
990 0 : err = UNZ_ERRNO;
991 :
992 : /* Check expected CRC for filename */
993 5 : if (nameCRC32 ==
994 5 : crc32(0, reinterpret_cast<const Bytef *>(szFileName),
995 5 : static_cast<uInt>(file_info.size_filename)))
996 : {
997 5 : const uLong utf8Size = dataSize - 1 - 4;
998 5 : uLong uSizeRead = 0;
999 :
1000 5 : bHasUTF8Filename = true;
1001 :
1002 5 : if (utf8Size < fileNameBufferSize)
1003 : {
1004 5 : *(szFileName + utf8Size) = '\0';
1005 5 : uSizeRead = utf8Size;
1006 : }
1007 : else
1008 0 : uSizeRead = fileNameBufferSize;
1009 :
1010 5 : if (ZREAD(s->z_filefunc, s->filestream, szFileName,
1011 5 : uSizeRead) != uSizeRead)
1012 0 : err = UNZ_ERRNO;
1013 5 : else if (utf8Size > fileNameBufferSize)
1014 : {
1015 0 : if (ZSEEK(s->z_filefunc, s->filestream,
1016 : utf8Size - fileNameBufferSize,
1017 0 : ZLIB_FILEFUNC_SEEK_CUR) != 0)
1018 0 : err = UNZ_ERRNO;
1019 : }
1020 : }
1021 : else
1022 : {
1023 : /* ignore unicode name if CRC mismatch */
1024 0 : if (ZSEEK(s->z_filefunc, s->filestream,
1025 : dataSize - 1 - 4,
1026 0 : ZLIB_FILEFUNC_SEEK_CUR) != 0)
1027 0 : err = UNZ_ERRNO;
1028 : }
1029 5 : }
1030 : }
1031 : else
1032 : {
1033 63840 : if (ZSEEK(s->z_filefunc, s->filestream, dataSize,
1034 63840 : ZLIB_FILEFUNC_SEEK_CUR) != 0)
1035 0 : err = UNZ_ERRNO;
1036 : }
1037 :
1038 63881 : acc += 2 + 2 + dataSize;
1039 : }
1040 : }
1041 :
1042 40395 : if (!bHasUTF8Filename && szFileName != nullptr &&
1043 15532 : (file_info.flag & (1 << 11)) == 0 &&
1044 14939 : file_info.size_filename < fileNameBufferSize)
1045 : {
1046 14939 : const char *pszSrcEncoding = CPLGetConfigOption("CPL_ZIP_ENCODING",
1047 : #if defined(_WIN32) && !defined(HAVE_ICONV)
1048 : "CP_OEMCP"
1049 : #else
1050 : "CP437"
1051 : #endif
1052 : );
1053 14939 : char *pszRecoded = CPLRecode(szFileName, pszSrcEncoding, CPL_ENC_UTF8);
1054 14939 : if (pszRecoded != nullptr && strlen(pszRecoded) < fileNameBufferSize)
1055 : {
1056 14939 : strcpy(szFileName, pszRecoded);
1057 : }
1058 14939 : CPLFree(pszRecoded);
1059 : }
1060 :
1061 : #if 0
1062 : if ((err==UNZ_OK) && (szComment != nullptr))
1063 : {
1064 : uLong64 uSizeRead = 0;
1065 : if (file_info.size_file_comment<commentBufferSize)
1066 : {
1067 : *(szComment+file_info.size_file_comment)='\0';
1068 : uSizeRead = file_info.size_file_comment;
1069 : }
1070 : else
1071 : uSizeRead = commentBufferSize;
1072 :
1073 : if (lSeek!=0)
1074 : {
1075 : if (ZSEEK(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
1076 : lSeek=0;
1077 : else
1078 : err=UNZ_ERRNO;
1079 : }
1080 :
1081 : if ((file_info.size_file_comment>0) && (commentBufferSize>0))
1082 : if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
1083 : err=UNZ_ERRNO;
1084 : lSeek+=file_info.size_file_comment - uSizeRead;
1085 : }
1086 : else
1087 : lSeek+=file_info.size_file_comment;
1088 : #endif
1089 :
1090 40395 : if ((err == UNZ_OK) && (pfile_info != nullptr))
1091 40395 : *pfile_info = file_info;
1092 :
1093 40395 : if ((err == UNZ_OK) && (pfile_info_internal != nullptr))
1094 20707 : *pfile_info_internal = file_info_internal;
1095 :
1096 40395 : return err;
1097 : }
1098 :
1099 : /*
1100 : Write info about the ZipFile in the *pglobal_info structure.
1101 : No preparation of the structure is needed
1102 : return UNZ_OK if there is no problem.
1103 : */
1104 19688 : extern int ZEXPORT cpl_unzGetCurrentFileInfo(
1105 : unzFile file, unz_file_info *pfile_info, char *szFileName,
1106 : uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize,
1107 : char *szComment, uLong commentBufferSize)
1108 : {
1109 19688 : return unzlocal_GetCurrentFileInfoInternal(
1110 : file, pfile_info, nullptr, szFileName, fileNameBufferSize, extraField,
1111 19688 : extraFieldBufferSize, szComment, commentBufferSize);
1112 : }
1113 :
1114 : /*
1115 : Set the current file of the zipfile to the first file.
1116 : return UNZ_OK if there is no problem
1117 : */
1118 11209 : extern int ZEXPORT cpl_unzGoToFirstFile(unzFile file)
1119 : {
1120 11209 : int err = UNZ_OK;
1121 : unz_s *s;
1122 11209 : if (file == nullptr)
1123 0 : return UNZ_PARAMERROR;
1124 11209 : s = reinterpret_cast<unz_s *>(file);
1125 11209 : s->pos_in_central_dir = s->offset_central_dir;
1126 11209 : s->num_file = 0;
1127 11209 : err = unzlocal_GetCurrentFileInfoInternal(
1128 : file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
1129 : nullptr, 0, nullptr, 0);
1130 11209 : s->current_file_ok = (err == UNZ_OK);
1131 11209 : return err;
1132 : }
1133 :
1134 : /*
1135 : Set the current file of the zipfile to the next file.
1136 : return UNZ_OK if there is no problem
1137 : return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
1138 : */
1139 5949 : extern int ZEXPORT cpl_unzGoToNextFile(unzFile file)
1140 : {
1141 : unz_s *s;
1142 :
1143 5949 : if (file == nullptr)
1144 0 : return UNZ_PARAMERROR;
1145 5949 : s = reinterpret_cast<unz_s *>(file);
1146 5949 : if (!s->current_file_ok)
1147 0 : return UNZ_END_OF_LIST_OF_FILE;
1148 5949 : if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
1149 5949 : if (s->num_file + 1 == s->gi.number_entry)
1150 485 : return UNZ_END_OF_LIST_OF_FILE;
1151 :
1152 5464 : s->pos_in_central_dir +=
1153 5464 : SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
1154 5464 : s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment;
1155 5464 : s->num_file++;
1156 5464 : int err = unzlocal_GetCurrentFileInfoInternal(
1157 : file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
1158 : nullptr, 0, nullptr, 0);
1159 5464 : s->current_file_ok = (err == UNZ_OK);
1160 5464 : return err;
1161 : }
1162 :
1163 : /*
1164 : Try locate the file szFileName in the zipfile.
1165 : For the iCaseSensitivity signification, see unzipStringFileNameCompare
1166 :
1167 : return value :
1168 : UNZ_OK if the file is found. It becomes the current file.
1169 : UNZ_END_OF_LIST_OF_FILE if the file is not found
1170 : */
1171 0 : extern int ZEXPORT cpl_unzLocateFile(unzFile file, const char *szFileName,
1172 : int iCaseSensitivity)
1173 : {
1174 : unz_s *s;
1175 :
1176 : /* We remember the 'current' position in the file so that we can jump
1177 : * back there if we fail.
1178 : */
1179 : unz_file_info cur_file_infoSaved;
1180 : unz_file_info_internal cur_file_info_internalSaved;
1181 : uLong64 num_fileSaved;
1182 : uLong64 pos_in_central_dirSaved;
1183 :
1184 0 : if (file == nullptr)
1185 0 : return UNZ_PARAMERROR;
1186 :
1187 0 : if (strlen(szFileName) >= UNZ_MAXFILENAMEINZIP)
1188 0 : return UNZ_PARAMERROR;
1189 :
1190 0 : s = reinterpret_cast<unz_s *>(file);
1191 0 : if (!s->current_file_ok)
1192 0 : return UNZ_END_OF_LIST_OF_FILE;
1193 :
1194 : /* Save the current state */
1195 0 : num_fileSaved = s->num_file;
1196 0 : pos_in_central_dirSaved = s->pos_in_central_dir;
1197 0 : cur_file_infoSaved = s->cur_file_info;
1198 0 : cur_file_info_internalSaved = s->cur_file_info_internal;
1199 :
1200 0 : int err = cpl_unzGoToFirstFile(file);
1201 :
1202 0 : while (err == UNZ_OK)
1203 : {
1204 : char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1];
1205 0 : err = cpl_unzGetCurrentFileInfo(file, nullptr, szCurrentFileName,
1206 : sizeof(szCurrentFileName) - 1, nullptr,
1207 : 0, nullptr, 0);
1208 0 : if (err == UNZ_OK)
1209 : {
1210 0 : if (cpl_unzStringFileNameCompare(szCurrentFileName, szFileName,
1211 0 : iCaseSensitivity) == 0)
1212 0 : return UNZ_OK;
1213 0 : err = cpl_unzGoToNextFile(file);
1214 : }
1215 : }
1216 :
1217 : /* We failed, so restore the state of the 'current file' to where we
1218 : * were.
1219 : */
1220 : // cppcheck-suppress redundantAssignment
1221 0 : s->num_file = num_fileSaved;
1222 0 : s->pos_in_central_dir = pos_in_central_dirSaved;
1223 0 : s->cur_file_info = cur_file_infoSaved;
1224 0 : s->cur_file_info_internal = cur_file_info_internalSaved;
1225 0 : return err;
1226 : }
1227 :
1228 : /*
1229 : ///////////////////////////////////////////
1230 : // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
1231 : // I need random access
1232 : //
1233 : // Further optimization could be realized by adding an ability
1234 : // to cache the directory in memory. The goal being a single
1235 : // comprehensive file read to put the file I need in a memory.
1236 : */
1237 :
1238 : /*
1239 : typedef struct unz_file_pos_s
1240 : {
1241 : uLong64 pos_in_zip_directory; // offset in file
1242 : uLong64 num_of_file; // # of file
1243 : } unz_file_pos;
1244 : */
1245 :
1246 14941 : extern int ZEXPORT cpl_unzGetFilePos(unzFile file, unz_file_pos *file_pos)
1247 : {
1248 : unz_s *s;
1249 :
1250 14941 : if (file == nullptr || file_pos == nullptr)
1251 0 : return UNZ_PARAMERROR;
1252 14941 : s = reinterpret_cast<unz_s *>(file);
1253 14941 : if (!s->current_file_ok)
1254 0 : return UNZ_END_OF_LIST_OF_FILE;
1255 :
1256 14941 : file_pos->pos_in_zip_directory = s->pos_in_central_dir;
1257 14941 : file_pos->num_of_file = s->num_file;
1258 :
1259 14941 : return UNZ_OK;
1260 : }
1261 :
1262 4034 : extern int ZEXPORT cpl_unzGoToFilePos(unzFile file, unz_file_pos *file_pos)
1263 : {
1264 : unz_s *s;
1265 :
1266 4034 : if (file == nullptr || file_pos == nullptr)
1267 0 : return UNZ_PARAMERROR;
1268 4034 : s = reinterpret_cast<unz_s *>(file);
1269 :
1270 : /* jump to the right spot */
1271 4034 : s->pos_in_central_dir = file_pos->pos_in_zip_directory;
1272 4034 : s->num_file = file_pos->num_of_file;
1273 :
1274 : /* set the current file */
1275 4034 : int err = unzlocal_GetCurrentFileInfoInternal(
1276 : file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
1277 : nullptr, 0, nullptr, 0);
1278 : /* return results */
1279 4034 : s->current_file_ok = (err == UNZ_OK);
1280 4034 : return err;
1281 : }
1282 :
1283 : /*
1284 : // Unzip Helper Functions - should be here?
1285 : ///////////////////////////////////////////
1286 : */
1287 :
1288 : /*
1289 : Read the local header of the current zipfile
1290 : Check the coherency of the local header and info in the end of central
1291 : directory about this file
1292 : store in *piSizeVar the size of extra info in local header
1293 : (filename and size of extra field data)
1294 : */
1295 : static int
1296 4151 : unzlocal_CheckCurrentFileCoherencyHeader(unz_s *s, uInt *piSizeVar,
1297 : uLong64 *poffset_local_extrafield,
1298 : uInt *psize_local_extrafield)
1299 : {
1300 : uLong uMagic, uData, uFlags;
1301 : uLong size_filename;
1302 : uLong size_extra_field;
1303 4151 : int err = UNZ_OK;
1304 :
1305 4151 : *piSizeVar = 0;
1306 4151 : *poffset_local_extrafield = 0;
1307 4151 : *psize_local_extrafield = 0;
1308 :
1309 4151 : if (ZSEEK(s->z_filefunc, s->filestream,
1310 : s->cur_file_info_internal.offset_curfile +
1311 : s->byte_before_the_zipfile,
1312 4151 : ZLIB_FILEFUNC_SEEK_SET) != 0)
1313 0 : return UNZ_ERRNO;
1314 :
1315 : // if (err == UNZ_OK)
1316 : {
1317 4151 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK)
1318 0 : err = UNZ_ERRNO;
1319 4151 : else if (uMagic != 0x04034b50)
1320 0 : err = UNZ_BADZIPFILE;
1321 : }
1322 :
1323 4151 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
1324 0 : err = UNZ_ERRNO;
1325 : /*
1326 : else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1327 : err=UNZ_BADZIPFILE;
1328 : */
1329 4151 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uFlags) != UNZ_OK)
1330 0 : err = UNZ_ERRNO;
1331 :
1332 4151 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
1333 0 : err = UNZ_ERRNO;
1334 4151 : else if ((err == UNZ_OK) && (uData != s->cur_file_info.compression_method))
1335 0 : err = UNZ_BADZIPFILE;
1336 :
1337 4151 : if ((err == UNZ_OK) && (s->cur_file_info.compression_method != 0) &&
1338 4080 : (s->cur_file_info.compression_method != Z_DEFLATED))
1339 : {
1340 : #ifdef ENABLE_DEFLATE64
1341 1 : if (s->cur_file_info.compression_method == 9)
1342 : {
1343 : // ok
1344 : }
1345 : else
1346 : #endif
1347 : {
1348 0 : CPLError(CE_Failure, CPLE_NotSupported,
1349 : "A file in the ZIP archive uses a unsupported "
1350 : "compression method (%lu)",
1351 : s->cur_file_info.compression_method);
1352 0 : err = UNZ_BADZIPFILE;
1353 : }
1354 : }
1355 :
1356 4151 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1357 : UNZ_OK) /* date/time */
1358 0 : err = UNZ_ERRNO;
1359 :
1360 4151 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1361 : UNZ_OK) /* crc */
1362 0 : err = UNZ_ERRNO;
1363 4151 : else if ((err == UNZ_OK) && (uData != s->cur_file_info.crc) &&
1364 163 : ((uFlags & 8) == 0))
1365 0 : err = UNZ_BADZIPFILE;
1366 :
1367 4151 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1368 : UNZ_OK) /* size compr */
1369 0 : err = UNZ_ERRNO;
1370 4151 : else if (uData != 0xFFFFFFFF && (err == UNZ_OK) &&
1371 4148 : (uData != s->cur_file_info.compressed_size) && ((uFlags & 8) == 0))
1372 0 : err = UNZ_BADZIPFILE;
1373 :
1374 4151 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1375 : UNZ_OK) /* size uncompr */
1376 0 : err = UNZ_ERRNO;
1377 4151 : else if (uData != 0xFFFFFFFF && (err == UNZ_OK) &&
1378 4148 : (uData != s->cur_file_info.uncompressed_size) &&
1379 163 : ((uFlags & 8) == 0))
1380 0 : err = UNZ_BADZIPFILE;
1381 :
1382 4151 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_filename) !=
1383 : UNZ_OK)
1384 0 : err = UNZ_ERRNO;
1385 4151 : else if ((err == UNZ_OK) &&
1386 4151 : (size_filename != s->cur_file_info.size_filename))
1387 0 : err = UNZ_BADZIPFILE;
1388 :
1389 4151 : *piSizeVar += static_cast<uInt>(size_filename);
1390 :
1391 4151 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_extra_field) !=
1392 : UNZ_OK)
1393 0 : err = UNZ_ERRNO;
1394 4151 : *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile +
1395 4151 : SIZEZIPLOCALHEADER + size_filename;
1396 4151 : *psize_local_extrafield = static_cast<uInt>(size_extra_field);
1397 :
1398 4151 : *piSizeVar += static_cast<uInt>(size_extra_field);
1399 :
1400 4151 : return err;
1401 : }
1402 :
1403 : /*
1404 : Open for reading data the current file in the zipfile.
1405 : If there is no error and the file is opened, the return value is UNZ_OK.
1406 : */
1407 4151 : extern int ZEXPORT cpl_unzOpenCurrentFile3(unzFile file, int *method,
1408 : int *level, int raw,
1409 : const char *password)
1410 : {
1411 4151 : int err = UNZ_OK;
1412 : uInt iSizeVar;
1413 : unz_s *s;
1414 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1415 : uLong64 offset_local_extrafield; /* offset of the local extra field */
1416 : uInt size_local_extrafield; /* size of the local extra field */
1417 : #ifndef NOUNCRYPT
1418 : char source[12];
1419 : #else
1420 4151 : if (password != nullptr)
1421 0 : return UNZ_PARAMERROR;
1422 : #endif
1423 :
1424 4151 : if (file == nullptr)
1425 0 : return UNZ_PARAMERROR;
1426 4151 : s = reinterpret_cast<unz_s *>(file);
1427 4151 : if (!s->current_file_ok)
1428 0 : return UNZ_PARAMERROR;
1429 :
1430 4151 : if (s->pfile_in_zip_read != nullptr)
1431 0 : cpl_unzCloseCurrentFile(file);
1432 :
1433 4151 : if (unzlocal_CheckCurrentFileCoherencyHeader(
1434 4151 : s, &iSizeVar, &offset_local_extrafield, &size_local_extrafield) !=
1435 : UNZ_OK)
1436 0 : return UNZ_BADZIPFILE;
1437 :
1438 : pfile_in_zip_read_info = static_cast<file_in_zip_read_info_s *>(
1439 4151 : ALLOC(sizeof(file_in_zip_read_info_s)));
1440 4151 : if (pfile_in_zip_read_info == nullptr)
1441 0 : return UNZ_INTERNALERROR;
1442 :
1443 4151 : pfile_in_zip_read_info->read_buffer =
1444 4151 : static_cast<char *>(ALLOC(UNZ_BUFSIZE));
1445 4151 : pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1446 4151 : pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1447 4151 : pfile_in_zip_read_info->pos_local_extrafield = 0;
1448 4151 : pfile_in_zip_read_info->raw = raw;
1449 :
1450 4151 : if (pfile_in_zip_read_info->read_buffer == nullptr)
1451 : {
1452 0 : TRYFREE(pfile_in_zip_read_info);
1453 0 : return UNZ_INTERNALERROR;
1454 : }
1455 :
1456 4151 : pfile_in_zip_read_info->stream_initialised = 0;
1457 :
1458 4151 : if (method != nullptr)
1459 0 : *method = static_cast<int>(s->cur_file_info.compression_method);
1460 :
1461 4151 : if (level != nullptr)
1462 : {
1463 0 : *level = 6;
1464 0 : switch (s->cur_file_info.flag & 0x06)
1465 : {
1466 0 : case 6:
1467 0 : *level = 1;
1468 0 : break;
1469 0 : case 4:
1470 0 : *level = 2;
1471 0 : break;
1472 0 : case 2:
1473 0 : *level = 9;
1474 0 : break;
1475 : }
1476 : }
1477 :
1478 : /*if ((s->cur_file_info.compression_method!=0) &&
1479 : (s->cur_file_info.compression_method!=Z_DEFLATED))
1480 : err=UNZ_BADZIPFILE;*/
1481 :
1482 4151 : pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc;
1483 4151 : pfile_in_zip_read_info->crc32 = 0;
1484 4151 : pfile_in_zip_read_info->compression_method =
1485 4151 : s->cur_file_info.compression_method;
1486 4151 : pfile_in_zip_read_info->filestream = s->filestream;
1487 4151 : pfile_in_zip_read_info->z_filefunc = s->z_filefunc;
1488 4151 : pfile_in_zip_read_info->byte_before_the_zipfile =
1489 4151 : s->byte_before_the_zipfile;
1490 :
1491 4151 : pfile_in_zip_read_info->stream.total_out = 0;
1492 :
1493 4151 : if ((s->cur_file_info.compression_method == Z_DEFLATED) && (!raw))
1494 : {
1495 4079 : pfile_in_zip_read_info->stream.zalloc = nullptr;
1496 4079 : pfile_in_zip_read_info->stream.zfree = nullptr;
1497 4079 : pfile_in_zip_read_info->stream.opaque = nullptr;
1498 4079 : pfile_in_zip_read_info->stream.next_in = nullptr;
1499 4079 : pfile_in_zip_read_info->stream.avail_in = 0;
1500 :
1501 4079 : err = inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1502 4079 : if (err == Z_OK)
1503 4079 : pfile_in_zip_read_info->stream_initialised = 1;
1504 : else
1505 : {
1506 0 : TRYFREE(pfile_in_zip_read_info);
1507 0 : return err;
1508 : }
1509 : /* windowBits is passed < 0 to tell that there is no zlib header.
1510 : * Note that in this case inflate *requires* an extra "dummy" byte
1511 : * after the compressed stream in order to complete decompression and
1512 : * return Z_STREAM_END.
1513 : * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1514 : * size of both compressed and uncompressed data
1515 : */
1516 : }
1517 4151 : pfile_in_zip_read_info->rest_read_compressed =
1518 4151 : s->cur_file_info.compressed_size;
1519 4151 : pfile_in_zip_read_info->rest_read_uncompressed =
1520 4151 : s->cur_file_info.uncompressed_size;
1521 :
1522 4151 : pfile_in_zip_read_info->pos_in_zipfile =
1523 4151 : s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1524 4151 : iSizeVar;
1525 :
1526 4151 : pfile_in_zip_read_info->stream.avail_in = 0;
1527 :
1528 4151 : s->pfile_in_zip_read = pfile_in_zip_read_info;
1529 :
1530 : #ifndef NOUNCRYPT
1531 : if (password != nullptr)
1532 : {
1533 : s->pcrc_32_tab = get_crc_table();
1534 : init_keys(password, s->keys, s->pcrc_32_tab);
1535 : if (ZSEEK(s->z_filefunc, s->filestream,
1536 : s->pfile_in_zip_read->pos_in_zipfile +
1537 : s->pfile_in_zip_read->byte_before_the_zipfile,
1538 : SEEK_SET) != 0)
1539 : return UNZ_INTERNALERROR;
1540 : if (ZREAD(s->z_filefunc, s->filestream, source, 12) < 12)
1541 : return UNZ_INTERNALERROR;
1542 :
1543 : for (int i = 0; i < 12; i++)
1544 : zdecode(s->keys, s->pcrc_32_tab, source[i]);
1545 :
1546 : s->pfile_in_zip_read->pos_in_zipfile += 12;
1547 : s->encrypted = 1;
1548 : }
1549 : #endif
1550 :
1551 4151 : return UNZ_OK;
1552 : }
1553 :
1554 4151 : extern int ZEXPORT cpl_unzOpenCurrentFile(unzFile file)
1555 : {
1556 4151 : return cpl_unzOpenCurrentFile3(file, nullptr, nullptr, 0, nullptr);
1557 : }
1558 :
1559 0 : extern int ZEXPORT cpl_unzOpenCurrentFilePassword(unzFile file,
1560 : const char *password)
1561 : {
1562 0 : return cpl_unzOpenCurrentFile3(file, nullptr, nullptr, 0, password);
1563 : }
1564 :
1565 0 : extern int ZEXPORT cpl_unzOpenCurrentFile2(unzFile file, int *method,
1566 : int *level, int raw)
1567 : {
1568 0 : return cpl_unzOpenCurrentFile3(file, method, level, raw, nullptr);
1569 : }
1570 :
1571 : /** Addition for GDAL : START */
1572 :
1573 4151 : extern uLong64 ZEXPORT cpl_unzGetCurrentFileZStreamPos(unzFile file)
1574 : {
1575 : unz_s *s;
1576 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1577 4151 : s = reinterpret_cast<unz_s *>(file);
1578 4151 : if (file == nullptr)
1579 0 : return 0; // UNZ_PARAMERROR;
1580 4151 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1581 4151 : if (pfile_in_zip_read_info == nullptr)
1582 0 : return 0; // UNZ_PARAMERROR;
1583 4151 : return pfile_in_zip_read_info->pos_in_zipfile +
1584 4151 : pfile_in_zip_read_info->byte_before_the_zipfile;
1585 : }
1586 :
1587 4151 : extern int cpl_unzGetLocalHeaderPos(unzFile file, uLong64 *pos_local_header)
1588 : {
1589 : unz_s *s;
1590 :
1591 4151 : if (file == nullptr)
1592 0 : return UNZ_PARAMERROR;
1593 4151 : s = reinterpret_cast<unz_s *>(file);
1594 4151 : *pos_local_header = s->cur_file_info_internal.offset_curfile;
1595 4151 : return UNZ_OK;
1596 : }
1597 :
1598 4079 : extern int cpl_unzCurrentFileInfoFromLocalHeader(
1599 : unzFile file, uLong64 pos_local_header, unz_file_info *pfile_info,
1600 : char *szFileName, size_t fileNameBufferSize, uLong64 *posData)
1601 : {
1602 4079 : int err = UNZ_OK;
1603 : uLong uMagic, uData, uFlags;
1604 : uLong size_filename;
1605 : uLong size_extra_field;
1606 : unz_s *s;
1607 :
1608 4079 : memset(pfile_info, 0, sizeof(*pfile_info));
1609 :
1610 4079 : if (!file)
1611 0 : return UNZ_PARAMERROR;
1612 4079 : s = reinterpret_cast<unz_s *>(file);
1613 :
1614 4079 : if (ZSEEK(s->z_filefunc, s->filestream, pos_local_header,
1615 4079 : ZLIB_FILEFUNC_SEEK_SET) != 0)
1616 0 : return UNZ_ERRNO;
1617 :
1618 : // if (err == UNZ_OK)
1619 : {
1620 4079 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK)
1621 0 : err = UNZ_ERRNO;
1622 4079 : else if (uMagic != 0x04034b50)
1623 508 : err = UNZ_BADZIPFILE;
1624 : }
1625 :
1626 4079 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
1627 0 : err = UNZ_ERRNO;
1628 :
1629 4079 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uFlags) != UNZ_OK)
1630 0 : err = UNZ_ERRNO;
1631 :
1632 4079 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
1633 0 : err = UNZ_ERRNO;
1634 : else
1635 4079 : pfile_info->compression_method = uData;
1636 :
1637 4079 : if ((err == UNZ_OK) && (pfile_info->compression_method != 0) &&
1638 3503 : (pfile_info->compression_method != Z_DEFLATED))
1639 : {
1640 : #ifdef ENABLE_DEFLATE64
1641 0 : if (pfile_info->compression_method == 9)
1642 : {
1643 : // ok
1644 : }
1645 : else
1646 : #endif
1647 : {
1648 0 : CPLError(CE_Failure, CPLE_NotSupported,
1649 : "A file in the ZIP archive uses a unsupported "
1650 : "compression method (%lu)",
1651 : pfile_info->compression_method);
1652 0 : err = UNZ_BADZIPFILE;
1653 : }
1654 : }
1655 :
1656 4079 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1657 : UNZ_OK) /* date/time */
1658 0 : err = UNZ_ERRNO;
1659 :
1660 4079 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1661 : UNZ_OK) /* crc */
1662 0 : err = UNZ_ERRNO;
1663 :
1664 4079 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1665 : UNZ_OK) /* size compr */
1666 0 : err = UNZ_ERRNO;
1667 : else
1668 4079 : pfile_info->compressed_size = uData;
1669 :
1670 4079 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1671 : UNZ_OK) /* size uncompr */
1672 0 : err = UNZ_ERRNO;
1673 : else
1674 4079 : pfile_info->uncompressed_size = uData;
1675 :
1676 4079 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_filename) !=
1677 : UNZ_OK)
1678 0 : err = UNZ_ERRNO;
1679 :
1680 4079 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_extra_field) !=
1681 : UNZ_OK)
1682 0 : err = UNZ_ERRNO;
1683 :
1684 4079 : if (posData)
1685 : {
1686 4079 : *posData = pos_local_header + SIZEZIPLOCALHEADER + size_filename +
1687 : size_extra_field;
1688 : }
1689 :
1690 4079 : if (size_filename <= fileNameBufferSize && szFileName)
1691 : {
1692 3931 : if (ZREAD(s->z_filefunc, s->filestream, szFileName, size_filename) !=
1693 : size_filename)
1694 3 : err = UNZ_ERRNO;
1695 : }
1696 :
1697 4079 : return err;
1698 : }
1699 :
1700 : /** Addition for GDAL : END */
1701 :
1702 : /*
1703 : Read bytes from the current file.
1704 : buf contain buffer where data must be copied
1705 : len the size of buf.
1706 :
1707 : return the number of byte copied if some bytes are copied
1708 : return 0 if the end of file was reached
1709 : return <0 with error code if there is an error
1710 : (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1711 : */
1712 0 : extern int ZEXPORT cpl_unzReadCurrentFile(unzFile file, voidp buf, unsigned len)
1713 : {
1714 0 : int err = UNZ_OK;
1715 0 : uInt iRead = 0;
1716 : unz_s *s;
1717 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1718 0 : if (file == nullptr)
1719 0 : return UNZ_PARAMERROR;
1720 0 : s = reinterpret_cast<unz_s *>(file);
1721 0 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1722 :
1723 0 : if (pfile_in_zip_read_info == nullptr)
1724 0 : return UNZ_PARAMERROR;
1725 :
1726 0 : if (pfile_in_zip_read_info->read_buffer == nullptr)
1727 0 : return UNZ_END_OF_LIST_OF_FILE;
1728 0 : if (len == 0)
1729 0 : return 0;
1730 :
1731 0 : pfile_in_zip_read_info->stream.next_out = reinterpret_cast<Bytef *>(buf);
1732 :
1733 0 : pfile_in_zip_read_info->stream.avail_out = static_cast<uInt>(len);
1734 :
1735 0 : if ((len > pfile_in_zip_read_info->rest_read_uncompressed) &&
1736 0 : (!(pfile_in_zip_read_info->raw)))
1737 0 : pfile_in_zip_read_info->stream.avail_out =
1738 0 : static_cast<uInt>(pfile_in_zip_read_info->rest_read_uncompressed);
1739 :
1740 0 : if ((len > pfile_in_zip_read_info->rest_read_compressed +
1741 0 : pfile_in_zip_read_info->stream.avail_in) &&
1742 0 : (pfile_in_zip_read_info->raw))
1743 0 : pfile_in_zip_read_info->stream.avail_out =
1744 0 : static_cast<uInt>(pfile_in_zip_read_info->rest_read_compressed) +
1745 0 : pfile_in_zip_read_info->stream.avail_in;
1746 :
1747 0 : while (pfile_in_zip_read_info->stream.avail_out > 0)
1748 : {
1749 0 : if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1750 0 : (pfile_in_zip_read_info->rest_read_compressed > 0))
1751 : {
1752 0 : uInt uReadThis = UNZ_BUFSIZE;
1753 0 : if (pfile_in_zip_read_info->rest_read_compressed < uReadThis)
1754 0 : uReadThis = static_cast<uInt>(
1755 0 : pfile_in_zip_read_info->rest_read_compressed);
1756 0 : if (uReadThis == 0)
1757 0 : return UNZ_EOF;
1758 0 : if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1759 : pfile_in_zip_read_info->filestream,
1760 : pfile_in_zip_read_info->pos_in_zipfile +
1761 : pfile_in_zip_read_info->byte_before_the_zipfile,
1762 0 : ZLIB_FILEFUNC_SEEK_SET) != 0)
1763 0 : return UNZ_ERRNO;
1764 0 : if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1765 : pfile_in_zip_read_info->filestream,
1766 : pfile_in_zip_read_info->read_buffer,
1767 0 : uReadThis) != uReadThis)
1768 0 : return UNZ_ERRNO;
1769 :
1770 : #ifndef NOUNCRYPT
1771 : if (s->encrypted)
1772 : {
1773 : uInt i;
1774 : for (i = 0; i < uReadThis; i++)
1775 : pfile_in_zip_read_info->read_buffer[i] =
1776 : zdecode(s->keys, s->pcrc_32_tab,
1777 : pfile_in_zip_read_info->read_buffer[i]);
1778 : }
1779 : #endif
1780 :
1781 0 : pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1782 :
1783 0 : pfile_in_zip_read_info->rest_read_compressed -= uReadThis;
1784 :
1785 0 : pfile_in_zip_read_info->stream.next_in =
1786 0 : reinterpret_cast<Bytef *>(pfile_in_zip_read_info->read_buffer);
1787 0 : pfile_in_zip_read_info->stream.avail_in =
1788 : static_cast<uInt>(uReadThis);
1789 : }
1790 :
1791 0 : if ((pfile_in_zip_read_info->compression_method == 0) ||
1792 0 : (pfile_in_zip_read_info->raw))
1793 : {
1794 0 : uInt uDoCopy = 0;
1795 0 : uInt i = 0;
1796 :
1797 0 : if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1798 0 : (pfile_in_zip_read_info->rest_read_compressed == 0))
1799 0 : return (iRead == 0) ? UNZ_EOF : iRead;
1800 :
1801 0 : if (pfile_in_zip_read_info->stream.avail_out <
1802 0 : pfile_in_zip_read_info->stream.avail_in)
1803 0 : uDoCopy = pfile_in_zip_read_info->stream.avail_out;
1804 : else
1805 0 : uDoCopy = pfile_in_zip_read_info->stream.avail_in;
1806 :
1807 0 : for (i = 0; i < uDoCopy; i++)
1808 0 : *(pfile_in_zip_read_info->stream.next_out + i) =
1809 0 : *(pfile_in_zip_read_info->stream.next_in + i);
1810 :
1811 0 : pfile_in_zip_read_info->crc32 =
1812 0 : crc32(pfile_in_zip_read_info->crc32,
1813 0 : pfile_in_zip_read_info->stream.next_out, uDoCopy);
1814 0 : pfile_in_zip_read_info->rest_read_uncompressed -= uDoCopy;
1815 0 : pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1816 0 : pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1817 0 : pfile_in_zip_read_info->stream.next_out += uDoCopy;
1818 0 : pfile_in_zip_read_info->stream.next_in += uDoCopy;
1819 0 : pfile_in_zip_read_info->stream.total_out += uDoCopy;
1820 0 : iRead += uDoCopy;
1821 : }
1822 : else
1823 : {
1824 : uLong64 uTotalOutBefore, uTotalOutAfter;
1825 : const Bytef *bufBefore;
1826 : uLong64 uOutThis;
1827 0 : int flush = Z_SYNC_FLUSH;
1828 :
1829 0 : uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1830 0 : bufBefore = pfile_in_zip_read_info->stream.next_out;
1831 :
1832 : /*
1833 : if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1834 : pfile_in_zip_read_info->stream.avail_out) &&
1835 : (pfile_in_zip_read_info->rest_read_compressed == 0))
1836 : flush = Z_FINISH;
1837 : */
1838 0 : err = inflate(&pfile_in_zip_read_info->stream, flush);
1839 :
1840 0 : if ((err >= 0) && (pfile_in_zip_read_info->stream.msg != nullptr))
1841 0 : err = Z_DATA_ERROR;
1842 :
1843 0 : uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1844 0 : uOutThis = uTotalOutAfter - uTotalOutBefore;
1845 :
1846 0 : pfile_in_zip_read_info->crc32 =
1847 0 : crc32(pfile_in_zip_read_info->crc32, bufBefore,
1848 : static_cast<uInt>(uOutThis));
1849 :
1850 0 : pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
1851 :
1852 0 : iRead += static_cast<uInt>(uTotalOutAfter - uTotalOutBefore);
1853 :
1854 0 : if (err == Z_STREAM_END)
1855 0 : return (iRead == 0) ? UNZ_EOF : iRead;
1856 0 : if (err != Z_OK)
1857 0 : break;
1858 : }
1859 : }
1860 :
1861 0 : if (err == Z_OK)
1862 0 : return iRead;
1863 0 : return err;
1864 : }
1865 :
1866 : /*
1867 : Give the current position in uncompressed data
1868 : */
1869 0 : extern z_off_t ZEXPORT cpl_unztell(unzFile file)
1870 : {
1871 : unz_s *s;
1872 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1873 0 : if (file == nullptr)
1874 0 : return UNZ_PARAMERROR;
1875 0 : s = reinterpret_cast<unz_s *>(file);
1876 0 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1877 :
1878 0 : if (pfile_in_zip_read_info == nullptr)
1879 0 : return UNZ_PARAMERROR;
1880 :
1881 0 : return static_cast<z_off_t>(pfile_in_zip_read_info->stream.total_out);
1882 : }
1883 :
1884 : /*
1885 : return 1 if the end of file was reached, 0 elsewhere
1886 : */
1887 0 : extern int ZEXPORT cpl_unzeof(unzFile file)
1888 : {
1889 : unz_s *s;
1890 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1891 0 : if (file == nullptr)
1892 0 : return UNZ_PARAMERROR;
1893 0 : s = reinterpret_cast<unz_s *>(file);
1894 0 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1895 :
1896 0 : if (pfile_in_zip_read_info == nullptr)
1897 0 : return UNZ_PARAMERROR;
1898 :
1899 0 : if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1900 0 : return 1;
1901 : else
1902 0 : return 0;
1903 : }
1904 :
1905 : /*
1906 : Read extra field from the current file (opened by unzOpenCurrentFile)
1907 : This is the local-header version of the extra field (sometimes, there is
1908 : more info in the local-header version than in the central-header)
1909 :
1910 : if buf==NULL, it return the size of the local extra field that can be read
1911 :
1912 : if buf!=NULL, len is the size of the buffer, the extra header is copied in
1913 : buf.
1914 : the return value is the number of bytes copied in buf, or (if <0)
1915 : the error code
1916 : */
1917 0 : extern int ZEXPORT cpl_unzGetLocalExtrafield(unzFile file, voidp buf,
1918 : unsigned len)
1919 : {
1920 : unz_s *s;
1921 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1922 : uInt read_now;
1923 : uLong64 size_to_read;
1924 :
1925 0 : if (file == nullptr)
1926 0 : return UNZ_PARAMERROR;
1927 0 : s = reinterpret_cast<unz_s *>(file);
1928 0 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1929 :
1930 0 : if (pfile_in_zip_read_info == nullptr)
1931 0 : return UNZ_PARAMERROR;
1932 :
1933 0 : size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1934 0 : pfile_in_zip_read_info->pos_local_extrafield);
1935 :
1936 0 : if (buf == nullptr)
1937 0 : return static_cast<int>(size_to_read);
1938 :
1939 0 : if (len > size_to_read)
1940 0 : read_now = static_cast<uInt>(size_to_read);
1941 : else
1942 0 : read_now = static_cast<uInt>(len);
1943 :
1944 0 : if (read_now == 0)
1945 0 : return 0;
1946 :
1947 0 : if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1948 : pfile_in_zip_read_info->filestream,
1949 : pfile_in_zip_read_info->offset_local_extrafield +
1950 : pfile_in_zip_read_info->pos_local_extrafield,
1951 0 : ZLIB_FILEFUNC_SEEK_SET) != 0)
1952 0 : return UNZ_ERRNO;
1953 :
1954 0 : if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1955 0 : pfile_in_zip_read_info->filestream, buf, read_now) != read_now)
1956 0 : return UNZ_ERRNO;
1957 :
1958 0 : return static_cast<int>(read_now);
1959 : }
1960 :
1961 : /*
1962 : Close the file in zip opened with unzipOpenCurrentFile
1963 : Return UNZ_CRCERROR if all the file was read but the CRC is not good
1964 : */
1965 4151 : extern int ZEXPORT cpl_unzCloseCurrentFile(unzFile file)
1966 : {
1967 4151 : int err = UNZ_OK;
1968 :
1969 : unz_s *s;
1970 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1971 4151 : if (file == nullptr)
1972 0 : return UNZ_PARAMERROR;
1973 4151 : s = reinterpret_cast<unz_s *>(file);
1974 4151 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1975 :
1976 4151 : if (pfile_in_zip_read_info == nullptr)
1977 0 : return UNZ_PARAMERROR;
1978 :
1979 4151 : if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1980 0 : (!pfile_in_zip_read_info->raw))
1981 : {
1982 0 : if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1983 0 : err = UNZ_CRCERROR;
1984 : }
1985 :
1986 4151 : TRYFREE(pfile_in_zip_read_info->read_buffer);
1987 4151 : pfile_in_zip_read_info->read_buffer = nullptr;
1988 4151 : if (pfile_in_zip_read_info->stream_initialised)
1989 4079 : inflateEnd(&pfile_in_zip_read_info->stream);
1990 :
1991 4151 : pfile_in_zip_read_info->stream_initialised = 0;
1992 4151 : TRYFREE(pfile_in_zip_read_info);
1993 :
1994 4151 : s->pfile_in_zip_read = nullptr;
1995 :
1996 4151 : return err;
1997 : }
1998 :
1999 : /*
2000 : Get the global comment string of the ZipFile, in the szComment buffer.
2001 : uSizeBuf is the size of the szComment buffer.
2002 : return the number of byte copied or an error code <0
2003 : */
2004 0 : extern int ZEXPORT cpl_unzGetGlobalComment(unzFile file, char *szComment,
2005 : uLong uSizeBuf)
2006 : {
2007 : /* int err=UNZ_OK; */
2008 : unz_s *s;
2009 : uLong uReadThis;
2010 0 : if (file == nullptr)
2011 0 : return UNZ_PARAMERROR;
2012 0 : s = reinterpret_cast<unz_s *>(file);
2013 :
2014 0 : uReadThis = uSizeBuf;
2015 0 : if (uReadThis > s->gi.size_comment)
2016 0 : uReadThis = s->gi.size_comment;
2017 :
2018 0 : if (ZSEEK(s->z_filefunc, s->filestream, s->central_pos + 22,
2019 0 : ZLIB_FILEFUNC_SEEK_SET) != 0)
2020 0 : return UNZ_ERRNO;
2021 :
2022 0 : if (uReadThis > 0)
2023 : {
2024 0 : *szComment = '\0';
2025 0 : if (ZREAD(s->z_filefunc, s->filestream, szComment, uReadThis) !=
2026 : uReadThis)
2027 0 : return UNZ_ERRNO;
2028 : }
2029 :
2030 0 : if ((szComment != nullptr) && (uSizeBuf > s->gi.size_comment))
2031 0 : *(szComment + s->gi.size_comment) = '\0';
2032 0 : return static_cast<int>(uReadThis);
2033 : }
2034 :
2035 : // Additions by RX '2004.
2036 0 : extern uLong64 ZEXPORT cpl_unzGetOffset(unzFile file)
2037 : {
2038 : unz_s *s;
2039 :
2040 0 : if (file == nullptr)
2041 0 : return 0; // UNZ_PARAMERROR;
2042 0 : s = reinterpret_cast<unz_s *>(file);
2043 0 : if (!s->current_file_ok)
2044 0 : return 0;
2045 0 : if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
2046 0 : if (s->num_file == s->gi.number_entry)
2047 0 : return 0;
2048 0 : return s->pos_in_central_dir;
2049 : }
2050 :
2051 0 : extern int ZEXPORT cpl_unzSetOffset(unzFile file, uLong64 pos)
2052 : {
2053 : unz_s *s;
2054 :
2055 0 : if (file == nullptr)
2056 0 : return UNZ_PARAMERROR;
2057 0 : s = reinterpret_cast<unz_s *>(file);
2058 :
2059 0 : s->pos_in_central_dir = pos;
2060 0 : s->num_file = s->gi.number_entry; /* hack */
2061 0 : int err = unzlocal_GetCurrentFileInfoInternal(
2062 : file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
2063 : nullptr, 0, nullptr, 0);
2064 0 : s->current_file_ok = (err == UNZ_OK);
2065 0 : return err;
2066 : }
|