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