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
16 #include "hap_parser.h"
17
18 #include <cstdlib>
19 #include <string>
20 #include <fcntl.h>
21 #include <unzip.h>
22 #include <unistd.h>
23 #include <set>
24 #include <sys/stat.h>
25 #include <unordered_map>
26
27 #include "hilog_wrapper.h"
28 #include "locale_matcher.h"
29 #if defined(__WINNT__)
30 #include <cstring>
31 #else
32 #include "securec.h"
33 #endif
34 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
35 #include "hitrace_meter.h"
36 #endif
37 #include "utils/errors.h"
38 #include "utils/string_utils.h"
39 #include "utils/utils.h"
40
41 namespace OHOS {
42 namespace Global {
43 namespace Resource {
44 const char *HapParser::RES_FILE_NAME = "/resources.index";
45 const std::string NOT_DEVICE_TYPE = "not_device_type";
46 const std::string DEVICE_DEFAULT = "default";
47 static const std::unordered_map<ResType, uint32_t> TYPE_MAP {
48 {INTEGER, SELECT_INTEGER},
49 {STRING, SELECT_STRING},
50 {STRINGARRAY, SELECT_STRINGARRAY},
51 {INTARRAY, SELECT_INTARRAY},
52 {BOOLEAN, SELECT_BOOLEAN},
53 {COLOR, SELECT_COLOR},
54 {THEME, SELECT_THEME},
55 {PLURALS, SELECT_PLURALS},
56 {FLOAT, SELECT_FLOAT},
57 {MEDIA, SELECT_MEDIA},
58 {PROF, SELECT_PROF},
59 {PATTERN, SELECT_PATTERN},
60 {SYMBOL, SELECT_SYMBOL}
61 };
62
63 struct SelectOptions {
64 bool match = true;
65 std::shared_ptr<ResConfigImpl> defaultConfig;
66 std::string deviceType;
67 uint32_t selectedTypes = SELECT_ALL;
68 };
69
LocateFile(unzFile & uf,const char * fileName)70 int32_t LocateFile(unzFile &uf, const char *fileName)
71 {
72 if (unzLocateFile2(uf, fileName, 1)) { // try to locate file inside zip, 1 = case sensitive
73 return UNKNOWN_ERROR;
74 }
75 return OK;
76 }
77
GetCurrentFileInfo(unzFile & uf,unz_file_info & fileInfo)78 int32_t GetCurrentFileInfo(unzFile &uf, unz_file_info &fileInfo)
79 {
80 // obtained the necessary details about file inside zip
81 char filenameInzip[256]; // for unzGetCurrentFileInfo
82 int err = unzGetCurrentFileInfo(uf, &fileInfo, filenameInzip, sizeof(filenameInzip), nullptr, 0, nullptr, 0);
83 if (err != UNZ_OK) {
84 RESMGR_HILOGE(RESMGR_TAG, "GetCurrentFileInfo failed");
85 return UNKNOWN_ERROR;
86 }
87 return OK;
88 }
89
ReadCurrentFile(unzFile & uf,unz_file_info & fileInfo,std::unique_ptr<uint8_t[]> & buffer,size_t & bufLen)90 int32_t ReadCurrentFile(unzFile &uf, unz_file_info &fileInfo, std::unique_ptr<uint8_t[]> &buffer,
91 size_t &bufLen)
92 {
93 buffer = std::make_unique<uint8_t[]>(fileInfo.uncompressed_size);
94 bufLen = fileInfo.uncompressed_size;
95 if (buffer == nullptr) {
96 RESMGR_HILOGE(RESMGR_TAG, "Error allocating memory for read buffer");
97 return UNKNOWN_ERROR;
98 }
99
100 int err = unzOpenCurrentFilePassword(uf, nullptr);
101 if (err != UNZ_OK) {
102 RESMGR_HILOGE(RESMGR_TAG, "Error %d in unzOpenCurrentFilePassword.", err);
103 return UNKNOWN_ERROR;
104 } // file inside the zip is open
105
106 err = unzReadCurrentFile(uf, buffer.get(), bufLen);
107 if (err < 0) {
108 RESMGR_HILOGE(RESMGR_TAG, "Error %d in unzReadCurrentFile", err);
109 return UNKNOWN_ERROR;
110 }
111
112 return OK;
113 }
114
ReadFileFromZip(unzFile & uf,const char * fileName,std::unique_ptr<uint8_t[]> & buffer,size_t & bufLen)115 int32_t HapParser::ReadFileFromZip(unzFile &uf, const char *fileName, std::unique_ptr<uint8_t[]> &buffer,
116 size_t &bufLen)
117 {
118 unz_file_info fileInfo;
119 if (LocateFile(uf, fileName) != OK) {
120 return UNKNOWN_ERROR;
121 }
122 if (GetCurrentFileInfo(uf, fileInfo) != OK) {
123 return UNKNOWN_ERROR;
124 }
125 if (ReadCurrentFile(uf, fileInfo, buffer, bufLen) != OK) {
126 return UNKNOWN_ERROR;
127 }
128 return OK;
129 }
130
GetModuleName(const char * configStr,size_t len)131 std::string GetModuleName(const char *configStr, size_t len)
132 {
133 if (configStr == nullptr) {
134 return std::string();
135 }
136 std::string config(configStr, len);
137 static const char *key = "\"moduleName\"";
138 auto idx = config.find(key);
139 if (idx == std::string::npos) {
140 return std::string();
141 }
142 auto start = config.find("\"", idx + strlen(key));
143 if (start == std::string::npos) {
144 return std::string();
145 }
146 auto end = config.find("\"", start + 1);
147 if (end == std::string::npos) {
148 return std::string();
149 }
150
151 if (end < start + 1) {
152 return std::string();
153 }
154 std::string retStr = std::string(configStr + start + 1, end - start - 1);
155 return retStr;
156 }
157
IsStageMode(unzFile & uf)158 bool HapParser::IsStageMode(unzFile &uf)
159 {
160 // stage mode contains "module.json", The 1 means the case sensitive
161 if (unzLocateFile2(uf, "module.json", 1) != UNZ_OK) {
162 return false;
163 }
164 return true;
165 }
166
ParseModuleNameFromHap(unzFile & uf)167 std::string ParseModuleNameFromHap(unzFile &uf)
168 {
169 std::unique_ptr<uint8_t[]> tmpBuf;
170 int32_t ret = UNZ_OK;
171 size_t tmpLen;
172 ret = HapParser::ReadFileFromZip(uf, "config.json", tmpBuf, tmpLen);
173 if (ret != OK) {
174 RESMGR_HILOGE(RESMGR_TAG, "read config.json error");
175 return std::string();
176 }
177 // parse config.json
178 std::string mName = GetModuleName(reinterpret_cast<char *>(tmpBuf.get()), tmpLen);
179 if (mName.size() == 0) {
180 RESMGR_HILOGE(RESMGR_TAG, "parse moduleName from config.json error");
181 return std::string();
182 }
183 return mName;
184 }
185
GetIndexFilePath(unzFile uf)186 std::string GetIndexFilePath(unzFile uf)
187 {
188 std::string mName = ParseModuleNameFromHap(uf);
189 std::string indexFilePath = std::string("assets/");
190 indexFilePath.append(mName);
191 indexFilePath.append("/resources.index");
192 return indexFilePath;
193 }
194
ReadFileInfoFromZip(unzFile & uf,const char * fileName,std::unique_ptr<uint8_t[]> & buffer,size_t & bufLen)195 int32_t ReadFileInfoFromZip(unzFile &uf, const char *fileName, std::unique_ptr<uint8_t[]> &buffer, size_t &bufLen)
196 {
197 int err = HapParser::ReadFileFromZip(uf, fileName, buffer, bufLen);
198 if (err < 0) {
199 unzClose(uf);
200 return UNKNOWN_ERROR;
201 }
202 unzClose(uf);
203 return OK;
204 }
205
ReadIndexFromFile(const char * zipFile,std::unique_ptr<uint8_t[]> & buffer,size_t & bufLen)206 int32_t HapParser::ReadIndexFromFile(const char *zipFile, std::unique_ptr<uint8_t[]> &buffer,
207 size_t &bufLen)
208 {
209 unzFile uf = unzOpen64(zipFile);
210 if (uf == nullptr) {
211 RESMGR_HILOGE(RESMGR_TAG, "Error open %{public}s in ReadIndexFromFile %{public}d", zipFile, errno);
212 return UNKNOWN_ERROR;
213 } // file is open
214 if (IsStageMode(uf)) {
215 return ReadFileInfoFromZip(uf, "resources.index", buffer, bufLen);
216 }
217 std::string indexFilePath = GetIndexFilePath(uf);
218 return ReadFileInfoFromZip(uf, indexFilePath.c_str(), buffer, bufLen);
219 }
220
GetPath(const std::string & filePath,std::string & rawFilePath)221 std::string HapParser::GetPath(const std::string &filePath, std::string &rawFilePath)
222 {
223 std::string tempName = filePath;
224 const std::string rawFileDirName = "rawfile/";
225 if (tempName.length() <= rawFileDirName.length()
226 || (tempName.compare(0, rawFileDirName.length(), rawFileDirName) != 0)) {
227 tempName = rawFileDirName + tempName;
228 }
229 rawFilePath.append(tempName);
230 return rawFilePath;
231 }
232
233 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
ParseModuleName(std::shared_ptr<AbilityBase::Extractor> & extractor)234 std::string HapParser::ParseModuleName(std::shared_ptr<AbilityBase::Extractor> &extractor)
235 {
236 if (extractor == nullptr) {
237 return std::string();
238 }
239 std::unique_ptr<uint8_t[]> configBuf;
240 size_t len;
241 bool ret = extractor->ExtractToBufByName("config.json", configBuf, len);
242 if (!ret) {
243 RESMGR_HILOGE(RESMGR_TAG, "failed to get config data from ability");
244 return std::string();
245 }
246 // parse config.json
247 std::string mName = GetModuleName(reinterpret_cast<char *>(configBuf.get()), len);
248 if (mName.size() == 0) {
249 RESMGR_HILOGE(RESMGR_TAG, "parse moduleName from config.json error");
250 return std::string();
251 }
252 return mName;
253 }
254
GetRawFilePathFromFA(std::shared_ptr<AbilityBase::Extractor> & extractor,const std::string & filePath)255 std::string GetRawFilePathFromFA(std::shared_ptr<AbilityBase::Extractor> &extractor,
256 const std::string &filePath)
257 {
258 std::string moduleName = HapParser::ParseModuleName(extractor);
259 std::string rawFilePath("assets/");
260 rawFilePath.append(moduleName);
261 rawFilePath.append("/resources/");
262 HapParser::GetPath(filePath, rawFilePath);
263 return rawFilePath;
264 }
265
GetRawFilePathFromStage(const std::string & filePath)266 std::string GetRawFilePathFromStage(const std::string &filePath)
267 {
268 std::string rawFilePath("resources/");
269 HapParser::GetPath(filePath, rawFilePath);
270 return rawFilePath;
271 }
272
GetRawFilePath(std::shared_ptr<AbilityBase::Extractor> & extractor,const std::string & rawFileName)273 std::string HapParser::GetRawFilePath(std::shared_ptr<AbilityBase::Extractor> &extractor,
274 const std::string &rawFileName)
275 {
276 std::string rawfilePath;
277 if (extractor->IsStageModel()) {
278 rawfilePath = GetRawFilePathFromStage(rawFileName);
279 } else {
280 rawfilePath = GetRawFilePathFromFA(extractor, rawFileName);
281 }
282 return rawfilePath;
283 }
284 #endif
285
ReadRawFileFromHap(const std::string & hapPath,const std::string & rawFileName,size_t & len,std::unique_ptr<uint8_t[]> & outValue)286 RState HapParser::ReadRawFileFromHap(const std::string &hapPath, const std::string &rawFileName, size_t &len,
287 std::unique_ptr<uint8_t[]> &outValue)
288 {
289 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
290 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
291 bool isNewExtractor = false;
292 auto extractor = AbilityBase::ExtractorUtil::GetExtractor(hapPath, isNewExtractor);
293 if (extractor == nullptr) {
294 RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor hapPath, %{public}s", hapPath.c_str());
295 return NOT_FOUND;
296 }
297 std::string rawfilePath = HapParser::GetRawFilePath(extractor, rawFileName);
298 if (!extractor->HasEntry(rawfilePath)) {
299 RESMGR_HILOGD(RESMGR_TAG,
300 "the rawfile file %{public}s is not exist in %{public}s", rawfilePath.c_str(), hapPath.c_str());
301 return ERROR_CODE_RES_PATH_INVALID;
302 }
303 bool ret = extractor->ExtractToBufByName(rawfilePath, outValue, len);
304 if (!ret) {
305 RESMGR_HILOGE(RESMGR_TAG, "failed to get rawfile data rawfilePath, %{public}s, hapPath, %{public}s",
306 rawfilePath.c_str(), hapPath.c_str());
307 return NOT_FOUND;
308 }
309 #endif
310 return SUCCESS;
311 }
312
ReadRawFileDescriptor(const char * hapPath,const std::string & rawFileName,ResourceManager::RawFileDescriptor & descriptor)313 RState HapParser::ReadRawFileDescriptor(const char *hapPath, const std::string &rawFileName,
314 ResourceManager::RawFileDescriptor &descriptor)
315 {
316 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
317 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
318 char outPath[PATH_MAX + 1] = {0};
319 Utils::CanonicalizePath(hapPath, outPath, PATH_MAX);
320 bool isNewExtractor = false;
321 auto extractor = AbilityBase::ExtractorUtil::GetExtractor(outPath, isNewExtractor);
322 if (extractor == nullptr) {
323 RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor in ReadRawFileDescriptor hapPath, %{public}s", outPath);
324 return NOT_FOUND;
325 }
326 std::string rawfilePath = HapParser::GetRawFilePath(extractor, rawFileName);
327 if (!extractor->HasEntry(rawfilePath)) {
328 RESMGR_HILOGD(RESMGR_TAG,
329 "the rawfile file %{public}s is not exist in %{public}s", rawfilePath.c_str(), hapPath);
330 return ERROR_CODE_RES_PATH_INVALID;
331 }
332 AbilityBase::FileInfo fileInfo;
333 bool ret = extractor->GetFileInfo(rawfilePath, fileInfo);
334 if (!ret) {
335 RESMGR_HILOGE(RESMGR_TAG, "failed to get rawFileDescriptor rawfilePath, %{public}s", rawfilePath.c_str());
336 return NOT_FOUND;
337 }
338 int zipFd = open(outPath, O_RDONLY);
339 if (zipFd < 0) {
340 RESMGR_HILOGE(RESMGR_TAG, "failed open file %{public}s", outPath);
341 return NOT_FOUND;
342 }
343 descriptor.offset = static_cast<long>(fileInfo.offset);
344 descriptor.length = static_cast<long>(fileInfo.length);
345 descriptor.fd = zipFd;
346 #endif
347 return SUCCESS;
348 }
349
GetRawFileList(const std::string & hapPath,const std::string & rawDirPath,std::vector<std::string> & fileList)350 RState HapParser::GetRawFileList(const std::string &hapPath, const std::string &rawDirPath,
351 std::vector<std::string>& fileList)
352 {
353 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
354 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
355 bool isNewExtractor = false;
356 auto extractor = AbilityBase::ExtractorUtil::GetExtractor(hapPath, isNewExtractor);
357 if (extractor == nullptr) {
358 RESMGR_HILOGE(RESMGR_TAG,
359 "failed to get extractor from ability in GetRawFileList hapPath, %{public}s", hapPath.c_str());
360 return NOT_FOUND;
361 }
362 std::set<std::string> fileSet;
363 std::string rawfilePath = HapParser::GetRawFilePath(extractor, rawDirPath);
364 if (!extractor->IsDirExist(rawfilePath)) {
365 RESMGR_HILOGD(RESMGR_TAG,
366 "the rawfile dir %{public}s is not exist in %{public}s", rawfilePath.c_str(), hapPath.c_str());
367 return ERROR_CODE_RES_PATH_INVALID;
368 }
369 bool ret = extractor->GetFileList(rawfilePath, fileSet);
370 if (!ret) {
371 RESMGR_HILOGE(RESMGR_TAG, "failed to get fileSet from ability rawfilePath, %{public}s", rawfilePath.c_str());
372 return ERROR_CODE_RES_PATH_INVALID;
373 }
374 for (auto it = fileSet.begin(); it != fileSet.end(); it++) {
375 fileList.emplace_back(*it);
376 }
377 #endif
378 return SUCCESS;
379 }
380
GetRawFileListUnCompressed(const std::string & indexPath,const std::string & rawDirPath,std::vector<std::string> & fileList)381 RState HapParser::GetRawFileListUnCompressed(const std::string &indexPath, const std::string &rawDirPath,
382 std::vector<std::string>& fileList)
383 {
384 auto pos = indexPath.rfind('/');
385 if (pos == std::string::npos) {
386 return ERROR_CODE_RES_PATH_INVALID;
387 }
388 std::string rawFilePath = indexPath.substr(0, pos) + "/resources/";
389 HapParser::GetPath(rawDirPath, rawFilePath);
390 return Utils::GetFiles(rawFilePath, fileList);
391 }
392 /**
393 *
394 * @param buffer
395 * @param offset
396 * @param bufLen
397 * @param id
398 * @param includeTemi dose length include '\0'
399 * @return OK or ERROR
400 */
ParseString(const char * buffer,uint32_t & offset,const size_t & bufLen,std::string & id,bool includeTemi=true)401 int32_t ParseString(const char *buffer, uint32_t &offset, const size_t &bufLen, std::string &id,
402 bool includeTemi = true)
403 {
404 uint16_t strLen;
405 if (offset + IdItem::SIZE_LEN > bufLen) {
406 RESMGR_HILOGE(RESMGR_TAG, "ParseString length failed, the offset will be out of bounds");
407 return SYS_ERROR;
408 }
409 errno_t eret = memcpy_s(&strLen, sizeof(strLen), buffer + offset, IdItem::SIZE_LEN);
410 if (eret != OK || (includeTemi && strLen == 0)) {
411 return SYS_ERROR;
412 }
413 offset += IdItem::SIZE_LEN; // Offset value plus 2
414 if (offset + (includeTemi ? (strLen - 1) : strLen) > bufLen) {
415 RESMGR_HILOGE(RESMGR_TAG, "ParseString value failed, the offset will be out of bounds");
416 return SYS_ERROR;
417 }
418 std::string tmp = std::string(const_cast<char *>(buffer) + offset, includeTemi ? (strLen - 1) : strLen);
419 offset += includeTemi ? strLen : (strLen + 1);
420 id = tmp;
421 return OK;
422 }
423
424 /**
425 *
426 * @param buffer
427 * @param offset
428 * @param bufLen
429 * @param values
430 * @return
431 */
ParseStringArray(const char * buffer,uint32_t & offset,const size_t & bufLen,std::vector<std::string> & values)432 int32_t ParseStringArray(const char *buffer, uint32_t &offset, const size_t &bufLen, std::vector<std::string> &values)
433 {
434 uint16_t arrLen;
435 if (offset + IdItem::SIZE_LEN > bufLen) {
436 RESMGR_HILOGE(RESMGR_TAG, "ParseStringArray failed, the offset will be out of bounds");
437 return SYS_ERROR;
438 }
439 errno_t eret = memcpy_s(&arrLen, sizeof(arrLen), buffer + offset, IdItem::SIZE_LEN);
440 if (eret != OK) {
441 return SYS_ERROR;
442 }
443 offset += IdItem::SIZE_LEN; // Offset value plus 2
444 // next arrLen bytes are several strings. then after, is one '\0'
445 uint32_t startOffset = offset;
446 std::string value;
447 while (true) {
448 int32_t ret = ParseString(buffer, offset, bufLen, value, false);
449 if (ret != OK) {
450 return ret;
451 }
452 values.push_back(value);
453
454 uint32_t readSize = offset - startOffset;
455 if (readSize + 1 == arrLen) {
456 offset += 1; // after arrLen, got '\0'
457 break;
458 }
459 if (readSize + 1 > arrLen) {
460 // size not match, cannot > arrLen
461 return SYS_ERROR;
462 }
463 }
464
465 return OK;
466 }
467
ConvertType(ResType type)468 uint32_t ConvertType(ResType type)
469 {
470 auto it = TYPE_MAP.find(type);
471 if (it == TYPE_MAP.end()) {
472 return SELECT_ALL;
473 }
474 return it->second;
475 }
476
ParseIdItem(const char * buffer,uint32_t & offset,const size_t & bufLen,std::shared_ptr<IdItem> idItem,const uint32_t & selectedTypes)477 int32_t ParseIdItem(const char *buffer, uint32_t &offset, const size_t &bufLen, std::shared_ptr<IdItem> idItem,
478 const uint32_t &selectedTypes)
479 {
480 if (offset + IdItem::HEADER_LEN > bufLen) {
481 RESMGR_HILOGE(RESMGR_TAG, "Parse IdItemHeader failed, the offset will be out of bounds");
482 return SYS_ERROR;
483 }
484 errno_t eret = memcpy_s(idItem.get(), sizeof(IdItem), buffer + offset, IdItem::HEADER_LEN);
485 if (eret != OK) {
486 return SYS_ERROR;
487 }
488 if (selectedTypes != SELECT_ALL && (selectedTypes & ConvertType(idItem->resType_)) == 0) {
489 return OK;
490 }
491 offset += IdItem::HEADER_LEN;
492
493 idItem->JudgeArray();
494 if (idItem->isArray_) {
495 int32_t ret = ParseStringArray(buffer, offset, bufLen, idItem->values_);
496 if (ret != OK) {
497 return ret;
498 }
499 } else {
500 int32_t ret = ParseString(buffer, offset, bufLen, idItem->value_);
501 if (ret != OK) {
502 return ret;
503 }
504 idItem->valueLen_ = idItem->value_.size();
505 }
506 int32_t ret = ParseString(buffer, offset, bufLen, idItem->name_);
507 if (ret != OK) {
508 return ret;
509 }
510 return OK;
511 }
512
ParseId(const char * buffer,uint32_t & offset,const size_t & bufLen,std::shared_ptr<ResId> id,const uint32_t & selectedTypes)513 int32_t ParseId(const char *buffer, uint32_t &offset, const size_t &bufLen, std::shared_ptr<ResId> id,
514 const uint32_t &selectedTypes)
515 {
516 if (offset + ResId::RESID_HEADER_LEN > bufLen) {
517 RESMGR_HILOGE(RESMGR_TAG, "Parse ResIdHeader failed, the offset will be out of bounds");
518 return SYS_ERROR;
519 }
520 errno_t eret = memcpy_s(id.get(), sizeof(ResId), buffer + offset, ResId::RESID_HEADER_LEN);
521 if (eret != OK) {
522 return SYS_ERROR;
523 }
524 offset += ResId::RESID_HEADER_LEN;
525 if (id->tag_[ArrayIndex::INDEX_ZERO] != 'I' || id->tag_[ArrayIndex::INDEX_ONE] != 'D'
526 || id->tag_[ArrayIndex::INDEX_TWO] != 'S' || id->tag_[ArrayIndex::INDEX_THREE] != 'S') {
527 return -1;
528 }
529 for (uint32_t i = 0; i < id->count_; ++i) {
530 std::shared_ptr<IdParam> ip = std::make_shared<IdParam>();
531 if (ip == nullptr) {
532 RESMGR_HILOGE(RESMGR_TAG, "new IdParam failed when ParseId");
533 return SYS_ERROR;
534 }
535 if (offset + ResId::IDPARAM_HEADER_LEN > bufLen) {
536 RESMGR_HILOGE(RESMGR_TAG, "Parse IdParam failed, the offset will be out of bounds");
537 return SYS_ERROR;
538 }
539 errno_t eret = memcpy_s(ip.get(), sizeof(IdParam), buffer + offset, ResId::IDPARAM_HEADER_LEN);
540 if (eret != OK) {
541 return SYS_ERROR;
542 }
543 offset += ResId::IDPARAM_HEADER_LEN;
544 std::shared_ptr<IdItem> idItem = std::make_shared<IdItem>();
545 if (idItem == nullptr) {
546 RESMGR_HILOGE(RESMGR_TAG, "new IdItem failed when ParseId");
547 return SYS_ERROR;
548 }
549 uint32_t ipOffset = ip->offset_;
550 int32_t ret = ParseIdItem(buffer, ipOffset, bufLen, idItem, selectedTypes);
551 if (ret != OK) {
552 return ret;
553 }
554 ip->idItem_ = idItem;
555 id->idParams_.push_back(ip);
556 }
557
558 return OK;
559 }
560
IsLocaleMatch(const std::shared_ptr<ResConfigImpl> defaultConfig,const std::vector<std::shared_ptr<KeyParam>> & keyParams)561 bool IsLocaleMatch(const std::shared_ptr<ResConfigImpl> defaultConfig,
562 const std::vector<std::shared_ptr<KeyParam>> &keyParams)
563 {
564 if (defaultConfig == nullptr) {
565 return true;
566 }
567 auto config = HapParser::CreateResConfigFromKeyParams(keyParams);
568 if (config == nullptr) {
569 return false;
570 }
571 if (LocaleMatcher::Match(defaultConfig->GetResLocale(), config->GetResLocale())) {
572 return true;
573 }
574 RESMGR_HILOGD(RESMGR_TAG, "mismatch, do not parse %s", HapParser::ToFolderPath(keyParams).c_str());
575 return false;
576 }
577
ParseKeyParam(const char * buffer,uint32_t & offset,const size_t & bufLen,SelectOptions * options,std::shared_ptr<KeyParam> & kp)578 int32_t ParseKeyParam(const char *buffer, uint32_t &offset, const size_t &bufLen,
579 SelectOptions *options, std::shared_ptr<KeyParam> &kp)
580 {
581 kp = std::make_shared<KeyParam>();
582 if (kp == nullptr) {
583 RESMGR_HILOGE(RESMGR_TAG, "ParseKeyParam new KeyParam failed");
584 return SYS_ERROR;
585 }
586 if (offset + ResKey::KEYPARAM_HEADER_LEN > bufLen) {
587 RESMGR_HILOGE(RESMGR_TAG, "ParseKeyParam failed, the offset will be out of bounds");
588 return SYS_ERROR;
589 }
590 errno_t eret = memcpy_s(kp.get(), sizeof(KeyParam), buffer + offset, ResKey::KEYPARAM_HEADER_LEN);
591 if (eret != OK) {
592 return SYS_ERROR;
593 }
594 offset += ResKey::KEYPARAM_HEADER_LEN;
595 kp->InitStr();
596 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
597 auto resDeviceType = kp->GetDeviceTypeStr();
598 if (options->deviceType != DEVICE_DEFAULT && resDeviceType != NOT_DEVICE_TYPE &&
599 resDeviceType != options->deviceType) {
600 options->match = false;
601 }
602 #endif
603 return OK;
604 }
605
ParseKey(const char * buffer,uint32_t & offset,const size_t & bufLen,std::shared_ptr<ResKey> key,SelectOptions * options)606 int32_t ParseKey(const char *buffer, uint32_t &offset, const size_t &bufLen, std::shared_ptr<ResKey> key,
607 SelectOptions *options)
608 {
609 if (offset + ResKey::RESKEY_HEADER_LEN > bufLen) {
610 RESMGR_HILOGE(RESMGR_TAG, "Parse ResKeyHeader failed, the offset will be out of bounds");
611 return SYS_ERROR;
612 }
613 errno_t eret = memcpy_s(key.get(), sizeof(ResKey), buffer + offset, ResKey::RESKEY_HEADER_LEN);
614 if (eret != OK) {
615 return SYS_ERROR;
616 }
617 offset += ResKey::RESKEY_HEADER_LEN;
618 if (key->tag_[ArrayIndex::INDEX_ZERO] != 'K' || key->tag_[ArrayIndex::INDEX_ONE] != 'E'
619 || key->tag_[ArrayIndex::INDEX_TWO] != 'Y' || key->tag_[ArrayIndex::INDEX_THREE] != 'S') {
620 return -1;
621 }
622 for (uint32_t i = 0; i < key->keyParamsCount_; ++i) {
623 std::shared_ptr<KeyParam> kp;
624 if (ParseKeyParam(buffer, offset, bufLen, options, kp) != OK) {
625 return SYS_ERROR;
626 }
627 if (kp == nullptr) {
628 return SYS_ERROR;
629 }
630 key->keyParams_.push_back(kp);
631 }
632
633 key->resConfig_ = HapParser::CreateResConfigFromKeyParams(key->keyParams_);
634 if (!options->match || (options->selectedTypes != SELECT_ALL && options->defaultConfig &&
635 !options->defaultConfig->Match(key->resConfig_, false))) {
636 options->match = false;
637 return OK;
638 }
639
640 uint32_t idOffset = key->offset_;
641 std::shared_ptr<ResId> id = std::make_shared<ResId>();
642 if (id == nullptr) {
643 RESMGR_HILOGE(RESMGR_TAG, "new ResId failed when ParseKey");
644 return SYS_ERROR;
645 }
646 int32_t ret = ParseId(buffer, idOffset, bufLen, id, options->selectedTypes);
647 if (ret != OK) {
648 return ret;
649 }
650 key->resId_ = id;
651 return OK;
652 }
653
654
ParseResHex(const char * buffer,const size_t bufLen,ResDesc & resDesc,const std::shared_ptr<ResConfigImpl> defaultConfig,const uint32_t & selectedTypes)655 int32_t HapParser::ParseResHex(const char *buffer, const size_t bufLen, ResDesc &resDesc,
656 const std::shared_ptr<ResConfigImpl> defaultConfig, const uint32_t &selectedTypes)
657 {
658 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
659 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
660 #endif
661 ResHeader *resHeader = new (std::nothrow) ResHeader();
662 if (resHeader == nullptr) {
663 RESMGR_HILOGE(RESMGR_TAG, "new ResHeader failed when ParseResHex");
664 return SYS_ERROR;
665 }
666 uint32_t offset = 0;
667 if (offset + RES_HEADER_LEN > bufLen) {
668 RESMGR_HILOGE(RESMGR_TAG, "Parse ResHeader failed, the offset will be out of bounds");
669 delete (resHeader);
670 return SYS_ERROR;
671 }
672 errno_t eret = memcpy_s(resHeader, sizeof(ResHeader), buffer + offset, RES_HEADER_LEN);
673 if (eret != OK) {
674 delete (resHeader);
675 return SYS_ERROR;
676 }
677 offset += RES_HEADER_LEN;
678 if (resHeader->keyCount_ == 0 || resHeader->length_ == 0) {
679 delete (resHeader);
680 return UNKNOWN_ERROR;
681 }
682
683 resDesc.resHeader_ = resHeader;
684 const std::string deviceType = resDesc.GetCurrentDeviceType();
685 for (uint32_t i = 0; i < resHeader->keyCount_; i++) {
686 std::shared_ptr<ResKey> key = std::make_shared<ResKey>();
687 if (key == nullptr) {
688 RESMGR_HILOGE(RESMGR_TAG, "new ResKey failed when ParseResHex");
689 return SYS_ERROR;
690 }
691 SelectOptions selectOptions{true, defaultConfig, deviceType, selectedTypes};
692 int32_t ret = ParseKey(buffer, offset, bufLen, key, &selectOptions);
693 if (ret != OK) {
694 return ret;
695 }
696 if (selectOptions.match) {
697 resDesc.keys_.push_back(key);
698 }
699 }
700 return OK;
701 }
702
CreateResConfigFromKeyParams(const std::vector<std::shared_ptr<KeyParam>> & keyParams)703 std::shared_ptr<ResConfigImpl> HapParser::CreateResConfigFromKeyParams(
704 const std::vector<std::shared_ptr<KeyParam>> &keyParams)
705 {
706 auto resConfig = std::make_shared<ResConfigImpl>();
707 if (resConfig == nullptr) {
708 RESMGR_HILOGE(RESMGR_TAG, "new ResConfigImpl failed when CreateResConfigFromKeyParams");
709 return nullptr;
710 }
711 size_t len = keyParams.size();
712 // default path
713 if (len == 0) {
714 resConfig->SetColorMode(COLOR_MODE_NOT_SET);
715 return resConfig;
716 }
717 size_t i = 0;
718 ResConfigKey configKey;
719 for (i = 0; i < len; ++i) {
720 const std::shared_ptr<KeyParam> kp = keyParams.at(i);
721 if (kp->type_ == LANGUAGES) {
722 configKey.language = kp->GetStr().c_str();
723 } else if (kp->type_ == REGION) {
724 configKey.region = kp->GetStr().c_str();
725 } else if (kp->type_ == SCRIPT) {
726 configKey.script = kp->GetStr().c_str();
727 } else if (kp->type_ == SCREEN_DENSITY) {
728 configKey.screenDensity = GetScreenDensity(kp->value_);
729 } else if (kp->type_ == DEVICETYPE) {
730 configKey.deviceType = GetDeviceType(kp->value_);
731 } else if (kp->type_ == DIRECTION) {
732 if (kp->value_ == 0) {
733 configKey.direction = DIRECTION_VERTICAL;
734 } else {
735 configKey.direction = DIRECTION_HORIZONTAL;
736 }
737 } else if (kp->type_ == INPUTDEVICE) {
738 configKey.inputDevice = GetInputDevice(kp->value_);
739 } else if (kp->type_ == COLORMODE) {
740 configKey.colorMode = GetColorMode(kp->value_);
741 } else if (kp->type_ == MCC) {
742 configKey.mcc = GetMcc(kp->value_);
743 } else if (kp->type_ == MNC) {
744 configKey.mnc = GetMnc(kp->value_);
745 }
746 }
747
748 return BuildResConfig(&configKey);
749 }
750
BuildResConfig(ResConfigKey * configKey)751 std::shared_ptr<ResConfigImpl> HapParser::BuildResConfig(ResConfigKey *configKey)
752 {
753 if (configKey == nullptr) {
754 RESMGR_HILOGE(RESMGR_TAG, "configKey is null");
755 return nullptr;
756 }
757 auto resConfig = std::make_shared<ResConfigImpl>();
758 if (resConfig == nullptr) {
759 RESMGR_HILOGE(RESMGR_TAG, "new ResConfigImpl failed when BuildResConfig");
760 return nullptr;
761 }
762 resConfig->SetDeviceType(configKey->deviceType);
763 resConfig->SetDirection(configKey->direction);
764 resConfig->SetColorMode(configKey->colorMode);
765 resConfig->SetMcc(configKey->mcc);
766 resConfig->SetMnc(configKey->mnc);
767 resConfig->SetInputDevice(configKey->inputDevice);
768 resConfig->SetScreenDensity((configKey->screenDensity) / Utils::DPI_BASE);
769 RState r = resConfig->SetLocaleInfo(configKey->language, configKey->script, configKey->region);
770 if (r != SUCCESS) {
771 RESMGR_HILOGE(RESMGR_TAG,
772 "error set locale,lang %s,script %s,region %s", configKey->language, configKey->script, configKey->region);
773 }
774
775 return resConfig;
776 }
777
GetDeviceType(uint32_t value)778 DeviceType HapParser::GetDeviceType(uint32_t value)
779 {
780 DeviceType deviceType = DEVICE_NOT_SET;
781 if (value == DEVICE_CAR) {
782 deviceType = DEVICE_CAR;
783 } else if (value == DEVICE_PAD) {
784 deviceType = DEVICE_PAD;
785 } else if (value == DEVICE_PHONE) {
786 deviceType = DEVICE_PHONE;
787 } else if (value == DEVICE_TABLET) {
788 deviceType = DEVICE_TABLET;
789 } else if (value == DEVICE_TV) {
790 deviceType = DEVICE_TV;
791 } else if (value == DEVICE_WEARABLE) {
792 deviceType = DEVICE_WEARABLE;
793 } else if (value == DEVICE_TWOINONE) {
794 deviceType = DEVICE_TWOINONE;
795 }
796 return deviceType;
797 }
798
GetMcc(uint32_t value)799 uint32_t HapParser::GetMcc(uint32_t value)
800 {
801 return value;
802 }
803
GetMnc(uint32_t value)804 uint32_t HapParser::GetMnc(uint32_t value)
805 {
806 return value;
807 }
808
GetColorMode(uint32_t value)809 ColorMode HapParser::GetColorMode(uint32_t value)
810 {
811 ColorMode colorMode = COLOR_MODE_NOT_SET;
812 if (value == DARK) {
813 colorMode = DARK;
814 } else {
815 colorMode = LIGHT;
816 }
817 return colorMode;
818 }
819
GetInputDevice(uint32_t value)820 InputDevice HapParser::GetInputDevice(uint32_t value)
821 {
822 InputDevice inputDevice = INPUTDEVICE_NOT_SET;
823 if (value == INPUTDEVICE_POINTINGDEVICE) {
824 inputDevice = INPUTDEVICE_POINTINGDEVICE;
825 }
826 return inputDevice;
827 }
828
GetScreenDensity(uint32_t value)829 ScreenDensity HapParser::GetScreenDensity(uint32_t value)
830 {
831 ScreenDensity screenDensity = SCREEN_DENSITY_NOT_SET;
832 if (value == SCREEN_DENSITY_SDPI) {
833 screenDensity = SCREEN_DENSITY_SDPI;
834 } else if (value == SCREEN_DENSITY_MDPI) {
835 screenDensity = SCREEN_DENSITY_MDPI;
836 } else if (value == SCREEN_DENSITY_LDPI) {
837 screenDensity = SCREEN_DENSITY_LDPI;
838 } else if (value == SCREEN_DENSITY_XLDPI) {
839 screenDensity = SCREEN_DENSITY_XLDPI;
840 } else if (value == SCREEN_DENSITY_XXLDPI) {
841 screenDensity = SCREEN_DENSITY_XXLDPI;
842 } else if (value == SCREEN_DENSITY_XXXLDPI) {
843 screenDensity = SCREEN_DENSITY_XXXLDPI;
844 }
845 return screenDensity;
846 }
847
PathAppend(std::string & path,const std::string & append,const std::string & connector)848 void PathAppend(std::string &path, const std::string &append, const std::string &connector)
849 {
850 if (append.size() > 0) {
851 if (path.size() > 0) {
852 path.append(connector);
853 }
854 path.append(append);
855 }
856 }
857
ToFolderPath(const std::vector<std::shared_ptr<KeyParam>> & keyParams)858 std::string HapParser::ToFolderPath(const std::vector<std::shared_ptr<KeyParam>> &keyParams)
859 {
860 if (keyParams.size() == 0) {
861 return std::string("default");
862 }
863 // mcc-mnc-language_script_region-direction-deviceType-colorMode-inputDevice-screenDensity
864 Determiner determiner;
865 for (const auto &keyParam : keyParams) {
866 switch (keyParam->type_) {
867 case KeyType::LANGUAGES:
868 determiner.language = keyParam->GetStr();
869 break;
870 case KeyType::SCRIPT:
871 determiner.script = keyParam->GetStr();
872 break;
873 case KeyType::REGION:
874 determiner.region = keyParam->GetStr();
875 break;
876 case KeyType::DIRECTION:
877 determiner.direction = keyParam->GetStr();
878 break;
879 case KeyType::DEVICETYPE:
880 determiner.deviceType = keyParam->GetStr();
881 break;
882 case KeyType::COLORMODE:
883 determiner.colorMode = keyParam->GetStr();
884 break;
885 case KeyType::INPUTDEVICE:
886 determiner.inputDevice = keyParam->GetStr();
887 break;
888 case KeyType::MCC:
889 determiner.mcc = keyParam->GetStr();
890 break;
891 case KeyType::MNC:
892 determiner.mnc = keyParam->GetStr();
893 break;
894 case KeyType::SCREEN_DENSITY:
895 determiner.screenDensity = keyParam->GetStr();
896 break;
897 default:
898 break;
899 }
900 }
901
902 return BuildFolderPath(&determiner);
903 }
904
BuildFolderPath(Determiner * determiner)905 std::string HapParser::BuildFolderPath(Determiner *determiner)
906 {
907 std::string path;
908 if (determiner == nullptr) {
909 RESMGR_HILOGE(RESMGR_TAG, "determiner is null");
910 return path;
911 }
912 std::string connecter1("_");
913 std::string connecter2("-");
914 if (determiner->mcc.size() > 0) {
915 path.append(determiner->mcc);
916 if (determiner->mnc.size() > 0) {
917 PathAppend(path, determiner->mnc, connecter1);
918 }
919 if (determiner->language.size() > 0) {
920 PathAppend(path, determiner->language, connecter2);
921 }
922 } else {
923 if (determiner->language.size() > 0) {
924 path.append(determiner->language);
925 }
926 }
927 PathAppend(path, determiner->script, connecter1);
928 PathAppend(path, determiner->region, connecter1);
929 PathAppend(path, determiner->direction, connecter2);
930 PathAppend(path, determiner->deviceType, connecter2);
931 PathAppend(path, determiner->colorMode, connecter2);
932 PathAppend(path, determiner->inputDevice, connecter2);
933 PathAppend(path, determiner->screenDensity, connecter2);
934
935 return path;
936 }
937
IsRawDirFromHap(const char * hapPath,const std::string & pathName,bool & outValue)938 RState HapParser::IsRawDirFromHap(const char *hapPath, const std::string &pathName, bool &outValue)
939 {
940 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
941 if (pathName.empty()) {
942 RESMGR_HILOGE(RESMGR_TAG, "the rawfile path is empty");
943 return ERROR_CODE_RES_PATH_INVALID;
944 }
945 bool isNewExtractor = false;
946 auto extractor = AbilityBase::ExtractorUtil::GetExtractor(hapPath, isNewExtractor);
947 if (extractor == nullptr) {
948 RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor hapPath, %{public}s", hapPath);
949 return NOT_FOUND;
950 }
951 std::string rawPath = HapParser::GetRawFilePath(extractor, pathName);
952 if (extractor->HasEntry(rawPath)) {
953 outValue = false;
954 } else if (extractor->IsDirExist(rawPath)) {
955 outValue = true;
956 } else {
957 RESMGR_HILOGD(RESMGR_TAG, "the rawfile file %{public}s is not exist in %{public}s", rawPath.c_str(), hapPath);
958 return ERROR_CODE_RES_PATH_INVALID;
959 }
960 #endif
961 return SUCCESS;
962 }
963
IsRawDirUnCompressed(const std::string & pathName,bool & outValue)964 RState HapParser::IsRawDirUnCompressed(const std::string &pathName, bool &outValue)
965 {
966 char outPath[PATH_MAX + 1] = {0};
967 Utils::CanonicalizePath(pathName.c_str(), outPath, PATH_MAX);
968 struct stat fileStat {};
969 if (stat(outPath, &fileStat) != 0) {
970 RESMGR_HILOGE(RESMGR_TAG, "failed to get rawfile file info, %{public}s", outPath);
971 return ERROR_CODE_RES_PATH_INVALID;
972 }
973 if ((fileStat.st_mode & S_IFDIR)) {
974 outValue = true;
975 } else if ((fileStat.st_mode & S_IFREG)) {
976 outValue = false;
977 } else {
978 RESMGR_HILOGE(RESMGR_TAG, "the rawfile file %{public}s is not exist", outPath);
979 return ERROR_CODE_RES_PATH_INVALID;
980 }
981 return SUCCESS;
982 }
983 } // namespace Resource
984 } // namespace Global
985 } // namespace OHOS
986