• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "extractor.h"
17 
18 #include <fstream>
19 #include <sstream>
20 #include "ability_base_log_wrapper.h"
21 #include "constants.h"
22 #include "file_path_utils.h"
23 #include "securec.h"
24 #include "string_ex.h"
25 
26 namespace OHOS {
27 namespace AbilityBase {
28 namespace {
29 constexpr char EXT_NAME_ABC[] = ".abc";
30 }
Extractor(const std::string & source)31 Extractor::Extractor(const std::string &source) : zipFile_(source)
32 {
33     hapPath_ = source;
34 }
35 
~Extractor()36 Extractor::~Extractor()
37 {}
38 
Init()39 bool Extractor::Init()
40 {
41     if (!zipFile_.Open()) {
42         ABILITYBASE_LOGE("open zip file failed");
43         return false;
44     }
45     initial_ = true;
46     return true;
47 }
48 
GetFileBuffer(const std::string & srcPath,std::ostringstream & dest)49 bool Extractor::GetFileBuffer(const std::string& srcPath, std::ostringstream& dest)
50 {
51     if (!initial_) {
52         ABILITYBASE_LOGE("extractor is not initial");
53         return false;
54     }
55 
56     if (srcPath.empty()) {
57         ABILITYBASE_LOGE("GetFileBuffer::srcPath is nullptr");
58         return false;
59     }
60 
61     std::string relativePath = GetRelativePath(srcPath);
62     if (!ExtractByName(relativePath, dest)) {
63         ABILITYBASE_LOGE("GetFileBuffer::Extract file failed");
64         return false;
65     }
66 
67     return true;
68 }
69 
GetFileList(const std::string & srcPath,std::vector<std::string> & assetList)70 bool Extractor::GetFileList(const std::string& srcPath, std::vector<std::string>& assetList)
71 {
72     if (!initial_) {
73         ABILITYBASE_LOGE("extractor is not initial");
74         return false;
75     }
76 
77     if (srcPath.empty()) {
78         ABILITYBASE_LOGE("GetFileList::srcPath is nullptr");
79         return false;
80     }
81     zipFile_.GetAllFileList(srcPath, assetList);
82     if (assetList.empty()) {
83         ABILITYBASE_LOGW("empty dir: %{public}s", srcPath.c_str());
84     }
85 
86     return true;
87 }
88 
HasEntry(const std::string & fileName) const89 bool Extractor::HasEntry(const std::string &fileName) const
90 {
91     if (!initial_) {
92         ABILITYBASE_LOGE("extractor is not initial");
93         return false;
94     }
95 
96     return zipFile_.HasEntry(fileName);
97 }
98 
IsDirExist(const std::string & dir) const99 bool Extractor::IsDirExist(const std::string &dir) const
100 {
101     if (!initial_) {
102         ABILITYBASE_LOGE("extractor is not initial");
103         return false;
104     }
105     if (dir.empty()) {
106         ABILITYBASE_LOGE("param dir empty");
107         return false;
108     }
109     return zipFile_.IsDirExist(dir);
110 }
111 
ExtractByName(const std::string & fileName,std::ostream & dest) const112 bool Extractor::ExtractByName(const std::string &fileName, std::ostream &dest) const
113 {
114     if (!initial_) {
115         ABILITYBASE_LOGE("extractor is not initial");
116         return false;
117     }
118     if (!zipFile_.ExtractFile(fileName, dest)) {
119         ABILITYBASE_LOGE("extractor is not ExtractFile");
120         return false;
121     }
122     return true;
123 }
124 
ExtractFile(const std::string & fileName,const std::string & targetPath) const125 bool Extractor::ExtractFile(const std::string &fileName, const std::string &targetPath) const
126 {
127     std::ofstream fileStream;
128     fileStream.open(targetPath, std::ios_base::out | std::ios_base::binary);
129     if (!fileStream.is_open()) {
130         ABILITYBASE_LOGE("fail to open %{private}s file to write", targetPath.c_str());
131         return false;
132     }
133     if ((!ExtractByName(fileName, fileStream)) || (!fileStream.good())) {
134         ABILITYBASE_LOGE("fail to extract %{public}s zip file into stream", fileName.c_str());
135         fileStream.clear();
136         fileStream.close();
137         if (remove(targetPath.c_str()) != 0) {
138             ABILITYBASE_LOGE("fail to remove %{private}s file which writes stream error", targetPath.c_str());
139         }
140         return false;
141     }
142     fileStream.clear();
143     fileStream.close();
144     return true;
145 }
146 
GetSpecifiedTypeFiles(std::vector<std::string> & fileNames,const std::string & suffix)147 void Extractor::GetSpecifiedTypeFiles(std::vector<std::string> &fileNames, const std::string &suffix)
148 {
149     auto &entryMap = zipFile_.GetAllEntries();
150     for (const auto &entry : entryMap) {
151         std::string fileName = entry.first;
152         auto position = fileName.rfind('.');
153         if (position != std::string::npos) {
154             std::string suffixStr = fileName.substr(position);
155             if (LowerStr(suffixStr) == suffix) {
156                 fileNames.emplace_back(fileName);
157             }
158         }
159     }
160 }
161 
IsStageBasedModel(std::string abilityName)162 bool Extractor::IsStageBasedModel(std::string abilityName)
163 {
164     std::vector<std::string> splitStrs;
165     OHOS::SplitStr(abilityName, ".", splitStrs);
166     std::string name = splitStrs.empty() ? abilityName : splitStrs.back();
167     std::string entry = "assets/js/" + name + "/" + name + ".js";
168     bool isStageBasedModel = zipFile_.HasEntry(entry);
169     return isStageBasedModel;
170 }
171 
IsSameHap(const std::string & hapPath) const172 bool Extractor::IsSameHap(const std::string& hapPath) const
173 {
174     return !hapPath_.empty() && !hapPath.empty() && hapPath_ == hapPath;
175 }
176 
GetData(const std::string & fileName,bool) const177 std::unique_ptr<FileMapper> Extractor::GetData(const std::string &fileName, bool) const
178 {
179     std::string relativePath = GetRelativePath(fileName);
180     return zipFile_.CreateFileMapper(relativePath, FileMapperType::NORMAL_MEM);
181 }
182 
GetSafeData(const std::string & fileName)183 std::shared_ptr<FileMapper> Extractor::GetSafeData(const std::string &fileName)
184 {
185     std::string relativePath = GetRelativePath(fileName);
186     if (!StringEndWith(relativePath, EXT_NAME_ABC, sizeof(EXT_NAME_ABC) - 1)) {
187         return nullptr;
188     }
189 
190     return zipFile_.CreateFileMapper(relativePath, FileMapperType::SAFE_ABC);
191 }
192 
GetMmapData(const std::string & fileName)193 std::unique_ptr<FileMapper> Extractor::GetMmapData(const std::string &fileName)
194 {
195     std::string relativePath = GetRelativePath(fileName);
196     return zipFile_.CreateFileMapper(relativePath, FileMapperType::SHARED_MMAP);
197 }
198 
UnzipData(std::unique_ptr<FileMapper> fileMapper,std::unique_ptr<uint8_t[]> & dataPtr,size_t & len) const199 bool Extractor::UnzipData(std::unique_ptr<FileMapper> fileMapper,
200     std::unique_ptr<uint8_t[]> &dataPtr, size_t &len) const
201 {
202     if (!initial_) {
203         ABILITYBASE_LOGE("extractor is not initial");
204         return false;
205     }
206 
207     if (!fileMapper) {
208         ABILITYBASE_LOGE("Input fileMapper is nullptr.");
209         return false;
210     }
211 
212     if (!zipFile_.ExtractFileFromMMap(fileMapper->GetFileName(), fileMapper->GetDataPtr(), dataPtr, len)) {
213         ABILITYBASE_LOGE("extract file from MMap failed.");
214         return false;
215     }
216     return true;
217 }
218 
IsStageModel()219 bool Extractor::IsStageModel()
220 {
221     if (isStageModel_.has_value()) {
222         return isStageModel_.value();
223     }
224     isStageModel_ = !zipFile_.HasEntry("config.json");
225     return isStageModel_.value();
226 }
227 
ExtractToBufByName(const std::string & fileName,std::unique_ptr<uint8_t[]> & dataPtr,size_t & len)228 bool Extractor::ExtractToBufByName(const std::string &fileName, std::unique_ptr<uint8_t[]> &dataPtr,
229     size_t &len)
230 {
231     std::string relativePath = GetRelativePath(fileName);
232     return zipFile_.ExtractToBufByName(relativePath, dataPtr, len);
233 }
234 
GetFileInfo(const std::string & fileName,FileInfo & fileInfo) const235 bool Extractor::GetFileInfo(const std::string &fileName, FileInfo &fileInfo) const
236 {
237     std::string relativePath = GetRelativePath(fileName);
238     ZipEntry zipEntry;
239     if (!zipFile_.GetEntry(relativePath, zipEntry)) {
240         ABILITYBASE_LOGE("Get zip entry failed.");
241         return false;
242     }
243 
244     ZipPos offset = 0;
245     uint32_t length = 0;
246     if (!zipFile_.GetDataOffsetRelative(relativePath, offset, length)) {
247         ABILITYBASE_LOGE("Get data offset relative failed.");
248         return false;
249     }
250 
251     fileInfo.fileName = fileName;
252     fileInfo.offset = static_cast<uint32_t>(offset);
253     fileInfo.length = static_cast<uint32_t>(length);
254     fileInfo.lastModTime = zipEntry.modifiedTime;
255     fileInfo.lastModDate = zipEntry.modifiedDate;
256     return true;
257 }
258 
GetFileList(const std::string & srcPath,std::set<std::string> & fileSet)259 bool Extractor::GetFileList(const std::string &srcPath, std::set<std::string> &fileSet)
260 {
261     if (!initial_) {
262         ABILITYBASE_LOGE("extractor is not initial");
263         return false;
264     }
265 
266     if (srcPath.empty()) {
267         ABILITYBASE_LOGE("GetFileList::srcPath is nullptr");
268         return false;
269     }
270 
271     zipFile_.GetChildNames(srcPath, fileSet);
272     if (fileSet.empty()) {
273         ABILITYBASE_LOGW("empty dir: %{public}s", srcPath.c_str());
274     }
275 
276     return true;
277 }
278 
IsHapCompress(const std::string & fileName) const279 bool Extractor::IsHapCompress(const std::string &fileName) const
280 {
281     std::string relativePath = GetRelativePath(fileName);
282     ZipEntry zipEntry;
283     if (!zipFile_.GetEntry(relativePath, zipEntry)) {
284         ABILITYBASE_LOGE("Get entry info by name failed. fileName: %{public}s", fileName.c_str());
285         return false;
286     }
287     return zipEntry.compressionMethod > 0;
288 }
289 
290 std::mutex ExtractorUtil::mapMutex_;
291 std::unordered_map<std::string, std::shared_ptr<Extractor>> ExtractorUtil::extractorMap_;
GetLoadFilePath(const std::string & hapPath)292 std::string ExtractorUtil::GetLoadFilePath(const std::string &hapPath)
293 {
294     std::string loadPath;
295     if (StringStartWith(hapPath, Constants::ABS_CODE_PATH, std::string(Constants::ABS_CODE_PATH).length())) {
296         loadPath = GetLoadPath(hapPath);
297     } else {
298         loadPath = hapPath;
299     }
300     return loadPath;
301 }
302 
GetExtractor(const std::string & hapPath,bool & newCreate,bool cache)303 std::shared_ptr<Extractor> ExtractorUtil::GetExtractor(const std::string &hapPath, bool &newCreate, bool cache)
304 {
305     newCreate = false;
306     if (hapPath.empty()) {
307         ABILITYBASE_LOGE("Input hapPath is empty.");
308         return nullptr;
309     }
310     {
311         std::lock_guard<std::mutex> mapMutex(mapMutex_);
312         auto mapIter = extractorMap_.find(hapPath);
313         if (mapIter != extractorMap_.end()) {
314             ABILITYBASE_LOGD("Extractor exists, hapPath: %{private}s.", hapPath.c_str());
315             return mapIter->second;
316         }
317     }
318 
319     std::shared_ptr<Extractor> extractor = std::make_shared<Extractor>(hapPath);
320     if (!extractor->Init()) {
321         ABILITYBASE_LOGE("Extractor create failed for %{private}s", hapPath.c_str());
322         return nullptr;
323     }
324     if (cache) {
325         std::lock_guard<std::mutex> mapMutex(mapMutex_);
326         extractorMap_.emplace(hapPath, extractor);
327         ABILITYBASE_LOGI("extractor cache size: %{public}zu.", extractorMap_.size());
328     }
329     newCreate = true;
330     return extractor;
331 }
332 
DeleteExtractor(const std::string & hapPath)333 void ExtractorUtil::DeleteExtractor(const std::string &hapPath)
334 {
335     if (hapPath.empty()) {
336         ABILITYBASE_LOGE("DeleteExtractor hapPath is empty.");
337         return;
338     }
339 
340     std::lock_guard<std::mutex> mapMutex(mapMutex_);
341     auto mapIter = extractorMap_.find(hapPath);
342     if (mapIter != extractorMap_.end()) {
343         ABILITYBASE_LOGI("DeleteExtractor, hapPath: %{public}s.", hapPath.c_str());
344         extractorMap_.erase(mapIter);
345     }
346 }
347 }  // namespace AbilityBase
348 }  // namespace OHOS
349