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