• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 };
44 
45 const map<string, string> ConfigParser::JSON_ARRAY_IDS = {
46     { "landscapeLayouts", "^\\$layout:" },
47     { "portraitLayouts", "^\\$layout:" }
48 };
49 
50 bool ConfigParser::useModule_ = false;
51 
ConfigParser()52 ConfigParser::ConfigParser()
53     : filePath_(""), packageName_(""), moduleName_(""), moduleType_(ModuleType::NONE)
54 {
55 }
56 
ConfigParser(const string & filePath)57 ConfigParser::ConfigParser(const string &filePath)
58     : filePath_(filePath), packageName_(""), moduleName_(""), moduleType_(ModuleType::NONE)
59 {
60 }
61 
~ConfigParser()62 ConfigParser::~ConfigParser()
63 {
64 }
65 
Init()66 uint32_t ConfigParser::Init()
67 {
68     if (!ResourceUtil::OpenJsonFile(filePath_, rootNode_)) {
69         return RESTOOL_ERROR;
70     }
71 
72     if (!rootNode_.isObject()) {
73         cerr << "Error: root node not obeject." << NEW_LINE_PATH << filePath_ << endl;
74         return RESTOOL_ERROR;
75     }
76 
77     if (!ParseModule(rootNode_["module"])) {
78         return RESTOOL_ERROR;
79     }
80     return RESTOOL_SUCCESS;
81 }
82 
GetPackageName() const83 const string &ConfigParser::GetPackageName() const
84 {
85     return packageName_;
86 }
87 
GetModuleName() const88 const string &ConfigParser::GetModuleName() const
89 {
90     return moduleName_;
91 }
92 
GetAbilityIconId() const93 int32_t ConfigParser::GetAbilityIconId() const
94 {
95     return abilityIconId_;
96 }
97 
GetAbilityLabelId() const98 int32_t ConfigParser::GetAbilityLabelId() const
99 {
100     return abilityLabelId_;
101 }
102 
GetModuleType() const103 ConfigParser::ModuleType ConfigParser::GetModuleType() const
104 {
105     return moduleType_;
106 }
107 
ParseRefence()108 uint32_t ConfigParser::ParseRefence()
109 {
110     if (ParseRefImpl(rootNode_, "", rootNode_)) {
111         return RESTOOL_SUCCESS;
112     }
113     return RESTOOL_ERROR;
114 }
115 
Save(const string & filePath) const116 uint32_t ConfigParser::Save(const string &filePath) const
117 {
118     if (ResourceUtil::SaveToJsonFile(filePath, rootNode_)) {
119         return RESTOOL_SUCCESS;
120     }
121     return RESTOOL_ERROR;
122 }
123 
SetAppIcon(string & icon,int32_t id)124 bool ConfigParser::SetAppIcon(string &icon, int32_t id)
125 {
126     if (!rootNode_["app"].isObject()) {
127         cerr << "Error: 'app' not object" << endl;
128         return false;
129     }
130     rootNode_["app"]["icon"] = icon;
131     rootNode_["app"]["iconId"] = id;
132     return true;
133 }
134 
SetAppLabel(string & label,int32_t id)135 bool ConfigParser::SetAppLabel(string &label, int32_t id)
136 {
137     if (!rootNode_["app"].isObject()) {
138         cerr << "Error: 'app' not object" << endl;
139         return false;
140     }
141     rootNode_["app"]["label"] = label;
142     rootNode_["app"]["labelId"] = id;
143     return true;
144 }
145 
146 // below private
ParseModule(Json::Value & moduleNode)147 bool ConfigParser::ParseModule(Json::Value &moduleNode)
148 {
149     if (!moduleNode.isObject()) {
150         cerr << "Error: 'module' not object." << NEW_LINE_PATH << filePath_ << endl;
151         return false;
152     }
153     if (moduleNode.empty()) {
154         cerr << "Error: 'module' empty." << NEW_LINE_PATH << filePath_ << endl;
155         return false;
156     }
157 
158     if (!useModule_) {
159         if (moduleNode.isMember("package") && moduleNode["package"].isString()) {
160             packageName_ = moduleNode["package"].asString();
161         }
162         if (!ParseDistro(moduleNode["distro"])) {
163             return false;
164         }
165         return ParseAbilitiesForDepend(moduleNode);
166     }
167 
168     if (moduleNode["name"].isString()) {
169         moduleName_ = moduleNode["name"].asString();
170     }
171 
172     if (moduleName_.empty()) {
173         cerr << "Error: 'name' don't found in 'module'." << NEW_LINE_PATH << filePath_ << endl;
174         return false;
175     }
176 
177     if (moduleNode["type"].isString() && !ParseModuleType(moduleNode["type"].asString())) {
178         return false;
179     }
180     return true;
181 }
182 
ParseAbilitiesForDepend(Json::Value & moduleNode)183 bool ConfigParser::ParseAbilitiesForDepend(Json::Value &moduleNode)
184 {
185     if (!IsDependEntry()) {
186         return true;
187     }
188     if (moduleNode["mainAbility"].isString()) {
189         mainAbility_ = moduleNode["mainAbility"].asString();
190         if (mainAbility_[0] == '.') {
191             mainAbility_ = packageName_ + mainAbility_;
192         }
193         return ParseAbilities(moduleNode["abilities"]);
194     }
195     return true;
196 }
197 
ParseDistro(Json::Value & distroNode)198 bool ConfigParser::ParseDistro(Json::Value &distroNode)
199 {
200     if (!distroNode.isObject()) {
201         cerr << "Error: 'distro' not object." << NEW_LINE_PATH << filePath_ << endl;
202         return false;
203     }
204     if (distroNode.empty()) {
205         cerr << "Error: 'distro' empty." << NEW_LINE_PATH << filePath_ << endl;
206         return false;
207     }
208 
209     if (distroNode["moduleName"].isString()) {
210         moduleName_ = distroNode["moduleName"].asString();
211     }
212 
213     if (moduleName_.empty()) {
214         cerr << "Error: 'moduleName' don't found in 'distro'." << NEW_LINE_PATH << filePath_ << endl;
215         return false;
216     }
217 
218     if (distroNode["moduleType"].isString() && !ParseModuleType(distroNode["moduleType"].asString())) {
219         return false;
220     }
221     return true;
222 }
223 
ParseAbilities(const Json::Value & abilites)224 bool ConfigParser::ParseAbilities(const Json::Value &abilites)
225 {
226     if (abilites.empty()) {
227         return true;
228     }
229     if (!abilites.isArray()) {
230         cerr << "Error: abilites not array." << NEW_LINE_PATH << filePath_ << endl;
231         return false;
232     }
233     bool isMainAbility = false;
234     for (Json::ArrayIndex i = 0; i < abilites.size(); i++) {
235         if (!ParseAbilitiy(abilites[i], isMainAbility)) {
236             cerr << "Error: ParseAbilitiy fail." << endl;
237             return false;
238         }
239         if (isMainAbility) {
240             break;
241         }
242     }
243     return true;
244 }
245 
ParseAbilitiy(const Json::Value & ability,bool & isMainAbility)246 bool ConfigParser::ParseAbilitiy(const Json::Value &ability, bool &isMainAbility)
247 {
248     if (ability.empty()) {
249         return true;
250     }
251     if (!ability["name"].isString()) {
252         return false;
253     }
254     string name = ability["name"].asString();
255     if (name[0] == '.') {
256         name = packageName_ + name;
257     }
258     if (mainAbility_ != name && !IsMainAbility(ability["skills"])) {
259         return true;
260     }
261     if (ability["iconId"].isInt()) {
262         abilityIconId_ = ability["iconId"].asInt();
263     }
264     if (abilityIconId_ <= 0) {
265         cerr << "Error: iconId don't found in 'ability'." << NEW_LINE_PATH << filePath_ << endl;
266         return false;
267     }
268     if (ability["labelId"].isInt()) {
269         abilityLabelId_ = ability["labelId"].asInt();
270     }
271     if (abilityLabelId_ <= 0) {
272         cerr << "Error: labelId don't found in 'ability'." << NEW_LINE_PATH << filePath_ << endl;
273         return false;
274     }
275     isMainAbility = true;
276     return true;
277 }
278 
IsMainAbility(const Json::Value & skills)279 bool ConfigParser::IsMainAbility(const Json::Value &skills)
280 {
281     if (!skills.isArray()) {
282         return false;
283     }
284     for (Json::ArrayIndex i = 0; i < skills.size(); i++) {
285         if (!skills[i].isObject()) {
286             return false;
287         }
288         if (IsHomeAction(skills[i]["actions"])) {
289             return true;
290         }
291     }
292     return false;
293 }
294 
IsHomeAction(const Json::Value & actions)295 bool ConfigParser::IsHomeAction(const Json::Value &actions)
296 {
297     if (!actions.isArray()) {
298         return false;
299     }
300     for (Json::ArrayIndex i = 0; i < actions.size(); i++) {
301         if (!actions[i].isObject()) {
302             return false;
303         }
304         if (actions[i].asString() == "action.system.home") {
305             return true;
306         }
307     }
308     return false;
309 }
310 
ParseRefImpl(Json::Value & parent,const std::string & key,Json::Value & node)311 bool ConfigParser::ParseRefImpl(Json::Value &parent, const std::string &key, Json::Value &node)
312 {
313     if (node.isArray()) {
314         const auto &result = JSON_ARRAY_IDS.find(key);
315         if (result != JSON_ARRAY_IDS.end()) {
316             return ParseJsonArrayRef(parent, key, node);
317         }
318         for (Json::ArrayIndex index = 0; index < node.size(); index++) {
319             if (!ParseRefImpl(node, "", node[index])) {
320                 return false;
321             }
322         }
323     } else if (node.isObject()) {
324         const auto members = node.getMemberNames();
325         for (const auto &member : members) {
326             if (!ParseRefImpl(node, member, node[member])) {
327                 return false;
328             }
329         }
330     } else if (!key.empty() && node.isString()) {
331         return ParseJsonStringRef(parent, key, node);
332     }
333     return true;
334 }
335 
ParseJsonArrayRef(Json::Value & parent,const string & key,Json::Value & node)336 bool ConfigParser::ParseJsonArrayRef(Json::Value &parent, const string &key, Json::Value &node)
337 {
338     Json::ArrayIndex size = node.size();
339     Json::Value array(Json::arrayValue);
340     for (Json::ArrayIndex index = 0; index < size; index++) {
341         if (!node[index].isString()) {
342             cerr << "Error: '" << key << "' invalid value." << NEW_LINE_PATH << filePath_ << endl;
343             return false;
344         }
345         string value = node[index].asString();
346         bool update = false;
347         if (!GetRefIdFromString(value, update, JSON_ARRAY_IDS.at(key))) {
348             cerr << "Error: '" << key << "' value " << node[index] << " invalid." << NEW_LINE_PATH << filePath_ << endl;
349             return false;
350         }
351         if (update) {
352             array.append(atoi(value.c_str()));
353         }
354     }
355     parent[key + "Id"] = array;
356     return true;
357 }
358 
ParseJsonStringRef(Json::Value & parent,const string & key,Json::Value & node)359 bool ConfigParser::ParseJsonStringRef(Json::Value &parent, const string &key, Json::Value &node)
360 {
361     const auto &result = JSON_STRING_IDS.find(key);
362     if (result == JSON_STRING_IDS.end()) {
363         return true;
364     }
365     string value = node.asString();
366     bool update = false;
367     if (!GetRefIdFromString(value, update, JSON_STRING_IDS.at(key))) {
368         cerr << "Error: '" << key << "' value " << node << " invalid value." << NEW_LINE_PATH << filePath_ << endl;
369         return false;
370     }
371     if (update) {
372         parent[key + "Id"] = atoi(value.c_str());
373         AddCheckNode(key, static_cast<uint32_t>(atoi(value.c_str())));
374     }
375     return true;
376 }
377 
AddCheckNode(const string & key,uint32_t id)378 void ConfigParser::AddCheckNode(const string &key, uint32_t id)
379 {
380     if (g_keyNodeIndexs.find(key) != g_keyNodeIndexs.end()) {
381         auto result = jsonCheckIds_.find(key);
382         if (result == jsonCheckIds_.end()) {
383             set<uint32_t> set;
384             set.emplace(id);
385             jsonCheckIds_.emplace(key, set);
386         } else {
387             result->second.emplace(id);
388         }
389     }
390 }
391 
GetRefIdFromString(string & value,bool & update,const string & match) const392 bool ConfigParser::GetRefIdFromString(string &value, bool &update, const string &match) const
393 {
394     ReferenceParser refParser;
395     string error = "Error: '" + value + "' must start with '" + match.substr(match.find("\\") + 1) + "'";
396     if (refParser.ParseRefInString(value, update) != RESTOOL_SUCCESS) {
397         return false;
398     }
399     if (!update) {
400         return true;
401     }
402     smatch result;
403     if (regex_search(value, result, regex(match))) {
404         value = value.substr(result[0].str().length());
405         return true;
406     }
407     cerr << error << endl;
408     return false;
409 }
410 
ParseModuleType(const string & type)411 bool ConfigParser::ParseModuleType(const string &type)
412 {
413     const auto &result = MODULE_TYPES.find(type);
414     if (result == MODULE_TYPES.end()) {
415         cerr << "Error: moduleType='" << type << "' invalid value." << NEW_LINE_PATH << filePath_ << endl;
416         return false;
417     }
418     moduleType_ = result->second;
419     return true;
420 }
421 }
422 }
423 }
424