• 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_v1.h"
17 
18 #include <cstdlib>
19 #include <fcntl.h>
20 #include <fstream>
21 #include <unistd.h>
22 #include <sys/stat.h>
23 #include <unordered_map>
24 
25 #include "hap_resource_manager.h"
26 #include "hap_resource_v1.h"
27 #include "hilog_wrapper.h"
28 #include "locale_matcher.h"
29 #include "utils/errors.h"
30 #include "utils/string_utils.h"
31 #include "utils/utils.h"
32 
33 #if defined(__WINNT__)
34 #include <cstring>
35 #else
36 #include "securec.h"
37 #endif
38 
39 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
40 #include "hitrace_meter.h"
41 #include "file_mapper.h"
42 #include "extractor.h"
43 #endif
44 
45 namespace OHOS {
46 namespace Global {
47 namespace Resource {
48 const std::string NOT_DEVICE_TYPE = "not_device_type";
49 const std::string DEVICE_DEFAULT = "default";
50 static const std::unordered_map<ResType, uint32_t> TYPE_MAP {
51     {INTEGER, SELECT_INTEGER},
52     {STRING, SELECT_STRING},
53     {STRINGARRAY, SELECT_STRINGARRAY},
54     {INTARRAY, SELECT_INTARRAY},
55     {BOOLEAN, SELECT_BOOLEAN},
56     {COLOR, SELECT_COLOR},
57     {THEME, SELECT_THEME},
58     {PLURALS, SELECT_PLURALS},
59     {FLOAT, SELECT_FLOAT},
60     {MEDIA, SELECT_MEDIA},
61     {PROF, SELECT_PROF},
62     {PATTERN, SELECT_PATTERN},
63     {SYMBOL, SELECT_SYMBOL}
64 };
65 
HapParserV1()66 HapParserV1::HapParserV1() : deviceType_(DEVICE_DEFAULT)
67 {}
68 
HapParserV1(std::shared_ptr<ResConfigImpl> & defaultConfig,uint32_t selectedTypes,bool loadAll,bool isUpdate)69 HapParserV1::HapParserV1(std::shared_ptr<ResConfigImpl> &defaultConfig, uint32_t selectedTypes,
70     bool loadAll, bool isUpdate) : defaultConfig_(defaultConfig), selectedTypes_(selectedTypes),
71     deviceType_(DEVICE_DEFAULT), loadAll_(loadAll), isUpdate_(isUpdate)
72 {}
73 
~HapParserV1()74 HapParserV1::~HapParserV1()
75 {}
76 
SetResDesc(std::shared_ptr<ResDesc> & resDesc)77 void HapParserV1::SetResDesc(std::shared_ptr<ResDesc> &resDesc)
78 {
79     resDesc_ = resDesc;
80 }
81 
Init(const char * path)82 bool HapParserV1::Init(const char *path)
83 {
84     if (resDesc_ == nullptr) {
85         return false;
86     }
87 
88     if (!GetIndexData(path, buffer_, bufLen_)) {
89         return false;
90     }
91 
92     int32_t out = this->ParseResHex();
93     if (out != OK) {
94         RESMGR_HILOGE(RESMGR_TAG, "ParseResHex failed! retcode:%d", out);
95         return false;
96     }
97     return true;
98 }
99 
ParseResHex()100 int32_t HapParserV1::ParseResHex()
101 {
102 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
103     HITRACE_METER_NAME_EX(HITRACE_LEVEL_INFO, HITRACE_TAG_APP, __PRETTY_FUNCTION__, nullptr);
104 #endif
105     ResHeader resHeader;
106     uint32_t offset = 0;
107     if (offset + ResHeader::RES_HEADER_LEN > bufLen_) {
108         RESMGR_HILOGE(RESMGR_TAG, "Parse ResHeader failed, the offset will be out of bounds");
109         return SYS_ERROR;
110     }
111     errno_t eret = memcpy_s(&resHeader, sizeof(ResHeader), buffer_.get() + offset, ResHeader::RES_HEADER_LEN);
112     if (eret != OK) {
113         return SYS_ERROR;
114     }
115     offset += ResHeader::RES_HEADER_LEN;
116     if (resHeader.keyCount_ == 0 || resHeader.length_ == 0) {
117         return UNKNOWN_ERROR;
118     }
119     deviceType_ = ResConfigImpl::GetCurrentDeviceType();
120     if (deviceType_ == std::string(TABLET_STR) || deviceType_ == std::string(TWOINONE_STR)) {
121         deviceTypes_ = ResConfigImpl::GetAppSupportDeviceTypes();
122     }
123     std::vector<bool> keyTypes(KeyType::KEY_TYPE_MAX, false);
124     for (uint32_t i = 0; i < resHeader.keyCount_; i++) {
125         std::shared_ptr<ResKey> key = std::make_shared<ResKey>();
126         if (key == nullptr) {
127             RESMGR_HILOGE(RESMGR_TAG, "new ResKey failed when ParseResHex");
128             return SYS_ERROR;
129         }
130         bool match = true;
131         int32_t ret = ParseKey(offset, key, match, keyTypes);
132         if (ret != OK) {
133             return ret;
134         }
135         if (match) {
136             resDesc_->keys_.push_back(key);
137         }
138     }
139     return OK;
140 }
141 
ParseKey(uint32_t & offset,std::shared_ptr<ResKey> key,bool & match,std::vector<bool> & keyTypes)142 int32_t HapParserV1::ParseKey(uint32_t &offset, std::shared_ptr<ResKey> key, bool &match, std::vector<bool> &keyTypes)
143 {
144     if (offset + ResKey::RESKEY_HEADER_LEN > bufLen_) {
145         RESMGR_HILOGE(RESMGR_TAG, "Parse ResKeyHeader failed, the offset will be out of bounds");
146         return SYS_ERROR;
147     }
148     errno_t eret = memcpy_s(key.get(), sizeof(ResKey), buffer_.get() + offset, ResKey::RESKEY_HEADER_LEN);
149     if (eret != OK) {
150         return SYS_ERROR;
151     }
152     offset += ResKey::RESKEY_HEADER_LEN;
153     if (key->tag_[ArrayIndex::INDEX_ZERO] != 'K' || key->tag_[ArrayIndex::INDEX_ONE] != 'E' ||
154         key->tag_[ArrayIndex::INDEX_TWO] != 'Y' || key->tag_[ArrayIndex::INDEX_THREE] != 'S') {
155         return -1;
156     }
157 
158     std::vector<std::shared_ptr<KeyParam>> keyParams;
159     if (!this->getKeyParams(offset, key->keyParamsCount_, match, keyTypes, keyParams)) {
160         return SYS_ERROR;
161     }
162     key->resConfig_ = HapParser::CreateResConfigFromKeyParams(keyParams);
163     if (SkipParseItem(key, match)) {
164         match = false;
165         return OK;
166     }
167 
168     uint32_t idOffset = key->offset_;
169     std::shared_ptr<ResId> id = std::make_shared<ResId>();
170     if (id == nullptr) {
171         RESMGR_HILOGE(RESMGR_TAG, "new ResId failed when ParseKey");
172         return SYS_ERROR;
173     }
174     int32_t ret = ParseId(idOffset, id);
175     if (ret != OK) {
176         return ret;
177     }
178     key->resId_ = id;
179     return OK;
180 }
181 
getKeyParams(uint32_t & offset,uint32_t paramsCount,bool & match,std::vector<bool> & keyTypes,std::vector<std::shared_ptr<KeyParam>> & keyParams)182 bool HapParserV1::getKeyParams(uint32_t &offset, uint32_t paramsCount, bool &match, std::vector<bool> &keyTypes,
183     std::vector<std::shared_ptr<KeyParam>> &keyParams)
184 {
185     std::string locale;
186     bool isLocale = false;
187     for (uint32_t i = 0; i < paramsCount; ++i) {
188         std::shared_ptr<KeyParam> kp;
189         if (ParseKeyParam(offset, match, kp) != OK) {
190             return false;
191         }
192         if (kp == nullptr) {
193             return false;
194         }
195         GetLimitKeyValue(kp->type_, keyTypes);
196         GetKeyParamsLocales(kp, locale, isLocale);
197         keyParams.push_back(kp);
198     }
199     if (isLocale) {
200         locales_.emplace(locale);
201     }
202     return true;
203 }
204 
ParseKeyParam(uint32_t & offset,bool & match,std::shared_ptr<KeyParam> & kp)205 int32_t HapParserV1::ParseKeyParam(uint32_t &offset, bool &match, std::shared_ptr<KeyParam> &kp)
206 {
207     kp = std::make_shared<KeyParam>();
208     if (kp == nullptr) {
209         RESMGR_HILOGE(RESMGR_TAG, "ParseKeyParam new KeyParam failed");
210         return SYS_ERROR;
211     }
212     if (offset + KeyParam::KEYPARAM_LEN > bufLen_) {
213         RESMGR_HILOGE(RESMGR_TAG, "ParseKeyParam failed, the offset will be out of bounds");
214         return SYS_ERROR;
215     }
216     errno_t eret = memcpy_s(kp.get(), sizeof(KeyParam), buffer_.get() + offset, KeyParam::KEYPARAM_LEN);
217     if (eret != OK) {
218         return SYS_ERROR;
219     }
220     offset += KeyParam::KEYPARAM_LEN;
221     kp->InitStr();
222 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
223     auto resDeviceType = kp->GetDeviceTypeStr();
224     deviceTypes_.push_back(deviceType_);
225     if (deviceType_ != DEVICE_DEFAULT && resDeviceType != NOT_DEVICE_TYPE &&
226         find(deviceTypes_.begin(), deviceTypes_.end(), resDeviceType) == deviceTypes_.end()) {
227         match = false;
228     }
229 #endif
230     return OK;
231 }
232 
GetLimitKeyValue(KeyType type,std::vector<bool> & keyTypes)233 void HapParserV1::GetLimitKeyValue(KeyType type, std::vector<bool> &keyTypes)
234 {
235     const uint32_t limitKeysBase = 0x00000001;
236     uint32_t typeValue = static_cast<uint32_t>(type);
237     if (type < KeyType::KEY_TYPE_MAX && !keyTypes[typeValue]) {
238         keyTypes[typeValue] = true;
239         limitKeyValue_ |= limitKeysBase << typeValue;
240     }
241 }
242 
SkipParseItem(const std::shared_ptr<ResKey> & key,bool & match)243 bool HapParserV1::SkipParseItem(const std::shared_ptr<ResKey> &key, bool &match)
244 {
245     if (!match || (selectedTypes_ != SELECT_ALL &&
246                     defaultConfig_ != nullptr && !defaultConfig_->Match(key->resConfig_, false))) {
247         return true;
248     }
249 
250     if (loadAll_) {
251         return false;
252     }
253 
254     if (!key->resConfig_->GetLocaleInfo()) {
255         return isUpdate_;
256     }
257 
258     if (defaultConfig_ != nullptr && defaultConfig_->MatchLocal(*key->resConfig_)) {
259         return false;
260     }
261     return true;
262 }
263 
ParseId(uint32_t & offset,std::shared_ptr<ResId> id)264 int32_t HapParserV1::ParseId(uint32_t &offset, std::shared_ptr<ResId> id)
265 {
266     if (offset + ResId::RESID_HEADER_LEN > bufLen_) {
267         RESMGR_HILOGE(RESMGR_TAG, "Parse ResIdHeader failed, the offset will be out of bounds");
268         return SYS_ERROR;
269     }
270     errno_t eret = memcpy_s(id.get(), sizeof(ResId), buffer_.get() + offset, ResId::RESID_HEADER_LEN);
271     if (eret != OK) {
272         return SYS_ERROR;
273     }
274     offset += ResId::RESID_HEADER_LEN;
275     if (id->tag_[ArrayIndex::INDEX_ZERO] != 'I' || id->tag_[ArrayIndex::INDEX_ONE] != 'D'
276         || id->tag_[ArrayIndex::INDEX_TWO] != 'S' || id->tag_[ArrayIndex::INDEX_THREE] != 'S') {
277         return -1;
278     }
279     for (uint32_t i = 0; i < id->count_; ++i) {
280         std::shared_ptr<IdParam> ip = std::make_shared<IdParam>();
281         if (ip == nullptr) {
282             RESMGR_HILOGE(RESMGR_TAG, "new IdParam failed when ParseId");
283             return SYS_ERROR;
284         }
285         if (offset + ResId::IDPARAM_HEADER_LEN > bufLen_) {
286             RESMGR_HILOGE(RESMGR_TAG, "Parse IdParam failed, the offset will be out of bounds");
287             return SYS_ERROR;
288         }
289         errno_t eret = memcpy_s(ip.get(), sizeof(IdParam), buffer_.get() + offset, ResId::IDPARAM_HEADER_LEN);
290         if (eret != OK) {
291             return SYS_ERROR;
292         }
293         offset += ResId::IDPARAM_HEADER_LEN;
294         std::shared_ptr<IdItem> idItem = std::make_shared<IdItem>();
295         if (idItem == nullptr) {
296             RESMGR_HILOGE(RESMGR_TAG, "new IdItem failed when ParseId");
297             return SYS_ERROR;
298         }
299         uint32_t ipOffset = ip->offset_;
300         int32_t ret = ParseIdItem(ipOffset, idItem);
301         if (ret != OK) {
302             return ret;
303         }
304         ip->idItem_ = idItem;
305         id->idParams_.push_back(ip);
306     }
307     return OK;
308 }
309 
ConvertType(ResType type)310 uint32_t ConvertType(ResType type)
311 {
312     auto it = TYPE_MAP.find(type);
313     if (it == TYPE_MAP.end()) {
314         return SELECT_ALL;
315     }
316     return it->second;
317 }
318 
ParseIdItem(uint32_t & offset,std::shared_ptr<IdItem> idItem)319 int32_t HapParserV1::ParseIdItem(uint32_t &offset, std::shared_ptr<IdItem> idItem)
320 {
321     if (offset + IdItem::HEADER_LEN > bufLen_) {
322         RESMGR_HILOGE(RESMGR_TAG, "Parse IdItemHeader failed, the offset will be out of bounds");
323         return SYS_ERROR;
324     }
325     errno_t eret = memcpy_s(idItem.get(), sizeof(IdItem), buffer_.get() + offset, IdItem::HEADER_LEN);
326     if (eret != OK) {
327         return SYS_ERROR;
328     }
329     if (selectedTypes_ != SELECT_ALL && (selectedTypes_ & ConvertType(idItem->resType_)) == 0) {
330         return OK;
331     }
332     offset += IdItem::HEADER_LEN;
333 
334     idItem->JudgeArray();
335     if (idItem->isArray_) {
336         int32_t ret = ParseStringArray(offset, idItem->values_);
337         if (ret != OK) {
338             return ret;
339         }
340     } else {
341         int32_t ret = ParseString(offset, idItem->value_);
342         if (ret != OK) {
343             return ret;
344         }
345         idItem->valueLen_ = idItem->value_.size();
346     }
347     int32_t ret = ParseString(offset, idItem->name_);
348     if (ret != OK) {
349         return ret;
350     }
351     return OK;
352 }
353 
ParseStringArray(uint32_t & offset,std::vector<std::string> & values)354 int32_t HapParserV1::ParseStringArray(uint32_t &offset, std::vector<std::string> &values)
355 {
356     uint16_t arrLen;
357     if (offset + IdItem::SIZE_LEN > bufLen_) {
358         RESMGR_HILOGE(RESMGR_TAG, "ParseStringArray failed, the offset will be out of bounds");
359         return SYS_ERROR;
360     }
361     errno_t eret = memcpy_s(&arrLen, sizeof(arrLen), buffer_.get() + offset, IdItem::SIZE_LEN);
362     if (eret != OK) {
363         return SYS_ERROR;
364     }
365     offset += IdItem::SIZE_LEN; // Offset value plus 2
366     // next arrLen bytes are several strings. then after, is one '\0'
367     uint32_t startOffset = offset;
368     std::string value;
369     while (true) {
370         int32_t ret = ParseString(offset, value, false);
371         if (ret != OK) {
372             return ret;
373         }
374         values.push_back(value);
375 
376         uint32_t readSize = offset - startOffset;
377         if (readSize + 1 == arrLen) {
378             offset += 1; // after arrLen, got '\0'
379             break;
380         }
381         if (readSize + 1 > arrLen) {
382             // size not match, cannot > arrLen
383             return SYS_ERROR;
384         }
385     }
386     return OK;
387 }
388 
ParseString(uint32_t & offset,std::string & id,bool includeTemi)389 int32_t HapParserV1::ParseString(uint32_t &offset, std::string &id, bool includeTemi)
390 {
391     uint16_t strLen;
392     if (offset + IdItem::SIZE_LEN > bufLen_) {
393         RESMGR_HILOGE(RESMGR_TAG, "ParseString length failed, the offset will be out of bounds");
394         return SYS_ERROR;
395     }
396     errno_t eret = memcpy_s(&strLen, sizeof(strLen), buffer_.get() + offset, IdItem::SIZE_LEN);
397     if (eret != OK || (includeTemi && strLen == 0)) {
398         return SYS_ERROR;
399     }
400     offset += IdItem::SIZE_LEN; // Offset value plus 2
401     if (offset + (includeTemi ? (strLen - 1) : strLen) > bufLen_) {
402         RESMGR_HILOGE(RESMGR_TAG, "ParseString value failed, the offset will be out of bounds");
403         return SYS_ERROR;
404     }
405     std::string tmp = std::string(reinterpret_cast<char *>(buffer_.get()) + offset,
406         includeTemi ? (strLen - 1) : strLen);
407     offset += includeTemi ? strLen : (strLen + 1);
408     id = tmp;
409     return OK;
410 }
411 
GetHapResource(const char * path,bool isSystem,bool isOverlay)412 std::shared_ptr<HapResource> HapParserV1::GetHapResource(const char *path, bool isSystem, bool isOverlay)
413 {
414     std::shared_ptr<HapResourceV1> pResource = std::make_shared<HapResourceV1>(path, 0, resDesc_, isSystem, isOverlay);
415     if (pResource == nullptr || !pResource->Init(defaultConfig_)) {
416         return nullptr;
417     }
418     pResource->SetLimitKeysValue(limitKeyValue_);
419     pResource->SetLocales(locales_);
420     pResource->SetSelectedType(selectedTypes_);
421     return pResource;
422 }
423 } // namespace Resource
424 } // namespace Global
425 } // namespace OHOS
426