11cb0ef41Sopenharmony_ci// Copyright 2011 The Chromium Authors
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "third_party/zlib/google/zip_internal.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <stddef.h>
81cb0ef41Sopenharmony_ci#include <string.h>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include <algorithm>
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include "base/containers/fixed_flat_set.h"
131cb0ef41Sopenharmony_ci#include "base/files/file_path.h"
141cb0ef41Sopenharmony_ci#include "base/logging.h"
151cb0ef41Sopenharmony_ci#include "base/notreached.h"
161cb0ef41Sopenharmony_ci#include "base/strings/string_piece.h"
171cb0ef41Sopenharmony_ci#include "base/strings/string_util.h"
181cb0ef41Sopenharmony_ci#include "base/strings/utf_string_conversions.h"
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci#if defined(USE_SYSTEM_MINIZIP)
211cb0ef41Sopenharmony_ci#include <minizip/ioapi.h>
221cb0ef41Sopenharmony_ci#include <minizip/unzip.h>
231cb0ef41Sopenharmony_ci#include <minizip/zip.h>
241cb0ef41Sopenharmony_ci#else
251cb0ef41Sopenharmony_ci#include "third_party/zlib/contrib/minizip/unzip.h"
261cb0ef41Sopenharmony_ci#include "third_party/zlib/contrib/minizip/zip.h"
271cb0ef41Sopenharmony_ci#if defined(OS_WIN)
281cb0ef41Sopenharmony_ci#include "third_party/zlib/contrib/minizip/iowin32.h"
291cb0ef41Sopenharmony_ci#elif defined(OS_POSIX)
301cb0ef41Sopenharmony_ci#include "third_party/zlib/contrib/minizip/ioapi.h"
311cb0ef41Sopenharmony_ci#endif  // defined(OS_POSIX)
321cb0ef41Sopenharmony_ci#endif  // defined(USE_SYSTEM_MINIZIP)
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_cinamespace {
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci#if defined(OS_WIN)
371cb0ef41Sopenharmony_citypedef struct {
381cb0ef41Sopenharmony_ci  HANDLE hf;
391cb0ef41Sopenharmony_ci  int error;
401cb0ef41Sopenharmony_ci} WIN32FILE_IOWIN;
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci// This function is derived from third_party/minizip/iowin32.c.
431cb0ef41Sopenharmony_ci// Its only difference is that it treats the filename as UTF-8 and
441cb0ef41Sopenharmony_ci// uses the Unicode version of CreateFile.
451cb0ef41Sopenharmony_civoid* ZipOpenFunc(void* opaque, const void* filename, int mode) {
461cb0ef41Sopenharmony_ci  DWORD desired_access = 0, creation_disposition = 0;
471cb0ef41Sopenharmony_ci  DWORD share_mode = 0, flags_and_attributes = 0;
481cb0ef41Sopenharmony_ci  HANDLE file = 0;
491cb0ef41Sopenharmony_ci  void* ret = NULL;
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) {
521cb0ef41Sopenharmony_ci    desired_access = GENERIC_READ;
531cb0ef41Sopenharmony_ci    creation_disposition = OPEN_EXISTING;
541cb0ef41Sopenharmony_ci    share_mode = FILE_SHARE_READ;
551cb0ef41Sopenharmony_ci  } else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) {
561cb0ef41Sopenharmony_ci    desired_access = GENERIC_WRITE | GENERIC_READ;
571cb0ef41Sopenharmony_ci    creation_disposition = OPEN_EXISTING;
581cb0ef41Sopenharmony_ci  } else if (mode & ZLIB_FILEFUNC_MODE_CREATE) {
591cb0ef41Sopenharmony_ci    desired_access = GENERIC_WRITE | GENERIC_READ;
601cb0ef41Sopenharmony_ci    creation_disposition = CREATE_ALWAYS;
611cb0ef41Sopenharmony_ci  }
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci  if (filename != nullptr && desired_access != 0) {
641cb0ef41Sopenharmony_ci    file = CreateFileW(
651cb0ef41Sopenharmony_ci        base::UTF8ToWide(static_cast<const char*>(filename)).c_str(),
661cb0ef41Sopenharmony_ci        desired_access, share_mode, nullptr, creation_disposition,
671cb0ef41Sopenharmony_ci        flags_and_attributes, nullptr);
681cb0ef41Sopenharmony_ci  }
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  if (file == INVALID_HANDLE_VALUE)
711cb0ef41Sopenharmony_ci    file = NULL;
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  if (file != NULL) {
741cb0ef41Sopenharmony_ci    WIN32FILE_IOWIN file_ret;
751cb0ef41Sopenharmony_ci    file_ret.hf = file;
761cb0ef41Sopenharmony_ci    file_ret.error = 0;
771cb0ef41Sopenharmony_ci    ret = malloc(sizeof(WIN32FILE_IOWIN));
781cb0ef41Sopenharmony_ci    if (ret == NULL)
791cb0ef41Sopenharmony_ci      CloseHandle(file);
801cb0ef41Sopenharmony_ci    else
811cb0ef41Sopenharmony_ci      *(static_cast<WIN32FILE_IOWIN*>(ret)) = file_ret;
821cb0ef41Sopenharmony_ci  }
831cb0ef41Sopenharmony_ci  return ret;
841cb0ef41Sopenharmony_ci}
851cb0ef41Sopenharmony_ci#endif
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci#if defined(OS_POSIX) || defined(OS_FUCHSIA)
881cb0ef41Sopenharmony_ci// Callback function for zlib that opens a file stream from a file descriptor.
891cb0ef41Sopenharmony_ci// Since we do not own the file descriptor, dup it so that we can fdopen/fclose
901cb0ef41Sopenharmony_ci// a file stream.
911cb0ef41Sopenharmony_civoid* FdOpenFileFunc(void* opaque, const void* filename, int mode) {
921cb0ef41Sopenharmony_ci  FILE* file = NULL;
931cb0ef41Sopenharmony_ci  const char* mode_fopen = NULL;
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
961cb0ef41Sopenharmony_ci    mode_fopen = "rb";
971cb0ef41Sopenharmony_ci  else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
981cb0ef41Sopenharmony_ci    mode_fopen = "r+b";
991cb0ef41Sopenharmony_ci  else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
1001cb0ef41Sopenharmony_ci    mode_fopen = "wb";
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  if ((filename != NULL) && (mode_fopen != NULL)) {
1031cb0ef41Sopenharmony_ci    int fd = dup(*static_cast<int*>(opaque));
1041cb0ef41Sopenharmony_ci    if (fd != -1)
1051cb0ef41Sopenharmony_ci      file = fdopen(fd, mode_fopen);
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  return file;
1091cb0ef41Sopenharmony_ci}
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ciint FdCloseFileFunc(void* opaque, void* stream) {
1121cb0ef41Sopenharmony_ci  fclose(static_cast<FILE*>(stream));
1131cb0ef41Sopenharmony_ci  free(opaque);  // malloc'ed in FillFdOpenFileFunc()
1141cb0ef41Sopenharmony_ci  return 0;
1151cb0ef41Sopenharmony_ci}
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci// Fills |pzlib_filecunc_def| appropriately to handle the zip file
1181cb0ef41Sopenharmony_ci// referred to by |fd|.
1191cb0ef41Sopenharmony_civoid FillFdOpenFileFunc(zlib_filefunc64_def* pzlib_filefunc_def, int fd) {
1201cb0ef41Sopenharmony_ci  fill_fopen64_filefunc(pzlib_filefunc_def);
1211cb0ef41Sopenharmony_ci  pzlib_filefunc_def->zopen64_file = FdOpenFileFunc;
1221cb0ef41Sopenharmony_ci  pzlib_filefunc_def->zclose_file = FdCloseFileFunc;
1231cb0ef41Sopenharmony_ci  int* ptr_fd = static_cast<int*>(malloc(sizeof(fd)));
1241cb0ef41Sopenharmony_ci  *ptr_fd = fd;
1251cb0ef41Sopenharmony_ci  pzlib_filefunc_def->opaque = ptr_fd;
1261cb0ef41Sopenharmony_ci}
1271cb0ef41Sopenharmony_ci#endif  // defined(OS_POSIX)
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci#if defined(OS_WIN)
1301cb0ef41Sopenharmony_ci// Callback function for zlib that opens a file stream from a Windows handle.
1311cb0ef41Sopenharmony_ci// Does not take ownership of the handle.
1321cb0ef41Sopenharmony_civoid* HandleOpenFileFunc(void* opaque, const void* /*filename*/, int mode) {
1331cb0ef41Sopenharmony_ci  WIN32FILE_IOWIN file_ret;
1341cb0ef41Sopenharmony_ci  file_ret.hf = static_cast<HANDLE>(opaque);
1351cb0ef41Sopenharmony_ci  file_ret.error = 0;
1361cb0ef41Sopenharmony_ci  if (file_ret.hf == INVALID_HANDLE_VALUE)
1371cb0ef41Sopenharmony_ci    return NULL;
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci  void* ret = malloc(sizeof(WIN32FILE_IOWIN));
1401cb0ef41Sopenharmony_ci  if (ret != NULL)
1411cb0ef41Sopenharmony_ci    *(static_cast<WIN32FILE_IOWIN*>(ret)) = file_ret;
1421cb0ef41Sopenharmony_ci  return ret;
1431cb0ef41Sopenharmony_ci}
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ciint HandleCloseFileFunc(void* opaque, void* stream) {
1461cb0ef41Sopenharmony_ci  free(stream);  // malloc'ed in HandleOpenFileFunc()
1471cb0ef41Sopenharmony_ci  return 0;
1481cb0ef41Sopenharmony_ci}
1491cb0ef41Sopenharmony_ci#endif
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci// A struct that contains data required for zlib functions to extract files from
1521cb0ef41Sopenharmony_ci// a zip archive stored in memory directly. The following I/O API functions
1531cb0ef41Sopenharmony_ci// expect their opaque parameters refer to this struct.
1541cb0ef41Sopenharmony_cistruct ZipBuffer {
1551cb0ef41Sopenharmony_ci  const char* data;  // weak
1561cb0ef41Sopenharmony_ci  ZPOS64_T length;
1571cb0ef41Sopenharmony_ci  ZPOS64_T offset;
1581cb0ef41Sopenharmony_ci};
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci// Opens the specified file. When this function returns a non-NULL pointer, zlib
1611cb0ef41Sopenharmony_ci// uses this pointer as a stream parameter while compressing or uncompressing
1621cb0ef41Sopenharmony_ci// data. (Returning NULL represents an error.) This function initializes the
1631cb0ef41Sopenharmony_ci// given opaque parameter and returns it because this parameter stores all
1641cb0ef41Sopenharmony_ci// information needed for uncompressing data. (This function does not support
1651cb0ef41Sopenharmony_ci// writing compressed data and it returns NULL for this case.)
1661cb0ef41Sopenharmony_civoid* OpenZipBuffer(void* opaque, const void* /*filename*/, int mode) {
1671cb0ef41Sopenharmony_ci  if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) != ZLIB_FILEFUNC_MODE_READ) {
1681cb0ef41Sopenharmony_ci    NOTREACHED();
1691cb0ef41Sopenharmony_ci    return NULL;
1701cb0ef41Sopenharmony_ci  }
1711cb0ef41Sopenharmony_ci  ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque);
1721cb0ef41Sopenharmony_ci  if (!buffer || !buffer->data || !buffer->length)
1731cb0ef41Sopenharmony_ci    return NULL;
1741cb0ef41Sopenharmony_ci  buffer->offset = 0;
1751cb0ef41Sopenharmony_ci  return opaque;
1761cb0ef41Sopenharmony_ci}
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci// Reads compressed data from the specified stream. This function copies data
1791cb0ef41Sopenharmony_ci// refered by the opaque parameter and returns the size actually copied.
1801cb0ef41Sopenharmony_ciuLong ReadZipBuffer(void* opaque, void* /*stream*/, void* buf, uLong size) {
1811cb0ef41Sopenharmony_ci  ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque);
1821cb0ef41Sopenharmony_ci  DCHECK_LE(buffer->offset, buffer->length);
1831cb0ef41Sopenharmony_ci  ZPOS64_T remaining_bytes = buffer->length - buffer->offset;
1841cb0ef41Sopenharmony_ci  if (!buffer || !buffer->data || !remaining_bytes)
1851cb0ef41Sopenharmony_ci    return 0;
1861cb0ef41Sopenharmony_ci  if (size > remaining_bytes)
1871cb0ef41Sopenharmony_ci    size = remaining_bytes;
1881cb0ef41Sopenharmony_ci  memcpy(buf, &buffer->data[buffer->offset], size);
1891cb0ef41Sopenharmony_ci  buffer->offset += size;
1901cb0ef41Sopenharmony_ci  return size;
1911cb0ef41Sopenharmony_ci}
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci// Writes compressed data to the stream. This function always returns zero
1941cb0ef41Sopenharmony_ci// because this implementation is only for reading compressed data.
1951cb0ef41Sopenharmony_ciuLong WriteZipBuffer(void* /*opaque*/,
1961cb0ef41Sopenharmony_ci                     void* /*stream*/,
1971cb0ef41Sopenharmony_ci                     const void* /*buf*/,
1981cb0ef41Sopenharmony_ci                     uLong /*size*/) {
1991cb0ef41Sopenharmony_ci  NOTREACHED();
2001cb0ef41Sopenharmony_ci  return 0;
2011cb0ef41Sopenharmony_ci}
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci// Returns the offset from the beginning of the data.
2041cb0ef41Sopenharmony_ciZPOS64_T GetOffsetOfZipBuffer(void* opaque, void* /*stream*/) {
2051cb0ef41Sopenharmony_ci  ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque);
2061cb0ef41Sopenharmony_ci  if (!buffer)
2071cb0ef41Sopenharmony_ci    return -1;
2081cb0ef41Sopenharmony_ci  return buffer->offset;
2091cb0ef41Sopenharmony_ci}
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci// Moves the current offset to the specified position.
2121cb0ef41Sopenharmony_cilong SeekZipBuffer(void* opaque,
2131cb0ef41Sopenharmony_ci                   void* /*stream*/,
2141cb0ef41Sopenharmony_ci                   ZPOS64_T offset,
2151cb0ef41Sopenharmony_ci                   int origin) {
2161cb0ef41Sopenharmony_ci  ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque);
2171cb0ef41Sopenharmony_ci  if (!buffer)
2181cb0ef41Sopenharmony_ci    return -1;
2191cb0ef41Sopenharmony_ci  if (origin == ZLIB_FILEFUNC_SEEK_CUR) {
2201cb0ef41Sopenharmony_ci    buffer->offset = std::min(buffer->offset + offset, buffer->length);
2211cb0ef41Sopenharmony_ci    return 0;
2221cb0ef41Sopenharmony_ci  }
2231cb0ef41Sopenharmony_ci  if (origin == ZLIB_FILEFUNC_SEEK_END) {
2241cb0ef41Sopenharmony_ci    buffer->offset = (buffer->length > offset) ? buffer->length - offset : 0;
2251cb0ef41Sopenharmony_ci    return 0;
2261cb0ef41Sopenharmony_ci  }
2271cb0ef41Sopenharmony_ci  if (origin == ZLIB_FILEFUNC_SEEK_SET) {
2281cb0ef41Sopenharmony_ci    buffer->offset = std::min(buffer->length, offset);
2291cb0ef41Sopenharmony_ci    return 0;
2301cb0ef41Sopenharmony_ci  }
2311cb0ef41Sopenharmony_ci  NOTREACHED();
2321cb0ef41Sopenharmony_ci  return -1;
2331cb0ef41Sopenharmony_ci}
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci// Closes the input offset and deletes all resources used for compressing or
2361cb0ef41Sopenharmony_ci// uncompressing data. This function deletes the ZipBuffer object referred by
2371cb0ef41Sopenharmony_ci// the opaque parameter since zlib deletes the unzFile object and it does not
2381cb0ef41Sopenharmony_ci// use this object any longer.
2391cb0ef41Sopenharmony_ciint CloseZipBuffer(void* opaque, void* /*stream*/) {
2401cb0ef41Sopenharmony_ci  if (opaque)
2411cb0ef41Sopenharmony_ci    free(opaque);
2421cb0ef41Sopenharmony_ci  return 0;
2431cb0ef41Sopenharmony_ci}
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci// Returns the last error happened when reading or writing data. This function
2461cb0ef41Sopenharmony_ci// always returns zero, which means there are not any errors.
2471cb0ef41Sopenharmony_ciint GetErrorOfZipBuffer(void* /*opaque*/, void* /*stream*/) {
2481cb0ef41Sopenharmony_ci  return 0;
2491cb0ef41Sopenharmony_ci}
2501cb0ef41Sopenharmony_ci
2511cb0ef41Sopenharmony_ci// Returns a zip_fileinfo struct with the time represented by |file_time|.
2521cb0ef41Sopenharmony_cizip_fileinfo TimeToZipFileInfo(const base::Time& file_time) {
2531cb0ef41Sopenharmony_ci  base::Time::Exploded file_time_parts;
2541cb0ef41Sopenharmony_ci  file_time.UTCExplode(&file_time_parts);
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ci  zip_fileinfo zip_info = {};
2571cb0ef41Sopenharmony_ci  if (file_time_parts.year >= 1980) {
2581cb0ef41Sopenharmony_ci    // This if check works around the handling of the year value in
2591cb0ef41Sopenharmony_ci    // contrib/minizip/zip.c in function zip64local_TmzDateToDosDate
2601cb0ef41Sopenharmony_ci    // It assumes that dates below 1980 are in the double digit format.
2611cb0ef41Sopenharmony_ci    // Hence the fail safe option is to leave the date unset. Some programs
2621cb0ef41Sopenharmony_ci    // might show the unset date as 1980-0-0 which is invalid.
2631cb0ef41Sopenharmony_ci    zip_info.tmz_date = {
2641cb0ef41Sopenharmony_ci        .tm_sec = static_cast<uInt>(file_time_parts.second),
2651cb0ef41Sopenharmony_ci        .tm_min = static_cast<uInt>(file_time_parts.minute),
2661cb0ef41Sopenharmony_ci        .tm_hour = static_cast<uInt>(file_time_parts.hour),
2671cb0ef41Sopenharmony_ci        .tm_mday = static_cast<uInt>(file_time_parts.day_of_month),
2681cb0ef41Sopenharmony_ci        .tm_mon = static_cast<uInt>(file_time_parts.month - 1),
2691cb0ef41Sopenharmony_ci        .tm_year = static_cast<uInt>(file_time_parts.year)};
2701cb0ef41Sopenharmony_ci  }
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci  return zip_info;
2731cb0ef41Sopenharmony_ci}
2741cb0ef41Sopenharmony_ci}  // namespace
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_cinamespace zip {
2771cb0ef41Sopenharmony_cinamespace internal {
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ciunzFile OpenForUnzipping(const std::string& file_name_utf8) {
2801cb0ef41Sopenharmony_ci  zlib_filefunc64_def* zip_func_ptrs = nullptr;
2811cb0ef41Sopenharmony_ci#if defined(OS_WIN)
2821cb0ef41Sopenharmony_ci  zlib_filefunc64_def zip_funcs;
2831cb0ef41Sopenharmony_ci  fill_win32_filefunc64(&zip_funcs);
2841cb0ef41Sopenharmony_ci  zip_funcs.zopen64_file = ZipOpenFunc;
2851cb0ef41Sopenharmony_ci  zip_func_ptrs = &zip_funcs;
2861cb0ef41Sopenharmony_ci#endif
2871cb0ef41Sopenharmony_ci  return unzOpen2_64(file_name_utf8.c_str(), zip_func_ptrs);
2881cb0ef41Sopenharmony_ci}
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci#if defined(OS_POSIX) || defined(OS_FUCHSIA)
2911cb0ef41Sopenharmony_ciunzFile OpenFdForUnzipping(int zip_fd) {
2921cb0ef41Sopenharmony_ci  zlib_filefunc64_def zip_funcs;
2931cb0ef41Sopenharmony_ci  FillFdOpenFileFunc(&zip_funcs, zip_fd);
2941cb0ef41Sopenharmony_ci  // Passing dummy "fd" filename to zlib.
2951cb0ef41Sopenharmony_ci  return unzOpen2_64("fd", &zip_funcs);
2961cb0ef41Sopenharmony_ci}
2971cb0ef41Sopenharmony_ci#endif
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci#if defined(OS_WIN)
3001cb0ef41Sopenharmony_ciunzFile OpenHandleForUnzipping(HANDLE zip_handle) {
3011cb0ef41Sopenharmony_ci  zlib_filefunc64_def zip_funcs;
3021cb0ef41Sopenharmony_ci  fill_win32_filefunc64(&zip_funcs);
3031cb0ef41Sopenharmony_ci  zip_funcs.zopen64_file = HandleOpenFileFunc;
3041cb0ef41Sopenharmony_ci  zip_funcs.zclose_file = HandleCloseFileFunc;
3051cb0ef41Sopenharmony_ci  zip_funcs.opaque = zip_handle;
3061cb0ef41Sopenharmony_ci  return unzOpen2_64("fd", &zip_funcs);
3071cb0ef41Sopenharmony_ci}
3081cb0ef41Sopenharmony_ci#endif
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci// static
3111cb0ef41Sopenharmony_ciunzFile PrepareMemoryForUnzipping(const std::string& data) {
3121cb0ef41Sopenharmony_ci  if (data.empty())
3131cb0ef41Sopenharmony_ci    return NULL;
3141cb0ef41Sopenharmony_ci
3151cb0ef41Sopenharmony_ci  ZipBuffer* buffer = static_cast<ZipBuffer*>(malloc(sizeof(ZipBuffer)));
3161cb0ef41Sopenharmony_ci  if (!buffer)
3171cb0ef41Sopenharmony_ci    return NULL;
3181cb0ef41Sopenharmony_ci  buffer->data = data.data();
3191cb0ef41Sopenharmony_ci  buffer->length = data.length();
3201cb0ef41Sopenharmony_ci  buffer->offset = 0;
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci  zlib_filefunc64_def zip_functions;
3231cb0ef41Sopenharmony_ci  zip_functions.zopen64_file = OpenZipBuffer;
3241cb0ef41Sopenharmony_ci  zip_functions.zread_file = ReadZipBuffer;
3251cb0ef41Sopenharmony_ci  zip_functions.zwrite_file = WriteZipBuffer;
3261cb0ef41Sopenharmony_ci  zip_functions.ztell64_file = GetOffsetOfZipBuffer;
3271cb0ef41Sopenharmony_ci  zip_functions.zseek64_file = SeekZipBuffer;
3281cb0ef41Sopenharmony_ci  zip_functions.zclose_file = CloseZipBuffer;
3291cb0ef41Sopenharmony_ci  zip_functions.zerror_file = GetErrorOfZipBuffer;
3301cb0ef41Sopenharmony_ci  zip_functions.opaque = buffer;
3311cb0ef41Sopenharmony_ci  return unzOpen2_64(nullptr, &zip_functions);
3321cb0ef41Sopenharmony_ci}
3331cb0ef41Sopenharmony_ci
3341cb0ef41Sopenharmony_cizipFile OpenForZipping(const std::string& file_name_utf8, int append_flag) {
3351cb0ef41Sopenharmony_ci  zlib_filefunc64_def* zip_func_ptrs = nullptr;
3361cb0ef41Sopenharmony_ci#if defined(OS_WIN)
3371cb0ef41Sopenharmony_ci  zlib_filefunc64_def zip_funcs;
3381cb0ef41Sopenharmony_ci  fill_win32_filefunc64(&zip_funcs);
3391cb0ef41Sopenharmony_ci  zip_funcs.zopen64_file = ZipOpenFunc;
3401cb0ef41Sopenharmony_ci  zip_func_ptrs = &zip_funcs;
3411cb0ef41Sopenharmony_ci#endif
3421cb0ef41Sopenharmony_ci  return zipOpen2_64(file_name_utf8.c_str(), append_flag, nullptr,
3431cb0ef41Sopenharmony_ci                     zip_func_ptrs);
3441cb0ef41Sopenharmony_ci}
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci#if defined(OS_POSIX) || defined(OS_FUCHSIA)
3471cb0ef41Sopenharmony_cizipFile OpenFdForZipping(int zip_fd, int append_flag) {
3481cb0ef41Sopenharmony_ci  zlib_filefunc64_def zip_funcs;
3491cb0ef41Sopenharmony_ci  FillFdOpenFileFunc(&zip_funcs, zip_fd);
3501cb0ef41Sopenharmony_ci  // Passing dummy "fd" filename to zlib.
3511cb0ef41Sopenharmony_ci  return zipOpen2_64("fd", append_flag, nullptr, &zip_funcs);
3521cb0ef41Sopenharmony_ci}
3531cb0ef41Sopenharmony_ci#endif
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_cibool ZipOpenNewFileInZip(zipFile zip_file,
3561cb0ef41Sopenharmony_ci                         const std::string& str_path,
3571cb0ef41Sopenharmony_ci                         base::Time last_modified_time,
3581cb0ef41Sopenharmony_ci                         Compression compression) {
3591cb0ef41Sopenharmony_ci  // Section 4.4.4 http://www.pkware.com/documents/casestudies/APPNOTE.TXT
3601cb0ef41Sopenharmony_ci  // Setting the Language encoding flag so the file is told to be in utf-8.
3611cb0ef41Sopenharmony_ci  const uLong LANGUAGE_ENCODING_FLAG = 0x1 << 11;
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ci  const zip_fileinfo file_info = TimeToZipFileInfo(last_modified_time);
3641cb0ef41Sopenharmony_ci  const int err = zipOpenNewFileInZip4_64(
3651cb0ef41Sopenharmony_ci      /*file=*/zip_file,
3661cb0ef41Sopenharmony_ci      /*filename=*/str_path.c_str(),
3671cb0ef41Sopenharmony_ci      /*zip_fileinfo=*/&file_info,
3681cb0ef41Sopenharmony_ci      /*extrafield_local=*/nullptr,
3691cb0ef41Sopenharmony_ci      /*size_extrafield_local=*/0u,
3701cb0ef41Sopenharmony_ci      /*extrafield_global=*/nullptr,
3711cb0ef41Sopenharmony_ci      /*size_extrafield_global=*/0u,
3721cb0ef41Sopenharmony_ci      /*comment=*/nullptr,
3731cb0ef41Sopenharmony_ci      /*method=*/compression,
3741cb0ef41Sopenharmony_ci      /*level=*/Z_DEFAULT_COMPRESSION,
3751cb0ef41Sopenharmony_ci      /*raw=*/0,
3761cb0ef41Sopenharmony_ci      /*windowBits=*/-MAX_WBITS,
3771cb0ef41Sopenharmony_ci      /*memLevel=*/DEF_MEM_LEVEL,
3781cb0ef41Sopenharmony_ci      /*strategy=*/Z_DEFAULT_STRATEGY,
3791cb0ef41Sopenharmony_ci      /*password=*/nullptr,
3801cb0ef41Sopenharmony_ci      /*crcForCrypting=*/0,
3811cb0ef41Sopenharmony_ci      /*versionMadeBy=*/0,
3821cb0ef41Sopenharmony_ci      /*flagBase=*/LANGUAGE_ENCODING_FLAG,
3831cb0ef41Sopenharmony_ci      /*zip64=*/1);
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ci  if (err != ZIP_OK) {
3861cb0ef41Sopenharmony_ci    DLOG(ERROR) << "Cannot open ZIP file entry '" << str_path
3871cb0ef41Sopenharmony_ci                << "': zipOpenNewFileInZip4_64 returned " << err;
3881cb0ef41Sopenharmony_ci    return false;
3891cb0ef41Sopenharmony_ci  }
3901cb0ef41Sopenharmony_ci
3911cb0ef41Sopenharmony_ci  return true;
3921cb0ef41Sopenharmony_ci}
3931cb0ef41Sopenharmony_ci
3941cb0ef41Sopenharmony_ciCompression GetCompressionMethod(const base::FilePath& path) {
3951cb0ef41Sopenharmony_ci  // Get the filename extension in lower case.
3961cb0ef41Sopenharmony_ci  const base::FilePath::StringType ext =
3971cb0ef41Sopenharmony_ci      base::ToLowerASCII(path.FinalExtension());
3981cb0ef41Sopenharmony_ci
3991cb0ef41Sopenharmony_ci  if (ext.empty())
4001cb0ef41Sopenharmony_ci    return kDeflated;
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci  using StringPiece = base::FilePath::StringPieceType;
4031cb0ef41Sopenharmony_ci
4041cb0ef41Sopenharmony_ci  // Skip the leading dot.
4051cb0ef41Sopenharmony_ci  StringPiece ext_without_dot = ext;
4061cb0ef41Sopenharmony_ci  DCHECK_EQ(ext_without_dot.front(), FILE_PATH_LITERAL('.'));
4071cb0ef41Sopenharmony_ci  ext_without_dot.remove_prefix(1);
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci  // Well known filename extensions of files that a likely to be already
4101cb0ef41Sopenharmony_ci  // compressed. The extensions are in lower case without the leading dot.
4111cb0ef41Sopenharmony_ci  static constexpr auto kExts = base::MakeFixedFlatSet<StringPiece>({
4121cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("3g2"),   //
4131cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("3gp"),   //
4141cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("7z"),    //
4151cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("7zip"),  //
4161cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("aac"),   //
4171cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("avi"),   //
4181cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("bz"),    //
4191cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("bz2"),   //
4201cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("crx"),   //
4211cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("gif"),   //
4221cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("gz"),    //
4231cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("jar"),   //
4241cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("jpeg"),  //
4251cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("jpg"),   //
4261cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("lz"),    //
4271cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("m2v"),   //
4281cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("m4p"),   //
4291cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("m4v"),   //
4301cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("mng"),   //
4311cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("mov"),   //
4321cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("mp2"),   //
4331cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("mp3"),   //
4341cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("mp4"),   //
4351cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("mpe"),   //
4361cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("mpeg"),  //
4371cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("mpg"),   //
4381cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("mpv"),   //
4391cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("ogg"),   //
4401cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("ogv"),   //
4411cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("png"),   //
4421cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("qt"),    //
4431cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("rar"),   //
4441cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("taz"),   //
4451cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("tb2"),   //
4461cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("tbz"),   //
4471cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("tbz2"),  //
4481cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("tgz"),   //
4491cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("tlz"),   //
4501cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("tz"),    //
4511cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("tz2"),   //
4521cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("vob"),   //
4531cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("webm"),  //
4541cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("wma"),   //
4551cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("wmv"),   //
4561cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("xz"),    //
4571cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("z"),     //
4581cb0ef41Sopenharmony_ci      FILE_PATH_LITERAL("zip"),   //
4591cb0ef41Sopenharmony_ci  });
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci  if (kExts.count(ext_without_dot)) {
4621cb0ef41Sopenharmony_ci    return kStored;
4631cb0ef41Sopenharmony_ci  }
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ci  return kDeflated;
4661cb0ef41Sopenharmony_ci}
4671cb0ef41Sopenharmony_ci
4681cb0ef41Sopenharmony_ci}  // namespace internal
4691cb0ef41Sopenharmony_ci}  // namespace zip
470