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