LCOV - code coverage report
Current view: top level - port - cpl_minizip_unzip.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 517 904 57.2 %
Date: 2024-04-28 18:08:58 Functions: 23 36 63.9 %

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

Generated by: LCOV version 1.14