Coverage Report

Created: 2026-04-01 06:20

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