• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024-2025 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 #define LOG_TAG "UtdClient"
17 #include <fstream>
18 #include <regex>
19 #include <thread>
20 #include "utd_client.h"
21 #include "logger.h"
22 #include "utd_graph.h"
23 #include "custom_utd_store.h"
24 
25 namespace OHOS {
26 namespace UDMF {
27 constexpr const int MAX_UTD_LENGTH = 256;
28 constexpr const char *CUSTOM_UTD_HAP_DIR = "/data/utd/utd-adt.json";
29 
UtdClient()30 UtdClient::UtdClient()
31 {
32     Init();
33 }
34 
~UtdClient()35 UtdClient::~UtdClient()
36 {
37 }
38 
GetInstance()39 UtdClient &UtdClient::GetInstance()
40 {
41     static auto instance = new UtdClient();
42     return *instance;
43 }
44 
GetHapTypeCfgs()45 std::vector<TypeDescriptorCfg> GetHapTypeCfgs()
46 {
47     LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", CUSTOM_UTD_HAP_DIR);
48     std::string jsonStr;
49     std::ifstream fin(CUSTOM_UTD_HAP_DIR);
50     while (fin.good()) {
51         std::string line;
52         std::getline(fin, line);
53         jsonStr += line;
54     }
55     std::vector<TypeDescriptorCfg> customUtdTypes;
56     CustomUtdJsonParser utdJsonParser;
57     utdJsonParser.ParseStoredCustomUtdJson(jsonStr, customUtdTypes);
58     LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size());
59     return customUtdTypes;
60 }
61 
Init()62 void UtdClient::Init()
63 {
64     std::unique_lock<std::shared_mutex> lock(utdMutex_);
65     descriptorCfgs_ = PresetTypeDescriptors::GetInstance().GetPresetTypes();
66     std::vector<TypeDescriptorCfg> customTypes;
67     customTypes = GetHapTypeCfgs();
68     LOG_INFO(UDMF_CLIENT, "get customUtd, size:%{public}zu", customTypes.size());
69     if (!customTypes.empty()) {
70         descriptorCfgs_.insert(descriptorCfgs_.end(), customTypes.begin(), customTypes.end());
71     }
72     UtdGraph::GetInstance().InitUtdGraph(descriptorCfgs_);
73 }
74 
IsHapTokenType()75 bool UtdClient::IsHapTokenType()
76 {
77     return true;
78 }
79 
GetCurrentActiveUserId(int32_t & userId)80 Status UtdClient::GetCurrentActiveUserId(int32_t &userId)
81 {
82     return Status::E_OK;
83 }
84 
GetTypeDescriptor(const std::string & typeId,std::shared_ptr<TypeDescriptor> & descriptor)85 Status UtdClient::GetTypeDescriptor(const std::string &typeId, std::shared_ptr<TypeDescriptor> &descriptor)
86 {
87     {
88         std::shared_lock<std::shared_mutex> guard(utdMutex_);
89         for (const auto &utdTypeCfg : descriptorCfgs_) {
90             if (utdTypeCfg.typeId == typeId) {
91                 descriptor = std::make_shared<TypeDescriptor>(utdTypeCfg);
92                 return Status::E_OK;
93             }
94         }
95     }
96     if (typeId.find(FLEXIBLE_TYPE_FLAG) != typeId.npos) {
97         return GetFlexibleTypeDescriptor(typeId, descriptor);
98     }
99     return Status::E_OK;
100 }
101 
IsValidFileExtension(const std::string & fileExtension)102 bool UtdClient::IsValidFileExtension(const std::string &fileExtension)
103 {
104     if (fileExtension.empty()) {
105         return false;
106     }
107     if (fileExtension[0] != '.' || fileExtension.find("?") != fileExtension.npos ||
108         fileExtension.find(":") != fileExtension.npos || fileExtension.find("=") != fileExtension.npos ||
109         fileExtension.find("\\") != fileExtension.npos) {
110             return false;
111     }
112 
113     return true;
114 }
115 
IsValidMimeType(const std::string & mimeType)116 bool UtdClient::IsValidMimeType(const std::string &mimeType)
117 {
118     if (mimeType.empty()) {
119         return false;
120     }
121     if (mimeType.find("?") != mimeType.npos || mimeType.find(":") != mimeType.npos ||
122         mimeType.find("=") != mimeType.npos || mimeType.find("\\") != mimeType.npos) {
123             return false;
124     }
125     return true;
126 }
127 
GetFlexibleTypeDescriptor(const std::string & typeId,std::shared_ptr<TypeDescriptor> & descriptor)128 Status UtdClient::GetFlexibleTypeDescriptor(const std::string &typeId, std::shared_ptr<TypeDescriptor> &descriptor)
129 {
130     TypeDescriptorCfg flexibleTypeDescriptorCfg;
131     if (!FlexibleType::ParseFlexibleUtd(typeId, flexibleTypeDescriptorCfg)) {
132         LOG_ERROR(UDMF_CLIENT, "ParseFlexibleUtd failed, invalid typeId");
133         return Status::E_ERROR;
134     }
135     descriptor = std::make_shared<TypeDescriptor>(flexibleTypeDescriptorCfg);
136     return Status::E_OK;
137 }
138 
GetUniformDataTypeByFilenameExtension(const std::string & fileExtension,std::string & typeId,std::string belongsTo)139 Status UtdClient::GetUniformDataTypeByFilenameExtension(const std::string &fileExtension, std::string &typeId,
140     std::string belongsTo)
141 {
142     std::string lowerFileExtension = fileExtension;
143     std::transform(lowerFileExtension.begin(), lowerFileExtension.end(), lowerFileExtension.begin(), ::tolower);
144     if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) {
145         LOG_ERROR(UDMF_CLIENT, "invalid belongsTo.");
146         return Status::E_INVALID_PARAMETERS;
147     }
148     {
149         std::shared_lock<std::shared_mutex> guard(utdMutex_);
150         bool found = false;
151         for (const auto &utdTypeCfg : descriptorCfgs_) {
152             for (auto fileEx : utdTypeCfg.filenameExtensions) {
153                 std::transform(fileEx.begin(), fileEx.end(), fileEx.begin(), ::tolower);
154                 if (fileEx == lowerFileExtension) {
155                     typeId = utdTypeCfg.typeId;
156                     found = true;
157                     break;
158                 }
159             }
160             if (found) {
161                 break;
162             }
163         }
164     }
165     // the find typeId is not belongsTo to the belongsTo.
166     if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId &&
167         !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) {
168         typeId = "";
169     }
170 
171     if (typeId.empty()) {
172         if (!IsValidFileExtension(lowerFileExtension)) {
173             LOG_ERROR(UDMF_CLIENT, "invalid fileExtension.");
174             return Status::E_INVALID_PARAMETERS;
175         }
176         typeId = FlexibleType::GenFlexibleUtd("", lowerFileExtension, belongsTo);
177     }
178     return Status::E_OK;
179 }
180 
GetUniformDataTypeByMIMEType(const std::string & mimeType,std::string & typeId,std::string belongsTo)181 Status UtdClient::GetUniformDataTypeByMIMEType(const std::string &mimeType, std::string &typeId,
182     std::string belongsTo)
183 {
184     std::string lowerMimeType = mimeType;
185     std::transform(lowerMimeType.begin(), lowerMimeType.end(), lowerMimeType.begin(), ::tolower);
186     if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) {
187         LOG_ERROR(UDMF_CLIENT, "invalid belongsTo.");
188         return Status::E_INVALID_PARAMETERS;
189     }
190     typeId = GetTypeIdFromCfg(lowerMimeType);
191     // the find typeId is not belongsTo to the belongsTo.
192     if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId &&
193         !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) {
194         typeId = "";
195     }
196     if (typeId.empty()) {
197         if (!IsValidMimeType(mimeType)) {
198             LOG_ERROR(UDMF_CLIENT, "invalid mimeType.");
199             return Status::E_INVALID_PARAMETERS;
200         }
201         typeId = FlexibleType::GenFlexibleUtd(lowerMimeType, "", belongsTo);
202     }
203     return Status::E_OK;
204 }
205 
IsUtd(std::string typeId,bool & result)206 Status UtdClient::IsUtd(std::string typeId, bool &result)
207 {
208     if (typeId.empty() || typeId.size() > MAX_UTD_LENGTH) {
209         result = false;
210         return Status::E_INVALID_PARAMETERS;
211     }
212     if (typeId[0] == '.' || find(typeId.begin(), typeId.end(), '/') != typeId.end()) {
213         result = false;
214         return Status::E_OK;
215     }
216     constexpr const char *preSetTypeIdRegexRule =
217       R"(^(general\.|openharmony\.|org\.|com\.|macos\.|debian\.|redhat\.|io\.|de\.|net\.)[a-z0-9-\.]+(\-[a-z0-9-]+)*$)";
218     if (std::regex_match(typeId, std::regex(preSetTypeIdRegexRule))) {
219         result = true;
220         return Status::E_OK;
221     }
222     constexpr const char *customUtdRegexRule =
223       R"(^([A-Za-z]\w*)(\.\w+)+(\.[A-Za-z\d-]+)+)";
224     if (std::regex_match(typeId, std::regex(customUtdRegexRule))) {
225         result = true;
226         return Status::E_OK;
227     }
228     result = false;
229     LOG_ERROR(UDMF_CLIENT, "is not utd");
230     return Status::E_OK;
231 }
232 
GetUniformDataTypesByFilenameExtension(const std::string & fileExtension,std::vector<std::string> & typeIds,const std::string & belongsTo)233 Status UtdClient::GetUniformDataTypesByFilenameExtension(const std::string &fileExtension,
234     std::vector<std::string> &typeIds, const std::string &belongsTo)
235 {
236     if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) {
237         LOG_ERROR(UDMF_CLIENT, "invalid belongsTo.");
238         return Status::E_INVALID_PARAMETERS;
239     }
240     if (!IsValidFileExtension(fileExtension)) {
241         LOG_ERROR(UDMF_CLIENT, "invalid fileExtension.");
242         return Status::E_INVALID_PARAMETERS;
243     }
244 
245     std::string lowerFileExtension = fileExtension;
246     std::transform(lowerFileExtension.begin(), lowerFileExtension.end(), lowerFileExtension.begin(), ::tolower);
247     std::vector<std::string> typeIdsInCfg;
248     {
249         std::shared_lock<std::shared_mutex> guard(utdMutex_);
250         for (const auto &utdTypeCfg : descriptorCfgs_) {
251             for (auto fileEx : utdTypeCfg.filenameExtensions) {
252                 std::transform(fileEx.begin(), fileEx.end(), fileEx.begin(), ::tolower);
253                 if (fileEx == lowerFileExtension) {
254                     typeIdsInCfg.push_back(utdTypeCfg.typeId);
255                     break;
256                 }
257             }
258         }
259     }
260     typeIds.clear();
261     for (const auto &typeId : typeIdsInCfg) {
262         // the find typeId is not belongsTo to the belongsTo.
263         if (belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId &&
264             !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) {
265             continue;
266         }
267         typeIds.emplace_back(typeId);
268     }
269     if (typeIds.empty()) {
270         typeIds.emplace_back(FlexibleType::GenFlexibleUtd("", lowerFileExtension, belongsTo));
271     }
272     return Status::E_OK;
273 }
274 
GetTypeIdFromCfg(const std::string & mimeType)275 std::string UtdClient::GetTypeIdFromCfg(const std::string &mimeType)
276 {
277     std::shared_lock<std::shared_mutex> guard(utdMutex_);
278     for (const auto &utdTypeCfg : descriptorCfgs_) {
279         for (auto mime : utdTypeCfg.mimeTypes) {
280             std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower);
281             if (mime == mimeType) {
282                 return utdTypeCfg.typeId;
283             }
284         }
285     }
286     if (mimeType.empty() || mimeType.back() != '*') {
287         return "";
288     }
289     std::string prefixType = mimeType.substr(0, mimeType.length() - 1);
290     for (const auto &utdTypeCfg : descriptorCfgs_) {
291         for (auto mime : utdTypeCfg.mimeTypes) {
292             std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower);
293             if (mime.rfind(prefixType, 0) == 0 && utdTypeCfg.belongingToTypes.size() > 0) {
294                 return utdTypeCfg.belongingToTypes[0];
295             }
296         }
297     }
298     return "";
299 }
300 
GetTypeIdsFromCfg(const std::string & mimeType)301 std::vector<std::string> UtdClient::GetTypeIdsFromCfg(const std::string &mimeType)
302 {
303     bool prefixMatch = false;
304     std::string prefixType;
305     if (!mimeType.empty() && mimeType.back() == '*') {
306         prefixType = mimeType.substr(0, mimeType.length() - 1);
307         prefixMatch = true;
308     }
309     std::vector<std::string> typeIdsInCfg;
310 
311     std::shared_lock<std::shared_mutex> guard(utdMutex_);
312     for (const auto &utdTypeCfg : descriptorCfgs_) {
313         for (auto mime : utdTypeCfg.mimeTypes) {
314             std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower);
315             if ((mime == mimeType) || (prefixMatch && mime.rfind(prefixType, 0) == 0)) {
316                 typeIdsInCfg.push_back(utdTypeCfg.typeId);
317                 break;
318             }
319         }
320     }
321     return typeIdsInCfg;
322 }
323 
SubscribeUtdChange()324 void UtdClient::SubscribeUtdChange()
325 {
326 }
327 
GetUniformDataTypesByMIMEType(const std::string & mimeType,std::vector<std::string> & typeIds,const std::string & belongsTo)328 Status UtdClient::GetUniformDataTypesByMIMEType(const std::string &mimeType, std::vector<std::string> &typeIds,
329     const std::string &belongsTo)
330 {
331     if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) {
332         LOG_ERROR(UDMF_CLIENT, "invalid belongsTo.");
333         return Status::E_INVALID_PARAMETERS;
334     }
335     if (!IsValidMimeType(mimeType)) {
336         LOG_ERROR(UDMF_CLIENT, "invalid mimeType.");
337         return Status::E_INVALID_PARAMETERS;
338     }
339 
340     std::string lowerMimeType = mimeType;
341     std::transform(lowerMimeType.begin(), lowerMimeType.end(), lowerMimeType.begin(), ::tolower);
342     std::vector<std::string> typeIdsInCfg = GetTypeIdsFromCfg(lowerMimeType);
343     typeIds.clear();
344     for (const auto &typeId : typeIdsInCfg) {
345         // the find typeId is not belongsTo to the belongsTo.
346         if (belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId &&
347             !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) {
348             continue;
349         }
350         typeIds.emplace_back(typeId);
351     }
352     if (typeIds.empty()) {
353         typeIds.emplace_back(FlexibleType::GenFlexibleUtd(lowerMimeType, "", belongsTo));
354     }
355     return Status::E_OK;
356 }
357 } // namespace UDMF
358 } // namespace OHOS
359