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