1 /*
2 * Copyright (c) 2023 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 #define LOG_TAG "UtdCfgsChecker"
16 #include "utd_cfgs_checker.h"
17
18 #include <regex>
19 #include "utd_graph.h"
20 #include "logger.h"
21
22 namespace OHOS {
23 namespace UDMF {
24 constexpr const char *TYPE_ID_REGEX = "[a-zA-Z0-9/.-]+$";
25 constexpr const char FILE_EXTENSION_PREFIX = '.';
26 constexpr const int32_t MAX_UTD_SIZE = 50;
27
UtdCfgsChecker()28 UtdCfgsChecker::UtdCfgsChecker()
29 {
30 }
31
~UtdCfgsChecker()32 UtdCfgsChecker::~UtdCfgsChecker()
33 {
34 }
35
GetInstance()36 UtdCfgsChecker &UtdCfgsChecker::GetInstance()
37 {
38 static auto instance = new UtdCfgsChecker();
39 return *instance;
40 }
41
CheckTypeDescriptors(CustomUtdCfgs & typeCfgs,const std::vector<TypeDescriptorCfg> & presetCfgs,const std::vector<TypeDescriptorCfg> & customCfgs,const std::string & bundleName)42 bool UtdCfgsChecker::CheckTypeDescriptors(CustomUtdCfgs &typeCfgs, const std::vector<TypeDescriptorCfg> &presetCfgs,
43 const std::vector<TypeDescriptorCfg> &customCfgs, const std::string &bundleName)
44 {
45 if (!CheckTypesFormat(typeCfgs, bundleName)) {
46 LOG_ERROR(UDMF_CLIENT, "CheckTypesFormat not pass, bundleName: %{public}s.", bundleName.c_str());
47 return false;
48 }
49 if (!CheckTypesRelation(typeCfgs, presetCfgs, customCfgs)) {
50 LOG_ERROR(UDMF_CLIENT, "CheckTypesRelation not pass, bundleName: %{public}s.", bundleName.c_str());
51 return false;
52 }
53 return true;
54 }
55
CheckTypesFormat(CustomUtdCfgs & typeCfgs,const std::string & bundleName)56 bool UtdCfgsChecker::CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string &bundleName)
57 {
58 #ifndef CROSS_PLATFORM
59 try {
60 #endif
61 for (auto declarationType: typeCfgs.first) {
62 if (!std::regex_match(declarationType.typeId, std::regex(bundleName + TYPE_ID_REGEX))) {
63 LOG_ERROR(UDMF_CLIENT, "Declaration typeId check failed, bundleName: %{public}s", bundleName.c_str());
64 return false;
65 }
66 }
67 for (auto referenceTypes: typeCfgs.second) {
68 if (!std::regex_match(referenceTypes.typeId, std::regex(TYPE_ID_REGEX))) {
69 LOG_ERROR(UDMF_CLIENT, "Reference typeId check failed, bundleName: %{public}s", bundleName.c_str());
70 return false;
71 }
72 }
73 #ifndef CROSS_PLATFORM
74 } catch (const std::regex_error& e) {
75 LOG_ERROR(UDMF_CLIENT, "catch regex_error, bundleName: %{public}s.", bundleName.c_str());
76 return false;
77 }
78 #endif
79 return CheckTypesOptions(typeCfgs, bundleName);
80 }
81
CheckTypesOptions(CustomUtdCfgs & typeCfgs,const std::string & bundleName)82 bool UtdCfgsChecker::CheckTypesOptions(CustomUtdCfgs &typeCfgs, const std::string &bundleName)
83 {
84 std::vector<TypeDescriptorCfg> inputTypeCfgs;
85 if (!typeCfgs.first.empty()) {
86 inputTypeCfgs.insert(inputTypeCfgs.end(), typeCfgs.first.begin(), typeCfgs.first.end());
87 }
88 if (!typeCfgs.second.empty()) {
89 inputTypeCfgs.insert(inputTypeCfgs.end(), typeCfgs.second.begin(), typeCfgs.second.end());
90 }
91 for (TypeDescriptorCfg &typeCfg : inputTypeCfgs) {
92 for (std::string filenames : typeCfg.filenameExtensions) {
93 if (filenames.size() <= 1 || filenames[0] != FILE_EXTENSION_PREFIX) {
94 LOG_ERROR(UDMF_CLIENT, "Extension not valid, bundleName: %{public}s.", bundleName.c_str());
95 return false;
96 }
97 }
98 if (typeCfg.belongingToTypes.empty()) {
99 LOG_ERROR(UDMF_CLIENT, "BelongingToTypes can not be empty, bundleName: %{public}s.", bundleName.c_str());
100 return false;
101 }
102 for (std::string mimeType : typeCfg.mimeTypes) {
103 if (mimeType.empty()) {
104 LOG_ERROR(UDMF_CLIENT, "mimeType can not be an empty string");
105 return false;
106 }
107 }
108 }
109 return true;
110 }
111
CheckTypesRelation(CustomUtdCfgs & typeCfgs,const std::vector<TypeDescriptorCfg> & presetCfgs,const std::vector<TypeDescriptorCfg> & customCfgs)112 bool UtdCfgsChecker::CheckTypesRelation(CustomUtdCfgs &typeCfgs, const std::vector<TypeDescriptorCfg> &presetCfgs,
113 const std::vector<TypeDescriptorCfg> &customCfgs)
114 {
115 std::vector<TypeDescriptorCfg> inputTypeCfgs;
116 if (!typeCfgs.first.empty()) {
117 inputTypeCfgs.insert(inputTypeCfgs.end(), typeCfgs.first.begin(), typeCfgs.first.end());
118 }
119 if (!typeCfgs.second.empty()) {
120 inputTypeCfgs.insert(inputTypeCfgs.end(), typeCfgs.second.begin(), typeCfgs.second.end());
121 }
122 std::vector<std::string> typeIds;
123 for (auto &inputTypeCfg: inputTypeCfgs) {
124 typeIds.push_back(inputTypeCfg.typeId);
125 }
126 if (typeIds.size() > MAX_UTD_SIZE) {
127 LOG_ERROR(UDMF_CLIENT, "Create more UTDs than limit.");
128 return false;
129 }
130 for (auto &presetCfg: presetCfgs) {
131 typeIds.push_back(presetCfg.typeId);
132 }
133 if (std::set<std::string>(typeIds.begin(), typeIds.end()).size() != typeIds.size()) {
134 LOG_ERROR(UDMF_CLIENT, "Find duplicated typeIds.");
135 return false;
136 }
137 if (!CheckBelongingToTypes(inputTypeCfgs, presetCfgs)) {
138 LOG_ERROR(UDMF_CLIENT, "BelongingToType check failed.");
139 return false;
140 }
141 if (!CanConstructDAG(typeCfgs, presetCfgs, customCfgs)) {
142 LOG_ERROR(UDMF_CLIENT, "Can not construct DAG.");
143 return false;
144 }
145 return true;
146 }
147
CheckBelongingToTypes(const std::vector<TypeDescriptorCfg> & typeCfgs,const std::vector<TypeDescriptorCfg> & presetCfgs)148 bool UtdCfgsChecker::CheckBelongingToTypes(const std::vector<TypeDescriptorCfg> &typeCfgs,
149 const std::vector<TypeDescriptorCfg> &presetCfgs)
150 {
151 std::vector<std::string> typeIds;
152 for (auto &typeCfg: typeCfgs) {
153 typeIds.push_back(typeCfg.typeId);
154 }
155 for (auto &presetCfg: presetCfgs) {
156 typeIds.push_back(presetCfg.typeId);
157 }
158 for (auto &inputCfg : typeCfgs) {
159 for (std::string belongingToType : inputCfg.belongingToTypes) {
160 if (belongingToType.empty()) {
161 LOG_ERROR(UDMF_CLIENT, "BelongingToType can not be an empty string");
162 return false;
163 }
164 if (inputCfg.typeId == belongingToType) {
165 LOG_ERROR(UDMF_CLIENT, "TypeId cannot equals belongingToType");
166 return false;
167 }
168 if (find(typeIds.begin(), typeIds.end(), belongingToType) == typeIds.end()) {
169 LOG_ERROR(UDMF_CLIENT, "BelongingToType can not find in typeids, belongingToType: %{public}s.",
170 belongingToType.c_str());
171 return false;
172 }
173 }
174 }
175 return true;
176 }
177
CanConstructDAG(CustomUtdCfgs & typeCfgs,const std::vector<TypeDescriptorCfg> & presetCfgs,const std::vector<TypeDescriptorCfg> & customCfgs)178 bool UtdCfgsChecker::CanConstructDAG(CustomUtdCfgs &typeCfgs, const std::vector<TypeDescriptorCfg> &presetCfgs,
179 const std::vector<TypeDescriptorCfg> &customCfgs)
180 {
181 std::vector<TypeDescriptorCfg> allTypeCfgs;
182 if (!customCfgs.empty()) {
183 allTypeCfgs.insert(allTypeCfgs.end(), customCfgs.begin(), customCfgs.end());
184 }
185 for (TypeDescriptorCfg &declarationType : typeCfgs.first) {
186 for (auto iter = allTypeCfgs.begin(); iter != allTypeCfgs.end();) {
187 if (iter->typeId == declarationType.typeId) {
188 iter = allTypeCfgs.erase(iter);
189 } else {
190 iter ++;
191 }
192 }
193 allTypeCfgs.push_back(declarationType);
194 }
195 for (TypeDescriptorCfg &referenceTypes : typeCfgs.second) {
196 bool found = false;
197 for (auto &typeCfg : allTypeCfgs) {
198 if (typeCfg.typeId == referenceTypes.typeId) {
199 found = true;
200 break;
201 }
202 }
203 if (!found) {
204 allTypeCfgs.push_back(referenceTypes);
205 }
206 }
207 if (!presetCfgs.empty()) {
208 allTypeCfgs.insert(allTypeCfgs.end(), presetCfgs.begin(), presetCfgs.end());
209 }
210 if (!allTypeCfgs.empty()) {
211 auto graph = UtdGraph::GetInstance().ConstructNewGraph(allTypeCfgs);
212 if (graph->IsDAG()) {
213 return true;
214 }
215 }
216 return false;
217 }
218 } // namespace UDMF
219 } // namespace OHOS
220