• 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_resource.h"
17 
18 #include <algorithm>
19 #include <climits>
20 #include <cstdlib>
21 #include <fstream>
22 #include "utils/utils.h"
23 
24 #ifdef __WINNT__
25 #include <shlwapi.h>
26 #include <windows.h>
27 #endif
28 
29 #ifdef __LINUX__
30 #include <cstring>
31 #endif
32 
33 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
34 #include "hitrace_meter.h"
35 #endif
36 #include "hap_parser.h"
37 #include "hilog_wrapper.h"
38 #include "utils/errors.h"
39 
40 namespace OHOS {
41 namespace Global {
42 namespace Resource {
ValueUnderQualifierDir(const std::vector<KeyParam * > & keyParams,IdItem * idItem,HapResource * hapResource,bool isOverlay,bool systemResource)43 HapResource::ValueUnderQualifierDir::ValueUnderQualifierDir(const std::vector<KeyParam *> &keyParams, IdItem *idItem,
44     HapResource *hapResource, bool isOverlay, bool systemResource) : hapResource_(hapResource)
45 {
46     keyParams_ = keyParams;
47     folder_ = HapParser::ToFolderPath(keyParams_);
48     idItem_ = idItem;
49     isOverlay_ = isOverlay;
50     isSystemResource_ = systemResource;
51     InitResConfig();
52 }
53 
~ValueUnderQualifierDir()54 HapResource::ValueUnderQualifierDir::~ValueUnderQualifierDir()
55 {
56     // keyParams_ idItem_ was passed into this, we don't delete them because someone will do
57     if (resConfig_ != nullptr) {
58         delete (resConfig_);
59         resConfig_ = nullptr;
60     }
61 }
62 
InitResConfig()63 void HapResource::ValueUnderQualifierDir::InitResConfig()
64 {
65     resConfig_ = HapParser::CreateResConfigFromKeyParams(keyParams_);
66 }
67 
68 // IdValues
~IdValues()69 HapResource::IdValues::~IdValues()
70 {
71     for (size_t i = 0; i < limitPaths_.size(); ++i) {
72         if (limitPaths_[i] != nullptr) {
73             delete limitPaths_[i];
74             limitPaths_[i] = nullptr;
75         }
76     }
77 }
78 
79 // HapResource
HapResource(const std::string path,time_t lastModTime,const ResConfig * defaultConfig,ResDesc * resDes)80 HapResource::HapResource(const std::string path, time_t lastModTime, const ResConfig *defaultConfig, ResDesc *resDes)
81     : indexPath_(path), lastModTime_(lastModTime), resDesc_(resDes), defaultConfig_(defaultConfig)
82 {
83 }
84 
~HapResource()85 HapResource::~HapResource()
86 {
87     if (resDesc_ != nullptr) {
88         delete (resDesc_);
89         resDesc_ = nullptr;
90     }
91     std::map<uint32_t, IdValues *>::iterator iter;
92     for (iter = idValuesMap_.begin(); iter != idValuesMap_.end(); ++iter) {
93         if (iter->second != nullptr) {
94             IdValues *ptr = iter->second;
95             delete (ptr);
96             iter->second = nullptr;
97         }
98     }
99 
100     for (size_t i = 0; i < idValuesNameMap_.size(); ++i) {
101         if (idValuesNameMap_[i] != nullptr) {
102             delete (idValuesNameMap_[i]);
103             idValuesNameMap_[i] = nullptr;
104         }
105     }
106     lastModTime_ = 0;
107     // defaultConfig_ was passed by constructor, we do not delete it here
108     defaultConfig_ = nullptr;
109 }
110 
CanonicalizePath(const char * path,char * outPath,size_t len)111 void CanonicalizePath(const char *path, char *outPath, size_t len)
112 {
113 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
114     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
115 #endif
116     if (path == nullptr) {
117         HILOG_ERROR("path is null");
118         return;
119     }
120     if (strlen(path) >= len) {
121         HILOG_ERROR("the length of path longer than len");
122         return;
123     }
124 #ifdef __WINNT__
125     if (!PathCanonicalizeA(outPath, path)) {
126         HILOG_ERROR("failed to canonicalize the path");
127         return;
128     }
129 #else
130     if (realpath(path, outPath) == nullptr) {
131         HILOG_ERROR("failed to realpath the path errno:%{public}d", errno);
132         return;
133     }
134 #endif
135 }
136 
Load(const char * path,const ResConfigImpl * defaultConfig,bool system)137 const HapResource* HapResource::Load(const char *path, const ResConfigImpl* defaultConfig, bool system)
138 {
139     if (Utils::ContainsTail(path, Utils::tailSet)) {
140         return LoadFromHap(path, defaultConfig, system);
141     } else {
142         return LoadFromIndex(path, defaultConfig, system);
143     }
144 }
145 
LoadFromIndex(const char * path,const ResConfigImpl * defaultConfig,bool system)146 const HapResource* HapResource::LoadFromIndex(const char *path, const ResConfigImpl *defaultConfig, bool system)
147 {
148     char outPath[PATH_MAX + 1] = {0};
149     CanonicalizePath(path, outPath, PATH_MAX);
150     std::ifstream inFile(outPath, std::ios::binary | std::ios::in);
151     if (!inFile.good()) {
152         return nullptr;
153     }
154     inFile.seekg(0, std::ios::end);
155     int bufLen = inFile.tellg();
156     if (bufLen <= 0) {
157         HILOG_ERROR("file size is zero");
158         inFile.close();
159         return nullptr;
160     }
161     void *buf = malloc(bufLen);
162     if (buf == nullptr) {
163         HILOG_ERROR("Error allocating memory");
164         inFile.close();
165         return nullptr;
166     }
167     inFile.seekg(0, std::ios::beg);
168     inFile.read(static_cast<char *>(buf), bufLen);
169     inFile.close();
170 
171     HILOG_DEBUG("extract success, bufLen:%d", bufLen);
172 
173     ResDesc *resDesc = new (std::nothrow) ResDesc();
174     if (resDesc == nullptr) {
175         HILOG_ERROR("new ResDesc failed when LoadFromIndex");
176         free(buf);
177         return nullptr;
178     }
179     int32_t out = HapParser::ParseResHex(static_cast<char *>(buf), bufLen, *resDesc, defaultConfig);
180     if (out != OK) {
181         delete (resDesc);
182         free(buf);
183         HILOG_ERROR("ParseResHex failed! retcode:%d", out);
184         return nullptr;
185     }
186     free(buf);
187 
188     HapResource *pResource = new (std::nothrow) HapResource(std::string(path), 0, defaultConfig, resDesc);
189     if (pResource == nullptr) {
190         HILOG_ERROR("new HapResource failed when LoadFromIndex");
191         delete (resDesc);
192         return nullptr;
193     }
194     if (!pResource->Init(system)) {
195         delete (pResource);
196         return nullptr;
197     }
198     return pResource;
199 }
200 
LoadFromHap(const char * path,const ResConfigImpl * defaultConfig,bool system)201 const HapResource* HapResource::LoadFromHap(const char *path, const ResConfigImpl *defaultConfig, bool system)
202 {
203     std::unique_ptr<uint8_t[]> tmpBuf;
204     size_t tmpLen;
205     int32_t ret = HapParser::ReadIndexFromFile(path, tmpBuf, tmpLen);
206     if (ret != OK) {
207         HILOG_ERROR("read Index from file failed");
208         return nullptr;
209     }
210     ResDesc *resDesc = new (std::nothrow) ResDesc();
211     if (resDesc == nullptr) {
212         HILOG_ERROR("new ResDesc failed when LoadFromHap");
213         return nullptr;
214     }
215     int32_t out = HapParser::ParseResHex(reinterpret_cast<char *>(tmpBuf.get()), tmpLen, *resDesc, defaultConfig);
216     if (out != OK) {
217         HILOG_ERROR("ParseResHex failed! retcode:%d", out);
218         delete (resDesc);
219         return nullptr;
220     }
221 
222     HapResource *pResource = new (std::nothrow) HapResource(path, 0, defaultConfig, resDesc);
223     if (pResource == nullptr) {
224         delete (resDesc);
225         return nullptr;
226     }
227 
228     if (!pResource->Init(system)) {
229         delete (pResource);
230         return nullptr;
231     }
232     return pResource;
233 }
234 
LoadOverlays(const std::string & path,const std::vector<std::string> & overlayPaths,const ResConfigImpl * defaultConfig)235 const std::unordered_map<std::string, HapResource *> HapResource::LoadOverlays(const std::string &path,
236     const std::vector<std::string> &overlayPaths, const ResConfigImpl *defaultConfig)
237 {
238     std::unordered_map<std::string, HapResource *> result;
239     do {
240         const HapResource *targetResource = Load(path.c_str(), defaultConfig, true);
241         if (targetResource == nullptr) {
242             HILOG_ERROR("load target failed");
243             break;
244         }
245         result[path] = const_cast<HapResource*>(targetResource);
246         bool success = true;
247         std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> mapping =
248             targetResource->BuildNameTypeIdMapping();
249         for (auto iter = overlayPaths.begin(); iter != overlayPaths.end(); iter++) {
250             const HapResource *overlayResource = Load(iter->c_str(), defaultConfig);
251             if (overlayResource == nullptr) {
252                 HILOG_ERROR("load overlay failed");
253                 success = false;
254                 break;
255             }
256             result[*iter] = const_cast<HapResource*>(overlayResource);
257         }
258 
259         if (!success) {
260             HILOG_ERROR("load overlay failed");
261             break;
262         }
263 
264         for (auto iter = result.begin(); iter != result.end(); iter++) {
265             auto index = iter->first.find(path);
266             if (index == std::string::npos) {
267                 iter->second->UpdateOverlayInfo(mapping);
268             }
269         }
270         return result;
271     } while (false);
272 
273     for_each (result.begin(), result.end(), [](auto &iter) {
274         delete iter.second;
275     });
276     return std::unordered_map<std::string, HapResource *>();
277 }
278 
BuildNameTypeIdMapping() const279 std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> HapResource::BuildNameTypeIdMapping() const
280 {
281     std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> result;
282     for (auto iter = idValuesMap_.begin(); iter != idValuesMap_.end(); iter++) {
283         const std::vector<ValueUnderQualifierDir *> &limitPaths = iter->second->GetLimitPathsConst();
284         if (limitPaths.size() > 0) {
285             ValueUnderQualifierDir* value = limitPaths[0];
286             result[value->idItem_->name_][value->idItem_->resType_] = value->idItem_->id_;
287         }
288     }
289     return result;
290 }
291 
UpdateOverlayInfo(std::unordered_map<std::string,std::unordered_map<ResType,uint32_t>> & nameTypeId)292 void HapResource::UpdateOverlayInfo(std::unordered_map<std::string, std::unordered_map<ResType, uint32_t>> &nameTypeId)
293 {
294     std::map<uint32_t, IdValues *> newIdValuesMap;
295     for (auto iter = idValuesMap_.begin(); iter != idValuesMap_.end(); iter++) {
296         const std::vector<ValueUnderQualifierDir *> &limitPaths = iter->second->GetLimitPathsConst();
297         if (limitPaths.size() > 0) {
298             ValueUnderQualifierDir *value = limitPaths[0];
299             std::string name = value->idItem_->name_;
300             ResType type = value->idItem_->resType_;
301             if (nameTypeId.find(name) == nameTypeId.end()) {
302                 continue;
303             }
304             auto &typeId = nameTypeId[name];
305             if (typeId.find(type) == typeId.end()) {
306                 continue;
307             }
308             uint32_t newId = typeId[type];
309             for_each(limitPaths.begin(), limitPaths.end(), [&](auto &item) {
310                 item->idItem_->id_ = newId;
311                 item->isOverlay_ = true;
312             });
313             newIdValuesMap[newId] = iter->second;
314         }
315     }
316     idValuesMap_.swap(newIdValuesMap);
317 }
318 
Init(bool system)319 bool HapResource::Init(bool system)
320 {
321 #if !defined(__WINNT__) && !defined(__IDE_PREVIEW__) && !defined(__ARKUI_CROSS__)
322     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
323 #endif
324 #ifdef __WINNT__
325     char separator = '\\';
326 #else
327     char separator = '/';
328 #endif
329     auto index = indexPath_.rfind(separator);
330     if (index == std::string::npos) {
331         HILOG_ERROR("index path format error, %s", indexPath_.c_str());
332         return false;
333     }
334 #if defined(__IDE_PREVIEW__) || defined(__ARKUI_CROSS__)
335     resourcePath_ = indexPath_.substr(0, index + 1);
336 #else
337     index = indexPath_.rfind(separator, index - 1);
338     if (index == std::string::npos) {
339         HILOG_ERROR("index path format error, %s", indexPath_.c_str());
340         return false;
341     }
342     resourcePath_ = indexPath_.substr(0, index + 1);
343 #endif
344     for (int i = 0; i < ResType::MAX_RES_TYPE; ++i) {
345         auto mptr = new (std::nothrow) std::map<std::string, IdValues *>();
346         if (mptr == nullptr) {
347             HILOG_ERROR("new std::map failed in HapResource::Init");
348             return false;
349         }
350         idValuesNameMap_.push_back(mptr);
351     }
352     return InitIdList(system);
353 }
354 
InitIdList(bool system)355 bool HapResource::InitIdList(bool system)
356 {
357     if (resDesc_ == nullptr) {
358         HILOG_ERROR("resDesc_ is null ! InitIdList failed");
359         return false;
360     }
361     for (size_t i = 0; i < resDesc_->keys_.size(); i++) {
362         ResKey *resKey = resDesc_->keys_[i];
363 
364         for (size_t j = 0; j < resKey->resId_->idParams_.size(); ++j) {
365             IdParam *idParam = resKey->resId_->idParams_[j];
366             uint32_t id = idParam->id_;
367             std::map<uint32_t, IdValues *>::iterator iter = idValuesMap_.find(id);
368             if (iter == idValuesMap_.end()) {
369                 auto idValues = new (std::nothrow) HapResource::IdValues();
370                 if (idValues == nullptr) {
371                     HILOG_ERROR("new IdValues failed in HapResource::InitIdList");
372                     return false;
373                 }
374                 auto limitPath = new (std::nothrow) HapResource::ValueUnderQualifierDir(resKey->keyParams_,
375                     idParam->idItem_, this, false, system);
376                 if (limitPath == nullptr) {
377                     HILOG_ERROR("new ValueUnderQualifierDir failed in HapResource::InitIdList");
378                     delete (idValues);
379                     return false;
380                 }
381                 idValues->AddLimitPath(limitPath);
382                 idValuesMap_.insert(std::make_pair(id, idValues));
383                 std::string name = std::string(idParam->idItem_->name_);
384                 idValuesNameMap_[idParam->idItem_->resType_]->insert(std::make_pair(name, idValues));
385             } else {
386                 HapResource::IdValues *idValues = iter->second;
387                 auto limitPath = new (std::nothrow) HapResource::ValueUnderQualifierDir(resKey->keyParams_,
388                     idParam->idItem_, this, false, system);
389                 if (limitPath == nullptr) {
390                     HILOG_ERROR("new ValueUnderQualifierDir failed in HapResource::InitIdList");
391                     return false;
392                 }
393                 idValues->AddLimitPath(limitPath);
394             }
395         }
396     }
397     return true;
398 };
399 
GetIdValues(const uint32_t id) const400 const HapResource::IdValues *HapResource::GetIdValues(const uint32_t id) const
401 {
402     if (idValuesMap_.empty()) {
403         HILOG_ERROR("idValuesMap_ is empty");
404         return nullptr;
405     }
406     uint32_t uid = id;
407     std::map<uint32_t, IdValues *>::const_iterator iter = idValuesMap_.find(uid);
408     if (iter == idValuesMap_.end()) {
409         return nullptr;
410     }
411 
412     return iter->second;
413 }
414 
GetIdValuesByName(const std::string name,const ResType resType) const415 const HapResource::IdValues *HapResource::GetIdValuesByName(
416     const std::string name, const ResType resType) const
417 {
418     const std::map<std::string, IdValues *> *map = idValuesNameMap_[resType];
419     std::map<std::string, IdValues *>::const_iterator iter = map->find(name);
420     if (iter == map->end()) {
421         return nullptr;
422     }
423 
424     return iter->second;
425 }
426 
GetIdByName(const char * name,const ResType resType) const427 int HapResource::GetIdByName(const char *name, const ResType resType) const
428 {
429     if (name == nullptr) {
430         return -1;
431     }
432     const std::map<std::string, IdValues *> *map = idValuesNameMap_[resType];
433     std::map<std::string, IdValues *>::const_iterator iter = map->find(name);
434     if (iter == map->end()) {
435         return OBJ_NOT_FOUND;
436     }
437     const IdValues *ids = iter->second;
438 
439     if (ids->GetLimitPathsConst().size() == 0) {
440         HILOG_ERROR("limitPaths empty");
441         return UNKNOWN_ERROR;
442     }
443 
444     if (ids->GetLimitPathsConst()[0]->GetIdItem()->resType_ != resType) {
445         HILOG_ERROR("ResType mismatch");
446         return UNKNOWN_ERROR;
447     }
448     return ids->GetLimitPathsConst()[0]->GetIdItem()->id_;
449 }
450 
GetQualifiers() const451 const std::vector<std::string> HapResource::GetQualifiers() const
452 {
453     std::vector<std::string> result;
454     for (size_t i = 0; i < resDesc_->keys_.size(); i++) {
455         result.push_back(resDesc_->keys_[i]->ToString());
456     }
457     return result;
458 }
459 } // namespace Resource
460 } // namespace Global
461 } // namespace OHOS
462