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