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.flush();
108     fileStream.clear();
109     fileStream.close();
110     return true;
111 }
112 
GetZipFileNames(std::vector<std::string> &fileNames) const113 bool BaseExtractor::GetZipFileNames(std::vector<std::string> &fileNames) const
114 {
115     auto &entryMap = zipFile_.GetAllEntries();
116     auto entryFilter = [&fileNames](const auto &entry) {
117         auto position = entry.first.rfind(ServiceConstants::QUICK_FIX_FILE_SUFFIX);
118         bool isHqfFile = false;
119         if (position != std::string::npos) {
120             std::string suffixStr = entry.first.substr(position);
121             isHqfFile = suffixStr == ServiceConstants::QUICK_FIX_FILE_SUFFIX;
122         }
123         if ((entry.first.find(ServiceConstants::RELATIVE_PATH) == std::string::npos) && !isHqfFile) {
124             fileNames.emplace_back(entry.first);
125         }
126     };
127     for_each(entryMap.begin(), entryMap.end(), entryFilter);
128     return true;
129 }
130 
IsStageBasedModel(std::string abilityName)131 bool BaseExtractor::IsStageBasedModel(std::string abilityName)
132 {
133     auto &entryMap = zipFile_.GetAllEntries();
134     std::vector<std::string> splitStrs;
135     OHOS::SplitStr(abilityName, ".", splitStrs);
136     std::string name = splitStrs.empty() ? abilityName : splitStrs.back();
137     std::string entry = "assets/js/" + name + "/" + name + ".js";
138     bool isStageBasedModel = entryMap.find(entry) != entryMap.end();
139     APP_LOGI("name:%{public}s isStageBasedModel:%{public}d", abilityName.c_str(), isStageBasedModel);
140     return isStageBasedModel;
141 }
142 
IsNewVersion() const143 bool BaseExtractor::IsNewVersion() const
144 {
145     return isNewVersion_;
146 }
147 
GetFileInfo(const std::string &fileName, uint32_t &offset, uint32_t &length) const148 bool BaseExtractor::GetFileInfo(const std::string &fileName, uint32_t &offset, uint32_t &length) const
149 {
150     if (!initial_) {
151         APP_LOGE("extractor is not initial");
152         return false;
153     }
154     ZipPos tmpOffset = 0;
155     if (!zipFile_.GetDataOffsetRelative(fileName, tmpOffset, length)) {
156         APP_LOGE("GetDataOffsetRelative failed");
157         return false;
158     }
159     if (tmpOffset > std::numeric_limits<uint32_t>::max()) {
160         APP_LOGE("offset too large");
161         return false;
162     }
163     offset = static_cast<uint32_t>(tmpOffset);
164     return true;
165 }
166 }  // namespace AppExecFwk
167 }  // namespace OHOS
168