1 /*
2  * Copyright (c) 2021-2022 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 "skills.h"
17 using namespace OHOS;
18 using namespace OHOS::AppExecFwk;
19 namespace OHOS {
20 namespace AAFwk {
21 namespace {
22 const size_t LENGTH_FOR_FINDMINETYPE = 3;
23 constexpr int CYCLE_LIMIT = 1000;
24 }
25 /**
26  * @brief Default constructor used to create a Skills instance.
27  */
Skills()28 Skills::Skills()
29 {}
30 
31 /**
32  * @brief A parameterized constructor used to create a Skills instance.
33  *
34  * @param skills Indicates skills used to create a Skills instance.
35  */
Skills(const Skills & skills)36 Skills::Skills(const Skills &skills)
37 {
38     // entities_
39     entities_ = skills.entities_;
40     // actions_
41     actions_ = skills.actions_;
42     // authorities_
43     authorities_ = skills.authorities_;
44     // schemes_
45     schemes_ = skills.schemes_;
46 
47     // paths_
48     paths_ = skills.paths_;
49     // schemeSpecificParts_
50     schemeSpecificParts_ = skills.schemeSpecificParts_;
51     // types_
52     types_ = skills.types_;
53 }
54 
~Skills()55 Skills::~Skills()
56 {
57     entities_.clear();
58     actions_.clear();
59     authorities_.clear();
60     schemes_.clear();
61 
62     paths_.clear();
63     schemeSpecificParts_.clear();
64     types_.clear();
65 }
66 
67 /**
68  * @brief Obtains the list of entities.
69  *
70  * @return vector of Entities.
71  */
GetEntities() const72 std::vector<std::string> Skills::GetEntities() const
73 {
74     return entities_;
75 }
76 
77 /**
78  * @brief Obtains the specified entity.
79  *
80  * @param entity Id of the specified entity.
81  */
GetEntity(int index) const82 std::string Skills::GetEntity(int index) const
83 {
84     if (index < 0 || entities_.empty() || std::size_t(index) >= entities_.size()) {
85         return std::string();
86     }
87     return entities_.at(index);
88 }
89 
90 /**
91  * @brief Adds an entity to this Skills object.
92  *
93  * @param entity Indicates the entity to add.
94  */
AddEntity(const std::string & entity)95 void Skills::AddEntity(const std::string &entity)
96 {
97     auto it = std::find(entities_.begin(), entities_.end(), entity);
98     if (it == entities_.end()) {
99         entities_.emplace_back(entity);
100     }
101 }
102 
103 /**
104  * @brief Checks whether the specified entity is exist.
105  *
106  * @param entity Name of the specified entity.
107  */
HasEntity(const std::string & entity)108 bool Skills::HasEntity(const std::string &entity)
109 {
110     return std::find(entities_.begin(), entities_.end(), entity) != entities_.end();
111 }
112 
113 /**
114  * @brief Remove the specified entity.
115  *
116  * @param entity Name of the specified entity.
117  */
RemoveEntity(const std::string & entity)118 void Skills::RemoveEntity(const std::string &entity)
119 {
120     if (!entities_.empty()) {
121         auto it = std::find(entities_.begin(), entities_.end(), entity);
122         if (it != entities_.end()) {
123             entities_.erase(it);
124         }
125     }
126 }
127 
128 /**
129  * @brief Obtains the count of entities.
130  *
131  */
CountEntities() const132 int Skills::CountEntities() const
133 {
134     return entities_.empty() ? 0 : entities_.size();
135 }
136 
137 /**
138  * @brief Obtains the specified action.
139  *
140  * @param actionId Id of the specified action.
141  */
GetAction(int index) const142 std::string Skills::GetAction(int index) const
143 {
144     if (index < 0 || actions_.empty() || std::size_t(index) >= actions_.size()) {
145         return std::string();
146     } else {
147         return actions_.at(index);
148     }
149 }
150 
151 /**
152  * @brief Adds an action to this Skills object.
153  *
154  * @param action Indicates the action to add.
155  */
AddAction(const std::string & action)156 void Skills::AddAction(const std::string &action)
157 {
158     auto it = std::find(actions_.begin(), actions_.end(), action);
159     if (it == actions_.end()) {
160         actions_.emplace_back(action);
161     }
162 }
163 
164 /**
165  * @brief Checks whether the specified action is exist.
166  *
167  * @param action Name of the specified action.
168  */
HasAction(const std::string & action)169 bool Skills::HasAction(const std::string &action)
170 {
171     return std::find(actions_.begin(), actions_.end(), action) != actions_.end();
172 }
173 
174 /**
175  * @brief Remove the specified action.
176  *
177  * @param action Name of the specified action.
178  */
RemoveAction(const std::string & action)179 void Skills::RemoveAction(const std::string &action)
180 {
181     if (!actions_.empty()) {
182         auto it = std::find(actions_.begin(), actions_.end(), action);
183         if (it != actions_.end()) {
184             actions_.erase(it);
185         }
186     }
187 }
188 
189 /**
190  * @brief Obtains the count of actions.
191  *
192  */
CountActions() const193 int Skills::CountActions() const
194 {
195     return actions_.empty() ? 0 : actions_.size();
196 }
197 
198 /**
199  * @brief Obtains the iterator of Actions.
200  *
201  * @return iterator of Actions.
202  */
ActionsIterator()203 std::vector<std::string>::iterator Skills::ActionsIterator()
204 {
205     return actions_.begin();
206 }
207 
208 /**
209  * @brief Obtains the specified authority.
210  *
211  * @param authorityId Id of the specified authority.
212  */
GetAuthority(int index) const213 std::string Skills::GetAuthority(int index) const
214 {
215     if (index < 0 || authorities_.empty() || std::size_t(index) >= authorities_.size()) {
216         return std::string();
217     } else {
218         return authorities_.at(index);
219     }
220 }
221 
222 /**
223  * @brief Adds an authority to this Skills object.
224  *
225  * @param authority Indicates the authority to add.
226  */
AddAuthority(const std::string & authority)227 void Skills::AddAuthority(const std::string &authority)
228 {
229     auto it = std::find(authorities_.begin(), authorities_.end(), authority);
230     if (it == authorities_.end()) {
231         authorities_.emplace_back(authority);
232     }
233 }
234 
235 /**
236  * @brief Checks whether the specified authority is exist.
237  *
238  * @param action Name of the specified authority.
239  */
HasAuthority(const std::string & authority)240 bool Skills::HasAuthority(const std::string &authority)
241 {
242     return std::find(authorities_.begin(), authorities_.end(), authority) != authorities_.end();
243 }
244 
245 /**
246  * @brief Remove the specified authority.
247  *
248  * @param authority Name of the specified authority.
249  */
RemoveAuthority(const std::string & authority)250 void Skills::RemoveAuthority(const std::string &authority)
251 {
252     if (!authorities_.empty()) {
253         auto it = std::find(authorities_.begin(), authorities_.end(), authority);
254         if (it != authorities_.end()) {
255             authorities_.erase(it);
256         }
257     }
258 }
259 
260 /**
261  * @brief Obtains the count of authorities.
262  *
263  */
CountAuthorities() const264 int Skills::CountAuthorities() const
265 {
266     return authorities_.empty() ? 0 : authorities_.size();
267 }
268 
269 /**
270  * @brief Obtains the specified path.
271  *
272  * @param pathId Id of the specified path.
273  */
GetPath(int index) const274 std::string Skills::GetPath(int index) const
275 {
276     if (index < 0 || paths_.empty() || std::size_t(index) >= paths_.size()) {
277         return std::string();
278     }
279     return paths_.at(index).GetPattern();
280 }
281 
282 /**
283  * @brief Adds a path to this Skills object.
284  *
285  * @param path Indicates the path to add.
286  */
AddPath(const std::string & path)287 void Skills::AddPath(const std::string &path)
288 {
289     PatternsMatcher pm(path, MatchType::DEFAULT);
290     AddPath(pm);
291 }
292 
293 /**
294  * @brief Adds a path to this Skills object.
295  *
296  * @param path Indicates the path to add.
297  */
AddPath(const PatternsMatcher & patternsMatcher)298 void Skills::AddPath(const PatternsMatcher &patternsMatcher)
299 {
300     auto hasPath = std::find_if(paths_.begin(), paths_.end(), [&patternsMatcher](const PatternsMatcher pm) {
301         return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType());
302     });
303     if (hasPath == paths_.end()) {
304         paths_.emplace_back(patternsMatcher);
305     }
306 }
307 
308 /**
309  * @brief Adds a path to this Skills object.
310  *
311  * @param path Indicates the path to add.
312  * @param matchType the specified match type.
313  */
AddPath(const std::string & path,const MatchType & matchType)314 void Skills::AddPath(const std::string &path, const MatchType &matchType)
315 {
316     PatternsMatcher pm(path, matchType);
317     AddPath(pm);
318 }
319 
320 /**
321  * @brief Checks whether the specified path is exist.
322  *
323  * @param path Name of the specified path.
324  */
HasPath(const std::string & path)325 bool Skills::HasPath(const std::string &path)
326 {
327     auto hasPath = std::find_if(
328         paths_.begin(), paths_.end(), [&path](const PatternsMatcher pm) { return pm.GetPattern() == path; });
329     return hasPath != paths_.end();
330 }
331 
332 /**
333  * @brief Remove the specified path.
334  *
335  * @param path Name of the specified path.
336  */
RemovePath(const std::string & path)337 void Skills::RemovePath(const std::string &path)
338 {
339     auto hasPath = std::find_if(
340         paths_.begin(), paths_.end(), [&path](const PatternsMatcher pm) { return pm.GetPattern() == path; });
341     if (hasPath != paths_.end()) {
342         paths_.erase(hasPath);
343     }
344 }
345 
346 /**
347  * @brief Remove the specified path.
348  *
349  * @param path The path to be added.
350  */
RemovePath(const PatternsMatcher & patternsMatcher)351 void Skills::RemovePath(const PatternsMatcher &patternsMatcher)
352 {
353     auto hasPath = std::find_if(paths_.begin(), paths_.end(), [&patternsMatcher](const PatternsMatcher pm) {
354         return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType());
355     });
356     if (hasPath != paths_.end()) {
357         paths_.erase(hasPath);
358     }
359 }
360 
361 /**
362  * @brief Remove the specified path.
363  *
364  * @param path Name of the specified path.
365  * @param matchType the specified match type.
366  */
RemovePath(const std::string & path,const MatchType & matchType)367 void Skills::RemovePath(const std::string &path, const MatchType &matchType)
368 {
369     PatternsMatcher pm(path, matchType);
370     RemovePath(pm);
371 }
372 
373 /**
374  * @brief Obtains the count of paths.
375  *
376  */
CountPaths() const377 int Skills::CountPaths() const
378 {
379     return paths_.empty() ? 0 : paths_.size();
380 }
381 
382 /**
383  * @brief Obtains the specified scheme.
384  *
385  * @param schemeId Id of the specified scheme.
386  */
GetScheme(int index) const387 std::string Skills::GetScheme(int index) const
388 {
389     if (index < 0 || schemes_.empty() || std::size_t(index) >= schemes_.size()) {
390         return std::string();
391     }
392     return schemes_.at(index);
393 }
394 
395 /**
396  * @brief Adds an scheme to this Skills object.
397  *
398  * @param scheme Indicates the scheme to add.
399  */
AddScheme(const std::string & scheme)400 void Skills::AddScheme(const std::string &scheme)
401 {
402     auto it = std::find(schemes_.begin(), schemes_.end(), scheme);
403     if (it == schemes_.end()) {
404         schemes_.emplace_back(scheme);
405     }
406 }
407 
408 /**
409  * @brief Checks whether the specified scheme is exist.
410  *
411  * @param scheme Name of the specified scheme.
412  */
HasScheme(const std::string & scheme)413 bool Skills::HasScheme(const std::string &scheme)
414 {
415     return std::find(schemes_.begin(), schemes_.end(), scheme) != schemes_.end();
416 }
417 
418 /**
419  * @brief Remove the specified scheme.
420  *
421  * @param scheme Name of the specified scheme.
422  */
RemoveScheme(const std::string & scheme)423 void Skills::RemoveScheme(const std::string &scheme)
424 {
425     if (!schemes_.empty()) {
426         auto it = std::find(schemes_.begin(), schemes_.end(), scheme);
427         if (it != schemes_.end()) {
428             schemes_.erase(it);
429         }
430     }
431 }
432 
433 /**
434  * @brief Obtains the count of schemes.
435  *
436  */
CountSchemes() const437 int Skills::CountSchemes() const
438 {
439     return schemes_.empty() ? 0 : schemes_.size();
440 }
441 
442 /**
443  * @brief Obtains the specified scheme part.
444  *
445  * @param schemeId Id of the specified scheme part.
446  */
GetSchemeSpecificPart(int index) const447 std::string Skills::GetSchemeSpecificPart(int index) const
448 {
449     if (index < 0 || schemeSpecificParts_.empty() || std::size_t(index) >= schemeSpecificParts_.size()) {
450         return std::string();
451     }
452     return schemeSpecificParts_.at(index).GetPattern();
453 }
454 
455 /**
456  * @brief Adds an scheme to this Skills object.
457  *
458  * @param scheme Indicates the scheme to add.
459  */
AddSchemeSpecificPart(const std::string & schemeSpecificPart)460 void Skills::AddSchemeSpecificPart(const std::string &schemeSpecificPart)
461 {
462     PatternsMatcher patternsMatcher(schemeSpecificPart, MatchType::DEFAULT);
463     auto it = std::find_if(
464         schemeSpecificParts_.begin(), schemeSpecificParts_.end(), [&patternsMatcher](const PatternsMatcher pm) {
465             return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType());
466         });
467     if (it == schemeSpecificParts_.end()) {
468         schemeSpecificParts_.emplace_back(patternsMatcher);
469     }
470 }
471 
472 /**
473  * @brief Checks whether the specified scheme part is exist.
474  *
475  * @param scheme Name of the specified scheme part.
476  */
HasSchemeSpecificPart(const std::string & schemeSpecificPart)477 bool Skills::HasSchemeSpecificPart(const std::string &schemeSpecificPart)
478 {
479     auto it = std::find_if(schemeSpecificParts_.begin(),
480         schemeSpecificParts_.end(),
481         [&schemeSpecificPart](const PatternsMatcher pm) { return pm.GetPattern() == schemeSpecificPart; });
482     return it != schemeSpecificParts_.end();
483 }
484 
485 /**
486  * @brief Remove the specified scheme part.
487  *
488  * @param scheme Name of the specified scheme part.
489  */
RemoveSchemeSpecificPart(const std::string & schemeSpecificPart)490 void Skills::RemoveSchemeSpecificPart(const std::string &schemeSpecificPart)
491 {
492     auto it = std::find_if(schemeSpecificParts_.begin(),
493         schemeSpecificParts_.end(),
494         [&schemeSpecificPart](const PatternsMatcher pm) { return pm.GetPattern() == schemeSpecificPart; });
495     if (it != schemeSpecificParts_.end()) {
496         schemeSpecificParts_.erase(it);
497     }
498 }
499 
500 /**
501  * @brief Obtains the count of scheme parts.
502  *
503  */
CountSchemeSpecificParts() const504 int Skills::CountSchemeSpecificParts() const
505 {
506     return schemeSpecificParts_.empty() ? 0 : schemeSpecificParts_.size();
507 }
508 
509 /**
510  * @brief Obtains the specified type.
511  *
512  * @param typeId Id of the specified type.
513  */
GetType(int index) const514 std::string Skills::GetType(int index) const
515 {
516     if (index < 0 || types_.empty() || std::size_t(index) >= types_.size()) {
517         return std::string();
518     }
519     return types_.at(index).GetPattern();
520 }
521 
522 /**
523  * @brief Adds a type to this Skills object.
524  *
525  * @param type Indicates the type to add.
526  */
AddType(const std::string & type)527 void Skills::AddType(const std::string &type)
528 {
529     PatternsMatcher pm(type, MatchType::DEFAULT);
530     AddType(pm);
531 }
532 
533 /**
534  * @brief Adds a type to this Skills object.
535  *
536  * @param type Indicates the type to add.
537  * @param matchType the specified match type.
538  */
AddType(const std::string & type,const MatchType & matchType)539 void Skills::AddType(const std::string &type, const MatchType &matchType)
540 {
541     PatternsMatcher pm(type, matchType);
542     AddType(pm);
543 }
544 
545 /**
546  * @brief Adds a type to this Skills object.
547  *
548  * @param type Indicates the type to add.
549  */
AddType(const PatternsMatcher & patternsMatcher)550 void Skills::AddType(const PatternsMatcher &patternsMatcher)
551 {
552     const size_t posNext = 1;
553     const size_t posOffset = 2;
554     std::string type = patternsMatcher.GetPattern();
555     size_t slashpos = type.find('/');
556     size_t typelen = type.length();
557     if (slashpos != std::string::npos && typelen >= slashpos + posOffset) {
558         if (typelen == slashpos + posOffset && type.at(slashpos + posNext) == '*') {
559             PatternsMatcher pm(type.substr(0, slashpos), patternsMatcher.GetType());
560             auto it = std::find_if(types_.begin(),
561                 types_.end(),
562                 [type = pm.GetPattern(), matchType = pm.GetType()](
563                     const PatternsMatcher pm) { return (pm.GetPattern() == type) && (pm.GetType() == matchType); });
564             if (it == types_.end()) {
565                 types_.emplace_back(pm);
566             }
567             hasPartialTypes_ = true;
568         } else {
569             PatternsMatcher pm(patternsMatcher);
570             auto it = std::find_if(types_.begin(),
571                 types_.end(),
572                 [type = pm.GetPattern(), matchType = pm.GetType()](
573                     const PatternsMatcher pm) { return (pm.GetPattern() == type) && (pm.GetType() == matchType); });
574             if (it == types_.end()) {
575                 types_.emplace_back(pm);
576             }
577         }
578     }
579 }
580 
581 /**
582  * @brief Checks whether the specified type is exist.
583  *
584  * @param type Name of the specified type.
585  */
HasType(const std::string & type)586 bool Skills::HasType(const std::string &type)
587 {
588     auto it = std::find_if(
589         types_.begin(), types_.end(), [&type](const PatternsMatcher pm) { return pm.GetPattern() == type; });
590     return it != types_.end();
591 }
592 
593 /**
594  * @brief Remove the specified type.
595  *
596  * @param type Name of the specified type.
597  */
RemoveType(const std::string & type)598 void Skills::RemoveType(const std::string &type)
599 {
600     auto it = std::find_if(
601         types_.begin(), types_.end(), [&type](const PatternsMatcher pm) { return pm.GetPattern() == type; });
602     if (it != types_.end()) {
603         types_.erase(it);
604     }
605 }
606 
607 /**
608  * @brief Remove the specified scheme type.
609  *
610  * @param patternsMatcher The type to be added.
611  */
RemoveType(const PatternsMatcher & patternsMatcher)612 void Skills::RemoveType(const PatternsMatcher &patternsMatcher)
613 {
614     auto it = std::find_if(types_.begin(), types_.end(), [&patternsMatcher](const PatternsMatcher pm) {
615         return (pm.GetPattern() == patternsMatcher.GetPattern()) && (pm.GetType() == patternsMatcher.GetType());
616     });
617     if (it != types_.end()) {
618         types_.erase(it);
619     }
620 }
621 
622 /**
623  * @brief Remove the specified scheme type.
624  *
625  * @param type Name of the specified type.
626  * @param matchType the specified match type.
627  */
RemoveType(const std::string & type,const MatchType & matchType)628 void Skills::RemoveType(const std::string &type, const MatchType &matchType)
629 {
630     PatternsMatcher pm(type, matchType);
631     RemoveType(pm);
632 }
633 
634 /**
635  * @brief Obtains the count of types.
636  *
637  */
CountTypes() const638 int Skills::CountTypes() const
639 {
640     return types_.empty() ? 0 : types_.size();
641 }
642 
643 /**
644  * @brief Match this skill against a Want's data.
645  *
646  * @param want The desired want data to match for.
647  */
Match(const Want & want)648 bool Skills::Match(const Want &want)
649 {
650     if (!MatchAction(want.GetAction())) {
651         return false;
652     }
653 
654     int dataMatch = MatchData(want.GetType(), want.GetScheme(), want.GetUri());
655     if (dataMatch < 0) {
656         return false;
657     }
658 
659     std::string entityMismatch = MatchEntities(want.GetEntities());
660     if (entityMismatch == std::string()) {
661         return false;
662     }
663 
664     return true;
665 }
666 
667 /**
668  * @brief Match this skills against a Want's entities.  Each entity in
669  * the Want must be specified by the skills; if any are not in the
670  * skills, the match fails.
671  *
672  * @param entities The entities included in the want, as returned by
673  *                   Want.getEntities().
674  *
675  * @return If all entities match (success), null; else the name of the
676  *         first entity that didn't match.
677  */
MatchEntities(const std::vector<std::string> & entities)678 std::string Skills::MatchEntities(const std::vector<std::string> &entities)
679 {
680     if (!entities.empty()) {
681         size_t size = entities.size();
682         for (size_t i = 0; i < size; i++) {
683             auto it = std::find(entities_.begin(), entities_.end(), entities[i]);
684             if (it != entities_.end()) {
685                 return entities[i];
686             }
687         }
688     }
689 
690     return std::string();
691 }
692 
693 /**
694  * @brief Match this skills against a Want's action.  If the skills does not
695  * specify any actions, the match will always fail.
696  *
697  * @param action The desired action to look for.
698  *
699  * @return True if the action is listed in the skills.
700  */
MatchAction(const std::string & action)701 bool Skills::MatchAction(const std::string &action)
702 {
703     return (action.empty() && actions_.empty()) || HasAction(action);
704 }
705 
706 /**
707  * @brief Match this skills against a Want's data (type, scheme and path).
708  *
709  * @param type The desired data type to look for.
710  * @param scheme The desired data scheme to look for.
711  * @param data The full data string to match against.
712  *
713  * @return Returns either a valid match constant.
714  */
MatchData(const std::string & type,const std::string & scheme,Uri data)715 int Skills::MatchData(const std::string &type, const std::string &scheme, Uri data)
716 {
717     std::vector<std::string> types;
718     for (auto it = types_.begin(); it != types_.end(); it++) {
719         types.emplace_back(it->GetPattern());
720     }
721     std::vector<std::string> schemes = schemes_;
722 
723     int match = RESULT_EMPTY;
724 
725     if (types.empty() && schemes.empty()) {
726         return (type == std::string() ? (RESULT_EMPTY + RESULT_NORMAL) : DISMATCH_DATA);
727     }
728 
729     if (!schemes.empty()) {
730         auto it = std::find(schemes.begin(), schemes.end(), scheme);
731         if (it != schemes.end()) {
732             match = RESULT_SCHEME;
733         } else {
734             return DISMATCH_DATA;
735         }
736 
737         std::vector<PatternsMatcher> schemeSpecificParts = schemeSpecificParts_;
738         if (schemeSpecificParts.size() >= 0) {
739             match = HasSchemeSpecificPart(data.GetSchemeSpecificPart()) ? RESULT_SCHEME_SPECIFIC_PART : DISMATCH_DATA;
740         }
741         if (match != RESULT_SCHEME_SPECIFIC_PART) {
742             std::vector<std::string> authorities = authorities_;
743             if (authorities.size() >= 0) {
744                 bool authMatch = HasAuthority(data.GetAuthority());
745                 if (authMatch == false) {
746                     return DISMATCH_DATA;
747                 }
748                 std::vector<PatternsMatcher> paths = paths_;
749                 if (paths.size() <= 0) {
750                     match = authMatch;
751                 } else if (HasPath(data.GetPath())) {
752                     match = RESULT_PATH;
753                 } else {
754                     return DISMATCH_DATA;
755                 }
756             }
757         }
758         if (match == DISMATCH_DATA) {
759             return DISMATCH_DATA;
760         }
761     } else {
762         if (scheme != std::string() && scheme != "content" && scheme != "file") {
763             return DISMATCH_DATA;
764         }
765     }
766 
767     if (!types.empty()) {
768         if (FindMimeType(type)) {
769             match = RESULT_TYPE;
770         } else {
771             return DISMATCH_TYPE;
772         }
773     } else {
774         if (type != std::string()) {
775             return DISMATCH_TYPE;
776         }
777     }
778 
779     return match + RESULT_NORMAL;
780 }
781 
FindMimeType(const std::string & type)782 bool Skills::FindMimeType(const std::string &type)
783 {
784     const int posNext = 1;
785     const int posOffset = 2;
786     std::vector<PatternsMatcher> types = types_;
787 
788     if (type == std::string()) {
789         return false;
790     }
791     auto it = types.begin();
792     for (; it != types.end(); it++) {
793         if (it->GetPattern() == type) {
794             break;
795         }
796     }
797     if (it != types.end()) {
798         return true;
799     }
800 
801     size_t typeLength = type.length();
802     if (typeLength == LENGTH_FOR_FINDMINETYPE && type == "*/*") {
803         return !types.empty();
804     }
805 
806     auto hasType =
807         std::find_if(types.begin(), types.end(), [](const PatternsMatcher pm) { return pm.GetPattern() == "*"; });
808     if (hasPartialTypes_ && hasType != types.end()) {
809         return true;
810     }
811 
812     auto typeIt = type.find(0, 1, '/');
813     size_t slashpos = type.size() - typeIt;
814     if (slashpos <= 0) {
815         return false;
816     }
817 
818     std::string typeSubstr = type.substr(0, slashpos);
819 
820     hasType = std::find_if(types.begin(), types.end(), [&typeSubstr](const PatternsMatcher pm) {
821         return pm.GetPattern() == typeSubstr;
822     });
823     if (hasPartialTypes_ && hasType != types.end()) {
824         return true;
825     }
826 
827     if (typeLength == slashpos + posOffset && type.at(slashpos + posNext) == '*') {
828         size_t numTypes = types.size();
829         for (size_t i = 0; i < numTypes; i++) {
830             std::string value = types.at(i).GetPattern();
831             if (RegionMatches(type, 0, value, 0, slashpos + posNext)) {
832                 return true;
833             }
834         }
835     }
836 
837     return false;
838 }
839 
RegionMatches(const std::string & type,int toffset,const std::string & other,int ooffset,int len)840 bool Skills::RegionMatches(const std::string &type, int toffset, const std::string &other, int ooffset, int len)
841 {
842     int to = toffset;
843     int po = ooffset;
844     // Note: toffset, ooffset, or len might be near -1>>>1.
845     if ((ooffset < 0) || (toffset < 0) || (toffset > (long)type.size() - len) ||
846         (ooffset > (long)other.length() - len)) {
847         return false;
848     }
849     while (len-- > 0) {
850         if (type.at(to++) != other.at(po++)) {
851             return false;
852         }
853     }
854     return true;
855 }
856 
857 /**
858  * @brief Obtains the want params data.
859  *
860  * @return the WantParams object.
861  */
GetWantParams() const862 const WantParams &Skills::GetWantParams() const
863 {
864     return wantParams_;
865 }
866 
867 /**
868  * @brief Sets a WantParams object in this MatchingSkills object.
869  *
870  * @param wantParams Indicates the WantParams object.
871  */
SetWantParams(const WantParams & wantParams)872 void Skills::SetWantParams(const WantParams &wantParams)
873 {
874     wantParams_ = wantParams;
875 }
876 
877 /**
878  * @brief Marshals this Sequenceable object into a Parcel.
879  *
880  * @param outParcel Indicates the Parcel object to which the Sequenceable object will be marshaled.
881  */
Marshalling(Parcel & parcel) const882 bool Skills::Marshalling(Parcel &parcel) const
883 {
884     // entities​_
885     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, entities_);
886     // actions_
887     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, actions_);
888     // authorities_
889     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, authorities_);
890     // schemes_
891     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, schemes_);
892     // paths_
893     if (paths_.empty()) {
894         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL);
895     } else {
896         if (!parcel.WriteInt32(VALUE_OBJECT)) {
897             return false;
898         }
899         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, paths_.size());
900         for (auto path : paths_) {
901             if (!parcel.WriteParcelable(&path)) {
902                 return false;
903             }
904         }
905     }
906     // schemeSpecificParts_
907     if (schemeSpecificParts_.empty()) {
908         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL);
909     } else {
910         if (!parcel.WriteInt32(VALUE_OBJECT)) {
911             return false;
912         }
913         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, schemeSpecificParts_.size());
914         for (auto schemeSpecificPart : schemeSpecificParts_) {
915             if (!parcel.WriteParcelable(&schemeSpecificPart)) {
916                 return false;
917             }
918         }
919     }
920     // types_
921     if (types_.empty()) {
922         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL);
923     } else {
924         if (!parcel.WriteInt32(VALUE_OBJECT)) {
925             return false;
926         }
927         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, types_.size());
928         for (auto type : types_) {
929             if (!parcel.WriteParcelable(&type)) {
930                 return false;
931             }
932         }
933     }
934 
935     // parameters_
936     if (wantParams_.GetParams().empty()) {
937         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, VALUE_NULL);
938     } else {
939         if (!parcel.WriteInt32(VALUE_OBJECT)) {
940             return false;
941         }
942         if (!parcel.WriteParcelable(&wantParams_)) {
943             return false;
944         }
945     }
946     return true;
947 }
948 
949 /**
950  * @brief Unmarshals this Sequenceable object from a Parcel.
951  *
952  * @param inParcel Indicates the Parcel object into which the Sequenceable object has been marshaled.
953  */
Unmarshalling(Parcel & parcel)954 Skills *Skills::Unmarshalling(Parcel &parcel)
955 {
956     Skills *skills = new (std::nothrow) Skills();
957     if (skills != nullptr) {
958         if (!skills->ReadFromParcel(parcel)) {
959             delete skills;
960             skills = nullptr;
961         }
962     }
963     return skills;
964 }
965 
ReadFromParcel(Parcel & parcel)966 bool Skills::ReadFromParcel(Parcel &parcel)
967 {
968     int32_t empty;
969     int32_t size = 0;
970     PatternsMatcher *pm = nullptr;
971 
972     // entities​_
973     READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &entities_);
974     // actions_
975     READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &actions_);
976     // authorities_
977     READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &authorities_);
978     // schemes_
979     READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(StringVector, parcel, &schemes_);
980     // paths_
981     empty = VALUE_NULL;
982     if (!parcel.ReadInt32(empty)) {
983         return false;
984     }
985 
986     if (empty == VALUE_OBJECT) {
987         READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, size);
988         if (size > CYCLE_LIMIT) {
989             return false;
990         }
991         for (int i = 0; i < size; i++) {
992             pm = parcel.ReadParcelable<PatternsMatcher>();
993             if (pm == nullptr) {
994                 return false;
995             } else {
996                 paths_.emplace_back(*pm);
997                 delete pm;
998                 pm = nullptr;
999             }
1000         }
1001     }
1002 
1003     // schemeSpecificParts_
1004     empty = VALUE_NULL;
1005     if (!parcel.ReadInt32(empty)) {
1006         return false;
1007     }
1008 
1009     if (empty == VALUE_OBJECT) {
1010         READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, size);
1011         if (size > CYCLE_LIMIT) {
1012             return false;
1013         }
1014         for (int i = 0; i < size; i++) {
1015             pm = parcel.ReadParcelable<PatternsMatcher>();
1016             if (pm == nullptr) {
1017                 return false;
1018             } else {
1019                 schemeSpecificParts_.emplace_back(*pm);
1020                 delete pm;
1021                 pm = nullptr;
1022             }
1023         }
1024     }
1025 
1026     // types_
1027     empty = VALUE_NULL;
1028     if (!parcel.ReadInt32(empty)) {
1029         return false;
1030     }
1031 
1032     if (empty == VALUE_OBJECT) {
1033         READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, size);
1034         if (size > CYCLE_LIMIT) {
1035             return false;
1036         }
1037         for (int i = 0; i < size; i++) {
1038             pm = parcel.ReadParcelable<PatternsMatcher>();
1039             if (pm == nullptr) {
1040                 return false;
1041             } else {
1042                 types_.emplace_back(*pm);
1043                 delete pm;
1044                 pm = nullptr;
1045             }
1046         }
1047     }
1048 
1049     // parameters_
1050     empty = VALUE_NULL;
1051     if (!parcel.ReadInt32(empty)) {
1052         return false;
1053     }
1054 
1055     if (empty == VALUE_OBJECT) {
1056         auto params = parcel.ReadParcelable<WantParams>();
1057         if (params != nullptr) {
1058             wantParams_ = *params;
1059             delete params;
1060             params = nullptr;
1061         } else {
1062             return false;
1063         }
1064     }
1065 
1066     return true;
1067 }
1068 }  // namespace AAFwk
1069 }  // namespace OHOS