1 /*
2 * Copyright (c) 2021-2024 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 "base_extractor.h"
17
18 #include <fstream>
19
20 #include "app_log_wrapper.h"
21 #include "bundle_service_constants.h"
22 #include "string_ex.h"
23
24 namespace OHOS {
25 namespace AppExecFwk {
26 namespace {
27 constexpr const char* MODULE_PROFILE_NAME = "module.json";
28 }
29
BaseExtractor(const std::string & source)30 BaseExtractor::BaseExtractor(const std::string &source) : sourceFile_(source), zipFile_(source)
31 {
32 APP_LOGD("BaseExtractor instance is created");
33 }
34
~BaseExtractor()35 BaseExtractor::~BaseExtractor()
36 {
37 APP_LOGD("BaseExtractor instance is destroyed");
38 }
39
Init()40 bool BaseExtractor::Init()
41 {
42 if (!zipFile_.Open()) {
43 APP_LOGE("open zip file failed, errno:%{public}d", errno);
44 return false;
45 }
46 ZipEntry zipEntry;
47 isNewVersion_ = zipFile_.GetEntry(MODULE_PROFILE_NAME, zipEntry);
48 initial_ = true;
49 return true;
50 }
51
HasEntry(const std::string & fileName) const52 bool BaseExtractor::HasEntry(const std::string &fileName) const
53 {
54 if (!initial_) {
55 APP_LOGE("extractor is not initial");
56 return false;
57 }
58
59 return zipFile_.HasEntry(fileName);
60 }
61
IsDirExist(const std::string & dir) const62 bool BaseExtractor::IsDirExist(const std::string &dir) const
63 {
64 if (!initial_) {
65 APP_LOGE("extractor is not initial");
66 return false;
67 }
68 if (dir.empty()) {
69 APP_LOGE("param dir empty");
70 return false;
71 }
72 return zipFile_.IsDirExist(dir);
73 }
74
ExtractByName(const std::string & fileName,std::ostream & dest) const75 bool BaseExtractor::ExtractByName(const std::string &fileName, std::ostream &dest) const
76 {
77 if (!initial_) {
78 APP_LOGE("extractor is not initial");
79 return false;
80 }
81 if (!zipFile_.ExtractFile(fileName, dest)) {
82 APP_LOGE("extractor is not ExtractFile");
83 return false;
84 }
85 return true;
86 }
87
ExtractFile(const std::string & fileName,const std::string & targetPath) const88 bool BaseExtractor::ExtractFile(const std::string &fileName, const std::string &targetPath) const
89 {
90 APP_LOGD("begin to extract %{public}s file into %{private}s targetPath", fileName.c_str(), targetPath.c_str());
91 std::ofstream fileStream;
92 fileStream.open(targetPath, std::ios_base::out | std::ios_base::binary);
93 if (!fileStream.is_open()) {
94 APP_LOGE("fail to open %{private}s file to write, errno:%{public}d", targetPath.c_str(), errno);
95 return false;
96 }
97 if ((!ExtractByName(fileName, fileStream)) || (!fileStream.good())) {
98 APP_LOGE("fail to extract %{public}s zip file into stream", fileName.c_str());
99 fileStream.clear();
100 fileStream.close();
101 if (remove(targetPath.c_str()) != 0) {
102 APP_LOGE("fail to remove %{private}s file which writes stream error, errno:%{public}d",
103 targetPath.c_str(), errno);
104 }
105 return false;
106 }
107 fileStream.clear();
108 fileStream.close();
109 return true;
110 }
111
GetZipFileNames(std::vector<std::string> & fileNames) const112 bool BaseExtractor::GetZipFileNames(std::vector<std::string> &fileNames) const
113 {
114 auto &entryMap = zipFile_.GetAllEntries();
115 auto entryFilter = [&fileNames](const auto &entry) {
116 auto position = entry.first.rfind(ServiceConstants::QUICK_FIX_FILE_SUFFIX);
117 bool isHqfFile = false;
118 if (position != std::string::npos) {
119 std::string suffixStr = entry.first.substr(position);
120 isHqfFile = suffixStr == ServiceConstants::QUICK_FIX_FILE_SUFFIX;
121 }
122 if ((entry.first.find(ServiceConstants::RELATIVE_PATH) == std::string::npos) && !isHqfFile) {
123 fileNames.emplace_back(entry.first);
124 }
125 };
126 for_each(entryMap.begin(), entryMap.end(), entryFilter);
127 return true;
128 }
129
IsStageBasedModel(std::string abilityName)130 bool BaseExtractor::IsStageBasedModel(std::string abilityName)
131 {
132 auto &entryMap = zipFile_.GetAllEntries();
133 std::vector<std::string> splitStrs;
134 OHOS::SplitStr(abilityName, ".", splitStrs);
135 std::string name = splitStrs.empty() ? abilityName : splitStrs.back();
136 std::string entry = "assets/js/" + name + "/" + name + ".js";
137 bool isStageBasedModel = entryMap.find(entry) != entryMap.end();
138 APP_LOGI("name:%{public}s isStageBasedModel:%{public}d", abilityName.c_str(), isStageBasedModel);
139 return isStageBasedModel;
140 }
141
IsNewVersion() const142 bool BaseExtractor::IsNewVersion() const
143 {
144 return isNewVersion_;
145 }
146
GetFileInfo(const std::string & fileName,uint32_t & offset,uint32_t & length) const147 bool BaseExtractor::GetFileInfo(const std::string &fileName, uint32_t &offset, uint32_t &length) const
148 {
149 if (!initial_) {
150 APP_LOGE("extractor is not initial");
151 return false;
152 }
153 ZipPos tmpOffset = 0;
154 if (!zipFile_.GetDataOffsetRelative(fileName, tmpOffset, length)) {
155 APP_LOGE("GetDataOffsetRelative failed");
156 return false;
157 }
158 if (tmpOffset > std::numeric_limits<uint32_t>::max()) {
159 APP_LOGE("offset too large");
160 return false;
161 }
162 offset = static_cast<uint32_t>(tmpOffset);
163 return true;
164 }
165 } // namespace AppExecFwk
166 } // namespace OHOS
167