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