Coverage Report

Created: 2025-06-13 06:18

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