Coverage Report

Created: 2025-11-16 06:25

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