1 /*
2 * Copyright (C) 2022 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 "operator_file_parser.h"
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <climits>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <fstream>
23 #include <iterator>
24 #include <string_ex.h>
25 #include <unistd.h>
26 #include "config_policy_utils.h"
27 #include "sim_utils.h"
28 #include "telephony_types.h"
29
30 namespace OHOS {
31 namespace Telephony {
~OperatorFileParser()32 OperatorFileParser::~OperatorFileParser() {}
33
WriteOperatorConfigJson(std::string filename,const cJSON * root)34 bool OperatorFileParser::WriteOperatorConfigJson(std::string filename, const cJSON *root)
35 {
36 if (root == nullptr) {
37 TELEPHONY_LOGE("json is invalid");
38 return false;
39 }
40 if (!isCachePathExit()) {
41 if (mkdir(DEFAULT_OPERATE_CONFIG_DIR, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != SUCCESS) {
42 TELEPHONY_LOGE("CreateDirFailed");
43 return false;
44 }
45 }
46 FILE *file = nullptr;
47 file = fopen(GetOperatorConfigFilePath(filename).c_str(), "w");
48 if (file == nullptr) {
49 printf("OpenFileFailed");
50 return false;
51 }
52 char *cjValue = cJSON_Print(root);
53 if (cjValue == nullptr) {
54 printf("ParseJsonFailed");
55 (void)fclose(file);
56 file = nullptr;
57 return false;
58 }
59 int ret = fwrite(cjValue, sizeof(char), strlen(cjValue), file);
60 (void)fclose(file);
61 free(cjValue);
62 cjValue = nullptr;
63 file = nullptr;
64 if (ret == 0) {
65 printf("write json to file failed!");
66 return false;
67 }
68 return true;
69 }
70
ClearFilesCache()71 void OperatorFileParser::ClearFilesCache()
72 {
73 if (isCachePathExit()) {
74 TELEPHONY_LOGI("removeAllCache");
75 DeleteFiles();
76 }
77 }
78
DeleteFiles()79 void OperatorFileParser::DeleteFiles()
80 {
81 std::filesystem::path dirPath = std::string(DEFAULT_OPERATE_CONFIG_DIR);
82 std::error_code errorCode;
83 std::filesystem::remove_all(dirPath, errorCode);
84 if (errorCode.operator bool()) {
85 TELEPHONY_LOGE("delete fail, error code : %{public}d", errorCode.value());
86 } else {
87 TELEPHONY_LOGI("delete success");
88 }
89 }
90
isCachePathExit()91 bool OperatorFileParser::isCachePathExit()
92 {
93 return access(DEFAULT_OPERATE_CONFIG_DIR, F_OK) == SUCCESS;
94 }
95
GetOperatorConfigFilePath(std::string filename)96 std::string OperatorFileParser::GetOperatorConfigFilePath(std::string filename)
97 {
98 if (filename.empty()) {
99 TELEPHONY_LOGE("filename is empty");
100 return filename;
101 }
102 return std::string(DEFAULT_OPERATE_CONFIG_DIR) + "/" + filename;
103 }
104
ParseFromCustomSystem(int32_t slotId,OperatorConfig & opc,cJSON * root)105 bool OperatorFileParser::ParseFromCustomSystem(int32_t slotId, OperatorConfig &opc, cJSON *root)
106 {
107 int mode = MODE_SLOT_0;
108 if (slotId == SimSlotId::SIM_SLOT_1) {
109 mode = MODE_SLOT_1;
110 }
111 CfgFiles *cfgFiles = GetCfgFilesEx(DEFAULT_OPERATE_CONFIG_PATH, mode, nullptr);
112 if (cfgFiles == nullptr) {
113 TELEPHONY_LOGE("ParseFromCustomSystem cfgFiles is null");
114 return false;
115 }
116 char *filePath = nullptr;
117 cJSON *tempRoot = nullptr;
118 std::lock_guard<std::mutex> lock(mutex_);
119 tempConfig_.clear();
120 for (size_t i = 0; i < MAX_CFG_POLICY_DIRS_CNT; i++) {
121 filePath = cfgFiles->paths[i];
122 if (filePath && *filePath != '\0') {
123 bool ret = ParseOperatorConfigFromFile(opc, filePath, tempRoot, true);
124 if (!ret) {
125 TELEPHONY_LOGE("ParseFromCustomSystem failed");
126 continue;
127 }
128 }
129 }
130 CreateJsonFromOperatorConfig(root);
131 FreeCfgFiles(cfgFiles);
132 filePath = nullptr;
133 tempRoot = nullptr;
134 return true;
135 }
136
CreateJsonFromOperatorConfig(cJSON * root)137 void OperatorFileParser::CreateJsonFromOperatorConfig(cJSON *root)
138 {
139 for (auto it = tempConfig_.begin(); it != tempConfig_.end(); ++it) {
140 cJSON *jsontemp = cJSON_Parse(it->second.c_str());
141 if (jsontemp != nullptr) {
142 cJSON_AddItemToObject(root, it->first.c_str(), jsontemp);
143 }
144 }
145 tempConfig_.clear();
146 }
147
ParseOperatorConfigFromFile(OperatorConfig & opc,const std::string & path,cJSON * root,bool needSaveTempOpc)148 bool OperatorFileParser::ParseOperatorConfigFromFile(
149 OperatorConfig &opc, const std::string &path, cJSON *root, bool needSaveTempOpc)
150 {
151 char *content = nullptr;
152 int contentLength = LoaderJsonFile(content, path);
153 if (contentLength == LOADER_JSON_ERROR) {
154 TELEPHONY_LOGE("ParseOperatorConfigFromFile failed!");
155 return false;
156 }
157 root = cJSON_Parse(content);
158 free(content);
159 content = nullptr;
160 if (root == nullptr) {
161 TELEPHONY_LOGE("ParseOperatorConfigFromFile root is error!");
162 return false;
163 }
164 ParseOperatorConfigFromJson(root, opc, needSaveTempOpc);
165 cJSON_Delete(root);
166 return true;
167 }
168
ParseOperatorConfigFromJson(const cJSON * root,OperatorConfig & opc,bool needSaveTempOpc)169 void OperatorFileParser::ParseOperatorConfigFromJson(const cJSON *root, OperatorConfig &opc, bool needSaveTempOpc)
170 {
171 cJSON *value = root->child;
172 char *tempChar = nullptr;
173 std::map<std::u16string, std::u16string> &configValue = opc.configValue;
174 while (value) {
175 if (needSaveTempOpc) {
176 tempChar = cJSON_PrintUnformatted(value);
177 tempConfig_[value->string] = tempChar != nullptr ? tempChar : "";
178 if (tempChar != nullptr) {
179 free(tempChar);
180 }
181 }
182 tempChar = cJSON_Print(value);
183 configValue[Str8ToStr16(value->string)] = tempChar != nullptr ? Str8ToStr16(tempChar) : u"";
184 TELEPHONY_LOGI("ParseOperatorConfigFromFile key %{public}s value %{public}s", value->string,
185 Str16ToStr8(configValue[Str8ToStr16(value->string)]).c_str());
186 if (tempChar != nullptr) {
187 free(tempChar);
188 }
189 if (value->type == cJSON_Array) {
190 TELEPHONY_LOGD("parse type arrayValue");
191 if (cJSON_GetArraySize(value) > 0) {
192 ParseArray(value->string, value, opc);
193 }
194 } else if (value->type == cJSON_String) {
195 TELEPHONY_LOGD("parse type stringValue");
196 opc.stringValue[value->string] = value->valuestring;
197 configValue[Str8ToStr16(value->string)] = Str8ToStr16(value->valuestring);
198 } else if (value->type == cJSON_Number) {
199 TELEPHONY_LOGD("parse type initValue");
200 int64_t lValue = static_cast<int64_t>(cJSON_GetNumberValue(value));
201 configValue[Str8ToStr16(value->string)] = Str8ToStr16(std::to_string(lValue));
202 if (lValue > INT_MAX) {
203 TELEPHONY_LOGD("value is long");
204 opc.longValue[value->string] = lValue;
205 } else {
206 opc.intValue[value->string] = static_cast<int32_t>(lValue);
207 }
208 } else if (value->type == cJSON_True) {
209 TELEPHONY_LOGD("parse type booleanValue true");
210 opc.boolValue[value->string] = true;
211 configValue[Str8ToStr16(value->string)] = Str8ToStr16("true");
212 } else if (value->type == cJSON_False) {
213 opc.boolValue[value->string] = false;
214 configValue[Str8ToStr16(value->string)] = Str8ToStr16("false");
215 }
216 value = value->next;
217 }
218 tempChar = nullptr;
219 }
220
LoaderJsonFile(char * & content,const std::string & path)221 int32_t OperatorFileParser::LoaderJsonFile(char *&content, const std::string &path)
222 {
223 std::ifstream ifs;
224 ifs.open(path);
225 if (ifs.fail()) {
226 TELEPHONY_LOGE("LoaderJsonFile path failed");
227 return LOADER_JSON_ERROR;
228 }
229 ifs.seekg(0, std::ios::end);
230 uint64_t len = static_cast<uint64_t>(ifs.tellg());
231 if (len == 0 || len > MAX_BYTE_LEN) {
232 TELEPHONY_LOGE("LoaderJsonFile len <= 0 or len > MAX_BYTE_LEN!");
233 ifs.close();
234 return LOADER_JSON_ERROR;
235 }
236 content = static_cast<char *>(malloc(len + 1));
237 if (content == nullptr) {
238 TELEPHONY_LOGE("LoaderJsonFile malloc content fail!");
239 ifs.close();
240 return LOADER_JSON_ERROR;
241 }
242 if (memset_s(content, len + 1, 0, len + 1) != EOK) {
243 TELEPHONY_LOGE("LoaderJsonFile memset_s failed");
244 free(content);
245 content = nullptr;
246 ifs.close();
247 return LOADER_JSON_ERROR;
248 }
249 ifs.seekg(0, std::ios::beg);
250 ifs.read(content, len);
251 ifs.close();
252 return len;
253 }
254
CloseFile(FILE * f)255 bool OperatorFileParser::CloseFile(FILE *f)
256 {
257 int ret_close = fclose(f);
258 if (ret_close != 0) {
259 TELEPHONY_LOGE("LoaderJsonFile ret_close != 0!");
260 return false;
261 }
262 return true;
263 }
264
ParseArray(const std::string key,const cJSON * value,OperatorConfig & opc)265 void OperatorFileParser::ParseArray(const std::string key, const cJSON *value, OperatorConfig &opc)
266 {
267 if (value == nullptr || cJSON_GetArraySize(value) <= 0 || value->child == nullptr) {
268 return;
269 }
270 cJSON *arrayValue = value->child;
271 auto valueType = arrayValue->type;
272 if (valueType == cJSON_String) {
273 TELEPHONY_LOGI("parse string array");
274 if (opc.stringArrayValue.find(key) == opc.stringArrayValue.end()) {
275 opc.stringArrayValue[key] = std::vector<std::string>();
276 }
277 while (arrayValue) {
278 opc.stringArrayValue[key].push_back(arrayValue->valuestring);
279 arrayValue = arrayValue->next;
280 }
281 } else if (valueType == cJSON_Number && static_cast<int64_t>(cJSON_GetNumberValue(arrayValue)) > INT_MAX) {
282 TELEPHONY_LOGI("parse long array");
283 if (opc.longArrayValue.find(key) == opc.longArrayValue.end()) {
284 opc.longArrayValue[key] = std::vector<int64_t>();
285 }
286 while (arrayValue) {
287 opc.longArrayValue[key].push_back(static_cast<int64_t>(cJSON_GetNumberValue(arrayValue)));
288 arrayValue = arrayValue->next;
289 }
290 } else if (valueType == cJSON_Number) {
291 TELEPHONY_LOGI("parse int array");
292 if (opc.intArrayValue.find(key) == opc.intArrayValue.end()) {
293 opc.intArrayValue[key] = std::vector<int32_t>();
294 }
295 while (arrayValue) {
296 opc.intArrayValue[key].push_back(static_cast<int32_t>(cJSON_GetNumberValue(arrayValue)));
297 arrayValue = arrayValue->next;
298 }
299 }
300 arrayValue = nullptr;
301 }
302 } // namespace Telephony
303 } // namespace OHOS
304