• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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