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 "app_log_wrapper.h"
17 #include "skill.h"
18 #include <regex>
19 #include <unistd.h>
20 #include "mime_type_mgr.h"
21 #include "parcel_macro.h"
22 #include "json_util.h"
23 #include <fcntl.h>
24 #include "nlohmann/json.hpp"
25 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED
26 #include "type_descriptor.h"
27 #include "utd_client.h"
28 #endif
29 
30 namespace OHOS {
31 namespace AppExecFwk {
32 namespace {
33 constexpr const char* JSON_KEY_TYPE = "type";
34 constexpr const char* JSON_KEY_PERMISSIONS = "permissions";
35 constexpr const char* JSON_KEY_ACTIONS = "actions";
36 constexpr const char* JSON_KEY_ENTITIES = "entities";
37 constexpr const char* JSON_KEY_URIS = "uris";
38 constexpr const char* JSON_KEY_SCHEME = "scheme";
39 constexpr const char* JSON_KEY_HOST = "host";
40 constexpr const char* JSON_KEY_PORT = "port";
41 constexpr const char* JSON_KEY_PATH = "path";
42 constexpr const char* JSON_KEY_PATHSTARTWITH = "pathStartWith";
43 constexpr const char* JSON_KEY_PATHREGEX = "pathRegex";
44 constexpr const char* JSON_KEY_UTD = "utd";
45 constexpr const char* JSON_KEY_MAXFILESUPPORTED = "maxFileSupported";
46 constexpr const char* JSON_KEY_LINKFEATURE =  "linkFeature";
47 constexpr const char* JSON_KEY_DOMAINVERIFY = "domainVerify";
48 constexpr const char* BUNDLE_MODULE_PROFILE_KEY_PATHREGX = "pathRegx";
49 constexpr const char* PARAM_SEPARATOR = "?";
50 constexpr const char* PORT_SEPARATOR = ":";
51 constexpr const char* SCHEME_SEPARATOR = "://";
52 constexpr const char* PATH_SEPARATOR = "/";
53 constexpr const char* TYPE_WILDCARD = "*/*";
54 const char WILDCARD = '*';
55 constexpr const char* TYPE_ONLY_MATCH_WILDCARD = "reserved/wildcard";
56 const char* LINK_FEATURE = "linkFeature";
57 const char* GENERAL_OBJECT = "general.object";
58 }; // namespace
59 
Match(const OHOS::AAFwk::Want &want) const60 bool Skill::Match(const OHOS::AAFwk::Want &want) const
61 {
62     std::string linkFeature = want.GetStringParam(LINK_FEATURE);
63     if (!linkFeature.empty()) {
64         size_t matchUriIndex = 0;
65         return MatchLinkFeature(linkFeature, want, matchUriIndex);
66     }
67 
68     if (!MatchLauncher(want)) {
69         APP_LOGD("Action or entities does not match");
70         return false;
71     }
72     std::vector<std::string> vecTypes = want.GetStringArrayParam(OHOS::AAFwk::Want::PARAM_ABILITY_URITYPES);
73     std::string uriString = want.GetUriString();
74     if (!vecTypes.empty()) {
75         for (std::string strType : vecTypes) {
76             if (MatchUriAndType(uriString, strType)) {
77                 APP_LOGD("type %{public}s, Is Matched", strType.c_str());
78                 return true;
79             }
80         }
81         return false;
82     }
83     bool matchUriAndType = MatchUriAndType(uriString, want.GetType());
84     if (!matchUriAndType) {
85         APP_LOGD("Uri or Type does not match");
86         return false;
87     }
88     return true;
89 }
90 
Match(const OHOS::AAFwk::Want &want, size_t &matchUriIndex) const91 bool Skill::Match(const OHOS::AAFwk::Want &want, size_t &matchUriIndex) const
92 {
93     std::string linkFeature = want.GetStringParam(LINK_FEATURE);
94     if (!linkFeature.empty()) {
95         return MatchLinkFeature(linkFeature, want, matchUriIndex);
96     }
97 
98     if (!MatchLauncher(want)) {
99         APP_LOGD("Action or entities does not match");
100         return false;
101     }
102 
103     std::vector<std::string> vecTypes = want.GetStringArrayParam(OHOS::AAFwk::Want::PARAM_ABILITY_URITYPES);
104     if (vecTypes.size() > 0) {
105         for (std::string strType : vecTypes) {
106             if (MatchUriAndType(want.GetUriString(), strType, matchUriIndex)) {
107                 APP_LOGD("type %{public}s, Is Matched", strType.c_str());
108                 return true;
109             }
110         }
111         return false;
112     }
113     bool matchUriAndType = MatchUriAndType(want.GetUriString(), want.GetType(), matchUriIndex);
114     if (!matchUriAndType) {
115         APP_LOGD("Uri or Type does not match");
116         return false;
117     }
118     return true;
119 }
120 
121 
MatchLauncher(const OHOS::AAFwk::Want &want) const122 bool Skill::MatchLauncher(const OHOS::AAFwk::Want &want) const
123 {
124     bool matchAction = MatchAction(want.GetAction());
125     if (!matchAction) {
126         APP_LOGD("Action does not match");
127         return false;
128     }
129     bool matchEntities = MatchEntities(want.GetEntities());
130     if (!matchEntities) {
131         APP_LOGD("Entities does not match");
132         return false;
133     }
134     return true;
135 }
136 
MatchAction(const std::string &action) const137 bool Skill::MatchAction(const std::string &action) const
138 {
139     // config actions empty, no match
140     if (actions.empty()) {
141         return false;
142     }
143     // config actions not empty, param empty, match
144     if (action.empty()) {
145         return true;
146     }
147     auto actionMatcher = [action] (const std::string &configAction) {
148         if (action == configAction) {
149             return true;
150         }
151         if (action == Constants::ACTION_HOME && configAction == Constants::WANT_ACTION_HOME) {
152             return true;
153         }
154         if (action == Constants::WANT_ACTION_HOME && configAction == Constants::ACTION_HOME) {
155             return true;
156         }
157         return false;
158     };
159     // config actions not empty, param not empty, if config actions contains param action, match
160     return std::find_if(actions.cbegin(), actions.cend(), actionMatcher) != actions.cend();
161 }
162 
MatchEntities(const std::vector<std::string> &paramEntities) const163 bool Skill::MatchEntities(const std::vector<std::string> &paramEntities) const
164 {
165     // param entities empty, match
166     if (paramEntities.empty()) {
167         return true;
168     }
169     // config entities empty, param entities not empty, not match
170     if (entities.empty()) {
171         return false;
172     }
173     // config entities not empty, param entities not empty, if every param entity in config entities, match
174     std::vector<std::string>::size_type size = paramEntities.size();
175     for (std::vector<std::string>::size_type i = 0; i < size; i++) {
176         bool ret = std::find(entities.cbegin(), entities.cend(), paramEntities[i]) == entities.cend();
177         if (ret) {
178             return false;
179         }
180     }
181     return true;
182 }
183 
MatchUriAndType(const std::string &rawUriString, const std::string &type) const184 bool Skill::MatchUriAndType(const std::string &rawUriString, const std::string &type) const
185 {
186     const std::string uriString = GetOptParamUri(rawUriString);
187     if (uriString.empty() && type.empty()) {
188         // case1 : param uri empty, param type empty
189         if (uris.empty()) {
190             return true;
191         }
192         for (const SkillUri &skillUri : uris) {
193             if (skillUri.scheme.empty() && skillUri.type.empty()) {
194                 return true;
195             }
196         }
197         return false;
198     }
199     if (uris.empty()) {
200         return false;
201     }
202     if (!uriString.empty() && type.empty()) {
203         // case2 : param uri not empty, param type empty
204         for (const SkillUri &skillUri : uris) {
205             if (MatchUri(uriString, skillUri) && skillUri.type.empty()) {
206                 return true;
207             }
208         }
209         // if uri is a file path, match type by the suffix
210         return MatchMimeType(uriString);
211     } else if (uriString.empty() && !type.empty()) {
212         // case3 : param uri empty, param type not empty
213         for (const SkillUri &skillUri : uris) {
214             if (skillUri.scheme.empty() && MatchType(type, skillUri.type)) {
215                 return true;
216             }
217         }
218         return false;
219     } else {
220         // case4 : param uri not empty, param type not empty
221         for (const SkillUri &skillUri : uris) {
222             if (MatchUri(uriString, skillUri) && MatchType(type, skillUri.type)) {
223                 return true;
224             }
225         }
226         return false;
227     }
228 }
229 
MatchLinkFeature(const std::string &linkFeature, const OHOS::AAFwk::Want &want, size_t &matchUriIndex) const230 bool Skill::MatchLinkFeature(const std::string &linkFeature, const OHOS::AAFwk::Want &want, size_t &matchUriIndex) const
231 {
232     std::string paramUriString = GetOptParamUri(want.GetUriString());
233     std::string paramType = want.GetType();
234     // only linkFeature
235     if (paramUriString.empty() && paramType.empty()) {
236         for (size_t uriIndex = 0; uriIndex < uris.size(); ++uriIndex) {
237             const SkillUri &skillUri = uris[uriIndex];
238             if (linkFeature == skillUri.linkFeature) {
239                 matchUriIndex = uriIndex;
240                 return true;
241             }
242         }
243         return false;
244     }
245     // linkFeature + uri + type
246     bool onlyUri = !paramUriString.empty() && paramType.empty();
247     for (size_t uriIndex = 0; uriIndex < uris.size(); ++uriIndex) {
248         const SkillUri &skillUri = uris[uriIndex];
249         if (linkFeature != skillUri.linkFeature) {
250             continue;
251         }
252         if (MatchUri(paramUriString, skillUri) && MatchType(paramType, skillUri.type)) {
253             matchUriIndex = uriIndex;
254             return true;
255         }
256         if (!onlyUri) {
257             continue;
258         }
259         std::vector<std::string> paramUtdVector;
260         if (!MimeTypeMgr::GetUtdVectorByUri(paramUriString, paramUtdVector)) {
261             continue;
262         }
263         for (const std::string &paramUtd : paramUtdVector) {
264             if ((MatchUri(paramUriString, skillUri) ||
265                 (skillUri.scheme.empty() && paramUriString.find(SCHEME_SEPARATOR) == std::string::npos)) &&
266                 MatchType(paramUtd, skillUri.type)) {
267                 matchUriIndex = uriIndex;
268                 return true;
269             }
270         }
271     }
272     return false;
273 }
274 
MatchUriAndType(const std::string &rawUriString, const std::string &type, size_t &matchUriIndex) const275 bool Skill::MatchUriAndType(const std::string &rawUriString, const std::string &type, size_t &matchUriIndex) const
276 {
277     const std::string uriString = GetOptParamUri(rawUriString);
278     if (uriString.empty() && type.empty()) {
279         // case1 : param uri empty, param type empty
280         if (uris.empty()) {
281             return true;
282         }
283         for (size_t uriIndex = 0; uriIndex < uris.size(); ++uriIndex) {
284             const SkillUri &skillUri = uris[uriIndex];
285             if (skillUri.scheme.empty() && skillUri.type.empty()) {
286                 matchUriIndex = uriIndex;
287                 return true;
288             }
289         }
290         return false;
291     }
292     if (uris.empty()) {
293         return false;
294     }
295     if (!uriString.empty() && type.empty()) {
296         // case2 : param uri not empty, param type empty
297         for (size_t uriIndex = 0; uriIndex < uris.size(); ++uriIndex) {
298             const SkillUri &skillUri = uris[uriIndex];
299             if (MatchUri(uriString, skillUri) && skillUri.type.empty()) {
300                 matchUriIndex = uriIndex;
301                 return true;
302             }
303         }
304         // if uri is a file path, match type by the suffix
305         return MatchMimeType(uriString, matchUriIndex);
306     } else if (uriString.empty() && !type.empty()) {
307         // case3 : param uri empty, param type not empty
308         for (size_t uriIndex = 0; uriIndex < uris.size(); ++uriIndex) {
309             const SkillUri &skillUri = uris[uriIndex];
310             if (skillUri.scheme.empty() && MatchType(type, skillUri.type)) {
311                 matchUriIndex = uriIndex;
312                 return true;
313             }
314         }
315         return false;
316     } else {
317         // case4 : param uri not empty, param type not empty
318         for (size_t uriIndex = 0; uriIndex < uris.size(); ++uriIndex) {
319             const SkillUri &skillUri = uris[uriIndex];
320             if (MatchUri(uriString, skillUri) && MatchType(type, skillUri.type)) {
321                 matchUriIndex = uriIndex;
322                 return true;
323             }
324         }
325         return false;
326     }
327 }
328 
StartsWith(const std::string &sourceString, const std::string &targetPrefix) const329 bool Skill::StartsWith(const std::string &sourceString, const std::string &targetPrefix) const
330 {
331     return sourceString.rfind(targetPrefix, 0) == 0;
332 }
333 
GetOptParamUri(const std::string &uriString)334 std::string Skill::GetOptParamUri(const std::string &uriString)
335 {
336     std::size_t pos = uriString.find(PARAM_SEPARATOR);
337     if (pos == std::string::npos) {
338         return uriString;
339     }
340     return uriString.substr(0, pos);
341 }
342 
MatchUri(const std::string &uriString, const SkillUri &skillUri) const343 bool Skill::MatchUri(const std::string &uriString, const SkillUri &skillUri) const
344 {
345     if (uriString.empty() && skillUri.scheme.empty()) {
346         return true;
347     }
348     if (uriString.empty() || skillUri.scheme.empty()) {
349         return false;
350     }
351     if (skillUri.host.empty()) {
352         // config uri is : scheme
353         // belows are param uri matched conditions:
354         // 1.scheme
355         // 2.scheme:
356         // 3.scheme:/
357         // 4.scheme://
358         return uriString == skillUri.scheme || StartsWith(uriString, skillUri.scheme + PORT_SEPARATOR);
359     }
360     std::string optParamUri = GetOptParamUri(uriString);
361     std::string skillUriString;
362     skillUriString.append(skillUri.scheme).append(SCHEME_SEPARATOR).append(skillUri.host);
363     if (!skillUri.port.empty()) {
364         skillUriString.append(PORT_SEPARATOR).append(skillUri.port);
365     }
366     if (skillUri.path.empty() && skillUri.pathStartWith.empty() && skillUri.pathRegex.empty()) {
367         // with port, config uri is : scheme://host:port
368         // belows are param uri matched conditions:
369         // 1.scheme://host:port
370         // 2.scheme://host:port/path
371 
372         // without port, config uri is : scheme://host
373         // belows are param uri matched conditions:
374         // 1.scheme://host
375         // 2.scheme://host/path
376         // 3.scheme://host:port     scheme://host:port/path
377         bool ret = (optParamUri == skillUriString || StartsWith(optParamUri, skillUriString + PATH_SEPARATOR));
378         if (skillUri.port.empty()) {
379             ret = ret || StartsWith(optParamUri, skillUriString + PORT_SEPARATOR);
380         }
381         return ret;
382     }
383     skillUriString.append(PATH_SEPARATOR);
384     // if one of path, pathStartWith, pathRegex match, then match
385     if (!skillUri.path.empty()) {
386         // path match
387         std::string pathUri(skillUriString);
388         pathUri.append(skillUri.path);
389         if (optParamUri == pathUri) {
390             return true;
391         }
392     }
393     if (!skillUri.pathStartWith.empty()) {
394         // pathStartWith match
395         std::string pathStartWithUri(skillUriString);
396         pathStartWithUri.append(skillUri.pathStartWith);
397         if (StartsWith(optParamUri, pathStartWithUri)) {
398             return true;
399         }
400     }
401     if (!skillUri.pathRegex.empty()) {
402         // pathRegex match
403         std::string pathRegexUri(skillUriString);
404         pathRegexUri.append(skillUri.pathRegex);
405         try {
406             std::regex regex(pathRegexUri);
407             if (regex_match(optParamUri, regex)) {
408                 return true;
409             }
410         } catch (const std::regex_error& e) {
411             APP_LOGE("regex error");
412         }
413     }
414     return false;
415 }
416 
MatchType(const std::string &type, const std::string &skillUriType) const417 bool Skill::MatchType(const std::string &type, const std::string &skillUriType) const
418 {
419     if (type.empty() && skillUriType.empty()) {
420         return true;
421     }
422     if (type.empty() || skillUriType.empty()) {
423         return false;
424     }
425 
426     // only match */* or general.object
427     if (type == TYPE_ONLY_MATCH_WILDCARD) {
428         return skillUriType == TYPE_WILDCARD || skillUriType == GENERAL_OBJECT;
429     }
430 
431     bool containsUtd = false;
432     bool matchUtdRet = MatchUtd(type, skillUriType, containsUtd);
433     if (containsUtd) {
434         return matchUtdRet;
435     }
436 
437     if (type == TYPE_WILDCARD || skillUriType == TYPE_WILDCARD) {
438         // param is */* or config is */*
439         return true;
440     }
441     bool paramTypeRegex = type.back() == WILDCARD;
442     if (paramTypeRegex) {
443         // param is string/*
444         std::string prefix = type.substr(0, type.length() - 1);
445         return skillUriType.find(prefix) == 0;
446     }
447     bool typeRegex = skillUriType.back() == WILDCARD;
448     if (typeRegex) {
449         // config is string/*
450         std::string prefix = skillUriType.substr(0, skillUriType.length() - 1);
451         return type.find(prefix) == 0;
452     } else {
453         return type == skillUriType;
454     }
455 }
456 
MatchUtd(const std::string &paramType, const std::string &skillUriType, bool &containsUtd) const457 bool Skill::MatchUtd(const std::string &paramType, const std::string &skillUriType, bool &containsUtd) const
458 {
459 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED
460     bool isParamUtd = IsUtd(paramType);
461     bool isSkillUtd = IsUtd(skillUriType);
462 
463     containsUtd = isParamUtd || isSkillUtd;
464 
465     if (!isParamUtd && !isSkillUtd) {
466         // 1.param : mimeType, skill : mimeType
467         return false;
468     } else if (isParamUtd && isSkillUtd) {
469         // 2.param : utd, skill : utd
470         return IsUtdMatch(paramType, skillUriType);
471     } else if (!isParamUtd && isSkillUtd) {
472         // 3.param : mimeType, skill : utd
473         std::vector<std::string> paramUtdVector;
474         auto ret = UDMF::UtdClient::GetInstance().GetUniformDataTypesByMIMEType(paramType, paramUtdVector);
475         if (ret != ERR_OK || paramUtdVector.empty()) {
476             return false;
477         }
478         for (const std::string &paramUtd : paramUtdVector) {
479             if (IsUtdMatch(paramUtd, skillUriType)) {
480                 return true;
481             }
482         }
483         return false;
484     } else {
485         // 4.param : utd, skill : mimeType
486         std::vector<std::string> skillUtdVector;
487         auto ret = UDMF::UtdClient::GetInstance().GetUniformDataTypesByMIMEType(skillUriType, skillUtdVector);
488         if (ret != ERR_OK || skillUtdVector.empty()) {
489             return false;
490         }
491         for (const std::string &skillUtd : skillUtdVector) {
492             if (IsUtdMatch(paramType, skillUtd)) {
493                 return true;
494             }
495         }
496         return false;
497     }
498 #else
499     containsUtd = false;
500     return false;
501 #endif
502 }
503 
IsUtdMatch(const std::string &paramUtd, const std::string &skillUtd) const504 bool Skill::IsUtdMatch(const std::string &paramUtd, const std::string &skillUtd) const
505 {
506 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED
507     std::shared_ptr<UDMF::TypeDescriptor> paramTypeDescriptor;
508     auto ret = UDMF::UtdClient::GetInstance().GetTypeDescriptor(paramUtd, paramTypeDescriptor);
509     if (ret != ERR_OK || paramTypeDescriptor == nullptr) {
510         return false;
511     }
512     bool isMatch = false;
513     ret = paramTypeDescriptor->BelongsTo(skillUtd, isMatch);
514     if (ret != ERR_OK) {
515         return false;
516     }
517     return isMatch;
518 #else
519     return false;
520 #endif
521 }
522 
IsUtd(const std::string &param) const523 bool Skill::IsUtd(const std::string &param) const
524 {
525 #ifdef BUNDLE_FRAMEWORK_UDMF_ENABLED
526     bool isUtd = false;
527     auto ret = UDMF::UtdClient::GetInstance().IsUtd(param, isUtd);
528     return ret == ERR_OK && isUtd;
529 #else
530     return false;
531 #endif
532 }
533 
MatchMimeType(const std::string & uriString) const534 bool Skill::MatchMimeType(const std::string & uriString) const
535 {
536     std::vector<std::string> paramUtdVector;
537     if (!MimeTypeMgr::GetUtdVectorByUri(uriString, paramUtdVector)) {
538         return false;
539     }
540     for (const SkillUri &skillUri : uris) {
541         for (const std::string &paramUtd : paramUtdVector) {
542             if ((MatchUri(uriString, skillUri) ||
543                 (skillUri.scheme.empty() && uriString.find(SCHEME_SEPARATOR) == std::string::npos)) &&
544                 MatchType(paramUtd, skillUri.type)) {
545                 return true;
546             }
547         }
548     }
549     return false;
550 }
551 
552 
MatchMimeType(const std::string & uriString, size_t &matchUriIndex) const553 bool Skill::MatchMimeType(const std::string & uriString, size_t &matchUriIndex) const
554 {
555     std::vector<std::string> paramUtdVector;
556     if (!MimeTypeMgr::GetUtdVectorByUri(uriString, paramUtdVector)) {
557         return false;
558     }
559     for (size_t uriIndex = 0; uriIndex < uris.size(); ++uriIndex) {
560         const SkillUri &skillUri = uris[uriIndex];
561         for (const std::string &paramUtd : paramUtdVector) {
562             if ((MatchUri(uriString, skillUri) ||
563                 (skillUri.scheme.empty() && uriString.find(SCHEME_SEPARATOR) == std::string::npos)) &&
564                 MatchType(paramUtd, skillUri.type)) {
565                 matchUriIndex = uriIndex;
566                 return true;
567             }
568         }
569     }
570     return false;
571 }
572 
ReadFromParcel(Parcel &parcel)573 bool Skill::ReadFromParcel(Parcel &parcel)
574 {
575     int32_t actionsSize;
576     READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, actionsSize);
577     CONTAINER_SECURITY_VERIFY(parcel, actionsSize, &actions);
578     for (auto i = 0; i < actionsSize; i++) {
579         actions.emplace_back(Str16ToStr8(parcel.ReadString16()));
580     }
581 
582     int32_t entitiesSize;
583     READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, entitiesSize);
584     CONTAINER_SECURITY_VERIFY(parcel, entitiesSize, &entities);
585     for (auto i = 0; i < entitiesSize; i++) {
586         entities.emplace_back(Str16ToStr8(parcel.ReadString16()));
587     }
588 
589     int32_t urisSize;
590     READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, urisSize);
591     CONTAINER_SECURITY_VERIFY(parcel, urisSize, &uris);
592     for (auto i = 0; i < urisSize; i++) {
593         SkillUri uri;
594         uri.scheme = Str16ToStr8(parcel.ReadString16());
595         uri.host = Str16ToStr8(parcel.ReadString16());
596         uri.port = Str16ToStr8(parcel.ReadString16());
597         uri.path = Str16ToStr8(parcel.ReadString16());
598         uri.pathStartWith = Str16ToStr8(parcel.ReadString16());
599         uri.pathRegex = Str16ToStr8(parcel.ReadString16());
600         uri.type = Str16ToStr8(parcel.ReadString16());
601         uri.utd = Str16ToStr8(parcel.ReadString16());
602         uri.maxFileSupported = parcel.ReadInt32();
603         uri.linkFeature = Str16ToStr8(parcel.ReadString16());
604         uris.emplace_back(uri);
605     }
606 
607     int32_t permissionsSize;
608     READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, permissionsSize);
609     CONTAINER_SECURITY_VERIFY(parcel, permissionsSize, &permissions);
610     for (auto i = 0; i < permissionsSize; i++) {
611         permissions.emplace_back(Str16ToStr8(parcel.ReadString16()));
612     }
613     domainVerify = parcel.ReadBool();
614     return true;
615 }
616 
Unmarshalling(Parcel &parcel)617 Skill *Skill::Unmarshalling(Parcel &parcel)
618 {
619     Skill *skill = new (std::nothrow) Skill();
620     if (skill && !skill->ReadFromParcel(parcel)) {
621         APP_LOGW("read from parcel failed");
622         delete skill;
623         skill = nullptr;
624     }
625     return skill;
626 }
627 
Marshalling(Parcel &parcel) const628 bool Skill::Marshalling(Parcel &parcel) const
629 {
630     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, actions.size());
631     for (auto &action : actions) {
632         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(action));
633     }
634 
635     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, entities.size());
636     for (auto &entitiy : entities) {
637         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(entitiy));
638     }
639 
640     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, uris.size());
641     for (auto &uri : uris) {
642         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(uri.scheme));
643         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(uri.host));
644         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(uri.port));
645         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(uri.path));
646         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(uri.pathStartWith));
647         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(uri.pathRegex));
648         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(uri.type));
649         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(uri.utd));
650         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, uri.maxFileSupported);
651         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(uri.linkFeature));
652     }
653     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, permissions.size());
654     for (auto &permission : permissions) {
655         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(permission));
656     }
657     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Bool, parcel, domainVerify);
658     return true;
659 }
660 
Dump(std::string prefix, int fd)661 void Skill::Dump(std::string prefix, int fd)
662 {
663     APP_LOGI("called dump Skill");
664     if (fd < 0) {
665         APP_LOGE("dump Skill fd error");
666         return;
667     }
668     int flags = fcntl(fd, F_GETFL);
669     if (flags < 0) {
670         APP_LOGE("dump Skill fcntl error : %{public}d", errno);
671         return;
672     }
673     uint uflags = static_cast<uint>(flags);
674     uflags &= O_ACCMODE;
675     if ((uflags == O_WRONLY) || (uflags == O_RDWR)) {
676         nlohmann::json jsonObject = *this;
677         std::string result;
678         result.append(prefix);
679         result.append(jsonObject.dump(Constants::DUMP_INDENT));
680         int ret = TEMP_FAILURE_RETRY(write(fd, result.c_str(), result.size()));
681         if (ret < 0) {
682             APP_LOGE("dump Abilityinfo write error : %{public}d", errno);
683         }
684     }
685     return;
686 }
687 
from_json(const nlohmann::json &jsonObject, SkillUri &uri)688 void from_json(const nlohmann::json &jsonObject, SkillUri &uri)
689 {
690     const auto &jsonObjectEnd = jsonObject.end();
691     int32_t parseResult = ERR_OK;
692     BMSJsonUtil::GetStrValueIfFindKey(jsonObject, jsonObjectEnd, JSON_KEY_SCHEME,
693     uri.scheme, false, parseResult);
694     BMSJsonUtil::GetStrValueIfFindKey(jsonObject, jsonObjectEnd, JSON_KEY_HOST,
695         uri.host, false, parseResult);
696     BMSJsonUtil::GetStrValueIfFindKey(jsonObject, jsonObjectEnd, JSON_KEY_PORT,
697         uri.port, false, parseResult);
698     BMSJsonUtil::GetStrValueIfFindKey(jsonObject, jsonObjectEnd, JSON_KEY_PATH,
699         uri.path, false, parseResult);
700     BMSJsonUtil::GetStrValueIfFindKey(jsonObject, jsonObjectEnd, JSON_KEY_PATHSTARTWITH,
701         uri.pathStartWith, false, parseResult);
702     BMSJsonUtil::GetStrValueIfFindKey(jsonObject, jsonObjectEnd, BUNDLE_MODULE_PROFILE_KEY_PATHREGX,
703         uri.pathRegex, false, parseResult);
704     BMSJsonUtil::GetStrValueIfFindKey(jsonObject, jsonObjectEnd, JSON_KEY_PATHREGEX,
705         uri.pathRegex, false, parseResult);
706     BMSJsonUtil::GetStrValueIfFindKey(jsonObject, jsonObjectEnd, JSON_KEY_TYPE,
707         uri.type, false, parseResult);
708     BMSJsonUtil::GetStrValueIfFindKey(jsonObject, jsonObjectEnd, JSON_KEY_UTD,
709         uri.utd, false, parseResult);
710     GetValueIfFindKey<int32_t>(jsonObject, jsonObjectEnd, JSON_KEY_MAXFILESUPPORTED,
711         uri.maxFileSupported, JsonType::NUMBER, false, parseResult, ArrayType::NOT_ARRAY);
712     BMSJsonUtil::GetStrValueIfFindKey(jsonObject, jsonObjectEnd, JSON_KEY_LINKFEATURE,
713         uri.linkFeature, false, parseResult);
714 }
715 
from_json(const nlohmann::json &jsonObject, Skill &skill)716 void from_json(const nlohmann::json &jsonObject, Skill &skill)
717 {
718     const auto &jsonObjectEnd = jsonObject.end();
719     int32_t parseResult = ERR_OK;
720     GetValueIfFindKey<std::vector<std::string>>(jsonObject,
721         jsonObjectEnd,
722         JSON_KEY_ACTIONS,
723         skill.actions,
724         JsonType::ARRAY,
725         false,
726         parseResult,
727         ArrayType::STRING);
728     GetValueIfFindKey<std::vector<std::string>>(jsonObject,
729         jsonObjectEnd,
730         JSON_KEY_ENTITIES,
731         skill.entities,
732         JsonType::ARRAY,
733         false,
734         parseResult,
735         ArrayType::STRING);
736     GetValueIfFindKey<std::vector<SkillUri>>(jsonObject,
737         jsonObjectEnd,
738         JSON_KEY_URIS,
739         skill.uris,
740         JsonType::ARRAY,
741         false,
742         parseResult,
743         ArrayType::OBJECT);
744     GetValueIfFindKey<std::vector<std::string>>(jsonObject,
745         jsonObjectEnd,
746         JSON_KEY_PERMISSIONS,
747         skill.permissions,
748         JsonType::ARRAY,
749         false,
750         parseResult,
751         ArrayType::STRING);
752     BMSJsonUtil::GetBoolValueIfFindKey(jsonObject,
753         jsonObjectEnd,
754         JSON_KEY_DOMAINVERIFY,
755         skill.domainVerify,
756         false,
757         parseResult);
758 }
759 
to_json(nlohmann::json &jsonObject, const SkillUri &uri)760 void to_json(nlohmann::json &jsonObject, const SkillUri &uri)
761 {
762     jsonObject = nlohmann::json {
763         {JSON_KEY_SCHEME, uri.scheme},
764         {JSON_KEY_HOST, uri.host},
765         {JSON_KEY_PORT, uri.port},
766         {JSON_KEY_PATH, uri.path},
767         {JSON_KEY_PATHSTARTWITH,  uri.pathStartWith},
768         {JSON_KEY_PATHREGEX, uri.pathRegex},
769         {JSON_KEY_TYPE, uri.type},
770         {JSON_KEY_UTD, uri.utd},
771         {JSON_KEY_MAXFILESUPPORTED, uri.maxFileSupported},
772         {JSON_KEY_LINKFEATURE, uri.linkFeature},
773     };
774 }
775 
to_json(nlohmann::json &jsonObject, const Skill &skill)776 void to_json(nlohmann::json &jsonObject, const Skill &skill)
777 {
778     jsonObject = nlohmann::json {
779         {JSON_KEY_ACTIONS, skill.actions},
780         {JSON_KEY_ENTITIES, skill.entities},
781         {JSON_KEY_URIS, skill.uris},
782         {JSON_KEY_PERMISSIONS, skill.permissions},
783         {JSON_KEY_DOMAINVERIFY, skill.domainVerify}
784     };
785 }
786 }  // namespace AppExecFwk
787 }  // namespace OHOS
788