1 /*
2 * Copyright (c) 2023 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 "extractor.h"
17
18 #include "constants.h"
19 #include "file_path_utils.h"
20 #include "ecmascript/platform/file.h"
21
22 namespace panda {
23 namespace ecmascript {
24 namespace {
25 constexpr char EXT_NAME_ABC[] = ".abc";
26 }
Extractor(const std::string & source)27 Extractor::Extractor(const std::string &source) : zipFile_(source)
28 {
29 hapPath_ = source;
30 }
31
~Extractor()32 Extractor::~Extractor()
33 {}
34
Init()35 bool Extractor::Init()
36 {
37 if (!zipFile_.Open()) {
38 return false;
39 }
40 initial_ = true;
41 return true;
42 }
43
GetFileBuffer(const std::string & srcPath,std::ostringstream & dest)44 bool Extractor::GetFileBuffer(const std::string& srcPath, std::ostringstream& dest)
45 {
46 if (!initial_) {
47 return false;
48 }
49
50 if (srcPath.empty()) {
51 return false;
52 }
53
54 std::string relativePath = GetRelativePath(srcPath);
55 if (!ExtractByName(relativePath, dest)) {
56 return false;
57 }
58
59 return true;
60 }
61
GetFileList(const std::string & srcPath,std::vector<std::string> & assetList)62 bool Extractor::GetFileList(const std::string& srcPath, std::vector<std::string>& assetList)
63 {
64 if (!initial_) {
65 return false;
66 }
67
68 if (srcPath.empty()) {
69 return false;
70 }
71 zipFile_.GetAllFileList(srcPath, assetList);
72 if (assetList.empty()) {
73 }
74
75 return true;
76 }
77
HasEntry(const std::string & fileName) const78 bool Extractor::HasEntry(const std::string &fileName) const
79 {
80 if (!initial_) {
81 return false;
82 }
83
84 return zipFile_.HasEntry(fileName);
85 }
86
IsDirExist(const std::string & dir) const87 bool Extractor::IsDirExist(const std::string &dir) const
88 {
89 if (!initial_) {
90 return false;
91 }
92 if (dir.empty()) {
93 return false;
94 }
95 return zipFile_.IsDirExist(dir);
96 }
97
ExtractByName(const std::string & fileName,std::ostream & dest) const98 bool Extractor::ExtractByName(const std::string &fileName, std::ostream &dest) const
99 {
100 if (!initial_) {
101 return false;
102 }
103 if (!zipFile_.ExtractFile(fileName, dest)) {
104 return false;
105 }
106 return true;
107 }
108
ExtractFile(const std::string & fileName,const std::string & targetPath) const109 bool Extractor::ExtractFile(const std::string &fileName, const std::string &targetPath) const
110 {
111 if (!panda::ecmascript::FileExist(targetPath.c_str())) {
112 return false;
113 }
114 std::ofstream fileStream;
115 fileStream.open(targetPath, std::ios_base::out | std::ios_base::binary);
116 if (!fileStream.is_open()) {
117 return false;
118 }
119 if ((!ExtractByName(fileName, fileStream)) || (!fileStream.good())) {
120 fileStream.clear();
121 fileStream.close();
122 if (remove(targetPath.c_str()) != 0) {
123 }
124 return false;
125 }
126 fileStream.clear();
127 fileStream.close();
128 return true;
129 }
130
IsSameHap(const std::string & hapPath) const131 bool Extractor::IsSameHap(const std::string& hapPath) const
132 {
133 return !hapPath_.empty() && !hapPath.empty() && hapPath_ == hapPath;
134 }
135
GetData(const std::string & fileName,bool) const136 std::unique_ptr<FileMapper> Extractor::GetData(const std::string &fileName, bool) const
137 {
138 std::string relativePath = GetRelativePath(fileName);
139 return zipFile_.CreateFileMapper(relativePath, FileMapperType::NORMAL_MEM);
140 }
141
GetSafeData(const std::string & fileName)142 std::shared_ptr<FileMapper> Extractor::GetSafeData(const std::string &fileName)
143 {
144 std::string relativePath = GetRelativePath(fileName);
145 if (!StringEndWith(relativePath, EXT_NAME_ABC, sizeof(EXT_NAME_ABC) - 1)) {
146 return nullptr;
147 }
148
149 return zipFile_.CreateFileMapper(relativePath, FileMapperType::SAFE_ABC);
150 }
151
GetMmapData(const std::string & fileName)152 std::unique_ptr<FileMapper> Extractor::GetMmapData(const std::string &fileName)
153 {
154 std::string relativePath = GetRelativePath(fileName);
155 return zipFile_.CreateFileMapper(relativePath, FileMapperType::SHARED_MMAP);
156 }
157
IsStageModel()158 bool Extractor::IsStageModel()
159 {
160 if (isStageModel_.has_value()) {
161 return isStageModel_.value();
162 }
163 isStageModel_ = !zipFile_.HasEntry("config.json");
164 return isStageModel_.value();
165 }
166
ExtractToBufByName(const std::string & fileName,std::unique_ptr<uint8_t[]> & dataPtr,size_t & len)167 bool Extractor::ExtractToBufByName(const std::string &fileName, std::unique_ptr<uint8_t[]> &dataPtr,
168 size_t &len)
169 {
170 std::string relativePath = GetRelativePath(fileName);
171 return zipFile_.ExtractToBufByName(relativePath, dataPtr, len);
172 }
173
GetFileInfo(const std::string & fileName,FileInfo & fileInfo) const174 bool Extractor::GetFileInfo(const std::string &fileName, FileInfo &fileInfo) const
175 {
176 std::string relativePath = GetRelativePath(fileName);
177 ZipEntry zipEntry;
178 if (!zipFile_.GetEntry(relativePath, zipEntry)) {
179 return false;
180 }
181
182 ZipPos offset = 0;
183 uint32_t length = 0;
184 if (!zipFile_.GetDataOffsetRelative(relativePath, offset, length)) {
185 return false;
186 }
187
188 fileInfo.fileName = fileName;
189 fileInfo.offset = static_cast<uint32_t>(offset);
190 fileInfo.length = static_cast<uint32_t>(length);
191 fileInfo.lastModTime = zipEntry.modifiedTime;
192 fileInfo.lastModDate = zipEntry.modifiedDate;
193 return true;
194 }
195
GetFileList(const std::string & srcPath,std::set<std::string> & fileSet)196 bool Extractor::GetFileList(const std::string &srcPath, std::set<std::string> &fileSet)
197 {
198 if (!initial_) {
199 return false;
200 }
201
202 if (srcPath.empty()) {
203 return false;
204 }
205
206 zipFile_.GetChildNames(srcPath, fileSet);
207 if (fileSet.empty()) {
208 }
209
210 return true;
211 }
212
IsHapCompress(const std::string & fileName) const213 bool Extractor::IsHapCompress(const std::string &fileName) const
214 {
215 std::string relativePath = GetRelativePath(fileName);
216 ZipEntry zipEntry;
217 if (!zipFile_.GetEntry(relativePath, zipEntry)) {
218 return false;
219 }
220 return zipEntry.compressionMethod > 0;
221 }
222
223 std::mutex ExtractorUtil::mapMutex_;
224 std::unordered_map<std::string, std::shared_ptr<Extractor>> ExtractorUtil::extractorMap_;
GetLoadFilePath(const std::string & hapPath)225 std::string ExtractorUtil::GetLoadFilePath(const std::string &hapPath)
226 {
227 std::string loadPath;
228 if (StringStartWith(hapPath, Constants::ABS_CODE_PATH, std::string(Constants::ABS_CODE_PATH).length())) {
229 loadPath = GetLoadPath(hapPath);
230 } else {
231 loadPath = hapPath;
232 }
233 return loadPath;
234 }
235
GetExtractor(const std::string & hapPath,bool & newCreate,bool cache)236 std::shared_ptr<Extractor> ExtractorUtil::GetExtractor(const std::string &hapPath, bool &newCreate, bool cache)
237 {
238 newCreate = false;
239 if (hapPath.empty()) {
240 return nullptr;
241 }
242 {
243 std::lock_guard<std::mutex> mapMutex(mapMutex_);
244 auto mapIter = extractorMap_.find(hapPath);
245 if (mapIter != extractorMap_.end()) {
246 return mapIter->second;
247 }
248 }
249
250 std::shared_ptr<Extractor> extractor = std::make_shared<Extractor>(hapPath);
251 if (!extractor->Init()) {
252 return nullptr;
253 }
254 if (cache) {
255 std::lock_guard<std::mutex> mapMutex(mapMutex_);
256 extractorMap_.emplace(hapPath, extractor);
257 }
258 newCreate = true;
259 return extractor;
260 }
261
DeleteExtractor(const std::string & hapPath)262 void ExtractorUtil::DeleteExtractor(const std::string &hapPath)
263 {
264 if (hapPath.empty()) {
265 return;
266 }
267
268 std::lock_guard<std::mutex> mapMutex(mapMutex_);
269 auto mapIter = extractorMap_.find(hapPath);
270 if (mapIter != extractorMap_.end()) {
271 extractorMap_.erase(mapIter);
272 }
273 }
274 } // namespace AbilityBase
275 } // namespace OHOS
276