• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "dinput_utils_tool.h"
17 
18 #include <cstdarg>
19 #include <cstdio>
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <sys/time.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <openssl/sha.h>
27 
28 #include "nlohmann/json.hpp"
29 #include "securec.h"
30 
31 #ifndef COMPILE_TEST_MODE
32 #include "softbus_bus_center.h"
33 #else
34 #include "softbus_bus_center_mock.h"
35 #endif
36 
37 #include "constants_dinput.h"
38 #include "dinput_errcode.h"
39 #include "dinput_softbus_define.h"
40 
41 namespace OHOS {
42 namespace DistributedHardware {
43 namespace DistributedInput {
44 namespace {
45     constexpr int32_t HEX_TO_UINT8 = 2;
46     constexpr size_t INT32_SHORT_ID_LENGTH = 20;
47     constexpr size_t INT32_PLAINTEXT_LENGTH = 4;
48     constexpr size_t INT32_MIN_ID_LENGTH = 3;
49     constexpr int32_t WIDTH = 4;
50     constexpr unsigned char MASK = 0x0F;
51     constexpr int32_t DOUBLE_TIMES = 2;
52     constexpr int32_t INT32_STRING_LENGTH = 40;
53     constexpr int32_t MAX_RETRY_COUNT = 10;
54     constexpr uint32_t SLEEP_TIME_US = 100 * 1000;
55     constexpr uint32_t ERROR_MSG_MAX_LEN = 256;
56 }
GetLocalDeviceInfo()57 DevInfo GetLocalDeviceInfo()
58 {
59     DevInfo devInfo{"", "", 0};
60     auto info = std::make_unique<NodeBasicInfo>();
61     auto ret = GetLocalNodeDeviceInfo(DINPUT_PKG_NAME.c_str(), info.get());
62     if (ret != 0) {
63         DHLOGE("GetLocalNodeDeviceInfo failed, errCode = %d", ret);
64         return devInfo;
65     }
66 
67     devInfo.networkId = info->networkId;
68     devInfo.deviceName = info->deviceName;
69     devInfo.deviceType = info->deviceTypeId;
70 
71     return devInfo;
72 }
73 
GetLocalNetworkId()74 std::string GetLocalNetworkId()
75 {
76     std::string localNetworkId = GetLocalDeviceInfo().networkId;
77     if (localNetworkId.empty()) {
78         DHLOGE("local networkId is empty!");
79     }
80     DHLOGI("GetLocalNetworkId, device local networkId is %s", GetAnonyString(localNetworkId).c_str());
81     return localNetworkId;
82 }
83 
GetUUIDBySoftBus(const std::string & networkId)84 std::string GetUUIDBySoftBus(const std::string &networkId)
85 {
86     if (networkId.empty()) {
87         return "";
88     }
89     char uuid[UUID_BUF_LEN] = {0};
90     auto ret = GetNodeKeyInfo(DINPUT_PKG_NAME.c_str(), networkId.c_str(), NodeDeviceInfoKey::NODE_KEY_UUID,
91         reinterpret_cast<uint8_t *>(uuid), UUID_BUF_LEN);
92     return (ret == DH_SUCCESS) ? std::string(uuid) : "";
93 }
94 
GetCurrentTime()95 uint64_t GetCurrentTime()
96 {
97     constexpr int32_t usOneSecond = 1000 * 1000;
98     struct timeval tv;
99     gettimeofday(&tv, nullptr);
100     return tv.tv_sec * usOneSecond + tv.tv_usec;
101 }
102 
SetAnonyId(const std::string & message)103 std::string SetAnonyId(const std::string &message)
104 {
105     nlohmann::json jsonObj = nlohmann::json::parse(message, nullptr, false);
106     if (jsonObj.is_discarded()) {
107         DHLOGE("jsonObj parse failed!");
108         return "";
109     }
110     if (IsString(jsonObj, DINPUT_SOFTBUS_KEY_DEVICE_ID)) {
111         jsonObj[DINPUT_SOFTBUS_KEY_DEVICE_ID] = GetAnonyString(jsonObj[DINPUT_SOFTBUS_KEY_DEVICE_ID]);
112     }
113     if (IsString(jsonObj, DESCRIPTOR)) {
114         jsonObj[DESCRIPTOR] = GetAnonyString(jsonObj[DESCRIPTOR]);
115     }
116     if (IsString(jsonObj, DINPUT_SOFTBUS_KEY_INPUT_DATA)) {
117         jsonObj[DINPUT_SOFTBUS_KEY_INPUT_DATA] = GetAnonyString(jsonObj[DINPUT_SOFTBUS_KEY_INPUT_DATA]);
118     }
119     if (IsString(jsonObj, DINPUT_SOFTBUS_KEY_VECTOR_DHID)) {
120         std::string dhidStr = jsonObj[DINPUT_SOFTBUS_KEY_VECTOR_DHID];
121         dhidStr.append(".");
122         size_t pos = dhidStr.find(".");
123         std::string anonyDhidStr = "";
124         while (pos != dhidStr.npos) {
125             anonyDhidStr += GetAnonyString(dhidStr.substr(0, pos)) + ".";
126             dhidStr = dhidStr.substr(pos + 1, dhidStr.size());
127             pos = dhidStr.find(".");
128         }
129         jsonObj[DINPUT_SOFTBUS_KEY_VECTOR_DHID] = anonyDhidStr.substr(0, anonyDhidStr.length() - 1);
130     }
131     if (IsString(jsonObj, DINPUT_SOFTBUS_KEY_SRC_DEV_ID)) {
132         jsonObj[DINPUT_SOFTBUS_KEY_SRC_DEV_ID] = GetAnonyString(jsonObj[DINPUT_SOFTBUS_KEY_SRC_DEV_ID]);
133     }
134     if (IsString(jsonObj, DINPUT_SOFTBUS_KEY_SINK_DEV_ID)) {
135         jsonObj[DINPUT_SOFTBUS_KEY_SINK_DEV_ID] = GetAnonyString(jsonObj[DINPUT_SOFTBUS_KEY_SINK_DEV_ID]);
136     }
137     return jsonObj.dump();
138 }
139 
IsBoolean(const nlohmann::json & jsonObj,const std::string & key)140 bool IsBoolean(const nlohmann::json &jsonObj, const std::string &key)
141 {
142     bool res = jsonObj.contains(key) && jsonObj[key].is_boolean();
143     if (!res) {
144         DHLOGE("The key %s in jsonObj is invalid.", key.c_str());
145     }
146     return res;
147 }
148 
IsString(const nlohmann::json & jsonObj,const std::string & key)149 bool IsString(const nlohmann::json &jsonObj, const std::string &key)
150 {
151     bool res = jsonObj.contains(key) && jsonObj[key].is_string();
152     if (!res) {
153         DHLOGE("The key %s in jsonObj is invalid.", key.c_str());
154     }
155     return res;
156 }
157 
IsInt32(const nlohmann::json & jsonObj,const std::string & key)158 bool IsInt32(const nlohmann::json &jsonObj, const std::string &key)
159 {
160     bool res = jsonObj.contains(key) && jsonObj[key].is_number_integer() && INT32_MIN <= jsonObj[key] &&
161         jsonObj[key] <= INT32_MAX;
162     if (!res) {
163         DHLOGE("The key %s in jsonObj is invalid.", key.c_str());
164     }
165     return res;
166 }
167 
IsInt64(const nlohmann::json & jsonObj,const std::string & key)168 bool IsInt64(const nlohmann::json &jsonObj, const std::string &key)
169 {
170     bool res = jsonObj.contains(key) && jsonObj[key].is_number_integer() && INT64_MIN <= jsonObj[key] &&
171         jsonObj[key] <= INT64_MAX;
172     if (!res) {
173         DHLOGE("The key %s in jsonObj is invalid.", key.c_str());
174     }
175     return res;
176 }
177 
IsUInt16(const nlohmann::json & jsonObj,const std::string & key)178 bool IsUInt16(const nlohmann::json &jsonObj, const std::string &key)
179 {
180     bool res = jsonObj.contains(key) && jsonObj[key].is_number_unsigned() && jsonObj[key] <= UINT16_MAX;
181     if (!res) {
182         DHLOGE("The key %s in jsonObj is invalid.", key.c_str());
183     }
184     return res;
185 }
186 
IsUInt32(const nlohmann::json & jsonObj,const std::string & key)187 bool IsUInt32(const nlohmann::json &jsonObj, const std::string &key)
188 {
189     bool res = jsonObj.contains(key) && jsonObj[key].is_number_unsigned() && jsonObj[key] <= UINT32_MAX;
190     if (!res) {
191         DHLOGE("The key %s in jsonObj is invalid.", key.c_str());
192     }
193     return res;
194 }
195 
IsUInt64(const nlohmann::json & jsonObj,const std::string & key)196 bool IsUInt64(const nlohmann::json &jsonObj, const std::string &key)
197 {
198     bool res = jsonObj.contains(key) && jsonObj[key].is_number_unsigned() && jsonObj[key] <= UINT64_MAX;
199     if (!res) {
200         DHLOGE("The key %s in jsonObj is invalid.", key.c_str());
201     }
202     return res;
203 }
204 
IsArray(const nlohmann::json & jsonObj,const std::string & key)205 bool IsArray(const nlohmann::json &jsonObj, const std::string &key)
206 {
207     bool res = jsonObj.contains(key) && jsonObj[key].is_array();
208     if (!res) {
209         DHLOGE("The key %s in jsonObj is invalid.", key.c_str());
210     }
211     return res;
212 }
213 
GetNodeDesc(std::string parameters)214 std::string GetNodeDesc(std::string parameters)
215 {
216     nlohmann::json parObj = nlohmann::json::parse(parameters, nullptr, false);
217     if (parObj.is_discarded()) {
218         DHLOGE("parObj parse failed!");
219         return "";
220     }
221     std::string nodeName = "N/A";
222     std::string physicalPath = "N/A";
223     int32_t classes = -1;
224 
225     if (IsString(parObj, DEVICE_NAME) && IsString(parObj, PHYSICAL_PATH) && IsInt32(parObj, CLASSES)) {
226         nodeName = parObj.at(DEVICE_NAME).get<std::string>();
227         physicalPath = parObj.at(PHYSICAL_PATH).get<std::string>();
228         classes = parObj.at(CLASSES).get<int32_t>();
229     }
230 
231     return "{ nodeName: " + nodeName + ", physicalPath: " + physicalPath + ", classes: " +
232         std::to_string(classes) + " }";
233 }
234 
GetAnonyString(const std::string & value)235 std::string GetAnonyString(const std::string &value)
236 {
237     std::string res;
238     std::string tmpStr("******");
239     size_t strLen = value.length();
240     if (strLen < INT32_MIN_ID_LENGTH) {
241         return tmpStr;
242     }
243 
244     if (strLen <= INT32_SHORT_ID_LENGTH) {
245         res += value[0];
246         res += tmpStr;
247         res += value[strLen - 1];
248     } else {
249         res.append(value, 0, INT32_PLAINTEXT_LENGTH);
250         res += tmpStr;
251         res.append(value, strLen - INT32_PLAINTEXT_LENGTH, INT32_PLAINTEXT_LENGTH);
252     }
253 
254     return res;
255 }
256 
GetAnonyInt32(const int32_t value)257 std::string GetAnonyInt32(const int32_t value)
258 {
259     char tempBuffer[INT32_STRING_LENGTH] = "";
260     int32_t secRet = sprintf_s(tempBuffer, INT32_STRING_LENGTH, "%d", value);
261     if (secRet <= 0) {
262         std::string nullString("");
263         return nullString;
264     }
265     size_t length = strlen(tempBuffer);
266     for (size_t i = 1; i <= length - 1; i++) {
267         tempBuffer[i] = '*';
268     }
269     if (length == 0x01) {
270         tempBuffer[0] = '*';
271     }
272 
273     std::string tempString(tempBuffer);
274     return tempString;
275 }
276 
Sha256(const std::string & in)277 std::string Sha256(const std::string &in)
278 {
279     unsigned char out[SHA256_DIGEST_LENGTH * HEX_TO_UINT8 + 1] = {0};
280     SHA256_CTX ctx;
281     SHA256_Init(&ctx);
282     SHA256_Update(&ctx, in.data(), in.size());
283     SHA256_Final(&out[SHA256_DIGEST_LENGTH], &ctx);
284     // here we translate sha256 hash to hexadecimal. each 8-bit char will be presented by two characters([0-9a-f])
285     const char* hexCode = "0123456789abcdef";
286     for (int32_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
287         unsigned char value = out[SHA256_DIGEST_LENGTH + i];
288         // uint8_t is 2 digits in hexadecimal.
289         out[i * DOUBLE_TIMES] = hexCode[(value >> WIDTH) & MASK];
290         out[i * DOUBLE_TIMES + 1] = hexCode[value & MASK];
291     }
292     out[SHA256_DIGEST_LENGTH * DOUBLE_TIMES] = 0;
293     return reinterpret_cast<char*>(out);
294 }
295 
CloseFd(int & fd)296 void CloseFd(int &fd)
297 {
298     if (fd < 0) {
299         DHLOGE("No fd need to beclosed.");
300         return;
301     }
302     close(fd);
303     fd = UN_INIT_FD_VALUE;
304 }
305 
BitIsSet(const unsigned long * array,int bit)306 int BitIsSet(const unsigned long *array, int bit)
307 {
308     return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS)));
309 }
310 
StringSplitToVector(const std::string & str,const char split,std::vector<std::string> & vecStr)311 void StringSplitToVector(const std::string &str, const char split, std::vector<std::string> &vecStr)
312 {
313     if (str.empty()) {
314         DHLOGE("StringSplitToVector param str is error.");
315         return;
316     }
317     std::string strTmp = str + split;
318     size_t pos = strTmp.find(split);
319     while (pos != strTmp.npos) {
320         std::string matchTmp = strTmp.substr(0, pos);
321         vecStr.push_back(matchTmp);
322         strTmp = strTmp.substr(pos + 1, strTmp.size());
323         pos = strTmp.find(split);
324     }
325 }
326 
OpenInputDeviceFdByPath(const std::string & devicePath)327 int OpenInputDeviceFdByPath(const std::string &devicePath)
328 {
329     chmod(devicePath.c_str(), S_IWRITE | S_IREAD);
330     char canonicalDevicePath[PATH_MAX] = {0x00};
331     if (devicePath.length() == 0 || devicePath.length() >= PATH_MAX ||
332         realpath(devicePath.c_str(), canonicalDevicePath) == nullptr) {
333         DHLOGE("path check fail, error path: %s", devicePath.c_str());
334         return -1;
335     }
336     struct stat s;
337     if ((stat(canonicalDevicePath, &s) == 0) && (s.st_mode & S_IFDIR)) {
338         DHLOGI("path: %s is a dir.", devicePath.c_str());
339         return -1;
340     }
341     int fd = open(canonicalDevicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
342     int32_t count = 0;
343     while ((fd < 0) && (count < MAX_RETRY_COUNT)) {
344         ++count;
345         usleep(SLEEP_TIME_US);
346         fd = open(canonicalDevicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
347         DHLOGE("could not open %s, %s; retry %d\n", devicePath.c_str(), ConvertErrNo().c_str(), count);
348     }
349     if (count >= MAX_RETRY_COUNT) {
350         DHLOGE("could not open %s, %s\n", devicePath.c_str(), ConvertErrNo().c_str());
351         CloseFd(fd);
352         return -1;
353     }
354     return fd;
355 }
356 
ConvertErrNo()357 std::string ConvertErrNo()
358 {
359     char errMsg[ERROR_MSG_MAX_LEN] = {0};
360     strerror_r(errno, errMsg, ERROR_MSG_MAX_LEN);
361     std::string errNoMsg(errMsg);
362     return errNoMsg;
363 }
364 
ScanInputDevicesPath(const std::string & dirName,std::vector<std::string> & vecInputDevPath)365 void ScanInputDevicesPath(const std::string &dirName, std::vector<std::string> &vecInputDevPath)
366 {
367     DIR *dir;
368     struct dirent *de;
369     dir = opendir(dirName.c_str());
370     if (dir == nullptr) {
371         DHLOGE("error opendir /dev/input :%{public}s\n", ConvertErrNo().c_str());
372         return;
373     }
374     size_t dirNameFirstPos = 0;
375     size_t dirNameSecondPos = 1;
376     size_t dirNameThirdPos = 2;
377     while ((de = readdir(dir))) {
378         if (de->d_name[dirNameFirstPos] == '.' && (de->d_name[dirNameSecondPos] == '\0' ||
379             (de->d_name[dirNameSecondPos] == '.' && de->d_name[dirNameThirdPos] == '\0'))) {
380             continue;
381         }
382         std::string tmpDevName = dirName + "/" + std::string(de->d_name);
383         vecInputDevPath.push_back(tmpDevName);
384     }
385     closedir(dir);
386 }
387 } // namespace DistributedInput
388 } // namespace DistributedHardware
389 } // namespace OHOS