1/*
2 * Copyright (c) 2022 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 "dm_anonymous.h"
17#include "dm_log.h"
18#include <sstream>
19namespace OHOS {
20namespace DistributedHardware {
21namespace {
22constexpr uint32_t MAX_MESSAGE_LEN = 40 * 1024 * 1024;
23constexpr uint32_t MAX_MAP_LEN = 1000;
24constexpr uint32_t MAX_INT_LEN = 20;
25}
26
27std::string GetAnonyString(const std::string &value)
28{
29    const int32_t INT32_SHORT_ID_LENGTH = 20;
30    const int32_t INT32_PLAINTEXT_LENGTH = 4;
31    const int32_t INT32_MIN_ID_LENGTH = 3;
32
33    std::string tmpStr("******");
34    size_t strLen = value.length();
35    if (strLen < INT32_MIN_ID_LENGTH) {
36        return tmpStr;
37    }
38
39    std::string res;
40    if (strLen <= INT32_SHORT_ID_LENGTH) {
41        res += value[0];
42        res += tmpStr;
43        res += value[strLen - 1];
44    } else {
45        res.append(value, 0, INT32_PLAINTEXT_LENGTH);
46        res += tmpStr;
47        res.append(value, strLen - INT32_PLAINTEXT_LENGTH, INT32_PLAINTEXT_LENGTH);
48    }
49
50    return res;
51}
52
53std::string GetAnonyInt32(const int32_t value)
54{
55    std::string tempString = std::to_string(value);
56    size_t length = tempString.length();
57    if (length == 0x01) {
58        tempString[0] = '*';
59        return tempString;
60    }
61    for (size_t i = 1; i < length - 1; i++) {
62        tempString[i] = '*';
63    }
64    return tempString;
65}
66
67bool IsNumberString(const std::string &inputString)
68{
69    LOGI("IsNumberString for DeviceManagerNapi");
70    if (inputString.length() == 0 || inputString.length() > MAX_INT_LEN) {
71        LOGE("inputString is Null or inputString length is too long");
72        return false;
73    }
74    const int32_t MIN_ASCII_NUM = 48;
75    const int32_t MAX_ASCII_NUM = 57;
76    for (size_t i = 0; i < inputString.length(); i++) {
77        int num = (int)inputString[i];
78        if (num >= MIN_ASCII_NUM && num <= MAX_ASCII_NUM) {
79            continue;
80        } else {
81            return false;
82        }
83    }
84    return true;
85}
86
87bool IsString(const nlohmann::json &jsonObj, const std::string &key)
88{
89    bool res = jsonObj.contains(key) && jsonObj[key].is_string() && jsonObj[key].size() <= MAX_MESSAGE_LEN;
90    if (!res) {
91        LOGE("the key %{public}s in jsonObj is invalid.", key.c_str());
92    }
93    return res;
94}
95
96bool IsInt32(const nlohmann::json &jsonObj, const std::string &key)
97{
98    bool res = jsonObj.contains(key) && jsonObj[key].is_number_integer() && jsonObj[key] >= INT32_MIN &&
99        jsonObj[key] <= INT32_MAX;
100    if (!res) {
101        LOGE("the key %{public}s in jsonObj is invalid.", key.c_str());
102    }
103    return res;
104}
105
106bool IsUint32(const nlohmann::json &jsonObj, const std::string &key)
107{
108    bool res = jsonObj.contains(key) && jsonObj[key].is_number_unsigned() && jsonObj[key] >= 0 &&
109        jsonObj[key] <= UINT32_MAX;
110    if (!res) {
111        LOGE("the key %{public}s in jsonObj is invalid.", key.c_str());
112    }
113    return res;
114}
115
116bool IsInt64(const nlohmann::json &jsonObj, const std::string &key)
117{
118    bool res = jsonObj.contains(key) && jsonObj[key].is_number_integer() && jsonObj[key] >= INT64_MIN &&
119        jsonObj[key] <= INT64_MAX;
120    if (!res) {
121        LOGE("the key %{public}s in jsonObj is invalid.", key.c_str());
122    }
123    return res;
124}
125
126bool IsArray(const nlohmann::json &jsonObj, const std::string &key)
127{
128    bool res = jsonObj.contains(key) && jsonObj[key].is_array();
129    if (!res) {
130        LOGE("the key %{public}s in jsonObj is invalid.", key.c_str());
131    }
132    return res;
133}
134
135bool IsBool(const nlohmann::json &jsonObj, const std::string &key)
136{
137    bool res = jsonObj.contains(key) && jsonObj[key].is_boolean();
138    if (!res) {
139        LOGE("the key %{public}s in jsonObj is invalid.", key.c_str());
140    }
141    return res;
142}
143
144std::string ConvertMapToJsonString(const std::map<std::string, std::string> &paramMap)
145{
146    std::string jsonStr = "";
147    if (paramMap.size() > MAX_MAP_LEN) {
148        LOGE("invalid paramMap");
149        return jsonStr;
150    }
151    if (!paramMap.empty()) {
152        nlohmann::json jsonObj;
153        for (const auto &it : paramMap) {
154            jsonObj[it.first] = it.second;
155        }
156        jsonStr = jsonObj.dump();
157    }
158    return jsonStr;
159}
160
161void ParseMapFromJsonString(const std::string &jsonStr, std::map<std::string, std::string> &paramMap)
162{
163    if (jsonStr.empty()) {
164        return;
165    }
166    if (paramMap.size() > MAX_MAP_LEN) {
167        LOGE("invalid paramMap");
168        return;
169    }
170    nlohmann::json paramJson = nlohmann::json::parse(jsonStr, nullptr, false);
171    if (paramJson.is_discarded()) {
172        return;
173    }
174    for (auto &element : paramJson.items()) {
175        if (element.value().is_string()) {
176            paramMap.insert(std::pair<std::string, std::string>(element.key(), element.value()));
177        }
178    }
179}
180
181bool IsInvalidPeerTargetId(const PeerTargetId &targetId)
182{
183    return targetId.deviceId.empty() && targetId.brMac.empty() && targetId.bleMac.empty() && targetId.wifiIp.empty();
184}
185
186std::string ConvertCharArray2String(const char *srcData, uint32_t srcLen)
187{
188    if (srcData == nullptr || srcLen == 0 || srcLen >= MAX_MESSAGE_LEN) {
189        LOGE("Invalid parameter.");
190        return "";
191    }
192    char *dstData = new char[srcLen + 1]();
193    if (memcpy_s(dstData, srcLen + 1, srcData, srcLen) != 0) {
194        LOGE("memcpy_s failed.");
195        delete[] dstData;
196        return "";
197    }
198    std::string temp(dstData);
199    delete[] dstData;
200    return temp;
201}
202
203int32_t StringToInt(const std::string &str, int32_t base)
204{
205    if (str.empty()) {
206        LOGE("Str is empty.");
207        return 0;
208    }
209    char *nextPtr = nullptr;
210    long result = strtol(str.c_str(), &nextPtr, base);
211    if (errno == ERANGE || *nextPtr != '\0') {
212        LOGE("parse int error");
213        return 0;
214    }
215    return static_cast<int32_t>(result);
216}
217
218int64_t StringToInt64(const std::string &str, int32_t base)
219{
220    if (str.empty()) {
221        LOGE("Str is empty.");
222        return 0;
223    }
224    char *nextPtr = nullptr;
225    int64_t result = strtoll(str.c_str(), &nextPtr, base);
226    if (errno == ERANGE || nextPtr == nullptr || nextPtr == str.c_str() || *nextPtr != '\0') {
227        LOGE("parse int error");
228        return 0;
229    }
230    return result;
231}
232
233void VersionSplitToInt(const std::string &str, const char split, std::vector<int> &numVec)
234{
235    std::istringstream iss(str);
236    std::string item = "";
237    while (getline(iss, item, split)) {
238        numVec.push_back(atoi(item.c_str()));
239    }
240}
241
242bool CompareVecNum(const std::vector<int32_t> &srcVecNum, const std::vector<int32_t> &sinkVecNum)
243{
244    for (uint32_t index = 0; index < std::min(srcVecNum.size(), sinkVecNum.size()); index++) {
245        if (srcVecNum[index] > sinkVecNum[index]) {
246            return true;
247        } else if (srcVecNum[index] < sinkVecNum[index]) {
248            return false;
249        } else {
250            continue;
251        }
252    }
253    if (srcVecNum.size() > sinkVecNum.size()) {
254        return true;
255    }
256    return false;
257}
258
259bool CompareVersion(const std::string &remoteVersion, const std::string &oldVersion)
260{
261    LOGI("remoteVersion %{public}s, oldVersion %{public}s.", remoteVersion.c_str(), oldVersion.c_str());
262    std::vector<int32_t> remoteVersionVec;
263    std::vector<int32_t> oldVersionVec;
264    VersionSplitToInt(remoteVersion, '.', remoteVersionVec);
265    VersionSplitToInt(oldVersion, '.', oldVersionVec);
266    return CompareVecNum(remoteVersionVec, oldVersionVec);
267}
268} // namespace DistributedHardware
269} // namespace OHOS