• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "bundle_parser.h"
17 
18 #include <fstream>
19 #include <sstream>
20 #include <unistd.h>
21 
22 #include "app_log_wrapper.h"
23 #include "app_privilege_capability.h"
24 #include "bundle_constants.h"
25 #include "bundle_extractor.h"
26 #include "bundle_profile.h"
27 #include "default_permission_profile.h"
28 #include "module_profile.h"
29 #include "pre_bundle_profile.h"
30 #include "rpcid_decode/syscap_tool.h"
31 #include "securec.h"
32 
33 namespace OHOS {
34 namespace AppExecFwk {
35 namespace {
36 const std::string INSTALL_ABILITY_CONFIGS = "install_ability_configs";
37 constexpr const char* BUNDLE_PACKFILE_NAME = "pack.info";
38 constexpr const char* SYSCAP_NAME = "rpcid.sc";
39 
ParseStr(const char * buf,const int itemLen,int totalLen,std::vector<std::string> & sysCaps)40 bool ParseStr(const char *buf, const int itemLen, int totalLen, std::vector<std::string> &sysCaps)
41 {
42     APP_LOGD("Parse rpcid output start, itemLen:%{public}d  totalLen:%{public}d.", itemLen, totalLen);
43     if (buf == nullptr || itemLen <= 0 || totalLen <= 0) {
44         APP_LOGE("param invalid.");
45         return false;
46     }
47 
48     int index = 0;
49     while (index + itemLen <= totalLen) {
50         char item[itemLen];
51         if (strncpy_s(item, sizeof(item), buf + index, itemLen) != 0) {
52             APP_LOGE("Parse rpcid failed due to strncpy_s error.");
53             return false;
54         }
55 
56         sysCaps.emplace_back((std::string)item, 0, itemLen);
57         index += itemLen;
58     }
59 
60     return true;
61 }
62 } // namespace
63 
ReadFileIntoJson(const std::string & filePath,nlohmann::json & jsonBuf)64 bool BundleParser::ReadFileIntoJson(const std::string &filePath, nlohmann::json &jsonBuf)
65 {
66     if (access(filePath.c_str(), F_OK) != 0) {
67         APP_LOGW("can not access the file: %{public}s, not existed", filePath.c_str());
68         return false;
69     }
70 
71     std::fstream in;
72     char errBuf[256];
73     errBuf[0] = '\0';
74     in.open(filePath, std::ios_base::in);
75     if (!in.is_open()) {
76         strerror_r(errno, errBuf, sizeof(errBuf));
77         APP_LOGE("the file cannot be open due to  %{public}s", errBuf);
78         return false;
79     }
80 
81     in.seekg(0, std::ios::end);
82     int64_t size = in.tellg();
83     if (size <= 0) {
84         APP_LOGE("the file is an empty file");
85         in.close();
86         return false;
87     }
88 
89     in.seekg(0, std::ios::beg);
90     jsonBuf = nlohmann::json::parse(in, nullptr, false);
91     in.close();
92     if (jsonBuf.is_discarded()) {
93         APP_LOGE("bad profile file");
94         return false;
95     }
96 
97     return true;
98 }
99 
Parse(const std::string & pathName,InnerBundleInfo & innerBundleInfo) const100 ErrCode BundleParser::Parse(
101     const std::string &pathName,
102     InnerBundleInfo &innerBundleInfo) const
103 {
104     APP_LOGI("parse from %{private}s", pathName.c_str());
105     BundleExtractor bundleExtractor(pathName);
106     if (!bundleExtractor.Init()) {
107         APP_LOGE("bundle extractor init failed");
108         return ERR_APPEXECFWK_PARSE_UNEXPECTED;
109     }
110 
111     // to extract config.json
112     std::ostringstream outStream;
113     if (!bundleExtractor.ExtractProfile(outStream)) {
114         APP_LOGE("extract profile file failed");
115         return ERR_APPEXECFWK_PARSE_NO_PROFILE;
116     }
117 
118     if (bundleExtractor.IsNewVersion()) {
119         APP_LOGD("module.json transform to InnerBundleInfo");
120         innerBundleInfo.SetIsNewVersion(true);
121         ModuleProfile moduleProfile;
122         return moduleProfile.TransformTo(
123             outStream, bundleExtractor, innerBundleInfo);
124     }
125     APP_LOGD("config.json transform to InnerBundleInfo");
126     innerBundleInfo.SetIsNewVersion(false);
127     BundleProfile bundleProfile;
128     ErrCode ret = bundleProfile.TransformTo(
129         outStream, bundleExtractor, innerBundleInfo);
130     if (ret != ERR_OK) {
131         APP_LOGE("transform stream to innerBundleInfo failed %{public}d", ret);
132         return ret;
133     }
134     auto& abilityInfos = innerBundleInfo.FetchAbilityInfos();
135     for (auto& info : abilityInfos) {
136         info.second.isStageBasedModel = bundleExtractor.IsStageBasedModel(info.second.name);
137         auto iter = innerBundleInfo.FetchInnerModuleInfos().find(info.second.package);
138         if (iter != innerBundleInfo.FetchInnerModuleInfos().end()) {
139             iter->second.isStageBasedModel = info.second.isStageBasedModel;
140         }
141     }
142 
143     return ERR_OK;
144 }
145 
ParsePackInfo(const std::string & pathName,BundlePackInfo & bundlePackInfo) const146 ErrCode BundleParser::ParsePackInfo(const std::string &pathName, BundlePackInfo &bundlePackInfo) const
147 {
148     APP_LOGI("parse from %{private}s", pathName.c_str());
149     BundleExtractor bundleExtractor(pathName);
150     if (!bundleExtractor.Init()) {
151         APP_LOGE("bundle extractor init failed");
152         return ERR_APPEXECFWK_PARSE_UNEXPECTED;
153     }
154 
155     // to extract pack.info
156     if (!bundleExtractor.HasEntry(BUNDLE_PACKFILE_NAME)) {
157         APP_LOGW("cannot find pack.info in the hap file");
158         return ERR_OK;
159     }
160     std::ostringstream outStreamForPackInfo;
161     if (!bundleExtractor.ExtractPackFile(outStreamForPackInfo)) {
162         APP_LOGE("extract profile file failed");
163         return ERR_APPEXECFWK_PARSE_NO_PROFILE;
164     }
165     BundleProfile bundleProfile;
166     ErrCode ret = bundleProfile.TransformTo(outStreamForPackInfo, bundlePackInfo);
167     if (ret != ERR_OK) {
168         APP_LOGE("transform stream to bundlePackinfo failed %{public}d", ret);
169         return ret;
170     }
171     return ERR_OK;
172 }
173 
ParseSysCap(const std::string & pathName,std::vector<std::string> & sysCaps) const174 ErrCode BundleParser::ParseSysCap(const std::string &pathName, std::vector<std::string> &sysCaps) const
175 {
176     APP_LOGD("Parse sysCaps from %{private}s", pathName.c_str());
177     BundleExtractor bundleExtractor(pathName);
178     if (!bundleExtractor.Init()) {
179         APP_LOGE("Bundle extractor init failed");
180         return ERR_APPEXECFWK_PARSE_UNEXPECTED;
181     }
182 
183     if (!bundleExtractor.HasEntry(SYSCAP_NAME)) {
184         APP_LOGD("Rpcid.sc is not exist, and do not need verification sysCaps.");
185         return ERR_OK;
186     }
187 
188     std::stringstream rpcidStream;
189     if (!bundleExtractor.ExtractByName(SYSCAP_NAME, rpcidStream)) {
190         APP_LOGE("Extract rpcid file failed");
191         return ERR_APPEXECFWK_PARSE_RPCID_FAILED;
192     }
193 
194     int32_t rpcidLen = rpcidStream.tellp();
195     if (rpcidLen < 0) {
196         return ERR_APPEXECFWK_PARSE_UNEXPECTED;
197     }
198     char rpcidBuf[rpcidLen];
199     rpcidStream.read(rpcidBuf, rpcidLen);
200     uint32_t outLen;
201     char *outBuffer;
202     int result = RPCIDStreamDecodeToBuffer(rpcidBuf, rpcidLen, &outBuffer, &outLen);
203     if (result != 0) {
204         APP_LOGE("Decode syscaps failed");
205         return ERR_APPEXECFWK_PARSE_RPCID_FAILED;
206     }
207 
208     if (!ParseStr(outBuffer, SINGLE_SYSCAP_LENGTH, outLen, sysCaps)) {
209         APP_LOGE("Parse syscaps str failed");
210         free(outBuffer);
211         return ERR_APPEXECFWK_PARSE_RPCID_FAILED;
212     }
213 
214     APP_LOGD("Parse sysCaps str success");
215     free(outBuffer);
216     return ERR_OK;
217 }
218 
ParsePreInstallConfig(const std::string & configFile,std::set<PreScanInfo> & scanInfos) const219 ErrCode BundleParser::ParsePreInstallConfig(
220     const std::string &configFile, std::set<PreScanInfo> &scanInfos) const
221 {
222     APP_LOGD("Parse preInstallConfig from %{public}s", configFile.c_str());
223     nlohmann::json jsonBuf;
224     if (!ReadFileIntoJson(configFile, jsonBuf)) {
225         APP_LOGE("Parse preInstallConfig file failed");
226         return ERR_APPEXECFWK_PARSE_FILE_FAILED;
227     }
228 
229     PreBundleProfile preBundleProfile;
230     return preBundleProfile.TransformTo(jsonBuf, scanInfos);
231 }
232 
ParsePreUnInstallConfig(const std::string & configFile,std::set<std::string> & uninstallList) const233 ErrCode BundleParser::ParsePreUnInstallConfig(
234     const std::string &configFile,
235     std::set<std::string> &uninstallList) const
236 {
237     APP_LOGD("Parse PreUnInstallConfig from %{public}s", configFile.c_str());
238     nlohmann::json jsonBuf;
239     if (!ReadFileIntoJson(configFile, jsonBuf)) {
240         APP_LOGE("Parse preUnInstallConfig file failed");
241         return ERR_APPEXECFWK_PARSE_FILE_FAILED;
242     }
243 
244     PreBundleProfile preBundleProfile;
245     return preBundleProfile.TransformTo(jsonBuf, uninstallList);
246 }
247 
ParsePreInstallAbilityConfig(const std::string & configFile,std::set<PreBundleConfigInfo> & preBundleConfigInfos) const248 ErrCode BundleParser::ParsePreInstallAbilityConfig(
249     const std::string &configFile, std::set<PreBundleConfigInfo> &preBundleConfigInfos) const
250 {
251     APP_LOGD("Parse PreInstallAbilityConfig from %{public}s", configFile.c_str());
252     nlohmann::json jsonBuf;
253     if (!ReadFileIntoJson(configFile, jsonBuf)) {
254         APP_LOGE("Parse preInstallAbilityConfig file failed");
255         return ERR_APPEXECFWK_PARSE_FILE_FAILED;
256     }
257 
258     PreBundleProfile preBundleProfile;
259     return preBundleProfile.TransformTo(jsonBuf, preBundleConfigInfos);
260 }
261 
ParseDefaultPermission(const std::string & permissionFile,std::set<DefaultPermission> & defaultPermissions) const262 ErrCode BundleParser::ParseDefaultPermission(
263     const std::string &permissionFile, std::set<DefaultPermission> &defaultPermissions) const
264 {
265     APP_LOGD("Parse DefaultPermission from %{private}s", permissionFile.c_str());
266     nlohmann::json jsonBuf;
267     if (!ReadFileIntoJson(permissionFile, jsonBuf)) {
268         APP_LOGE("Parse default-permissions file failed");
269         return ERR_APPEXECFWK_PARSE_FILE_FAILED;
270     }
271 
272     DefaultPermissionProfile profile;
273     return profile.TransformTo(jsonBuf, defaultPermissions);
274 }
275 }  // namespace AppExecFwk
276 }  // namespace OHOS
277