• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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