1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "base_extractor.h"
17 
18 #include <fstream>
19 
20 #include "app_log_wrapper.h"
21 #include "bundle_service_constants.h"
22 #include "string_ex.h"
23 
24 namespace OHOS {
25 namespace AppExecFwk {
26 namespace {
27 constexpr const char* MODULE_PROFILE_NAME = "module.json";
28 }
29 
BaseExtractor(const std::string & source)30 BaseExtractor::BaseExtractor(const std::string &source) : sourceFile_(source), zipFile_(source)
31 {
32     APP_LOGD("BaseExtractor instance is created");
33 }
34 
~BaseExtractor()35 BaseExtractor::~BaseExtractor()
36 {
37     APP_LOGD("BaseExtractor instance is destroyed");
38 }
39 
Init()40 bool BaseExtractor::Init()
41 {
42     if (!zipFile_.Open()) {
43         APP_LOGE("open zip file failed, errno:%{public}d", errno);
44         return false;
45     }
46     ZipEntry zipEntry;
47     isNewVersion_ = zipFile_.GetEntry(MODULE_PROFILE_NAME, zipEntry);
48     initial_ = true;
49     return true;
50 }
51 
HasEntry(const std::string & fileName) const52 bool BaseExtractor::HasEntry(const std::string &fileName) const
53 {
54     if (!initial_) {
55         APP_LOGE("extractor is not initial");
56         return false;
57     }
58 
59     return zipFile_.HasEntry(fileName);
60 }
61 
IsDirExist(const std::string & dir) const62 bool BaseExtractor::IsDirExist(const std::string &dir) const
63 {
64     if (!initial_) {
65         APP_LOGE("extractor is not initial");
66         return false;
67     }
68     if (dir.empty()) {
69         APP_LOGE("param dir empty");
70         return false;
71     }
72     return zipFile_.IsDirExist(dir);
73 }
74 
ExtractByName(const std::string & fileName,std::ostream & dest) const75 bool BaseExtractor::ExtractByName(const std::string &fileName, std::ostream &dest) const
76 {
77     if (!initial_) {
78         APP_LOGE("extractor is not initial");
79         return false;
80     }
81     if (!zipFile_.ExtractFile(fileName, dest)) {
82         APP_LOGE("extractor is not ExtractFile");
83         return false;
84     }
85     return true;
86 }
87 
ExtractFile(const std::string & fileName,const std::string & targetPath) const88 bool BaseExtractor::ExtractFile(const std::string &fileName, const std::string &targetPath) const
89 {
90     APP_LOGD("begin to extract %{public}s file into %{private}s targetPath", fileName.c_str(), targetPath.c_str());
91     std::ofstream fileStream;
92     fileStream.open(targetPath, std::ios_base::out | std::ios_base::binary);
93     if (!fileStream.is_open()) {
94         APP_LOGE("fail to open %{private}s file to write, errno:%{public}d", targetPath.c_str(), errno);
95         return false;
96     }
97     if ((!ExtractByName(fileName, fileStream)) || (!fileStream.good())) {
98         APP_LOGE("fail to extract %{public}s zip file into stream", fileName.c_str());
99         fileStream.clear();
100         fileStream.close();
101         if (remove(targetPath.c_str()) != 0) {
102             APP_LOGE("fail to remove %{private}s file which writes stream error, errno:%{public}d",
103                 targetPath.c_str(), errno);
104         }
105         return false;
106     }
107     fileStream.clear();
108     fileStream.close();
109     return true;
110 }
111 
GetZipFileNames(std::vector<std::string> & fileNames) const112 bool BaseExtractor::GetZipFileNames(std::vector<std::string> &fileNames) const
113 {
114     auto &entryMap = zipFile_.GetAllEntries();
115     auto entryFilter = [&fileNames](const auto &entry) {
116         auto position = entry.first.rfind(ServiceConstants::QUICK_FIX_FILE_SUFFIX);
117         bool isHqfFile = false;
118         if (position != std::string::npos) {
119             std::string suffixStr = entry.first.substr(position);
120             isHqfFile = suffixStr == ServiceConstants::QUICK_FIX_FILE_SUFFIX;
121         }
122         if ((entry.first.find(ServiceConstants::RELATIVE_PATH) == std::string::npos) && !isHqfFile) {
123             fileNames.emplace_back(entry.first);
124         }
125     };
126     for_each(entryMap.begin(), entryMap.end(), entryFilter);
127     return true;
128 }
129 
IsStageBasedModel(std::string abilityName)130 bool BaseExtractor::IsStageBasedModel(std::string abilityName)
131 {
132     auto &entryMap = zipFile_.GetAllEntries();
133     std::vector<std::string> splitStrs;
134     OHOS::SplitStr(abilityName, ".", splitStrs);
135     std::string name = splitStrs.empty() ? abilityName : splitStrs.back();
136     std::string entry = "assets/js/" + name + "/" + name + ".js";
137     bool isStageBasedModel = entryMap.find(entry) != entryMap.end();
138     APP_LOGI("name:%{public}s isStageBasedModel:%{public}d", abilityName.c_str(), isStageBasedModel);
139     return isStageBasedModel;
140 }
141 
IsNewVersion() const142 bool BaseExtractor::IsNewVersion() const
143 {
144     return isNewVersion_;
145 }
146 
GetFileInfo(const std::string & fileName,uint32_t & offset,uint32_t & length) const147 bool BaseExtractor::GetFileInfo(const std::string &fileName, uint32_t &offset, uint32_t &length) const
148 {
149     if (!initial_) {
150         APP_LOGE("extractor is not initial");
151         return false;
152     }
153     ZipPos tmpOffset = 0;
154     if (!zipFile_.GetDataOffsetRelative(fileName, tmpOffset, length)) {
155         APP_LOGE("GetDataOffsetRelative failed");
156         return false;
157     }
158     if (tmpOffset > std::numeric_limits<uint32_t>::max()) {
159         APP_LOGE("offset too large");
160         return false;
161     }
162     offset = static_cast<uint32_t>(tmpOffset);
163     return true;
164 }
165 }  // namespace AppExecFwk
166 }  // namespace OHOS
167