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