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 "operator_name_utils.h"
17 
18 #include <securec.h>
19 
20 #include "config_policy_utils.h"
21 #include "cstdint"
22 #include "cstdio"
23 #include "cstdlib"
24 #include "cstring"
25 #include "iosfwd"
26 #include "locale_config.h"
27 #include "locale_info.h"
28 #include "memory"
29 #include "parameter.h"
30 #include "telephony_errors.h"
31 #include "telephony_log_wrapper.h"
32 
33 namespace OHOS {
34 namespace Telephony {
35 OperatorNameUtils OperatorNameUtils::operatorNameUtils_;
36 const char *PATH = "/etc/telephony/operator_name.json";
37 const char *ITEM_OPERATOR_NAMES = "operator_names";
38 const char *ITEM_PLMN = "mcc_mnc_array";
39 const char *ITEM_ZH_CN = "zh_CN";
40 const char *ITEM_EN_US = "en_US";
41 const char *ITEM_ZH_TW = "zh_TW";
42 const char *ITEM_ZH_HK = "zh_HK";
43 const char *ITEM_ZH_HANS = "zh_Hans";
44 const char *ITEM_ZH_HANT = "zh_Hant";
45 const int MAX_BYTE_LEN = 10 * 1024 * 1024;
46 
GetInstance()47 OperatorNameUtils &OperatorNameUtils::GetInstance()
48 {
49     return operatorNameUtils_;
50 }
51 
Init()52 void OperatorNameUtils::Init()
53 {
54     std::unique_lock<std::mutex> lock(mutex_);
55     if (isInit_) {
56         TELEPHONY_LOGI("has init");
57         return;
58     }
59     nameArray_.clear();
60     ParserOperatorNameCustJson(nameArray_);
61     TELEPHONY_LOGI("init success");
62     isInit_ = true;
63 }
64 
IsInit()65 bool OperatorNameUtils::IsInit()
66 {
67     TELEPHONY_LOGD("is init %{public}d nameArray_ size %{public}zu", isInit_, nameArray_.size());
68     return isInit_;
69 }
70 
ParserOperatorNameCustJson(std::vector<OperatorNameCust> & vec)71 int32_t OperatorNameUtils::ParserOperatorNameCustJson(std::vector<OperatorNameCust> &vec)
72 {
73     char *content = nullptr;
74     char buf[MAX_PATH_LEN];
75     char *path = GetOneCfgFile(PATH, buf, MAX_PATH_LEN);
76     int32_t ret = TELEPHONY_SUCCESS;
77     if (path && *path != '\0') {
78         ret = LoaderJsonFile(content, path);
79     }
80     if (ret != TELEPHONY_SUCCESS) {
81         TELEPHONY_LOGE("load fail!");
82         return ret;
83     }
84     if (content == nullptr) {
85         TELEPHONY_LOGE("content is nullptr!");
86         return TELEPHONY_ERR_READ_DATA_FAIL;
87     }
88     cJSON *root = cJSON_Parse(content);
89     free(content);
90     content = nullptr;
91     if (root == nullptr) {
92         TELEPHONY_LOGE("json root is error!");
93         return TELEPHONY_ERR_READ_DATA_FAIL;
94     }
95 
96     cJSON *itemRoots = cJSON_GetObjectItem(root, ITEM_OPERATOR_NAMES);
97     if (itemRoots == nullptr || !cJSON_IsArray(itemRoots) || cJSON_GetArraySize(itemRoots) == 0) {
98         TELEPHONY_LOGE("operator name itemRoots is invalid");
99         cJSON_Delete(root);
100         itemRoots = nullptr;
101         root = nullptr;
102         return TELEPHONY_ERR_READ_DATA_FAIL;
103     }
104     ParserOperatorNames(vec, itemRoots);
105     cJSON_Delete(root);
106     itemRoots = nullptr;
107     root = nullptr;
108     return TELEPHONY_SUCCESS;
109 }
110 
LoaderJsonFile(char * & content,const char * path) const111 int32_t OperatorNameUtils::LoaderJsonFile(char *&content, const char *path) const
112 {
113     long len = 0;
114     char realPath[PATH_MAX] = { 0x00 };
115     if (realpath(path, realPath) == nullptr) {
116         TELEPHONY_LOGE("realpath fail! #PATH: %{public}s", path);
117         return TELEPHONY_ERR_READ_DATA_FAIL;
118     }
119     FILE *f = fopen(realPath, "rb");
120     if (f == nullptr) {
121         return TELEPHONY_ERR_READ_DATA_FAIL;
122     }
123     int ret_seek_end = fseek(f, 0, SEEK_END);
124     if (ret_seek_end != 0) {
125         TELEPHONY_LOGE("ret_seek_end != 0!");
126         CloseFile(f);
127         return TELEPHONY_ERR_READ_DATA_FAIL;
128     }
129     len = ftell(f);
130     int ret_seek_set = fseek(f, 0, SEEK_SET);
131     if (ret_seek_set != 0) {
132         CloseFile(f);
133         return TELEPHONY_ERR_READ_DATA_FAIL;
134     }
135     if (len == 0 || len > static_cast<long>(MAX_BYTE_LEN)) {
136         TELEPHONY_LOGE("len is valid!");
137         CloseFile(f);
138         return TELEPHONY_ERR_READ_DATA_FAIL;
139     }
140     content = static_cast<char *>(malloc(len + 1));
141     if (content == nullptr) {
142         CloseFile(f);
143         return TELEPHONY_ERR_READ_DATA_FAIL;
144     }
145     if (memset_s(content, len + 1, 0, len + 1) != EOK) {
146         TELEPHONY_LOGE("memset_s failed");
147         free(content);
148         content = nullptr;
149         CloseFile(f);
150         return TELEPHONY_ERR_READ_DATA_FAIL;
151     }
152     size_t ret_read = fread(content, 1, len, f);
153     if (ret_read != static_cast<size_t>(len)) {
154         free(content);
155         content = nullptr;
156         CloseFile(f);
157         return TELEPHONY_ERR_READ_DATA_FAIL;
158     }
159     return CloseFile(f);
160 }
161 
ParserOperatorNames(std::vector<OperatorNameCust> & vec,cJSON * itemRoots)162 void OperatorNameUtils::ParserOperatorNames(std::vector<OperatorNameCust> &vec, cJSON *itemRoots)
163 {
164     cJSON *itemRoot = nullptr;
165     cJSON *plmnArray = nullptr;
166     cJSON *arrValue = nullptr;
167     for (int32_t i = 0; i < cJSON_GetArraySize(itemRoots); i++) {
168         itemRoot = cJSON_GetArrayItem(itemRoots, i);
169         if (itemRoot == nullptr) {
170             continue;
171         }
172         OperatorNameCust nameCust;
173         plmnArray = cJSON_GetObjectItem(itemRoot, ITEM_PLMN);
174         if (plmnArray == nullptr || !cJSON_IsArray(plmnArray)) {
175             continue;
176         }
177         for (int32_t j = 0; j < cJSON_GetArraySize(plmnArray); j++) {
178             arrValue = cJSON_GetArrayItem(plmnArray, j);
179             if (arrValue != nullptr && cJSON_IsNumber(arrValue)) {
180                 nameCust.mccMnc.push_back(std::to_string(static_cast<int32_t>(cJSON_GetNumberValue(arrValue))));
181             }
182         }
183 
184         nameCust.zhCN = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_ZH_CN));
185         nameCust.enUS = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_EN_US));
186         nameCust.zhTW = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_ZH_TW));
187         nameCust.zhHK = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_ZH_HK));
188         nameCust.zhHans = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_ZH_HANS));
189         nameCust.zhHant = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_ZH_HANT));
190         vec.push_back(nameCust);
191     }
192     itemRoot = nullptr;
193     plmnArray = nullptr;
194     arrValue = nullptr;
195 }
196 
ParseString(cJSON * value)197 std::string OperatorNameUtils::ParseString(cJSON *value)
198 {
199     if (value != nullptr && value->type == cJSON_String && value->valuestring != nullptr) {
200         return value->valuestring;
201     }
202     return "";
203 }
204 
CloseFile(FILE * f) const205 int32_t OperatorNameUtils::CloseFile(FILE *f) const
206 {
207     int ret_close = fclose(f);
208     if (ret_close != 0) {
209         TELEPHONY_LOGE("ret_close != 0!");
210         return TELEPHONY_ERR_READ_DATA_FAIL;
211     }
212     return TELEPHONY_SUCCESS;
213 }
214 
GetNameByLocale(OperatorNameCust & value)215 std::string OperatorNameUtils::GetNameByLocale(OperatorNameCust &value)
216 {
217     std::string locale = OHOS::Global::I18n::LocaleConfig::GetSystemLocale();
218     OHOS::Global::I18n::LocaleInfo localeInfo(locale);
219     std::string languageCode = localeInfo.GetLanguage() + "_" + localeInfo.GetRegion();
220     std::string countryCodeTempScript = "";
221     if (!(localeInfo.GetScript().empty())) {
222         countryCodeTempScript = localeInfo.GetLanguage() + "_" + localeInfo.GetScript();
223     }
224     TELEPHONY_LOGD("locale is %{public}s, languageCode is %{public}s, countryCodeTempScript is %{public}s",
225         locale.c_str(), languageCode.c_str(), countryCodeTempScript.c_str());
226     if (countryCodeTempScript == std::string(ITEM_ZH_HANS)) {
227         languageCode = std::string(ITEM_ZH_HANS);
228     }
229     if (countryCodeTempScript == std::string(ITEM_ZH_HANT)) {
230         languageCode = std::string(ITEM_ZH_HANT);
231     }
232     if (languageCode == std::string(ITEM_ZH_CN)) {
233         return value.zhCN;
234     }
235     if (languageCode == std::string(ITEM_ZH_TW)) {
236         return value.zhTW;
237     }
238     if (languageCode == std::string(ITEM_ZH_HK)) {
239         return value.zhHK;
240     }
241     if (languageCode == std::string(ITEM_ZH_HANS)) {
242         return value.zhHans;
243     }
244     if (languageCode == std::string(ITEM_ZH_HANT)) {
245         return value.zhHant;
246     }
247     if (languageCode == std::string(ITEM_EN_US)) {
248         return value.enUS;
249     }
250     return value.enUS;
251 }
252 
GetCustomName(const std::string & numeric)253 std::string OperatorNameUtils::GetCustomName(const std::string &numeric)
254 {
255     if (!IsInit()) {
256         Init();
257     }
258     TELEPHONY_LOGD("Start");
259     std::unique_lock<std::mutex> lock(mutex_);
260     if (nameArray_.empty()) {
261         TELEPHONY_LOGE("nameArray_ is empty");
262         return "";
263     }
264     for (OperatorNameCust &value : nameArray_) {
265         auto obj = std::find(value.mccMnc.begin(), value.mccMnc.end(), numeric);
266         if (obj != value.mccMnc.end()) {
267             std::string name = GetNameByLocale(value);
268             TELEPHONY_LOGD("Name is %{public}s", name.c_str());
269             return name;
270         }
271     }
272     TELEPHONY_LOGD("Not found name %{public}s", numeric.c_str());
273     return "";
274 }
275 } // namespace Telephony
276 } // namespace OHOS
277