14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "zip_file.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include <ostream>
194514f5e3Sopenharmony_ci#include "securec.h"
204514f5e3Sopenharmony_ci#include "zip_file_reader.h"
214514f5e3Sopenharmony_ci
224514f5e3Sopenharmony_cinamespace panda {
234514f5e3Sopenharmony_cinamespace ecmascript {
244514f5e3Sopenharmony_cinamespace {
254514f5e3Sopenharmony_ciconstexpr uint32_t MAX_FILE_NAME = 4096;
264514f5e3Sopenharmony_ciconstexpr uint32_t UNZIP_BUFFER_SIZE = 1024;
274514f5e3Sopenharmony_ciconstexpr uint32_t UNZIP_BUF_IN_LEN = 160 * UNZIP_BUFFER_SIZE;   // in  buffer length: 160KB
284514f5e3Sopenharmony_ciconstexpr uint32_t UNZIP_BUF_OUT_LEN = 320 * UNZIP_BUFFER_SIZE;  // out buffer length: 320KB
294514f5e3Sopenharmony_ciconstexpr uint32_t LOCAL_HEADER_SIGNATURE = 0x04034b50;
304514f5e3Sopenharmony_ciconstexpr uint32_t CENTRAL_SIGNATURE = 0x02014b50;
314514f5e3Sopenharmony_ciconstexpr uint32_t EOCD_SIGNATURE = 0x06054b50;
324514f5e3Sopenharmony_ciconstexpr uint32_t DATA_DESC_SIGNATURE = 0x08074b50;
334514f5e3Sopenharmony_ciconstexpr uint32_t FLAG_DATA_DESC = 0x8;
344514f5e3Sopenharmony_ciconstexpr uint8_t INFLATE_ERROR_TIMES = 5;
354514f5e3Sopenharmony_ciconst char FILE_SEPARATOR_CHAR = '/';
364514f5e3Sopenharmony_ci}  // namespace
374514f5e3Sopenharmony_ci
384514f5e3Sopenharmony_ciZipEntry::ZipEntry(const CentralDirEntry &centralEntry)
394514f5e3Sopenharmony_ci{
404514f5e3Sopenharmony_ci    compressionMethod = centralEntry.compressionMethod;
414514f5e3Sopenharmony_ci    uncompressedSize = centralEntry.uncompressedSize;
424514f5e3Sopenharmony_ci    compressedSize = centralEntry.compressedSize;
434514f5e3Sopenharmony_ci    localHeaderOffset = centralEntry.localHeaderOffset;
444514f5e3Sopenharmony_ci    crc = centralEntry.crc;
454514f5e3Sopenharmony_ci    flags = centralEntry.flags;
464514f5e3Sopenharmony_ci    modifiedTime = centralEntry.modifiedTime;
474514f5e3Sopenharmony_ci    modifiedDate = centralEntry.modifiedDate;
484514f5e3Sopenharmony_ci}
494514f5e3Sopenharmony_ci
504514f5e3Sopenharmony_ciZipFile::ZipFile(const std::string &pathName) : pathName_(pathName)
514514f5e3Sopenharmony_ci{
524514f5e3Sopenharmony_ci    dirRoot_ = std::make_shared<DirTreeNode>();
534514f5e3Sopenharmony_ci}
544514f5e3Sopenharmony_ci
554514f5e3Sopenharmony_ciZipFile::~ZipFile()
564514f5e3Sopenharmony_ci{
574514f5e3Sopenharmony_ci    Close();
584514f5e3Sopenharmony_ci}
594514f5e3Sopenharmony_ci
604514f5e3Sopenharmony_civoid ZipFile::SetContentLocation(const ZipPos start, const size_t length)
614514f5e3Sopenharmony_ci{
624514f5e3Sopenharmony_ci    if (isOpen_) {
634514f5e3Sopenharmony_ci        return;
644514f5e3Sopenharmony_ci    }
654514f5e3Sopenharmony_ci    fileStartPos_ = start;
664514f5e3Sopenharmony_ci    fileLength_ = length;
674514f5e3Sopenharmony_ci}
684514f5e3Sopenharmony_ci
694514f5e3Sopenharmony_cibool ZipFile::CheckEndDir(const EndDir &endDir) const
704514f5e3Sopenharmony_ci{
714514f5e3Sopenharmony_ci    size_t lenEndDir = sizeof(EndDir);
724514f5e3Sopenharmony_ci    if ((endDir.numDisk != 0) || (endDir.signature != EOCD_SIGNATURE) || (endDir.startDiskOfCentralDir != 0) ||
734514f5e3Sopenharmony_ci        (endDir.offset >= fileLength_) || (endDir.totalEntriesInThisDisk != endDir.totalEntries) ||
744514f5e3Sopenharmony_ci        (endDir.commentLen != 0) ||
754514f5e3Sopenharmony_ci        // central dir can't overlap end of central dir
764514f5e3Sopenharmony_ci        ((endDir.offset + endDir.sizeOfCentralDir + lenEndDir) > fileLength_)) {
774514f5e3Sopenharmony_ci        return false;
784514f5e3Sopenharmony_ci    }
794514f5e3Sopenharmony_ci    return true;
804514f5e3Sopenharmony_ci}
814514f5e3Sopenharmony_ci
824514f5e3Sopenharmony_cibool ZipFile::ParseEndDirectory()
834514f5e3Sopenharmony_ci{
844514f5e3Sopenharmony_ci    size_t endDirLen = sizeof(EndDir);
854514f5e3Sopenharmony_ci    size_t endFilePos = fileStartPos_ + fileLength_;
864514f5e3Sopenharmony_ci
874514f5e3Sopenharmony_ci    if (fileLength_ <= endDirLen) {
884514f5e3Sopenharmony_ci        return false;
894514f5e3Sopenharmony_ci    }
904514f5e3Sopenharmony_ci
914514f5e3Sopenharmony_ci    size_t eocdPos = endFilePos - endDirLen;
924514f5e3Sopenharmony_ci    if (!zipFileReader_->ReadBuffer(reinterpret_cast<uint8_t*>(&endDir_), eocdPos, sizeof(EndDir))) {
934514f5e3Sopenharmony_ci        return false;
944514f5e3Sopenharmony_ci    }
954514f5e3Sopenharmony_ci
964514f5e3Sopenharmony_ci    centralDirPos_ = endDir_.offset + fileStartPos_;
974514f5e3Sopenharmony_ci
984514f5e3Sopenharmony_ci    return CheckEndDir(endDir_);
994514f5e3Sopenharmony_ci}
1004514f5e3Sopenharmony_ci
1014514f5e3Sopenharmony_cibool ZipFile::ParseOneEntry(uint8_t* &entryPtr)
1024514f5e3Sopenharmony_ci{
1034514f5e3Sopenharmony_ci    if (entryPtr == nullptr) {
1044514f5e3Sopenharmony_ci        return false;
1054514f5e3Sopenharmony_ci    }
1064514f5e3Sopenharmony_ci
1074514f5e3Sopenharmony_ci    CentralDirEntry directoryEntry;
1084514f5e3Sopenharmony_ci    if (memcpy_s(&directoryEntry, sizeof(CentralDirEntry), entryPtr, sizeof(CentralDirEntry)) != EOK) {
1094514f5e3Sopenharmony_ci        return false;
1104514f5e3Sopenharmony_ci    }
1114514f5e3Sopenharmony_ci
1124514f5e3Sopenharmony_ci    if (directoryEntry.signature != CENTRAL_SIGNATURE) {
1134514f5e3Sopenharmony_ci        return false;
1144514f5e3Sopenharmony_ci    }
1154514f5e3Sopenharmony_ci
1164514f5e3Sopenharmony_ci    entryPtr += sizeof(CentralDirEntry);
1174514f5e3Sopenharmony_ci    size_t fileLength = (directoryEntry.nameSize >= MAX_FILE_NAME) ? (MAX_FILE_NAME - 1) : directoryEntry.nameSize;
1184514f5e3Sopenharmony_ci    std::string fileName(fileLength, 0);
1194514f5e3Sopenharmony_ci    if (memcpy_s(&(fileName[0]), fileLength, entryPtr, fileLength) != EOK) {
1204514f5e3Sopenharmony_ci        return false;
1214514f5e3Sopenharmony_ci    }
1224514f5e3Sopenharmony_ci
1234514f5e3Sopenharmony_ci    ZipEntry currentEntry(directoryEntry);
1244514f5e3Sopenharmony_ci    currentEntry.fileName = fileName;
1254514f5e3Sopenharmony_ci    entriesMap_[fileName] = currentEntry;
1264514f5e3Sopenharmony_ci    AddEntryToTree(fileName);
1274514f5e3Sopenharmony_ci    entryPtr += directoryEntry.nameSize + directoryEntry.extraSize + directoryEntry.commentSize;
1284514f5e3Sopenharmony_ci    return true;
1294514f5e3Sopenharmony_ci}
1304514f5e3Sopenharmony_ci
1314514f5e3Sopenharmony_civoid ZipFile::AddEntryToTree(const std::string &fileName)
1324514f5e3Sopenharmony_ci{
1334514f5e3Sopenharmony_ci    size_t cur = 0;
1344514f5e3Sopenharmony_ci    auto parent = dirRoot_;
1354514f5e3Sopenharmony_ci    do {
1364514f5e3Sopenharmony_ci        while (cur < fileName.size() && fileName[cur] == FILE_SEPARATOR_CHAR) {
1374514f5e3Sopenharmony_ci            cur++;
1384514f5e3Sopenharmony_ci        }
1394514f5e3Sopenharmony_ci        if (cur >= fileName.size()) {
1404514f5e3Sopenharmony_ci            break;
1414514f5e3Sopenharmony_ci        }
1424514f5e3Sopenharmony_ci        auto next = fileName.find_first_of(FILE_SEPARATOR_CHAR, cur);
1434514f5e3Sopenharmony_ci        auto nodeName = fileName.substr(cur, next - cur);
1444514f5e3Sopenharmony_ci        auto it = parent->children.find(nodeName);
1454514f5e3Sopenharmony_ci        if (it != parent->children.end()) {
1464514f5e3Sopenharmony_ci            parent = it->second;
1474514f5e3Sopenharmony_ci        } else {
1484514f5e3Sopenharmony_ci            auto node = std::make_shared<DirTreeNode>();
1494514f5e3Sopenharmony_ci            parent->children.emplace(nodeName, node);
1504514f5e3Sopenharmony_ci            parent = node;
1514514f5e3Sopenharmony_ci        }
1524514f5e3Sopenharmony_ci        cur = next;
1534514f5e3Sopenharmony_ci    } while (cur != std::string::npos);
1544514f5e3Sopenharmony_ci}
1554514f5e3Sopenharmony_ci
1564514f5e3Sopenharmony_cibool ZipFile::ParseAllEntries()
1574514f5e3Sopenharmony_ci{
1584514f5e3Sopenharmony_ci    auto centralData = zipFileReader_->ReadBuffer(static_cast<size_t>(centralDirPos_),
1594514f5e3Sopenharmony_ci        static_cast<size_t>(endDir_.sizeOfCentralDir));
1604514f5e3Sopenharmony_ci    if (centralData.empty()) {
1614514f5e3Sopenharmony_ci        return false;
1624514f5e3Sopenharmony_ci    }
1634514f5e3Sopenharmony_ci
1644514f5e3Sopenharmony_ci    bool ret = true;
1654514f5e3Sopenharmony_ci    uint8_t *entryPtr = reinterpret_cast<uint8_t *>(centralData.data());
1664514f5e3Sopenharmony_ci    for (uint16_t i = 0; i < endDir_.totalEntries; i++) {
1674514f5e3Sopenharmony_ci        if (!ParseOneEntry(entryPtr)) {
1684514f5e3Sopenharmony_ci            ret = false;
1694514f5e3Sopenharmony_ci            break;
1704514f5e3Sopenharmony_ci        }
1714514f5e3Sopenharmony_ci    }
1724514f5e3Sopenharmony_ci
1734514f5e3Sopenharmony_ci    return ret;
1744514f5e3Sopenharmony_ci}
1754514f5e3Sopenharmony_ci
1764514f5e3Sopenharmony_cibool ZipFile::Open()
1774514f5e3Sopenharmony_ci{
1784514f5e3Sopenharmony_ci    if (isOpen_) {
1794514f5e3Sopenharmony_ci        return true;
1804514f5e3Sopenharmony_ci    }
1814514f5e3Sopenharmony_ci
1824514f5e3Sopenharmony_ci    if (pathName_.length() > PATH_MAX) {
1834514f5e3Sopenharmony_ci        return false;
1844514f5e3Sopenharmony_ci    }
1854514f5e3Sopenharmony_ci
1864514f5e3Sopenharmony_ci    zipFileReader_ = ZipFileReader::CreateZipFileReader(pathName_);
1874514f5e3Sopenharmony_ci    if (!zipFileReader_) {
1884514f5e3Sopenharmony_ci        return false;
1894514f5e3Sopenharmony_ci    }
1904514f5e3Sopenharmony_ci
1914514f5e3Sopenharmony_ci    if (fileLength_ == 0) {
1924514f5e3Sopenharmony_ci        auto fileLength = zipFileReader_->GetFileLen();
1934514f5e3Sopenharmony_ci        fileLength_ = static_cast<ZipPos>(fileLength);
1944514f5e3Sopenharmony_ci        if (fileStartPos_ >= fileLength_) {
1954514f5e3Sopenharmony_ci            zipFileReader_.reset();
1964514f5e3Sopenharmony_ci            return false;
1974514f5e3Sopenharmony_ci        }
1984514f5e3Sopenharmony_ci
1994514f5e3Sopenharmony_ci        fileLength_ -= fileStartPos_;
2004514f5e3Sopenharmony_ci    }
2014514f5e3Sopenharmony_ci
2024514f5e3Sopenharmony_ci    bool result = ParseEndDirectory();
2034514f5e3Sopenharmony_ci    if (result) {
2044514f5e3Sopenharmony_ci        result = ParseAllEntries();
2054514f5e3Sopenharmony_ci    }
2064514f5e3Sopenharmony_ci    // it means open file success.
2074514f5e3Sopenharmony_ci    isOpen_ = true;
2084514f5e3Sopenharmony_ci    return result;
2094514f5e3Sopenharmony_ci}
2104514f5e3Sopenharmony_ci
2114514f5e3Sopenharmony_civoid ZipFile::Close()
2124514f5e3Sopenharmony_ci{
2134514f5e3Sopenharmony_ci    if (!isOpen_ || zipFileReader_ == nullptr) {
2144514f5e3Sopenharmony_ci        return;
2154514f5e3Sopenharmony_ci    }
2164514f5e3Sopenharmony_ci
2174514f5e3Sopenharmony_ci    isOpen_ = false;
2184514f5e3Sopenharmony_ci    entriesMap_.clear();
2194514f5e3Sopenharmony_ci    dirRoot_->children.clear();
2204514f5e3Sopenharmony_ci    pathName_ = "";
2214514f5e3Sopenharmony_ci
2224514f5e3Sopenharmony_ci    zipFileReader_.reset();
2234514f5e3Sopenharmony_ci}
2244514f5e3Sopenharmony_ci
2254514f5e3Sopenharmony_ci// Get all file zipEntry in this file
2264514f5e3Sopenharmony_ciconst ZipEntryMap &ZipFile::GetAllEntries() const
2274514f5e3Sopenharmony_ci{
2284514f5e3Sopenharmony_ci    return entriesMap_;
2294514f5e3Sopenharmony_ci}
2304514f5e3Sopenharmony_ci
2314514f5e3Sopenharmony_cibool ZipFile::HasEntry(const std::string &entryName) const
2324514f5e3Sopenharmony_ci{
2334514f5e3Sopenharmony_ci    return entriesMap_.find(entryName) != entriesMap_.end();
2344514f5e3Sopenharmony_ci}
2354514f5e3Sopenharmony_ci
2364514f5e3Sopenharmony_cibool ZipFile::IsDirExist(const std::string &dir) const
2374514f5e3Sopenharmony_ci{
2384514f5e3Sopenharmony_ci    if (dir.empty()) {
2394514f5e3Sopenharmony_ci        return false;
2404514f5e3Sopenharmony_ci    }
2414514f5e3Sopenharmony_ci
2424514f5e3Sopenharmony_ci    size_t cur = 0;
2434514f5e3Sopenharmony_ci    auto parent = dirRoot_;
2444514f5e3Sopenharmony_ci    do {
2454514f5e3Sopenharmony_ci        while (cur < dir.size() && dir[cur] == FILE_SEPARATOR_CHAR) {
2464514f5e3Sopenharmony_ci            cur++;
2474514f5e3Sopenharmony_ci        }
2484514f5e3Sopenharmony_ci        if (cur >= dir.size()) {
2494514f5e3Sopenharmony_ci            break;
2504514f5e3Sopenharmony_ci        }
2514514f5e3Sopenharmony_ci        auto next = dir.find_first_of(FILE_SEPARATOR_CHAR, cur);
2524514f5e3Sopenharmony_ci        auto nodeName = dir.substr(cur, next - cur);
2534514f5e3Sopenharmony_ci        auto it = parent->children.find(nodeName);
2544514f5e3Sopenharmony_ci        if (it == parent->children.end()) {
2554514f5e3Sopenharmony_ci            return false;
2564514f5e3Sopenharmony_ci        }
2574514f5e3Sopenharmony_ci        parent = it->second;
2584514f5e3Sopenharmony_ci        cur = next;
2594514f5e3Sopenharmony_ci    } while (cur != std::string::npos);
2604514f5e3Sopenharmony_ci
2614514f5e3Sopenharmony_ci    return true;
2624514f5e3Sopenharmony_ci}
2634514f5e3Sopenharmony_cinamespace {
2644514f5e3Sopenharmony_civoid GetTreeFileList(const std::shared_ptr<DirTreeNode> &root, const std::string &rootPath,
2654514f5e3Sopenharmony_ci    std::vector<std::string> &assetList)
2664514f5e3Sopenharmony_ci{
2674514f5e3Sopenharmony_ci    if (root->children.empty()) {
2684514f5e3Sopenharmony_ci        assetList.push_back(rootPath);
2694514f5e3Sopenharmony_ci    } else {
2704514f5e3Sopenharmony_ci        for (const auto &child : root->children) {
2714514f5e3Sopenharmony_ci            GetTreeFileList(child.second, rootPath + "/" + child.first, assetList);
2724514f5e3Sopenharmony_ci        }
2734514f5e3Sopenharmony_ci    }
2744514f5e3Sopenharmony_ci}
2754514f5e3Sopenharmony_ci}
2764514f5e3Sopenharmony_ci
2774514f5e3Sopenharmony_civoid ZipFile::GetAllFileList(const std::string &srcPath, std::vector<std::string> &assetList)
2784514f5e3Sopenharmony_ci{
2794514f5e3Sopenharmony_ci    if (srcPath.empty()) {
2804514f5e3Sopenharmony_ci        return;
2814514f5e3Sopenharmony_ci    }
2824514f5e3Sopenharmony_ci
2834514f5e3Sopenharmony_ci    auto rootName = srcPath.back() == FILE_SEPARATOR_CHAR ?
2844514f5e3Sopenharmony_ci        srcPath.substr(0, srcPath.length() - 1) : srcPath;
2854514f5e3Sopenharmony_ci
2864514f5e3Sopenharmony_ci    size_t cur = 0;
2874514f5e3Sopenharmony_ci    auto parent = dirRoot_;
2884514f5e3Sopenharmony_ci    do {
2894514f5e3Sopenharmony_ci        while (cur < rootName.size() && rootName[cur] == FILE_SEPARATOR_CHAR) {
2904514f5e3Sopenharmony_ci            cur++;
2914514f5e3Sopenharmony_ci        }
2924514f5e3Sopenharmony_ci        if (cur >= rootName.size()) {
2934514f5e3Sopenharmony_ci            break;
2944514f5e3Sopenharmony_ci        }
2954514f5e3Sopenharmony_ci        auto next = rootName.find_first_of(FILE_SEPARATOR_CHAR, cur);
2964514f5e3Sopenharmony_ci        auto nodeName = (next == std::string::npos) ? rootName.substr(cur) :
2974514f5e3Sopenharmony_ci            rootName.substr(cur, next - cur);
2984514f5e3Sopenharmony_ci        auto it = parent->children.find(nodeName);
2994514f5e3Sopenharmony_ci        if (it == parent->children.end()) {
3004514f5e3Sopenharmony_ci            return;
3014514f5e3Sopenharmony_ci        }
3024514f5e3Sopenharmony_ci        parent = it->second;
3034514f5e3Sopenharmony_ci        cur = next;
3044514f5e3Sopenharmony_ci    } while (cur != std::string::npos);
3054514f5e3Sopenharmony_ci
3064514f5e3Sopenharmony_ci    GetTreeFileList(parent, rootName, assetList);
3074514f5e3Sopenharmony_ci}
3084514f5e3Sopenharmony_ci
3094514f5e3Sopenharmony_civoid ZipFile::GetChildNames(const std::string &srcPath, std::set<std::string> &fileSet)
3104514f5e3Sopenharmony_ci{
3114514f5e3Sopenharmony_ci    if (srcPath.empty()) {
3124514f5e3Sopenharmony_ci        return;
3134514f5e3Sopenharmony_ci    }
3144514f5e3Sopenharmony_ci
3154514f5e3Sopenharmony_ci    size_t cur = 0;
3164514f5e3Sopenharmony_ci    auto parent = dirRoot_;
3174514f5e3Sopenharmony_ci    do {
3184514f5e3Sopenharmony_ci        while (cur < srcPath.size() && srcPath[cur] == FILE_SEPARATOR_CHAR) {
3194514f5e3Sopenharmony_ci            cur++;
3204514f5e3Sopenharmony_ci        }
3214514f5e3Sopenharmony_ci        if (cur >= srcPath.size()) {
3224514f5e3Sopenharmony_ci            break;
3234514f5e3Sopenharmony_ci        }
3244514f5e3Sopenharmony_ci        auto next = srcPath.find_first_of(FILE_SEPARATOR_CHAR, cur);
3254514f5e3Sopenharmony_ci        auto nodeName = srcPath.substr(cur, next - cur);
3264514f5e3Sopenharmony_ci        auto it = parent->children.find(nodeName);
3274514f5e3Sopenharmony_ci        if (it == parent->children.end()) {
3284514f5e3Sopenharmony_ci            return;
3294514f5e3Sopenharmony_ci        }
3304514f5e3Sopenharmony_ci        parent = it->second;
3314514f5e3Sopenharmony_ci        cur = next;
3324514f5e3Sopenharmony_ci    } while (cur != std::string::npos);
3334514f5e3Sopenharmony_ci
3344514f5e3Sopenharmony_ci    for (const auto &child : parent->children) {
3354514f5e3Sopenharmony_ci        fileSet.insert(child.first);
3364514f5e3Sopenharmony_ci    }
3374514f5e3Sopenharmony_ci}
3384514f5e3Sopenharmony_ci
3394514f5e3Sopenharmony_cibool ZipFile::GetEntry(const std::string &entryName, ZipEntry &resultEntry) const
3404514f5e3Sopenharmony_ci{
3414514f5e3Sopenharmony_ci    auto iter = entriesMap_.find(entryName);
3424514f5e3Sopenharmony_ci    if (iter != entriesMap_.end()) {
3434514f5e3Sopenharmony_ci        resultEntry = iter->second;
3444514f5e3Sopenharmony_ci        return true;
3454514f5e3Sopenharmony_ci    }
3464514f5e3Sopenharmony_ci    return false;
3474514f5e3Sopenharmony_ci}
3484514f5e3Sopenharmony_ci
3494514f5e3Sopenharmony_cisize_t ZipFile::GetLocalHeaderSize(const uint16_t nameSize, const uint16_t extraSize) const
3504514f5e3Sopenharmony_ci{
3514514f5e3Sopenharmony_ci    return sizeof(LocalHeader) + nameSize + extraSize;
3524514f5e3Sopenharmony_ci}
3534514f5e3Sopenharmony_ci
3544514f5e3Sopenharmony_cibool ZipFile::CheckDataDesc(const ZipEntry &zipEntry, const LocalHeader &localHeader) const
3554514f5e3Sopenharmony_ci{
3564514f5e3Sopenharmony_ci    uint32_t crcLocal = 0;
3574514f5e3Sopenharmony_ci    uint32_t compressedLocal = 0;
3584514f5e3Sopenharmony_ci    uint32_t uncompressedLocal = 0;
3594514f5e3Sopenharmony_ci
3604514f5e3Sopenharmony_ci    if (localHeader.flags & FLAG_DATA_DESC) {  // use data desc
3614514f5e3Sopenharmony_ci        DataDesc dataDesc;
3624514f5e3Sopenharmony_ci        auto descPos = zipEntry.localHeaderOffset + GetLocalHeaderSize(localHeader.nameSize, localHeader.extraSize);
3634514f5e3Sopenharmony_ci        descPos += fileStartPos_ + zipEntry.compressedSize;
3644514f5e3Sopenharmony_ci
3654514f5e3Sopenharmony_ci        if (!zipFileReader_->ReadBuffer(reinterpret_cast<uint8_t*>(&dataDesc), descPos, sizeof(DataDesc))) {
3664514f5e3Sopenharmony_ci            return false;
3674514f5e3Sopenharmony_ci        }
3684514f5e3Sopenharmony_ci
3694514f5e3Sopenharmony_ci        if (dataDesc.signature != DATA_DESC_SIGNATURE) {
3704514f5e3Sopenharmony_ci            return false;
3714514f5e3Sopenharmony_ci        }
3724514f5e3Sopenharmony_ci
3734514f5e3Sopenharmony_ci        crcLocal = dataDesc.crc;
3744514f5e3Sopenharmony_ci        compressedLocal = dataDesc.compressedSize;
3754514f5e3Sopenharmony_ci        uncompressedLocal = dataDesc.uncompressedSize;
3764514f5e3Sopenharmony_ci    } else {
3774514f5e3Sopenharmony_ci        crcLocal = localHeader.crc;
3784514f5e3Sopenharmony_ci        compressedLocal = localHeader.compressedSize;
3794514f5e3Sopenharmony_ci        uncompressedLocal = localHeader.uncompressedSize;
3804514f5e3Sopenharmony_ci    }
3814514f5e3Sopenharmony_ci
3824514f5e3Sopenharmony_ci    if ((zipEntry.crc != crcLocal) || (zipEntry.compressedSize != compressedLocal) ||
3834514f5e3Sopenharmony_ci        (zipEntry.uncompressedSize != uncompressedLocal)) {
3844514f5e3Sopenharmony_ci        return false;
3854514f5e3Sopenharmony_ci    }
3864514f5e3Sopenharmony_ci
3874514f5e3Sopenharmony_ci    return true;
3884514f5e3Sopenharmony_ci}
3894514f5e3Sopenharmony_ci
3904514f5e3Sopenharmony_cibool ZipFile::CheckCoherencyLocalHeader(const ZipEntry &zipEntry, uint16_t &extraSize) const
3914514f5e3Sopenharmony_ci{
3924514f5e3Sopenharmony_ci    // current only support store and Z_DEFLATED method
3934514f5e3Sopenharmony_ci    if ((zipEntry.compressionMethod != Z_DEFLATED) && (zipEntry.compressionMethod != 0)) {
3944514f5e3Sopenharmony_ci        return false;
3954514f5e3Sopenharmony_ci    }
3964514f5e3Sopenharmony_ci
3974514f5e3Sopenharmony_ci    auto nameSize = zipEntry.fileName.length();
3984514f5e3Sopenharmony_ci    auto startPos = fileStartPos_ + zipEntry.localHeaderOffset;
3994514f5e3Sopenharmony_ci    size_t buffSize = sizeof(LocalHeader) + nameSize;
4004514f5e3Sopenharmony_ci    auto buff = zipFileReader_->ReadBuffer(startPos, buffSize);
4014514f5e3Sopenharmony_ci    if (buff.size() < buffSize) {
4024514f5e3Sopenharmony_ci        return false;
4034514f5e3Sopenharmony_ci    }
4044514f5e3Sopenharmony_ci
4054514f5e3Sopenharmony_ci    LocalHeader localHeader = {0};
4064514f5e3Sopenharmony_ci    if (memcpy_s(&localHeader, sizeof(LocalHeader), buff.data(), sizeof(LocalHeader)) != EOK) {
4074514f5e3Sopenharmony_ci        return false;
4084514f5e3Sopenharmony_ci    }
4094514f5e3Sopenharmony_ci    if ((localHeader.signature != LOCAL_HEADER_SIGNATURE) ||
4104514f5e3Sopenharmony_ci        (zipEntry.compressionMethod != localHeader.compressionMethod)) {
4114514f5e3Sopenharmony_ci        return false;
4124514f5e3Sopenharmony_ci    }
4134514f5e3Sopenharmony_ci
4144514f5e3Sopenharmony_ci    if (localHeader.nameSize != nameSize && nameSize < MAX_FILE_NAME - 1) {
4154514f5e3Sopenharmony_ci        return false;
4164514f5e3Sopenharmony_ci    }
4174514f5e3Sopenharmony_ci    std::string fileName = buff.substr(sizeof(LocalHeader));
4184514f5e3Sopenharmony_ci    if (zipEntry.fileName != fileName) {
4194514f5e3Sopenharmony_ci        return false;
4204514f5e3Sopenharmony_ci    }
4214514f5e3Sopenharmony_ci
4224514f5e3Sopenharmony_ci    if (!CheckDataDesc(zipEntry, localHeader)) {
4234514f5e3Sopenharmony_ci        return false;
4244514f5e3Sopenharmony_ci    }
4254514f5e3Sopenharmony_ci
4264514f5e3Sopenharmony_ci    extraSize = localHeader.extraSize;
4274514f5e3Sopenharmony_ci    return true;
4284514f5e3Sopenharmony_ci}
4294514f5e3Sopenharmony_ci
4304514f5e3Sopenharmony_cisize_t ZipFile::GetEntryStart(const ZipEntry &zipEntry, const uint16_t extraSize) const
4314514f5e3Sopenharmony_ci{
4324514f5e3Sopenharmony_ci    ZipPos startOffset = zipEntry.localHeaderOffset;
4334514f5e3Sopenharmony_ci    // get data offset, add signature+localheader+namesize+extrasize
4344514f5e3Sopenharmony_ci    startOffset += GetLocalHeaderSize(zipEntry.fileName.length(), extraSize);
4354514f5e3Sopenharmony_ci    startOffset += fileStartPos_;  // add file start relative to file stream
4364514f5e3Sopenharmony_ci
4374514f5e3Sopenharmony_ci    return startOffset;
4384514f5e3Sopenharmony_ci}
4394514f5e3Sopenharmony_ci
4404514f5e3Sopenharmony_cibool ZipFile::UnzipWithStore(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const
4414514f5e3Sopenharmony_ci{
4424514f5e3Sopenharmony_ci    auto startPos = GetEntryStart(zipEntry, extraSize);
4434514f5e3Sopenharmony_ci    uint32_t remainSize = zipEntry.compressedSize;
4444514f5e3Sopenharmony_ci    while (remainSize > 0) {
4454514f5e3Sopenharmony_ci        size_t readLen = (remainSize > UNZIP_BUF_OUT_LEN) ? UNZIP_BUF_OUT_LEN : remainSize;
4464514f5e3Sopenharmony_ci        std::string readBuffer = zipFileReader_->ReadBuffer(startPos, readLen);
4474514f5e3Sopenharmony_ci        if (readBuffer.empty()) {
4484514f5e3Sopenharmony_ci            return false;
4494514f5e3Sopenharmony_ci        }
4504514f5e3Sopenharmony_ci        remainSize -= readLen;
4514514f5e3Sopenharmony_ci        startPos += readLen;
4524514f5e3Sopenharmony_ci        dest.write(readBuffer.data(), readBuffer.length());
4534514f5e3Sopenharmony_ci    }
4544514f5e3Sopenharmony_ci    return true;
4554514f5e3Sopenharmony_ci}
4564514f5e3Sopenharmony_ci
4574514f5e3Sopenharmony_cibool ZipFile::InitZStream(z_stream &zstream) const
4584514f5e3Sopenharmony_ci{
4594514f5e3Sopenharmony_ci    // init zlib stream
4604514f5e3Sopenharmony_ci    if (memset_s(&zstream, sizeof(z_stream), 0, sizeof(z_stream))) {
4614514f5e3Sopenharmony_ci        return false;
4624514f5e3Sopenharmony_ci    }
4634514f5e3Sopenharmony_ci    int32_t zlibErr = inflateInit2(&zstream, -MAX_WBITS);
4644514f5e3Sopenharmony_ci    if (zlibErr != Z_OK) {
4654514f5e3Sopenharmony_ci        return false;
4664514f5e3Sopenharmony_ci    }
4674514f5e3Sopenharmony_ci
4684514f5e3Sopenharmony_ci    BytePtr bufOut = new (std::nothrow) Byte[UNZIP_BUF_OUT_LEN];
4694514f5e3Sopenharmony_ci    if (bufOut == nullptr) {
4704514f5e3Sopenharmony_ci        return false;
4714514f5e3Sopenharmony_ci    }
4724514f5e3Sopenharmony_ci
4734514f5e3Sopenharmony_ci    BytePtr bufIn = new (std::nothrow) Byte[UNZIP_BUF_IN_LEN];
4744514f5e3Sopenharmony_ci    if (bufIn == nullptr) {
4754514f5e3Sopenharmony_ci        delete[] bufOut;
4764514f5e3Sopenharmony_ci        return false;
4774514f5e3Sopenharmony_ci    }
4784514f5e3Sopenharmony_ci    zstream.next_out = bufOut;
4794514f5e3Sopenharmony_ci    zstream.next_in = bufIn;
4804514f5e3Sopenharmony_ci    zstream.avail_out = UNZIP_BUF_OUT_LEN;
4814514f5e3Sopenharmony_ci    return true;
4824514f5e3Sopenharmony_ci}
4834514f5e3Sopenharmony_ci
4844514f5e3Sopenharmony_cibool ZipFile::ReadZStream(const BytePtr &buffer, z_stream &zstream, uint32_t &remainCompressedSize,
4854514f5e3Sopenharmony_ci    size_t &startPos) const
4864514f5e3Sopenharmony_ci{
4874514f5e3Sopenharmony_ci    if (zstream.avail_in == 0) {
4884514f5e3Sopenharmony_ci        size_t remainBytes = (remainCompressedSize > UNZIP_BUF_IN_LEN) ? UNZIP_BUF_IN_LEN : remainCompressedSize;
4894514f5e3Sopenharmony_ci        if (!zipFileReader_->ReadBuffer(buffer, startPos, remainBytes)) {
4904514f5e3Sopenharmony_ci            return false;
4914514f5e3Sopenharmony_ci        }
4924514f5e3Sopenharmony_ci
4934514f5e3Sopenharmony_ci        remainCompressedSize -= remainBytes;
4944514f5e3Sopenharmony_ci        startPos += remainBytes;
4954514f5e3Sopenharmony_ci        zstream.avail_in = remainBytes;
4964514f5e3Sopenharmony_ci        zstream.next_in = buffer;
4974514f5e3Sopenharmony_ci    }
4984514f5e3Sopenharmony_ci    return true;
4994514f5e3Sopenharmony_ci}
5004514f5e3Sopenharmony_ci
5014514f5e3Sopenharmony_cibool ZipFile::UnzipWithInflated(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const
5024514f5e3Sopenharmony_ci{
5034514f5e3Sopenharmony_ci    z_stream zstream;
5044514f5e3Sopenharmony_ci    if (!InitZStream(zstream)) {
5054514f5e3Sopenharmony_ci        return false;
5064514f5e3Sopenharmony_ci    }
5074514f5e3Sopenharmony_ci
5084514f5e3Sopenharmony_ci    auto startPos = GetEntryStart(zipEntry, extraSize);
5094514f5e3Sopenharmony_ci
5104514f5e3Sopenharmony_ci    BytePtr bufIn = zstream.next_in;
5114514f5e3Sopenharmony_ci    BytePtr bufOut = zstream.next_out;
5124514f5e3Sopenharmony_ci
5134514f5e3Sopenharmony_ci    bool ret = true;
5144514f5e3Sopenharmony_ci    int32_t zlibErr = Z_OK;
5154514f5e3Sopenharmony_ci    uint32_t remainCompressedSize = zipEntry.compressedSize;
5164514f5e3Sopenharmony_ci    size_t inflateLen = 0;
5174514f5e3Sopenharmony_ci    uint8_t errorTimes = 0;
5184514f5e3Sopenharmony_ci    while ((remainCompressedSize > 0) || (zstream.avail_in > 0)) {
5194514f5e3Sopenharmony_ci        if (!ReadZStream(bufIn, zstream, remainCompressedSize, startPos)) {
5204514f5e3Sopenharmony_ci            ret = false;
5214514f5e3Sopenharmony_ci            break;
5224514f5e3Sopenharmony_ci        }
5234514f5e3Sopenharmony_ci
5244514f5e3Sopenharmony_ci        zlibErr = inflate(&zstream, Z_SYNC_FLUSH);
5254514f5e3Sopenharmony_ci        if ((zlibErr >= Z_OK) && (zstream.msg != nullptr)) {
5264514f5e3Sopenharmony_ci            ret = false;
5274514f5e3Sopenharmony_ci            break;
5284514f5e3Sopenharmony_ci        }
5294514f5e3Sopenharmony_ci
5304514f5e3Sopenharmony_ci        inflateLen = UNZIP_BUF_OUT_LEN - zstream.avail_out;
5314514f5e3Sopenharmony_ci        if (inflateLen > 0) {
5324514f5e3Sopenharmony_ci            dest.write((const char *)bufOut, inflateLen);
5334514f5e3Sopenharmony_ci            zstream.next_out = bufOut;
5344514f5e3Sopenharmony_ci            zstream.avail_out = UNZIP_BUF_OUT_LEN;
5354514f5e3Sopenharmony_ci            errorTimes = 0;
5364514f5e3Sopenharmony_ci        } else {
5374514f5e3Sopenharmony_ci            errorTimes++;
5384514f5e3Sopenharmony_ci        }
5394514f5e3Sopenharmony_ci        if (errorTimes >= INFLATE_ERROR_TIMES) {
5404514f5e3Sopenharmony_ci            ret = false;
5414514f5e3Sopenharmony_ci            break;
5424514f5e3Sopenharmony_ci        }
5434514f5e3Sopenharmony_ci    }
5444514f5e3Sopenharmony_ci
5454514f5e3Sopenharmony_ci    // free all dynamically allocated data structures except the next_in and next_out for this stream.
5464514f5e3Sopenharmony_ci    zlibErr = inflateEnd(&zstream);
5474514f5e3Sopenharmony_ci    if (zlibErr != Z_OK) {
5484514f5e3Sopenharmony_ci        ret = false;
5494514f5e3Sopenharmony_ci    }
5504514f5e3Sopenharmony_ci
5514514f5e3Sopenharmony_ci    delete[] bufOut;
5524514f5e3Sopenharmony_ci    delete[] bufIn;
5534514f5e3Sopenharmony_ci    return ret;
5544514f5e3Sopenharmony_ci}
5554514f5e3Sopenharmony_ci
5564514f5e3Sopenharmony_ciZipPos ZipFile::GetEntryDataOffset(const ZipEntry &zipEntry, const uint16_t extraSize) const
5574514f5e3Sopenharmony_ci{
5584514f5e3Sopenharmony_ci    // get entry data offset relative file
5594514f5e3Sopenharmony_ci    ZipPos offset = zipEntry.localHeaderOffset;
5604514f5e3Sopenharmony_ci
5614514f5e3Sopenharmony_ci    offset += GetLocalHeaderSize(zipEntry.fileName.length(), extraSize);
5624514f5e3Sopenharmony_ci    offset += fileStartPos_;
5634514f5e3Sopenharmony_ci
5644514f5e3Sopenharmony_ci    return offset;
5654514f5e3Sopenharmony_ci}
5664514f5e3Sopenharmony_ci
5674514f5e3Sopenharmony_cibool ZipFile::GetDataOffsetRelative(const std::string &file, ZipPos &offset, uint32_t &length) const
5684514f5e3Sopenharmony_ci{
5694514f5e3Sopenharmony_ci    ZipEntry zipEntry;
5704514f5e3Sopenharmony_ci    if (!GetEntry(file, zipEntry)) {
5714514f5e3Sopenharmony_ci        return false;
5724514f5e3Sopenharmony_ci    }
5734514f5e3Sopenharmony_ci
5744514f5e3Sopenharmony_ci    return GetDataOffsetRelative(zipEntry, offset, length);
5754514f5e3Sopenharmony_ci}
5764514f5e3Sopenharmony_ci
5774514f5e3Sopenharmony_cibool ZipFile::GetDataOffsetRelative(const ZipEntry &zipEntry, ZipPos &offset, uint32_t &length) const
5784514f5e3Sopenharmony_ci{
5794514f5e3Sopenharmony_ci    uint16_t extraSize = 0;
5804514f5e3Sopenharmony_ci    if (!CheckCoherencyLocalHeader(zipEntry, extraSize)) {
5814514f5e3Sopenharmony_ci        return false;
5824514f5e3Sopenharmony_ci    }
5834514f5e3Sopenharmony_ci
5844514f5e3Sopenharmony_ci    offset = GetEntryDataOffset(zipEntry, extraSize);
5854514f5e3Sopenharmony_ci    length = zipEntry.compressedSize;
5864514f5e3Sopenharmony_ci    return true;
5874514f5e3Sopenharmony_ci}
5884514f5e3Sopenharmony_ci
5894514f5e3Sopenharmony_cibool ZipFile::ExtractFile(const std::string &file, std::ostream &dest) const
5904514f5e3Sopenharmony_ci{
5914514f5e3Sopenharmony_ci    ZipEntry zipEntry;
5924514f5e3Sopenharmony_ci    if (!GetEntry(file, zipEntry)) {
5934514f5e3Sopenharmony_ci        return false;
5944514f5e3Sopenharmony_ci    }
5954514f5e3Sopenharmony_ci
5964514f5e3Sopenharmony_ci    uint16_t extraSize = 0;
5974514f5e3Sopenharmony_ci    if (!CheckCoherencyLocalHeader(zipEntry, extraSize)) {
5984514f5e3Sopenharmony_ci        return false;
5994514f5e3Sopenharmony_ci    }
6004514f5e3Sopenharmony_ci
6014514f5e3Sopenharmony_ci    bool ret = true;
6024514f5e3Sopenharmony_ci    if (zipEntry.compressionMethod == 0) {
6034514f5e3Sopenharmony_ci        ret = UnzipWithStore(zipEntry, extraSize, dest);
6044514f5e3Sopenharmony_ci    } else {
6054514f5e3Sopenharmony_ci        ret = UnzipWithInflated(zipEntry, extraSize, dest);
6064514f5e3Sopenharmony_ci    }
6074514f5e3Sopenharmony_ci
6084514f5e3Sopenharmony_ci    return ret;
6094514f5e3Sopenharmony_ci}
6104514f5e3Sopenharmony_ci
6114514f5e3Sopenharmony_cibool ZipFile::ReadZStreamFromMMap(const BytePtr &buffer, void* &dataPtr,
6124514f5e3Sopenharmony_ci    z_stream &zstream, uint32_t &remainCompressedSize) const
6134514f5e3Sopenharmony_ci{
6144514f5e3Sopenharmony_ci    if (!dataPtr) {
6154514f5e3Sopenharmony_ci        return false;
6164514f5e3Sopenharmony_ci    }
6174514f5e3Sopenharmony_ci
6184514f5e3Sopenharmony_ci    uint8_t *srcDataPtr = static_cast<uint8_t *>(dataPtr);
6194514f5e3Sopenharmony_ci    if (zstream.avail_in == 0) {
6204514f5e3Sopenharmony_ci        size_t remainBytes = (remainCompressedSize > UNZIP_BUF_IN_LEN) ? UNZIP_BUF_IN_LEN : remainCompressedSize;
6214514f5e3Sopenharmony_ci        size_t readBytes = sizeof(Byte) * remainBytes;
6224514f5e3Sopenharmony_ci        if (memcpy_s(buffer, readBytes, srcDataPtr, readBytes) != EOK) {
6234514f5e3Sopenharmony_ci            return false;
6244514f5e3Sopenharmony_ci        }
6254514f5e3Sopenharmony_ci        srcDataPtr += readBytes;
6264514f5e3Sopenharmony_ci        remainCompressedSize -= remainBytes;
6274514f5e3Sopenharmony_ci        zstream.avail_in = remainBytes;
6284514f5e3Sopenharmony_ci        zstream.next_in = buffer;
6294514f5e3Sopenharmony_ci    }
6304514f5e3Sopenharmony_ci    dataPtr = srcDataPtr;
6314514f5e3Sopenharmony_ci    return true;
6324514f5e3Sopenharmony_ci}
6334514f5e3Sopenharmony_ci
6344514f5e3Sopenharmony_cistd::unique_ptr<FileMapper> ZipFile::CreateFileMapper(const std::string &fileName, FileMapperType type) const
6354514f5e3Sopenharmony_ci{
6364514f5e3Sopenharmony_ci    ZipEntry zipEntry;
6374514f5e3Sopenharmony_ci    if (!GetEntry(fileName, zipEntry)) {
6384514f5e3Sopenharmony_ci        return nullptr;
6394514f5e3Sopenharmony_ci    }
6404514f5e3Sopenharmony_ci
6414514f5e3Sopenharmony_ci    ZipPos offset = 0;
6424514f5e3Sopenharmony_ci    uint32_t length = 0;
6434514f5e3Sopenharmony_ci    if (!GetDataOffsetRelative(zipEntry, offset, length)) {
6444514f5e3Sopenharmony_ci        return nullptr;
6454514f5e3Sopenharmony_ci    }
6464514f5e3Sopenharmony_ci    bool compress = zipEntry.compressionMethod > 0;
6474514f5e3Sopenharmony_ci    if (type == FileMapperType::SAFE_ABC && compress) {
6484514f5e3Sopenharmony_ci    }
6494514f5e3Sopenharmony_ci    std::unique_ptr<FileMapper> fileMapper = std::make_unique<FileMapper>();
6504514f5e3Sopenharmony_ci    auto result = false;
6514514f5e3Sopenharmony_ci    if (type == FileMapperType::NORMAL_MEM) {
6524514f5e3Sopenharmony_ci        result = fileMapper->CreateFileMapper(zipFileReader_, fileName, offset, length, compress);
6534514f5e3Sopenharmony_ci    } else {
6544514f5e3Sopenharmony_ci        result = fileMapper->CreateFileMapper(fileName, compress, zipFileReader_->GetFd(), offset, length, type);
6554514f5e3Sopenharmony_ci        if (result && type == FileMapperType::SAFE_ABC) {
6564514f5e3Sopenharmony_ci            zipFileReader_->SetClosable(false);
6574514f5e3Sopenharmony_ci        }
6584514f5e3Sopenharmony_ci    }
6594514f5e3Sopenharmony_ci
6604514f5e3Sopenharmony_ci    if (!result) {
6614514f5e3Sopenharmony_ci        return nullptr;
6624514f5e3Sopenharmony_ci    }
6634514f5e3Sopenharmony_ci    return fileMapper;
6644514f5e3Sopenharmony_ci}
6654514f5e3Sopenharmony_ci
6664514f5e3Sopenharmony_cibool ZipFile::UnzipWithInflatedFromMMap(const ZipEntry &zipEntry, [[maybe_unused]] const uint16_t extraSize,
6674514f5e3Sopenharmony_ci    void *mmapDataPtr, std::unique_ptr<uint8_t[]> &dataPtr, size_t &len) const
6684514f5e3Sopenharmony_ci{
6694514f5e3Sopenharmony_ci    z_stream zstream;
6704514f5e3Sopenharmony_ci    if (!InitZStream(zstream)) {
6714514f5e3Sopenharmony_ci        return false;
6724514f5e3Sopenharmony_ci    }
6734514f5e3Sopenharmony_ci
6744514f5e3Sopenharmony_ci    BytePtr bufIn = zstream.next_in;
6754514f5e3Sopenharmony_ci    BytePtr bufOut = zstream.next_out;
6764514f5e3Sopenharmony_ci
6774514f5e3Sopenharmony_ci    bool ret = true;
6784514f5e3Sopenharmony_ci    int32_t zlibErr = Z_OK;
6794514f5e3Sopenharmony_ci    uint32_t remainCompressedSize = zipEntry.compressedSize;
6804514f5e3Sopenharmony_ci    size_t inflateLen = 0;
6814514f5e3Sopenharmony_ci    uint8_t errorTimes = 0;
6824514f5e3Sopenharmony_ci
6834514f5e3Sopenharmony_ci    len = zipEntry.uncompressedSize;
6844514f5e3Sopenharmony_ci    dataPtr = std::make_unique<uint8_t[]>(len);
6854514f5e3Sopenharmony_ci    if (!dataPtr) {
6864514f5e3Sopenharmony_ci        delete[] bufOut;
6874514f5e3Sopenharmony_ci        delete[] bufIn;
6884514f5e3Sopenharmony_ci        return false;
6894514f5e3Sopenharmony_ci    }
6904514f5e3Sopenharmony_ci    uint8_t *dstDataPtr = static_cast<uint8_t *>(dataPtr.get());
6914514f5e3Sopenharmony_ci    void *mmapSrcDataPtr = mmapDataPtr;
6924514f5e3Sopenharmony_ci
6934514f5e3Sopenharmony_ci    while ((remainCompressedSize > 0) || (zstream.avail_in > 0)) {
6944514f5e3Sopenharmony_ci        if (!ReadZStreamFromMMap(bufIn, mmapSrcDataPtr, zstream, remainCompressedSize)) {
6954514f5e3Sopenharmony_ci            ret = false;
6964514f5e3Sopenharmony_ci            break;
6974514f5e3Sopenharmony_ci        }
6984514f5e3Sopenharmony_ci
6994514f5e3Sopenharmony_ci        zlibErr = inflate(&zstream, Z_SYNC_FLUSH);
7004514f5e3Sopenharmony_ci        if ((zlibErr >= Z_OK) && (zstream.msg != nullptr)) {
7014514f5e3Sopenharmony_ci            ret = false;
7024514f5e3Sopenharmony_ci            break;
7034514f5e3Sopenharmony_ci        }
7044514f5e3Sopenharmony_ci
7054514f5e3Sopenharmony_ci        inflateLen = UNZIP_BUF_OUT_LEN - zstream.avail_out;
7064514f5e3Sopenharmony_ci        if (inflateLen > 0) {
7074514f5e3Sopenharmony_ci            if (memcpy_s(dstDataPtr, inflateLen, bufOut, inflateLen) != EOK) {
7084514f5e3Sopenharmony_ci                ret = false;
7094514f5e3Sopenharmony_ci                break;
7104514f5e3Sopenharmony_ci            }
7114514f5e3Sopenharmony_ci
7124514f5e3Sopenharmony_ci            dstDataPtr += inflateLen;
7134514f5e3Sopenharmony_ci            zstream.next_out = bufOut;
7144514f5e3Sopenharmony_ci            zstream.avail_out = UNZIP_BUF_OUT_LEN;
7154514f5e3Sopenharmony_ci            errorTimes = 0;
7164514f5e3Sopenharmony_ci        } else {
7174514f5e3Sopenharmony_ci            errorTimes++;
7184514f5e3Sopenharmony_ci        }
7194514f5e3Sopenharmony_ci        if (errorTimes >= INFLATE_ERROR_TIMES) {
7204514f5e3Sopenharmony_ci            ret = false;
7214514f5e3Sopenharmony_ci            break;
7224514f5e3Sopenharmony_ci        }
7234514f5e3Sopenharmony_ci    }
7244514f5e3Sopenharmony_ci
7254514f5e3Sopenharmony_ci    // free all dynamically allocated data structures except the next_in and next_out for this stream.
7264514f5e3Sopenharmony_ci    zlibErr = inflateEnd(&zstream);
7274514f5e3Sopenharmony_ci    if (zlibErr != Z_OK) {
7284514f5e3Sopenharmony_ci        ret = false;
7294514f5e3Sopenharmony_ci    }
7304514f5e3Sopenharmony_ci
7314514f5e3Sopenharmony_ci    delete[] bufOut;
7324514f5e3Sopenharmony_ci    delete[] bufIn;
7334514f5e3Sopenharmony_ci    return ret;
7344514f5e3Sopenharmony_ci}
7354514f5e3Sopenharmony_ci
7364514f5e3Sopenharmony_cibool ZipFile::ExtractToBufByName(const std::string &fileName, std::unique_ptr<uint8_t[]> &dataPtr,
7374514f5e3Sopenharmony_ci    size_t &len) const
7384514f5e3Sopenharmony_ci{
7394514f5e3Sopenharmony_ci    ZipEntry zipEntry;
7404514f5e3Sopenharmony_ci    if (!GetEntry(fileName, zipEntry)) {
7414514f5e3Sopenharmony_ci        return false;
7424514f5e3Sopenharmony_ci    }
7434514f5e3Sopenharmony_ci    uint16_t extraSize = 0;
7444514f5e3Sopenharmony_ci    if (!CheckCoherencyLocalHeader(zipEntry, extraSize)) {
7454514f5e3Sopenharmony_ci        return false;
7464514f5e3Sopenharmony_ci    }
7474514f5e3Sopenharmony_ci
7484514f5e3Sopenharmony_ci    ZipPos offset = GetEntryDataOffset(zipEntry, extraSize);
7494514f5e3Sopenharmony_ci    uint32_t length = zipEntry.compressedSize;
7504514f5e3Sopenharmony_ci    auto dataTmp = std::make_unique<uint8_t[]>(length);
7514514f5e3Sopenharmony_ci    if (!zipFileReader_->ReadBuffer(dataTmp.get(), offset, length)) {
7524514f5e3Sopenharmony_ci        dataTmp.reset();
7534514f5e3Sopenharmony_ci        return false;
7544514f5e3Sopenharmony_ci    }
7554514f5e3Sopenharmony_ci
7564514f5e3Sopenharmony_ci    if (zipEntry.compressionMethod > 0) {
7574514f5e3Sopenharmony_ci        return UnzipWithInflatedFromMMap(zipEntry, extraSize, dataTmp.get(), dataPtr, len);
7584514f5e3Sopenharmony_ci    }
7594514f5e3Sopenharmony_ci
7604514f5e3Sopenharmony_ci    len = length;
7614514f5e3Sopenharmony_ci    dataPtr = std::move(dataTmp);
7624514f5e3Sopenharmony_ci
7634514f5e3Sopenharmony_ci    return true;
7644514f5e3Sopenharmony_ci}
7654514f5e3Sopenharmony_ci}  // namespace AbilityBase
7664514f5e3Sopenharmony_ci}  // namespace OHOS
767