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