1 /*
2 * Copyright (c) 2020 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 "gt_bundle_parser.h"
17
18 #include "ability_info_utils.h"
19 #include "adapter.h"
20 #include "appexecfwk_errors.h"
21 #include "bundle_info_utils.h"
22 #include "bundle_util.h"
23 #include "bundlems_log.h"
24 #include "fcntl.h"
25 #include "global.h"
26 #include "gt_bundle_extractor.h"
27 #include "module_info_utils.h"
28 #include "parameter.h"
29 #include "pms.h"
30 #include "securec.h"
31 #include "sys/stat.h"
32 #include "unistd.h"
33 #include "utils.h"
34
35 namespace OHOS {
36 const int32_t BASE_API_VERSION = 3;
37
ParseValue(const cJSON * object,const char * key,int32_t defaultValue)38 int32_t GtBundleParser::ParseValue(const cJSON *object, const char *key, int32_t defaultValue)
39 {
40 if (object == nullptr) {
41 return defaultValue;
42 }
43
44 cJSON *son = nullptr;
45 son = cJSON_GetObjectItem(object, key);
46 if (!cJSON_IsNumber(son)) {
47 return defaultValue;
48 }
49 return son->valueint;
50 }
51
ParseValue(const cJSON * object,const char * key)52 char *GtBundleParser::ParseValue(const cJSON *object, const char *key)
53 {
54 if (object == nullptr) {
55 return nullptr;
56 }
57
58 cJSON *son = nullptr;
59 son = cJSON_GetObjectItem(object, key);
60 if (!cJSON_IsString(son)) {
61 return nullptr;
62 }
63 return son->valuestring;
64 }
65
ParseValue(const cJSON * object,const char * key,cJSON * defaultValue)66 cJSON *GtBundleParser::ParseValue(const cJSON *object, const char *key, cJSON *defaultValue)
67 {
68 if (object == nullptr) {
69 return defaultValue;
70 }
71
72 cJSON *son = nullptr;
73 son = cJSON_GetObjectItem(object, key);
74 if (son == nullptr) {
75 return defaultValue;
76 }
77
78 if (cJSON_IsArray(son) || cJSON_IsObject(son)) {
79 return son;
80 }
81 return defaultValue;
82 }
83
ParseBundleAttr(const char * path,char ** bundleName,int32_t & versionCode)84 bool GtBundleParser::ParseBundleAttr(const char *path, char **bundleName, int32_t &versionCode)
85 {
86 if (!BundleUtil::CheckRealPath(path)) {
87 return false;
88 }
89
90 uint32_t totalFileSize = BundleUtil::GetFileSize(path);
91 int32_t fp = open(path, O_RDONLY, S_IREAD);
92 if (fp < 0) {
93 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] open file failed!");
94 return false;
95 }
96
97 char *profileStr = GtBundleExtractor::ExtractHapProfile(fp, totalFileSize);
98 if (profileStr == nullptr) {
99 close(fp);
100 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] ExtractHapProfile failed when excute parse bundle!");
101 return false;
102 }
103 close(fp);
104
105 cJSON *root = cJSON_Parse(profileStr);
106 if (root == nullptr) {
107 AdapterFree(profileStr);
108 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] cJSON_Parse failed when excute parse bundle!");
109 return false;
110 }
111 AdapterFree(profileStr);
112
113 cJSON *appObject = cJSON_GetObjectItem(root, PROFILE_KEY_APP);
114 if (appObject == nullptr) {
115 cJSON_Delete(root);
116 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] cJSON_GetObjectItem failed when excute parse bundle!");
117 return false;
118 }
119
120 *bundleName = Utils::Strdup(ParseValue(appObject, PROFILE_KEY_BUNDLENAME));
121 if (*bundleName == nullptr) {
122 cJSON_Delete(root);
123 return false;
124 }
125
126 cJSON *object = ParseValue(appObject, PROFILE_KEY_VERSION, nullptr);
127 if (object == nullptr) {
128 cJSON_Delete(root);
129 return false;
130 }
131
132 versionCode = ParseValue(object, PROFILE_KEY_VERSION_CODE, -1);
133 if (versionCode == -1) {
134 cJSON_Delete(root);
135 return false;
136 }
137 cJSON_Delete(root);
138 return true;
139 }
140
ParseHapProfile(const char * path,BundleRes * bundleRes)141 BundleInfo *GtBundleParser::ParseHapProfile(const char *path, BundleRes *bundleRes)
142 {
143 if (!BundleUtil::CheckRealPath(path) || bundleRes == nullptr) {
144 return nullptr;
145 }
146
147 char profilePath[PATH_LENGTH] = { 0 };
148 if (sprintf_s(profilePath, PATH_LENGTH, "%s/%s", path, PROFILE_NAME) < 0) {
149 return nullptr;
150 }
151
152 cJSON *root = BundleUtil::GetJsonStream(profilePath);
153 if (root == nullptr) {
154 return nullptr;
155 }
156
157 cJSON *appObject = cJSON_GetObjectItem(root, PROFILE_KEY_APP);
158 cJSON *configObject = cJSON_GetObjectItem(root, PROFILE_KEY_DEVICECONFIG);
159 cJSON *moduleObject = cJSON_GetObjectItem(root, PROFILE_KEY_MODULE);
160 if (appObject == nullptr || moduleObject == nullptr) {
161 cJSON_Delete(root);
162 return nullptr;
163 }
164
165 BundleProfile bundleProfile;
166 if (memset_s(&bundleProfile, sizeof(BundleProfile), 0, sizeof(BundleProfile)) != EOK) {
167 cJSON_Delete(root);
168 return nullptr;
169 }
170
171 if (ParseJsonInfo(appObject, configObject, moduleObject, bundleProfile, *bundleRes) != ERR_OK) {
172 cJSON_Delete(root);
173 FREE_BUNDLE_PROFILE(bundleProfile);
174 return nullptr;
175 }
176
177 BundleInfo *bundleInfo = CreateBundleInfo(path, bundleProfile, *bundleRes);
178 FREE_BUNDLE_PROFILE(bundleProfile);
179 cJSON_Delete(root);
180 return bundleInfo;
181 }
182
ParseJsonInfo(const cJSON * appObject,const cJSON * configObject,const cJSON * moduleObject,BundleProfile & bundleProfile,BundleRes & bundleRes)183 uint8_t GtBundleParser::ParseJsonInfo(const cJSON *appObject, const cJSON *configObject, const cJSON *moduleObject,
184 BundleProfile &bundleProfile, BundleRes &bundleRes)
185 {
186 // parse app config
187 bundleProfile.bundleName = ParseValue(appObject, PROFILE_KEY_BUNDLENAME);
188 CHECK_NULL(bundleProfile.bundleName, ERR_APPEXECFWK_INSTALL_FAILED_PARSE_BUNDLENAME_ERROR);
189 if (!((strlen(bundleProfile.bundleName) >= MIN_BUNDLE_NAME_LEN) &&
190 (strlen(bundleProfile.bundleName) <= MAX_BUNDLE_NAME_LEN))) {
191 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_INVALID_BUNDLENAME_LENGTH;
192 }
193
194 if (cJSON_HasObjectItem(appObject, PROFILE_KEY_VENDOR)) {
195 bundleProfile.vendor = ParseValue(appObject, PROFILE_KEY_VENDOR);
196 CHECK_NULL(bundleProfile.vendor, ERR_APPEXECFWK_INSTALL_FAILED_PARSE_VENDOR_ERROR);
197 }
198
199 cJSON *object = ParseValue(appObject, PROFILE_KEY_VERSION, nullptr);
200 bundleProfile.profileVersion.versionName = ParseValue(object, PROFILE_KEY_VERSION_NAME);
201 CHECK_NULL(bundleProfile.profileVersion.versionName, ERR_APPEXECFWK_INSTALL_FAILED_PARSE_VERSIONNAME_ERROR);
202 CHECK_LENGTH(strlen(bundleProfile.profileVersion.versionName), MAX_VERSION_NAME_LEN,
203 ERR_APPEXECFWK_INSTALL_FAILED_EXCEED_MAX_VERSIONNAME_LENGTH_ERROR);
204
205 bundleProfile.profileVersion.versionCode = ParseValue(object, PROFILE_KEY_VERSION_CODE, -1);
206 if (bundleProfile.profileVersion.versionCode == -1) {
207 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_VERSIONCODE_ERROR;
208 }
209 // check apiVersion
210 if (cJSON_HasObjectItem(appObject, PROFILE_KEY_APIVERSION)) {
211 object = ParseValue(appObject, PROFILE_KEY_APIVERSION, nullptr);
212 CHECK_NULL(object, ERR_APPEXECFWK_INSTALL_FAILED_PARSE_API_VERSION_ERROR);
213 bundleProfile.profileApiVersion.minApiVersion = ParseValue(object, PROFILE_KEY_APIVERSION_COMPATIBLE, -1);
214 if (cJSON_HasObjectItem(object, PROFILE_KEY_APIVERSION_TARGET)) {
215 bundleProfile.profileApiVersion.maxApiVersion = ParseValue(object, PROFILE_KEY_APIVERSION_TARGET, -1);
216 CHECK_IS_TRUE(
217 (bundleProfile.profileApiVersion.maxApiVersion >= bundleProfile.profileApiVersion.minApiVersion),
218 ERR_APPEXECFWK_INSTALL_FAILED_PARSE_API_VERSION_ERROR);
219 }
220 } else {
221 // parse deviceConfig
222 bundleProfile.profileApiVersion.minApiVersion = BASE_API_VERSION;
223 bundleProfile.profileApiVersion.maxApiVersion = BASE_API_VERSION;
224 }
225
226 uint8_t errorCode = ParseModuleInfo(moduleObject, bundleProfile, bundleRes);
227 return errorCode;
228 }
229
ParseModuleInfo(const cJSON * moduleObject,BundleProfile & bundleProfile,BundleRes & bundleRes)230 uint8_t GtBundleParser::ParseModuleInfo(const cJSON *moduleObject, BundleProfile &bundleProfile, BundleRes &bundleRes)
231 {
232 // parse deviceType
233 cJSON *object = ParseValue(moduleObject, PROFILE_KEY_MODULE_DEVICETYPE, nullptr);
234 if (!CheckDeviceTypeIsValid(object)) {
235 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_DEVICETYPE_ERROR;
236 }
237 // parse distro
238 object = ParseValue(moduleObject, PROFILE_KEY_MODULE_DISTRO, nullptr);
239 CHECK_NULL(object, ERR_APPEXECFWK_INSTALL_FAILED_PARSE_DISTRO_ERROR);
240 cJSON *deliveryObject = cJSON_GetObjectItem(object, PROFILE_KEY_MODULE_DISTRO_DELIVERY);
241 CHECK_NULL(deliveryObject, ERR_APPEXECFWK_INSTALL_FAILED_PARSE_DISTRO_DELIVERY_ERROR);
242 if (!cJSON_IsBool(deliveryObject)) {
243 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_DISTRO_DELIVERY_ERROR;
244 }
245
246 bundleProfile.moduleInfo.moduleName = ParseValue(object, PROFILE_KEY_MODULE_DISTRO_MODULENAME);
247 CHECK_NULL(bundleProfile.moduleInfo.moduleName, ERR_APPEXECFWK_INSTALL_FAILED_PARSE_DISTRO_MODULENAME_ERROR);
248 if (strstr(bundleProfile.moduleInfo.moduleName, "../") != nullptr) {
249 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_INVALID_MODULENAME;
250 }
251 // parse metaData
252 uint8_t errorCode = ParseModuleMetaData(moduleObject, bundleProfile);
253 if (errorCode != ERR_OK) {
254 return errorCode;
255 }
256
257 char *moduleType = ParseValue(object, PROFILE_KEY_MODULE_DISTRO_MODULETYPE);
258 CHECK_NULL(moduleType, ERR_APPEXECFWK_INSTALL_FAILED_PARSE_DISTRO_MODULETYPE_ERROR);
259 bool result = ((strcmp(moduleType, MODULE_ENTRY) == 0) || (strcmp(moduleType, MODULE_FEATURE) == 0));
260 if (!result) {
261 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_DISTRO_MODULETYPE_ERROR;
262 }
263 // parse ability
264 cJSON *abilityObjects = ParseValue(moduleObject, PROFILE_KEY_MODULE_ABILITIES, nullptr);
265 CHECK_NULL(abilityObjects, ERR_APPEXECFWK_INSTALL_FAILED_PARSE_ABILITIES_ERROR);
266 if (abilityObjects->type != cJSON_Array || cJSON_GetArraySize(abilityObjects) == 0) {
267 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_ABILITIES_ERROR;
268 }
269 return ParseAbilityInfo(abilityObjects, bundleProfile, bundleRes);
270 }
271
ParseAbilityInfo(const cJSON * abilityInfoObjects,BundleProfile & bundleProfile,BundleRes & bundleRes)272 uint8_t GtBundleParser::ParseAbilityInfo(const cJSON *abilityInfoObjects, BundleProfile &bundleProfile,
273 BundleRes &bundleRes)
274 {
275 cJSON *firstAbilityJson = cJSON_GetArrayItem(abilityInfoObjects, 0);
276 bundleProfile.label = ParseValue(firstAbilityJson, PROFILE_KEY_MODULE_ABILITY_LABEL);
277 CHECK_NULL(bundleProfile.label, ERR_APPEXECFWK_INSTALL_FAILED_PARSE_ABILITY_LABEL_ERROR);
278
279 bundleRes.abilityRes = reinterpret_cast<AbilityRes *>(AdapterMalloc(sizeof(AbilityRes)));
280 bundleRes.totalNumOfAbilityRes = 1;
281 CHECK_NULL(bundleRes.abilityRes, ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR);
282 if (memset_s(bundleRes.abilityRes, sizeof(AbilityRes), 0, sizeof(AbilityRes)) != EOK) {
283 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
284 }
285
286 if (BundleUtil::StartWith(bundleProfile.label, DEFAULT_LABEL_SETTING)) {
287 int32_t labelId = ParseValue(firstAbilityJson, LABEL_ID, -1);
288 if (labelId < 0) {
289 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_ABILITY_LABEL_ERROR;
290 }
291 bundleRes.abilityRes->labelId = labelId;
292 }
293 CHECK_LENGTH(strlen(bundleProfile.label), MAX_LABLE_LEN,
294 ERR_APPEXECFWK_INSTALL_FAILED_EXCEED_MAX_LABEL_LENGTH_ERROR);
295
296 bundleProfile.iconPath = ParseValue(firstAbilityJson, PROFILE_KEY_MODULE_ABILITY_ICON);
297 CHECK_NULL(bundleProfile.iconPath, ERR_APPEXECFWK_INSTALL_FAILED_PARSE_ABILITY_ICONPATH_ERROR);
298 if (strcmp(bundleProfile.iconPath, DEFAULT_ICON_SETTING) != 0) {
299 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_ABILITY_ICONPATH_ERROR;
300 }
301 int32_t iconId = ParseValue(firstAbilityJson, ICON_ID, -1);
302 if (iconId < 0) {
303 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_ABILITY_ICONPATH_ERROR;
304 }
305 bundleRes.abilityRes->iconId = iconId;
306 return ERR_OK;
307 }
308
CheckDeviceTypeIsValid(const cJSON * deviceTypeObject)309 bool GtBundleParser::CheckDeviceTypeIsValid(const cJSON *deviceTypeObject)
310 {
311 if (!cJSON_IsArray(deviceTypeObject)) {
312 return false;
313 }
314
315 const char *deviceType = GetDeviceType();
316 if (deviceType == nullptr) {
317 return false;
318 }
319
320 cJSON *object = nullptr;
321 cJSON_ArrayForEach(object, deviceTypeObject) {
322 if (object->type != cJSON_String) {
323 return false;
324 }
325 if ((object->valuestring != nullptr) && (strcmp(object->valuestring, deviceType) == 0 ||
326 (strcmp(object->valuestring, DEFAULT_DEVICE_TYPE) == 0))) {
327 return true;
328 }
329 }
330 return false;
331 }
332
ParseModuleMetaData(const cJSON * moduleObject,BundleProfile & bundleProfile)333 uint8_t GtBundleParser::ParseModuleMetaData(const cJSON *moduleObject, BundleProfile &bundleProfile)
334 {
335 cJSON *object = ParseValue(moduleObject, PROFILE_KEY_MODULE_METADATA, nullptr);
336 if (object == nullptr || object->type == cJSON_NULL) {
337 return ERR_OK;
338 }
339
340 object = cJSON_GetObjectItem(object, PROFILE_KEY_MODULE_METADATA_CUSTOMIZEDATA);
341 if (object == nullptr || object->type == cJSON_NULL) {
342 return ERR_OK;
343 }
344 int32_t size = cJSON_GetArraySize(object);
345 if (object->type != cJSON_Array || size > METADATA_SIZE) {
346 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_METADATA_ERROR;
347 }
348 cJSON *objectItem = nullptr;
349 int32_t i = 0;
350 cJSON_ArrayForEach(objectItem, object) {
351 bundleProfile.moduleInfo.metaData[i] = reinterpret_cast<MetaData *>
352 (AdapterMalloc(sizeof(MetaData)));
353 if (bundleProfile.moduleInfo.metaData[i] == nullptr ||
354 memset_s(bundleProfile.moduleInfo.metaData[i], sizeof(MetaData), 0, sizeof(MetaData)) != EOK) {
355 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_METADATA_ERROR;
356 }
357 if (cJSON_HasObjectItem(objectItem, PROFILE_KEY_MODULE_METADATA_NAME)) {
358 bundleProfile.moduleInfo.metaData[i]->name = ParseValue(objectItem, PROFILE_KEY_MODULE_METADATA_NAME);
359 CHECK_NULL(bundleProfile.moduleInfo.metaData[i]->name,
360 ERR_APPEXECFWK_INSTALL_FAILED_PARSE_METADATA_ERROR);
361 CHECK_LENGTH(strlen(bundleProfile.moduleInfo.metaData[i]->name), MAX_METADATA_NAME,
362 ERR_APPEXECFWK_INSTALL_FAILED_EXCEED_MAX_METADATA_NAME_LENGTH_ERROR);
363 }
364
365 if (cJSON_HasObjectItem(objectItem, PROFILE_KEY_MODULE_METADATA_VALUE)) {
366 bundleProfile.moduleInfo.metaData[i]->value = ParseValue(objectItem, PROFILE_KEY_MODULE_METADATA_VALUE);
367 CHECK_NULL(bundleProfile.moduleInfo.metaData[i]->value,
368 ERR_APPEXECFWK_INSTALL_FAILED_PARSE_METADATA_ERROR);
369 CHECK_LENGTH(strlen(bundleProfile.moduleInfo.metaData[i]->value), MAX_METADATA_VALUE,
370 ERR_APPEXECFWK_INSTALL_FAILED_EXCEED_MAX_METADATA_VALUE_LENGTH_ERROR);
371 }
372
373 if (cJSON_HasObjectItem(objectItem, PROFILE_KEY_MODULE_METADATA_EXTRA)) {
374 bundleProfile.moduleInfo.metaData[i]->extra = ParseValue(objectItem, PROFILE_KEY_MODULE_METADATA_EXTRA);
375 CHECK_NULL(bundleProfile.moduleInfo.metaData[i]->extra,
376 ERR_APPEXECFWK_INSTALL_FAILED_PARSE_METADATA_ERROR);
377 }
378 i++;
379 }
380 return ERR_OK;
381 }
382
CreateBundleInfo(const char * path,const BundleProfile & bundleProfile,const BundleRes & bundleRes)383 BundleInfo *GtBundleParser::CreateBundleInfo(const char *path, const BundleProfile &bundleProfile,
384 const BundleRes &bundleRes)
385 {
386 BundleInfo *bundleInfo = reinterpret_cast<BundleInfo *>(AdapterMalloc(sizeof(BundleInfo)));
387 if (bundleInfo == nullptr) {
388 return nullptr;
389 }
390
391 if (memset_s(bundleInfo, sizeof(BundleInfo), 0, sizeof(BundleInfo)) != EOK) {
392 AdapterFree(bundleInfo);
393 return nullptr;
394 }
395
396 char *installedPath = Utils::Strdup(path);
397 if (!SetBundleInfo(installedPath, bundleProfile, bundleRes, bundleInfo)) {
398 BundleInfoUtils::FreeBundleInfo(bundleInfo);
399 return nullptr;
400 }
401
402 uint8_t errorCode = ConvertResInfoToBundleInfo(path, bundleRes.abilityRes->labelId, bundleRes.abilityRes->iconId,
403 bundleInfo);
404 if (errorCode != ERR_OK) {
405 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] convert res to bundle info failed!");
406 BundleInfoUtils::FreeBundleInfo(bundleInfo);
407 return nullptr;
408 }
409 // get js path
410 char *jsPathComp[] = {bundleInfo->codePath, const_cast<char *>(ASSET_JS_PATH)};
411 char *jsPath = BundleUtil::Strscat(jsPathComp, sizeof(jsPathComp) / sizeof(char *));
412 if (jsPath == nullptr) {
413 BundleInfoUtils::FreeBundleInfo(bundleInfo);
414 return nullptr;
415 }
416
417 if (!BundleUtil::IsDir(jsPath)) {
418 BundleInfoUtils::FreeBundleInfo(bundleInfo);
419 AdapterFree(jsPath);
420 return nullptr;
421 }
422 // set abilityInfo
423 AbilityInfo abilityInfo = {.srcPath = jsPath, .bundleName = bundleInfo->bundleName};
424 if (!BundleInfoUtils::SetBundleInfoAbilityInfo(bundleInfo, abilityInfo)) {
425 AdapterFree(abilityInfo.srcPath);
426 BundleInfoUtils::FreeBundleInfo(bundleInfo);
427 return nullptr;
428 }
429 AdapterFree(abilityInfo.srcPath);
430 return bundleInfo;
431 }
432
ConvertResInfoToBundleInfo(const char * path,uint32_t labelId,uint32_t iconId,BundleInfo * bundleInfo)433 uint8_t GtBundleParser::ConvertResInfoToBundleInfo(const char *path, uint32_t labelId, uint32_t iconId,
434 BundleInfo *bundleInfo)
435 {
436 if (path == nullptr || bundleInfo == nullptr) {
437 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
438 }
439 char *resPathComp[] = {
440 const_cast<char *>(path), const_cast<char *>(ASSETS), bundleInfo->moduleInfos[0].moduleName,
441 const_cast<char *>(RESOURCES_INDEX)
442 };
443 char *resPath = BundleUtil::Strscat(resPathComp, sizeof(resPathComp) / sizeof(char *));
444 if (resPath == nullptr) {
445 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
446 }
447 if (!BundleUtil::IsFile(resPath)) {
448 AdapterFree(resPath);
449 return ERR_APPEXECFWK_INSTALL_FAILED_RESOURCE_INDEX_NOT_EXISTS;
450 }
451 if (labelId != 0) {
452 char *label = nullptr;
453 if (GLOBAL_GetValueById(labelId, resPath, &label) != 0) {
454 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] global get label failed!");
455 Free(label);
456 AdapterFree(resPath);
457 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_LABEL_RES_ERROR;
458 }
459 // release label memory first
460 AdapterFree(bundleInfo->label);
461 bundleInfo->label = Utils::Strdup(label);
462 Free(label);
463 if (bundleInfo->label == nullptr) {
464 AdapterFree(resPath);
465 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
466 }
467 }
468 if (!ConvertIconResToBundleInfo(resPath, iconId, bundleInfo)) {
469 AdapterFree(resPath);
470 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_ICON_RES_ERROR;
471 }
472 AdapterFree(resPath);
473 return ERR_OK;
474 }
475
ConvertIconResToBundleInfo(const char * resPath,uint32_t iconId,BundleInfo * bundleInfo)476 bool GtBundleParser::ConvertIconResToBundleInfo(const char *resPath, uint32_t iconId, BundleInfo *bundleInfo)
477 {
478 if (resPath == nullptr || bundleInfo == nullptr || iconId == 0) {
479 return false;
480 }
481
482 char *relativeIconPath = nullptr;
483 if (GLOBAL_GetValueById(iconId, const_cast<char *>(resPath), &relativeIconPath) != 0) {
484 HILOG_ERROR(HILOG_MODULE_AAFWK, "[BMS] global get icon failed!");
485 return false;
486 }
487 // set relativeIconDir
488 if (relativeIconPath == nullptr) {
489 return false;
490 }
491 char *pos = relativeIconPath + strlen(relativeIconPath);
492 for (; *pos != '/'; pos--) {};
493 *pos = '\0';
494 char *bigIconPathComp[] = {
495 bundleInfo->codePath, const_cast<char *>(ASSETS), relativeIconPath, const_cast<char *>(ICON_NAME)
496 };
497 char *smallIconPathComp[] = {
498 bundleInfo->codePath, const_cast<char *>(ASSETS), relativeIconPath, const_cast<char *>(SMALL_ICON_NAME)
499 };
500 char *bigIconPath = BundleUtil::Strscat(bigIconPathComp, sizeof(bigIconPathComp) / sizeof(char *));
501 if (bigIconPath == nullptr) {
502 Free(relativeIconPath);
503 return false;
504 }
505 char *smallIconPath = BundleUtil::Strscat(smallIconPathComp, sizeof(smallIconPathComp) / sizeof(char *));
506 if (smallIconPath == nullptr) {
507 Free(relativeIconPath);
508 AdapterFree(bigIconPath);
509 return false;
510 }
511 Free(relativeIconPath);
512 if (!BundleUtil::IsFile(bigIconPath) || !BundleUtil::IsFile(smallIconPath)) {
513 AdapterFree(bigIconPath);
514 AdapterFree(smallIconPath);
515 return false;
516 }
517 // release bigIconPath and smallIconPath memory in bundleInfo first
518 AdapterFree(bundleInfo->bigIconPath);
519 AdapterFree(bundleInfo->smallIconPath);
520 bundleInfo->bigIconPath = bigIconPath;
521 bundleInfo->smallIconPath = smallIconPath;
522 return true;
523 }
524
ParseHapProfile(int32_t fp,uint32_t fileSize,Permissions & permissions,BundleRes & bundleRes,BundleInfo ** bundleInfo)525 uint8_t GtBundleParser::ParseHapProfile(int32_t fp, uint32_t fileSize, Permissions &permissions, BundleRes &bundleRes,
526 BundleInfo **bundleInfo)
527 {
528 char *profileStr = GtBundleExtractor::ExtractHapProfile(fp, fileSize);
529 if (profileStr == nullptr) {
530 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_PROFILE_ERROR;
531 }
532
533 cJSON *root = cJSON_Parse(profileStr);
534 if (root == nullptr) {
535 AdapterFree(profileStr);
536 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_PROFILE_ERROR;
537 }
538 AdapterFree(profileStr);
539
540 cJSON *appObject = cJSON_GetObjectItem(root, PROFILE_KEY_APP);
541 cJSON *configObject = cJSON_GetObjectItem(root, PROFILE_KEY_DEVICECONFIG);
542 cJSON *moduleObject = cJSON_GetObjectItem(root, PROFILE_KEY_MODULE);
543 if (appObject == nullptr || moduleObject == nullptr) {
544 cJSON_Delete(root);
545 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_PROFILE_ERROR;
546 }
547
548 BundleProfile bundleProfile;
549 if (memset_s(&bundleProfile, sizeof(BundleProfile), 0, sizeof(BundleProfile)) != EOK) {
550 cJSON_Delete(root);
551 return ERR_APPEXECFWK_SYSTEM_INTERNAL_ERROR;
552 }
553
554 uint8_t errorCode = ParseJsonInfo(appObject, configObject, moduleObject, bundleProfile, bundleRes);
555 CHECK_PARSE_RESULT(errorCode, root, bundleProfile, bundleRes);
556
557 cJSON *object = ParseValue(moduleObject, PROFILE_KEY_REQPERMISSIONS, nullptr);
558 errorCode = ParsePermissions(object, permissions);
559 CHECK_PARSE_RESULT(errorCode, root, bundleProfile, bundleRes);
560
561 errorCode = SaveBundleInfo(bundleProfile, bundleRes, bundleInfo);
562 CHECK_PARSE_RESULT(errorCode, root, bundleProfile, bundleRes);
563
564 FREE_BUNDLE_PROFILE(bundleProfile);
565 cJSON_Delete(root);
566 return ERR_OK;
567 }
568
SaveBundleInfo(const BundleProfile & bundleProfile,const BundleRes & bundleRes,BundleInfo ** bundleInfo)569 uint8_t GtBundleParser::SaveBundleInfo(const BundleProfile &bundleProfile, const BundleRes &bundleRes,
570 BundleInfo **bundleInfo)
571 {
572 int32_t len = strlen(INSTALL_PATH) + 1 + strlen(bundleProfile.bundleName) + 1;
573 char *installedPath = reinterpret_cast<char *>(AdapterMalloc(len));
574 if (installedPath == nullptr) {
575 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
576 }
577 if (sprintf_s(installedPath, len, "%s/%s", INSTALL_PATH, bundleProfile.bundleName) < 0) {
578 AdapterFree(installedPath);
579 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
580 }
581
582 *bundleInfo = reinterpret_cast<BundleInfo *>(AdapterMalloc(sizeof(BundleInfo)));
583 if (*bundleInfo == nullptr) {
584 AdapterFree(installedPath);
585 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
586 }
587
588 if (memset_s(*bundleInfo, sizeof(BundleInfo), 0, sizeof(BundleInfo)) != EOK) {
589 AdapterFree(*bundleInfo);
590 *bundleInfo = nullptr;
591 AdapterFree(installedPath);
592 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
593 }
594
595 if (!SetBundleInfo(installedPath, bundleProfile, bundleRes, *bundleInfo)) {
596 BundleInfoUtils::FreeBundleInfo(*bundleInfo);
597 *bundleInfo = nullptr;
598 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
599 }
600
601 char *jsPathComp[] = {(*bundleInfo)->codePath, const_cast<char *>(ASSET_JS_PATH)};
602 char *jsPath = BundleUtil::Strscat(jsPathComp, sizeof(jsPathComp) / sizeof(char *));
603 if (jsPath == nullptr) {
604 BundleInfoUtils::FreeBundleInfo(*bundleInfo);
605 *bundleInfo = nullptr;
606 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
607 }
608 AbilityInfo abilityInfo = {.srcPath = jsPath, .bundleName = (*bundleInfo)->bundleName};
609 // set abilityInfo
610 if (!BundleInfoUtils::SetBundleInfoAbilityInfo(*bundleInfo, abilityInfo)) {
611 AdapterFree(jsPath);
612 BundleInfoUtils::FreeBundleInfo(*bundleInfo);
613 *bundleInfo = nullptr;
614 return ERR_APPEXECFWK_INSTALL_FAILED_INTERNAL_ERROR;
615 }
616 AdapterFree(jsPath);
617 return ERR_OK;
618 }
619
SetBundleInfo(const char * installedPath,const BundleProfile & bundleProfile,const BundleRes & bundleRes,BundleInfo * bundleInfo)620 bool GtBundleParser::SetBundleInfo(const char *installedPath, const BundleProfile &bundleProfile,
621 const BundleRes &bundleRes, BundleInfo *bundleInfo)
622 {
623 if (bundleInfo == nullptr || bundleRes.abilityRes == nullptr || installedPath == nullptr) {
624 return false;
625 }
626
627 bundleInfo->versionCode = bundleProfile.profileVersion.versionCode;
628 bundleInfo->compatibleApi = bundleProfile.profileApiVersion.minApiVersion;
629 bundleInfo->targetApi = bundleProfile.profileApiVersion.maxApiVersion;
630 bundleInfo->codePath = const_cast<char *>(installedPath);
631
632 int32_t len = strlen(DATA_PATH) + 1 + strlen(bundleProfile.bundleName) + 1;
633 char *dataPath = reinterpret_cast<char *>(UI_Malloc(len));
634 if (dataPath == nullptr) {
635 return false;
636 }
637 if (sprintf_s(dataPath, len, "%s/%s", DATA_PATH, bundleProfile.bundleName) < 0) {
638 UI_Free(dataPath);
639 return false;
640 }
641
642 bundleInfo->dataPath = Utils::Strdup(dataPath);
643 UI_Free(dataPath);
644 if (bundleInfo->dataPath == nullptr) {
645 return false;
646 }
647
648 if (bundleProfile.vendor != nullptr && !BundleInfoUtils::SetBundleInfoVendor(bundleInfo, bundleProfile.vendor)) {
649 return false;
650 }
651
652 if (bundleRes.abilityRes->labelId == 0 && bundleProfile.label != nullptr &&
653 !BundleInfoUtils::SetBundleInfoLabel(bundleInfo, bundleProfile.label)) {
654 return false;
655 }
656
657 if (!BundleInfoUtils::SetBundleInfoBundleName(bundleInfo, bundleProfile.bundleName) ||
658 !BundleInfoUtils::SetBundleInfoVersionName(bundleInfo, bundleProfile.profileVersion.versionName) ||
659 !SetModuleInfos(bundleProfile, bundleInfo)) {
660 return false;
661 }
662 return true;
663 }
664
SetModuleInfos(const BundleProfile & bundleProfile,BundleInfo * bundleInfo)665 bool GtBundleParser::SetModuleInfos(const BundleProfile &bundleProfile, BundleInfo *bundleInfo)
666 {
667 if (bundleInfo == nullptr) {
668 return false;
669 }
670 bundleInfo->moduleInfos = reinterpret_cast<ModuleInfo *>(AdapterMalloc(sizeof(ModuleInfo)));
671 if (bundleInfo->moduleInfos == nullptr) {
672 return false;
673 }
674
675 if (memset_s(bundleInfo->moduleInfos, sizeof(ModuleInfo), 0, sizeof(ModuleInfo)) != EOK) {
676 AdapterFree(bundleInfo->moduleInfos);
677 return false;
678 }
679
680 bundleInfo->numOfModule = 1;
681 if (!ModuleInfoUtils::SetModuleInfoMetaData(bundleInfo->moduleInfos,
682 const_cast<MetaData **>(bundleProfile.moduleInfo.metaData), METADATA_SIZE)) {
683 return false;
684 }
685 if (!ModuleInfoUtils::SetModuleInfoModuleName(bundleInfo->moduleInfos, bundleProfile.moduleInfo.moduleName)) {
686 return false;
687 }
688 return true;
689 }
690
ParsePermissions(const cJSON * object,Permissions & permissions)691 uint8_t GtBundleParser::ParsePermissions(const cJSON *object, Permissions &permissions)
692 {
693 if (object == nullptr) {
694 return ERR_OK;
695 }
696
697 if (object->type != cJSON_Array) {
698 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_PERMISSIONS_ERROR;
699 }
700 permissions.permNum = cJSON_GetArraySize(object);
701 if (permissions.permNum == 0) {
702 return ERR_OK;
703 }
704
705 permissions.permissionTrans = reinterpret_cast<PermissionTrans *>(UI_Malloc(sizeof(PermissionTrans) *
706 permissions.permNum));
707
708 if (permissions.permissionTrans == nullptr) {
709 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_PERMISSIONS_ERROR;
710 }
711
712 PermissionTrans *perms = permissions.permissionTrans;
713 cJSON *reqPermission = nullptr;
714 cJSON_ArrayForEach(reqPermission, object) {
715 if (!SetReqPermission(reqPermission, perms)) {
716 return ERR_APPEXECFWK_INSTALL_FAILED_PARSE_PERMISSIONS_ERROR;
717 }
718 perms++;
719 }
720 return ERR_OK;
721 }
722
SetReqPermission(const cJSON * object,PermissionTrans * permission)723 bool GtBundleParser::SetReqPermission(const cJSON *object, PermissionTrans *permission)
724 {
725 if (object == nullptr || permission == nullptr) {
726 return false;
727 }
728
729 char *name = ParseValue(object, PROFILE_KEY_REQPERMISSIONS_NAME);
730 char *desc = ParseValue(object, PROFILE_KEY_REQPERMISSIONS_REASON);
731 if (name == nullptr || desc == nullptr) {
732 return false;
733 }
734
735 if (strncpy_s(permission->name, sizeof(permission->name), name, strlen(name)) != EOK ||
736 strncpy_s(permission->desc, sizeof(permission->desc), desc, strlen(desc)) != EOK) {
737 return false;
738 }
739
740 cJSON *usedSceneObject = ParseValue(object, PROFILE_KEY_REQPERMISSIONS_USEDSCENE, nullptr);
741 char *when = ParseValue(usedSceneObject, PROFILE_KEY_REQPERMISSIONS_WHEN);
742 if (when == nullptr) {
743 return false;
744 }
745 if (strcmp(when, GRANTTIME_INUSE) == 0) {
746 permission->when = INUSE;
747 } else if (strcmp(when, GRANTTIME_ALWAYS) == 0) {
748 permission->when = ALWAYS;
749 } else {
750 return false;
751 }
752 return true;
753 }
754 } // namespace OHOS