1 /*
2  * Copyright (c) 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 "json_utils.h"
17 
18 #include <climits>
19 #include <fcntl.h>
20 #include <fstream>
21 #include <sstream>
22 #include <unistd.h>
23 #include <vector>
24 
25 #include "standby_service_log.h"
26 
27 namespace OHOS {
28 namespace DevStandbyMgr {
29 namespace {
30     constexpr uint32_t JSON_FORMAT = 4;
31 }
32 
LoadJsonValueFromContent(nlohmann::json & jsonValue,const std::string & content)33 bool JsonUtils::LoadJsonValueFromContent(nlohmann::json& jsonValue, const std::string& content)
34 {
35     if (content.empty()) {
36         STANDBYSERVICE_LOGE("content is empty");
37         return false;
38     }
39     jsonValue = nlohmann::json::parse(content, nullptr, false);
40     if (jsonValue.is_discarded()) {
41         STANDBYSERVICE_LOGE("failed to parse content");
42         return false;
43     }
44     if (!jsonValue.is_object()) {
45         STANDBYSERVICE_LOGE("the content is not an object");
46         return false;
47     }
48     return true;
49 }
50 
LoadJsonValueFromFile(nlohmann::json & jsonValue,const std::string & filePath)51 bool JsonUtils::LoadJsonValueFromFile(nlohmann::json& jsonValue, const std::string& filePath)
52 {
53     std::string content;
54     if (!GetFileContent(filePath, content)) {
55         STANDBYSERVICE_LOGE("failed to load content from %{public}s", filePath.c_str());
56         return false;
57     }
58     if (content.empty()) {
59         STANDBYSERVICE_LOGE("content of %{public}s is empty", filePath.c_str());
60         return false;
61     }
62     jsonValue = nlohmann::json::parse(content, nullptr, false);
63     if (jsonValue.is_discarded()) {
64         STANDBYSERVICE_LOGE("failed to parse content from %{public}s", filePath.c_str());
65         return false;
66     }
67     if (!jsonValue.is_object()) {
68         STANDBYSERVICE_LOGE("the content of %{public}s is not an object ", filePath.c_str());
69         return false;
70     }
71     return true;
72 }
73 
DumpJsonValueToFile(const nlohmann::json & jsonValue,const std::string & filePath)74 bool JsonUtils::DumpJsonValueToFile(const nlohmann::json& jsonValue, const std::string& filePath)
75 {
76     if (!CreateNodeFile(filePath)) {
77         STANDBYSERVICE_LOGE("create file failed.");
78         return false;
79     }
80     std::ofstream fout;
81     std::string realPath;
82     if (!GetRealPath(filePath, realPath)) {
83         STANDBYSERVICE_LOGE("get real file path: %{public}s failed", filePath.c_str());
84         return false;
85     }
86     fout.open(realPath, std::ios::out);
87     if (!fout.is_open()) {
88         STANDBYSERVICE_LOGE("open file: %{public}s failed.", filePath.c_str());
89         return false;
90     }
91     fout << jsonValue.dump(JSON_FORMAT).c_str() << std::endl;
92     fout.close();
93     return true;
94 }
95 
CreateNodeFile(const std::string & filePath)96 bool JsonUtils::CreateNodeFile(const std::string &filePath)
97 {
98     if (access(filePath.c_str(), F_OK) == ERR_OK) {
99         STANDBYSERVICE_LOGD("the standby service config file: %{public}s already exists.", filePath.c_str());
100         return true;
101     }
102     std::string fullpath {""};
103     if (!GetRealPath(filePath, fullpath)) {
104         STANDBYSERVICE_LOGD("the standby service config file: %{public}s not exists.", filePath.c_str());
105         fullpath = filePath;
106     }
107     int32_t fd = open(fullpath.c_str(), O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
108     if (fd < ERR_OK) {
109         STANDBYSERVICE_LOGE("Fail to open file: %{public}s", fullpath.c_str());
110         return false;
111     }
112     close(fd);
113     return true;
114 }
115 
GetInt32FromJsonValue(const nlohmann::json & jsonValue,const std::string & key,int32_t & value)116 bool JsonUtils::GetInt32FromJsonValue(const nlohmann::json& jsonValue, const std::string& key, int32_t& value)
117 {
118     if (jsonValue.empty() || key.empty()) {
119         return false;
120     }
121     if (jsonValue.contains(key) == 0 || !jsonValue.at(key).is_number_integer()) {
122         return false;
123     }
124     value =  jsonValue.at(key).get<int32_t>();
125     return true;
126 }
127 
GetBoolFromJsonValue(const nlohmann::json & jsonValue,const std::string & key,bool & value)128 bool JsonUtils::GetBoolFromJsonValue(const nlohmann::json& jsonValue, const std::string& key, bool& value)
129 {
130     if (jsonValue.empty() || key.empty()) {
131         return false;
132     }
133     if (jsonValue.contains(key) == 0 || !jsonValue.at(key).is_boolean()) {
134         return false;
135     }
136     value =  jsonValue.at(key).get<bool>();
137     return true;
138 }
139 
GetStringFromJsonValue(const nlohmann::json & jsonValue,const std::string & key,std::string & value)140 bool JsonUtils::GetStringFromJsonValue(const nlohmann::json& jsonValue, const std::string& key, std::string& value)
141 {
142     if (jsonValue.empty() || key.empty()) {
143         return false;
144     }
145     if (jsonValue.contains(key) == 0 || !jsonValue.at(key).is_string()) {
146         return false;
147     }
148     value =  jsonValue.at(key).get<std::string>();
149     return true;
150 }
151 
GetObjFromJsonValue(const nlohmann::json & jsonValue,const std::string & key,nlohmann::json & value)152 bool JsonUtils::GetObjFromJsonValue(const nlohmann::json& jsonValue, const std::string& key, nlohmann::json& value)
153 {
154     if (jsonValue.empty() || key.empty()) {
155         return false;
156     }
157     if (jsonValue.contains(key) == 0 || !jsonValue.at(key).is_object()) {
158         return false;
159     }
160     value =  jsonValue.at(key);
161     return true;
162 }
163 
GetArrayFromJsonValue(const nlohmann::json & jsonValue,const std::string & key,nlohmann::json & value)164 bool JsonUtils::GetArrayFromJsonValue(const nlohmann::json& jsonValue, const std::string& key, nlohmann::json& value)
165 {
166     if (jsonValue.empty() || key.empty()) {
167         return false;
168     }
169     if (jsonValue.contains(key) == 0 || !jsonValue.at(key).is_array()) {
170         return false;
171     }
172     value =  jsonValue.at(key);
173     return true;
174 }
175 
GetStrArrFromJsonValue(const nlohmann::json & jsonValue,const std::string & key,std::vector<std::string> & strArray)176 bool JsonUtils::GetStrArrFromJsonValue(const nlohmann::json& jsonValue, const std::string& key,
177     std::vector<std::string>& strArray)
178 {
179     nlohmann::json strArrayValue;
180     if (!JsonUtils::GetArrayFromJsonValue(jsonValue, key, strArrayValue)) {
181         return false;
182     }
183     strArray.clear();
184     for (const auto &strItem : strArrayValue) {
185         if (!strItem.is_string()) {
186             return false;
187         }
188         strArray.emplace_back(strItem.get<std::string>());
189     }
190     return true;
191 }
192 
GetFileContent(const std::string & filePath,std::string & content)193 bool JsonUtils::GetFileContent(const std::string& filePath, std::string& content)
194 {
195     std::string fullPath;
196     if (!GetRealPath(filePath, fullPath)) {
197         return false;
198     }
199     STANDBYSERVICE_LOGD("full path of standby service config file is: %{public}s ", fullPath.c_str());
200     std::ifstream fin(fullPath);
201     if (!fin.is_open()) {
202         return false;
203     }
204     std::ostringstream ss;
205     ss << fin.rdbuf();
206     content = ss.str();
207     return true;
208 }
209 
GetRealPath(const std::string & partialPath,std::string & fullPath)210 bool JsonUtils::GetRealPath(const std::string& partialPath, std::string& fullPath)
211 {
212     char tmpPath[PATH_MAX] = {0};
213     if (partialPath.size() > PATH_MAX || !realpath(partialPath.c_str(), tmpPath)) {
214         return false;
215     }
216     fullPath = tmpPath;
217     return true;
218 }
219 
SplitVersion(const std::string & versionStr,char versionDelim)220 std::vector<std::string> JsonUtils::SplitVersion(const std::string& versionStr, char versionDelim)
221 {
222     std::vector<std::string> tokens;
223     std::stringstream ss(versionStr);
224     std::string token;
225     while (std::getline(ss, token, versionDelim)) {
226         if (!token.empty()) {
227             tokens.push_back(token);
228         }
229     }
230     return tokens;
231 }
232 }  // namespace DevStandbyMgr
233 }  // namespace OHOS