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 return TELEPHONY_ERR_READ_DATA_FAIL;
117 }
118 FILE *f = fopen(realPath, "rb");
119 if (f == nullptr) {
120 return TELEPHONY_ERR_READ_DATA_FAIL;
121 }
122 int ret_seek_end = fseek(f, 0, SEEK_END);
123 if (ret_seek_end != 0) {
124 TELEPHONY_LOGE("ret_seek_end != 0!");
125 CloseFile(f);
126 return TELEPHONY_ERR_READ_DATA_FAIL;
127 }
128 len = ftell(f);
129 int ret_seek_set = fseek(f, 0, SEEK_SET);
130 if (ret_seek_set != 0) {
131 CloseFile(f);
132 return TELEPHONY_ERR_READ_DATA_FAIL;
133 }
134 if (len == 0 || len > static_cast<long>(MAX_BYTE_LEN)) {
135 TELEPHONY_LOGE("len is valid!");
136 CloseFile(f);
137 return TELEPHONY_ERR_READ_DATA_FAIL;
138 }
139 content = static_cast<char *>(malloc(len + 1));
140 if (content == nullptr) {
141 CloseFile(f);
142 return TELEPHONY_ERR_READ_DATA_FAIL;
143 }
144 if (memset_s(content, len + 1, 0, len + 1) != EOK) {
145 TELEPHONY_LOGE("memset_s failed");
146 free(content);
147 content = nullptr;
148 CloseFile(f);
149 return TELEPHONY_ERR_READ_DATA_FAIL;
150 }
151 size_t ret_read = fread(content, 1, len, f);
152 if (ret_read != static_cast<size_t>(len)) {
153 free(content);
154 content = nullptr;
155 CloseFile(f);
156 return TELEPHONY_ERR_READ_DATA_FAIL;
157 }
158 return CloseFile(f);
159 }
160
ParserOperatorNames(std::vector<OperatorNameCust> & vec,cJSON * itemRoots)161 void OperatorNameUtils::ParserOperatorNames(std::vector<OperatorNameCust> &vec, cJSON *itemRoots)
162 {
163 cJSON *itemRoot = nullptr;
164 cJSON *plmnArray = nullptr;
165 cJSON *arrValue = nullptr;
166 for (int32_t i = 0; i < cJSON_GetArraySize(itemRoots); i++) {
167 itemRoot = cJSON_GetArrayItem(itemRoots, i);
168 if (itemRoot == nullptr) {
169 continue;
170 }
171 OperatorNameCust nameCust;
172 plmnArray = cJSON_GetObjectItem(itemRoot, ITEM_PLMN);
173 if (plmnArray == nullptr || !cJSON_IsArray(plmnArray)) {
174 continue;
175 }
176 for (int32_t j = 0; j < cJSON_GetArraySize(plmnArray); j++) {
177 arrValue = cJSON_GetArrayItem(plmnArray, j);
178 if (arrValue != nullptr && cJSON_IsNumber(arrValue)) {
179 nameCust.mccMnc.push_back(std::to_string(static_cast<int32_t>(cJSON_GetNumberValue(arrValue))));
180 }
181 }
182
183 nameCust.zhCN = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_ZH_CN));
184 nameCust.enUS = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_EN_US));
185 nameCust.zhTW = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_ZH_TW));
186 nameCust.zhHK = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_ZH_HK));
187 nameCust.zhHans = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_ZH_HANS));
188 nameCust.zhHant = ParseString(cJSON_GetObjectItem(itemRoot, ITEM_ZH_HANT));
189 vec.push_back(nameCust);
190 }
191 itemRoot = nullptr;
192 plmnArray = nullptr;
193 arrValue = nullptr;
194 }
195
ParseString(cJSON * value)196 std::string OperatorNameUtils::ParseString(cJSON *value)
197 {
198 if (value != nullptr && value->type == cJSON_String && value->valuestring != nullptr) {
199 return value->valuestring;
200 }
201 return "";
202 }
203
CloseFile(FILE * f) const204 int32_t OperatorNameUtils::CloseFile(FILE *f) const
205 {
206 int ret_close = fclose(f);
207 if (ret_close != 0) {
208 TELEPHONY_LOGE("ret_close != 0!");
209 return TELEPHONY_ERR_READ_DATA_FAIL;
210 }
211 return TELEPHONY_SUCCESS;
212 }
213
GetNameByLocale(OperatorNameCust & value)214 std::string OperatorNameUtils::GetNameByLocale(OperatorNameCust &value)
215 {
216 std::string locale = OHOS::Global::I18n::LocaleConfig::GetSystemLocale();
217 OHOS::Global::I18n::LocaleInfo localeInfo(locale);
218 std::string languageCode = localeInfo.GetLanguage() + "_" + localeInfo.GetRegion();
219 std::string countryCodeTempScript = "";
220 if (!(localeInfo.GetScript().empty())) {
221 countryCodeTempScript = localeInfo.GetLanguage() + "_" + localeInfo.GetScript();
222 }
223 TELEPHONY_LOGD("locale is %{public}s, languageCode is %{public}s, countryCodeTempScript is %{public}s",
224 locale.c_str(), languageCode.c_str(), countryCodeTempScript.c_str());
225 if (countryCodeTempScript == std::string(ITEM_ZH_HANS)) {
226 languageCode = std::string(ITEM_ZH_HANS);
227 }
228 if (countryCodeTempScript == std::string(ITEM_ZH_HANT)) {
229 languageCode = std::string(ITEM_ZH_HANT);
230 }
231 if (languageCode == std::string(ITEM_ZH_CN)) {
232 return value.zhCN;
233 }
234 if (languageCode == std::string(ITEM_ZH_TW)) {
235 return value.zhTW;
236 }
237 if (languageCode == std::string(ITEM_ZH_HK)) {
238 return value.zhHK;
239 }
240 if (languageCode == std::string(ITEM_ZH_HANS)) {
241 return value.zhHans;
242 }
243 if (languageCode == std::string(ITEM_ZH_HANT)) {
244 return value.zhHant;
245 }
246 if (languageCode == std::string(ITEM_EN_US)) {
247 return value.enUS;
248 }
249 return value.enUS;
250 }
251
GetCustomName(const std::string & numeric)252 std::string OperatorNameUtils::GetCustomName(const std::string &numeric)
253 {
254 if (!IsInit()) {
255 Init();
256 }
257 TELEPHONY_LOGD("Start");
258 std::unique_lock<std::mutex> lock(mutex_);
259 if (nameArray_.empty()) {
260 TELEPHONY_LOGE("nameArray_ is empty");
261 return "";
262 }
263 for (OperatorNameCust &value : nameArray_) {
264 auto obj = std::find(value.mccMnc.begin(), value.mccMnc.end(), numeric);
265 if (obj != value.mccMnc.end()) {
266 std::string name = GetNameByLocale(value);
267 TELEPHONY_LOGD("Name is %{public}s", name.c_str());
268 return name;
269 }
270 }
271 TELEPHONY_LOGD("Not found name %{public}s", numeric.c_str());
272 return "";
273 }
274 } // namespace Telephony
275 } // namespace OHOS
276