• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "parse_util.h"
17 
18 #include <cinttypes>
19 #include <dlfcn.h>
20 #include <fstream>
21 #include <memory>
22 #include <sstream>
23 #include <vector>
24 
25 #include "datetime_ex.h"
26 #include "hisysevent_adapter.h"
27 #include "hitrace_meter.h"
28 #include "sam_log.h"
29 #include "string_ex.h"
30 
31 namespace OHOS {
32 using std::string;
33 
34 namespace {
35 constexpr const char* EVENT_TYPE = "eventId";
36 constexpr const char* EVENT_NAME = "name";
37 constexpr const char* EVENT_VALUE = "value";
38 constexpr const char* SA_TAG_SYSTEM_ABILITY = "systemability";
39 constexpr const char* SA_TAG_PROCESS = "process";
40 constexpr const char* SA_TAG_LIB_PATH = "libpath";
41 constexpr const char* SA_TAG_NAME = "name";
42 constexpr const char* SA_TAG_DEPEND = "depend";
43 constexpr const char* SA_TAG_DEPEND_TIMEOUT = "depend-time-out";
44 constexpr const char* SA_TAG_DEPEND_TIMEOUT_COMPATIBILITY = "depend_time_out";
45 constexpr const char* SA_TAG_RUN_ON_CREATE = "run-on-create";
46 constexpr const char* SA_TAG_AUTO_RESTART = "auto-restart";
47 constexpr const char* SA_TAG_DISTRIBUTED = "distributed";
48 constexpr const char* SA_TAG_DUMP_LEVEL = "dump-level";
49 constexpr const char* SA_TAG_CAPABILITY = "capability";
50 constexpr const char* SA_TAG_PERMISSION = "permission";
51 constexpr const char* SA_TAG_BOOT_PHASE = "bootphase";
52 constexpr const char* SA_TAG_SAID = "said";
53 constexpr const char* SA_TAG_START_ON_DEMAND = "start-on-demand";
54 constexpr const char* SA_TAG_STOP_ON_DEMAND = "stop-on-demand";
55 constexpr const char* SA_TAG_ALLOW_UPDATE = "allow-update";
56 constexpr const char* SA_TAG_RECYCLE_DELAYTIME = "recycle-delaytime";
57 constexpr const char* SA_TAG_DEVICE_ON_LINE = "deviceonline";
58 constexpr const char* SA_TAG_SETTING_SWITCH = "settingswitch";
59 constexpr const char* SA_TAG_COMMON_EVENT = "commonevent";
60 constexpr const char* SA_TAG_PARAM = "param";
61 constexpr const char* SA_TAG_TIEMD_EVENT = "timedevent";
62 constexpr const char* SA_TAG_RECYCLE_STRATEGY = "recycle-strategy";
63 constexpr int32_t MAX_JSON_OBJECT_SIZE = 50 * 1024;
64 constexpr int32_t MAX_JSON_STRING_LENGTH = 128;
65 constexpr int32_t FIRST_SYS_ABILITY_ID = 0x00000000;
66 constexpr int32_t LAST_SYS_ABILITY_ID = 0x00ffffff;
67 const string BOOT_START_PHASE = "BootStartPhase";
68 const string CORE_START_PHASE = "CoreStartPhase";
69 const string HIGH_LOAD_PRIORITY = "HighPriority";
70 const string MEDIUM_LOAD_PRIORITY = "MediumPriority";
71 
72 enum {
73     BOOT_START = 1,
74     CORE_START = 2,
75     OTHER_START = 3,
76 };
77 
78 enum {
79     EQ = 1,
80     GREATER_EQ = 2,
81     GREATER = 3,
82     LESS_EQ = 4,
83     LESS = 5
84 };
85 
ParseLibPath(const string & libPath,string & fileName,string & libDir)86 void ParseLibPath(const string& libPath, string& fileName, string& libDir)
87 {
88     std::vector<string> libPathVec;
89     SplitStr(libPath, "/", libPathVec);
90     if ((libPathVec.size() > 0)) {
91         int fileNameIndex = static_cast<int>(libPathVec.size()) - 1;
92         fileName = libPathVec[fileNameIndex];
93         int libDirIndex = fileNameIndex - 1;
94         if (libDirIndex >= 0) {
95             libDir = libPathVec[libDirIndex];
96         }
97     }
98     if (libDir.empty()) {
99 #ifdef __aarch64__
100         libDir = "lib64";
101 #else
102         libDir = "lib";
103 #endif
104     }
105 }
106 }
107 
~ParseUtil()108 ParseUtil::~ParseUtil()
109 {
110     ClearResource();
111 }
112 
CloseHandle(SaProfile & saProfile)113 void ParseUtil::CloseHandle(SaProfile& saProfile)
114 {
115     if (saProfile.handle == nullptr) {
116         return;
117     }
118     int32_t ret = dlclose(saProfile.handle);
119     if (ret) {
120         HILOGW("close handle failed with errno:%{public}d!", errno);
121     }
122     saProfile.handle = nullptr;
123 }
124 
CloseSo()125 void ParseUtil::CloseSo()
126 {
127     for (auto& saProfile : saProfiles_) {
128         CloseHandle(saProfile);
129     }
130 }
131 
CloseSo(int32_t systemAbilityId)132 void ParseUtil::CloseSo(int32_t systemAbilityId)
133 {
134     for (auto& saProfile : saProfiles_) {
135         if (saProfile.saId == systemAbilityId) {
136             CloseHandle(saProfile);
137             break;
138         }
139     }
140 }
141 
ClearResource()142 void ParseUtil::ClearResource()
143 {
144     CloseSo();
145     saProfiles_.clear();
146 }
147 
SetUpdateList(const std::vector<std::string> & updateVec)148 void ParseUtil::SetUpdateList(const std::vector<std::string>& updateVec)
149 {
150     updateVec_ = updateVec;
151 }
152 
OpenSo(uint32_t bootPhase)153 void ParseUtil::OpenSo(uint32_t bootPhase)
154 {
155     for (auto& saProfile : saProfiles_) {
156         if (saProfile.runOnCreate && saProfile.bootPhase == bootPhase) {
157             OpenSo(saProfile);
158         }
159     }
160 }
161 
IsUpdateSA(const std::string & saId)162 bool ParseUtil::IsUpdateSA(const std::string& saId)
163 {
164     return std::find(updateVec_.begin(), updateVec_.end(), saId) != updateVec_.end();
165 }
166 
OpenSo(SaProfile & saProfile)167 void ParseUtil::OpenSo(SaProfile& saProfile)
168 {
169     if (saProfile.handle == nullptr) {
170         string fileName;
171         string libDir;
172         ParseLibPath(saProfile.libPath, fileName, libDir);
173         if (libDir != "lib64" && libDir != "lib") {
174             HILOGE("invalid libDir %{public}s", libDir.c_str());
175             return;
176         }
177         bool loadFromModuleUpdate = false;
178         string updateLibPath = GetRealPath("/module_update/" + ToString(saProfile.saId) + "/" + libDir + "/"
179             + fileName);
180         if (IsUpdateSA(ToString(saProfile.saId)) && CheckPathExist(updateLibPath)) {
181             HILOGI("load module_update so");
182             loadFromModuleUpdate = true;
183         }
184 
185         string dlopenTag = ToString(saProfile.saId) + "_DLOPEN";
186         HITRACE_METER_NAME(HITRACE_TAG_SAMGR, dlopenTag);
187         int64_t begin = GetTickCount();
188         DlHandle handle = nullptr;
189         if (loadFromModuleUpdate) {
190             handle = dlopen(updateLibPath.c_str(), RTLD_NOW);
191         }
192         if (handle == nullptr) {
193             handle = dlopen(saProfile.libPath.c_str(), RTLD_NOW);
194         }
195         HILOGI("[PerformanceTest] SA:%{public}d OpenSo spend %{public}" PRId64 " ms",
196             saProfile.saId, GetTickCount() - begin);
197         if (handle == nullptr) {
198             ReportAddSystemAbilityFailed(saProfile.saId, fileName);
199             HILOGE("dlopen %{public}s failed with errno:%{public}s!", fileName.c_str(), dlerror());
200             return;
201         }
202         saProfile.handle = handle;
203     } else {
204         HILOGI("SA:%{public}d handle is not null", saProfile.saId);
205     }
206 }
207 
LoadSaLib(int32_t systemAbilityId)208 bool ParseUtil::LoadSaLib(int32_t systemAbilityId)
209 {
210     for (auto& saProfile : saProfiles_) {
211         if (saProfile.saId == systemAbilityId) {
212             OpenSo(saProfile);
213             return true;
214         }
215     }
216     return false;
217 }
218 
GetAllSaProfiles() const219 const std::list<SaProfile>& ParseUtil::GetAllSaProfiles() const
220 {
221     return saProfiles_;
222 }
223 
GetProfile(int32_t saId,SaProfile & saProfile)224 bool ParseUtil::GetProfile(int32_t saId, SaProfile& saProfile)
225 {
226     auto iter = std::find_if(saProfiles_.begin(), saProfiles_.end(), [saId](auto saProfile) {
227         return saProfile.saId == saId;
228     });
229     if (iter != saProfiles_.end()) {
230         saProfile = *iter;
231         return true;
232     }
233     return false;
234 }
235 
RemoveSaProfile(int32_t saId)236 void ParseUtil::RemoveSaProfile(int32_t saId)
237 {
238     saProfiles_.remove_if([saId] (auto saInfo) -> bool { return saInfo.saId == saId; });
239 }
240 
GetBootPriorityPara(const std::string & bootPhase)241 uint32_t ParseUtil::GetBootPriorityPara(const std::string& bootPhase)
242 {
243     if (bootPhase == BOOT_START_PHASE) {
244         return static_cast<uint32_t>(BOOT_START);
245     } else if (bootPhase == CORE_START_PHASE) {
246         return static_cast<uint32_t>(CORE_START);
247     } else {
248         return static_cast<uint32_t>(OTHER_START);
249     }
250 }
251 
GetOndemandPriorityPara(const std::string & loadPriority)252 uint32_t ParseUtil::GetOndemandPriorityPara(const std::string& loadPriority)
253 {
254     if (loadPriority == HIGH_LOAD_PRIORITY) {
255         return static_cast<uint32_t>(HIGH_PRIORITY);
256     } else if (loadPriority == MEDIUM_LOAD_PRIORITY) {
257         return static_cast<uint32_t>(MEDIUM_PRIORITY);
258     } else {
259         return static_cast<uint32_t>(LOW_PRIORITY);
260     }
261 }
262 
ParseSaProfiles(const string & profilePath)263 bool ParseUtil::ParseSaProfiles(const string& profilePath)
264 {
265     HILOGD("profilePath:%{private}s", profilePath.c_str());
266     string realPath = GetRealPath(profilePath);
267     if (!CheckPathExist(realPath.c_str())) {
268         HILOGE("bad profile path!");
269         return false;
270     }
271 
272     if (Endswith(realPath, ".json")) {
273         return ParseJsonFile(realPath);
274     } else {
275         HILOGE("Invalid file format, please use json file!");
276         return false;
277     }
278 }
279 
Endswith(const std::string & src,const std::string & sub)280 bool ParseUtil::Endswith(const std::string& src, const std::string& sub)
281 {
282     return (src.length() >= sub.length() && (src.rfind(sub) == (src.length() - sub.length())));
283 }
284 
StringToMap(const std::string & eventStr)285 std::unordered_map<std::string, std::string> ParseUtil::StringToMap(const std::string& eventStr)
286 {
287     nlohmann::json eventJson = StringToJsonObj(eventStr);
288     std::unordered_map<std::string, std::string> eventMap = JsonObjToMap(eventJson);
289     return eventMap;
290 }
291 
StringToJsonObj(const std::string & eventStr)292 nlohmann::json ParseUtil::StringToJsonObj(const std::string& eventStr)
293 {
294     nlohmann::json jsonObj = nlohmann::json::object();
295     if (eventStr.empty()) {
296         return jsonObj;
297     }
298     nlohmann::json eventJson = nlohmann::json::parse(eventStr, nullptr, false);
299     if (eventJson.is_discarded()) {
300         HILOGE("parse eventStr to json failed");
301         return jsonObj;
302     }
303     if (!eventJson.is_object()) {
304         HILOGE("eventStr converted result is not a jsonObj");
305         return jsonObj;
306     }
307     return eventJson;
308 }
309 
JsonObjToMap(const nlohmann::json & eventJson)310 std::unordered_map<std::string, std::string> ParseUtil::JsonObjToMap(const nlohmann::json& eventJson)
311 {
312     std::unordered_map<std::string, std::string> eventMap;
313     if (eventJson.contains(EVENT_TYPE) && eventJson[EVENT_TYPE].is_string()) {
314         eventMap[EVENT_TYPE] = eventJson[EVENT_TYPE];
315     } else {
316         eventMap[EVENT_TYPE] = "";
317     }
318     if (eventJson.contains(EVENT_NAME) && eventJson[EVENT_NAME].is_string()) {
319         eventMap[EVENT_NAME] = eventJson[EVENT_NAME];
320     } else {
321         eventMap[EVENT_NAME] = "";
322     }
323     if (eventJson.contains(EVENT_VALUE) && eventJson[EVENT_VALUE].is_string()) {
324         eventMap[EVENT_VALUE] = eventJson[EVENT_VALUE];
325     } else {
326         eventMap[EVENT_VALUE] = "";
327     }
328     return eventMap;
329 }
330 
ParseJsonFile(const string & realPath)331 bool ParseUtil::ParseJsonFile(const string& realPath)
332 {
333     nlohmann::json profileJson;
334     bool result = ParseJsonObj(profileJson, realPath);
335     if (!result) {
336         HILOGE("json file parse error!");
337         return false;
338     }
339     HILOGD("profileJson:%{private}s", profileJson.dump().c_str());
340     string process;
341     GetStringFromJson(profileJson, SA_TAG_PROCESS, process);
342     if (process.empty()) {
343         HILOGE("profile format error: no process tag");
344         return false;
345     }
346     if (process.length() > MAX_JSON_STRING_LENGTH) {
347         HILOGE("profile format error: process is too long");
348         return false;
349     }
350     procName_ = Str8ToStr16(process);
351     if (profileJson.find(SA_TAG_SYSTEM_ABILITY) == profileJson.end()) {
352         HILOGE("system ability parse error!");
353         return false;
354     }
355     nlohmann::json& systemAbilityJson = profileJson.at(SA_TAG_SYSTEM_ABILITY);
356     HILOGD("systemAbilityJson:%{private}s", systemAbilityJson.dump().c_str());
357     if (!systemAbilityJson.is_array()) {
358         HILOGE("system ability is not array!");
359         return false;
360     }
361     size_t size = systemAbilityJson.size();
362     for (size_t i = 0; i < size; i++) {
363         SaProfile saProfile = { procName_ };
364         if (!ParseSystemAbility(saProfile, systemAbilityJson[i])) {
365             continue;
366         }
367         saProfiles_.emplace_back(saProfile);
368     }
369     return !saProfiles_.empty();
370 }
371 
ParseSystemAbility(SaProfile & saProfile,nlohmann::json & systemAbilityJson)372 bool ParseUtil::ParseSystemAbility(SaProfile& saProfile, nlohmann::json& systemAbilityJson)
373 {
374     HILOGD("ParseSystemAbility begin");
375     GetInt32FromJson(systemAbilityJson, SA_TAG_NAME, saProfile.saId);
376     if (saProfile.saId == 0) {
377         HILOGE("profile format error: no name tag");
378         return false;
379     }
380     if (saProfile.saId < FIRST_SYS_ABILITY_ID || saProfile.saId > LAST_SYS_ABILITY_ID) {
381         HILOGE("profile format error: saId error");
382         return false;
383     }
384     GetStringFromJson(systemAbilityJson, SA_TAG_LIB_PATH, saProfile.libPath);
385     if (saProfile.libPath.empty()) {
386         HILOGE("profile format error: no libPath tag");
387         return false;
388     }
389     if (saProfile.libPath.length() > MAX_JSON_STRING_LENGTH) {
390         HILOGE("profile format error: libPath is too long");
391         return false;
392     }
393     GetBoolFromJson(systemAbilityJson, SA_TAG_RUN_ON_CREATE, saProfile.runOnCreate);
394     GetBoolFromJson(systemAbilityJson, SA_TAG_AUTO_RESTART, saProfile.autoRestart);
395     GetBoolFromJson(systemAbilityJson, SA_TAG_DISTRIBUTED, saProfile.distributed);
396     GetIntArrayFromJson(systemAbilityJson, SA_TAG_DEPEND, saProfile.dependSa);
397     GetInt32FromJson(systemAbilityJson, SA_TAG_DEPEND_TIMEOUT, saProfile.dependTimeout);
398     if (saProfile.dependTimeout == 0) {
399         GetInt32FromJson(systemAbilityJson, SA_TAG_DEPEND_TIMEOUT_COMPATIBILITY, saProfile.dependTimeout);
400     }
401     GetInt32FromJson(systemAbilityJson, SA_TAG_DUMP_LEVEL, saProfile.dumpLevel);
402     string capability;
403     GetStringFromJson(systemAbilityJson, SA_TAG_CAPABILITY, capability);
404     saProfile.capability = capability.length() <= MAX_JSON_STRING_LENGTH ? Str8ToStr16(capability) : u"";
405     string permission;
406     GetStringFromJson(systemAbilityJson, SA_TAG_PERMISSION, permission);
407     saProfile.permission = permission.length() <= MAX_JSON_STRING_LENGTH ? Str8ToStr16(permission) : u"";
408     string bootPhase;
409     GetStringFromJson(systemAbilityJson, SA_TAG_BOOT_PHASE, bootPhase);
410     saProfile.bootPhase = GetBootPriorityPara(bootPhase);
411     // parse start-on-demand tag
412     ParseStartOndemandTag(systemAbilityJson, SA_TAG_START_ON_DEMAND, saProfile.startOnDemand);
413     // parse stop-on-demand tag
414     ParseStopOndemandTag(systemAbilityJson, SA_TAG_STOP_ON_DEMAND, saProfile.stopOnDemand);
415     string recycleStrategy;
416     GetStringFromJson(systemAbilityJson, SA_TAG_RECYCLE_STRATEGY, recycleStrategy);
417     if (!CheckRecycleStrategy(recycleStrategy, saProfile.recycleStrategy)) {
418         HILOGE("profile format error: recycleStrategy: %{public}s is not immediately or low-memory",
419             recycleStrategy.c_str());
420         return false;
421     }
422     HILOGD("ParseSystemAbility end");
423     return true;
424 }
425 
CheckRecycleStrategy(const std::string & recycleStrategyStr,int32_t & recycleStrategy)426 bool ParseUtil::CheckRecycleStrategy(const std::string& recycleStrategyStr, int32_t& recycleStrategy)
427 {
428     if (recycleStrategyStr == "" || recycleStrategyStr == "immediately") {
429         recycleStrategy = IMMEDIATELY;
430         return true;
431     } else if (recycleStrategyStr == "low-memory") {
432         recycleStrategy = LOW_MEMORY;
433         return true;
434     }
435     return false;
436 }
437 
ParseJsonTag(const nlohmann::json & systemAbilityJson,const std::string & jsonTag,nlohmann::json & onDemandJson)438 bool ParseUtil::ParseJsonTag(const nlohmann::json& systemAbilityJson, const std::string& jsonTag,
439     nlohmann::json& onDemandJson)
440 {
441     if (systemAbilityJson.find(jsonTag) == systemAbilityJson.end()) {
442         return false;
443     }
444     onDemandJson = systemAbilityJson.at(jsonTag);
445     if (!onDemandJson.is_object()) {
446         HILOGE("parse ondemand tag error");
447         return false;
448     }
449     return true;
450 }
451 
ParseOndemandTag(const nlohmann::json & onDemandJson,std::vector<OnDemandEvent> & onDemandEvents)452 void ParseUtil::ParseOndemandTag(const nlohmann::json& onDemandJson, std::vector<OnDemandEvent>& onDemandEvents)
453 {
454     GetOnDemandArrayFromJson(DEVICE_ONLINE, onDemandJson, SA_TAG_DEVICE_ON_LINE, onDemandEvents);
455     GetOnDemandArrayFromJson(SETTING_SWITCH, onDemandJson, SA_TAG_SETTING_SWITCH, onDemandEvents);
456     GetOnDemandArrayFromJson(COMMON_EVENT, onDemandJson, SA_TAG_COMMON_EVENT, onDemandEvents);
457     GetOnDemandArrayFromJson(PARAM, onDemandJson, SA_TAG_PARAM, onDemandEvents);
458     GetOnDemandArrayFromJson(TIMED_EVENT, onDemandJson, SA_TAG_TIEMD_EVENT, onDemandEvents);
459 }
460 
ParseStartOndemandTag(const nlohmann::json & systemAbilityJson,const std::string & jsonTag,StartOnDemand & startOnDemand)461 void ParseUtil::ParseStartOndemandTag(const nlohmann::json& systemAbilityJson,
462     const std::string& jsonTag, StartOnDemand& startOnDemand)
463 {
464     nlohmann::json onDemandJson;
465     if (!ParseJsonTag(systemAbilityJson, jsonTag, onDemandJson)) {
466         return;
467     }
468     ParseOndemandTag(onDemandJson, startOnDemand.onDemandEvents);
469     GetBoolFromJson(onDemandJson, SA_TAG_ALLOW_UPDATE, startOnDemand.allowUpdate);
470 }
471 
ParseStopOndemandTag(const nlohmann::json & systemAbilityJson,const std::string & jsonTag,StopOnDemand & stopOnDemand)472 void ParseUtil::ParseStopOndemandTag(const nlohmann::json& systemAbilityJson,
473     const std::string& jsonTag, StopOnDemand& stopOnDemand)
474 {
475     nlohmann::json onDemandJson;
476     if (!ParseJsonTag(systemAbilityJson, jsonTag, onDemandJson)) {
477         return;
478     }
479     ParseOndemandTag(onDemandJson, stopOnDemand.onDemandEvents);
480     GetBoolFromJson(onDemandJson, SA_TAG_ALLOW_UPDATE, stopOnDemand.allowUpdate);
481     GetInt32FromJson(onDemandJson, SA_TAG_RECYCLE_DELAYTIME, stopOnDemand.delayTime);
482 }
483 
GetOnDemandArrayFromJson(int32_t eventId,const nlohmann::json & obj,const std::string & key,std::vector<OnDemandEvent> & out)484 void ParseUtil::GetOnDemandArrayFromJson(int32_t eventId, const nlohmann::json& obj,
485     const std::string& key, std::vector<OnDemandEvent>& out)
486 {
487     if (obj.find(key.c_str()) != obj.end() && obj[key.c_str()].is_array()) {
488         for (auto& item : obj[key.c_str()]) {
489             std::string name;
490             GetStringFromJson(item, "name", name);
491             std::string value;
492             GetStringFromJson(item, "value", value);
493             bool persistence = false;
494             GetBoolFromJson(item, "persistence", persistence);
495             std::vector<OnDemandCondition> conditions;
496             GetOnDemandConditionsFromJson(item, "conditions", conditions);
497             HILOGD("conditions size: %{public}zu", conditions.size());
498             bool enableOnce = false;
499             GetBoolFromJson(item, "enable-once", enableOnce);
500             std::string priority;
501             GetStringFromJson(item, "load-priority", priority);
502             uint32_t loadPriority = GetOndemandPriorityPara(priority);
503             std::map<std::string, std::string> extraMessages;
504             GetOnDemandExtraMessagesFromJson(item, "extra-messages", extraMessages);
505             HILOGD("extraMessages size: %{public}zu", extraMessages.size());
506             if (!name.empty() && name.length() <= MAX_JSON_STRING_LENGTH &&
507                 value.length() <= MAX_JSON_STRING_LENGTH) {
508                 OnDemandEvent event = {eventId, name, value, -1, persistence,
509                     conditions, enableOnce, loadPriority, extraMessages};
510                 out.emplace_back(event);
511             }
512         }
513     }
514 }
515 
GetOnDemandExtraMessagesFromJson(const nlohmann::json & obj,const std::string & key,std::map<std::string,std::string> & out)516 void ParseUtil::GetOnDemandExtraMessagesFromJson(const nlohmann::json& obj,
517     const std::string& key, std::map<std::string, std::string>& out)
518 {
519     if (obj.find(key.c_str()) == obj.end() || !obj[key.c_str()].is_object()) {
520         return;
521     }
522     for (auto &it: obj[key.c_str()].items()) {
523         if (it.value().is_string()) {
524             out[it.key()] = it.value();
525         } else {
526             HILOGW("extra-mesasge: not string type");
527         }
528     }
529 }
530 
GetOnDemandConditionsFromJson(const nlohmann::json & obj,const std::string & key,std::vector<OnDemandCondition> & out)531 void ParseUtil::GetOnDemandConditionsFromJson(const nlohmann::json& obj,
532     const std::string& key, std::vector<OnDemandCondition>& out)
533 {
534     nlohmann::json conditionsJson;
535     if (obj.find(key.c_str()) == obj.end() || !obj[key.c_str()].is_array()) {
536         return;
537     }
538     conditionsJson = obj.at(key.c_str());
539     for (auto& condition : conditionsJson) {
540         std::string type;
541         GetStringFromJson(condition, "eventId", type);
542         std::string name;
543         GetStringFromJson(condition, "name", name);
544         std::string value;
545         GetStringFromJson(condition, "value", value);
546         int32_t eventId = 0;
547         if (type == SA_TAG_DEVICE_ON_LINE) {
548             eventId = DEVICE_ONLINE;
549         } else if (type == SA_TAG_SETTING_SWITCH) {
550             eventId = SETTING_SWITCH;
551         } else if (type == SA_TAG_COMMON_EVENT) {
552             eventId = COMMON_EVENT;
553         } else if (type == SA_TAG_PARAM) {
554             eventId = PARAM;
555         } else if (type == SA_TAG_TIEMD_EVENT) {
556             eventId = TIMED_EVENT;
557         } else {
558             HILOGW("invalid condition eventId: %{public}s", type.c_str());
559             continue;
560         }
561         std::map<std::string, std::string> extraMessages;
562         GetOnDemandExtraMessagesFromJson(condition, "extra-messages", extraMessages);
563         OnDemandCondition conditionEvent = {eventId, name, value, extraMessages};
564         out.emplace_back(conditionEvent);
565     }
566 }
567 
GetProcessName() const568 std::u16string ParseUtil::GetProcessName() const
569 {
570     return procName_;
571 }
572 
GetRealPath(const string & profilePath) const573 string ParseUtil::GetRealPath(const string& profilePath) const
574 {
575     char path[PATH_MAX] = {'\0'};
576     if (realpath(profilePath.c_str(), path) == nullptr) {
577         HILOGD("get real path fail");
578         return "";
579     }
580     string realPath(path);
581     return realPath;
582 }
583 
CheckPathExist(const string & profilePath)584 bool ParseUtil::CheckPathExist(const string& profilePath)
585 {
586     std::ifstream profileStream(profilePath.c_str());
587     return profileStream.good();
588 }
589 
ParseTrustConfig(const string & profilePath,std::map<std::u16string,std::set<int32_t>> & values)590 bool ParseUtil::ParseTrustConfig(const string& profilePath,
591     std::map<std::u16string, std::set<int32_t>>& values)
592 {
593     HILOGD("config path:%{private}s", profilePath.c_str());
594     string realPath = GetRealPath(profilePath);
595     if (!CheckPathExist(realPath.c_str())) {
596         HILOGE("bad profile path!");
597         return false;
598     }
599     nlohmann::json trustSaIdJson;
600     bool result = ParseJsonObj(trustSaIdJson, realPath);
601     if (!result) {
602         HILOGE("trust json file parse error!");
603         return false;
604     }
605     string process;
606     GetStringFromJson(trustSaIdJson, SA_TAG_PROCESS, process);
607     if (process.empty()) {
608         HILOGE("trust profile format error: no process tag");
609         return false;
610     }
611     if (process.length() > MAX_JSON_STRING_LENGTH) {
612         HILOGE("trust profile format error: process is too long");
613         return false;
614     }
615     auto& saIds = values[Str8ToStr16(process)];
616     GetIntArrayFromJson(trustSaIdJson, SA_TAG_SAID, saIds);
617     HILOGI("ParseTrustConfig realPath:%{public}s, saIds size = %{public}zu", realPath.c_str(), saIds.size());
618     return true;
619 }
620 
ParseJsonObj(nlohmann::json & jsonObj,const string & jsonPath)621 bool ParseUtil::ParseJsonObj(nlohmann::json& jsonObj, const string& jsonPath)
622 {
623     std::ifstream jsonFileStream;
624     jsonFileStream.open(jsonPath.c_str(), std::ios::in);
625     if (!jsonFileStream.is_open()) {
626         HILOGE("open json file error!!");
627         return false;
628     }
629     std::ostringstream buffer;
630     char ch;
631     int32_t readSize = 0;
632     while (buffer && jsonFileStream.get(ch)) {
633         readSize++;
634         if (readSize < MAX_JSON_OBJECT_SIZE) {
635             buffer.put(ch);
636         } else {
637             jsonFileStream.close();
638             HILOGE("too big json file error!!");
639             return false;
640         }
641     }
642     jsonFileStream.close();
643     string jsonStr = buffer.str();
644     jsonObj = nlohmann::json::parse(jsonStr, nullptr, false);
645     if (jsonObj.is_discarded()) {
646         HILOGE("parse json obj error!!");
647         return false;
648     }
649     return true;
650 }
651 
CheckLogicRelationship(const std::string & state,const std::string & profile)652 bool ParseUtil::CheckLogicRelationship(const std::string& state, const std::string& profile)
653 {
654     HILOGD("CheckLogicRelationship State:%{public}s || Profile:%{public}s", state.c_str(), profile.c_str());
655     if (profile.empty() || state == profile) {
656         return true;
657     }
658     if (state.empty()) {
659         return false;
660     }
661     int32_t logicRelationship = EQ;
662     int32_t valueStartPosition = 0;
663     if (profile[0] == '>') {
664         valueStartPosition ++;
665         if (profile[1] == '=') {
666             valueStartPosition ++;
667             logicRelationship = GREATER_EQ;
668         } else {
669             logicRelationship = GREATER;
670         }
671     } else if (profile[0] == '<') {
672         valueStartPosition ++;
673         if (profile[1] == '=') {
674             valueStartPosition ++;
675             logicRelationship = LESS_EQ;
676         } else {
677             logicRelationship = LESS;
678         }
679     }
680     int32_t stateInt, profileInt;
681     if (!StrToInt(profile.substr(valueStartPosition, profile.length() - 1), profileInt)) {
682         return false;
683     }
684     if (!StrToInt(state, stateInt)) {
685         return false;
686     }
687     if (logicRelationship == EQ) {
688         return stateInt == profileInt;
689     } else if (logicRelationship == GREATER_EQ) {
690         return stateInt >= profileInt;
691     } else if (logicRelationship == GREATER) {
692         return stateInt > profileInt;
693     } else if (logicRelationship == LESS_EQ) {
694         return stateInt <= profileInt;
695     } else if (logicRelationship == LESS) {
696         return stateInt < profileInt;
697     }
698     return false;
699 }
700 } // namespace OHOS
701