• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 
16 #include "white_list_util.h"
17 
18 #include <algorithm>
19 #include <cstring>
20 #include <fstream>
21 #include <sstream>
22 
23 #include "config_policy_utils.h"
24 
25 #include "dinput_errcode.h"
26 #include "dinput_log.h"
27 #include "dinput_utils_tool.h"
28 
29 namespace OHOS {
30 namespace DistributedHardware {
31 namespace DistributedInput {
32 namespace {
33     const char * const SPLIT_LINE = "|";
34     const char * const SPLIT_COMMA = ",";
35     const char * const WHITELIST_FILE_PATH = "etc/distributedhardware/dinput_business_event_whitelist.cfg";
36     const int32_t COMB_KEY_VEC_MIN_LEN = 2;
37     const int32_t LAST_KEY_ACTION_LEN = 1;
38     const int32_t LAST_KEY_LEN = 1;
39     const int32_t MAX_LINE_NUM = 100;
40     const int32_t MAX_CHAR_PER_LINE_NUM = 100;
41     const int32_t MAX_SPLIT_COMMA_NUM = 4;
42     const int32_t MAX_SPLIT_LINE_NUM = 12;
43     const int32_t MAX_KEY_CODE_NUM = 4;
44 }
45 
WhiteListUtil()46 WhiteListUtil::WhiteListUtil()
47 {
48     DHLOGI("Ctor WhiteListUtil.");
49     Init();
50 }
51 
~WhiteListUtil()52 WhiteListUtil::~WhiteListUtil()
53 {
54     DHLOGI("Dtor WhiteListUtil.");
55 }
56 
GetInstance(void)57 WhiteListUtil &WhiteListUtil::GetInstance(void)
58 {
59     static WhiteListUtil instance;
60     return instance;
61 }
62 
Init()63 int32_t WhiteListUtil::Init()
64 {
65     char buf[MAX_PATH_LEN] = {0};
66     char path[PATH_MAX + 1] = {0x00};
67     char *whiteListFilePath = GetOneCfgFile(WHITELIST_FILE_PATH, buf, MAX_PATH_LEN);
68     if (strlen(whiteListFilePath) == 0 || strlen(whiteListFilePath) > PATH_MAX ||
69         realpath(whiteListFilePath, path) == nullptr) {
70         DHLOGE("File connicailization failed.");
71         return ERR_DH_INPUT_WHILTELIST_INIT_FAIL;
72     }
73     std::ifstream inFile(path, std::ios::in | std::ios::binary);
74     if (!inFile.is_open()) {
75         DHLOGE("WhiteListUtil Init error, file open fail path=%s", path);
76         return ERR_DH_INPUT_WHILTELIST_INIT_FAIL;
77     }
78 
79     TYPE_KEY_CODE_VEC vecKeyCode;
80     TYPE_COMBINATION_KEY_VEC vecCombinationKey;
81     TYPE_WHITE_LIST_VEC vecWhiteList;
82     std::string line;
83     std::size_t lineNum = 0;
84     while (getline(inFile, line)) {
85         if ((++lineNum > MAX_LINE_NUM) || !IsValidLine(line)) {
86             DHLOGE("whitelist cfg file has too many lines or too complicated. lineNum is %d", lineNum);
87             break;
88         }
89         vecKeyCode.clear();
90         vecCombinationKey.clear();
91         SplitCombinationKey(line, vecKeyCode, vecCombinationKey);
92 
93         if (CheckIsNumber(line)) {
94             int32_t keyCode = std::stoi(line);
95             if (keyCode != 0) {
96                 vecKeyCode.push_back(keyCode);
97             }
98             if (!vecKeyCode.empty()) {
99                 vecCombinationKey.push_back(vecKeyCode);
100                 vecKeyCode.clear();
101             }
102         }
103 
104         if (!vecCombinationKey.empty()) {
105             vecWhiteList.push_back(vecCombinationKey);
106             vecCombinationKey.clear();
107         }
108     }
109     inFile.close();
110     std::string localNetworkId = GetLocalDeviceInfo().networkId;
111     if (!localNetworkId.empty()) {
112         SyncWhiteList(localNetworkId, vecWhiteList);
113     }
114     return DH_SUCCESS;
115 }
116 
IsValidLine(const std::string & line) const117 bool WhiteListUtil::IsValidLine(const std::string &line) const
118 {
119     if (line.size() > MAX_CHAR_PER_LINE_NUM) {
120         DHLOGE("This line is too long, size is %d", line.size());
121         return false;
122     }
123     if (std::count(line.begin(), line.end(), SPLIT_COMMA[0]) > MAX_SPLIT_COMMA_NUM) {
124         DHLOGE("This line %s has too many SPLIT_COMMA", line.c_str());
125         return false;
126     }
127     if (std::count(line.begin(), line.end(), SPLIT_LINE[0]) > MAX_SPLIT_LINE_NUM) {
128         DHLOGE("This line %s has too many SPLIT_LINE", line.c_str());
129         return false;
130     }
131     return true;
132 }
133 
CheckIsNumber(const std::string & str) const134 bool WhiteListUtil::CheckIsNumber(const std::string &str) const
135 {
136     if (str.empty() || str.size() > MAX_KEY_CODE_NUM) {
137         DHLOGE("KeyCode size %d, is zero or too long.", str.size());
138         return false;
139     }
140     for (char const &c : str) {
141         if (std::isdigit(c) == 0) {
142             DHLOGE("Check KeyCode format fail, %s.", str.c_str());
143             return false;
144         }
145     }
146     return true;
147 }
148 
ReadLineDataStepOne(std::string & column,TYPE_KEY_CODE_VEC & vecKeyCode,TYPE_COMBINATION_KEY_VEC & vecCombinationKey) const149 void WhiteListUtil::ReadLineDataStepOne(std::string &column, TYPE_KEY_CODE_VEC &vecKeyCode,
150     TYPE_COMBINATION_KEY_VEC &vecCombinationKey) const
151 {
152     std::size_t pos2 = column.find(SPLIT_LINE);
153     while (pos2 != std::string::npos) {
154         std::string single = column.substr(0, pos2);
155         column = column.substr(pos2 + 1, column.size());
156         pos2 = column.find(SPLIT_LINE);
157 
158         if (CheckIsNumber(single)) {
159             int32_t keyCode = std::stoi(single);
160             if (keyCode != 0) {
161                 vecKeyCode.push_back(keyCode);
162             }
163         }
164     }
165 
166     if (CheckIsNumber(column)) {
167         int32_t keyCode = std::stoi(column);
168         if (keyCode != 0) {
169             vecKeyCode.push_back(keyCode);
170         }
171     }
172 
173     if (!vecKeyCode.empty()) {
174         vecCombinationKey.push_back(vecKeyCode);
175         vecKeyCode.clear();
176     }
177 }
178 
SplitCombinationKey(std::string & line,TYPE_KEY_CODE_VEC & vecKeyCode,TYPE_COMBINATION_KEY_VEC & vecCombinationKey) const179 void WhiteListUtil::SplitCombinationKey(std::string &line, TYPE_KEY_CODE_VEC &vecKeyCode,
180     TYPE_COMBINATION_KEY_VEC &vecCombinationKey) const
181 {
182     std::size_t pos1 = line.find(SPLIT_COMMA);
183     while (pos1 != std::string::npos) {
184         std::string column = line.substr(0, pos1);
185         line = line.substr(pos1 + 1, line.size());
186         pos1 = line.find(SPLIT_COMMA);
187         vecKeyCode.clear();
188         ReadLineDataStepOne(column, vecKeyCode, vecCombinationKey);
189     }
190 }
191 
SyncWhiteList(const std::string & deviceId,const TYPE_WHITE_LIST_VEC & vecWhiteList)192 int32_t WhiteListUtil::SyncWhiteList(const std::string &deviceId, const TYPE_WHITE_LIST_VEC &vecWhiteList)
193 {
194     DHLOGI("deviceId=%s", GetAnonyString(deviceId).c_str());
195 
196     std::lock_guard<std::mutex> lock(mutex_);
197     mapDeviceWhiteList_[deviceId] = vecWhiteList;
198     for (auto combKeys : vecWhiteList) {
199         GetCombKeysHash(combKeys, combKeysHashMap_[deviceId]);
200     }
201 
202     return DH_SUCCESS;
203 }
204 
GetCombKeysHash(TYPE_COMBINATION_KEY_VEC combKeys,std::unordered_set<std::string> & targetSet)205 void WhiteListUtil::GetCombKeysHash(TYPE_COMBINATION_KEY_VEC combKeys, std::unordered_set<std::string> &targetSet)
206 {
207     if (combKeys.size() < COMB_KEY_VEC_MIN_LEN) {
208         DHLOGE("white list item length invalid");
209         return;
210     }
211 
212     TYPE_KEY_CODE_VEC lastKeyAction = combKeys.back();
213     if (lastKeyAction.size() != LAST_KEY_ACTION_LEN) {
214         DHLOGE("last key action invalid");
215         return;
216     }
217     combKeys.pop_back();
218     TYPE_KEY_CODE_VEC lastKey = combKeys.back();
219     if (lastKey.size() != LAST_KEY_LEN) {
220         DHLOGE("last key invalid");
221         return;
222     }
223     combKeys.pop_back();
224 
225     std::unordered_set<std::string> hashSets;
226     WhiteListItemHash hash;
227     GetAllComb(combKeys, hash, combKeys.size(), hashSets);
228 
229     for (const auto &hashSet : hashSets) {
230         targetSet.insert(hashSet + std::to_string(lastKey[0]) + std::to_string(lastKeyAction[0]));
231     }
232 }
233 
GetAllComb(TYPE_COMBINATION_KEY_VEC vecs,WhiteListItemHash hash,int32_t targetLen,std::unordered_set<std::string> & hashSets)234 void WhiteListUtil::GetAllComb(TYPE_COMBINATION_KEY_VEC vecs, WhiteListItemHash hash,
235     int32_t targetLen, std::unordered_set<std::string> &hashSets)
236 {
237     for (size_t i = 0; i < vecs.size(); i++) {
238         TYPE_KEY_CODE_VEC nowVec = vecs[i];
239         for (int32_t code : nowVec) {
240             std::string hashStr = hash.hash + std::to_string(code);
241             WhiteListItemHash newHash(hashStr, hash.len + 1);
242             TYPE_COMBINATION_KEY_VEC leftVecs = vecs;
243             leftVecs.erase(leftVecs.begin() + i);
244             GetAllComb(leftVecs, newHash, targetLen, hashSets);
245         }
246     }
247 
248     if (hash.len == targetLen) {
249         hashSets.insert(hash.hash);
250     }
251 }
252 
ClearWhiteList(const std::string & deviceId)253 int32_t WhiteListUtil::ClearWhiteList(const std::string &deviceId)
254 {
255     DHLOGI("deviceId=%s", GetAnonyString(deviceId).c_str());
256 
257     std::lock_guard<std::mutex> lock(mutex_);
258     mapDeviceWhiteList_.erase(deviceId);
259     return DH_SUCCESS;
260 }
261 
ClearWhiteList(void)262 int32_t WhiteListUtil::ClearWhiteList(void)
263 {
264     std::lock_guard<std::mutex> lock(mutex_);
265     TYPE_DEVICE_WHITE_LIST_MAP().swap(mapDeviceWhiteList_);
266     return DH_SUCCESS;
267 }
268 
GetWhiteList(const std::string & deviceId,TYPE_WHITE_LIST_VEC & vecWhiteList)269 int32_t WhiteListUtil::GetWhiteList(const std::string &deviceId, TYPE_WHITE_LIST_VEC &vecWhiteList)
270 {
271     DHLOGI("GetWhiteList start, deviceId=%s", GetAnonyString(deviceId).c_str());
272 
273     std::lock_guard<std::mutex> lock(mutex_);
274     TYPE_DEVICE_WHITE_LIST_MAP::const_iterator iter = mapDeviceWhiteList_.find(deviceId);
275     if (iter != mapDeviceWhiteList_.end()) {
276         vecWhiteList = iter->second;
277         DHLOGI("GetWhiteList success, deviceId=%s", GetAnonyString(deviceId).c_str());
278         return DH_SUCCESS;
279     }
280 
281     DHLOGI("GetWhiteList fail, deviceId=%s", GetAnonyString(deviceId).c_str());
282     return ERR_DH_INPUT_WHILTELIST_GET_WHILTELIST_FAIL;
283 }
284 
GetBusinessEventHash(const BusinessEvent & event)285 std::string WhiteListUtil::GetBusinessEventHash(const BusinessEvent &event)
286 {
287     std::string hash = "";
288     for (const auto &p : event.pressedKeys) {
289         hash += std::to_string(p);
290     }
291     hash += std::to_string(event.keyCode);
292     hash += std::to_string(event.keyAction);
293 
294     return hash;
295 }
296 
IsNeedFilterOut(const std::string & deviceId,const BusinessEvent & event)297 bool WhiteListUtil::IsNeedFilterOut(const std::string &deviceId, const BusinessEvent &event)
298 {
299     DHLOGI("IsNeedFilterOut start, deviceId=%s", GetAnonyString(deviceId).c_str());
300 
301     std::lock_guard<std::mutex> lock(mutex_);
302     if (combKeysHashMap_.empty()) {
303         DHLOGE("IsNeedFilterOut error, white list is empty!");
304         return false;
305     }
306 
307     auto iter = combKeysHashMap_.find(deviceId);
308     if (iter == combKeysHashMap_.end()) {
309         DHLOGE("IsNeedFilterOut error, not find by deviceId!");
310         return false;
311     }
312 
313     std::string hash = GetBusinessEventHash(event);
314     DHLOGI("Searched business event hash: %s", hash.c_str());
315 
316     return combKeysHashMap_[deviceId].find(hash) != combKeysHashMap_[deviceId].end();
317 }
318 } // namespace DistributedInput
319 } // namespace DistributedHardware
320 } // namespace OHOS
321