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