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