• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "config_parser.h"
17 #include <iostream>
18 #include <regex>
19 #include "reference_parser.h"
20 #include "restool_errors.h"
21 
22 namespace OHOS {
23 namespace Global {
24 namespace Restool {
25 using namespace std;
26 const map<string, ConfigParser::ModuleType> ConfigParser::MODULE_TYPES = {
27     { "har", ModuleType::HAR },
28     { "entry", ModuleType::ENTRY },
29     { "feature", ModuleType::FEATURE },
30     { "shared", ModuleType::SHARED }
31 };
32 
33 const map<string, string> ConfigParser::JSON_STRING_IDS = {
34     { "icon", "^\\$media:" },
35     { "label", "^\\$string:" },
36     { "description", "^\\$string:" },
37     { "theme", "^\\$theme:" },
38     { "reason", "^\\$string:" },
39     { "startWindowIcon", "^\\$media:" },
40     { "startWindowBackground", "^\\$color:"},
41     { "resource", "^\\$[a-z]+:" },
42     { "extra", "^\\$[a-z]+:" },
43     { "fileContextMenu", "^\\$profile:" },
44     { "orientation", "^\\$string:" },
45     { "value", "^\\$string:" },
46     { "startWindow", "^\\$profile:" }
47 };
48 
49 const map<string, string> ConfigParser::JSON_ARRAY_IDS = {
50     { "landscapeLayouts", "^\\$layout:" },
51     { "portraitLayouts", "^\\$layout:" }
52 };
53 
54 bool ConfigParser::useModule_ = false;
55 
ConfigParser()56 ConfigParser::ConfigParser()
57     : filePath_(""), packageName_(""), moduleName_(""), moduleType_(ModuleType::NONE),
58     abilityIconId_(0), abilityLabelId_(0), root_(nullptr)
59 {
60 }
61 
ConfigParser(const string & filePath)62 ConfigParser::ConfigParser(const string &filePath)
63     : filePath_(filePath), packageName_(""), moduleName_(""), moduleType_(ModuleType::NONE),
64     abilityIconId_(0), abilityLabelId_(0), root_(nullptr)
65 {
66 }
67 
~ConfigParser()68 ConfigParser::~ConfigParser()
69 {
70     if (root_) {
71         cJSON_Delete(root_);
72     }
73 }
74 
Init()75 uint32_t ConfigParser::Init()
76 {
77     if (!ResourceUtil::OpenJsonFile(filePath_, &root_)) {
78         return RESTOOL_ERROR;
79     }
80 
81     if (!root_ || !cJSON_IsObject(root_)) {
82         PrintError(GetError(ERR_CODE_JSON_FORMAT_ERROR).SetPosition(filePath_));
83         return RESTOOL_ERROR;
84     }
85 
86     cJSON *moduleNode = cJSON_GetObjectItem(root_, "module");
87     if (!ParseModule(moduleNode)) {
88         return RESTOOL_ERROR;
89     }
90     return RESTOOL_SUCCESS;
91 }
92 
GetPackageName() const93 const string &ConfigParser::GetPackageName() const
94 {
95     return packageName_;
96 }
97 
GetModuleName() const98 const string &ConfigParser::GetModuleName() const
99 {
100     return moduleName_;
101 }
102 
GetAbilityIconId() const103 int64_t ConfigParser::GetAbilityIconId() const
104 {
105     return abilityIconId_;
106 }
107 
GetAbilityLabelId() const108 int64_t ConfigParser::GetAbilityLabelId() const
109 {
110     return abilityLabelId_;
111 }
112 
GetModuleType() const113 ConfigParser::ModuleType ConfigParser::GetModuleType() const
114 {
115     return moduleType_;
116 }
117 
ParseRefence()118 uint32_t ConfigParser::ParseRefence()
119 {
120     if (ParseRefImpl(root_, "", root_)) {
121         return RESTOOL_SUCCESS;
122     }
123     return RESTOOL_ERROR;
124 }
125 
Save(const string & filePath) const126 uint32_t ConfigParser::Save(const string &filePath) const
127 {
128     if (ResourceUtil::SaveToJsonFile(filePath, root_)) {
129         return RESTOOL_SUCCESS;
130     }
131     return RESTOOL_ERROR;
132 }
133 
SetAppIcon(string & icon,int64_t id)134 bool ConfigParser::SetAppIcon(string &icon, int64_t id)
135 {
136     cJSON *appNode = cJSON_GetObjectItem(root_, "app");
137     if (!appNode || !cJSON_IsObject(appNode)) {
138         cout << "Warning: 'app' not object" << endl;
139         return false;
140     }
141     cJSON_AddStringToObject(appNode, "icon", icon.c_str());
142     cJSON_AddNumberToObject(appNode, "iconId", id);
143     return true;
144 }
145 
SetAppLabel(string & label,int64_t id)146 bool ConfigParser::SetAppLabel(string &label, int64_t id)
147 {
148     cJSON *appNode = cJSON_GetObjectItem(root_, "app");
149     if (!appNode || !cJSON_IsObject(appNode)) {
150         cout << "Warning: 'app' not object" << endl;
151         return false;
152     }
153     cJSON_AddStringToObject(appNode, "label", label.c_str());
154     cJSON_AddNumberToObject(appNode, "labelId", id);
155     return true;
156 }
157 
158 // below private
ParseModule(cJSON * moduleNode)159 bool ConfigParser::ParseModule(cJSON *moduleNode)
160 {
161     if (!moduleNode || !cJSON_IsObject(moduleNode)) {
162         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("module", "object").SetPosition(filePath_));
163         return false;
164     }
165     if (cJSON_GetArraySize(moduleNode) == 0) {
166         PrintError(GetError(ERR_CODE_JSON_NODE_EMPTY).FormatCause("module").SetPosition(filePath_));
167         return false;
168     }
169 
170     if (!useModule_) {
171         cJSON *packageNode = cJSON_GetObjectItem(moduleNode, "package");
172         if (packageNode && cJSON_IsString(packageNode)) {
173             packageName_ = packageNode->valuestring;
174         }
175         cJSON *distroNode = cJSON_GetObjectItem(moduleNode, "distro");
176         if (!ParseDistro(distroNode)) {
177             return false;
178         }
179         return ParseAbilitiesForDepend(moduleNode);
180     }
181     cJSON *nameNode = cJSON_GetObjectItem(moduleNode, "name");
182     if (nameNode && cJSON_IsString(nameNode)) {
183         moduleName_ = nameNode->valuestring;
184     }
185 
186     if (moduleName_.empty()) {
187         PrintError(GetError(ERR_CODE_JSON_NODE_MISSING).FormatCause("module.name").SetPosition(filePath_));
188         return false;
189     }
190     cJSON *typeNode = cJSON_GetObjectItem(moduleNode, "type");
191     if (typeNode && cJSON_IsString(typeNode) && !ParseModuleType(typeNode->valuestring)) {
192         return false;
193     }
194     return true;
195 }
196 
ParseAbilitiesForDepend(cJSON * moduleNode)197 bool ConfigParser::ParseAbilitiesForDepend(cJSON *moduleNode)
198 {
199     if (!IsDependEntry()) {
200         return true;
201     }
202     cJSON *mainAbilityNode = cJSON_GetObjectItem(moduleNode, "mainAbility");
203     if (mainAbilityNode && cJSON_IsString(mainAbilityNode)) {
204         mainAbility_ = mainAbilityNode->valuestring;
205         if (mainAbility_[0] == '.') {
206             mainAbility_ = packageName_ + mainAbility_;
207         }
208         return ParseAbilities(cJSON_GetObjectItem(moduleNode, "abilities"));
209     }
210     return true;
211 }
212 
ParseDistro(cJSON * distroNode)213 bool ConfigParser::ParseDistro(cJSON *distroNode)
214 {
215     if (!distroNode || !cJSON_IsObject(distroNode)) {
216         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("distro", "object").SetPosition(filePath_));
217         return false;
218     }
219     if (cJSON_GetArraySize(distroNode) == 0) {
220         PrintError(GetError(ERR_CODE_JSON_NODE_EMPTY).FormatCause("distro").SetPosition(filePath_));
221         return false;
222     }
223 
224     cJSON *moduleNameNode = cJSON_GetObjectItem(distroNode, "moduleName");
225     if (moduleNameNode && cJSON_IsString(moduleNameNode)) {
226         moduleName_ = moduleNameNode->valuestring;
227     }
228 
229     if (moduleName_.empty()) {
230         PrintError(GetError(ERR_CODE_JSON_NODE_MISSING).FormatCause("distro.moduleName").SetPosition(filePath_));
231         return false;
232     }
233 
234     cJSON *moduleTypeNode = cJSON_GetObjectItem(distroNode, "moduleType");
235     if (moduleTypeNode && cJSON_IsString(moduleTypeNode) && !ParseModuleType(moduleTypeNode->valuestring)) {
236         return false;
237     }
238     return true;
239 }
240 
ParseAbilities(const cJSON * abilities)241 bool ConfigParser::ParseAbilities(const cJSON *abilities)
242 {
243     if (!abilities || !cJSON_IsArray(abilities)) {
244         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("abilites", "array").SetPosition(filePath_));
245         return false;
246     }
247     if (cJSON_GetArraySize(abilities) == 0) {
248         return true;
249     }
250     bool isMainAbility = false;
251     for (cJSON *ability = abilities->child; ability; ability = ability->next) {
252         if (!ParseAbilitiy(ability, isMainAbility)) {
253             return false;
254         }
255         if (isMainAbility) {
256             break;
257         }
258     }
259     return true;
260 }
261 
ParseAbilitiy(const cJSON * ability,bool & isMainAbility)262 bool ConfigParser::ParseAbilitiy(const cJSON *ability, bool &isMainAbility)
263 {
264     if (!ability || !cJSON_IsObject(ability)) {
265         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("ability", "object").SetPosition(filePath_));
266         return false;
267     }
268     if (cJSON_GetArraySize(ability) == 0) {
269         return true;
270     }
271     cJSON *nameNode = cJSON_GetObjectItem(ability, "name");
272     if (!nameNode || !cJSON_IsString(nameNode)) {
273         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("ability.name", "object")
274             .SetPosition(filePath_));
275         return false;
276     }
277     string name = nameNode->valuestring;
278     if (name[0] == '.') {
279         name = packageName_ + name;
280     }
281     if (mainAbility_ != name && !IsMainAbility(cJSON_GetObjectItem(ability, "skills"))) {
282         return true;
283     }
284     cJSON *iconIdNode = cJSON_GetObjectItem(ability, "iconId");
285     if (iconIdNode && ResourceUtil::IsIntValue(iconIdNode)) {
286         abilityIconId_ = iconIdNode->valueint;
287     }
288     if (abilityIconId_ <= 0) {
289         PrintError(GetError(ERR_CODE_JSON_NODE_MISSING).FormatCause("ability.iconId").SetPosition(filePath_));
290         return false;
291     }
292     cJSON *labelIdNode = cJSON_GetObjectItem(ability, "labelId");
293     if (labelIdNode && ResourceUtil::IsIntValue(labelIdNode)) {
294         abilityLabelId_ = labelIdNode->valueint;
295     }
296     if (abilityLabelId_ <= 0) {
297         PrintError(GetError(ERR_CODE_JSON_NODE_MISSING).FormatCause("ability.labelId").SetPosition(filePath_));
298         return false;
299     }
300     isMainAbility = true;
301     return true;
302 }
303 
IsMainAbility(const cJSON * skills)304 bool ConfigParser::IsMainAbility(const cJSON *skills)
305 {
306     if (!skills || !cJSON_IsArray(skills)) {
307         return false;
308     }
309     for (cJSON *skill = skills->child; skill; skill = skill->next) {
310         if (!cJSON_IsObject(skill)) {
311             return false;
312         }
313         if (IsHomeAction(cJSON_GetObjectItem(skill, "actions"))) {
314             return true;
315         }
316     }
317     return false;
318 }
319 
IsHomeAction(const cJSON * actions)320 bool ConfigParser::IsHomeAction(const cJSON *actions)
321 {
322     if (!actions || !cJSON_IsArray(actions)) {
323         return false;
324     }
325     for (cJSON *action = actions->child; action; action = action->next) {
326         if (!cJSON_IsObject(action)) {
327             return false;
328         }
329         if (strcmp(action->valuestring, "action.system.home") == 0) {
330             return true;
331         }
332     }
333     return false;
334 }
335 
ParseRefImpl(cJSON * parent,const string & key,cJSON * node)336 bool ConfigParser::ParseRefImpl(cJSON *parent, const string &key, cJSON *node)
337 {
338     if (cJSON_IsArray(node)) {
339         const auto &result = JSON_ARRAY_IDS.find(key);
340         if (result != JSON_ARRAY_IDS.end()) {
341             return ParseJsonArrayRef(parent, key, node);
342         }
343         cJSON *arrayItem = node->child;
344         while (arrayItem) {
345             if (!ParseRefImpl(node, "", arrayItem)) {
346                 return false;
347             }
348             arrayItem = arrayItem->next;
349         }
350     } else if (cJSON_IsObject(node)) {
351         cJSON *child = node->child;
352         while (child) {
353             if (!ParseRefImpl(node, child->string, child)) {
354                 return false;
355             }
356             child = child->next;
357         }
358     } else if (!key.empty() && cJSON_IsString(node)) {
359         return ParseJsonStringRef(parent, key, node);
360     }
361     return true;
362 }
363 
ParseJsonArrayRef(cJSON * parent,const string & key,cJSON * node)364 bool ConfigParser::ParseJsonArrayRef(cJSON *parent, const string &key, cJSON *node)
365 {
366     if (!node || !cJSON_IsArray(node)) {
367         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause(key.c_str(), "array")
368             .SetPosition(filePath_));
369         return false;
370     }
371     cJSON *array = cJSON_CreateArray();
372     for (cJSON *item = node->child; item; item = item->next) {
373         if (!cJSON_IsString(item)) {
374             PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause(string(key + " value").c_str(), "string")
375                 .SetPosition(filePath_));
376             cJSON_Delete(array);
377             return false;
378         }
379         string value = item->valuestring;
380         bool update = false;
381         if (!GetRefIdFromString(value, update, JSON_ARRAY_IDS.at(key))) {
382             cJSON_Delete(array);
383             return false;
384         }
385         if (update) {
386             cJSON_AddItemToArray(array, cJSON_CreateNumber(atoll(value.c_str())));
387         }
388     }
389     cJSON_AddItemToObject(parent, (key + "Id").c_str(), array);
390     return true;
391 }
392 
ParseJsonStringRef(cJSON * parent,const string & key,cJSON * node)393 bool ConfigParser::ParseJsonStringRef(cJSON *parent, const string &key, cJSON *node)
394 {
395     const auto &result = JSON_STRING_IDS.find(key);
396     if (result == JSON_STRING_IDS.end()) {
397         return true;
398     }
399     if (!node || !cJSON_IsString(node)) {
400         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause(key.c_str(), "string").SetPosition(filePath_));
401         return false;
402     }
403     string value = node->valuestring;
404     bool update = false;
405     if (!GetRefIdFromString(value, update, JSON_STRING_IDS.at(key))) {
406         return false;
407     }
408     if (update) {
409         cJSON_AddItemToObject(parent, (key + "Id").c_str(), cJSON_CreateNumber(atoll(value.c_str())));
410         AddCheckNode(key, static_cast<uint32_t>(atoll(value.c_str())));
411     }
412     return true;
413 }
414 
AddCheckNode(const string & key,uint32_t id)415 void ConfigParser::AddCheckNode(const string &key, uint32_t id)
416 {
417     if (g_keyNodeIndexs.find(key) != g_keyNodeIndexs.end()) {
418         auto result = jsonCheckIds_.find(key);
419         if (result == jsonCheckIds_.end()) {
420             set<uint32_t> set;
421             set.emplace(id);
422             jsonCheckIds_.emplace(key, set);
423         } else {
424             result->second.emplace(id);
425         }
426         auto layerIconIds = ReferenceParser::GetLayerIconIds();
427         if (layerIconIds.find(id) != layerIconIds.end()) {
428             auto ids = layerIconIds[id];
429             jsonCheckIds_[key].insert(ids.begin(), ids.end());
430         }
431     }
432 }
433 
GetRefIdFromString(string & value,bool & update,const string & match) const434 bool ConfigParser::GetRefIdFromString(string &value, bool &update, const string &match) const
435 {
436     ReferenceParser refParser;
437     if (refParser.ParseRefInString(value, update, filePath_) != RESTOOL_SUCCESS) {
438         return false;
439     }
440     if (!update) {
441         return true;
442     }
443     smatch result;
444     if (regex_search(value, result, regex(match))) {
445         value = value.substr(result[0].str().length());
446         return true;
447     }
448     string ref = match.substr(match.find("\\") + 1);
449     PrintError(GetError(ERR_CODE_INVALID_RESOURCE_REF).FormatCause(value.c_str(), ref.c_str()).SetPosition(filePath_));
450     return false;
451 }
452 
ParseModuleType(const string & type)453 bool ConfigParser::ParseModuleType(const string &type)
454 {
455     const auto &result = MODULE_TYPES.find(type);
456     if (result == MODULE_TYPES.end()) {
457         PrintError(GetError(ERR_CODE_INVALID_MODULE_TYPE).FormatCause(type.c_str()).SetPosition(filePath_));
458         return false;
459     }
460     moduleType_ = result->second;
461     return true;
462 }
463 }
464 }
465 }
466