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 "ecmascript/platform/file.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     if (!panda::ecmascript::FileExist(targetPath.c_str())) {
114         return false;
115     }
116     std::ofstream fileStream;
117     fileStream.open(targetPath, std::ios_base::out | std::ios_base::binary);
118     if (!fileStream.is_open()) {
119         return false;
120     }
121     if ((!ExtractByName(fileName, fileStream)) || (!fileStream.good())) {
122         fileStream.clear();
123         fileStream.close();
124         if (remove(targetPath.c_str()) != 0) {
125         }
126         return false;
127     }
128     fileStream.clear();
129     fileStream.close();
130     return true;
131 }
132 
IsSameHap(const std::string& hapPath) const133 bool Extractor::IsSameHap(const std::string& hapPath) const
134 {
135     return !hapPath_.empty() && !hapPath.empty() && hapPath_ == hapPath;
136 }
137 
GetData(const std::string &fileName, bool) const138 std::unique_ptr<FileMapper> Extractor::GetData(const std::string &fileName, bool) const
139 {
140     std::string relativePath = GetRelativePath(fileName);
141     return zipFile_.CreateFileMapper(relativePath, FileMapperType::NORMAL_MEM);
142 }
143 
GetSafeData(const std::string &fileName)144 std::shared_ptr<FileMapper> Extractor::GetSafeData(const std::string &fileName)
145 {
146     std::string relativePath = GetRelativePath(fileName);
147     if (!StringEndWith(relativePath, EXT_NAME_ABC, sizeof(EXT_NAME_ABC) - 1)) {
148         return nullptr;
149     }
150 
151     return zipFile_.CreateFileMapper(relativePath, FileMapperType::SAFE_ABC);
152 }
153 
GetMmapData(const std::string &fileName)154 std::unique_ptr<FileMapper> Extractor::GetMmapData(const std::string &fileName)
155 {
156     std::string relativePath = GetRelativePath(fileName);
157     return zipFile_.CreateFileMapper(relativePath, FileMapperType::SHARED_MMAP);
158 }
159 
IsStageModel()160 bool Extractor::IsStageModel()
161 {
162     if (isStageModel_.has_value()) {
163         return isStageModel_.value();
164     }
165     isStageModel_ = !zipFile_.HasEntry("config.json");
166     return isStageModel_.value();
167 }
168 
ExtractToBufByName(const std::string &fileName, std::unique_ptr<uint8_t[]> &dataPtr, size_t &len)169 bool Extractor::ExtractToBufByName(const std::string &fileName, std::unique_ptr<uint8_t[]> &dataPtr,
170     size_t &len)
171 {
172     std::string relativePath = GetRelativePath(fileName);
173     return zipFile_.ExtractToBufByName(relativePath, dataPtr, len);
174 }
175 
GetFileInfo(const std::string &fileName, FileInfo &fileInfo) const176 bool Extractor::GetFileInfo(const std::string &fileName, FileInfo &fileInfo) const
177 {
178     std::string relativePath = GetRelativePath(fileName);
179     ZipEntry zipEntry;
180     if (!zipFile_.GetEntry(relativePath, zipEntry)) {
181         return false;
182     }
183 
184     ZipPos offset = 0;
185     uint32_t length = 0;
186     if (!zipFile_.GetDataOffsetRelative(relativePath, offset, length)) {
187         return false;
188     }
189 
190     fileInfo.fileName = fileName;
191     fileInfo.offset = static_cast<uint32_t>(offset);
192     fileInfo.length = static_cast<uint32_t>(length);
193     fileInfo.lastModTime = zipEntry.modifiedTime;
194     fileInfo.lastModDate = zipEntry.modifiedDate;
195     return true;
196 }
197 
GetFileList(const std::string &srcPath, std::set<std::string> &fileSet)198 bool Extractor::GetFileList(const std::string &srcPath, std::set<std::string> &fileSet)
199 {
200     if (!initial_) {
201         return false;
202     }
203 
204     if (srcPath.empty()) {
205         return false;
206     }
207 
208     zipFile_.GetChildNames(srcPath, fileSet);
209     if (fileSet.empty()) {
210     }
211 
212     return true;
213 }
214 
IsHapCompress(const std::string &fileName) const215 bool Extractor::IsHapCompress(const std::string &fileName) const
216 {
217     std::string relativePath = GetRelativePath(fileName);
218     ZipEntry zipEntry;
219     if (!zipFile_.GetEntry(relativePath, zipEntry)) {
220         return false;
221     }
222     return zipEntry.compressionMethod > 0;
223 }
224 
225 std::mutex ExtractorUtil::mapMutex_;
226 std::unordered_map<std::string, std::shared_ptr<Extractor>> ExtractorUtil::extractorMap_;
GetLoadFilePath(const std::string &hapPath)227 std::string ExtractorUtil::GetLoadFilePath(const std::string &hapPath)
228 {
229     std::string loadPath;
230     if (StringStartWith(hapPath, Constants::ABS_CODE_PATH, std::string(Constants::ABS_CODE_PATH).length())) {
231         loadPath = GetLoadPath(hapPath);
232     } else {
233         loadPath = hapPath;
234     }
235     return loadPath;
236 }
237 
GetExtractor(const std::string &hapPath, bool &newCreate, bool cache)238 std::shared_ptr<Extractor> ExtractorUtil::GetExtractor(const std::string &hapPath, bool &newCreate, bool cache)
239 {
240     newCreate = false;
241     if (hapPath.empty()) {
242         return nullptr;
243     }
244     {
245         std::lock_guard<std::mutex> mapMutex(mapMutex_);
246         auto mapIter = extractorMap_.find(hapPath);
247         if (mapIter != extractorMap_.end()) {
248             return mapIter->second;
249         }
250     }
251 
252     std::shared_ptr<Extractor> extractor = std::make_shared<Extractor>(hapPath);
253     if (!extractor->Init()) {
254         return nullptr;
255     }
256     if (cache) {
257         std::lock_guard<std::mutex> mapMutex(mapMutex_);
258         extractorMap_.emplace(hapPath, extractor);
259     }
260     newCreate = true;
261     return extractor;
262 }
263 
DeleteExtractor(const std::string &hapPath)264 void ExtractorUtil::DeleteExtractor(const std::string &hapPath)
265 {
266     if (hapPath.empty()) {
267         return;
268     }
269 
270     std::lock_guard<std::mutex> mapMutex(mapMutex_);
271     auto mapIter = extractorMap_.find(hapPath);
272     if (mapIter != extractorMap_.end()) {
273         extractorMap_.erase(mapIter);
274     }
275 }
276 }  // namespace AbilityBase
277 }  // namespace OHOS
278