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