• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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