1 /*
2  * Copyright (c) 2021-2024 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 "event_json_parser.h"
17 
18 #include <cctype>
19 #include <cinttypes>
20 #include <fstream>
21 #include <map>
22 
23 #include "hiview_logger.h"
24 
25 namespace OHOS {
26 namespace HiviewDFX {
27 namespace {
28 DEFINE_LOG_TAG("Event-JsonParser");
29 
30 constexpr char BASE[] = "__BASE";
31 constexpr char LEVEL[] = "level";
32 constexpr char TAG[] = "tag";
33 constexpr char TYPE[] = "type";
34 constexpr char PRIVACY[] = "privacy";
35 constexpr char PRESERVE[] = "preserve";
36 const std::map<std::string, uint8_t> EVENT_TYPE_MAP = {
37     {"FAULT", 1}, {"STATISTIC", 2}, {"SECURITY", 3}, {"BEHAVIOR", 4}
38 };
39 
ReadSysEventDefFromFile(const std::string& path, Json::Value& hiSysEventDef)40 bool ReadSysEventDefFromFile(const std::string& path, Json::Value& hiSysEventDef)
41 {
42     std::ifstream fin(path, std::ifstream::binary);
43     if (!fin.is_open()) {
44         HIVIEW_LOGW("failed to open file, path: %{public}s.", path.c_str());
45         return false;
46     }
47     Json::CharReaderBuilder jsonRBuilder;
48     Json::CharReaderBuilder::strictMode(&jsonRBuilder.settings_);
49     JSONCPP_STRING errs;
50     return parseFromStream(jsonRBuilder, fin, &hiSysEventDef, &errs);
51 }
52 }
53 
EventJsonParser(const std::string& defFilePath)54 EventJsonParser::EventJsonParser(const std::string& defFilePath)
55 {
56     // read json file
57     ReadDefFile(defFilePath);
58 }
59 
GetTagByDomainAndName(const std::string& domain, const std::string& name) const60 std::string EventJsonParser::GetTagByDomainAndName(const std::string& domain, const std::string& name) const
61 {
62     return GetDefinedBaseInfoByDomainName(domain, name).tag;
63 }
64 
GetTypeByDomainAndName(const std::string& domain, const std::string& name) const65 int EventJsonParser::GetTypeByDomainAndName(const std::string& domain, const std::string& name) const
66 {
67     return GetDefinedBaseInfoByDomainName(domain, name).type;
68 }
69 
GetPreserveByDomainAndName(const std::string& domain, const std::string& name) const70 bool EventJsonParser::GetPreserveByDomainAndName(const std::string& domain, const std::string& name) const
71 {
72     return GetDefinedBaseInfoByDomainName(domain, name).preserve;
73 }
74 
GetDefinedBaseInfoByDomainName(const std::string& domain, const std::string& name) const75 BaseInfo EventJsonParser::GetDefinedBaseInfoByDomainName(const std::string& domain,
76     const std::string& name) const
77 {
78     if (hiSysEventDefMap_ == nullptr) {
79         HIVIEW_LOGD("sys def map is null");
80         return BaseInfo();
81     }
82     auto domainIter = hiSysEventDefMap_->find(domain);
83     if (domainIter == hiSysEventDefMap_->end()) {
84         HIVIEW_LOGD("domain %{public}s is not defined.", domain.c_str());
85         return BaseInfo();
86     }
87     auto domainNames = hiSysEventDefMap_->at(domain);
88     auto nameIter = domainNames.find(name);
89     if (nameIter == domainNames.end()) {
90         HIVIEW_LOGD("%{public}s is not defined in domain %{public}s.", name.c_str(), domain.c_str());
91         return BaseInfo();
92     }
93     return nameIter->second;
94 }
95 
HasIntMember(const Json::Value& jsonObj, const std::string& name) const96 bool EventJsonParser::HasIntMember(const Json::Value& jsonObj, const std::string& name) const
97 {
98     return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isInt();
99 }
100 
HasStringMember(const Json::Value& jsonObj, const std::string& name) const101 bool EventJsonParser::HasStringMember(const Json::Value& jsonObj, const std::string& name) const
102 {
103     return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isString();
104 }
105 
HasBoolMember(const Json::Value& jsonObj, const std::string& name) const106 bool EventJsonParser::HasBoolMember(const Json::Value& jsonObj, const std::string& name) const
107 {
108     return jsonObj.isMember(name.c_str()) && jsonObj[name.c_str()].isBool();
109 }
110 
InitEventInfoMapRef(const Json::Value& eventJson, JSON_VALUE_LOOP_HANDLER handler) const111 void EventJsonParser::InitEventInfoMapRef(const Json::Value& eventJson, JSON_VALUE_LOOP_HANDLER handler) const
112 {
113     if (!eventJson.isObject()) {
114         return;
115     }
116     auto attrList = eventJson.getMemberNames();
117     for (auto it = attrList.cbegin(); it != attrList.cend(); it++) {
118         std::string key = *it;
119         if (key.empty()) {
120             continue;
121         }
122         if (handler != nullptr) {
123             handler(key, eventJson[key]);
124         }
125     }
126 }
127 
ParseBaseConfig(const Json::Value& eventNameJson) const128 BaseInfo EventJsonParser::ParseBaseConfig(const Json::Value& eventNameJson) const
129 {
130     BaseInfo baseInfo;
131     if (!eventNameJson.isObject() || !eventNameJson[BASE].isObject()) {
132         HIVIEW_LOGD("__BASE definition is invalid.");
133         return baseInfo;
134     }
135 
136     Json::Value baseJsonInfo = eventNameJson[BASE];
137     if (!baseJsonInfo.isObject() || !HasStringMember(baseJsonInfo, TYPE)) {
138         HIVIEW_LOGD("type is not defined in __BASE.");
139         return baseInfo;
140     }
141     std::string typeDes = baseJsonInfo[TYPE].asString();
142     if (EVENT_TYPE_MAP.find(typeDes) == EVENT_TYPE_MAP.end()) {
143         HIVIEW_LOGD("type is defined as %{public}s, but a valid type must be FAULT, STATISTIC, SECURITY, or BEHAVIOR",
144             typeDes.c_str());
145         return baseInfo;
146     }
147     baseInfo.type = EVENT_TYPE_MAP.at(typeDes);
148 
149     if (!HasStringMember(baseJsonInfo, LEVEL)) {
150         HIVIEW_LOGD("level is not defined in __BASE.");
151         return baseInfo;
152     }
153     baseInfo.level = baseJsonInfo[LEVEL].asString();
154 
155     if (HasStringMember(baseJsonInfo, TAG)) {
156         baseInfo.tag = baseJsonInfo[TAG].asString();
157     }
158 
159     if (HasIntMember(baseJsonInfo, PRIVACY)) {
160         int privacy = baseJsonInfo[PRIVACY].asInt();
161         baseInfo.privacy = privacy > 0 ? static_cast<uint8_t>(privacy) : baseInfo.privacy;
162     }
163 
164     if (HasBoolMember(baseJsonInfo, PRESERVE)) {
165         baseInfo.preserve = baseJsonInfo[PRESERVE].asBool();
166     }
167 
168     return baseInfo;
169 }
170 
ParseHiSysEventDef(const Json::Value& hiSysEventDef, std::shared_ptr<DOMAIN_INFO_MAP> sysDefMap)171 void EventJsonParser::ParseHiSysEventDef(const Json::Value& hiSysEventDef, std::shared_ptr<DOMAIN_INFO_MAP> sysDefMap)
172 {
173     InitEventInfoMapRef(hiSysEventDef, [this, sysDefMap] (const std::string& key, const Json::Value& value) {
174        sysDefMap->insert(std::make_pair(key, this->ParseNameConfig(value)));
175     });
176 }
177 
ParseNameConfig(const Json::Value& domainJson) const178 NAME_INFO_MAP EventJsonParser::ParseNameConfig(const Json::Value& domainJson) const
179 {
180     NAME_INFO_MAP allNames;
181     if (!domainJson.isObject()) {
182         return allNames;
183     }
184     InitEventInfoMapRef(domainJson, [this, &allNames] (const std::string& key, const Json::Value& value) {
185         allNames[key] = ParseBaseConfig(value);
186     });
187     return allNames;
188 }
189 
ReadDefFile(const std::string& defFilePath)190 void EventJsonParser::ReadDefFile(const std::string& defFilePath)
191 {
192     Json::Value hiSysEventDef;
193     if (!ReadSysEventDefFromFile(defFilePath, hiSysEventDef)) {
194         HIVIEW_LOGE("parse json file failed, please check the style of json file: %{public}s", defFilePath.c_str());
195         return;
196     }
197     auto tmpMap = std::make_shared<DOMAIN_INFO_MAP>();
198     ParseHiSysEventDef(hiSysEventDef, tmpMap);
199     hiSysEventDefMap_ = tmpMap;
200 }
201 } // namespace HiviewDFX
202 } // namespace OHOS
203