LCOV - code coverage report
Current view: top level - port - cpl_minizip_unzip.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 513 908 56.5 %
Date: 2026-03-25 02:32:38 Functions: 22 36 61.1 %

          Line data    Source code
       1             : /* Modified version by Even Rouault. :
       2             :      - Addition of cpl_unzGetCurrentFileZStreamPos
       3             :      - Decoration of symbol names unz* -> cpl_unz*
       4             :      - Undef EXPORT so that we are sure the symbols are not exported
       5             :      - Remove old C style function prototypes
       6             :      - Add support for ZIP64
       7             :      - Recode filename to UTF-8 if GP 11 is unset
       8             :      - Use Info-ZIP Unicode Path Extra Field (0x7075) to get UTF-8 filenames
       9             :      - ZIP64: accept number_disk == 0 in unzlocal_SearchCentralDir64()
      10             : 
      11             :  * Copyright (c) 2008-2014, Even Rouault <even dot rouault at spatialys.com>
      12             : 
      13             :    Original licence available in port/LICENCE_minizip
      14             : */
      15             : 
      16             : /* unzip.c -- IO for uncompress .zip files using zlib
      17             :    Version 1.01e, February 12th, 2005
      18             : 
      19             :    Copyright (C) 1998-2005 Gilles Vollant
      20             : 
      21             :    Read unzip.h for more info
      22             : */
      23             : 
      24             : /* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced
      25             : in terms of compatibility with older software. The following is from the
      26             : original crypt.c. Code woven in by Terry Thorsen 1/2003.
      27             : */
      28             : /*
      29             :   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
      30             : 
      31             :   See the accompanying file LICENSE, version 2000-Apr-09 or later
      32             :   (the contents of which are also included in zip.h) for terms of use.
      33             :   If, for some reason, all these files are missing, the Info-ZIP license
      34             :   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
      35             : */
      36             : /*
      37             :   crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
      38             : 
      39             :   The encryption/decryption parts of this source code (as opposed to the
      40             :   non-echoing password parts) were originally written in Europe.  The
      41             :   whole source package can be freely distributed, including from the USA.
      42             :   (Prior to January 2000, re-export from the US was a violation of US law.)
      43             :  */
      44             : 
      45             : /*
      46             :   This encryption code is a direct transcription of the algorithm from
      47             :   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
      48             :   file (appnote.txt) is distributed with the PKZIP program (even in the
      49             :   version without encryption capabilities).
      50             :  */
      51             : 
      52             : #include "cpl_port.h"
      53             : #include "cpl_minizip_unzip.h"
      54             : 
      55             : #include <cstddef>
      56             : #include <cstdlib>
      57             : #include <cstring>
      58             : #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             : #define UNZ_BUFSIZE (16384)
      77             : #endif
      78             : 
      79             : #ifndef UNZ_MAXFILENAMEINZIP
      80             : #define UNZ_MAXFILENAMEINZIP (256)
      81             : #endif
      82             : 
      83             : #ifndef ALLOC
      84             : #define ALLOC(size) (malloc(size))
      85             : #endif
      86             : #ifndef TRYFREE
      87             : #define TRYFREE(p)                                                             \
      88             :     {                                                                          \
      89             :         if (p)                                                                 \
      90             :             free(p);                                                           \
      91             :     }
      92             : #endif
      93             : 
      94             : #define SIZECENTRALDIRITEM (0x2e)
      95             : #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     2644600 : static int unzlocal_getByte(const zlib_filefunc_def *pzlib_filefunc_def,
     175             :                             voidpf filestream, int *pi)
     176             : {
     177     2644600 :     unsigned char c = 0;
     178             :     const int err =
     179     2644600 :         static_cast<int>(ZREAD(*pzlib_filefunc_def, filestream, &c, 1));
     180     2644600 :     if (err == 1)
     181             :     {
     182     2644570 :         *pi = static_cast<int>(c);
     183     2644570 :         return UNZ_OK;
     184             :     }
     185             :     else
     186             :     {
     187          22 :         if (ZERROR(*pzlib_filefunc_def, filestream))
     188           0 :             return UNZ_ERRNO;
     189             :         else
     190          22 :             return UNZ_EOF;
     191             :     }
     192             : }
     193             : 
     194             : /* ===========================================================================
     195             :    Reads a long in LSB order from the given gz_stream. Sets
     196             : */
     197      592560 : static int unzlocal_getShort(const zlib_filefunc_def *pzlib_filefunc_def,
     198             :                              voidpf filestream, uLong *pX)
     199             : {
     200      592560 :     int i = 0;
     201      592560 :     int err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     202      592560 :     uLong x = static_cast<uLong>(i);
     203             : 
     204      592560 :     if (err == UNZ_OK)
     205      592560 :         err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     206      592560 :     x += static_cast<uLong>(i) << 8;
     207             : 
     208      592560 :     if (err == UNZ_OK)
     209      592560 :         *pX = x;
     210             :     else
     211           0 :         *pX = 0;
     212      592560 :     return err;
     213             : }
     214             : 
     215      361875 : static int unzlocal_getLong(const zlib_filefunc_def *pzlib_filefunc_def,
     216             :                             voidpf filestream, uLong *pX)
     217             : {
     218      361875 :     int i = 0;
     219      361875 :     int err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     220      361875 :     uLong x = static_cast<uLong>(i);
     221             : 
     222      361875 :     if (err == UNZ_OK)
     223      361875 :         err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     224      361875 :     x += static_cast<uLong>(i) << 8;
     225             : 
     226      361875 :     if (err == UNZ_OK)
     227      361875 :         err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     228      361875 :     x += static_cast<uLong>(i) << 16;
     229             : 
     230      361875 :     if (err == UNZ_OK)
     231      361875 :         err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     232      361875 :     x += static_cast<uLong>(i) << 24;
     233             : 
     234      361875 :     if (err == UNZ_OK)
     235      361875 :         *pX = x;
     236             :     else
     237           0 :         *pX = 0;
     238      361875 :     return err;
     239             : }
     240             : 
     241        1496 : static int unzlocal_getLong64(const zlib_filefunc_def *pzlib_filefunc_def,
     242             :                               voidpf filestream, uLong64 *pX)
     243             : {
     244        1496 :     int i = 0;
     245        1496 :     int err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     246        1496 :     uLong64 x = static_cast<uLong64>(i);
     247             : 
     248        1496 :     if (err == UNZ_OK)
     249        1496 :         err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     250        1496 :     x += static_cast<uLong64>(i) << 8;
     251             : 
     252        1496 :     if (err == UNZ_OK)
     253        1496 :         err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     254        1496 :     x += static_cast<uLong64>(i) << 16;
     255             : 
     256        1496 :     if (err == UNZ_OK)
     257        1496 :         err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     258        1496 :     x += static_cast<uLong64>(i) << 24;
     259             : 
     260        1496 :     if (err == UNZ_OK)
     261        1496 :         err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     262        1496 :     x += static_cast<uLong64>(i) << 32;
     263             : 
     264        1496 :     if (err == UNZ_OK)
     265        1496 :         err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     266        1496 :     x += static_cast<uLong64>(i) << 40;
     267             : 
     268        1496 :     if (err == UNZ_OK)
     269        1496 :         err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     270        1496 :     x += static_cast<uLong64>(i) << 48;
     271             : 
     272        1496 :     if (err == UNZ_OK)
     273        1496 :         err = unzlocal_getByte(pzlib_filefunc_def, filestream, &i);
     274        1496 :     x += static_cast<uLong64>(i) << 56;
     275             : 
     276        1496 :     if (err == UNZ_OK)
     277        1496 :         *pX = x;
     278             :     else
     279           0 :         *pX = 0;
     280        1496 :     return err;
     281             : }
     282             : 
     283             : /* My own strcmpi / strcasecmp */
     284           0 : static int strcmpcasenosensitive_internal(const char *fileName1,
     285             :                                           const char *fileName2)
     286             : {
     287             :     for (;;)
     288             :     {
     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             : }
     305             : 
     306             : #ifdef CASESENSITIVITYDEFAULT_NO
     307             : #define CASESENSITIVITYDEFAULTVALUE 2
     308             : #else
     309             : #define CASESENSITIVITYDEFAULTVALUE 1
     310             : #endif
     311             : 
     312             : #ifndef STRCMPCASENOSENTIVEFUNCTION
     313             : #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           0 : extern int ZEXPORT cpl_unzStringFileNameCompare(const char *fileName1,
     326             :                                                 const char *fileName2,
     327             :                                                 int iCaseSensitivity)
     328             : 
     329             : {
     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             : }
     338             : 
     339             : #ifndef BUFREADCOMMENT
     340             : #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        5440 : unzlocal_SearchCentralDir(const zlib_filefunc_def *pzlib_filefunc_def,
     349             :                           voidpf filestream)
     350             : {
     351        5440 :     if (ZSEEK(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
     352           0 :         return 0;
     353             : 
     354             :     unsigned char *buf =
     355        5440 :         static_cast<unsigned char *>(ALLOC(BUFREADCOMMENT + 4));
     356        5440 :     if (buf == nullptr)
     357           0 :         return 0;
     358             : 
     359        5440 :     const uLong64 uSizeFile = ZTELL(*pzlib_filefunc_def, filestream);
     360             : 
     361        5440 :     uLong64 uMaxBack = 0xffff; /* maximum size of global comment */
     362        5440 :     if (uMaxBack > uSizeFile)
     363        2192 :         uMaxBack = uSizeFile;
     364             : 
     365        5440 :     uLong64 uPosFound = 0;
     366        5440 :     uLong64 uBackRead = 4;
     367        5443 :     while (uBackRead < uMaxBack)
     368             :     {
     369        5439 :         if (uBackRead + BUFREADCOMMENT > uMaxBack)
     370         295 :             uBackRead = uMaxBack;
     371             :         else
     372        5144 :             uBackRead += BUFREADCOMMENT;
     373        5439 :         const uLong64 uReadPos = uSizeFile - uBackRead;
     374             : 
     375        5439 :         const uLong uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos))
     376             :                                     ? (BUFREADCOMMENT + 4)
     377             :                                     : static_cast<uLong>(uSizeFile - uReadPos);
     378        5439 :         if (ZSEEK(*pzlib_filefunc_def, filestream, uReadPos,
     379        5439 :                   ZLIB_FILEFUNC_SEEK_SET) != 0)
     380           0 :             break;
     381             : 
     382        5439 :         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      103341 :         for (int i = static_cast<int>(uReadSize) - 3; (i--) > 0;)
     387      103341 :             if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) &&
     388        5439 :                 ((*(buf + i + 2)) == 0x05) && ((*(buf + i + 3)) == 0x06))
     389             :             {
     390        5439 :                 uPosFound = uReadPos + i;
     391        5439 :                 break;
     392             :             }
     393             : 
     394        5439 :         if (uPosFound != 0)
     395        5436 :             break;
     396             :     }
     397        5440 :     TRYFREE(buf);
     398        5440 :     return uPosFound;
     399             : }
     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        5670 : unzlocal_SearchCentralDir64(const zlib_filefunc_def *pzlib_filefunc_def,
     407             :                             voidpf filestream)
     408             : {
     409             :     unsigned char *buf;
     410             :     uLong64 uSizeFile;
     411             :     uLong64 uBackRead;
     412        5670 :     uLong64 uMaxBack = 0xffff; /* maximum size of global comment */
     413        5670 :     uLong64 uPosFound = 0;
     414             :     uLong uL;
     415             : 
     416        5670 :     if (ZSEEK(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
     417           0 :         return 0;
     418             : 
     419        5670 :     uSizeFile = ZTELL(*pzlib_filefunc_def, filestream);
     420             : 
     421        5670 :     if (uMaxBack > uSizeFile)
     422        2192 :         uMaxBack = uSizeFile;
     423             : 
     424        5670 :     buf = static_cast<unsigned char *>(ALLOC(BUFREADCOMMENT + 4));
     425        5670 :     if (buf == nullptr)
     426           0 :         return 0;
     427             : 
     428        5670 :     uBackRead = 4;
     429      258893 :     while (uBackRead < uMaxBack)
     430             :     {
     431             :         uLong uReadSize;
     432             :         uLong64 uReadPos;
     433      253453 :         if (uBackRead + BUFREADCOMMENT > uMaxBack)
     434        5439 :             uBackRead = uMaxBack;
     435             :         else
     436      248014 :             uBackRead += BUFREADCOMMENT;
     437      253453 :         uReadPos = uSizeFile - uBackRead;
     438             : 
     439      253453 :         uReadSize = ((BUFREADCOMMENT + 4) < (uSizeFile - uReadPos))
     440             :                         ? (BUFREADCOMMENT + 4)
     441             :                         : static_cast<uLong>(uSizeFile - uReadPos);
     442      253453 :         if (ZSEEK(*pzlib_filefunc_def, filestream, uReadPos,
     443      253453 :                   ZLIB_FILEFUNC_SEEK_SET) != 0)
     444           0 :             break;
     445             : 
     446      253453 :         if (ZREAD(*pzlib_filefunc_def, filestream, buf, uReadSize) != uReadSize)
     447           0 :             break;
     448             : 
     449   259643000 :         for (int i = static_cast<int>(uReadSize) - 3; (i--) > 0;)
     450   259389000 :             if (((*(buf + i)) == 0x50) && ((*(buf + i + 1)) == 0x4b) &&
     451     1109900 :                 ((*(buf + i + 2)) == 0x06) && ((*(buf + i + 3)) == 0x07))
     452             :             {
     453         230 :                 uPosFound = uReadPos + i;
     454         230 :                 break;
     455             :             }
     456             : 
     457      253453 :         if (uPosFound != 0)
     458         230 :             break;
     459             :     }
     460        5670 :     TRYFREE(buf);
     461        5670 :     if (uPosFound == 0)
     462        5440 :         return 0;
     463             : 
     464             :     /* Zip64 end of central directory locator */
     465         230 :     if (ZSEEK(*pzlib_filefunc_def, filestream, uPosFound,
     466         230 :               ZLIB_FILEFUNC_SEEK_SET) != 0)
     467           0 :         return 0;
     468             : 
     469             :     /* the signature, already checked */
     470         230 :     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         230 :     if (unzlocal_getLong(pzlib_filefunc_def, filestream, &uL) != UNZ_OK)
     476           0 :         return 0;
     477         230 :     if (uL != 0)
     478           0 :         return 0;
     479             : 
     480             :     /* relative offset of the zip64 end of central directory record */
     481             :     uLong64 relativeOffset;
     482         230 :     if (unzlocal_getLong64(pzlib_filefunc_def, filestream, &relativeOffset) !=
     483             :         UNZ_OK)
     484           0 :         return 0;
     485             : 
     486             :     /* total number of disks */
     487         230 :     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         230 :     if (uL != 1 && uL != 0)
     492           0 :         return 0;
     493             : 
     494             :     /* Goto end of central directory record */
     495         230 :     if (ZSEEK(*pzlib_filefunc_def, filestream, relativeOffset,
     496         230 :               ZLIB_FILEFUNC_SEEK_SET) != 0)
     497           0 :         return 0;
     498             : 
     499             :     /* the signature */
     500         230 :     if (unzlocal_getLong(pzlib_filefunc_def, filestream, &uL) != UNZ_OK)
     501           0 :         return 0;
     502             : 
     503         230 :     if (uL != 0x06064b50)
     504           0 :         return 0;
     505             : 
     506         230 :     return relativeOffset;
     507             : }
     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        5670 : extern unzFile ZEXPORT cpl_unzOpen2(const char *path,
     519             :                                     zlib_filefunc_def *pzlib_filefunc_def)
     520             : {
     521             :     unz_s us;
     522             :     unz_s *s;
     523             :     uLong64 central_pos;
     524             :     uLong uL;
     525             : 
     526             :     uLong number_disk;         /* number of the current dist, used for
     527             :                                   spanning ZIP, unsupported, always 0*/
     528             :     uLong number_disk_with_CD; /* number the disk with central dir, used
     529             :                                   for spanning ZIP, unsupported, always 0*/
     530             :     uLong64 number_entry_CD;   /* total number of entries in
     531             :                                 the central dir
     532             :                                 (same than number_entry on nospan) */
     533             : 
     534        5670 :     int err = UNZ_OK;
     535             : 
     536        5670 :     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        5670 :     central_pos = (unz_copyright[0] != ' ');
     541             : 
     542        5670 :     if (pzlib_filefunc_def == nullptr)
     543        5670 :         cpl_fill_fopen_filefunc(&us.z_filefunc);
     544             :     else
     545           0 :         us.z_filefunc = *pzlib_filefunc_def;
     546             : 
     547        5670 :     us.filestream = (*(us.z_filefunc.zopen_file))(
     548             :         us.z_filefunc.opaque, path,
     549             :         ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
     550        5670 :     if (us.filestream == nullptr)
     551           0 :         return nullptr;
     552             : 
     553        5670 :     central_pos += unzlocal_SearchCentralDir64(&us.z_filefunc, us.filestream);
     554        5670 :     if (central_pos)
     555             :     {
     556             :         uLong uS;
     557             :         uLong64 uL64;
     558             : 
     559         230 :         us.isZip64 = 1;
     560             : 
     561         230 :         if (ZSEEK(us.z_filefunc, us.filestream, central_pos,
     562         230 :                   ZLIB_FILEFUNC_SEEK_SET) != 0)
     563           0 :             err = UNZ_ERRNO;
     564             : 
     565             :         /* the signature, already checked */
     566         230 :         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         230 :         if (unzlocal_getLong64(&us.z_filefunc, us.filestream, &uL64) != UNZ_OK)
     571           0 :             err = UNZ_ERRNO;
     572             : 
     573             :         /* version made by */
     574         230 :         if (unzlocal_getShort(&us.z_filefunc, us.filestream, &uS) != UNZ_OK)
     575           0 :             err = UNZ_ERRNO;
     576             : 
     577             :         /* version needed to extract */
     578         230 :         if (unzlocal_getShort(&us.z_filefunc, us.filestream, &uS) != UNZ_OK)
     579           0 :             err = UNZ_ERRNO;
     580             : 
     581             :         /* number of this disk */
     582         230 :         if (unzlocal_getLong(&us.z_filefunc, us.filestream, &number_disk) !=
     583             :             UNZ_OK)
     584           0 :             err = UNZ_ERRNO;
     585             : 
     586             :         /* number of the disk with the start of the central directory */
     587         230 :         if (unzlocal_getLong(&us.z_filefunc, us.filestream,
     588         230 :                              &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         230 :         if (unzlocal_getLong64(&us.z_filefunc, us.filestream,
     593         230 :                                &us.gi.number_entry) != UNZ_OK)
     594           0 :             err = UNZ_ERRNO;
     595             : 
     596             :         /* total number of entries in the central directory */
     597         230 :         if (unzlocal_getLong64(&us.z_filefunc, us.filestream,
     598         230 :                                &number_entry_CD) != UNZ_OK)
     599           0 :             err = UNZ_ERRNO;
     600             : 
     601         230 :         if ((number_entry_CD != us.gi.number_entry) ||
     602         230 :             (number_disk_with_CD != 0) || (number_disk != 0))
     603           0 :             err = UNZ_BADZIPFILE;
     604             : 
     605             :         /* size of the central directory */
     606         230 :         if (unzlocal_getLong64(&us.z_filefunc, us.filestream,
     607         230 :                                &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         230 :         if (unzlocal_getLong64(&us.z_filefunc, us.filestream,
     613         230 :                                &us.offset_central_dir) != UNZ_OK)
     614           0 :             err = UNZ_ERRNO;
     615             : 
     616         230 :         us.gi.size_comment = 0;
     617             :     }
     618             :     else
     619             :     {
     620        5440 :         central_pos = unzlocal_SearchCentralDir(&us.z_filefunc, us.filestream);
     621        5440 :         if (central_pos == 0)
     622           4 :             err = UNZ_ERRNO;
     623             : 
     624        5440 :         us.isZip64 = 0;
     625             : 
     626        5440 :         if (ZSEEK(us.z_filefunc, us.filestream, central_pos,
     627        5440 :                   ZLIB_FILEFUNC_SEEK_SET) != 0)
     628           0 :             err = UNZ_ERRNO;
     629             : 
     630             :         /* the signature, already checked */
     631        5440 :         if (unzlocal_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
     632           0 :             err = UNZ_ERRNO;
     633             : 
     634             :         /* number of this disk */
     635        5440 :         if (unzlocal_getShort(&us.z_filefunc, us.filestream, &number_disk) !=
     636             :             UNZ_OK)
     637           0 :             err = UNZ_ERRNO;
     638             : 
     639             :         /* number of the disk with the start of the central directory */
     640        5440 :         if (unzlocal_getShort(&us.z_filefunc, us.filestream,
     641        5440 :                               &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        5440 :         if (unzlocal_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
     646           0 :             err = UNZ_ERRNO;
     647        5440 :         us.gi.number_entry = uL;
     648             : 
     649             :         /* total number of entries in the central dir */
     650        5440 :         if (unzlocal_getShort(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
     651           0 :             err = UNZ_ERRNO;
     652        5440 :         number_entry_CD = uL;
     653             : 
     654        5440 :         if ((number_entry_CD != us.gi.number_entry) ||
     655        5440 :             (number_disk_with_CD != 0) || (number_disk != 0))
     656           0 :             err = UNZ_BADZIPFILE;
     657             : 
     658             :         /* size of the central directory */
     659        5440 :         if (unzlocal_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
     660           0 :             err = UNZ_ERRNO;
     661        5440 :         us.size_central_dir = uL;
     662             : 
     663             :         /* offset of start of central directory with respect to the
     664             :             starting disk number */
     665        5440 :         if (unzlocal_getLong(&us.z_filefunc, us.filestream, &uL) != UNZ_OK)
     666           0 :             err = UNZ_ERRNO;
     667        5440 :         us.offset_central_dir = uL;
     668             : 
     669             :         /* zipfile comment length */
     670        5440 :         if (unzlocal_getShort(&us.z_filefunc, us.filestream,
     671        5440 :                               &us.gi.size_comment) != UNZ_OK)
     672           0 :             err = UNZ_ERRNO;
     673             :     }
     674             : 
     675       11340 :     if (us.offset_central_dir >
     676        5670 :         std::numeric_limits<uint64_t>::max() - us.size_central_dir)
     677           0 :         err = UNZ_BADZIPFILE;
     678        5670 :     else if ((central_pos < us.offset_central_dir + us.size_central_dir) &&
     679             :              (err == UNZ_OK))
     680           0 :         err = UNZ_BADZIPFILE;
     681             : 
     682        5670 :     if (err != UNZ_OK)
     683             :     {
     684           4 :         ZCLOSE(us.z_filefunc, us.filestream);
     685           4 :         return nullptr;
     686             :     }
     687             : 
     688        5666 :     us.byte_before_the_zipfile =
     689        5666 :         central_pos - (us.offset_central_dir + us.size_central_dir);
     690        5666 :     us.central_pos = central_pos;
     691        5666 :     us.pfile_in_zip_read = nullptr;
     692        5666 :     us.encrypted = 0;
     693        5666 :     us.num_file = 0;
     694        5666 :     us.pos_in_central_dir = 0;
     695        5666 :     us.current_file_ok = 0;
     696             : 
     697        5666 :     s = static_cast<unz_s *>(ALLOC(sizeof(unz_s)));
     698        5666 :     if (!s)
     699             :     {
     700           0 :         ZCLOSE(us.z_filefunc, us.filestream);
     701           0 :         return nullptr;
     702             :     }
     703        5666 :     *s = us;
     704        5666 :     cpl_unzGoToFirstFile(reinterpret_cast<unzFile>(s));
     705        5666 :     return reinterpret_cast<unzFile>(s);
     706             : }
     707             : 
     708        5670 : extern unzFile ZEXPORT cpl_unzOpen(const char *path)
     709             : {
     710        5670 :     return cpl_unzOpen2(path, nullptr);
     711             : }
     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        5666 : extern int ZEXPORT cpl_unzClose(unzFile file)
     719             : {
     720             :     unz_s *s;
     721        5666 :     if (file == nullptr)
     722           0 :         return UNZ_PARAMERROR;
     723        5666 :     s = reinterpret_cast<unz_s *>(file);
     724             : 
     725        5666 :     if (s->pfile_in_zip_read != nullptr)
     726           0 :         cpl_unzCloseCurrentFile(file);
     727             : 
     728        5666 :     ZCLOSE(s->z_filefunc, s->filestream);
     729        5666 :     TRYFREE(s);
     730        5666 :     return UNZ_OK;
     731             : }
     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           0 : extern int ZEXPORT cpl_unzGetGlobalInfo(unzFile file,
     738             :                                         unz_global_info *pglobal_info)
     739             : {
     740             :     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             : }
     747             : 
     748             : /*
     749             :    Translate date/time from Dos format to tm_unz (readable more easily).
     750             : */
     751       43154 : static void unzlocal_DosDateToTmuDate(uLong64 ulDosDate, tm_unz *ptm)
     752             : {
     753             :     uLong64 uDate;
     754       43154 :     uDate = static_cast<uLong64>(ulDosDate >> 16);
     755       43154 :     ptm->tm_mday = static_cast<uInt>(uDate & 0x1f);
     756       43154 :     ptm->tm_mon = static_cast<uInt>(((uDate) & 0x1E0) / 0x20);
     757       43154 :     if (ptm->tm_mon)
     758       43149 :         ptm->tm_mon--;
     759       43154 :     ptm->tm_year = static_cast<uInt>(((uDate & 0x0FE00) / 0x0200) + 1980);
     760             : 
     761       43154 :     ptm->tm_hour = static_cast<uInt>((ulDosDate & 0xF800) / 0x800);
     762       43154 :     ptm->tm_min = static_cast<uInt>((ulDosDate & 0x7E0) / 0x20);
     763       43154 :     ptm->tm_sec = static_cast<uInt>(2 * (ulDosDate & 0x1f));
     764       43154 : }
     765             : 
     766             : /*
     767             :   Get Info about the current file in the zipfile, with internal only info
     768             : */
     769       43154 : 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             : {
     776             :     unz_s *s;
     777             :     unz_file_info file_info;
     778             :     unz_file_info_internal file_info_internal;
     779       43154 :     int err = UNZ_OK;
     780             :     uLong uMagic;
     781       43154 :     long lSeek = 0;
     782             :     uLong uL;
     783       43154 :     bool bHasUTF8Filename = false;
     784             : 
     785       43154 :     if (file == nullptr)
     786           0 :         return UNZ_PARAMERROR;
     787       43154 :     s = reinterpret_cast<unz_s *>(file);
     788       43154 :     if (ZSEEK(s->z_filefunc, s->filestream,
     789             :               s->pos_in_central_dir + s->byte_before_the_zipfile,
     790       43154 :               ZLIB_FILEFUNC_SEEK_SET) != 0)
     791           0 :         err = UNZ_ERRNO;
     792             : 
     793             :     /* we check the magic */
     794       43154 :     if (err == UNZ_OK)
     795             :     {
     796       43154 :         if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK)
     797           0 :             err = UNZ_ERRNO;
     798       43154 :         else if (uMagic != 0x02014b50)
     799           0 :             err = UNZ_BADZIPFILE;
     800             :     }
     801             : 
     802       43154 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.version) !=
     803             :         UNZ_OK)
     804           0 :         err = UNZ_ERRNO;
     805             : 
     806       43154 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream,
     807       43154 :                           &file_info.version_needed) != UNZ_OK)
     808           0 :         err = UNZ_ERRNO;
     809             : 
     810       43154 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream, &file_info.flag) !=
     811             :         UNZ_OK)
     812           0 :         err = UNZ_ERRNO;
     813             : 
     814       43154 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream,
     815       43154 :                           &file_info.compression_method) != UNZ_OK)
     816           0 :         err = UNZ_ERRNO;
     817             : 
     818       43154 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info.dosDate) !=
     819             :         UNZ_OK)
     820           0 :         err = UNZ_ERRNO;
     821             : 
     822       43154 :     unzlocal_DosDateToTmuDate(file_info.dosDate, &file_info.tmu_date);
     823             : 
     824       43154 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &file_info.crc) !=
     825             :         UNZ_OK)
     826           0 :         err = UNZ_ERRNO;
     827             : 
     828       43154 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
     829           0 :         err = UNZ_ERRNO;
     830       43154 :     file_info.compressed_size = uL;
     831             : 
     832       43154 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
     833           0 :         err = UNZ_ERRNO;
     834       43154 :     file_info.uncompressed_size = uL;
     835             : 
     836       43154 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream,
     837       43154 :                           &file_info.size_filename) != UNZ_OK)
     838           0 :         err = UNZ_ERRNO;
     839             : 
     840       43154 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream,
     841       43154 :                           &file_info.size_file_extra) != UNZ_OK)
     842           0 :         err = UNZ_ERRNO;
     843             : 
     844       43154 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream,
     845       43154 :                           &file_info.size_file_comment) != UNZ_OK)
     846           0 :         err = UNZ_ERRNO;
     847             : 
     848       43154 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream,
     849       43154 :                           &file_info.disk_num_start) != UNZ_OK)
     850           0 :         err = UNZ_ERRNO;
     851             : 
     852       43154 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream,
     853       43154 :                           &file_info.internal_fa) != UNZ_OK)
     854           0 :         err = UNZ_ERRNO;
     855             : 
     856       43154 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream,
     857       43154 :                          &file_info.external_fa) != UNZ_OK)
     858           0 :         err = UNZ_ERRNO;
     859             : 
     860       43154 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uL) != UNZ_OK)
     861           0 :         err = UNZ_ERRNO;
     862       43154 :     file_info_internal.offset_curfile = uL;
     863             : 
     864       43154 :     lSeek += file_info.size_filename;
     865       43154 :     if ((err == UNZ_OK) && (szFileName != nullptr))
     866             :     {
     867       16632 :         uLong uSizeRead = 0;
     868       16632 :         if (file_info.size_filename < fileNameBufferSize)
     869             :         {
     870       16632 :             *(szFileName + file_info.size_filename) = '\0';
     871       16632 :             uSizeRead = file_info.size_filename;
     872             :         }
     873             :         else
     874           0 :             uSizeRead = fileNameBufferSize;
     875             : 
     876       16632 :         if ((file_info.size_filename > 0) && (fileNameBufferSize > 0))
     877             :         {
     878       16632 :             if (ZREAD(s->z_filefunc, s->filestream, szFileName, uSizeRead) !=
     879             :                 uSizeRead)
     880           0 :                 err = UNZ_ERRNO;
     881             :         }
     882       16632 :         lSeek -= uSizeRead;
     883             :     }
     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       43154 :     if ((err == UNZ_OK) && (file_info.size_file_extra != 0))
     911             :     {
     912       33940 :         if (lSeek != 0)
     913             :         {
     914       20978 :             if (ZSEEK(s->z_filefunc, s->filestream, lSeek,
     915       20978 :                       ZLIB_FILEFUNC_SEEK_CUR) == 0)
     916             :             {
     917       20978 :                 lSeek = 0;
     918       20978 :                 CPL_IGNORE_RET_VAL(lSeek);
     919             :             }
     920             :             else
     921           0 :                 err = UNZ_ERRNO;
     922             :         }
     923             : 
     924       33940 :         uLong acc = 0;
     925       33940 :         file_info.file_extra_abs_offset = ZTELL(s->z_filefunc, s->filestream);
     926      101267 :         while (acc < file_info.size_file_extra)
     927             :         {
     928             :             uLong headerId;
     929       67327 :             if (unzlocal_getShort(&s->z_filefunc, s->filestream, &headerId) !=
     930             :                 UNZ_OK)
     931           0 :                 err = UNZ_ERRNO;
     932             : 
     933             :             uLong dataSize;
     934       67327 :             if (unzlocal_getShort(&s->z_filefunc, s->filestream, &dataSize) !=
     935             :                 UNZ_OK)
     936           0 :                 err = UNZ_ERRNO;
     937             : 
     938             :             /* ZIP64 extra fields */
     939       67327 :             if (headerId == 0x0001)
     940             :             {
     941             :                 uLong64 u64;
     942          88 :                 if (file_info.uncompressed_size == 0xFFFFFFFF)
     943             :                 {
     944          43 :                     if (unzlocal_getLong64(&s->z_filefunc, s->filestream,
     945          43 :                                            &u64) != UNZ_OK)
     946           0 :                         err = UNZ_ERRNO;
     947          43 :                     file_info.uncompressed_size = u64;
     948             :                 }
     949             : 
     950          88 :                 if (file_info.compressed_size == 0xFFFFFFFF)
     951             :                 {
     952          26 :                     if (unzlocal_getLong64(&s->z_filefunc, s->filestream,
     953          26 :                                            &u64) != UNZ_OK)
     954           0 :                         err = UNZ_ERRNO;
     955          26 :                     file_info.compressed_size = u64;
     956             :                 }
     957             : 
     958             :                 /* Relative Header offset */
     959          88 :                 if (file_info_internal.offset_curfile == 0xFFFFFFFF)
     960             :                 {
     961          47 :                     if (unzlocal_getLong64(&s->z_filefunc, s->filestream,
     962          47 :                                            &u64) != UNZ_OK)
     963           0 :                         err = UNZ_ERRNO;
     964          47 :                     file_info_internal.offset_curfile = u64;
     965             :                 }
     966             : 
     967             :                 /* Disk Start Number */
     968          88 :                 if (file_info.disk_num_start == 0xFFFF)
     969             :                 {
     970             :                     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             :                 }
     976             :             }
     977             :             /* Info-ZIP Unicode Path Extra Field (0x7075) */
     978       67239 :             else if (headerId == 0x7075 && dataSize > 5 &&
     979          17 :                      file_info.size_filename <= fileNameBufferSize &&
     980             :                      szFileName != nullptr)
     981             :             {
     982           7 :                 int version = 0;
     983           7 :                 if (unzlocal_getByte(&s->z_filefunc, s->filestream, &version) !=
     984             :                     UNZ_OK)
     985           0 :                     err = UNZ_ERRNO;
     986           7 :                 if (version != 1)
     987             :                 {
     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             :                 }
     993             :                 else
     994             :                 {
     995             :                     uLong nameCRC32;
     996           7 :                     if (unzlocal_getLong(&s->z_filefunc, s->filestream,
     997           7 :                                          &nameCRC32) != UNZ_OK)
     998           0 :                         err = UNZ_ERRNO;
     999             : 
    1000             :                     /* Check expected CRC for filename */
    1001           7 :                     if (nameCRC32 ==
    1002           7 :                         crc32(0, reinterpret_cast<const Bytef *>(szFileName),
    1003           7 :                               static_cast<uInt>(file_info.size_filename)))
    1004             :                     {
    1005           7 :                         const uLong utf8Size = dataSize - 1 - 4;
    1006           7 :                         uLong uSizeRead = 0;
    1007             : 
    1008           7 :                         bHasUTF8Filename = true;
    1009             : 
    1010           7 :                         if (utf8Size < fileNameBufferSize)
    1011             :                         {
    1012           7 :                             *(szFileName + utf8Size) = '\0';
    1013           7 :                             uSizeRead = utf8Size;
    1014             :                         }
    1015             :                         else
    1016           0 :                             uSizeRead = fileNameBufferSize;
    1017             : 
    1018           7 :                         if (ZREAD(s->z_filefunc, s->filestream, szFileName,
    1019           7 :                                   uSizeRead) != uSizeRead)
    1020           0 :                             err = UNZ_ERRNO;
    1021           7 :                         else if (utf8Size > fileNameBufferSize)
    1022             :                         {
    1023           0 :                             if (ZSEEK(s->z_filefunc, s->filestream,
    1024             :                                       utf8Size - fileNameBufferSize,
    1025           0 :                                       ZLIB_FILEFUNC_SEEK_CUR) != 0)
    1026           0 :                                 err = UNZ_ERRNO;
    1027             :                         }
    1028             :                     }
    1029             :                     else
    1030             :                     {
    1031             :                         /* ignore unicode name if CRC mismatch */
    1032           0 :                         if (ZSEEK(s->z_filefunc, s->filestream,
    1033             :                                   dataSize - 1 - 4,
    1034           0 :                                   ZLIB_FILEFUNC_SEEK_CUR) != 0)
    1035           0 :                             err = UNZ_ERRNO;
    1036             :                     }
    1037           7 :                 }
    1038             :             }
    1039             :             else
    1040             :             {
    1041       67232 :                 if (ZSEEK(s->z_filefunc, s->filestream, dataSize,
    1042       67232 :                           ZLIB_FILEFUNC_SEEK_CUR) != 0)
    1043           0 :                     err = UNZ_ERRNO;
    1044             :             }
    1045             : 
    1046       67327 :             acc += 2 + 2 + dataSize;
    1047             :         }
    1048             :     }
    1049             : 
    1050       43154 :     if (!bHasUTF8Filename && szFileName != nullptr &&
    1051       16625 :         (file_info.flag & (1 << 11)) == 0 &&
    1052       16013 :         file_info.size_filename < fileNameBufferSize)
    1053             :     {
    1054       16013 :         const char *pszSrcEncoding = CPLGetConfigOption("CPL_ZIP_ENCODING",
    1055             : #if defined(_WIN32) && !defined(HAVE_ICONV)
    1056             :                                                         "CP_OEMCP"
    1057             : #else
    1058             :                                                         "CP437"
    1059             : #endif
    1060             :         );
    1061       16013 :         char *pszRecoded = CPLRecode(szFileName, pszSrcEncoding, CPL_ENC_UTF8);
    1062       16013 :         if (pszRecoded != nullptr && strlen(pszRecoded) < fileNameBufferSize)
    1063             :         {
    1064       16013 :             strcpy(szFileName, pszRecoded);
    1065             :         }
    1066       16013 :         CPLFree(pszRecoded);
    1067             :     }
    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       43154 :     if ((err == UNZ_OK) && (pfile_info != nullptr))
    1099       43154 :         *pfile_info = file_info;
    1100             : 
    1101       43154 :     if ((err == UNZ_OK) && (pfile_info_internal != nullptr))
    1102       22298 :         *pfile_info_internal = file_info_internal;
    1103             : 
    1104       43154 :     return err;
    1105             : }
    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       20856 : 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             : {
    1117       20856 :     return unzlocal_GetCurrentFileInfoInternal(
    1118             :         file, pfile_info, nullptr, szFileName, fileNameBufferSize, extraField,
    1119       20856 :         extraFieldBufferSize, szComment, commentBufferSize);
    1120             : }
    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       12247 : extern int ZEXPORT cpl_unzGoToFirstFile(unzFile file)
    1127             : {
    1128       12247 :     int err = UNZ_OK;
    1129             :     unz_s *s;
    1130       12247 :     if (file == nullptr)
    1131           0 :         return UNZ_PARAMERROR;
    1132       12247 :     s = reinterpret_cast<unz_s *>(file);
    1133       12247 :     s->pos_in_central_dir = s->offset_central_dir;
    1134       12247 :     s->num_file = 0;
    1135       12247 :     err = unzlocal_GetCurrentFileInfoInternal(
    1136             :         file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
    1137             :         nullptr, 0, nullptr, 0);
    1138       12247 :     s->current_file_ok = (err == UNZ_OK);
    1139       12247 :     return err;
    1140             : }
    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        6490 : extern int ZEXPORT cpl_unzGoToNextFile(unzFile file)
    1148             : {
    1149             :     unz_s *s;
    1150             : 
    1151        6490 :     if (file == nullptr)
    1152           0 :         return UNZ_PARAMERROR;
    1153        6490 :     s = reinterpret_cast<unz_s *>(file);
    1154        6490 :     if (!s->current_file_ok)
    1155           0 :         return UNZ_END_OF_LIST_OF_FILE;
    1156        6490 :     if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
    1157        6490 :         if (s->num_file + 1 == s->gi.number_entry)
    1158         543 :             return UNZ_END_OF_LIST_OF_FILE;
    1159             : 
    1160        5947 :     s->pos_in_central_dir +=
    1161        5947 :         SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
    1162        5947 :         s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment;
    1163        5947 :     s->num_file++;
    1164        5947 :     int err = unzlocal_GetCurrentFileInfoInternal(
    1165             :         file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
    1166             :         nullptr, 0, nullptr, 0);
    1167        5947 :     s->current_file_ok = (err == UNZ_OK);
    1168        5947 :     return err;
    1169             : }
    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           0 : extern int ZEXPORT cpl_unzLocateFile(unzFile file, const char *szFileName,
    1180             :                                      int iCaseSensitivity)
    1181             : {
    1182             :     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             :     unz_file_info cur_file_infoSaved;
    1188             :     unz_file_info_internal cur_file_info_internalSaved;
    1189             :     uLong64 num_fileSaved;
    1190             :     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             :     {
    1212             :         char szCurrentFileName[UNZ_MAXFILENAMEINZIP + 1];
    1213           0 :         err = cpl_unzGetCurrentFileInfo(file, nullptr, szCurrentFileName,
    1214             :                                         sizeof(szCurrentFileName) - 1, nullptr,
    1215             :                                         0, nullptr, 0);
    1216           0 :         if (err == UNZ_OK)
    1217             :         {
    1218           0 :             if (cpl_unzStringFileNameCompare(szCurrentFileName, szFileName,
    1219           0 :                                              iCaseSensitivity) == 0)
    1220           0 :                 return UNZ_OK;
    1221           0 :             err = cpl_unzGoToNextFile(file);
    1222             :         }
    1223             :     }
    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             : }
    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       15823 : extern int ZEXPORT cpl_unzGetFilePos(unzFile file, unz_file_pos *file_pos)
    1255             : {
    1256             :     unz_s *s;
    1257             : 
    1258       15823 :     if (file == nullptr || file_pos == nullptr)
    1259           0 :         return UNZ_PARAMERROR;
    1260       15823 :     s = reinterpret_cast<unz_s *>(file);
    1261       15823 :     if (!s->current_file_ok)
    1262           0 :         return UNZ_END_OF_LIST_OF_FILE;
    1263             : 
    1264       15823 :     file_pos->pos_in_zip_directory = s->pos_in_central_dir;
    1265       15823 :     file_pos->num_of_file = s->num_file;
    1266             : 
    1267       15823 :     return UNZ_OK;
    1268             : }
    1269             : 
    1270        4104 : extern int ZEXPORT cpl_unzGoToFilePos(unzFile file, unz_file_pos *file_pos)
    1271             : {
    1272             :     unz_s *s;
    1273             : 
    1274        4104 :     if (file == nullptr || file_pos == nullptr)
    1275           0 :         return UNZ_PARAMERROR;
    1276        4104 :     s = reinterpret_cast<unz_s *>(file);
    1277             : 
    1278             :     /* jump to the right spot */
    1279        4104 :     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
    1280        4104 :     s->num_file = file_pos->num_of_file;
    1281             : 
    1282             :     /* set the current file */
    1283        4104 :     int err = unzlocal_GetCurrentFileInfoInternal(
    1284             :         file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
    1285             :         nullptr, 0, nullptr, 0);
    1286             :     /* return results */
    1287        4104 :     s->current_file_ok = (err == UNZ_OK);
    1288        4104 :     return err;
    1289             : }
    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        4224 : unzlocal_CheckCurrentFileCoherencyHeader(unz_s *s, uInt *piSizeVar,
    1305             :                                          uLong64 *poffset_local_extrafield,
    1306             :                                          uInt *psize_local_extrafield)
    1307             : {
    1308             :     uLong uMagic, uData, uFlags;
    1309             :     uLong size_filename;
    1310             :     uLong size_extra_field;
    1311        4224 :     int err = UNZ_OK;
    1312             : 
    1313        4224 :     *piSizeVar = 0;
    1314        4224 :     *poffset_local_extrafield = 0;
    1315        4224 :     *psize_local_extrafield = 0;
    1316             : 
    1317        4224 :     if (ZSEEK(s->z_filefunc, s->filestream,
    1318             :               s->cur_file_info_internal.offset_curfile +
    1319             :                   s->byte_before_the_zipfile,
    1320        4224 :               ZLIB_FILEFUNC_SEEK_SET) != 0)
    1321           0 :         return UNZ_ERRNO;
    1322             : 
    1323             :     // if (err == UNZ_OK)
    1324             :     {
    1325        4224 :         if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK)
    1326           0 :             err = UNZ_ERRNO;
    1327        4224 :         else if (uMagic != 0x04034b50)
    1328           0 :             err = UNZ_BADZIPFILE;
    1329             :     }
    1330             : 
    1331        4224 :     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        4224 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uFlags) != UNZ_OK)
    1338           0 :         err = UNZ_ERRNO;
    1339             : 
    1340        4224 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
    1341           0 :         err = UNZ_ERRNO;
    1342        4224 :     else if ((err == UNZ_OK) && (uData != s->cur_file_info.compression_method))
    1343           0 :         err = UNZ_BADZIPFILE;
    1344             : 
    1345        4224 :     if ((err == UNZ_OK) && (s->cur_file_info.compression_method != 0) &&
    1346        4149 :         (s->cur_file_info.compression_method != Z_DEFLATED))
    1347             :     {
    1348             : #ifdef ENABLE_DEFLATE64
    1349           1 :         if (s->cur_file_info.compression_method == 9)
    1350             :         {
    1351             :             // ok
    1352             :         }
    1353             :         else
    1354             : #endif
    1355             :         {
    1356           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    1357             :                      "A file in the ZIP archive uses a unsupported "
    1358             :                      "compression method (%lu)",
    1359             :                      s->cur_file_info.compression_method);
    1360           0 :             err = UNZ_BADZIPFILE;
    1361             :         }
    1362             :     }
    1363             : 
    1364        4224 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
    1365             :         UNZ_OK) /* date/time */
    1366           0 :         err = UNZ_ERRNO;
    1367             : 
    1368        4224 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
    1369             :         UNZ_OK) /* crc */
    1370           0 :         err = UNZ_ERRNO;
    1371        4224 :     else if ((err == UNZ_OK) && (uData != s->cur_file_info.crc) &&
    1372         163 :              ((uFlags & 8) == 0))
    1373           0 :         err = UNZ_BADZIPFILE;
    1374             : 
    1375        4224 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
    1376             :         UNZ_OK) /* size compr */
    1377           0 :         err = UNZ_ERRNO;
    1378        4224 :     else if (uData != 0xFFFFFFFF && (err == UNZ_OK) &&
    1379        4219 :              (uData != s->cur_file_info.compressed_size) && ((uFlags & 8) == 0))
    1380           0 :         err = UNZ_BADZIPFILE;
    1381             : 
    1382        4224 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
    1383             :         UNZ_OK) /* size uncompr */
    1384           0 :         err = UNZ_ERRNO;
    1385        4224 :     else if (uData != 0xFFFFFFFF && (err == UNZ_OK) &&
    1386        4219 :              (uData != s->cur_file_info.uncompressed_size) &&
    1387         163 :              ((uFlags & 8) == 0))
    1388           0 :         err = UNZ_BADZIPFILE;
    1389             : 
    1390        4224 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_filename) !=
    1391             :         UNZ_OK)
    1392           0 :         err = UNZ_ERRNO;
    1393        4224 :     else if ((err == UNZ_OK) &&
    1394        4224 :              (size_filename != s->cur_file_info.size_filename))
    1395           0 :         err = UNZ_BADZIPFILE;
    1396             : 
    1397        4224 :     *piSizeVar += static_cast<uInt>(size_filename);
    1398             : 
    1399        4224 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_extra_field) !=
    1400             :         UNZ_OK)
    1401           0 :         err = UNZ_ERRNO;
    1402        4224 :     *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile +
    1403        4224 :                                 SIZEZIPLOCALHEADER + size_filename;
    1404        4224 :     *psize_local_extrafield = static_cast<uInt>(size_extra_field);
    1405             : 
    1406        4224 :     *piSizeVar += static_cast<uInt>(size_extra_field);
    1407             : 
    1408        4224 :     return err;
    1409             : }
    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        4224 : extern int ZEXPORT cpl_unzOpenCurrentFile3(unzFile file, int *method,
    1416             :                                            int *level, int raw,
    1417             :                                            const char *password)
    1418             : {
    1419        4224 :     int err = UNZ_OK;
    1420             :     uInt iSizeVar;
    1421             :     unz_s *s;
    1422             :     file_in_zip_read_info_s *pfile_in_zip_read_info;
    1423             :     uLong64 offset_local_extrafield; /* offset of the local extra field */
    1424             :     uInt size_local_extrafield;      /* size of the local extra field */
    1425             : #ifndef NOUNCRYPT
    1426             :     char source[12];
    1427             : #else
    1428        4224 :     if (password != nullptr)
    1429           0 :         return UNZ_PARAMERROR;
    1430             : #endif
    1431             : 
    1432        4224 :     if (file == nullptr)
    1433           0 :         return UNZ_PARAMERROR;
    1434        4224 :     s = reinterpret_cast<unz_s *>(file);
    1435        4224 :     if (!s->current_file_ok)
    1436           0 :         return UNZ_PARAMERROR;
    1437             : 
    1438        4224 :     if (s->pfile_in_zip_read != nullptr)
    1439           0 :         cpl_unzCloseCurrentFile(file);
    1440             : 
    1441        4224 :     if (unzlocal_CheckCurrentFileCoherencyHeader(
    1442        4224 :             s, &iSizeVar, &offset_local_extrafield, &size_local_extrafield) !=
    1443             :         UNZ_OK)
    1444           0 :         return UNZ_BADZIPFILE;
    1445             : 
    1446             :     pfile_in_zip_read_info = static_cast<file_in_zip_read_info_s *>(
    1447        4224 :         ALLOC(sizeof(file_in_zip_read_info_s)));
    1448        4224 :     if (pfile_in_zip_read_info == nullptr)
    1449           0 :         return UNZ_INTERNALERROR;
    1450             : 
    1451        4224 :     pfile_in_zip_read_info->read_buffer =
    1452        4224 :         static_cast<char *>(ALLOC(UNZ_BUFSIZE));
    1453        4224 :     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
    1454        4224 :     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
    1455        4224 :     pfile_in_zip_read_info->pos_local_extrafield = 0;
    1456        4224 :     pfile_in_zip_read_info->raw = raw;
    1457             : 
    1458        4224 :     if (pfile_in_zip_read_info->read_buffer == nullptr)
    1459             :     {
    1460           0 :         TRYFREE(pfile_in_zip_read_info);
    1461           0 :         return UNZ_INTERNALERROR;
    1462             :     }
    1463             : 
    1464        4224 :     pfile_in_zip_read_info->stream_initialised = 0;
    1465             : 
    1466        4224 :     if (method != nullptr)
    1467           0 :         *method = static_cast<int>(s->cur_file_info.compression_method);
    1468             : 
    1469        4224 :     if (level != nullptr)
    1470             :     {
    1471           0 :         *level = 6;
    1472           0 :         switch (s->cur_file_info.flag & 0x06)
    1473             :         {
    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             :         }
    1484             :     }
    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        4224 :     pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc;
    1491        4224 :     pfile_in_zip_read_info->crc32 = 0;
    1492        4224 :     pfile_in_zip_read_info->compression_method =
    1493        4224 :         s->cur_file_info.compression_method;
    1494        4224 :     pfile_in_zip_read_info->filestream = s->filestream;
    1495        4224 :     pfile_in_zip_read_info->z_filefunc = s->z_filefunc;
    1496        4224 :     pfile_in_zip_read_info->byte_before_the_zipfile =
    1497        4224 :         s->byte_before_the_zipfile;
    1498             : 
    1499        4224 :     pfile_in_zip_read_info->stream.total_out = 0;
    1500             : 
    1501        4224 :     if ((s->cur_file_info.compression_method == Z_DEFLATED) && (!raw))
    1502             :     {
    1503        4148 :         pfile_in_zip_read_info->stream.zalloc = nullptr;
    1504        4148 :         pfile_in_zip_read_info->stream.zfree = nullptr;
    1505        4148 :         pfile_in_zip_read_info->stream.opaque = nullptr;
    1506        4148 :         pfile_in_zip_read_info->stream.next_in = nullptr;
    1507        4148 :         pfile_in_zip_read_info->stream.avail_in = 0;
    1508             : 
    1509        4148 :         err = inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
    1510        4148 :         if (err == Z_OK)
    1511        4148 :             pfile_in_zip_read_info->stream_initialised = 1;
    1512             :         else
    1513             :         {
    1514           0 :             TRYFREE(pfile_in_zip_read_info->read_buffer);
    1515           0 :             TRYFREE(pfile_in_zip_read_info);
    1516           0 :             return err;
    1517             :         }
    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             :     }
    1526        4224 :     pfile_in_zip_read_info->rest_read_compressed =
    1527        4224 :         s->cur_file_info.compressed_size;
    1528        4224 :     pfile_in_zip_read_info->rest_read_uncompressed =
    1529        4224 :         s->cur_file_info.uncompressed_size;
    1530             : 
    1531        4224 :     pfile_in_zip_read_info->pos_in_zipfile =
    1532        4224 :         s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
    1533        4224 :         iSizeVar;
    1534             : 
    1535        4224 :     pfile_in_zip_read_info->stream.avail_in = 0;
    1536             : 
    1537        4224 :     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        4224 :     return UNZ_OK;
    1561             : }
    1562             : 
    1563        4224 : extern int ZEXPORT cpl_unzOpenCurrentFile(unzFile file)
    1564             : {
    1565        4224 :     return cpl_unzOpenCurrentFile3(file, nullptr, nullptr, 0, nullptr);
    1566             : }
    1567             : 
    1568           0 : extern int ZEXPORT cpl_unzOpenCurrentFilePassword(unzFile file,
    1569             :                                                   const char *password)
    1570             : {
    1571           0 :     return cpl_unzOpenCurrentFile3(file, nullptr, nullptr, 0, password);
    1572             : }
    1573             : 
    1574           0 : extern int ZEXPORT cpl_unzOpenCurrentFile2(unzFile file, int *method,
    1575             :                                            int *level, int raw)
    1576             : {
    1577           0 :     return cpl_unzOpenCurrentFile3(file, method, level, raw, nullptr);
    1578             : }
    1579             : 
    1580             : /** Addition for GDAL : START */
    1581             : 
    1582        4224 : extern uLong64 ZEXPORT cpl_unzGetCurrentFileZStreamPos(unzFile file)
    1583             : {
    1584             :     unz_s *s;
    1585             :     file_in_zip_read_info_s *pfile_in_zip_read_info;
    1586        4224 :     s = reinterpret_cast<unz_s *>(file);
    1587        4224 :     if (file == nullptr)
    1588           0 :         return 0;  // UNZ_PARAMERROR;
    1589        4224 :     pfile_in_zip_read_info = s->pfile_in_zip_read;
    1590        4224 :     if (pfile_in_zip_read_info == nullptr)
    1591           0 :         return 0;  // UNZ_PARAMERROR;
    1592        4224 :     return pfile_in_zip_read_info->pos_in_zipfile +
    1593        4224 :            pfile_in_zip_read_info->byte_before_the_zipfile;
    1594             : }
    1595             : 
    1596           0 : extern int cpl_unzGetLocalHeaderPos(unzFile file, uLong64 *pos_local_header)
    1597             : {
    1598             :     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             : }
    1606             : 
    1607        4148 : 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             : {
    1611        4148 :     int err = UNZ_OK;
    1612             :     uLong uMagic, uData, uFlags;
    1613             :     uLong size_filename;
    1614             :     uLong size_extra_field;
    1615             :     unz_s *s;
    1616             : 
    1617        4148 :     memset(pfile_info, 0, sizeof(*pfile_info));
    1618             : 
    1619        4148 :     if (!file)
    1620           0 :         return UNZ_PARAMERROR;
    1621        4148 :     s = reinterpret_cast<unz_s *>(file);
    1622             : 
    1623        4148 :     if (ZSEEK(s->z_filefunc, s->filestream, pos_local_header,
    1624        4148 :               ZLIB_FILEFUNC_SEEK_SET) != 0)
    1625           0 :         return UNZ_ERRNO;
    1626             : 
    1627             :     // if (err == UNZ_OK)
    1628             :     {
    1629        4148 :         if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uMagic) != UNZ_OK)
    1630           0 :             err = UNZ_ERRNO;
    1631        4148 :         else if (uMagic != 0x04034b50)
    1632         528 :             err = UNZ_BADZIPFILE;
    1633             :     }
    1634             : 
    1635        4148 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
    1636           0 :         err = UNZ_ERRNO;
    1637             : 
    1638        4148 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uFlags) != UNZ_OK)
    1639           0 :         err = UNZ_ERRNO;
    1640             : 
    1641        4148 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream, &uData) != UNZ_OK)
    1642           0 :         err = UNZ_ERRNO;
    1643             :     else
    1644        4148 :         pfile_info->compression_method = uData;
    1645             : 
    1646        4148 :     if ((err == UNZ_OK) && (pfile_info->compression_method != 0) &&
    1647        3543 :         (pfile_info->compression_method != Z_DEFLATED))
    1648             :     {
    1649             : #ifdef ENABLE_DEFLATE64
    1650           0 :         if (pfile_info->compression_method == 9)
    1651             :         {
    1652             :             // ok
    1653             :         }
    1654             :         else
    1655             : #endif
    1656             :         {
    1657           0 :             CPLError(CE_Failure, CPLE_NotSupported,
    1658             :                      "A file in the ZIP archive uses a unsupported "
    1659             :                      "compression method (%lu)",
    1660             :                      pfile_info->compression_method);
    1661           0 :             err = UNZ_BADZIPFILE;
    1662             :         }
    1663             :     }
    1664             : 
    1665        4148 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
    1666             :         UNZ_OK) /* date/time */
    1667           0 :         err = UNZ_ERRNO;
    1668             : 
    1669        4148 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
    1670             :         UNZ_OK) /* crc */
    1671           0 :         err = UNZ_ERRNO;
    1672             : 
    1673        4148 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
    1674             :         UNZ_OK) /* size compr */
    1675           0 :         err = UNZ_ERRNO;
    1676             :     else
    1677        4148 :         pfile_info->compressed_size = uData;
    1678             : 
    1679        4148 :     if (unzlocal_getLong(&s->z_filefunc, s->filestream, &uData) !=
    1680             :         UNZ_OK) /* size uncompr */
    1681           0 :         err = UNZ_ERRNO;
    1682             :     else
    1683        4148 :         pfile_info->uncompressed_size = uData;
    1684             : 
    1685        4148 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_filename) !=
    1686             :         UNZ_OK)
    1687           0 :         err = UNZ_ERRNO;
    1688             : 
    1689        4148 :     if (unzlocal_getShort(&s->z_filefunc, s->filestream, &size_extra_field) !=
    1690             :         UNZ_OK)
    1691           0 :         err = UNZ_ERRNO;
    1692             : 
    1693        4148 :     if (posData)
    1694             :     {
    1695        4148 :         *posData = pos_local_header + SIZEZIPLOCALHEADER + size_filename +
    1696             :                    size_extra_field;
    1697             :     }
    1698             : 
    1699        4148 :     if (size_filename <= fileNameBufferSize && szFileName)
    1700             :     {
    1701        4000 :         if (ZREAD(s->z_filefunc, s->filestream, szFileName, size_filename) !=
    1702             :             size_filename)
    1703           3 :             err = UNZ_ERRNO;
    1704             :     }
    1705             : 
    1706        4148 :     return err;
    1707             : }
    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           0 : extern int ZEXPORT cpl_unzReadCurrentFile(unzFile file, voidp buf, unsigned len)
    1722             : {
    1723           0 :     int err = UNZ_OK;
    1724           0 :     uInt iRead = 0;
    1725             :     unz_s *s;
    1726             :     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             :     {
    1758           0 :         if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
    1759           0 :             (pfile_in_zip_read_info->rest_read_compressed > 0))
    1760             :         {
    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             :                       pfile_in_zip_read_info->filestream,
    1769             :                       pfile_in_zip_read_info->pos_in_zipfile +
    1770             :                           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             :                       pfile_in_zip_read_info->filestream,
    1775             :                       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             :                 static_cast<uInt>(uReadThis);
    1798             :         }
    1799             : 
    1800           0 :         if ((pfile_in_zip_read_info->compression_method == 0) ||
    1801           0 :             (pfile_in_zip_read_info->raw))
    1802             :         {
    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             :             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             :         }
    1831             :         else
    1832             :         {
    1833             :             uLong64 uTotalOutBefore, uTotalOutAfter;
    1834             :             const Bytef *bufBefore;
    1835             :             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             :                       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             :         }
    1868             :     }
    1869             : 
    1870           0 :     if (err == Z_OK)
    1871           0 :         return iRead;
    1872           0 :     return err;
    1873             : }
    1874             : 
    1875             : /*
    1876             :   Give the current position in uncompressed data
    1877             : */
    1878           0 : extern z_off_t ZEXPORT cpl_unztell(unzFile file)
    1879             : {
    1880             :     unz_s *s;
    1881             :     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             : }
    1892             : 
    1893             : /*
    1894             :   return 1 if the end of file was reached, 0 elsewhere
    1895             : */
    1896           0 : extern int ZEXPORT cpl_unzeof(unzFile file)
    1897             : {
    1898             :     unz_s *s;
    1899             :     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             :     else
    1911           0 :         return 0;
    1912             : }
    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           0 : extern int ZEXPORT cpl_unzGetLocalExtrafield(unzFile file, voidp buf,
    1927             :                                              unsigned len)
    1928             : {
    1929             :     unz_s *s;
    1930             :     file_in_zip_read_info_s *pfile_in_zip_read_info;
    1931             :     uInt read_now;
    1932             :     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             :     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             :               pfile_in_zip_read_info->filestream,
    1958             :               pfile_in_zip_read_info->offset_local_extrafield +
    1959             :                   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             : }
    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        4224 : extern int ZEXPORT cpl_unzCloseCurrentFile(unzFile file)
    1975             : {
    1976        4224 :     int err = UNZ_OK;
    1977             : 
    1978             :     unz_s *s;
    1979             :     file_in_zip_read_info_s *pfile_in_zip_read_info;
    1980        4224 :     if (file == nullptr)
    1981           0 :         return UNZ_PARAMERROR;
    1982        4224 :     s = reinterpret_cast<unz_s *>(file);
    1983        4224 :     pfile_in_zip_read_info = s->pfile_in_zip_read;
    1984             : 
    1985        4224 :     if (pfile_in_zip_read_info == nullptr)
    1986           0 :         return UNZ_PARAMERROR;
    1987             : 
    1988        4224 :     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
    1989           0 :         (!pfile_in_zip_read_info->raw))
    1990             :     {
    1991           0 :         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
    1992           0 :             err = UNZ_CRCERROR;
    1993             :     }
    1994             : 
    1995        4224 :     TRYFREE(pfile_in_zip_read_info->read_buffer);
    1996        4224 :     pfile_in_zip_read_info->read_buffer = nullptr;
    1997        4224 :     if (pfile_in_zip_read_info->stream_initialised)
    1998        4148 :         inflateEnd(&pfile_in_zip_read_info->stream);
    1999             : 
    2000        4224 :     pfile_in_zip_read_info->stream_initialised = 0;
    2001        4224 :     TRYFREE(pfile_in_zip_read_info);
    2002             : 
    2003        4224 :     s->pfile_in_zip_read = nullptr;
    2004             : 
    2005        4224 :     return err;
    2006             : }
    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           0 : extern int ZEXPORT cpl_unzGetGlobalComment(unzFile file, char *szComment,
    2014             :                                            uLong uSizeBuf)
    2015             : {
    2016             :     /* int err=UNZ_OK; */
    2017             :     unz_s *s;
    2018             :     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             :     {
    2033           0 :         *szComment = '\0';
    2034           0 :         if (ZREAD(s->z_filefunc, s->filestream, szComment, uReadThis) !=
    2035             :             uReadThis)
    2036           0 :             return UNZ_ERRNO;
    2037             :     }
    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             : }
    2043             : 
    2044             : // Additions by RX '2004.
    2045           0 : extern uLong64 ZEXPORT cpl_unzGetOffset(unzFile file)
    2046             : {
    2047             :     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             : }
    2059             : 
    2060           0 : extern int ZEXPORT cpl_unzSetOffset(unzFile file, uLong64 pos)
    2061             : {
    2062             :     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             :         file, &s->cur_file_info, &s->cur_file_info_internal, nullptr, 0,
    2072             :         nullptr, 0, nullptr, 0);
    2073           0 :     s->current_file_ok = (err == UNZ_OK);
    2074           0 :     return err;
    2075             : }

Generated by: LCOV version 1.14