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 ¢ralEntry) 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