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 <fstream>
19 #include <iostream>
20 
21 #include "hap_parser.h"
22 #include "hilog_wrapper.h"
23 #include "locale_matcher.h"
24 #include "utils/errors.h"
25 #include "utils/string_utils.h"
26 
27 #if defined(__linux__)
28 #include <malloc.h>
29 #endif
30 
31 namespace OHOS {
32 namespace Global {
33 namespace Resource {
ValueUnderQualifierDir(const std::vector<KeyParam * > & keyParams,IdItem * idItem,HapResource * hapResource)34 HapResource::ValueUnderQualifierDir::ValueUnderQualifierDir(const std::vector<KeyParam *> &keyParams, IdItem *idItem,
35     HapResource *hapResource) : hapResource_(hapResource)
36 {
37     keyParams_ = keyParams;
38     folder_ = HapParser::ToFolderPath(keyParams_);
39     idItem_ = idItem;
40     InitResConfig();
41 }
42 
~ValueUnderQualifierDir()43 HapResource::ValueUnderQualifierDir::~ValueUnderQualifierDir()
44 {
45     // keyParams_ idItem_ was passed into this, we dont delete them because someone will do
46     delete (resConfig_);
47 }
48 
InitResConfig()49 void HapResource::ValueUnderQualifierDir::InitResConfig()
50 {
51     resConfig_ = HapParser::CreateResConfigFromKeyParams(keyParams_);
52 }
53 
54 // IdValues
~IdValues()55 HapResource::IdValues::~IdValues()
56 {
57     for (size_t i = 0; i < limitPaths_.size(); ++i) {
58         auto path = limitPaths_[i];
59         delete (path);
60     }
61 }
62 
63 // HapResource
HapResource(const std::string path,time_t lastModTime,const ResConfig * defaultConfig,ResDesc * resDes)64 HapResource::HapResource(const std::string path, time_t lastModTime, const ResConfig *defaultConfig, ResDesc *resDes)
65     : indexPath_(path), lastModTime_(lastModTime), resDesc_(resDes), defaultConfig_(defaultConfig)
66 {
67 }
68 
~HapResource()69 HapResource::~HapResource()
70 {
71     delete (resDesc_);
72     std::map<uint32_t, IdValues *>::iterator iter;
73     for (iter = idValuesMap_.begin(); iter != idValuesMap_.end(); ++iter) {
74         IdValues *ptr = iter->second;
75         delete (ptr);
76     }
77 
78     for (size_t i = 0; i < idValuesNameMap_.size(); ++i) {
79         delete (idValuesNameMap_[i]);
80     }
81     lastModTime_ = 0;
82     // defaultConfig_ was passed by constructor, we do not delete it here
83     defaultConfig_ = nullptr;
84 }
85 
LoadFromIndex(const char * path,const ResConfigImpl * defaultConfig,bool system)86 const HapResource *HapResource::LoadFromIndex(const char *path, const ResConfigImpl *defaultConfig, bool system)
87 {
88     std::ifstream inFile(path, std::ios::binary | std::ios::in);
89     if (!inFile.good()) {
90         return nullptr;
91     }
92     inFile.seekg(0, std::ios::end);
93     int bufLen = inFile.tellg();
94     if (bufLen <= 0) {
95         HILOG_ERROR("file size is zero");
96         inFile.close();
97         return nullptr;
98     }
99     void *buf = malloc(bufLen);
100     if (buf == nullptr) {
101         HILOG_ERROR("Error allocating memory");
102         inFile.close();
103         return nullptr;
104     }
105     inFile.seekg(0, std::ios::beg);
106     inFile.read(static_cast<char *>(buf), bufLen);
107     inFile.close();
108 
109     HILOG_DEBUG("extract success, bufLen:%d", bufLen);
110 
111     ResDesc *resDesc = new (std::nothrow) ResDesc();
112     if (resDesc == nullptr) {
113         HILOG_ERROR("new ResDesc failed when LoadFromIndex");
114         free(buf);
115         return nullptr;
116     }
117     int32_t out = HapParser::ParseResHex(static_cast<char *>(buf), bufLen, *resDesc, defaultConfig);
118     if (out != OK) {
119         delete (resDesc);
120         free(buf);
121         HILOG_ERROR("ParseResHex failed! retcode:%d", out);
122         return nullptr;
123     } else {
124         HILOG_DEBUG("ParseResHex success:\n%s", resDesc->ToString().c_str());
125     }
126     free(buf);
127 
128     HapResource *pResource = new (std::nothrow) HapResource(std::string(path), 0, defaultConfig, resDesc);
129     if (pResource == nullptr) {
130         HILOG_ERROR("new HapResource failed when LoadFromIndex");
131         delete (resDesc);
132         return nullptr;
133     }
134     if (!pResource->Init()) {
135         delete (pResource);
136         return nullptr;
137     }
138     return pResource;
139 }
140 
Init()141 bool HapResource::Init()
142 {
143     auto index = indexPath_.rfind('/');
144     if (index == std::string::npos) {
145         HILOG_ERROR("index path format error, %s", indexPath_.c_str());
146         return false;
147     }
148     index = indexPath_.rfind('/', index - 1);
149     if (index == std::string::npos) {
150         HILOG_ERROR("index path format error, %s", indexPath_.c_str());
151         return false;
152     }
153     resourcePath_ = indexPath_.substr(0, index + 1);
154     for (int i = 0; i < ResType::MAX_RES_TYPE; ++i) {
155         auto mptr = new (std::nothrow) std::map<std::string, IdValues *>();
156         if (mptr == nullptr) {
157             HILOG_ERROR("new std::map failed in HapResource::Init");
158             return false;
159         }
160         idValuesNameMap_.push_back(mptr);
161     }
162     return InitIdList();
163 }
164 
InitIdList()165 bool HapResource::InitIdList()
166 {
167     if (resDesc_ == nullptr) {
168         HILOG_ERROR("resDesc_ is null ! InitIdList failed");
169         return false;
170     }
171     for (size_t i = 0; i < resDesc_->keys_.size(); i++) {
172         ResKey *resKey = resDesc_->keys_[i];
173 
174         for (size_t j = 0; j < resKey->resId_->idParams_.size(); ++j) {
175             IdParam *idParam = resKey->resId_->idParams_[j];
176             uint32_t id = idParam->id_;
177             std::map<uint32_t, IdValues *>::iterator iter = idValuesMap_.find(id);
178             if (iter == idValuesMap_.end()) {
179                 auto idValues = new (std::nothrow) HapResource::IdValues();
180                 if (idValues == nullptr) {
181                     HILOG_ERROR("new IdValues failed in HapResource::InitIdList");
182                     return false;
183                 }
184                 auto limitPath =
185                     new (std::nothrow) HapResource::ValueUnderQualifierDir(resKey->keyParams_, idParam->idItem_, this);
186                 if (limitPath == nullptr) {
187                     HILOG_ERROR("new ValueUnderQualifierDir failed in HapResource::InitIdList");
188                     delete (idValues);
189                     return false;
190                 }
191                 idValues->AddLimitPath(limitPath);
192                 idValuesMap_.insert(std::make_pair(id, idValues));
193                 std::string name = std::string(idParam->idItem_->name_);
194                 idValuesNameMap_[idParam->idItem_->resType_]->insert(std::make_pair(name, idValues));
195             } else {
196                 HapResource::IdValues *idValues = iter->second;
197                 auto limitPath =
198                     new (std::nothrow) HapResource::ValueUnderQualifierDir(resKey->keyParams_, idParam->idItem_, this);
199                 if (limitPath == nullptr) {
200                     HILOG_ERROR("new ValueUnderQualifierDir failed in HapResource::InitIdList");
201                     return false;
202                 }
203                 idValues->AddLimitPath(limitPath);
204             }
205         }
206     }
207     return true;
208 };
209 
GetIdValues(const uint32_t id) const210 const HapResource::IdValues *HapResource::GetIdValues(const uint32_t id) const
211 {
212     uint32_t uid = id;
213     std::map<uint32_t, IdValues *>::const_iterator iter = idValuesMap_.find(uid);
214     if (iter == idValuesMap_.end()) {
215         return nullptr;
216     }
217 
218     return iter->second;
219 }
220 
GetIdValuesByName(const std::string name,const ResType resType) const221 const HapResource::IdValues *HapResource::GetIdValuesByName(
222     const std::string name, const ResType resType) const
223 {
224     const std::map<std::string, IdValues *> *map = idValuesNameMap_[resType];
225     std::map<std::string, IdValues *>::const_iterator iter = map->find(name);
226     if (iter == map->end()) {
227         return nullptr;
228     }
229 
230     return iter->second;
231 }
232 
GetIdByName(const char * name,const ResType resType) const233 int HapResource::GetIdByName(const char *name, const ResType resType) const
234 {
235     if (name == nullptr) {
236         return -1;
237     }
238     const std::map<std::string, IdValues *> *map = idValuesNameMap_[resType];
239     std::map<std::string, IdValues *>::const_iterator iter = map->find(name);
240     if (iter == map->end()) {
241         return OBJ_NOT_FOUND;
242     }
243     const IdValues *ids = iter->second;
244 
245     if (ids->GetLimitPathsConst().size() == 0) {
246         HILOG_ERROR("limitPaths empty");
247         return UNKNOWN_ERROR;
248     }
249 
250     if (ids->GetLimitPathsConst()[0]->GetIdItem()->resType_ != resType) {
251         HILOG_ERROR("ResType mismatch");
252         return UNKNOWN_ERROR;
253     }
254     return ids->GetLimitPathsConst()[0]->GetIdItem()->id_;
255 }
256 } // namespace Resource
257 } // namespace Global
258 } // namespace OHOS
259