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 "UnifiedKey"
16 #include "unified_key.h"
17
18 #include "logger.h"
19
20 namespace OHOS {
21 namespace UDMF {
22 static std::bitset<MAX_BIT_SIZE> g_ruleIntention;
23 static std::bitset<MAX_BIT_SIZE> g_ruleBundleName;
24 static std::bitset<MAX_BIT_SIZE> g_ruleGroupId;
25 static constexpr const char *UNIFIED_KEY_SCHEMA = "udmf://";
26 static constexpr const char *ALPHA_AGGREGATE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
27 static constexpr const char *DIGIT_AGGREGATE = "0123456789";
28 static constexpr const char *SYMBOL_AGGREGATE = ":;<=>?@[\\]_`";
UnifiedKey(std::string key)29 UnifiedKey::UnifiedKey(std::string key)
30 {
31 this->key = std::move(key);
32 }
33
UnifiedKey(std::string intention,std::string bundle,std::string groupId)34 UnifiedKey::UnifiedKey(std::string intention, std::string bundle, std::string groupId)
35 {
36 this->intention = std::move(intention);
37 this->bundleName = std::move(bundle);
38 this->groupId = std::move(groupId);
39 }
40
GetUnifiedKey()41 std::string UnifiedKey::GetUnifiedKey()
42 {
43 if (!this->key.empty()) {
44 return this->key;
45 }
46 if (this->intention.empty() || this->groupId.empty()) {
47 return "";
48 }
49 // Uri-compliant structure, example: udmf://drag/com.ohos.test/012345679abc
50 this->key = UNIFIED_KEY_SCHEMA + this->intention + "/" + this->bundleName + "/" + this->groupId;
51 return this->key;
52 }
53
IsValid()54 bool UnifiedKey::IsValid()
55 {
56 if (this->key.empty()) {
57 LOG_DEBUG(UDMF_FRAMEWORK, "empty key");
58 return false;
59 }
60 PreliminaryWork();
61
62 std::string data = this->key; // schema/intention/groupId
63 std::string separator = "://";
64 size_t pos = data.find(separator);
65 if (pos == std::string::npos) {
66 return false;
67 }
68 std::string schema = data.substr(0, pos + separator.size()); // schema
69 if (UNIFIED_KEY_SCHEMA != schema) {
70 LOG_DEBUG(UDMF_FRAMEWORK, "wrong schema");
71 return false;
72 }
73
74 data = data.substr(pos + separator.size()); // intention/bundleName/groupId
75 pos = data.find('/'); // intention
76 if (pos == std::string::npos) {
77 return false;
78 }
79 std::string intentionTmp = data.substr(0, pos);
80 if (!CheckCharacter(intentionTmp, g_ruleIntention)) {
81 return false;
82 }
83 this->intention = intentionTmp;
84
85 data = data.substr(pos + 1);
86 pos = data.find('/'); // bundleName
87 if (pos == std::string::npos) {
88 return false;
89 }
90 std::string bundle = data.substr(0, pos);
91 if (!CheckCharacter(bundle, g_ruleBundleName)) {
92 LOG_DEBUG(UDMF_FRAMEWORK, "wrong bundle");
93 return false;
94 }
95 this->bundleName = bundle;
96
97 data = data.substr(pos + 1); // groupId
98 if (data.empty()) {
99 return false;
100 }
101 if (!CheckCharacter(data, g_ruleGroupId)) {
102 LOG_DEBUG(UDMF_FRAMEWORK, "wrong groupId");
103 return false;
104 }
105 this->groupId = data;
106 return true;
107 }
108
CheckCharacter(std::string data,std::bitset<MAX_BIT_SIZE> rule)109 bool UnifiedKey::CheckCharacter(std::string data, std::bitset<MAX_BIT_SIZE> rule)
110 {
111 if (data.empty()) {
112 LOG_DEBUG(UDMF_FRAMEWORK, "empty key");
113 return false;
114 }
115 size_t dataLen = data.size();
116 for (size_t i = 0; i < dataLen; ++i) {
117 if (static_cast<int>(data[i]) >= 0 && static_cast<int>(data[i]) < 128) { // 128:ASCII Max Number
118 bool isLegal = rule.test(data[i]);
119 if (!isLegal) {
120 return false;
121 }
122 }
123 }
124 return true;
125 }
126
PreliminaryWork()127 void UnifiedKey::PreliminaryWork()
128 {
129 // All intentions are composed of uppercase and lowercase letters and underscores.
130 if (g_ruleIntention.none()) {
131 std::string intentionTmp = std::string(ALPHA_AGGREGATE) + "_";
132 for (char i : intentionTmp) {
133 g_ruleIntention.set(i);
134 }
135 }
136 // All bundle name are composed of uppercase and lowercase letters and dots.
137 if (g_ruleBundleName.none()) {
138 std::string bundleAggregate = std::string(ALPHA_AGGREGATE) + DIGIT_AGGREGATE + "._";
139 for (char i : bundleAggregate) {
140 g_ruleBundleName.set(i);
141 }
142 }
143 // Characters of groupId are taken from Ascii codes 48 to 122.
144 if (g_ruleGroupId.none()) {
145 std::string idAggregate = std::string(DIGIT_AGGREGATE) + ALPHA_AGGREGATE + SYMBOL_AGGREGATE;
146 for (char i : idAggregate) {
147 g_ruleGroupId.set(i);
148 }
149 }
150 }
151 } // namespace UDMF
152 } // namespace OHOS