1 /*
2 * Copyright (c) 2022 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 "runtime_extractor.h"
17
18 #include <fstream>
19 #include <regex>
20 #include <sstream>
21
22 #include "ability_constants.h"
23 #include "file_path_utils.h"
24 #include "hilog_wrapper.h"
25 #include "string_ex.h"
26
27 namespace OHOS {
28 namespace AbilityRuntime {
RuntimeExtractor(const std::string & source)29 RuntimeExtractor::RuntimeExtractor(const std::string &source) : sourceFile_(source), zipFile_(source)
30 {
31 hapPath_ = source;
32 }
33
~RuntimeExtractor()34 RuntimeExtractor::~RuntimeExtractor()
35 {}
36
Init()37 bool RuntimeExtractor::Init()
38 {
39 if (!zipFile_.Open()) {
40 HILOG_ERROR("open zip file failed");
41 return false;
42 }
43 ZipEntry zipEntry;
44 initial_ = true;
45 return true;
46 }
47
Create(const std::string & hapPath)48 std::shared_ptr<RuntimeExtractor> RuntimeExtractor::Create(const std::string& hapPath)
49 {
50 if (hapPath.empty()) {
51 HILOG_ERROR("source is nullptr");
52 return nullptr;
53 }
54
55 std::string loadPath;
56 if (StringStartWith(hapPath, Constants::ABS_CODE_PATH, std::string(Constants::ABS_CODE_PATH).length())) {
57 loadPath = GetLoadPath(hapPath);
58 } else {
59 loadPath = hapPath;
60 }
61 std::shared_ptr<RuntimeExtractor> runtimeExtractor = std::make_shared<RuntimeExtractor>(loadPath);
62 if (!runtimeExtractor->Init()) {
63 HILOG_ERROR("RuntimeExtractor create failed for %{public}s", loadPath.c_str());
64 return nullptr;
65 }
66
67 return runtimeExtractor;
68 }
69
GetFileBuffer(const std::string & srcPath,std::ostringstream & dest)70 bool RuntimeExtractor::GetFileBuffer(const std::string& srcPath, std::ostringstream& dest)
71 {
72 if (!initial_) {
73 HILOG_ERROR("extractor is not initial");
74 return false;
75 }
76
77 if (srcPath.empty()) {
78 HILOG_ERROR("GetFileBuffer::srcPath is nullptr");
79 return false;
80 }
81
82 std::string relativePath = GetRelativePath(srcPath);
83 if (!ExtractByName(relativePath, dest)) {
84 HILOG_ERROR("GetFileBuffer::Extract file failed");
85 return false;
86 }
87
88 return true;
89 }
90
GetFileList(const std::string & srcPath,std::vector<std::string> & assetList)91 bool RuntimeExtractor::GetFileList(const std::string& srcPath, std::vector<std::string>& assetList)
92 {
93 if (!initial_) {
94 HILOG_ERROR("extractor is not initial");
95 return false;
96 }
97
98 if (srcPath.empty()) {
99 HILOG_ERROR("GetFileList::srcPath is nullptr");
100 return false;
101 }
102
103 std::vector<std::string> fileList;
104 if (!GetZipFileNames(fileList)) {
105 HILOG_ERROR("GetFileList::Get file list failed");
106 return false;
107 }
108
109 std::regex replacePattern(srcPath);
110 for (auto value : fileList) {
111 if (StringStartWith(value, srcPath.c_str(), srcPath.length())) {
112 assetList.emplace_back(value);
113 }
114 }
115
116 return true;
117 }
118
HasEntry(const std::string & fileName) const119 bool RuntimeExtractor::HasEntry(const std::string &fileName) const
120 {
121 if (!initial_) {
122 HILOG_ERROR("extractor is not initial");
123 return false;
124 }
125
126 return zipFile_.HasEntry(fileName);
127 }
128
IsDirExist(const std::string & dir) const129 bool RuntimeExtractor::IsDirExist(const std::string &dir) const
130 {
131 if (!initial_) {
132 HILOG_ERROR("extractor is not initial");
133 return false;
134 }
135 if (dir.empty()) {
136 HILOG_ERROR("param dir empty");
137 return false;
138 }
139 return zipFile_.IsDirExist(dir);
140 }
141
ExtractByName(const std::string & fileName,std::ostream & dest) const142 bool RuntimeExtractor::ExtractByName(const std::string &fileName, std::ostream &dest) const
143 {
144 if (!initial_) {
145 HILOG_ERROR("extractor is not initial");
146 return false;
147 }
148 if (!zipFile_.ExtractFile(fileName, dest)) {
149 HILOG_ERROR("extractor is not ExtractFile");
150 return false;
151 }
152 return true;
153 }
154
ExtractFile(const std::string & fileName,const std::string & targetPath) const155 bool RuntimeExtractor::ExtractFile(const std::string &fileName, const std::string &targetPath) const
156 {
157 std::ofstream fileStream;
158 fileStream.open(targetPath, std::ios_base::out | std::ios_base::binary);
159 if (!fileStream.is_open()) {
160 HILOG_ERROR("fail to open %{private}s file to write", targetPath.c_str());
161 return false;
162 }
163 if ((!ExtractByName(fileName, fileStream)) || (!fileStream.good())) {
164 HILOG_ERROR("fail to extract %{public}s zip file into stream", fileName.c_str());
165 fileStream.clear();
166 fileStream.close();
167 if (remove(targetPath.c_str()) != 0) {
168 HILOG_ERROR("fail to remove %{private}s file which writes stream error", targetPath.c_str());
169 }
170 return false;
171 }
172 fileStream.clear();
173 fileStream.close();
174 return true;
175 }
176
GetZipFileNames(std::vector<std::string> & fileNames)177 bool RuntimeExtractor::GetZipFileNames(std::vector<std::string> &fileNames)
178 {
179 auto &entryMap = zipFile_.GetAllEntries();
180 if (entryMap.empty()) {
181 HILOG_ERROR("Zip file is empty");
182 return false;
183 }
184
185 for (auto &entry : entryMap) {
186 fileNames.emplace_back(entry.first);
187 }
188 return true;
189 }
190
GetSpecifiedTypeFiles(std::vector<std::string> & fileNames,const std::string & suffix)191 void RuntimeExtractor::GetSpecifiedTypeFiles(std::vector<std::string> &fileNames, const std::string &suffix)
192 {
193 auto &entryMap = zipFile_.GetAllEntries();
194 for (const auto &entry : entryMap) {
195 std::string fileName = entry.first;
196 auto position = fileName.rfind('.');
197 if (position != std::string::npos) {
198 std::string suffixStr = fileName.substr(position);
199 if (LowerStr(suffixStr) == suffix) {
200 fileNames.emplace_back(fileName);
201 }
202 }
203 }
204 }
205
IsStageBasedModel(std::string abilityName)206 bool RuntimeExtractor::IsStageBasedModel(std::string abilityName)
207 {
208 auto &entryMap = zipFile_.GetAllEntries();
209 std::vector<std::string> splitStrs;
210 OHOS::SplitStr(abilityName, ".", splitStrs);
211 std::string name = splitStrs.empty() ? abilityName : splitStrs.back();
212 std::string entry = "assets/js/" + name + "/" + name + ".js";
213 bool isStageBasedModel = entryMap.find(entry) != entryMap.end();
214 return isStageBasedModel;
215 }
216
IsSameHap(const std::string & hapPath) const217 bool RuntimeExtractor::IsSameHap(const std::string& hapPath) const
218 {
219 return !hapPath_.empty() && !hapPath.empty() && hapPath_ == hapPath;
220 }
221
SetRuntimeFlag(bool isRuntime)222 void RuntimeExtractor::SetRuntimeFlag(bool isRuntime)
223 {
224 zipFile_.SetIsRuntime(isRuntime);
225 }
226 } // namespace AbilityRuntime
227 } // namespace OHOS
228