• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "utils.h"
16 #include <algorithm>
17 #include <cerrno>
18 #include <climits>
19 #include <filesystem>
20 #include <fstream>
21 #include <iomanip>
22 #include <mutex>
23 #include <sstream>
24 #include <stdexcept>
25 #include <string>
26 #include <sys/stat.h>
27 #include <vector>
28 #include "accesstoken_kit.h"
29 #include "i18n_hilog.h"
30 #include "ipc_skeleton.h"
31 #include "locale_config.h"
32 #include "parameter.h"
33 #include "tokenid_kit.h"
34 #include "unicode/localebuilder.h"
35 
36 namespace OHOS {
37 namespace Global {
38 namespace I18n {
39 using namespace std;
40 static const std::string PSEUDO_LOCALE_TAG = "en-XA";
41 static const std::string PSEUDO_START_TAG = "{";
42 static const std::string PSEUDO_END_TAG = "}";
43 static const char CHAR_A = 'A';
44 static const int32_t CHAR2INT_SIZE = 2;
45 constexpr const char *TIMEZONE_LIST_CONFIG_PATH = "/system/etc/zoneinfo/timezone_list.cfg";
46 constexpr const char *DISTRO_TIMEZONE_LIST_CONFIG = "/system/etc/tzdata_distro/timezone_list.cfg";
47 static std::mutex validLocaleMutex;
48 
Split(const string & src,const string & sep,vector<string> & dest)49 void Split(const string &src, const string &sep, vector<string> &dest)
50 {
51     if (src.empty()) {
52         return;
53     }
54     string::size_type begin = 0;
55     string::size_type end = src.find(sep);
56     while (end != string::npos) {
57         dest.push_back(src.substr(begin, end - begin));
58         begin = end + sep.size();
59         end = src.find(sep, begin);
60     }
61     if (begin != src.size()) {
62         dest.push_back(src.substr(begin));
63     }
64 }
65 
Split(const std::string & src,const std::string & sep,std::unordered_set<std::string> & dest)66 void Split(const std::string& src, const std::string& sep, std::unordered_set<std::string>& dest)
67 {
68     dest.clear();
69     if (src.empty()) {
70         return;
71     }
72     std::string::size_type begin = 0;
73     std::string::size_type end = src.find(sep);
74     while (end != string::npos) {
75         dest.insert(src.substr(begin, end - begin));
76         begin = end + sep.size();
77         end = src.find(sep, begin);
78     }
79     if (begin != src.size()) {
80         dest.insert(src.substr(begin));
81     }
82 }
83 
Merge(const std::vector<std::string> & src,const std::string & sep,std::string & dest)84 void Merge(const std::vector<std::string>& src, const std::string& sep, std::string& dest)
85 {
86     if (src.size() == 0) {
87         dest = "";
88         return;
89     }
90     dest = src[0];
91     for (size_t i = 1; i < src.size(); ++i) {
92         dest += sep;
93         dest += src[i];
94     }
95 }
96 
ReadSystemParameter(const char * paramKey,const int paramLength)97 std::string ReadSystemParameter(const char *paramKey, const int paramLength)
98 {
99     char param[paramLength];
100     int status = GetParameter(paramKey, "", param, paramLength);
101     if (status > 0) {
102         return param;
103     }
104     return "";
105 }
106 
ConvertString2Int(const string & numberStr,int32_t & status)107 int32_t ConvertString2Int(const string &numberStr, int32_t& status)
108 {
109     if (!numberStr.empty() && std::all_of(numberStr.begin(), numberStr.end(), ::isdigit)) {
110         try {
111             return std::stoi(numberStr);
112         } catch (const std::invalid_argument &except) {
113             status = -1;
114             return -1;
115         } catch (const std::out_of_range &except) {
116             status = -1;
117             return -1;
118         } catch (...) {
119             status = -1;
120             HILOG_ERROR_I18N("ConvertString2Int: unknow error. numberStr: %{public}s.", numberStr.c_str());
121             return -1;
122         }
123     } else {
124         status = -1;
125         return -1;
126     }
127 }
128 
IsValidLocaleTag(icu::Locale & locale)129 bool IsValidLocaleTag(icu::Locale &locale)
130 {
131     static std::unordered_set<std::string> allValidLocalesLanguageTag;
132     GetAllValidLocalesTag(allValidLocalesLanguageTag);
133     std::string languageTag = locale.getLanguage() == nullptr ? "" : locale.getLanguage();
134     if (allValidLocalesLanguageTag.find(languageTag) == allValidLocalesLanguageTag.end()) {
135         HILOG_ERROR_I18N("GetTimePeriodName does not support this languageTag: %{public}s", languageTag.c_str());
136         return false;
137     }
138     return true;
139 }
140 
GetAllValidLocalesTag(std::unordered_set<std::string> & allValidLocalesLanguageTag)141 void GetAllValidLocalesTag(std::unordered_set<std::string>& allValidLocalesLanguageTag)
142 {
143     static bool init = false;
144     if (init) {
145         return;
146     }
147     std::lock_guard<std::mutex> matchLocaleLock(validLocaleMutex);
148     if (init) {
149         return;
150     }
151     int32_t validCount = 1;
152     const icu::Locale *validLocales = icu::Locale::getAvailableLocales(validCount);
153     if (validLocales == nullptr) {
154         return;
155     }
156     for (int i = 0; i < validCount; i++) {
157         const char* language = validLocales[i].getLanguage();
158         if (language != nullptr) {
159             allValidLocalesLanguageTag.insert(language);
160         }
161     }
162     init = true;
163 }
164 
CheckFilePath(const std::string & filePath)165 bool CheckFilePath(const std::string &filePath)
166 {
167     char* result = realpath(filePath.c_str(), nullptr);
168     if (result == nullptr) {
169         HILOG_ERROR_I18N("utils: CheckFilePath realpath error, error message: %{public}s.", strerror(errno));
170         return false;
171     }
172     std::ifstream file(result);
173     free(result);
174     result = nullptr;
175     if (!file.good()) {
176         HILOG_ERROR_I18N("utils: file open is not good.");
177         return false;
178     }
179     return true;
180 }
181 
StrReplaceAll(const std::string & str,const std::string & target,const std::string & replace)182 std::string StrReplaceAll(const std::string& str,
183     const std::string& target, const std::string& replace)
184 {
185     std::string::size_type pos = 0;
186     std::string result = str;
187     if (replace.empty() || target.compare(replace) == 0) {
188         return result;
189     }
190     while ((pos = result.find(target)) != std::string::npos) {
191         result.replace(pos, target.length(), replace);
192     }
193     return result;
194 }
195 
GetISO3Language(const string & language)196 std::string GetISO3Language(const string& language)
197 {
198     UErrorCode icuStatus = U_ZERO_ERROR;
199     icu::Locale locale = icu::Locale::forLanguageTag(language.data(), icuStatus);
200     if (U_FAILURE(icuStatus) || !IsValidLocaleTag(locale)) {
201         return "";
202     }
203     return locale.getISO3Language();
204 }
205 
GetISO3Country(const string & country)206 std::string GetISO3Country(const string& country)
207 {
208     UErrorCode icuStatus = U_ZERO_ERROR;
209     icu::Locale locale;
210     if (LocaleConfig::IsValidRegion(country)) {
211         locale = icu::LocaleBuilder().setLanguage("zh").setRegion(country).build(icuStatus);
212     } else if (LocaleConfig::IsValidTag(country)) {
213         locale = icu::Locale::forLanguageTag(country.data(), icuStatus);
214     } else {
215         return "";
216     }
217     if (U_FAILURE(icuStatus) || !IsValidLocaleTag(locale)) {
218         return "";
219     }
220     return locale.getISO3Country();
221 }
222 
FileExist(const std::string & path)223 bool FileExist(const std::string& path)
224 {
225     bool status = false;
226     try {
227         status = std::filesystem::exists(path.c_str());
228     } catch (const std::filesystem::filesystem_error &except) {
229         HILOG_ERROR_I18N("utils: FileExist failed because filesystem_error, error message: %{public}s.",
230             except.code().message().c_str());
231         return false;
232     } catch (const std::__h::__fs::filesystem::filesystem_error &except) {
233         HILOG_ERROR_I18N("utils: FileExist failed because filesystem_error, error message: %{public}s.",
234             except.code().message().c_str());
235         return false;
236     } catch (const std::bad_alloc &except) {
237         HILOG_ERROR_I18N("utils: FileExist failed because bad_alloc, error message: %{public}s.",
238             except.what());
239         return false;
240     }
241     return status;
242 }
243 
FileCopy(const std::string & srcPath,const std::string & dstPath)244 bool FileCopy(const std::string& srcPath, const std::string& dstPath)
245 {
246     try {
247         std::filesystem::copy(srcPath.c_str(), dstPath.c_str());
248         return true;
249     } catch (const std::filesystem::filesystem_error &except) {
250         HILOG_ERROR_I18N("utils: FileCopy failed because filesystem_error, error message: %{public}s.",
251             except.code().message().c_str());
252     } catch (const std::__h::__fs::filesystem::filesystem_error &except) {
253         HILOG_ERROR_I18N("utils: FileCopy failed because filesystem_error, error message: %{public}s.",
254             except.code().message().c_str());
255     } catch (const std::bad_alloc &except) {
256         HILOG_ERROR_I18N("utils: FileCopy failed because bad_alloc, error message: %{public}s.",
257             except.what());
258     }
259     return false;
260 }
261 
IsLegalPath(const std::string & path)262 bool IsLegalPath(const std::string& path)
263 {
264     if (path.find("./") != std::string::npos ||
265         path.find("../") != std::string::npos) {
266         return false;
267     }
268     return true;
269 }
270 
IsDirExist(const char * path)271 bool IsDirExist(const char *path)
272 {
273     if (!(path && *path)) {
274         return false;
275     }
276     size_t length = strlen(path);
277     if (length > PATH_MAX) {
278         return false;
279     }
280     char resolvedPath[PATH_MAX];
281     if (realpath(path, resolvedPath) == nullptr) {
282         return false;
283     }
284     struct stat buf;
285     return stat(resolvedPath, &buf) == 0 && S_ISDIR(buf.st_mode);
286 }
287 
ClearDir(const std::filesystem::path & dirPath)288 void ClearDir(const std::filesystem::path& dirPath)
289 {
290     std::error_code errCode;
291     for (const auto& entry : std::filesystem::directory_iterator(dirPath)) {
292         std::filesystem::remove_all(entry.path(), errCode);
293         if (errCode) {
294             HILOG_ERROR_I18N("ClearDir: Error removing file: %{public}s, Error: %{public}s", entry.path().c_str(),
295                 errCode.message().c_str());
296         }
297     }
298 }
299 
trim(std::string & s)300 std::string trim(std::string &s)
301 {
302     if (s.empty()) {
303         return s;
304     }
305     s.erase(0, s.find_first_not_of(" "));
306     s.erase(s.find_last_not_of(" ") + 1);
307     return s;
308 }
309 
GetPseudoLocalizationEnforce()310 bool GetPseudoLocalizationEnforce()
311 {
312     std::string systemLocale = LocaleConfig::GetSystemLocale();
313     if (systemLocale.compare(PSEUDO_LOCALE_TAG) == 0) {
314         return true;
315     }
316     return false;
317 }
318 
PseudoLocalizationProcessor(const std::string & input)319 std::string PseudoLocalizationProcessor(const std::string &input)
320 {
321     return PseudoLocalizationProcessor(input, GetPseudoLocalizationEnforce());
322 }
323 
PseudoLocalizationProcessor(const std::string & input,bool ifEnforce)324 std::string PseudoLocalizationProcessor(const std::string &input, bool ifEnforce)
325 {
326     if (ifEnforce) {
327         return PSEUDO_START_TAG + input + PSEUDO_END_TAG;
328     }
329     return input;
330 }
331 
CheckSystemPermission()332 bool CheckSystemPermission()
333 {
334     uint64_t tokenId = IPCSkeleton::GetCallingFullTokenID();
335     uint32_t callerToken = IPCSkeleton::GetCallingTokenID();
336     bool isSystemApp = Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(tokenId);
337     Security::AccessToken::ATokenTypeEnum tokenType =
338         Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken);
339     bool isShell = tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_SHELL;
340     bool isNative = tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE;
341     if (!isSystemApp && !isShell && !isNative) {
342         HILOG_ERROR_I18N("CheckSystemPermission failed, because current app is not system app.");
343         return false;
344     }
345     return true;
346 }
347 
GetTimeZoneAvailableIDs(I18nErrorCode & errorCode)348 std::set<std::string> GetTimeZoneAvailableIDs(I18nErrorCode &errorCode)
349 {
350     if (availableIDs.size() != 0) {
351         return availableIDs;
352     }
353     struct stat s;
354     const char *tzIdConfigPath = stat(DISTRO_TIMEZONE_LIST_CONFIG, &s) == 0 ?
355         DISTRO_TIMEZONE_LIST_CONFIG : TIMEZONE_LIST_CONFIG_PATH;
356     if (!CheckFilePath(tzIdConfigPath)) {
357         HILOG_ERROR_I18N("GetTimeZoneAvailableIDs: check file %{public}s failed.", tzIdConfigPath);
358         return availableIDs;
359     }
360     std::unique_ptr<char[]> resolvedPath = std::make_unique<char[]>(PATH_MAX + 1);
361     if (realpath(tzIdConfigPath, resolvedPath.get()) == nullptr) {
362         HILOG_ERROR_I18N("Get realpath failed, errno: %{public}d.", errno);
363         return availableIDs;
364     }
365     std::ifstream file(resolvedPath.get());
366     if (!file.good()) {
367         HILOG_ERROR_I18N("Open timezone list config file failed.");
368         return availableIDs;
369     }
370     std::string line;
371     while (std::getline(file, line)) {
372         if (line.length() == 0) {
373             break;
374         }
375         line.resize(line.find_last_not_of("\r\n") + 1);
376         availableIDs.insert(line);
377     }
378     file.close();
379     return availableIDs;
380 }
381 
RegexSearchNoExcept(const std::string & str,std::smatch & match,const std::regex & regex)382 bool RegexSearchNoExcept(const std::string& str, std::smatch& match, const std::regex& regex)
383 {
384     try {
385         return std::regex_search(str, match, regex);
386     } catch (const std::regex_error &except) {
387         HILOG_ERROR_I18N("RegexSearchNoExcept: regex_error caught %{public}s.", except.what());
388         return false;
389     }
390 }
391 
LocaleEncode(const std::string & locale)392 std::string LocaleEncode(const std::string& locale)
393 {
394     std::stringstream ss;
395     for (auto& c : locale) {
396         int32_t number = (c == '-') ? 0 : static_cast<int32_t>(c) - static_cast<int32_t>(CHAR_A) + 1;
397         ss << std::setw(CHAR2INT_SIZE) << std::setfill('0') << number;
398     }
399     return ss.str();
400 }
401 
Eq(double a,double b)402 bool Eq(double a, double b)
403 {
404     return fabs(a - b) < 1e-6;
405 }
406 
Geq(double a,double b)407 bool Geq(double a, double b)
408 {
409     return a > b || Eq(a, b);
410 }
411 
Leq(double a,double b)412 bool Leq(double a, double b)
413 {
414     return a < b || Eq(a, b);
415 }
416 } // namespace I18n
417 } // namespace Global
418 } // namespace OHOS