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 20namespace OHOS { 21namespace UDMF { 22static std::bitset<MAX_BIT_SIZE> g_ruleIntention; 23static std::bitset<MAX_BIT_SIZE> g_ruleBundleName; 24static std::bitset<MAX_BIT_SIZE> g_ruleGroupId; 25static constexpr const char *UNIFIED_KEY_SCHEMA = "udmf://"; 26static constexpr const char *ALPHA_AGGREGATE = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 27static constexpr const char *DIGIT_AGGREGATE = "0123456789"; 28static constexpr const char *SYMBOL_AGGREGATE = ":;<=>?@[\\]_`"; 29UnifiedKey::UnifiedKey(std::string key) 30{ 31 this->key = std::move(key); 32} 33 34UnifiedKey::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 41std::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 54bool 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 109bool 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 127void 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