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 "extractor.h"
174514f5e3Sopenharmony_ci
184514f5e3Sopenharmony_ci#include <fstream>
194514f5e3Sopenharmony_ci#include <sstream>
204514f5e3Sopenharmony_ci#include "constants.h"
214514f5e3Sopenharmony_ci#include "file_path_utils.h"
224514f5e3Sopenharmony_ci#include "ecmascript/platform/file.h"
234514f5e3Sopenharmony_ci
244514f5e3Sopenharmony_cinamespace panda {
254514f5e3Sopenharmony_cinamespace ecmascript {
264514f5e3Sopenharmony_cinamespace {
274514f5e3Sopenharmony_ciconstexpr char EXT_NAME_ABC[] = ".abc";
284514f5e3Sopenharmony_ci}
294514f5e3Sopenharmony_ciExtractor::Extractor(const std::string &source) : zipFile_(source)
304514f5e3Sopenharmony_ci{
314514f5e3Sopenharmony_ci    hapPath_ = source;
324514f5e3Sopenharmony_ci}
334514f5e3Sopenharmony_ci
344514f5e3Sopenharmony_ciExtractor::~Extractor()
354514f5e3Sopenharmony_ci{}
364514f5e3Sopenharmony_ci
374514f5e3Sopenharmony_cibool Extractor::Init()
384514f5e3Sopenharmony_ci{
394514f5e3Sopenharmony_ci    if (!zipFile_.Open()) {
404514f5e3Sopenharmony_ci        return false;
414514f5e3Sopenharmony_ci    }
424514f5e3Sopenharmony_ci    initial_ = true;
434514f5e3Sopenharmony_ci    return true;
444514f5e3Sopenharmony_ci}
454514f5e3Sopenharmony_ci
464514f5e3Sopenharmony_cibool Extractor::GetFileBuffer(const std::string& srcPath, std::ostringstream& dest)
474514f5e3Sopenharmony_ci{
484514f5e3Sopenharmony_ci    if (!initial_) {
494514f5e3Sopenharmony_ci        return false;
504514f5e3Sopenharmony_ci    }
514514f5e3Sopenharmony_ci
524514f5e3Sopenharmony_ci    if (srcPath.empty()) {
534514f5e3Sopenharmony_ci        return false;
544514f5e3Sopenharmony_ci    }
554514f5e3Sopenharmony_ci
564514f5e3Sopenharmony_ci    std::string relativePath = GetRelativePath(srcPath);
574514f5e3Sopenharmony_ci    if (!ExtractByName(relativePath, dest)) {
584514f5e3Sopenharmony_ci        return false;
594514f5e3Sopenharmony_ci    }
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_ci    return true;
624514f5e3Sopenharmony_ci}
634514f5e3Sopenharmony_ci
644514f5e3Sopenharmony_cibool Extractor::GetFileList(const std::string& srcPath, std::vector<std::string>& assetList)
654514f5e3Sopenharmony_ci{
664514f5e3Sopenharmony_ci    if (!initial_) {
674514f5e3Sopenharmony_ci        return false;
684514f5e3Sopenharmony_ci    }
694514f5e3Sopenharmony_ci
704514f5e3Sopenharmony_ci    if (srcPath.empty()) {
714514f5e3Sopenharmony_ci        return false;
724514f5e3Sopenharmony_ci    }
734514f5e3Sopenharmony_ci    zipFile_.GetAllFileList(srcPath, assetList);
744514f5e3Sopenharmony_ci    if (assetList.empty()) {
754514f5e3Sopenharmony_ci    }
764514f5e3Sopenharmony_ci
774514f5e3Sopenharmony_ci    return true;
784514f5e3Sopenharmony_ci}
794514f5e3Sopenharmony_ci
804514f5e3Sopenharmony_cibool Extractor::HasEntry(const std::string &fileName) const
814514f5e3Sopenharmony_ci{
824514f5e3Sopenharmony_ci    if (!initial_) {
834514f5e3Sopenharmony_ci        return false;
844514f5e3Sopenharmony_ci    }
854514f5e3Sopenharmony_ci
864514f5e3Sopenharmony_ci    return zipFile_.HasEntry(fileName);
874514f5e3Sopenharmony_ci}
884514f5e3Sopenharmony_ci
894514f5e3Sopenharmony_cibool Extractor::IsDirExist(const std::string &dir) const
904514f5e3Sopenharmony_ci{
914514f5e3Sopenharmony_ci    if (!initial_) {
924514f5e3Sopenharmony_ci        return false;
934514f5e3Sopenharmony_ci    }
944514f5e3Sopenharmony_ci    if (dir.empty()) {
954514f5e3Sopenharmony_ci        return false;
964514f5e3Sopenharmony_ci    }
974514f5e3Sopenharmony_ci    return zipFile_.IsDirExist(dir);
984514f5e3Sopenharmony_ci}
994514f5e3Sopenharmony_ci
1004514f5e3Sopenharmony_cibool Extractor::ExtractByName(const std::string &fileName, std::ostream &dest) const
1014514f5e3Sopenharmony_ci{
1024514f5e3Sopenharmony_ci    if (!initial_) {
1034514f5e3Sopenharmony_ci        return false;
1044514f5e3Sopenharmony_ci    }
1054514f5e3Sopenharmony_ci    if (!zipFile_.ExtractFile(fileName, dest)) {
1064514f5e3Sopenharmony_ci        return false;
1074514f5e3Sopenharmony_ci    }
1084514f5e3Sopenharmony_ci    return true;
1094514f5e3Sopenharmony_ci}
1104514f5e3Sopenharmony_ci
1114514f5e3Sopenharmony_cibool Extractor::ExtractFile(const std::string &fileName, const std::string &targetPath) const
1124514f5e3Sopenharmony_ci{
1134514f5e3Sopenharmony_ci    if (!panda::ecmascript::FileExist(targetPath.c_str())) {
1144514f5e3Sopenharmony_ci        return false;
1154514f5e3Sopenharmony_ci    }
1164514f5e3Sopenharmony_ci    std::ofstream fileStream;
1174514f5e3Sopenharmony_ci    fileStream.open(targetPath, std::ios_base::out | std::ios_base::binary);
1184514f5e3Sopenharmony_ci    if (!fileStream.is_open()) {
1194514f5e3Sopenharmony_ci        return false;
1204514f5e3Sopenharmony_ci    }
1214514f5e3Sopenharmony_ci    if ((!ExtractByName(fileName, fileStream)) || (!fileStream.good())) {
1224514f5e3Sopenharmony_ci        fileStream.clear();
1234514f5e3Sopenharmony_ci        fileStream.close();
1244514f5e3Sopenharmony_ci        if (remove(targetPath.c_str()) != 0) {
1254514f5e3Sopenharmony_ci        }
1264514f5e3Sopenharmony_ci        return false;
1274514f5e3Sopenharmony_ci    }
1284514f5e3Sopenharmony_ci    fileStream.clear();
1294514f5e3Sopenharmony_ci    fileStream.close();
1304514f5e3Sopenharmony_ci    return true;
1314514f5e3Sopenharmony_ci}
1324514f5e3Sopenharmony_ci
1334514f5e3Sopenharmony_cibool Extractor::IsSameHap(const std::string& hapPath) const
1344514f5e3Sopenharmony_ci{
1354514f5e3Sopenharmony_ci    return !hapPath_.empty() && !hapPath.empty() && hapPath_ == hapPath;
1364514f5e3Sopenharmony_ci}
1374514f5e3Sopenharmony_ci
1384514f5e3Sopenharmony_cistd::unique_ptr<FileMapper> Extractor::GetData(const std::string &fileName, bool) const
1394514f5e3Sopenharmony_ci{
1404514f5e3Sopenharmony_ci    std::string relativePath = GetRelativePath(fileName);
1414514f5e3Sopenharmony_ci    return zipFile_.CreateFileMapper(relativePath, FileMapperType::NORMAL_MEM);
1424514f5e3Sopenharmony_ci}
1434514f5e3Sopenharmony_ci
1444514f5e3Sopenharmony_cistd::shared_ptr<FileMapper> Extractor::GetSafeData(const std::string &fileName)
1454514f5e3Sopenharmony_ci{
1464514f5e3Sopenharmony_ci    std::string relativePath = GetRelativePath(fileName);
1474514f5e3Sopenharmony_ci    if (!StringEndWith(relativePath, EXT_NAME_ABC, sizeof(EXT_NAME_ABC) - 1)) {
1484514f5e3Sopenharmony_ci        return nullptr;
1494514f5e3Sopenharmony_ci    }
1504514f5e3Sopenharmony_ci
1514514f5e3Sopenharmony_ci    return zipFile_.CreateFileMapper(relativePath, FileMapperType::SAFE_ABC);
1524514f5e3Sopenharmony_ci}
1534514f5e3Sopenharmony_ci
1544514f5e3Sopenharmony_cistd::unique_ptr<FileMapper> Extractor::GetMmapData(const std::string &fileName)
1554514f5e3Sopenharmony_ci{
1564514f5e3Sopenharmony_ci    std::string relativePath = GetRelativePath(fileName);
1574514f5e3Sopenharmony_ci    return zipFile_.CreateFileMapper(relativePath, FileMapperType::SHARED_MMAP);
1584514f5e3Sopenharmony_ci}
1594514f5e3Sopenharmony_ci
1604514f5e3Sopenharmony_cibool Extractor::IsStageModel()
1614514f5e3Sopenharmony_ci{
1624514f5e3Sopenharmony_ci    if (isStageModel_.has_value()) {
1634514f5e3Sopenharmony_ci        return isStageModel_.value();
1644514f5e3Sopenharmony_ci    }
1654514f5e3Sopenharmony_ci    isStageModel_ = !zipFile_.HasEntry("config.json");
1664514f5e3Sopenharmony_ci    return isStageModel_.value();
1674514f5e3Sopenharmony_ci}
1684514f5e3Sopenharmony_ci
1694514f5e3Sopenharmony_cibool Extractor::ExtractToBufByName(const std::string &fileName, std::unique_ptr<uint8_t[]> &dataPtr,
1704514f5e3Sopenharmony_ci    size_t &len)
1714514f5e3Sopenharmony_ci{
1724514f5e3Sopenharmony_ci    std::string relativePath = GetRelativePath(fileName);
1734514f5e3Sopenharmony_ci    return zipFile_.ExtractToBufByName(relativePath, dataPtr, len);
1744514f5e3Sopenharmony_ci}
1754514f5e3Sopenharmony_ci
1764514f5e3Sopenharmony_cibool Extractor::GetFileInfo(const std::string &fileName, FileInfo &fileInfo) const
1774514f5e3Sopenharmony_ci{
1784514f5e3Sopenharmony_ci    std::string relativePath = GetRelativePath(fileName);
1794514f5e3Sopenharmony_ci    ZipEntry zipEntry;
1804514f5e3Sopenharmony_ci    if (!zipFile_.GetEntry(relativePath, zipEntry)) {
1814514f5e3Sopenharmony_ci        return false;
1824514f5e3Sopenharmony_ci    }
1834514f5e3Sopenharmony_ci
1844514f5e3Sopenharmony_ci    ZipPos offset = 0;
1854514f5e3Sopenharmony_ci    uint32_t length = 0;
1864514f5e3Sopenharmony_ci    if (!zipFile_.GetDataOffsetRelative(relativePath, offset, length)) {
1874514f5e3Sopenharmony_ci        return false;
1884514f5e3Sopenharmony_ci    }
1894514f5e3Sopenharmony_ci
1904514f5e3Sopenharmony_ci    fileInfo.fileName = fileName;
1914514f5e3Sopenharmony_ci    fileInfo.offset = static_cast<uint32_t>(offset);
1924514f5e3Sopenharmony_ci    fileInfo.length = static_cast<uint32_t>(length);
1934514f5e3Sopenharmony_ci    fileInfo.lastModTime = zipEntry.modifiedTime;
1944514f5e3Sopenharmony_ci    fileInfo.lastModDate = zipEntry.modifiedDate;
1954514f5e3Sopenharmony_ci    return true;
1964514f5e3Sopenharmony_ci}
1974514f5e3Sopenharmony_ci
1984514f5e3Sopenharmony_cibool Extractor::GetFileList(const std::string &srcPath, std::set<std::string> &fileSet)
1994514f5e3Sopenharmony_ci{
2004514f5e3Sopenharmony_ci    if (!initial_) {
2014514f5e3Sopenharmony_ci        return false;
2024514f5e3Sopenharmony_ci    }
2034514f5e3Sopenharmony_ci
2044514f5e3Sopenharmony_ci    if (srcPath.empty()) {
2054514f5e3Sopenharmony_ci        return false;
2064514f5e3Sopenharmony_ci    }
2074514f5e3Sopenharmony_ci
2084514f5e3Sopenharmony_ci    zipFile_.GetChildNames(srcPath, fileSet);
2094514f5e3Sopenharmony_ci    if (fileSet.empty()) {
2104514f5e3Sopenharmony_ci    }
2114514f5e3Sopenharmony_ci
2124514f5e3Sopenharmony_ci    return true;
2134514f5e3Sopenharmony_ci}
2144514f5e3Sopenharmony_ci
2154514f5e3Sopenharmony_cibool Extractor::IsHapCompress(const std::string &fileName) const
2164514f5e3Sopenharmony_ci{
2174514f5e3Sopenharmony_ci    std::string relativePath = GetRelativePath(fileName);
2184514f5e3Sopenharmony_ci    ZipEntry zipEntry;
2194514f5e3Sopenharmony_ci    if (!zipFile_.GetEntry(relativePath, zipEntry)) {
2204514f5e3Sopenharmony_ci        return false;
2214514f5e3Sopenharmony_ci    }
2224514f5e3Sopenharmony_ci    return zipEntry.compressionMethod > 0;
2234514f5e3Sopenharmony_ci}
2244514f5e3Sopenharmony_ci
2254514f5e3Sopenharmony_cistd::mutex ExtractorUtil::mapMutex_;
2264514f5e3Sopenharmony_cistd::unordered_map<std::string, std::shared_ptr<Extractor>> ExtractorUtil::extractorMap_;
2274514f5e3Sopenharmony_cistd::string ExtractorUtil::GetLoadFilePath(const std::string &hapPath)
2284514f5e3Sopenharmony_ci{
2294514f5e3Sopenharmony_ci    std::string loadPath;
2304514f5e3Sopenharmony_ci    if (StringStartWith(hapPath, Constants::ABS_CODE_PATH, std::string(Constants::ABS_CODE_PATH).length())) {
2314514f5e3Sopenharmony_ci        loadPath = GetLoadPath(hapPath);
2324514f5e3Sopenharmony_ci    } else {
2334514f5e3Sopenharmony_ci        loadPath = hapPath;
2344514f5e3Sopenharmony_ci    }
2354514f5e3Sopenharmony_ci    return loadPath;
2364514f5e3Sopenharmony_ci}
2374514f5e3Sopenharmony_ci
2384514f5e3Sopenharmony_cistd::shared_ptr<Extractor> ExtractorUtil::GetExtractor(const std::string &hapPath, bool &newCreate, bool cache)
2394514f5e3Sopenharmony_ci{
2404514f5e3Sopenharmony_ci    newCreate = false;
2414514f5e3Sopenharmony_ci    if (hapPath.empty()) {
2424514f5e3Sopenharmony_ci        return nullptr;
2434514f5e3Sopenharmony_ci    }
2444514f5e3Sopenharmony_ci    {
2454514f5e3Sopenharmony_ci        std::lock_guard<std::mutex> mapMutex(mapMutex_);
2464514f5e3Sopenharmony_ci        auto mapIter = extractorMap_.find(hapPath);
2474514f5e3Sopenharmony_ci        if (mapIter != extractorMap_.end()) {
2484514f5e3Sopenharmony_ci            return mapIter->second;
2494514f5e3Sopenharmony_ci        }
2504514f5e3Sopenharmony_ci    }
2514514f5e3Sopenharmony_ci
2524514f5e3Sopenharmony_ci    std::shared_ptr<Extractor> extractor = std::make_shared<Extractor>(hapPath);
2534514f5e3Sopenharmony_ci    if (!extractor->Init()) {
2544514f5e3Sopenharmony_ci        return nullptr;
2554514f5e3Sopenharmony_ci    }
2564514f5e3Sopenharmony_ci    if (cache) {
2574514f5e3Sopenharmony_ci        std::lock_guard<std::mutex> mapMutex(mapMutex_);
2584514f5e3Sopenharmony_ci        extractorMap_.emplace(hapPath, extractor);
2594514f5e3Sopenharmony_ci    }
2604514f5e3Sopenharmony_ci    newCreate = true;
2614514f5e3Sopenharmony_ci    return extractor;
2624514f5e3Sopenharmony_ci}
2634514f5e3Sopenharmony_ci
2644514f5e3Sopenharmony_civoid ExtractorUtil::DeleteExtractor(const std::string &hapPath)
2654514f5e3Sopenharmony_ci{
2664514f5e3Sopenharmony_ci    if (hapPath.empty()) {
2674514f5e3Sopenharmony_ci        return;
2684514f5e3Sopenharmony_ci    }
2694514f5e3Sopenharmony_ci
2704514f5e3Sopenharmony_ci    std::lock_guard<std::mutex> mapMutex(mapMutex_);
2714514f5e3Sopenharmony_ci    auto mapIter = extractorMap_.find(hapPath);
2724514f5e3Sopenharmony_ci    if (mapIter != extractorMap_.end()) {
2734514f5e3Sopenharmony_ci        extractorMap_.erase(mapIter);
2744514f5e3Sopenharmony_ci    }
2754514f5e3Sopenharmony_ci}
2764514f5e3Sopenharmony_ci}  // namespace AbilityBase
2774514f5e3Sopenharmony_ci}  // namespace OHOS
278