• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 "id_defined_parser.h"
17 #include "file_entry.h"
18 #include "file_manager.h"
19 #include "resource_util.h"
20 
21 namespace OHOS {
22 namespace Global {
23 namespace Restool {
24 using namespace std;
25 const int64_t IdDefinedParser::START_SYS_ID = 0x07800000;
IdDefinedParser(const PackageParser & packageParser,const ResourceIdCluster & type)26 IdDefinedParser::IdDefinedParser(const PackageParser &packageParser, const ResourceIdCluster &type)
27     : packageParser_(packageParser), type_(type), root_(nullptr)
28 {
29 }
30 
~IdDefinedParser()31 IdDefinedParser::~IdDefinedParser()
32 {
33     if (root_) {
34         cJSON_Delete(root_);
35     }
36 }
37 
Init()38 uint32_t IdDefinedParser::Init()
39 {
40     InitParser();
41     string idDefinedInput = packageParser_.GetIdDefinedInputPath();
42     int64_t startId = static_cast<int64_t>(packageParser_.GetStartId());
43     bool combine = packageParser_.GetCombine();
44     bool isSys = type_ == ResourceIdCluster::RES_ID_SYS;
45     for (const auto &inputPath : packageParser_.GetInputs()) {
46         string idDefinedPath;
47         if (combine) {
48             idDefinedPath = FileEntry::FilePath(inputPath).Append(ID_DEFINED_FILE).GetPath();
49         } else {
50             idDefinedPath = ResourceUtil::GetBaseElementPath(inputPath).Append(ID_DEFINED_FILE).GetPath();
51         }
52         if (ResourceUtil::FileExist(idDefinedPath) && startId > 0) {
53             PrintError(GetError(ERR_CODE_EXCLUSIVE_START_ID).FormatCause(startId).SetPosition(idDefinedPath));
54             return RESTOOL_ERROR;
55         }
56         if (Init(idDefinedPath, isSys) != RESTOOL_SUCCESS) {
57             return RESTOOL_ERROR;
58         }
59     }
60     //SystemResource.hap only defined by base/element/id_defined.json
61     string moduleName = FileManager::GetInstance().GetModuleName();
62     if (isSys && moduleName == "entry") {
63         return RESTOOL_SUCCESS;
64     }
65     if (!idDefinedInput.empty() && ResourceUtil::FileExist(idDefinedInput)) {
66         appDefinedIds_.clear();
67         idDefineds_.clear();
68         string idDefinedPath = FileEntry::FilePath(idDefinedInput).GetPath();
69         if (Init(idDefinedPath, false) != RESTOOL_SUCCESS) {
70             return RESTOOL_ERROR;
71         }
72     }
73     for (const auto &sysIdDefinedPath : packageParser_.GetSysIdDefinedPaths()) {
74         if (Init(sysIdDefinedPath, true) != RESTOOL_SUCCESS) {
75             return RESTOOL_ERROR;
76         }
77     }
78     string sysIdDefinedPath = FileEntry::FilePath(packageParser_.GetRestoolPath())
79         .GetParent().Append(ID_DEFINED_FILE).GetPath();
80     if (Init(sysIdDefinedPath, true) != RESTOOL_SUCCESS) {
81         return RESTOOL_ERROR;
82     }
83     return RESTOOL_SUCCESS;
84 }
85 
Init(const string & filePath,bool isSystem)86 uint32_t IdDefinedParser::Init(const string &filePath, bool isSystem)
87 {
88     if (!ResourceUtil::FileExist(filePath)) {
89         return RESTOOL_SUCCESS;
90     }
91 
92     if (!ResourceUtil::OpenJsonFile(filePath, &root_)) {
93         return RESTOOL_ERROR;
94     }
95 
96     if (!root_ || !cJSON_IsObject(root_)) {
97         PrintError(GetError(ERR_CODE_JSON_FORMAT_ERROR).SetPosition(filePath));
98         return RESTOOL_ERROR;
99     }
100 
101     cJSON *recordNode = cJSON_GetObjectItem(root_, "record");
102     if (!recordNode || !cJSON_IsArray(recordNode)) {
103         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("record", "array").SetPosition(filePath));
104         return RESTOOL_ERROR;
105     }
106     if (cJSON_GetArraySize(recordNode) == 0) {
107         cerr << "Warning: 'record' node is empty, please check the JSON file.";
108         cerr << NEW_LINE_PATH << filePath << endl;
109         return RESTOOL_SUCCESS;
110     }
111     int64_t startSysId = 0;
112     if (isSystem) {
113         startSysId = GetStartId(filePath);
114         if (startSysId < 0) {
115             return RESTOOL_ERROR;
116         }
117     }
118 
119     if (IdDefinedToResourceIds(filePath, recordNode, isSystem, startSysId) != RESTOOL_SUCCESS) {
120         return RESTOOL_ERROR;
121     }
122     return RESTOOL_SUCCESS;
123 }
124 
InitParser()125 void IdDefinedParser::InitParser()
126 {
127     using namespace placeholders;
128     handles_.emplace("type", bind(&IdDefinedParser::ParseType, this, _1, _2, _3));
129     handles_.emplace("name", bind(&IdDefinedParser::ParseName, this, _1, _2, _3));
130     handles_.emplace("id", bind(&IdDefinedParser::ParseId, this, _1, _2, _3));
131     handles_.emplace("order", bind(&IdDefinedParser::ParseOrder, this, _1, _2, _3));
132 }
133 
IdDefinedToResourceIds(const std::string & filePath,const cJSON * record,bool isSystem,const int64_t startSysId)134 uint32_t IdDefinedParser::IdDefinedToResourceIds(const std::string &filePath, const cJSON *record,
135     bool isSystem, const int64_t startSysId)
136 {
137     int64_t index = -1;
138     for (cJSON *item = record->child; item; item = item->next) {
139         index++;
140         if (!cJSON_IsObject(item)) {
141             PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("record's child", "object")
142                 .SetPosition(filePath));
143             return RESTOOL_ERROR;
144         }
145         ResourceId resourceId;
146         resourceId.seq = index;
147         resourceId.id = startSysId;
148         for (const auto &handle : handles_) {
149             if ((handle.first == "id" && isSystem) || (handle.first == "order" && !isSystem)) {
150                 continue;
151             }
152             if (!handle.second(filePath, cJSON_GetObjectItem(item, handle.first.c_str()), resourceId)) {
153                 return RESTOOL_ERROR;
154             }
155         }
156         if (!PushResourceId(filePath, resourceId, isSystem)) {
157             return RESTOOL_ERROR;
158         }
159     }
160     return RESTOOL_SUCCESS;
161 }
162 
PushResourceId(const std::string & filePath,const ResourceId & resourceId,bool isSystem)163 bool IdDefinedParser::PushResourceId(const std::string &filePath, const ResourceId &resourceId, bool isSystem)
164 {
165     ResType resType = ResourceUtil::GetResTypeFromString(resourceId.type);
166     auto ret = idDefineds_.emplace(resourceId.id, resourceId);
167     if (!ret.second) {
168         PrintError(GetError(ERR_CODE_ID_DEFINED_SAME_ID).FormatCause(ret.first->second.name.c_str(),
169             resourceId.name.c_str()).SetPosition(filePath));
170         return false;
171     }
172     auto checkRet = checkDefinedIds_.find(filePath);
173     if (checkRet != checkDefinedIds_.end()) {
174         bool found = any_of(checkRet->second.begin(), checkRet->second.end(),
175             [resType, resourceId](const auto &iterItem) {
176             return (resType == iterItem.first)  && (resourceId.name == iterItem.second);
177         });
178         if (found) {
179             PrintError(GetError(ERR_CODE_RESOURCE_DUPLICATE).FormatCause(resourceId.name.c_str(),
180                 filePath.c_str(), filePath.c_str()));
181             return false;
182         }
183         checkRet->second.push_back(make_pair(resType, resourceId.name));
184     } else {
185         std::vector<std::pair<ResType, std::string>> vects;
186         vects.push_back(make_pair(resType, resourceId.name));
187         checkDefinedIds_.emplace(filePath, vects);
188     }
189     if (isSystem) {
190         sysDefinedIds_.emplace(make_pair(resType, resourceId.name), resourceId);
191     } else {
192         appDefinedIds_.emplace(make_pair(resType, resourceId.name), resourceId);
193     }
194     return true;
195 }
196 
ParseId(const std::string & filePath,const cJSON * origId,ResourceId & resourceId)197 bool IdDefinedParser::ParseId(const std::string &filePath, const cJSON *origId, ResourceId &resourceId)
198 {
199     if (!origId) {
200         PrintError(GetError(ERR_CODE_JSON_NODE_MISSING).FormatCause("id").SetPosition(filePath));
201         return false;
202     }
203     if (!cJSON_IsString(origId)) {
204         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("id", "string").SetPosition(filePath));
205         return false;
206     }
207     string idStr = origId->valuestring;
208     if (!ResourceUtil::CheckHexStr(idStr)) {
209         PrintError(GetError(ERR_CODE_ID_DEFINED_INVALID_ID).FormatCause(idStr.c_str()).SetPosition(filePath));
210         return false;
211     }
212     int64_t id = strtoll(idStr.c_str(), nullptr, 16);
213     if (id < 0x01000000 || (id > 0x06FFFFFF && id < 0x08000000) || id > 0xFFFFFFFF) {
214         PrintError(GetError(ERR_CODE_ID_DEFINED_INVALID_ID).FormatCause(idStr.c_str()).SetPosition(filePath));
215         return false;
216     }
217     resourceId.id = id;
218     return true;
219 }
220 
ParseType(const std::string & filePath,const cJSON * type,ResourceId & resourceId)221 bool IdDefinedParser::ParseType(const std::string &filePath, const cJSON *type, ResourceId &resourceId)
222 {
223     if (!type) {
224         std::string msg = "type";
225         msg.append(cJSON_GetErrorPtr());
226         PrintError(GetError(ERR_CODE_JSON_NODE_MISSING).FormatCause("type").SetPosition(filePath));
227         return false;
228     }
229     if (!cJSON_IsString(type)) {
230         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("type", "string").SetPosition(filePath));
231         return false;
232     }
233     if (ResourceUtil::GetResTypeFromString(type->valuestring) == ResType::INVALID_RES_TYPE) {
234         PrintError(GetError(ERR_CODE_ID_DEFINED_INVALID_TYPE)
235                        .FormatCause(type->valuestring, ResourceUtil::GetAllRestypeString().c_str())
236                        .SetPosition(filePath));
237         return false;
238     }
239     resourceId.type = type->valuestring;
240     return true;
241 }
242 
ParseName(const std::string & filePath,const cJSON * name,ResourceId & resourceId)243 bool IdDefinedParser::ParseName(const std::string &filePath, const cJSON *name, ResourceId &resourceId)
244 {
245     if (!name) {
246         PrintError(GetError(ERR_CODE_JSON_NODE_MISSING).FormatCause("name").SetPosition(filePath));
247         return false;
248     }
249     if (!cJSON_IsString(name)) {
250         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("name", "string").SetPosition(filePath));
251         return false;
252     }
253     resourceId.name = name->valuestring;
254     if (type_ == ResourceIdCluster::RES_ID_SYS &&
255         (static_cast<uint64_t>(resourceId.id) & static_cast<uint64_t>(START_SYS_ID)) == START_SYS_ID &&
256         !ResourceUtil::IsValidName(resourceId.name)) {
257         PrintError(GetError(ERR_CODE_INVALID_RESOURCE_NAME).FormatCause(resourceId.name.c_str())
258             .SetPosition(filePath));
259         return false;
260     }
261     return true;
262 }
263 
ParseOrder(const std::string & filePath,const cJSON * order,ResourceId & resourceId)264 bool IdDefinedParser::ParseOrder(const std::string &filePath, const cJSON *order, ResourceId &resourceId)
265 {
266     if (!order) {
267         PrintError(GetError(ERR_CODE_JSON_NODE_MISSING).FormatCause("order").SetPosition(filePath));
268         return false;
269     }
270     if (!ResourceUtil::IsIntValue(order)) {
271         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("order", "integer").SetPosition(filePath));
272         return false;
273     }
274     int64_t orderId = order->valueint;
275     if (orderId != resourceId.seq) {
276         PrintError(GetError(ERR_CODE_ID_DEFINED_ORDER_MISMATCH).FormatCause(orderId, resourceId.seq, resourceId.seq)
277             .SetPosition(filePath));
278         return false;
279     }
280     resourceId.id = resourceId.id + orderId;
281     return true;
282 }
283 
GetStartId(const std::string & filePath) const284 int64_t IdDefinedParser::GetStartId(const std::string &filePath) const
285 {
286     cJSON *startIdNode = cJSON_GetObjectItem(root_, "startId");
287     if (!startIdNode) {
288         PrintError(GetError(ERR_CODE_JSON_NODE_MISSING).FormatCause("startId").SetPosition(filePath));
289         return -1;
290     }
291 
292     if (!cJSON_IsString(startIdNode)) {
293         PrintError(GetError(ERR_CODE_JSON_NODE_MISMATCH).FormatCause("startId", "string").SetPosition(filePath));
294         return -1;
295     }
296 
297     int64_t id = strtoll(startIdNode->valuestring, nullptr, 16);
298     if (id == 0) {
299         PrintError(GetError(ERR_CODE_ID_DEFINED_INVALID_ID).FormatCause(startIdNode->valuestring)
300             .SetPosition(filePath));
301         return -1;
302     }
303     return id;
304 }
305 
306 }
307 }
308 }