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