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