• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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_v2.h"
17 
18 #include <fcntl.h>
19 #include <fstream>
20 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
21 #include <sys/mman.h>
22 #include <sys/stat.h>
23 #endif
24 #include <unistd.h>
25 
26 #if defined(__WINNT__)
27 #include <cstring>
28 #else
29 #include "securec.h"
30 #endif
31 
32 #include "hilog_wrapper.h"
33 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
34 #include "hitrace_meter.h"
35 #endif
36 
37 #include "utils/errors.h"
38 #include "utils/utils.h"
39 
40 namespace OHOS {
41 namespace Global {
42 namespace Resource {
HapParserV2()43 HapParserV2::HapParserV2()
44 {}
45 
~HapParserV2()46 HapParserV2::~HapParserV2()
47 {}
48 
Init(const char * path)49 bool HapParserV2::Init(const char *path)
50 {
51     mMapFile_ = std::make_shared<MmapFile>();
52     if (mMapFile_ == nullptr) {
53         RESMGR_HILOGE(RESMGR_TAG, "Init mmap file failed");
54         return false;
55     }
56 
57     if (!this->GetIndexMmap(path)) {
58         RESMGR_HILOGE(RESMGR_TAG, "GetIndexMmap failed when construct hapParser");
59         return false;
60     }
61 
62     int32_t out = this->ParseResHex();
63     if (out != OK) {
64         RESMGR_HILOGE(RESMGR_TAG, "ParseResHex failed! retcode:%d", out);
65         return false;
66     }
67     return true;
68 }
69 
ParseResHex()70 int32_t HapParserV2::ParseResHex()
71 {
72 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
73     HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
74 #endif
75     uint32_t offset = 0;
76     int32_t ret = this->ParseHeader(offset);
77     if (ret != OK) {
78         return ret;
79     }
80 
81     ret = this->ParseKeys(offset);
82     if (ret != OK) {
83         return ret;
84     }
85 
86     ret = this->ParseIds(offset);
87     if (ret != OK) {
88         return ret;
89     }
90 
91     if (offset != resHeader_.dataBlockOffset_) {
92         RESMGR_HILOGE(RESMGR_TAG, "Parse ResHeader failed, resource data error.");
93         return UNKNOWN_ERROR;
94     }
95     return OK;
96 }
97 
ParseHeader(uint32_t & offset)98 int32_t HapParserV2::ParseHeader(uint32_t &offset)
99 {
100     if (offset + ResIndexHeader::RES_HEADER_LEN > mMapFile_->mmapLen_) {
101         RESMGR_HILOGE(RESMGR_TAG, "Parse ResHeader failed, the offset will be out of bounds.");
102         return SYS_ERROR;
103     }
104     errno_t eret = memcpy_s(&resHeader_, sizeof(ResIndexHeader),
105         mMapFile_->mmap_ + offset, ResIndexHeader::RES_HEADER_LEN);
106     if (eret != OK) {
107         RESMGR_HILOGE(RESMGR_TAG, "Parse ResHeader failed, memory copy failed.");
108         return SYS_ERROR;
109     }
110     if (resHeader_.keyCount_ == 0 || resHeader_.length_ == 0 || resHeader_.dataBlockOffset_ > mMapFile_->mmapLen_) {
111         RESMGR_HILOGE(RESMGR_TAG, "Parse ResHeader failed, ResHeader data error.");
112         return UNKNOWN_ERROR;
113     }
114     offset += ResIndexHeader::RES_HEADER_LEN;
115     keys_.reserve(resHeader_.keyCount_);
116     return OK;
117 }
118 
ParseKeys(uint32_t & offset)119 int32_t HapParserV2::ParseKeys(uint32_t &offset)
120 {
121     for (uint32_t i = 0; i < resHeader_.keyCount_; i++) {
122         std::shared_ptr<KeyInfo> key = std::make_shared<KeyInfo>();
123         if (key == nullptr) {
124             RESMGR_HILOGE(RESMGR_TAG, "new ResKey failed when ParseResHex");
125             return SYS_ERROR;
126         }
127         int32_t ret = this->ParseKey(offset, key);
128         if (ret != OK) {
129             return ret;
130         }
131         keys_[key->resConfigId_] = HapParser::CreateResConfigFromKeyParams(key->params_);
132         if (keys_[key->resConfigId_]->GetColorMode() == ColorMode::DARK) {
133             hasDarkRes_ = true;
134         }
135     }
136     return OK;
137 }
138 
ParseIds(uint32_t & offset)139 int32_t HapParserV2::ParseIds(uint32_t &offset)
140 {
141     if (offset + IdsHeader::IDS_HEADER_LEN > mMapFile_->mmapLen_) {
142         RESMGR_HILOGE(RESMGR_TAG, "Parse IdsHeader failed, the offset will be out of bounds.");
143         return SYS_ERROR;
144     }
145     errno_t eret = memcpy_s(&idsHeader_, sizeof(IdsHeader), mMapFile_->mmap_ + offset, IdsHeader::IDS_HEADER_LEN);
146     if (eret != OK) {
147         RESMGR_HILOGE(RESMGR_TAG, "Parse IdsHeader failed, memory copy failed.");
148         return SYS_ERROR;
149     }
150     if (idsHeader_.tag_[ArrayIndex::INDEX_ZERO] != 'I' || idsHeader_.tag_[ArrayIndex::INDEX_ONE] != 'D' ||
151         idsHeader_.tag_[ArrayIndex::INDEX_TWO] != 'S' || idsHeader_.tag_[ArrayIndex::INDEX_THREE] != 'S' ||
152         offset + idsHeader_.length_ > resHeader_.dataBlockOffset_ ||
153         idsHeader_.typeCount_ == 0 || idsHeader_.idCount_ == 0) {
154         RESMGR_HILOGE(RESMGR_TAG, "Parse IdsHeader failed, IdsHeader data error.");
155         return UNKNOWN_ERROR;
156     }
157     offset += IdsHeader::IDS_HEADER_LEN;
158     idMap_.reserve(idsHeader_.idCount_);
159     typeNameMap_.reserve(idsHeader_.typeCount_);
160 
161     for (uint32_t i = 0; i < idsHeader_.typeCount_; i++) {
162         int32_t ret = ParseType(offset);
163         if (ret != OK) {
164             return ret;
165         }
166     }
167     return OK;
168 }
169 
ParseType(uint32_t & offset)170 int32_t HapParserV2::ParseType(uint32_t &offset)
171 {
172     if (offset + TypeInfo::TYPE_INFO_LEN > mMapFile_->mmapLen_) {
173         RESMGR_HILOGE(RESMGR_TAG, "Parse TypeInfo failed, the offset will be out of bounds.");
174         return SYS_ERROR;
175     }
176     TypeInfo typeInfo;
177     errno_t eret = memcpy_s(&typeInfo, sizeof(TypeInfo), mMapFile_->mmap_ + offset, TypeInfo::TYPE_INFO_LEN);
178     if (eret != OK) {
179         RESMGR_HILOGE(RESMGR_TAG, "Parse TypeInfo failed, memory copy failed.");
180         return SYS_ERROR;
181     }
182     if (typeInfo.type_ >= ResType::MAX_RES_TYPE || offset + typeInfo.length_ > resHeader_.dataBlockOffset_ ||
183         typeInfo.count_ > idsHeader_.idCount_) {
184         RESMGR_HILOGE(RESMGR_TAG, "Parse TypeInfo failed, TypeInfo data error.");
185         return UNKNOWN_ERROR;
186     }
187     offset += TypeInfo::TYPE_INFO_LEN;
188     typeNameMap_[typeInfo.type_].reserve(typeInfo.count_);
189 
190     for (uint32_t i = 0; i < typeInfo.count_; i++) {
191         int32_t ret = this->ParseItem(offset, typeInfo);
192         if (ret != OK) {
193             return ret;
194         }
195     }
196     return OK;
197 }
198 
ParseItem(uint32_t & offset,const TypeInfo & typeInfo)199 int32_t HapParserV2::ParseItem(uint32_t &offset, const TypeInfo &typeInfo)
200 {
201     if (offset + ResItem::RES_ITEM_LEN > mMapFile_->mmapLen_) {
202         RESMGR_HILOGE(RESMGR_TAG, "Parse ResItem failed, the offset will be out of bounds.");
203         return SYS_ERROR;
204     }
205     ResItem resItem;
206     errno_t eret = memcpy_s(&resItem, sizeof(ResItem), mMapFile_->mmap_ + offset, ResItem::RES_ITEM_LEN);
207     if (eret != OK) {
208         RESMGR_HILOGE(RESMGR_TAG, "Parse ResItem failed, memory copy failed.");
209         return SYS_ERROR;
210     }
211     offset += ResItem::RES_ITEM_LEN;
212     resItem.name_ = std::string(reinterpret_cast<const char *>(mMapFile_->mmap_) + offset, resItem.length_);
213     offset += resItem.length_;
214 
215     std::shared_ptr<IdValuesV2> idValues =
216         std::make_shared<IdValuesV2>((ResType)typeInfo.type_, resItem.resId_, resItem.offset_, resItem.name_);
217     idValues->SetMMap(mMapFile_);
218     typeNameMap_[typeInfo.type_][resItem.name_] = idValues;
219     idMap_[resItem.resId_] = idValues;
220     return OK;
221 }
222 
ParseStringArray(uint32_t & offset,std::vector<std::string> & values,size_t bufLen,uint8_t * buf)223 int32_t HapParserV2::ParseStringArray(uint32_t &offset, std::vector<std::string> &values, size_t bufLen, uint8_t *buf)
224 {
225     uint16_t arrLen;
226     if (offset + ValueUnderQualifierDirV2::DATA_HEAD_LEN > bufLen) {
227         RESMGR_HILOGE(RESMGR_TAG, "ParseStringArray failed, the offset will be out of bounds.");
228         return SYS_ERROR;
229     }
230     errno_t eret = memcpy_s(&arrLen, sizeof(uint16_t), buf + offset, ValueUnderQualifierDirV2::DATA_HEAD_LEN);
231     if (eret != OK) {
232         RESMGR_HILOGE(RESMGR_TAG, "ParseStringArray failed, memory copy failed.");
233         return SYS_ERROR;
234     }
235     offset += ValueUnderQualifierDirV2::DATA_HEAD_LEN;
236 
237     uint32_t startOffset = offset;
238     std::string value;
239     while (true) {
240         int32_t ret = ParseString(offset, value, bufLen, buf);
241         if (ret != OK) {
242             return ret;
243         }
244         values.push_back(value);
245         offset++;
246 
247         uint32_t readSize = offset - startOffset;
248         if (readSize == arrLen) {
249             break;
250         }
251         if (readSize > arrLen) {
252             RESMGR_HILOGE(RESMGR_TAG, "ParseStringArray failed, the read size out of bounds.");
253             return SYS_ERROR;
254         }
255     }
256     return OK;
257 }
258 
ParseString(uint32_t & offset,std::string & id,size_t bufLen,uint8_t * buf)259 int32_t HapParserV2::ParseString(uint32_t &offset, std::string &id, size_t bufLen, uint8_t *buf)
260 {
261     uint16_t strLen;
262     if (offset + ValueUnderQualifierDirV2::DATA_HEAD_LEN > bufLen) {
263         RESMGR_HILOGE(RESMGR_TAG, "ParseString failed, the offset will be out of bounds.");
264         return SYS_ERROR;
265     }
266     errno_t eret = memcpy_s(&strLen, sizeof(uint16_t), buf + offset, ValueUnderQualifierDirV2::DATA_HEAD_LEN);
267     if (eret != OK) {
268         RESMGR_HILOGE(RESMGR_TAG, "ParseString failed, memory copy failed.");
269         return SYS_ERROR;
270     }
271     offset += ValueUnderQualifierDirV2::DATA_HEAD_LEN;
272 
273     if (offset + strLen > bufLen) {
274         RESMGR_HILOGE(RESMGR_TAG, "ParseString failed, the string offset will be out of bounds");
275         return SYS_ERROR;
276     }
277     std::string tmp = std::string(reinterpret_cast<char *>(buf) + offset, strLen);
278     offset += strLen;
279     id = tmp;
280     return OK;
281 }
282 
ParseResInfo(uint32_t & offset,ResInfo & resInfo,const size_t bufLen,const uint8_t * buf)283 int32_t HapParserV2::ParseResInfo(uint32_t &offset, ResInfo &resInfo, const size_t bufLen, const uint8_t *buf)
284 {
285     if (offset + ResInfo::RES_INFO_LEN > bufLen) {
286         RESMGR_HILOGE(RESMGR_TAG, "Parse ResInfo failed, the offset will be out of bounds.");
287         return SYS_ERROR;
288     }
289     errno_t eret = memcpy_s(&resInfo, sizeof(ResInfo), buf + offset, ResInfo::RES_INFO_LEN);
290     if (eret != OK) {
291         RESMGR_HILOGE(RESMGR_TAG, "Parse ResInfo failed, memory copy failed.");
292         return SYS_ERROR;
293     }
294     offset += ResInfo::RES_INFO_LEN;
295     return OK;
296 }
297 
ParseConfigItem(uint32_t & offset,ConfigItem & configItem,const size_t bufLen,const uint8_t * buf)298 int32_t HapParserV2::ParseConfigItem(uint32_t &offset, ConfigItem &configItem, const size_t bufLen, const uint8_t *buf)
299 {
300     if (offset + ConfigItem::CONFIG_ITEM_LEN > bufLen) {
301         RESMGR_HILOGE(RESMGR_TAG, "Parse ConfigItem failed, the offset will be out of bounds.");
302         return SYS_ERROR;
303     }
304     errno_t eret = memcpy_s(&configItem, sizeof(ConfigItem), buf + offset, ConfigItem::CONFIG_ITEM_LEN);
305     if (eret != OK) {
306         RESMGR_HILOGE(RESMGR_TAG, "Parse ConfigItem failed, memory copy failed.");
307         return SYS_ERROR;
308     }
309     offset += ConfigItem::CONFIG_ITEM_LEN;
310     return OK;
311 }
312 
ParseKey(uint32_t & offset,std::shared_ptr<KeyInfo> key)313 int32_t HapParserV2::ParseKey(uint32_t &offset, std::shared_ptr<KeyInfo> key)
314 {
315     if (offset + KeyInfo::RESKEY_HEADER_LEN > mMapFile_->mmapLen_) {
316         RESMGR_HILOGE(RESMGR_TAG, "Parse ResKey failed, the offset will be out of bounds.");
317         return SYS_ERROR;
318     }
319     errno_t eret = memcpy_s(key.get(), sizeof(KeyInfo), mMapFile_->mmap_ + offset, KeyInfo::RESKEY_HEADER_LEN);
320     if (eret != OK) {
321         RESMGR_HILOGE(RESMGR_TAG, "Parse ResKey failed, memory copy failed.");
322         return SYS_ERROR;
323     }
324     if (key->tag_[ArrayIndex::INDEX_ZERO] != 'K' || key->tag_[ArrayIndex::INDEX_ONE] != 'E' ||
325         key->tag_[ArrayIndex::INDEX_TWO] != 'Y' || key->tag_[ArrayIndex::INDEX_THREE] != 'S') {
326         RESMGR_HILOGE(RESMGR_TAG, "Parse ResKey failed, ResKey data error.");
327         return UNKNOWN_ERROR;
328     }
329     offset += KeyInfo::RESKEY_HEADER_LEN;
330 
331     std::string locale;
332     bool isLocale = false;
333     for (uint32_t i = 0; i < key->keyParamsCount_; i++) {
334         std::shared_ptr<KeyParam> keyParam = std::make_shared<KeyParam>();
335         if (keyParam == nullptr) {
336             RESMGR_HILOGE(RESMGR_TAG, "new KeyParam failed when ParseResHex");
337             return SYS_ERROR;
338         }
339         int32_t ret = this->ParseKeyParam(offset, keyParam);
340         GetKeyParamsLocales(keyParam, locale, isLocale);
341         if (ret != OK) {
342             return ret;
343         }
344         key->params_.push_back(keyParam);
345     }
346     if (isLocale) {
347         locales_.emplace(locale);
348     }
349     return OK;
350 }
351 
ParseKeyParam(uint32_t & offset,std::shared_ptr<KeyParam> keyParam)352 int32_t HapParserV2::ParseKeyParam(uint32_t &offset, std::shared_ptr<KeyParam> keyParam)
353 {
354     if (offset + KeyParam::KEYPARAM_LEN > mMapFile_->mmapLen_) {
355         RESMGR_HILOGE(RESMGR_TAG, "Parse KeyParam failed, the offset will be out of bounds.");
356         return SYS_ERROR;
357     }
358     errno_t eret = memcpy_s(keyParam.get(), sizeof(KeyParam), mMapFile_->mmap_ + offset, KeyParam::KEYPARAM_LEN);
359     if (eret != OK) {
360         RESMGR_HILOGE(RESMGR_TAG, "Parse KeyParam failed, memory copy failed.");
361         return SYS_ERROR;
362     }
363     offset += KeyParam::KEYPARAM_LEN;
364     keyParam->InitStr();
365 
366     this->GetLimitKeyValue(keyParam->type_);
367     return OK;
368 }
369 
GetLimitKeyValue(KeyType type)370 void HapParserV2::GetLimitKeyValue(KeyType type)
371 {
372     const uint32_t limitKeysBase = 0x00000001;
373     if (type < KeyType::KEY_TYPE_MAX) {
374         uint32_t typeValue = static_cast<uint32_t>(type);
375         limitKeyValue_ |= limitKeysBase << typeValue;
376     }
377 }
378 
GetHapResource(const char * path,bool isSystem,bool isOverlay)379 std::shared_ptr<HapResource> HapParserV2::GetHapResource(const char *path, bool isSystem, bool isOverlay)
380 {
381     if (keys_.size() == 0 || idMap_.size() == 0 || typeNameMap_.size() == 0) {
382         RESMGR_HILOGE(RESMGR_TAG, "Get Hap resource failed, parse data is empty.");
383         return nullptr;
384     }
385 
386     std::shared_ptr<HapResourceV2> pResource = nullptr;
387     if (isSystem && isOverlay) {
388         pResource = std::make_shared<SystemOverlayResource>(path, 0);
389     } else if (isSystem) {
390         pResource = std::make_shared<SystemResource>(path, 0);
391     } else if (isOverlay) {
392         pResource = std::make_shared<OverlayResource>(path, 0);
393     } else {
394         pResource = std::make_shared<HapResourceV2>(path, 0, hasDarkRes_);
395     }
396 
397     if (pResource == nullptr || !pResource->Init(keys_, idMap_, typeNameMap_, mMapFile_)) {
398         RESMGR_HILOGE(RESMGR_TAG, "Get Hap resource failed, HapResource init failed.");
399         return nullptr;
400     }
401 
402     pResource->SetLimitKeysValue(limitKeyValue_);
403     pResource->SetLocales(locales_);
404     pResource->InitThemeSystemRes();
405     return pResource;
406 }
407 
GetIndexMmap(const char * path)408 bool HapParserV2::GetIndexMmap(const char *path)
409 {
410     if (Utils::ContainsTail(path, Utils::tailSet)) {
411         return this->GetIndexMmapFromHap(path);
412     } else {
413         return this->GetIndexMmapFromIndex(path);
414     }
415 }
416 
GetIndexMmapFromHap(const char * path)417 bool HapParserV2::GetIndexMmapFromHap(const char *path)
418 {
419 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
420     HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
421     bool isNewExtractor = false;
422     mMapFile_->extractor_ = AbilityBase::ExtractorUtil::GetExtractor(path, isNewExtractor);
423     if (mMapFile_->extractor_ == nullptr) {
424         return false;
425     }
426     std::string indexFilePath;
427     if (mMapFile_->extractor_->IsStageModel()) {
428         indexFilePath = "resources.index";
429     } else {
430         indexFilePath = HapParser::GetIndexFilePath(mMapFile_->extractor_);
431     }
432     mMapFile_->mapper_ = mMapFile_->extractor_->GetMmapData(indexFilePath);
433     if (mMapFile_->mapper_ == nullptr) {
434         RESMGR_HILOGE(RESMGR_TAG, "failed to get mmap data indexFilePath from hap");
435         return false;
436     }
437     mMapFile_->mmapLen_ = mMapFile_->mapper_->GetDataLen();
438     mMapFile_->mmap_ = mMapFile_->mapper_->GetDataPtr();
439 #endif
440     return true;
441 }
442 
GetIndexMmapFromIndex(const char * path)443 bool HapParserV2::GetIndexMmapFromIndex(const char *path)
444 {
445     char indexPath[PATH_MAX + 1] = {0};
446     Utils::CanonicalizePath(path, indexPath, PATH_MAX);
447 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
448     mMapFile_->fd_ = open(indexPath, O_RDONLY);
449     if (mMapFile_->fd_ <= 0) {
450         return false;
451     }
452     struct stat fileStat;
453     fstat(mMapFile_->fd_, &fileStat);
454     mMapFile_->mmapLen_ = static_cast<size_t>(fileStat.st_size);
455     mMapFile_->mmap_ = (uint8_t*)mmap(nullptr, mMapFile_->mmapLen_, PROT_READ, MAP_PRIVATE, mMapFile_->fd_, 0);
456     if (mMapFile_->mmap_ == MAP_FAILED) {
457         RESMGR_HILOGE(RESMGR_TAG, "failed to get mmap data indexFilePath from index");
458         return false;
459     }
460 #else
461     std::ifstream inFile(indexPath, std::ios::binary | std::ios::in);
462     if (!inFile.good()) {
463         return false;
464     }
465     inFile.seekg(0, std::ios::end);
466     int fileLen = inFile.tellg();
467     if (fileLen <= 0) {
468         RESMGR_HILOGE(RESMGR_TAG, "file size is zero");
469         inFile.close();
470         return false;
471     }
472     mMapFile_->mmapLen_ = static_cast<size_t>(fileLen);
473     mMapFile_->mmap_ = new uint8_t[fileLen + 1];
474     inFile.seekg(0, std::ios::beg);
475     inFile.read(reinterpret_cast<char*>(mMapFile_->mmap_), fileLen);
476     inFile.close();
477     RESMGR_HILOGD(RESMGR_TAG, "extract success, bufLen:%d", fileLen);
478 #endif
479     return true;
480 }
481 } // namespace Resource
482 } // namespace Global
483 } // namespace OHOS
484