• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 #include "utils/utils.h"
16 
17 #include <fstream>
18 #include <vector>
19 #include <sys/stat.h>
20 #include "hilog_wrapper.h"
21 #ifdef __LINUX__
22 #include <cstring>
23 #endif
24 
25 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
26 #include "hitrace_meter.h"
27 #endif
28 
29 #ifdef __WINNT__
30 #include <shlwapi.h>
31 #include <windows.h>
32 #undef ERROR
33 #endif
34 
35 namespace OHOS {
36 namespace Global {
37 namespace Resource {
38 constexpr int ERROR_RESULT = -1;
39 
40 const std::set<std::string> Utils::tailSet {
41     ".hap",
42     ".hsp",
43 };
44 
45 std::vector<char> g_codes = {
46     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
47     'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
48     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
49     'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
50     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
51 };
52 
GetMediaBase64Data(const std::string & iconPath,std::string & base64Data)53 RState Utils::GetMediaBase64Data(const std::string& iconPath, std::string &base64Data)
54 {
55     size_t len = 0;
56     auto tempData = Utils::LoadResourceFile(iconPath, len);
57     if (tempData == nullptr) {
58         RESMGR_HILOGE(RESMGR_TAG, "get the tempData error");
59         return NOT_FOUND;
60     }
61     auto pos = iconPath.find_last_of('.');
62     std::string imgType;
63     if (pos != std::string::npos) {
64         imgType = iconPath.substr(pos + 1);
65     }
66     Utils::EncodeBase64(tempData, len, imgType, base64Data);
67     return SUCCESS;
68 }
69 
LoadResourceFile(const std::string & path,size_t & len)70 std::unique_ptr<uint8_t[]> Utils::LoadResourceFile(const std::string &path, size_t &len)
71 {
72     std::ifstream mediaStream(path, std::ios::binary);
73     if (!mediaStream.is_open()) {
74         return nullptr;
75     }
76     mediaStream.seekg(0, std::ios::end);
77     int length = mediaStream.tellg();
78     if (length == ERROR_RESULT) {
79         RESMGR_HILOGE(RESMGR_TAG, "failed to get the file length");
80         return nullptr;
81     } else {
82         len = static_cast<size_t>(length);
83     }
84     std::unique_ptr<uint8_t[]> tempData = std::make_unique<uint8_t[]>(len);
85     if (tempData == nullptr) {
86         return nullptr;
87     }
88     mediaStream.seekg(0, std::ios::beg);
89     mediaStream.read(reinterpret_cast<char *>(tempData.get()), len);
90     return tempData;
91 }
92 
EncodeBase64(std::unique_ptr<uint8_t[]> & data,int srcLen,const std::string & imgType,std::string & dstData)93 RState Utils::EncodeBase64(std::unique_ptr<uint8_t[]> &data, int srcLen,
94     const std::string &imgType, std::string &dstData)
95 {
96     const unsigned char *srcData = data.get();
97     if (srcData == nullptr) {
98         return ERROR;
99     }
100     std::string base64data;
101     base64data += "data:image/" + imgType + ";base64,";
102     int i = 0;
103     // encode in groups of every 3 bytes
104     for (; i <= srcLen - 3; i += 3) {
105         unsigned char byte1 = static_cast<unsigned char>(srcData[i]);
106         unsigned char byte2 = static_cast<unsigned char>(srcData[i + 1]);
107         unsigned char byte3 = static_cast<unsigned char>(srcData[i + 2]);
108         base64data += g_codes[byte1 >> BitOperatorNum::BIT_TWO];
109         base64data += g_codes[((byte1 & 0x3) << BitOperatorNum::BIT_FOUR) | (byte2 >> BitOperatorNum::BIT_FOUR)];
110         base64data += g_codes[((byte2 & 0xF) << BitOperatorNum::BIT_TWO) | (byte3 >> BitOperatorNum::BIT_SIX)];
111         base64data += g_codes[byte3 & 0x3F];
112     }
113 
114     if (i >= srcLen) {
115         dstData = base64data;
116         return SUCCESS;
117     }
118 
119     // Handle the case where there is one element left
120     if (srcLen % ArrayLen::LEN_THREE == 1) {
121         unsigned char byte1 = static_cast<unsigned char>(srcData[i]);
122         base64data += g_codes[byte1 >> BitOperatorNum::BIT_TWO];
123         base64data += g_codes[(byte1 & 0x3) << BitOperatorNum::BIT_FOUR];
124         base64data += '=';
125         base64data += '=';
126     } else if (srcLen % ArrayLen::LEN_THREE == ArrayIndex::INDEX_TWO) {
127         unsigned char byte1 = static_cast<unsigned char>(srcData[i]);
128         unsigned char byte2 = static_cast<unsigned char>(srcData[i + 1]);
129         base64data += g_codes[byte1 >> BitOperatorNum::BIT_TWO];
130         base64data += g_codes[((byte1 & 0x3) << BitOperatorNum::BIT_FOUR) | (byte2 >> BitOperatorNum::BIT_FOUR)];
131         base64data += g_codes[(byte2 & 0xF) << BitOperatorNum::BIT_TWO];
132         base64data += '=';
133     }
134     dstData = base64data;
135     return SUCCESS;
136 }
137 
IsAlphaString(const char * s,int32_t len)138 bool Utils::IsAlphaString(const char *s, int32_t len)
139 {
140     if (s == nullptr) {
141         return false;
142     }
143     int32_t i;
144     for (i = 0; i < len; i++) {
145         char c = *(s + i);
146         if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) {
147             return false;
148         }
149     }
150     return true;
151 }
152 
IsNumericString(const char * s,int32_t len)153 bool Utils::IsNumericString(const char *s, int32_t len)
154 {
155     if (s == nullptr) {
156         return false;
157     }
158     int32_t i;
159     for (i = 0; i < len; i++) {
160         char c = *(s + i);
161         if (!(c >= '0' && c <= '9')) {
162             return false;
163         }
164     }
165 
166     return true;
167 }
168 
169 /**
170  * @brief decode 32 bits as script array.
171  * 31-24 bits is script[0]
172  * 23-16 bits is script[1]
173  * 15-8 bits is script[2]
174  * 0-7 bits is script[3]
175  *
176  * @param encodeScript
177  * @param outValue
178  */
DecodeScript(uint32_t encodeScript,char * outValue)179 void Utils::DecodeScript(uint32_t encodeScript, char *outValue)
180 {
181     if (outValue == nullptr) {
182         return;
183     }
184     outValue[ArrayIndex::INDEX_ZERO] = (encodeScript & 0xFF000000) >> BitOperatorNum::BIT_TWENTY_FOUR;
185     outValue[ArrayIndex::INDEX_ONE] = (encodeScript & 0x00FF0000) >> BitOperatorNum::BIT_SIXTEEN;
186     outValue[ArrayIndex::INDEX_TWO] = (encodeScript & 0x0000FF00) >> BitOperatorNum::BIT_EIGHT;
187     outValue[ArrayIndex::INDEX_THREE] = (encodeScript & 0x000000FF);
188 }
189 
IsStrEmpty(const char * s)190 bool Utils::IsStrEmpty(const char *s)
191 {
192     return (s == nullptr || *s == '\0');
193 }
194 
StrLen(const char * s)195 size_t Utils::StrLen(const char *s)
196 {
197     if (s == nullptr) {
198         return 0;
199     }
200     return strlen(s);
201 }
202 
EncodeLanguage(const char * language)203 uint16_t Utils::EncodeLanguage(const char *language)
204 {
205     if (Utils::IsStrEmpty(language)) {
206         return NULL_LANGUAGE;
207     }
208     return Utils::EncodeLanguageOrRegion(language, 'a');
209 }
210 
211 /**
212  * @brief  locale compose of language,script and region,encode as 64bits.
213  * 63-48 bits represent language,detail format see EncodeLanguageOrRegion method
214  * 47-16 bits represent script,detail format see EncodeScript method
215  * 15-0 bits represent region,detail format see EncodeLanguageOrRegion method
216  *
217  * @param language
218  * @param script
219  * @param region
220  * @return uint64_t
221  */
EncodeLocale(const char * language,const char * script,const char * region)222 uint64_t Utils::EncodeLocale(const char *language,
223                              const char *script,
224                              const char *region)
225 {
226     uint16_t languageData = Utils::EncodeLanguage(language);
227     uint32_t scriptData = Utils::EncodeScript(script);
228     uint16_t regionData = Utils::EncodeRegion(region);
229 
230     return (uint64_t)(0xffff000000000000 & (((uint64_t)languageData) << BitOperatorNum::BIT_FORTY_EIGHT)) |
231            (0x0000ffffffff0000 & (((uint64_t)scriptData) << BitOperatorNum::BIT_SIXTEEN)) |
232            (0x000000000000ffff & (uint64_t)(regionData));
233 }
234 
EncodeRegionByResLocale(const ResLocale * locale)235 uint16_t Utils::EncodeRegionByResLocale(const ResLocale *locale)
236 {
237     if (locale == nullptr) {
238         return NULL_REGION;
239     }
240     return Utils::EncodeRegion(locale->GetRegion());
241 }
242 
EncodeLanguageByResLocale(const ResLocale * locale)243 uint16_t Utils::EncodeLanguageByResLocale(const ResLocale *locale)
244 {
245     if (locale == nullptr) {
246         return NULL_LANGUAGE;
247     }
248     return Utils::EncodeLanguage(locale->GetLanguage());
249 }
250 
EncodeScriptByResLocale(const ResLocale * locale)251 uint32_t Utils::EncodeScriptByResLocale(const ResLocale *locale)
252 {
253     if (locale == nullptr) {
254         return NULL_SCRIPT;
255     }
256     return Utils::EncodeScript(locale->GetScript());
257 }
258 
EncodeRegion(const char * region)259 uint16_t Utils::EncodeRegion(const char *region)
260 {
261     if (Utils::IsStrEmpty(region)) {
262         return NULL_REGION;
263     }
264     if (region[0] >= '0' && region[0] <= '9') {
265         return Utils::EncodeLanguageOrRegion(region, '0');
266     }
267     return Utils::EncodeLanguageOrRegion(region, 'A');
268 }
269 
270 /**
271  * @brief script is four letter array.encode script array as four bytes.Encode format.
272  * 31-24 bits represent script[0]
273  * 23-16 bits represent script[1]
274  * 15-8 bits represent script[2]
275  * 0-7 bits represent script[3]
276  *
277  * @param script
278  * @return uint32_t
279  */
EncodeScript(const char * script)280 uint32_t Utils::EncodeScript(const char *script)
281 {
282     if (Utils::IsStrEmpty(script)) {
283         return NULL_SCRIPT;
284     }
285     return ((uint8_t)script[ArrayIndex::INDEX_ZERO] << BitOperatorNum::BIT_TWENTY_FOUR) |
286         ((uint8_t)script[ArrayIndex::INDEX_ONE] << BitOperatorNum::BIT_SIXTEEN) |
287         ((uint8_t)script[ArrayIndex::INDEX_TWO] << BitOperatorNum::BIT_EIGHT) |
288         (uint8_t)script[ArrayIndex::INDEX_THREE];
289 }
290 
291 /**
292  * @brief encode language or region str as two byte.
293  * language is two or three lowercase.
294  * region is two capital  letter or three digit.
295  *
296  * two char,encode format
297  * 15-8 bits is the first char
298  * 7-0 bits is the second char
299  *
300  * three chars,encode format
301  * 15 bit is 1
302  * 14-10 bits represent the value of  the first char subtract base char,
303  * 9-5 bits represent the value of the second char subtract base char  .
304  * 4-0 bits represent the value of the third char subtract base char.
305  * base char is 'a','A','0'.
306  * example when base is 'a',max value('z' - 'a') is 26,so five bits can represent a char.
307  *
308  * @param str
309  * @param base is '0' or 'a' or 'A'
310  * @return uint16_t
311  */
EncodeLanguageOrRegion(const char * str,char base)312 uint16_t Utils::EncodeLanguageOrRegion(const char *str, char base)
313 {
314     if (str[ArrayIndex::INDEX_TWO] == 0 || str[ArrayIndex::INDEX_TWO] == '-' || str[ArrayIndex::INDEX_TWO] == '_') {
315         return ((uint8_t)str[ArrayIndex::INDEX_ZERO] << BitOperatorNum::BIT_EIGHT) |
316             ((uint8_t)str[ArrayIndex::INDEX_ONE]);
317     }
318     uint8_t first = ((uint8_t)(str[ArrayIndex::INDEX_ZERO] - base)) & 0x7f;
319     uint8_t second = ((uint8_t)(str[ArrayIndex::INDEX_ONE] - base)) & 0x7f;
320     uint8_t third = ((uint8_t)(str[ArrayIndex::INDEX_TWO] - base)) & 0x7f;
321     return ((0x80 | (first << BitOperatorNum::BIT_TWO) | (second >> BitOperatorNum::BIT_THREE)) <<
322         BitOperatorNum::BIT_EIGHT) | ((second << BitOperatorNum::BIT_FIVE) | third);
323 };
324 
StrCompare(const char * left,const char * right,size_t len,bool isCaseSensitive)325 bool Utils::StrCompare(const char *left, const char *right, size_t len, bool isCaseSensitive)
326 {
327     if (left == nullptr && right == nullptr) {
328         return true;
329     }
330 
331     if (left == nullptr || right == nullptr) {
332         return false;
333     }
334 
335     int rc;
336     unsigned char c1;
337     unsigned char c2;
338     while (len--) {
339         c1 = (unsigned char)*left;
340         c2 = (unsigned char)*right;
341         if (c1 == 0) {
342             if (c2 == 0) {
343                 return true;
344             }
345             return false;
346         } else if (c2 == 0) {
347             return false;
348         } else {
349             if (isCaseSensitive) {
350                 rc = (int)(c1) - (int)(c2);
351             } else {
352                 rc = tolower(c1) - tolower(c2);
353             }
354             if (rc != 0) {
355                 return false;
356             }
357         }
358         ++left;
359         ++right;
360     }
361     return true;
362 }
363 
364 /**
365  * @brief convert hex char as int value
366  *
367  * @param c
368  * @param state
369  * @return uint32_t
370  */
ParseHex(char c,RState & state)371 static uint32_t ParseHex(char c, RState &state)
372 {
373     if (c >= '0' && c <= '9') {
374         return (c - '0');
375     } else if (c >= 'a' && c <= 'f') {
376         return (c - 'a' + 0xa);
377     } else if (c >= 'A' && c <= 'F') {
378         return (c - 'A' + 0xa);
379     }
380     state = INVALID_FORMAT;
381     return -1;
382 }
383 
384 /**
385  * @brief  convert color string to 32 bits value 0xaarrggbb.
386  * color string format is
387  * #rgb  red (0-f) greed(0-f) blue(0-f)
388  * #argb transparency(0-f)  red (0-f) greed(0-f) blue(0-f)
389  * #rrggbb red (00-ff) greed(00-ff) blue(00-ff)
390  * #aarrggbb transparency(00-ff) red (00-ff) greed(00-ff) blue(00-ff)
391  *
392  * @param s
393  * @param outValue
394  * @return RState
395  */
ConvertColorToUInt32(const char * s,uint32_t & outValue)396 RState Utils::ConvertColorToUInt32(const char *s, uint32_t &outValue)
397 {
398     if (s == nullptr) {
399         return INVALID_FORMAT;
400     }
401     uint32_t color = 0;
402     RState parseState = SUCCESS;
403     size_t len = strlen(s);
404     if (*s == '#') {
405         if (len == ArrayLen::LEN_FOUR) {
406             color |= 0xFF000000;
407             color |= ParseHex(s[ArrayIndex::INDEX_ONE], parseState) << BitOperatorNum::BIT_TWENTY;
408             color |= ParseHex(s[ArrayIndex::INDEX_ONE], parseState) << BitOperatorNum::BIT_SIXTEEN;
409             color |= ParseHex(s[ArrayIndex::INDEX_TWO], parseState) << BitOperatorNum::BIT_TWELVE;
410             color |= ParseHex(s[ArrayIndex::INDEX_TWO], parseState) << BitOperatorNum::BIT_EIGHT;
411             color |= ParseHex(s[ArrayIndex::INDEX_THREE], parseState) << BitOperatorNum::BIT_FOUR;
412             color |= ParseHex(s[ArrayIndex::INDEX_THREE], parseState);
413         } else if (len == ArrayLen::LEN_FIVE) {
414             color |= ParseHex(s[ArrayIndex::INDEX_ONE], parseState) << BitOperatorNum::BIT_TWENTY_EIGHT;
415             color |= ParseHex(s[ArrayIndex::INDEX_ONE], parseState) << BitOperatorNum::BIT_TWENTY_FOUR;
416             color |= ParseHex(s[ArrayIndex::INDEX_TWO], parseState) << BitOperatorNum::BIT_TWENTY;
417             color |= ParseHex(s[ArrayIndex::INDEX_TWO], parseState) << BitOperatorNum::BIT_SIXTEEN;
418             color |= ParseHex(s[ArrayIndex::INDEX_THREE], parseState) << BitOperatorNum::BIT_TWELVE;
419             color |= ParseHex(s[ArrayIndex::INDEX_THREE], parseState) << BitOperatorNum::BIT_EIGHT;
420             color |= ParseHex(s[ArrayIndex::INDEX_FOUR], parseState) << BitOperatorNum::BIT_FOUR;
421             color |= ParseHex(s[ArrayIndex::INDEX_FOUR], parseState);
422         } else if (len == ArrayLen::LEN_SEVEN) {
423             color |= 0xFF000000;
424             color |= ParseHex(s[ArrayIndex::INDEX_ONE], parseState) << BitOperatorNum::BIT_TWENTY;
425             color |= ParseHex(s[ArrayIndex::INDEX_TWO], parseState) << BitOperatorNum::BIT_SIXTEEN;
426             color |= ParseHex(s[ArrayIndex::INDEX_THREE], parseState) << BitOperatorNum::BIT_TWELVE;
427             color |= ParseHex(s[ArrayIndex::INDEX_FOUR], parseState) << BitOperatorNum::BIT_EIGHT;
428             color |= ParseHex(s[ArrayIndex::INDEX_FIVE], parseState) << BitOperatorNum::BIT_FOUR;
429             color |= ParseHex(s[ArrayIndex::INDEX_SIX], parseState);
430         } else if (len == ArrayLen::LEN_NINE) {
431             color |= ParseHex(s[ArrayIndex::INDEX_ONE], parseState) << BitOperatorNum::BIT_TWENTY_EIGHT;
432             color |= ParseHex(s[ArrayIndex::INDEX_TWO], parseState) << BitOperatorNum::BIT_TWENTY_FOUR;
433             color |= ParseHex(s[ArrayIndex::INDEX_THREE], parseState) << BitOperatorNum::BIT_TWENTY;
434             color |= ParseHex(s[ArrayIndex::INDEX_FOUR], parseState) << BitOperatorNum::BIT_SIXTEEN;
435             color |= ParseHex(s[ArrayIndex::INDEX_FIVE], parseState) << BitOperatorNum::BIT_TWELVE;
436             color |= ParseHex(s[ArrayIndex::INDEX_SIX], parseState) << BitOperatorNum::BIT_EIGHT;
437             color |= ParseHex(s[ArrayIndex::INDEX_SEVEN], parseState) << BitOperatorNum::BIT_FOUR;
438             color |= ParseHex(s[ArrayIndex::INDEX_EIGHT], parseState);
439         }
440     } else {
441         parseState = INVALID_FORMAT;
442     }
443     outValue = color;
444     return parseState;
445 }
446 
endWithTail(const std::string & path,const std::string & tail)447 bool Utils::endWithTail(const std::string& path, const std::string& tail)
448 {
449     if (path.size() < tail.size()) {
450         RESMGR_HILOGE(RESMGR_TAG, "the path is shorter than tail");
451         return false;
452     }
453     return path.compare(path.size() - tail.size(), tail.size(), tail) == 0;
454 }
455 
IsFileExist(const std::string & filePath)456 bool Utils::IsFileExist(const std::string& filePath)
457 {
458     struct stat buffer;
459     return (stat(filePath.c_str(), &buffer) == 0);
460 }
461 
ContainsTail(std::string hapPath,std::set<std::string> tailSet)462 bool Utils::ContainsTail(std::string hapPath, std::set<std::string> tailSet)
463 {
464     for (auto tail : tailSet) {
465         if (Utils::endWithTail(hapPath, tail)) {
466             return true;
467         }
468     }
469     return false;
470 }
471 
CanonicalizePath(const char * path,char * outPath,size_t len)472 void Utils::CanonicalizePath(const char *path, char *outPath, size_t len)
473 {
474 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
475     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
476 #endif
477     if (path == nullptr) {
478         RESMGR_HILOGE(RESMGR_TAG, "path is null");
479         return;
480     }
481     if (strlen(path) >= len) {
482         RESMGR_HILOGE(RESMGR_TAG, "the length of path longer than len");
483         return;
484     }
485 #ifdef __WINNT__
486     if (!PathCanonicalizeA(outPath, path)) {
487         RESMGR_HILOGE(RESMGR_TAG, "failed to canonicalize the path");
488         return;
489     }
490 #else
491     if (realpath(path, outPath) == nullptr) {
492         RESMGR_HILOGE(RESMGR_TAG, "failed to realpath the path, %{public}s, errno:%{public}d", path, errno);
493         return;
494     }
495 #endif
496 }
497 
GetFiles(const std::string & strCurrentDir,std::vector<std::string> & vFiles)498 RState Utils::GetFiles(const std::string &strCurrentDir, std::vector<std::string> &vFiles)
499 {
500 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__)
501     char outPath[PATH_MAX + 1] = {0};
502     Utils::CanonicalizePath(strCurrentDir.c_str(), outPath, PATH_MAX);
503     if (outPath[0] == '\0') {
504         RESMGR_HILOGE(RESMGR_TAG, "invalid path, %{public}s", strCurrentDir.c_str());
505         return ERROR_CODE_RES_PATH_INVALID;
506     }
507     DIR *dir;
508     struct dirent *pDir;
509     if ((dir = opendir(strCurrentDir.c_str())) == nullptr) {
510         RESMGR_HILOGE(RESMGR_TAG, "opendir failed strCurrentDir = %{public}s", strCurrentDir.c_str());
511         return ERROR_CODE_RES_PATH_INVALID;
512     }
513     while ((pDir = readdir(dir)) != nullptr) {
514         if (strcmp(pDir->d_name, ".") == 0 || strcmp(pDir->d_name, "..") == 0) {
515             continue;
516         }
517         if (pDir->d_type != DT_REG && pDir->d_type != DT_DIR) {
518             continue;
519         }
520         vFiles.emplace_back(pDir->d_name);
521     }
522     closedir(dir);
523 #endif
524     return SUCCESS;
525 }
526 } // namespace Resource
527 } // namespace Global
528 } // namespace OHOS
529