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 2211040 : static int unzlocal_getByte(const zlib_filefunc_def *pzlib_filefunc_def,
174 : voidpf filestream, int *pi)
175 : {
176 2211040 : unsigned char c = 0;
177 : const int err =
178 2211040 : static_cast<int>(ZREAD(*pzlib_filefunc_def, filestream, &c, 1));
179 2211040 : if (err == 1)
180 : {
181 2211020 : *pi = static_cast<int>(c);
182 2211020 : 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 497518 : static int unzlocal_getShort(const zlib_filefunc_def *pzlib_filefunc_def,
197 : voidpf filestream, uLong *pX)
198 : {
199 497518 : int i = 0;
200 497518 : int err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
201 497518 : uLong x = static_cast<uLong>(i);
202 :
203 497518 : if (err == UNZ_OK)
204 497518 : err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
205 497518 : x += static_cast<uLong>(i) << 8;
206 :
207 497518 : if (err == UNZ_OK)
208 497518 : *pX = x;
209 : else
210 0 : *pX = 0;
211 497518 : return err;
212 : }
213 :
214 303851 : static int unzlocal_getLong(const zlib_filefunc_def *pzlib_filefunc_def,
215 : voidpf filestream, uLong *pX)
216 : {
217 303851 : int i = 0;
218 303851 : int err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
219 303851 : uLong x = static_cast<uLong>(i);
220 :
221 303851 : if (err == UNZ_OK)
222 303851 : err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
223 303851 : x += static_cast<uLong>(i) << 8;
224 :
225 303851 : if (err == UNZ_OK)
226 303851 : err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
227 303851 : x += static_cast<uLong>(i) << 16;
228 :
229 303851 : if (err == UNZ_OK)
230 303851 : err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
231 303851 : x += static_cast<uLong>(i) << 24;
232 :
233 303851 : if (err == UNZ_OK)
234 303851 : *pX = x;
235 : else
236 0 : *pX = 0;
237 303851 : 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 4644 : unzlocal_SearchCentralDir(const zlib_filefunc_def *pzlib_filefunc_def,
348 : voidpf filestream)
349 : {
350 4644 : if (ZSEEK(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
351 0 : return 0;
352 :
353 : unsigned char *buf =
354 4644 : static_cast<unsigned char *>(ALLOC(BUFREADCOMMENT + 4));
355 4644 : if (buf == nullptr)
356 0 : return 0;
357 :
358 4644 : const uLong64 uSizeFile = ZTELL(*pzlib_filefunc_def, filestream);
359 :
360 4644 : uLong64 uMaxBack = 0xffff; /* maximum size of global comment */
361 4644 : if (uMaxBack > uSizeFile)
362 1902 : uMaxBack = uSizeFile;
363 :
364 4644 : uLong64 uPosFound = 0;
365 4644 : uLong64 uBackRead = 4;
366 4646 : while (uBackRead < uMaxBack)
367 : {
368 4643 : if (uBackRead + BUFREADCOMMENT > uMaxBack)
369 255 : uBackRead = uMaxBack;
370 : else
371 4388 : uBackRead += BUFREADCOMMENT;
372 4643 : const uLong64 uReadPos = uSizeFile - uBackRead;
373 :
374 4643 : const uLong uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos))
375 : ? (BUFREADCOMMENT + 4)
376 : : static_cast<uLong>(uSizeFile - uReadPos);
377 4643 : if (ZSEEK(*pzlib_filefunc_def, filestream, uReadPos,
378 4643 : ZLIB_FILEFUNC_SEEK_SET) != 0)
379 0 : break;
380 :
381 4643 : 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 88217 : for (int i = static_cast<int>(uReadSize) - 3; (i--) > 0;)
386 88217 : if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) &&
387 4643 : ((*(buf + i + 2)) == 0x05) && ((*(buf + i + 3)) == 0x06))
388 : {
389 4643 : uPosFound = uReadPos + i;
390 4643 : break;
391 : }
392 :
393 4643 : if (uPosFound != 0)
394 4641 : break;
395 : }
396 4644 : TRYFREE(buf);
397 4644 : 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 4648 : unzlocal_SearchCentralDir64(const zlib_filefunc_def *pzlib_filefunc_def,
406 : voidpf filestream)
407 : {
408 : unsigned char *buf;
409 : uLong64 uSizeFile;
410 : uLong64 uBackRead;
411 4648 : uLong64 uMaxBack = 0xffff; /* maximum size of global comment */
412 4648 : uLong64 uPosFound = 0;
413 : uLong uL;
414 :
415 4648 : if (ZSEEK(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
416 0 : return 0;
417 :
418 4648 : uSizeFile = ZTELL(*pzlib_filefunc_def, filestream);
419 :
420 4648 : if (uMaxBack > uSizeFile)
421 1902 : uMaxBack = uSizeFile;
422 :
423 4648 : buf = static_cast<unsigned char *>(ALLOC(BUFREADCOMMENT + 4));
424 4648 : if (buf == nullptr)
425 0 : return 0;
426 :
427 4648 : uBackRead = 4;
428 223565 : while (uBackRead < uMaxBack)
429 : {
430 : uLong uReadSize;
431 : uLong64 uReadPos;
432 218921 : if (uBackRead + BUFREADCOMMENT > uMaxBack)
433 4643 : uBackRead = uMaxBack;
434 : else
435 214278 : uBackRead += BUFREADCOMMENT;
436 218921 : uReadPos = uSizeFile - uBackRead;
437 :
438 218921 : uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos))
439 : ? (BUFREADCOMMENT + 4)
440 : : static_cast<uLong>(uSizeFile - uReadPos);
441 218921 : if (ZSEEK(*pzlib_filefunc_def, filestream, uReadPos,
442 218921 : ZLIB_FILEFUNC_SEEK_SET) != 0)
443 0 : break;
444 :
445 218921 : if (ZREAD(*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize)
446 0 : break;
447 :
448 224464000 : for (int i = static_cast<int>(uReadSize) - 3; (i--) > 0;)
449 224245000 : if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) &&
450 1086090 : ((*(buf + i + 2)) == 0x06) && ((*(buf + i + 3)) == 0x07))
451 : {
452 4 : uPosFound = uReadPos + i;
453 4 : break;
454 : }
455 :
456 218921 : if (uPosFound != 0)
457 4 : break;
458 : }
459 4648 : TRYFREE(buf);
460 4648 : if (uPosFound == 0)
461 4644 : 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 4648 : 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 4648 : int err = UNZ_OK;
534 :
535 4648 : 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 4648 : if (unz_copyright[0] != ' ')
540 0 : return nullptr;
541 :
542 4648 : if (pzlib_filefunc_def == nullptr)
543 4648 : cpl_fill_fopen_filefunc(&us.z_filefunc);
544 : else
545 0 : us.z_filefunc = *pzlib_filefunc_def;
546 :
547 4648 : us.filestream = (*(us.z_filefunc.zopen_file))(
548 : us.z_filefunc.opaque, path,
549 : ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
550 4648 : if (us.filestream == nullptr)
551 0 : return nullptr;
552 :
553 4648 : central_pos = unzlocal_SearchCentralDir64(&us.z_filefunc, us.filestream);
554 4648 : 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 4644 : central_pos = unzlocal_SearchCentralDir(&us.z_filefunc, us.filestream);
621 4644 : if (central_pos == 0)
622 3 : err = UNZ_ERRNO;
623 :
624 4644 : us.isZip64 = 0;
625 :
626 4644 : if (ZSEEK(us.z_filefunc, us.filestream, central_pos,
627 4644 : ZLIB_FILEFUNC_SEEK_SET) != 0)
628 0 : err = UNZ_ERRNO;
629 :
630 : /* the signature, already checked */
631 4644 : if (unzlocal_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
632 0 : err = UNZ_ERRNO;
633 :
634 : /* number of this disk */
635 4644 : 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 4644 : if (unzlocal_getShort(&us.z_filefunc, us.filestream,
641 4644 : &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 4644 : if (unzlocal_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
646 0 : err = UNZ_ERRNO;
647 4644 : us.gi.number_entry = uL;
648 :
649 : /* total number of entries in the central dir */
650 4644 : if (unzlocal_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
651 0 : err = UNZ_ERRNO;
652 4644 : number_entry_CD = uL;
653 :
654 4644 : if ((number_entry_CD != us.gi.number_entry) ||
655 4644 : (number_disk_with_CD != 0) || (number_disk != 0))
656 0 : err = UNZ_BADZIPFILE;
657 :
658 : /* size of the central directory */
659 4644 : if (unzlocal_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
660 0 : err = UNZ_ERRNO;
661 4644 : us.size_central_dir = uL;
662 :
663 : /* offset of start of central directory with respect to the
664 : starting disk number */
665 4644 : if (unzlocal_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
666 0 : err = UNZ_ERRNO;
667 4644 : us.offset_central_dir = uL;
668 :
669 : /* zipfile comment length */
670 4644 : if (unzlocal_getShort(&us.z_filefunc, us.filestream,
671 4644 : &us.gi.size_comment) != UNZ_OK)
672 0 : err = UNZ_ERRNO;
673 : }
674 :
675 4648 : if ((central_pos < us.offset_central_dir + us.size_central_dir) &&
676 : (err == UNZ_OK))
677 0 : err = UNZ_BADZIPFILE;
678 :
679 4648 : if (err != UNZ_OK)
680 : {
681 3 : ZCLOSE(us.z_filefunc, us.filestream);
682 3 : return nullptr;
683 : }
684 :
685 4645 : us.byte_before_the_zipfile =
686 4645 : central_pos - (us.offset_central_dir + us.size_central_dir);
687 4645 : us.central_pos = central_pos;
688 4645 : us.pfile_in_zip_read = nullptr;
689 4645 : us.encrypted = 0;
690 4645 : us.num_file = 0;
691 4645 : us.pos_in_central_dir = 0;
692 4645 : us.current_file_ok = 0;
693 :
694 4645 : s = static_cast<unz_s *>(ALLOC(sizeof(unz_s)));
695 4645 : *s = us;
696 4645 : cpl_unzGoToFirstFile(reinterpret_cast<unzFile>(s));
697 4645 : return reinterpret_cast<unzFile>(s);
698 : }
699 :
700 4648 : extern unzFile ZEXPORT cpl_unzOpen(const char *path)
701 : {
702 4648 : 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 4645 : extern int ZEXPORT cpl_unzClose(unzFile file)
711 : {
712 : unz_s *s;
713 4645 : if (file == nullptr)
714 0 : return UNZ_PARAMERROR;
715 4645 : s = reinterpret_cast<unz_s *>(file);
716 :
717 4645 : if (s->pfile_in_zip_read != nullptr)
718 0 : cpl_unzCloseCurrentFile(file);
719 :
720 4645 : ZCLOSE(s->z_filefunc, s->filestream);
721 4645 : TRYFREE(s);
722 4645 : 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 35918 : static void unzlocal_DosDateToTmuDate(uLong64 ulDosDate, tm_unz *ptm)
744 : {
745 : uLong64 uDate;
746 35918 : uDate = static_cast<uLong64>(ulDosDate >> 16);
747 35918 : ptm->tm_mday = static_cast<uInt>(uDate & 0x1f);
748 35918 : ptm->tm_mon = static_cast<uInt>(((uDate)&0x1E0) / 0x20);
749 35918 : if (ptm->tm_mon)
750 35913 : ptm->tm_mon--;
751 35918 : ptm->tm_year = static_cast<uInt>(((uDate & 0x0FE00) / 0x0200) + 1980);
752 :
753 35918 : ptm->tm_hour = static_cast<uInt>((ulDosDate & 0xF800) / 0x800);
754 35918 : ptm->tm_min = static_cast<uInt>((ulDosDate & 0x7E0) / 0x20);
755 35918 : ptm->tm_sec = static_cast<uInt>(2 * (ulDosDate & 0x1f));
756 35918 : }
757 :
758 : /*
759 : Get Info about the current file in the zipfile, with internal only info
760 : */
761 35918 : 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 35918 : int err = UNZ_OK;
772 : uLong uMagic;
773 35918 : long lSeek = 0;
774 : uLong uL;
775 35918 : bool bHasUTF8Filename = false;
776 :
777 35918 : if (file == nullptr)
778 0 : return UNZ_PARAMERROR;
779 35918 : s = reinterpret_cast<unz_s *>(file);
780 35918 : if (ZSEEK(s->z_filefunc, s->filestream,
781 : s->pos_in_central_dir + s->byte_before_the_zipfile,
782 35918 : ZLIB_FILEFUNC_SEEK_SET) != 0)
783 0 : err = UNZ_ERRNO;
784 :
785 : /* we check the magic */
786 35918 : if (err == UNZ_OK)
787 : {
788 35918 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK)
789 0 : err = UNZ_ERRNO;
790 35918 : else if (uMagic != 0x02014b50)
791 0 : err = UNZ_BADZIPFILE;
792 : }
793 :
794 35918 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.version) !=
795 : UNZ_OK)
796 0 : err = UNZ_ERRNO;
797 :
798 35918 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
799 35918 : &file_info.version_needed) != UNZ_OK)
800 0 : err = UNZ_ERRNO;
801 :
802 35918 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.flag) !=
803 : UNZ_OK)
804 0 : err = UNZ_ERRNO;
805 :
806 35918 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
807 35918 : &file_info.compression_method) != UNZ_OK)
808 0 : err = UNZ_ERRNO;
809 :
810 35918 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info.dosDate) !=
811 : UNZ_OK)
812 0 : err = UNZ_ERRNO;
813 :
814 35918 : unzlocal_DosDateToTmuDate(file_info.dosDate, &file_info.tmu_date);
815 :
816 35918 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info.crc) !=
817 : UNZ_OK)
818 0 : err = UNZ_ERRNO;
819 :
820 35918 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
821 0 : err = UNZ_ERRNO;
822 35918 : file_info.compressed_size = uL;
823 :
824 35918 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
825 0 : err = UNZ_ERRNO;
826 35918 : file_info.uncompressed_size = uL;
827 :
828 35918 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
829 35918 : &file_info.size_filename) != UNZ_OK)
830 0 : err = UNZ_ERRNO;
831 :
832 35918 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
833 35918 : &file_info.size_file_extra) != UNZ_OK)
834 0 : err = UNZ_ERRNO;
835 :
836 35918 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
837 35918 : &file_info.size_file_comment) != UNZ_OK)
838 0 : err = UNZ_ERRNO;
839 :
840 35918 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
841 35918 : &file_info.disk_num_start) != UNZ_OK)
842 0 : err = UNZ_ERRNO;
843 :
844 35918 : if (unzlocal_getShort(&s->z_filefunc, s->filestream,
845 35918 : &file_info.internal_fa) != UNZ_OK)
846 0 : err = UNZ_ERRNO;
847 :
848 35918 : if (unzlocal_getLong(&s->z_filefunc, s->filestream,
849 35918 : &file_info.external_fa) != UNZ_OK)
850 0 : err = UNZ_ERRNO;
851 :
852 35918 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
853 0 : err = UNZ_ERRNO;
854 35918 : file_info_internal.offset_curfile = uL;
855 :
856 35918 : lSeek += file_info.size_filename;
857 35918 : if ((err == UNZ_OK) && (szFileName != nullptr))
858 : {
859 13699 : uLong uSizeRead = 0;
860 13699 : if (file_info.size_filename < fileNameBufferSize)
861 : {
862 13699 : *(szFileName + file_info.size_filename) = '\0';
863 13699 : uSizeRead = file_info.size_filename;
864 : }
865 : else
866 0 : uSizeRead = fileNameBufferSize;
867 :
868 13699 : if ((file_info.size_filename > 0) && (fileNameBufferSize > 0))
869 : {
870 13697 : if (ZREAD(s->z_filefunc, s->filestream, szFileName, uSizeRead) !=
871 : uSizeRead)
872 0 : err = UNZ_ERRNO;
873 : }
874 13699 : 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 35918 : if ((err == UNZ_OK) && (file_info.size_file_extra != 0))
903 : {
904 28338 : if (lSeek != 0)
905 : {
906 17639 : if (ZSEEK(s->z_filefunc, s->filestream, lSeek,
907 17639 : ZLIB_FILEFUNC_SEEK_CUR) == 0)
908 : {
909 17639 : lSeek = 0;
910 17639 : CPL_IGNORE_RET_VAL(lSeek);
911 : }
912 : else
913 0 : err = UNZ_ERRNO;
914 : }
915 :
916 28338 : uLong acc = 0;
917 28338 : file_info.file_extra_abs_offset = ZTELL(s->z_filefunc, s->filestream);
918 84622 : while (acc < file_info.size_file_extra)
919 : {
920 : uLong headerId;
921 56284 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &headerId) !=
922 : UNZ_OK)
923 0 : err = UNZ_ERRNO;
924 :
925 : uLong dataSize;
926 56284 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &dataSize) !=
927 : UNZ_OK)
928 0 : err = UNZ_ERRNO;
929 :
930 : /* ZIP64 extra fields */
931 56284 : 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 56248 : 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 56243 : if (ZSEEK(s->z_filefunc, s->filestream, dataSize,
1034 56243 : ZLIB_FILEFUNC_SEEK_CUR) != 0)
1035 0 : err = UNZ_ERRNO;
1036 : }
1037 :
1038 56284 : acc += 2 + 2 + dataSize;
1039 : }
1040 : }
1041 :
1042 35918 : if (!bHasUTF8Filename && szFileName != nullptr &&
1043 13694 : (file_info.flag & (1 << 11)) == 0 &&
1044 13123 : file_info.size_filename < fileNameBufferSize)
1045 : {
1046 13123 : 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 13123 : char *pszRecoded = CPLRecode(szFileName, pszSrcEncoding, CPL_ENC_UTF8);
1054 13123 : if (pszRecoded != nullptr && strlen(pszRecoded) < fileNameBufferSize)
1055 : {
1056 13123 : strcpy(szFileName, pszRecoded);
1057 : }
1058 13123 : 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 35918 : if ((err == UNZ_OK) && (pfile_info != nullptr))
1091 35918 : *pfile_info = file_info;
1092 :
1093 35918 : if ((err == UNZ_OK) && (pfile_info_internal != nullptr))
1094 18344 : *pfile_info_internal = file_info_internal;
1095 :
1096 35918 : 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 17574 : 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 17574 : return unzlocal_GetCurrentFileInfoInternal(
1110 : file, pfile_info, nullptr, szFileName, fileNameBufferSize, extraField,
1111 17574 : 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 9894 : extern int ZEXPORT cpl_unzGoToFirstFile(unzFile file)
1119 : {
1120 9894 : int err = UNZ_OK;
1121 : unz_s *s;
1122 9894 : if (file == nullptr)
1123 0 : return UNZ_PARAMERROR;
1124 9894 : s = reinterpret_cast<unz_s *>(file);
1125 9894 : s->pos_in_central_dir = s->offset_central_dir;
1126 9894 : s->num_file = 0;
1127 9894 : err = unzlocal_GetCurrentFileInfoInternal(
1128 : file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
1129 : nullptr, 0, nullptr, 0);
1130 9894 : s->current_file_ok = (err == UNZ_OK);
1131 9894 : 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 5107 : extern int ZEXPORT cpl_unzGoToNextFile(unzFile file)
1140 : {
1141 : unz_s *s;
1142 :
1143 5107 : if (file == nullptr)
1144 0 : return UNZ_PARAMERROR;
1145 5107 : s = reinterpret_cast<unz_s *>(file);
1146 5107 : if (!s->current_file_ok)
1147 0 : return UNZ_END_OF_LIST_OF_FILE;
1148 5107 : if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
1149 5107 : if (s->num_file + 1 == s->gi.number_entry)
1150 436 : return UNZ_END_OF_LIST_OF_FILE;
1151 :
1152 4671 : s->pos_in_central_dir +=
1153 4671 : SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
1154 4671 : s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment;
1155 4671 : s->num_file++;
1156 4671 : int err = unzlocal_GetCurrentFileInfoInternal(
1157 : file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
1158 : nullptr, 0, nullptr, 0);
1159 4671 : s->current_file_ok = (err == UNZ_OK);
1160 4671 : 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 0 : s->num_file = num_fileSaved;
1221 0 : s->pos_in_central_dir = pos_in_central_dirSaved;
1222 0 : s->cur_file_info = cur_file_infoSaved;
1223 0 : s->cur_file_info_internal = cur_file_info_internalSaved;
1224 0 : return err;
1225 : }
1226 :
1227 : /*
1228 : ///////////////////////////////////////////
1229 : // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
1230 : // I need random access
1231 : //
1232 : // Further optimization could be realized by adding an ability
1233 : // to cache the directory in memory. The goal being a single
1234 : // comprehensive file read to put the file I need in a memory.
1235 : */
1236 :
1237 : /*
1238 : typedef struct unz_file_pos_s
1239 : {
1240 : uLong64 pos_in_zip_directory; // offset in file
1241 : uLong64 num_of_file; // # of file
1242 : } unz_file_pos;
1243 : */
1244 :
1245 13133 : extern int ZEXPORT cpl_unzGetFilePos(unzFile file, unz_file_pos *file_pos)
1246 : {
1247 : unz_s *s;
1248 :
1249 13133 : if (file == nullptr || file_pos == nullptr)
1250 0 : return UNZ_PARAMERROR;
1251 13133 : s = reinterpret_cast<unz_s *>(file);
1252 13133 : if (!s->current_file_ok)
1253 0 : return UNZ_END_OF_LIST_OF_FILE;
1254 :
1255 13133 : file_pos->pos_in_zip_directory = s->pos_in_central_dir;
1256 13133 : file_pos->num_of_file = s->num_file;
1257 :
1258 13133 : return UNZ_OK;
1259 : }
1260 :
1261 3779 : extern int ZEXPORT cpl_unzGoToFilePos(unzFile file, unz_file_pos *file_pos)
1262 : {
1263 : unz_s *s;
1264 :
1265 3779 : if (file == nullptr || file_pos == nullptr)
1266 0 : return UNZ_PARAMERROR;
1267 3779 : s = reinterpret_cast<unz_s *>(file);
1268 :
1269 : /* jump to the right spot */
1270 3779 : s->pos_in_central_dir = file_pos->pos_in_zip_directory;
1271 3779 : s->num_file = file_pos->num_of_file;
1272 :
1273 : /* set the current file */
1274 3779 : int err = unzlocal_GetCurrentFileInfoInternal(
1275 : file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
1276 : nullptr, 0, nullptr, 0);
1277 : /* return results */
1278 3779 : s->current_file_ok = (err == UNZ_OK);
1279 3779 : return err;
1280 : }
1281 :
1282 : /*
1283 : // Unzip Helper Functions - should be here?
1284 : ///////////////////////////////////////////
1285 : */
1286 :
1287 : /*
1288 : Read the local header of the current zipfile
1289 : Check the coherency of the local header and info in the end of central
1290 : directory about this file
1291 : store in *piSizeVar the size of extra info in local header
1292 : (filename and size of extra field data)
1293 : */
1294 : static int
1295 3875 : unzlocal_CheckCurrentFileCoherencyHeader(unz_s *s, uInt *piSizeVar,
1296 : uLong64 *poffset_local_extrafield,
1297 : uInt *psize_local_extrafield)
1298 : {
1299 : uLong uMagic, uData, uFlags;
1300 : uLong size_filename;
1301 : uLong size_extra_field;
1302 3875 : int err = UNZ_OK;
1303 :
1304 3875 : *piSizeVar = 0;
1305 3875 : *poffset_local_extrafield = 0;
1306 3875 : *psize_local_extrafield = 0;
1307 :
1308 3875 : if (ZSEEK(s->z_filefunc, s->filestream,
1309 : s->cur_file_info_internal.offset_curfile +
1310 : s->byte_before_the_zipfile,
1311 3875 : ZLIB_FILEFUNC_SEEK_SET) != 0)
1312 0 : return UNZ_ERRNO;
1313 :
1314 3875 : if (err == UNZ_OK)
1315 : {
1316 3875 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK)
1317 0 : err = UNZ_ERRNO;
1318 3875 : else if (uMagic != 0x04034b50)
1319 0 : err = UNZ_BADZIPFILE;
1320 : }
1321 :
1322 3875 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
1323 0 : err = UNZ_ERRNO;
1324 : /*
1325 : else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1326 : err=UNZ_BADZIPFILE;
1327 : */
1328 3875 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uFlags) != UNZ_OK)
1329 0 : err = UNZ_ERRNO;
1330 :
1331 3875 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
1332 0 : err = UNZ_ERRNO;
1333 3875 : else if ((err == UNZ_OK) && (uData != s->cur_file_info.compression_method))
1334 0 : err = UNZ_BADZIPFILE;
1335 :
1336 3875 : if ((err == UNZ_OK) && (s->cur_file_info.compression_method != 0) &&
1337 3818 : (s->cur_file_info.compression_method != Z_DEFLATED))
1338 : {
1339 : #ifdef ENABLE_DEFLATE64
1340 1 : if (s->cur_file_info.compression_method == 9)
1341 : {
1342 : // ok
1343 : }
1344 : else
1345 : #endif
1346 : {
1347 0 : CPLError(CE_Failure, CPLE_NotSupported,
1348 : "A file in the ZIP archive uses a unsupported "
1349 : "compression method (%lu)",
1350 : s->cur_file_info.compression_method);
1351 0 : err = UNZ_BADZIPFILE;
1352 : }
1353 : }
1354 :
1355 3875 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1356 : UNZ_OK) /* date/time */
1357 0 : err = UNZ_ERRNO;
1358 :
1359 3875 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1360 : UNZ_OK) /* crc */
1361 0 : err = UNZ_ERRNO;
1362 3875 : else if ((err == UNZ_OK) && (uData != s->cur_file_info.crc) &&
1363 157 : ((uFlags & 8) == 0))
1364 0 : err = UNZ_BADZIPFILE;
1365 :
1366 3875 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1367 : UNZ_OK) /* size compr */
1368 0 : err = UNZ_ERRNO;
1369 3875 : else if (uData != 0xFFFFFFFF && (err == UNZ_OK) &&
1370 3872 : (uData != s->cur_file_info.compressed_size) && ((uFlags & 8) == 0))
1371 0 : err = UNZ_BADZIPFILE;
1372 :
1373 3875 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1374 : UNZ_OK) /* size uncompr */
1375 0 : err = UNZ_ERRNO;
1376 3875 : else if (uData != 0xFFFFFFFF && (err == UNZ_OK) &&
1377 3872 : (uData != s->cur_file_info.uncompressed_size) &&
1378 157 : ((uFlags & 8) == 0))
1379 0 : err = UNZ_BADZIPFILE;
1380 :
1381 3875 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_filename) !=
1382 : UNZ_OK)
1383 0 : err = UNZ_ERRNO;
1384 3875 : else if ((err == UNZ_OK) &&
1385 3875 : (size_filename != s->cur_file_info.size_filename))
1386 0 : err = UNZ_BADZIPFILE;
1387 :
1388 3875 : *piSizeVar += static_cast<uInt>(size_filename);
1389 :
1390 3875 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_extra_field) !=
1391 : UNZ_OK)
1392 0 : err = UNZ_ERRNO;
1393 3875 : *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile +
1394 3875 : SIZEZIPLOCALHEADER + size_filename;
1395 3875 : *psize_local_extrafield = static_cast<uInt>(size_extra_field);
1396 :
1397 3875 : *piSizeVar += static_cast<uInt>(size_extra_field);
1398 :
1399 3875 : return err;
1400 : }
1401 :
1402 : /*
1403 : Open for reading data the current file in the zipfile.
1404 : If there is no error and the file is opened, the return value is UNZ_OK.
1405 : */
1406 3875 : extern int ZEXPORT cpl_unzOpenCurrentFile3(unzFile file, int *method,
1407 : int *level, int raw,
1408 : const char *password)
1409 : {
1410 3875 : int err = UNZ_OK;
1411 : uInt iSizeVar;
1412 : unz_s *s;
1413 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1414 : uLong64 offset_local_extrafield; /* offset of the local extra field */
1415 : uInt size_local_extrafield; /* size of the local extra field */
1416 : #ifndef NOUNCRYPT
1417 : char source[12];
1418 : #else
1419 3875 : if (password != nullptr)
1420 0 : return UNZ_PARAMERROR;
1421 : #endif
1422 :
1423 3875 : if (file == nullptr)
1424 0 : return UNZ_PARAMERROR;
1425 3875 : s = reinterpret_cast<unz_s *>(file);
1426 3875 : if (!s->current_file_ok)
1427 0 : return UNZ_PARAMERROR;
1428 :
1429 3875 : if (s->pfile_in_zip_read != nullptr)
1430 0 : cpl_unzCloseCurrentFile(file);
1431 :
1432 3875 : if (unzlocal_CheckCurrentFileCoherencyHeader(
1433 3875 : s, &iSizeVar, &offset_local_extrafield, &size_local_extrafield) !=
1434 : UNZ_OK)
1435 0 : return UNZ_BADZIPFILE;
1436 :
1437 : pfile_in_zip_read_info = static_cast<file_in_zip_read_info_s *>(
1438 3875 : ALLOC(sizeof(file_in_zip_read_info_s)));
1439 3875 : if (pfile_in_zip_read_info == nullptr)
1440 0 : return UNZ_INTERNALERROR;
1441 :
1442 3875 : pfile_in_zip_read_info->read_buffer =
1443 3875 : static_cast<char *>(ALLOC(UNZ_BUFSIZE));
1444 3875 : pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1445 3875 : pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1446 3875 : pfile_in_zip_read_info->pos_local_extrafield = 0;
1447 3875 : pfile_in_zip_read_info->raw = raw;
1448 :
1449 3875 : if (pfile_in_zip_read_info->read_buffer == nullptr)
1450 : {
1451 0 : TRYFREE(pfile_in_zip_read_info);
1452 0 : return UNZ_INTERNALERROR;
1453 : }
1454 :
1455 3875 : pfile_in_zip_read_info->stream_initialised = 0;
1456 :
1457 3875 : if (method != nullptr)
1458 0 : *method = static_cast<int>(s->cur_file_info.compression_method);
1459 :
1460 3875 : if (level != nullptr)
1461 : {
1462 0 : *level = 6;
1463 0 : switch (s->cur_file_info.flag & 0x06)
1464 : {
1465 0 : case 6:
1466 0 : *level = 1;
1467 0 : break;
1468 0 : case 4:
1469 0 : *level = 2;
1470 0 : break;
1471 0 : case 2:
1472 0 : *level = 9;
1473 0 : break;
1474 : }
1475 : }
1476 :
1477 : /*if ((s->cur_file_info.compression_method!=0) &&
1478 : (s->cur_file_info.compression_method!=Z_DEFLATED))
1479 : err=UNZ_BADZIPFILE;*/
1480 :
1481 3875 : pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc;
1482 3875 : pfile_in_zip_read_info->crc32 = 0;
1483 3875 : pfile_in_zip_read_info->compression_method =
1484 3875 : s->cur_file_info.compression_method;
1485 3875 : pfile_in_zip_read_info->filestream = s->filestream;
1486 3875 : pfile_in_zip_read_info->z_filefunc = s->z_filefunc;
1487 3875 : pfile_in_zip_read_info->byte_before_the_zipfile =
1488 3875 : s->byte_before_the_zipfile;
1489 :
1490 3875 : pfile_in_zip_read_info->stream.total_out = 0;
1491 :
1492 3875 : if ((s->cur_file_info.compression_method == Z_DEFLATED) && (!raw))
1493 : {
1494 3817 : pfile_in_zip_read_info->stream.zalloc = nullptr;
1495 3817 : pfile_in_zip_read_info->stream.zfree = nullptr;
1496 3817 : pfile_in_zip_read_info->stream.opaque = nullptr;
1497 3817 : pfile_in_zip_read_info->stream.next_in = nullptr;
1498 3817 : pfile_in_zip_read_info->stream.avail_in = 0;
1499 :
1500 3817 : err = inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1501 3817 : if (err == Z_OK)
1502 3817 : pfile_in_zip_read_info->stream_initialised = 1;
1503 : else
1504 : {
1505 0 : TRYFREE(pfile_in_zip_read_info);
1506 0 : return err;
1507 : }
1508 : /* windowBits is passed < 0 to tell that there is no zlib header.
1509 : * Note that in this case inflate *requires* an extra "dummy" byte
1510 : * after the compressed stream in order to complete decompression and
1511 : * return Z_STREAM_END.
1512 : * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1513 : * size of both compressed and uncompressed data
1514 : */
1515 : }
1516 3875 : pfile_in_zip_read_info->rest_read_compressed =
1517 3875 : s->cur_file_info.compressed_size;
1518 3875 : pfile_in_zip_read_info->rest_read_uncompressed =
1519 3875 : s->cur_file_info.uncompressed_size;
1520 :
1521 3875 : pfile_in_zip_read_info->pos_in_zipfile =
1522 3875 : s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1523 3875 : iSizeVar;
1524 :
1525 3875 : pfile_in_zip_read_info->stream.avail_in = 0;
1526 :
1527 3875 : s->pfile_in_zip_read = pfile_in_zip_read_info;
1528 :
1529 : #ifndef NOUNCRYPT
1530 : if (password != nullptr)
1531 : {
1532 : s->pcrc_32_tab = get_crc_table();
1533 : init_keys(password, s->keys, s->pcrc_32_tab);
1534 : if (ZSEEK(s->z_filefunc, s->filestream,
1535 : s->pfile_in_zip_read->pos_in_zipfile +
1536 : s->pfile_in_zip_read->byte_before_the_zipfile,
1537 : SEEK_SET) != 0)
1538 : return UNZ_INTERNALERROR;
1539 : if (ZREAD(s->z_filefunc, s->filestream, source, 12) < 12)
1540 : return UNZ_INTERNALERROR;
1541 :
1542 : for (int i = 0; i < 12; i++)
1543 : zdecode(s->keys, s->pcrc_32_tab, source[i]);
1544 :
1545 : s->pfile_in_zip_read->pos_in_zipfile += 12;
1546 : s->encrypted = 1;
1547 : }
1548 : #endif
1549 :
1550 3875 : return UNZ_OK;
1551 : }
1552 :
1553 3875 : extern int ZEXPORT cpl_unzOpenCurrentFile(unzFile file)
1554 : {
1555 3875 : return cpl_unzOpenCurrentFile3(file, nullptr, nullptr, 0, nullptr);
1556 : }
1557 :
1558 0 : extern int ZEXPORT cpl_unzOpenCurrentFilePassword(unzFile file,
1559 : const char *password)
1560 : {
1561 0 : return cpl_unzOpenCurrentFile3(file, nullptr, nullptr, 0, password);
1562 : }
1563 :
1564 0 : extern int ZEXPORT cpl_unzOpenCurrentFile2(unzFile file, int *method,
1565 : int *level, int raw)
1566 : {
1567 0 : return cpl_unzOpenCurrentFile3(file, method, level, raw, nullptr);
1568 : }
1569 :
1570 : /** Addition for GDAL : START */
1571 :
1572 3875 : extern uLong64 ZEXPORT cpl_unzGetCurrentFileZStreamPos(unzFile file)
1573 : {
1574 : unz_s *s;
1575 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1576 3875 : s = reinterpret_cast<unz_s *>(file);
1577 3875 : if (file == nullptr)
1578 0 : return 0; // UNZ_PARAMERROR;
1579 3875 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1580 3875 : if (pfile_in_zip_read_info == nullptr)
1581 0 : return 0; // UNZ_PARAMERROR;
1582 3875 : return pfile_in_zip_read_info->pos_in_zipfile +
1583 3875 : pfile_in_zip_read_info->byte_before_the_zipfile;
1584 : }
1585 :
1586 3875 : extern int cpl_unzGetLocalHeaderPos(unzFile file, uLong64 *pos_local_header)
1587 : {
1588 : unz_s *s;
1589 :
1590 3875 : if (file == nullptr)
1591 0 : return UNZ_PARAMERROR;
1592 3875 : s = reinterpret_cast<unz_s *>(file);
1593 3875 : *pos_local_header = s->cur_file_info_internal.offset_curfile;
1594 3875 : return UNZ_OK;
1595 : }
1596 :
1597 3817 : extern int cpl_unzCurrentFileInfoFromLocalHeader(
1598 : unzFile file, uLong64 pos_local_header, unz_file_info *pfile_info,
1599 : char *szFileName, size_t fileNameBufferSize, uLong64 *posData)
1600 : {
1601 3817 : int err = UNZ_OK;
1602 : uLong uMagic, uData, uFlags;
1603 : uLong size_filename;
1604 : uLong size_extra_field;
1605 : unz_s *s;
1606 :
1607 3817 : memset(pfile_info, 0, sizeof(*pfile_info));
1608 :
1609 3817 : if (!file)
1610 0 : return UNZ_PARAMERROR;
1611 3817 : s = reinterpret_cast<unz_s *>(file);
1612 :
1613 3817 : if (ZSEEK(s->z_filefunc, s->filestream, pos_local_header,
1614 3817 : ZLIB_FILEFUNC_SEEK_SET) != 0)
1615 0 : return UNZ_ERRNO;
1616 :
1617 3817 : if (err == UNZ_OK)
1618 : {
1619 3817 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK)
1620 0 : err = UNZ_ERRNO;
1621 3817 : else if (uMagic != 0x04034b50)
1622 408 : err = UNZ_BADZIPFILE;
1623 : }
1624 :
1625 3817 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
1626 0 : err = UNZ_ERRNO;
1627 :
1628 3817 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uFlags) != UNZ_OK)
1629 0 : err = UNZ_ERRNO;
1630 :
1631 3817 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
1632 0 : err = UNZ_ERRNO;
1633 : else
1634 3817 : pfile_info->compression_method = uData;
1635 :
1636 3817 : if ((err == UNZ_OK) && (pfile_info->compression_method != 0) &&
1637 3353 : (pfile_info->compression_method != Z_DEFLATED))
1638 : {
1639 : #ifdef ENABLE_DEFLATE64
1640 0 : if (pfile_info->compression_method == 9)
1641 : {
1642 : // ok
1643 : }
1644 : else
1645 : #endif
1646 : {
1647 0 : CPLError(CE_Failure, CPLE_NotSupported,
1648 : "A file in the ZIP archive uses a unsupported "
1649 : "compression method (%lu)",
1650 : pfile_info->compression_method);
1651 0 : err = UNZ_BADZIPFILE;
1652 : }
1653 : }
1654 :
1655 3817 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1656 : UNZ_OK) /* date/time */
1657 0 : err = UNZ_ERRNO;
1658 :
1659 3817 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1660 : UNZ_OK) /* crc */
1661 0 : err = UNZ_ERRNO;
1662 :
1663 3817 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1664 : UNZ_OK) /* size compr */
1665 0 : err = UNZ_ERRNO;
1666 : else
1667 3817 : pfile_info->compressed_size = uData;
1668 :
1669 3817 : if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
1670 : UNZ_OK) /* size uncompr */
1671 0 : err = UNZ_ERRNO;
1672 : else
1673 3817 : pfile_info->uncompressed_size = uData;
1674 :
1675 3817 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_filename) !=
1676 : UNZ_OK)
1677 0 : err = UNZ_ERRNO;
1678 :
1679 3817 : if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_extra_field) !=
1680 : UNZ_OK)
1681 0 : err = UNZ_ERRNO;
1682 :
1683 3817 : if (posData)
1684 : {
1685 3817 : *posData = pos_local_header + SIZEZIPLOCALHEADER + size_filename +
1686 : size_extra_field;
1687 : }
1688 :
1689 3817 : if (size_filename <= fileNameBufferSize && szFileName)
1690 : {
1691 3674 : if (ZREAD(s->z_filefunc, s->filestream, szFileName, size_filename) !=
1692 : size_filename)
1693 3 : err = UNZ_ERRNO;
1694 : }
1695 :
1696 3817 : return err;
1697 : }
1698 :
1699 : /** Addition for GDAL : END */
1700 :
1701 : /*
1702 : Read bytes from the current file.
1703 : buf contain buffer where data must be copied
1704 : len the size of buf.
1705 :
1706 : return the number of byte copied if some bytes are copied
1707 : return 0 if the end of file was reached
1708 : return <0 with error code if there is an error
1709 : (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1710 : */
1711 0 : extern int ZEXPORT cpl_unzReadCurrentFile(unzFile file, voidp buf, unsigned len)
1712 : {
1713 0 : int err = UNZ_OK;
1714 0 : uInt iRead = 0;
1715 : unz_s *s;
1716 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1717 0 : if (file == nullptr)
1718 0 : return UNZ_PARAMERROR;
1719 0 : s = reinterpret_cast<unz_s *>(file);
1720 0 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1721 :
1722 0 : if (pfile_in_zip_read_info == nullptr)
1723 0 : return UNZ_PARAMERROR;
1724 :
1725 0 : if (pfile_in_zip_read_info->read_buffer == nullptr)
1726 0 : return UNZ_END_OF_LIST_OF_FILE;
1727 0 : if (len == 0)
1728 0 : return 0;
1729 :
1730 0 : pfile_in_zip_read_info->stream.next_out = reinterpret_cast<Bytef *>(buf);
1731 :
1732 0 : pfile_in_zip_read_info->stream.avail_out = static_cast<uInt>(len);
1733 :
1734 0 : if ((len > pfile_in_zip_read_info->rest_read_uncompressed) &&
1735 0 : (!(pfile_in_zip_read_info->raw)))
1736 0 : pfile_in_zip_read_info->stream.avail_out =
1737 0 : static_cast<uInt>(pfile_in_zip_read_info->rest_read_uncompressed);
1738 :
1739 0 : if ((len > pfile_in_zip_read_info->rest_read_compressed +
1740 0 : pfile_in_zip_read_info->stream.avail_in) &&
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_compressed) +
1744 0 : pfile_in_zip_read_info->stream.avail_in;
1745 :
1746 0 : while (pfile_in_zip_read_info->stream.avail_out > 0)
1747 : {
1748 0 : if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1749 0 : (pfile_in_zip_read_info->rest_read_compressed > 0))
1750 : {
1751 0 : uInt uReadThis = UNZ_BUFSIZE;
1752 0 : if (pfile_in_zip_read_info->rest_read_compressed < uReadThis)
1753 0 : uReadThis = static_cast<uInt>(
1754 0 : pfile_in_zip_read_info->rest_read_compressed);
1755 0 : if (uReadThis == 0)
1756 0 : return UNZ_EOF;
1757 0 : if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1758 : pfile_in_zip_read_info->filestream,
1759 : pfile_in_zip_read_info->pos_in_zipfile +
1760 : pfile_in_zip_read_info->byte_before_the_zipfile,
1761 0 : ZLIB_FILEFUNC_SEEK_SET) != 0)
1762 0 : return UNZ_ERRNO;
1763 0 : if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1764 : pfile_in_zip_read_info->filestream,
1765 : pfile_in_zip_read_info->read_buffer,
1766 0 : uReadThis) != uReadThis)
1767 0 : return UNZ_ERRNO;
1768 :
1769 : #ifndef NOUNCRYPT
1770 : if (s->encrypted)
1771 : {
1772 : uInt i;
1773 : for (i = 0; i < uReadThis; i++)
1774 : pfile_in_zip_read_info->read_buffer[i] =
1775 : zdecode(s->keys, s->pcrc_32_tab,
1776 : pfile_in_zip_read_info->read_buffer[i]);
1777 : }
1778 : #endif
1779 :
1780 0 : pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1781 :
1782 0 : pfile_in_zip_read_info->rest_read_compressed -= uReadThis;
1783 :
1784 0 : pfile_in_zip_read_info->stream.next_in =
1785 0 : reinterpret_cast<Bytef *>(pfile_in_zip_read_info->read_buffer);
1786 0 : pfile_in_zip_read_info->stream.avail_in =
1787 : static_cast<uInt>(uReadThis);
1788 : }
1789 :
1790 0 : if ((pfile_in_zip_read_info->compression_method == 0) ||
1791 0 : (pfile_in_zip_read_info->raw))
1792 : {
1793 0 : uInt uDoCopy = 0;
1794 0 : uInt i = 0;
1795 :
1796 0 : if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1797 0 : (pfile_in_zip_read_info->rest_read_compressed == 0))
1798 0 : return (iRead == 0) ? UNZ_EOF : iRead;
1799 :
1800 0 : if (pfile_in_zip_read_info->stream.avail_out <
1801 0 : pfile_in_zip_read_info->stream.avail_in)
1802 0 : uDoCopy = pfile_in_zip_read_info->stream.avail_out;
1803 : else
1804 0 : uDoCopy = pfile_in_zip_read_info->stream.avail_in;
1805 :
1806 0 : for (i = 0; i < uDoCopy; i++)
1807 0 : *(pfile_in_zip_read_info->stream.next_out + i) =
1808 0 : *(pfile_in_zip_read_info->stream.next_in + i);
1809 :
1810 0 : pfile_in_zip_read_info->crc32 =
1811 0 : crc32(pfile_in_zip_read_info->crc32,
1812 0 : pfile_in_zip_read_info->stream.next_out, uDoCopy);
1813 0 : pfile_in_zip_read_info->rest_read_uncompressed -= uDoCopy;
1814 0 : pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1815 0 : pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1816 0 : pfile_in_zip_read_info->stream.next_out += uDoCopy;
1817 0 : pfile_in_zip_read_info->stream.next_in += uDoCopy;
1818 0 : pfile_in_zip_read_info->stream.total_out += uDoCopy;
1819 0 : iRead += uDoCopy;
1820 : }
1821 : else
1822 : {
1823 : uLong64 uTotalOutBefore, uTotalOutAfter;
1824 : const Bytef *bufBefore;
1825 : uLong64 uOutThis;
1826 0 : int flush = Z_SYNC_FLUSH;
1827 :
1828 0 : uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1829 0 : bufBefore = pfile_in_zip_read_info->stream.next_out;
1830 :
1831 : /*
1832 : if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1833 : pfile_in_zip_read_info->stream.avail_out) &&
1834 : (pfile_in_zip_read_info->rest_read_compressed == 0))
1835 : flush = Z_FINISH;
1836 : */
1837 0 : err = inflate(&pfile_in_zip_read_info->stream, flush);
1838 :
1839 0 : if ((err >= 0) && (pfile_in_zip_read_info->stream.msg != nullptr))
1840 0 : err = Z_DATA_ERROR;
1841 :
1842 0 : uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1843 0 : uOutThis = uTotalOutAfter - uTotalOutBefore;
1844 :
1845 0 : pfile_in_zip_read_info->crc32 =
1846 0 : crc32(pfile_in_zip_read_info->crc32, bufBefore,
1847 : static_cast<uInt>(uOutThis));
1848 :
1849 0 : pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
1850 :
1851 0 : iRead += static_cast<uInt>(uTotalOutAfter - uTotalOutBefore);
1852 :
1853 0 : if (err == Z_STREAM_END)
1854 0 : return (iRead == 0) ? UNZ_EOF : iRead;
1855 0 : if (err != Z_OK)
1856 0 : break;
1857 : }
1858 : }
1859 :
1860 0 : if (err == Z_OK)
1861 0 : return iRead;
1862 0 : return err;
1863 : }
1864 :
1865 : /*
1866 : Give the current position in uncompressed data
1867 : */
1868 0 : extern z_off_t ZEXPORT cpl_unztell(unzFile file)
1869 : {
1870 : unz_s *s;
1871 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1872 0 : if (file == nullptr)
1873 0 : return UNZ_PARAMERROR;
1874 0 : s = reinterpret_cast<unz_s *>(file);
1875 0 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1876 :
1877 0 : if (pfile_in_zip_read_info == nullptr)
1878 0 : return UNZ_PARAMERROR;
1879 :
1880 0 : return static_cast<z_off_t>(pfile_in_zip_read_info->stream.total_out);
1881 : }
1882 :
1883 : /*
1884 : return 1 if the end of file was reached, 0 elsewhere
1885 : */
1886 0 : extern int ZEXPORT cpl_unzeof(unzFile file)
1887 : {
1888 : unz_s *s;
1889 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1890 0 : if (file == nullptr)
1891 0 : return UNZ_PARAMERROR;
1892 0 : s = reinterpret_cast<unz_s *>(file);
1893 0 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1894 :
1895 0 : if (pfile_in_zip_read_info == nullptr)
1896 0 : return UNZ_PARAMERROR;
1897 :
1898 0 : if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1899 0 : return 1;
1900 : else
1901 0 : return 0;
1902 : }
1903 :
1904 : /*
1905 : Read extra field from the current file (opened by unzOpenCurrentFile)
1906 : This is the local-header version of the extra field (sometimes, there is
1907 : more info in the local-header version than in the central-header)
1908 :
1909 : if buf==NULL, it return the size of the local extra field that can be read
1910 :
1911 : if buf!=NULL, len is the size of the buffer, the extra header is copied in
1912 : buf.
1913 : the return value is the number of bytes copied in buf, or (if <0)
1914 : the error code
1915 : */
1916 0 : extern int ZEXPORT cpl_unzGetLocalExtrafield(unzFile file, voidp buf,
1917 : unsigned len)
1918 : {
1919 : unz_s *s;
1920 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1921 : uInt read_now;
1922 : uLong64 size_to_read;
1923 :
1924 0 : if (file == nullptr)
1925 0 : return UNZ_PARAMERROR;
1926 0 : s = reinterpret_cast<unz_s *>(file);
1927 0 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1928 :
1929 0 : if (pfile_in_zip_read_info == nullptr)
1930 0 : return UNZ_PARAMERROR;
1931 :
1932 0 : size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1933 0 : pfile_in_zip_read_info->pos_local_extrafield);
1934 :
1935 0 : if (buf == nullptr)
1936 0 : return static_cast<int>(size_to_read);
1937 :
1938 0 : if (len > size_to_read)
1939 0 : read_now = static_cast<uInt>(size_to_read);
1940 : else
1941 0 : read_now = static_cast<uInt>(len);
1942 :
1943 0 : if (read_now == 0)
1944 0 : return 0;
1945 :
1946 0 : if (ZSEEK(pfile_in_zip_read_info->z_filefunc,
1947 : pfile_in_zip_read_info->filestream,
1948 : pfile_in_zip_read_info->offset_local_extrafield +
1949 : pfile_in_zip_read_info->pos_local_extrafield,
1950 0 : ZLIB_FILEFUNC_SEEK_SET) != 0)
1951 0 : return UNZ_ERRNO;
1952 :
1953 0 : if (ZREAD(pfile_in_zip_read_info->z_filefunc,
1954 0 : pfile_in_zip_read_info->filestream, buf, read_now) != read_now)
1955 0 : return UNZ_ERRNO;
1956 :
1957 0 : return static_cast<int>(read_now);
1958 : }
1959 :
1960 : /*
1961 : Close the file in zip opened with unzipOpenCurrentFile
1962 : Return UNZ_CRCERROR if all the file was read but the CRC is not good
1963 : */
1964 3875 : extern int ZEXPORT cpl_unzCloseCurrentFile(unzFile file)
1965 : {
1966 3875 : int err = UNZ_OK;
1967 :
1968 : unz_s *s;
1969 : file_in_zip_read_info_s *pfile_in_zip_read_info;
1970 3875 : if (file == nullptr)
1971 0 : return UNZ_PARAMERROR;
1972 3875 : s = reinterpret_cast<unz_s *>(file);
1973 3875 : pfile_in_zip_read_info = s->pfile_in_zip_read;
1974 :
1975 3875 : if (pfile_in_zip_read_info == nullptr)
1976 0 : return UNZ_PARAMERROR;
1977 :
1978 3875 : if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1979 0 : (!pfile_in_zip_read_info->raw))
1980 : {
1981 0 : if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1982 0 : err = UNZ_CRCERROR;
1983 : }
1984 :
1985 3875 : TRYFREE(pfile_in_zip_read_info->read_buffer);
1986 3875 : pfile_in_zip_read_info->read_buffer = nullptr;
1987 3875 : if (pfile_in_zip_read_info->stream_initialised)
1988 3817 : inflateEnd(&pfile_in_zip_read_info->stream);
1989 :
1990 3875 : pfile_in_zip_read_info->stream_initialised = 0;
1991 3875 : TRYFREE(pfile_in_zip_read_info);
1992 :
1993 3875 : s->pfile_in_zip_read = nullptr;
1994 :
1995 3875 : return err;
1996 : }
1997 :
1998 : /*
1999 : Get the global comment string of the ZipFile, in the szComment buffer.
2000 : uSizeBuf is the size of the szComment buffer.
2001 : return the number of byte copied or an error code <0
2002 : */
2003 0 : extern int ZEXPORT cpl_unzGetGlobalComment(unzFile file, char *szComment,
2004 : uLong uSizeBuf)
2005 : {
2006 : /* int err=UNZ_OK; */
2007 : unz_s *s;
2008 : uLong uReadThis;
2009 0 : if (file == nullptr)
2010 0 : return UNZ_PARAMERROR;
2011 0 : s = reinterpret_cast<unz_s *>(file);
2012 :
2013 0 : uReadThis = uSizeBuf;
2014 0 : if (uReadThis > s->gi.size_comment)
2015 0 : uReadThis = s->gi.size_comment;
2016 :
2017 0 : if (ZSEEK(s->z_filefunc, s->filestream, s->central_pos + 22,
2018 0 : ZLIB_FILEFUNC_SEEK_SET) != 0)
2019 0 : return UNZ_ERRNO;
2020 :
2021 0 : if (uReadThis > 0)
2022 : {
2023 0 : *szComment = '\0';
2024 0 : if (ZREAD(s->z_filefunc, s->filestream, szComment, uReadThis) !=
2025 : uReadThis)
2026 0 : return UNZ_ERRNO;
2027 : }
2028 :
2029 0 : if ((szComment != nullptr) && (uSizeBuf > s->gi.size_comment))
2030 0 : *(szComment + s->gi.size_comment) = '\0';
2031 0 : return static_cast<int>(uReadThis);
2032 : }
2033 :
2034 : // Additions by RX '2004.
2035 0 : extern uLong64 ZEXPORT cpl_unzGetOffset(unzFile file)
2036 : {
2037 : unz_s *s;
2038 :
2039 0 : if (file == nullptr)
2040 0 : return 0; // UNZ_PARAMERROR;
2041 0 : s = reinterpret_cast<unz_s *>(file);
2042 0 : if (!s->current_file_ok)
2043 0 : return 0;
2044 0 : if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
2045 0 : if (s->num_file == s->gi.number_entry)
2046 0 : return 0;
2047 0 : return s->pos_in_central_dir;
2048 : }
2049 :
2050 0 : extern int ZEXPORT cpl_unzSetOffset(unzFile file, uLong64 pos)
2051 : {
2052 : unz_s *s;
2053 :
2054 0 : if (file == nullptr)
2055 0 : return UNZ_PARAMERROR;
2056 0 : s = reinterpret_cast<unz_s *>(file);
2057 :
2058 0 : s->pos_in_central_dir = pos;
2059 0 : s->num_file = s->gi.number_entry; /* hack */
2060 0 : int err = unzlocal_GetCurrentFileInfoInternal(
2061 : file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
2062 : nullptr, 0, nullptr, 0);
2063 0 : s->current_file_ok = (err == UNZ_OK);
2064 0 : return err;
2065 : }
|