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