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