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 *
414 * @param buffer
415 * @param offset
416 * @param bufLen
417 * @param id
418 * @param includeTemi dose length include '\0'
419 * @return OK or ERROR
420 */
ParseString(const char * buffer,uint32_t & offset,const size_t & bufLen,std::string & id,bool includeTemi=true)421 int32_t ParseString(const char *buffer, uint32_t &offset, const size_t &bufLen, std::string &id,
422 bool includeTemi = true)
423 {
424 uint16_t strLen;
425 if (offset + IdItem::SIZE_LEN > bufLen) {
426 RESMGR_HILOGE(RESMGR_TAG, "ParseString length failed, the offset will be out of bounds");
427 return SYS_ERROR;
428 }
429 errno_t eret = memcpy_s(&strLen, sizeof(strLen), buffer + offset, IdItem::SIZE_LEN);
430 if (eret != OK || (includeTemi && strLen == 0)) {
431 return SYS_ERROR;
432 }
433 offset += IdItem::SIZE_LEN; // Offset value plus 2
434 if (offset + (includeTemi ? (strLen - 1) : strLen) > bufLen) {
435 RESMGR_HILOGE(RESMGR_TAG, "ParseString value failed, the offset will be out of bounds");
436 return SYS_ERROR;
437 }
438 std::string tmp = std::string(const_cast<char *>(buffer) + offset, includeTemi ? (strLen - 1) : strLen);
439 offset += includeTemi ? strLen : (strLen + 1);
440 id = tmp;
441 return OK;
442 }
443
444 /**
445 *
446 * @param buffer
447 * @param offset
448 * @param bufLen
449 * @param values
450 * @return
451 */
ParseStringArray(const char * buffer,uint32_t & offset,const size_t & bufLen,std::vector<std::string> & values)452 int32_t ParseStringArray(const char *buffer, uint32_t &offset, const size_t &bufLen, std::vector<std::string> &values)
453 {
454 uint16_t arrLen;
455 if (offset + IdItem::SIZE_LEN > bufLen) {
456 RESMGR_HILOGE(RESMGR_TAG, "ParseStringArray failed, the offset will be out of bounds");
457 return SYS_ERROR;
458 }
459 errno_t eret = memcpy_s(&arrLen, sizeof(arrLen), buffer + offset, IdItem::SIZE_LEN);
460 if (eret != OK) {
461 return SYS_ERROR;
462 }
463 offset += IdItem::SIZE_LEN; // Offset value plus 2
464 // next arrLen bytes are several strings. then after, is one '\0'
465 uint32_t startOffset = offset;
466 std::string value;
467 while (true) {
468 int32_t ret = ParseString(buffer, offset, bufLen, value, false);
469 if (ret != OK) {
470 return ret;
471 }
472 values.push_back(value);
473
474 uint32_t readSize = offset - startOffset;
475 if (readSize + 1 == arrLen) {
476 offset += 1; // after arrLen, got '\0'
477 break;
478 }
479 if (readSize + 1 > arrLen) {
480 // size not match, cannot > arrLen
481 return SYS_ERROR;
482 }
483 }
484
485 return OK;
486 }
487
ConvertType(ResType type)488 uint32_t ConvertType(ResType type)
489 {
490 auto it = TYPE_MAP.find(type);
491 if (it == TYPE_MAP.end()) {
492 return SELECT_ALL;
493 }
494 return it->second;
495 }
496
ParseIdItem(const char * buffer,uint32_t & offset,const size_t & bufLen,std::shared_ptr<IdItem> idItem,const uint32_t & selectedTypes)497 int32_t ParseIdItem(const char *buffer, uint32_t &offset, const size_t &bufLen, std::shared_ptr<IdItem> idItem,
498 const uint32_t &selectedTypes)
499 {
500 if (offset + IdItem::HEADER_LEN > bufLen) {
501 RESMGR_HILOGE(RESMGR_TAG, "Parse IdItemHeader failed, the offset will be out of bounds");
502 return SYS_ERROR;
503 }
504 errno_t eret = memcpy_s(idItem.get(), sizeof(IdItem), buffer + offset, IdItem::HEADER_LEN);
505 if (eret != OK) {
506 return SYS_ERROR;
507 }
508 if (selectedTypes != SELECT_ALL && (selectedTypes & ConvertType(idItem->resType_)) == 0) {
509 return OK;
510 }
511 offset += IdItem::HEADER_LEN;
512
513 idItem->JudgeArray();
514 if (idItem->isArray_) {
515 int32_t ret = ParseStringArray(buffer, offset, bufLen, idItem->values_);
516 if (ret != OK) {
517 return ret;
518 }
519 } else {
520 int32_t ret = ParseString(buffer, offset, bufLen, idItem->value_);
521 if (ret != OK) {
522 return ret;
523 }
524 idItem->valueLen_ = idItem->value_.size();
525 }
526 int32_t ret = ParseString(buffer, offset, bufLen, idItem->name_);
527 if (ret != OK) {
528 return ret;
529 }
530 return OK;
531 }
532
ParseId(const char * buffer,uint32_t & offset,const size_t & bufLen,std::shared_ptr<ResId> id,const uint32_t & selectedTypes)533 int32_t ParseId(const char *buffer, uint32_t &offset, const size_t &bufLen, std::shared_ptr<ResId> id,
534 const uint32_t &selectedTypes)
535 {
536 if (offset + ResId::RESID_HEADER_LEN > bufLen) {
537 RESMGR_HILOGE(RESMGR_TAG, "Parse ResIdHeader failed, the offset will be out of bounds");
538 return SYS_ERROR;
539 }
540 errno_t eret = memcpy_s(id.get(), sizeof(ResId), buffer + offset, ResId::RESID_HEADER_LEN);
541 if (eret != OK) {
542 return SYS_ERROR;
543 }
544 offset += ResId::RESID_HEADER_LEN;
545 if (id->tag_[ArrayIndex::INDEX_ZERO] != 'I' || id->tag_[ArrayIndex::INDEX_ONE] != 'D'
546 || id->tag_[ArrayIndex::INDEX_TWO] != 'S' || id->tag_[ArrayIndex::INDEX_THREE] != 'S') {
547 return -1;
548 }
549 for (uint32_t i = 0; i < id->count_; ++i) {
550 std::shared_ptr<IdParam> ip = std::make_shared<IdParam>();
551 if (ip == nullptr) {
552 RESMGR_HILOGE(RESMGR_TAG, "new IdParam failed when ParseId");
553 return SYS_ERROR;
554 }
555 if (offset + ResId::IDPARAM_HEADER_LEN > bufLen) {
556 RESMGR_HILOGE(RESMGR_TAG, "Parse IdParam failed, the offset will be out of bounds");
557 return SYS_ERROR;
558 }
559 errno_t eret = memcpy_s(ip.get(), sizeof(IdParam), buffer + offset, ResId::IDPARAM_HEADER_LEN);
560 if (eret != OK) {
561 return SYS_ERROR;
562 }
563 offset += ResId::IDPARAM_HEADER_LEN;
564 std::shared_ptr<IdItem> idItem = std::make_shared<IdItem>();
565 if (idItem == nullptr) {
566 RESMGR_HILOGE(RESMGR_TAG, "new IdItem failed when ParseId");
567 return SYS_ERROR;
568 }
569 uint32_t ipOffset = ip->offset_;
570 int32_t ret = ParseIdItem(buffer, ipOffset, bufLen, idItem, selectedTypes);
571 if (ret != OK) {
572 return ret;
573 }
574 ip->idItem_ = idItem;
575 id->idParams_.push_back(ip);
576 }
577
578 return OK;
579 }
580
ParseKeyParam(ParserContext & context,uint32_t & offset,bool & match,std::shared_ptr<KeyParam> & kp)581 int32_t ParseKeyParam(ParserContext &context, uint32_t &offset, bool &match, std::shared_ptr<KeyParam> &kp)
582 {
583 kp = std::make_shared<KeyParam>();
584 if (kp == nullptr) {
585 RESMGR_HILOGE(RESMGR_TAG, "ParseKeyParam new KeyParam failed");
586 return SYS_ERROR;
587 }
588 if (offset + ResKey::KEYPARAM_HEADER_LEN > context.bufLen) {
589 RESMGR_HILOGE(RESMGR_TAG, "ParseKeyParam failed, the offset will be out of bounds");
590 return SYS_ERROR;
591 }
592 errno_t eret = memcpy_s(kp.get(), sizeof(KeyParam), context.buffer + offset, ResKey::KEYPARAM_HEADER_LEN);
593 if (eret != OK) {
594 return SYS_ERROR;
595 }
596 offset += ResKey::KEYPARAM_HEADER_LEN;
597 kp->InitStr();
598 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
599 auto resDeviceType = kp->GetDeviceTypeStr();
600 if (context.deviceType != DEVICE_DEFAULT && resDeviceType != NOT_DEVICE_TYPE &&
601 resDeviceType != context.deviceType) {
602 match = false;
603 }
604 #endif
605 return OK;
606 }
607
GetLimitKeyValue(uint32_t & limitKeyValue,KeyType type,std::vector<bool> & keyTypes)608 void GetLimitKeyValue(uint32_t &limitKeyValue, KeyType type, std::vector<bool> &keyTypes)
609 {
610 const uint32_t limitKeysBase = 0x00000001;
611 uint32_t typeValue = static_cast<uint32_t>(type);
612 if (type < KeyType::KEY_TYPE_MAX && !keyTypes[typeValue]) {
613 keyTypes[typeValue] = true;
614 limitKeyValue |= limitKeysBase << typeValue;
615 }
616 }
617
GetKeyParamsLocales(std::shared_ptr<KeyParam> kp,std::string & locale,bool & isLocale)618 void GetKeyParamsLocales(std::shared_ptr<KeyParam> kp, std::string &locale, bool &isLocale)
619 {
620 KeyType keyType = kp->type_;
621 if (keyType == KeyType::MCC || keyType == KeyType::MNC) {
622 return;
623 }
624 if (keyType == KeyType::LANGUAGES) {
625 locale = kp->GetStr();
626 isLocale = true;
627 return;
628 }
629 if (keyType == KeyType::SCRIPT) {
630 locale.append("-");
631 locale.append(kp->GetStr());
632 return;
633 }
634 if (keyType == KeyType::REGION) {
635 locale.append("-");
636 locale.append(kp->GetStr());
637 }
638 }
639
SkipParseItem(ParserContext & context,const std::shared_ptr<ResKey> & key,bool & match)640 bool SkipParseItem(ParserContext &context, const std::shared_ptr<ResKey> &key, bool &match)
641 {
642 if (!match || (context.selectedTypes != SELECT_ALL && context.defaultConfig &&
643 !context.defaultConfig->Match(key->resConfig_, false))) {
644 return true;
645 }
646
647 if (context.loadAll) {
648 return false;
649 }
650 if (!key->resConfig_->GetLocaleInfo()) {
651 return context.isUpdate;
652 }
653
654 if (context.defaultConfig && context.defaultConfig->MatchLocal(*key->resConfig_)) {
655 return false;
656 }
657
658 return true;
659 }
660
ParseKey(ParserContext & context,uint32_t & offset,std::shared_ptr<ResKey> key,bool & match,std::vector<bool> & keyTypes)661 int32_t ParseKey(ParserContext &context, uint32_t &offset, std::shared_ptr<ResKey> key,
662 bool &match, std::vector<bool> &keyTypes)
663 {
664 if (offset + ResKey::RESKEY_HEADER_LEN > context.bufLen) {
665 RESMGR_HILOGE(RESMGR_TAG, "Parse ResKeyHeader failed, the offset will be out of bounds");
666 return SYS_ERROR;
667 }
668 errno_t eret = memcpy_s(key.get(), sizeof(ResKey), context.buffer + offset, ResKey::RESKEY_HEADER_LEN);
669 if (eret != OK) {
670 return SYS_ERROR;
671 }
672 offset += ResKey::RESKEY_HEADER_LEN;
673 if (key->tag_[ArrayIndex::INDEX_ZERO] != 'K' || key->tag_[ArrayIndex::INDEX_ONE] != 'E'
674 || key->tag_[ArrayIndex::INDEX_TWO] != 'Y' || key->tag_[ArrayIndex::INDEX_THREE] != 'S') {
675 return -1;
676 }
677 std::string locale;
678 bool isLocale = false;
679 std::vector<std::shared_ptr<KeyParam>> keyParams;
680 for (uint32_t i = 0; i < key->keyParamsCount_; ++i) {
681 std::shared_ptr<KeyParam> kp;
682 if (ParseKeyParam(context, offset, match, kp) != OK) {
683 return SYS_ERROR;
684 }
685 if (kp == nullptr) {
686 return SYS_ERROR;
687 }
688 GetLimitKeyValue(context.limitKeyValue, kp->type_, keyTypes);
689 GetKeyParamsLocales(kp, locale, isLocale);
690 keyParams.push_back(kp);
691 }
692 if (isLocale) {
693 context.locales.emplace(locale);
694 }
695 key->resConfig_ = HapParser::CreateResConfigFromKeyParams(keyParams);
696 if (SkipParseItem(context, key, match)) {
697 match = false;
698 return OK;
699 }
700
701 uint32_t idOffset = key->offset_;
702 std::shared_ptr<ResId> id = std::make_shared<ResId>();
703 if (id == nullptr) {
704 RESMGR_HILOGE(RESMGR_TAG, "new ResId failed when ParseKey");
705 return SYS_ERROR;
706 }
707 int32_t ret = ParseId(context.buffer, idOffset, context.bufLen, id, context.selectedTypes);
708 if (ret != OK) {
709 return ret;
710 }
711 key->resId_ = id;
712 return OK;
713 }
714
ParseResHex(ParserContext & context)715 int32_t HapParser::ParseResHex(ParserContext &context)
716 {
717 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
718 HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
719 #endif
720 ResHeader resHeader;
721 uint32_t offset = 0;
722 if (offset + RES_HEADER_LEN > context.bufLen) {
723 RESMGR_HILOGE(RESMGR_TAG, "Parse ResHeader failed, the offset will be out of bounds");
724 return SYS_ERROR;
725 }
726 errno_t eret = memcpy_s(&resHeader, sizeof(ResHeader), context.buffer + offset, RES_HEADER_LEN);
727 if (eret != OK) {
728 return SYS_ERROR;
729 }
730 offset += RES_HEADER_LEN;
731 if (resHeader.keyCount_ == 0 || resHeader.length_ == 0) {
732 return UNKNOWN_ERROR;
733 }
734 context.deviceType = context.resDesc.GetCurrentDeviceType();
735 std::vector<bool> keyTypes(KeyType::KEY_TYPE_MAX, false);
736 for (uint32_t i = 0; i < resHeader.keyCount_; i++) {
737 std::shared_ptr<ResKey> key = std::make_shared<ResKey>();
738 if (key == nullptr) {
739 RESMGR_HILOGE(RESMGR_TAG, "new ResKey failed when ParseResHex");
740 return SYS_ERROR;
741 }
742 bool match = true;
743 int32_t ret = ParseKey(context, offset, key, match, keyTypes);
744 if (ret != OK) {
745 return ret;
746 }
747 if (match) {
748 context.resDesc.keys_.push_back(key);
749 }
750 }
751 return OK;
752 }
753
CreateResConfigFromKeyParams(const std::vector<std::shared_ptr<KeyParam>> & keyParams)754 std::shared_ptr<ResConfigImpl> HapParser::CreateResConfigFromKeyParams(
755 const std::vector<std::shared_ptr<KeyParam>> &keyParams)
756 {
757 auto resConfig = std::make_shared<ResConfigImpl>();
758 if (resConfig == nullptr) {
759 RESMGR_HILOGE(RESMGR_TAG, "new ResConfigImpl failed when CreateResConfigFromKeyParams");
760 return nullptr;
761 }
762 size_t len = keyParams.size();
763 // default path
764 if (len == 0) {
765 resConfig->SetColorMode(COLOR_MODE_NOT_SET);
766 return resConfig;
767 }
768 size_t i = 0;
769 ResConfigKey configKey;
770 for (i = 0; i < len; ++i) {
771 const std::shared_ptr<KeyParam> kp = keyParams.at(i);
772 if (kp->type_ == LANGUAGES) {
773 configKey.language = kp->GetStr().c_str();
774 } else if (kp->type_ == REGION) {
775 configKey.region = kp->GetStr().c_str();
776 } else if (kp->type_ == SCRIPT) {
777 configKey.script = kp->GetStr().c_str();
778 } else if (kp->type_ == SCREEN_DENSITY) {
779 configKey.screenDensity = GetScreenDensity(kp->value_);
780 } else if (kp->type_ == DEVICETYPE) {
781 configKey.deviceType = GetDeviceType(kp->value_);
782 } else if (kp->type_ == DIRECTION) {
783 if (kp->value_ == 0) {
784 configKey.direction = DIRECTION_VERTICAL;
785 } else {
786 configKey.direction = DIRECTION_HORIZONTAL;
787 }
788 } else if (kp->type_ == INPUTDEVICE) {
789 configKey.inputDevice = GetInputDevice(kp->value_);
790 } else if (kp->type_ == COLORMODE) {
791 configKey.colorMode = GetColorMode(kp->value_);
792 } else if (kp->type_ == MCC) {
793 configKey.mcc = GetMcc(kp->value_);
794 } else if (kp->type_ == MNC) {
795 configKey.mnc = GetMnc(kp->value_);
796 }
797 }
798
799 return BuildResConfig(&configKey);
800 }
801
BuildResConfig(ResConfigKey * configKey)802 std::shared_ptr<ResConfigImpl> HapParser::BuildResConfig(ResConfigKey *configKey)
803 {
804 if (configKey == nullptr) {
805 RESMGR_HILOGE(RESMGR_TAG, "configKey is null");
806 return nullptr;
807 }
808 auto resConfig = std::make_shared<ResConfigImpl>();
809 if (resConfig == nullptr) {
810 RESMGR_HILOGE(RESMGR_TAG, "new ResConfigImpl failed when BuildResConfig");
811 return nullptr;
812 }
813 resConfig->SetDeviceType(configKey->deviceType);
814 resConfig->SetDirection(configKey->direction);
815 resConfig->SetColorMode(configKey->colorMode);
816 resConfig->SetMcc(configKey->mcc);
817 resConfig->SetMnc(configKey->mnc);
818 resConfig->SetInputDevice(configKey->inputDevice);
819 resConfig->SetScreenDensity((configKey->screenDensity) / Utils::DPI_BASE);
820 RState r = resConfig->SetLocaleInfo(configKey->language, configKey->script, configKey->region);
821 if (r != SUCCESS) {
822 RESMGR_HILOGE(RESMGR_TAG,
823 "error set locale,lang %s,script %s,region %s", configKey->language, configKey->script, configKey->region);
824 }
825
826 return resConfig;
827 }
828
GetDeviceType(uint32_t value)829 DeviceType HapParser::GetDeviceType(uint32_t value)
830 {
831 DeviceType deviceType = DEVICE_NOT_SET;
832 if (value == DEVICE_CAR) {
833 deviceType = DEVICE_CAR;
834 } else if (value == DEVICE_PAD) {
835 deviceType = DEVICE_PAD;
836 } else if (value == DEVICE_PHONE) {
837 deviceType = DEVICE_PHONE;
838 } else if (value == DEVICE_TABLET) {
839 deviceType = DEVICE_TABLET;
840 } else if (value == DEVICE_TV) {
841 deviceType = DEVICE_TV;
842 } else if (value == DEVICE_WEARABLE) {
843 deviceType = DEVICE_WEARABLE;
844 } else if (value == DEVICE_TWOINONE) {
845 deviceType = DEVICE_TWOINONE;
846 }
847 return deviceType;
848 }
849
GetMcc(uint32_t value)850 uint32_t HapParser::GetMcc(uint32_t value)
851 {
852 return value;
853 }
854
GetMnc(uint32_t value)855 uint32_t HapParser::GetMnc(uint32_t value)
856 {
857 return value;
858 }
859
GetColorMode(uint32_t value)860 ColorMode HapParser::GetColorMode(uint32_t value)
861 {
862 ColorMode colorMode = COLOR_MODE_NOT_SET;
863 if (value == DARK) {
864 colorMode = DARK;
865 } else {
866 colorMode = LIGHT;
867 }
868 return colorMode;
869 }
870
GetInputDevice(uint32_t value)871 InputDevice HapParser::GetInputDevice(uint32_t value)
872 {
873 InputDevice inputDevice = INPUTDEVICE_NOT_SET;
874 if (value == INPUTDEVICE_POINTINGDEVICE) {
875 inputDevice = INPUTDEVICE_POINTINGDEVICE;
876 }
877 return inputDevice;
878 }
879
GetScreenDensity(uint32_t value)880 ScreenDensity HapParser::GetScreenDensity(uint32_t value)
881 {
882 ScreenDensity screenDensity = SCREEN_DENSITY_NOT_SET;
883 if (value == SCREEN_DENSITY_SDPI) {
884 screenDensity = SCREEN_DENSITY_SDPI;
885 } else if (value == SCREEN_DENSITY_MDPI) {
886 screenDensity = SCREEN_DENSITY_MDPI;
887 } else if (value == SCREEN_DENSITY_LDPI) {
888 screenDensity = SCREEN_DENSITY_LDPI;
889 } else if (value == SCREEN_DENSITY_XLDPI) {
890 screenDensity = SCREEN_DENSITY_XLDPI;
891 } else if (value == SCREEN_DENSITY_XXLDPI) {
892 screenDensity = SCREEN_DENSITY_XXLDPI;
893 } else if (value == SCREEN_DENSITY_XXXLDPI) {
894 screenDensity = SCREEN_DENSITY_XXXLDPI;
895 }
896 return screenDensity;
897 }
898
IsRawDirFromHap(const char * hapPath,const std::string & pathName,bool & outValue)899 RState HapParser::IsRawDirFromHap(const char *hapPath, const std::string &pathName, bool &outValue)
900 {
901 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
902 if (pathName.empty()) {
903 RESMGR_HILOGE(RESMGR_TAG, "the rawfile path is empty");
904 return ERROR_CODE_RES_PATH_INVALID;
905 }
906 bool isNewExtractor = false;
907 auto extractor = AbilityBase::ExtractorUtil::GetExtractor(hapPath, isNewExtractor);
908 if (extractor == nullptr) {
909 RESMGR_HILOGE(RESMGR_TAG, "failed to get extractor hapPath, %{public}s", hapPath);
910 return NOT_FOUND;
911 }
912 std::string rawPath = HapParser::GetRawFilePath(extractor, pathName);
913 if (extractor->HasEntry(rawPath)) {
914 outValue = false;
915 } else if (extractor->IsDirExist(rawPath)) {
916 outValue = true;
917 } else {
918 RESMGR_HILOGD(RESMGR_TAG, "the rawfile file %{public}s is not exist in %{public}s", rawPath.c_str(), hapPath);
919 return ERROR_CODE_RES_PATH_INVALID;
920 }
921 #endif
922 return SUCCESS;
923 }
924
IsRawDirUnCompressed(const std::string & pathName,bool & outValue)925 RState HapParser::IsRawDirUnCompressed(const std::string &pathName, bool &outValue)
926 {
927 char outPath[PATH_MAX + 1] = {0};
928 Utils::CanonicalizePath(pathName.c_str(), outPath, PATH_MAX);
929 struct stat fileStat {};
930 if (stat(outPath, &fileStat) != 0) {
931 RESMGR_HILOGE(RESMGR_TAG, "failed to get rawfile file info, %{public}s", outPath);
932 return ERROR_CODE_RES_PATH_INVALID;
933 }
934 if ((fileStat.st_mode & S_IFDIR)) {
935 outValue = true;
936 } else if ((fileStat.st_mode & S_IFREG)) {
937 outValue = false;
938 } else {
939 RESMGR_HILOGE(RESMGR_TAG, "the rawfile file %{public}s is not exist", outPath);
940 return ERROR_CODE_RES_PATH_INVALID;
941 }
942 return SUCCESS;
943 }
944 } // namespace Resource
945 } // namespace Global
946 } // namespace OHOS
947