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 "include/util.h"
17
18#include <string>
19
20#ifndef OHOS_BUILD_ENABLE_ARKUI_X
21#include <sys/prctl.h>
22#endif // OHOS_BUILD_ENABLE_ARKUI_X
23#include <sys/stat.h>
24#include <sys/syscall.h>
25#include <unistd.h>
26
27#ifndef OHOS_BUILD_ENABLE_ARKUI_X
28#include "parameters.h"
29#endif // OHOS_BUILD_ENABLE_ARKUI_X
30#include "securec.h"
31
32#include "devicestatus_define.h"
33#include "utility.h"
34
35#undef LOG_TAG
36#define LOG_TAG "Util"
37
38namespace OHOS {
39namespace Msdp {
40namespace DeviceStatus {
41namespace {
42constexpr size_t BUF_TID_SIZE { 10 };
43constexpr size_t PROGRAM_NAME_SIZE { 256 };
44constexpr size_t BUF_CMD_SIZE { 512 };
45constexpr uint32_t BASE_YEAR { 1900 };
46constexpr uint32_t BASE_MON { 1 };
47constexpr uint32_t MS_NS { 1000000 };
48constexpr int32_t FILE_SIZE_MAX { 0x5000 };
49constexpr size_t SHORT_KEY_LENGTH { 20 };
50constexpr size_t PLAINTEXT_LENGTH { 4 };
51constexpr int32_t ROTATE_POLICY_WINDOW_ROTATE { 0 };
52constexpr int32_t ROTATE_POLICY_SCREEN_ROTATE { 1 };
53constexpr int32_t ROTATE_POLICY_FOLD_MODE { 2 };
54#ifndef OHOS_BUILD_ENABLE_ARKUI_X
55const int32_t ROTATE_POLICY = OHOS::system::GetIntParameter("const.window.device.rotate_policy", 0);
56const std::string FOLD_ROTATE_POLICY = OHOS::system::GetParameter("const.window.foldabledevice.rotate_policy", "0,0");
57#endif // OHOS_BUILD_ENABLE_ARKUI_X
58const std::string SVG_PATH { "/system/etc/device_status/drag_icon/" };
59} // namespace
60
61int32_t GetPid()
62{
63    return static_cast<int32_t>(getpid());
64}
65
66static std::string GetThisThreadIdOfString()
67{
68    thread_local std::string threadLocalId;
69    if (threadLocalId.empty()) {
70        long tid = syscall(SYS_gettid);
71        char buf[BUF_TID_SIZE] = { 0 };
72        const int32_t ret = sprintf_s(buf, BUF_TID_SIZE, "%06d", tid);
73        if (ret < 0) {
74            FI_HILOGE("Call sprintf_s failed, ret:%{public}d", ret);
75            return threadLocalId;
76        }
77        buf[BUF_TID_SIZE - 1] = '\0';
78        threadLocalId = buf;
79    }
80    return threadLocalId;
81}
82
83uint64_t GetThisThreadId()
84{
85    std::string threadId = GetThisThreadIdOfString();
86    uint64_t tid = std::stoull(threadId);
87    return tid;
88}
89
90int64_t GetMillisTime()
91{
92    auto timeNow = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now());
93    auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow.time_since_epoch());
94    return tmp.count();
95}
96
97void GetTimeStamp(std::string &startTime)
98{
99    timespec curTime;
100    clock_gettime(CLOCK_REALTIME, &curTime);
101    struct tm *timeinfo = localtime(&(curTime.tv_sec));
102    CHKPV(timeinfo);
103    startTime.append(std::to_string(timeinfo->tm_year + BASE_YEAR)).append("-")
104        .append(std::to_string(timeinfo->tm_mon + BASE_MON)).append("-").append(std::to_string(timeinfo->tm_mday))
105        .append(" ").append(std::to_string(timeinfo->tm_hour)).append(":").append(std::to_string(timeinfo->tm_min))
106        .append(":").append(std::to_string(timeinfo->tm_sec)).append(".")
107        .append(std::to_string(curTime.tv_nsec / MS_NS));
108}
109
110void SetThreadName(const std::string &name)
111{
112#ifndef OHOS_BUILD_ENABLE_ARKUI_X
113    prctl(PR_SET_NAME, name.c_str());
114#endif // OHOS_BUILD_ENABLE_ARKUI_X
115}
116
117static size_t StringToken(std::string &strs, const std::string &sep, std::string &token)
118{
119    token = "";
120    if (strs.empty()) {
121        return strs.npos;
122    }
123    size_t seat = strs.npos;
124    size_t temp = 0;
125    for (auto &item : sep) {
126        temp = strs.find(item);
127        if (strs.npos != temp) {
128            seat = (std::min)(seat, temp);
129        }
130    }
131    if (strs.npos != seat) {
132        token = strs.substr(0, seat);
133        if (strs.npos != seat + 1) {
134            strs = strs.substr(seat + 1, strs.npos);
135        }
136        if (seat == 0) {
137            return StringToken(strs, sep, token);
138        }
139    } else {
140        token = strs;
141        strs = "";
142    }
143    return token.size();
144}
145
146size_t StringSplit(const std::string &str, const std::string &sep, std::vector<std::string> &vecList)
147{
148    size_t size = 0;
149    auto strs = str;
150    std::string token;
151    while (str.npos != (size = StringToken(strs, sep, token))) {
152        vecList.push_back(token);
153    }
154    return vecList.size();
155}
156
157std::string StringPrintf(const char *format, ...)
158{
159    char space[1024] { 0 };
160
161    va_list ap;
162    va_start(ap, format);
163    std::string result;
164    int32_t ret = vsnprintf_s(space, sizeof(space), sizeof(space) - 1, format, ap);
165    if (ret >= RET_OK && static_cast<size_t>(ret) < sizeof(space)) {
166        result = space;
167    } else {
168        FI_HILOGE("The buffer is overflow");
169    }
170    va_end(ap);
171    return result;
172}
173
174std::string GetAnonyString(const std::string &value)
175{
176    if (value.empty()) {
177        return "empty";
178    }
179    std::string anonyStr = "******";
180    std::string str;
181    size_t strLen = value.length();
182    if (strLen == 0) {
183        FI_HILOGE("strLen is 0, value will overflow");
184        return "empty";
185    } else if (strLen <= SHORT_KEY_LENGTH) {
186        str += value[0];
187        str += anonyStr;
188        str += value[strLen - 1];
189    } else {
190        str.append(value, 0, PLAINTEXT_LENGTH);
191        str += anonyStr;
192        str.append(value, strLen - PLAINTEXT_LENGTH, PLAINTEXT_LENGTH);
193    }
194    return str;
195}
196
197static std::string GetFileName(const std::string &path)
198{
199    size_t nPos = path.find_last_of('/');
200    if (path.npos == nPos) {
201        nPos = path.find_last_of('\\');
202    }
203    if (path.npos == nPos) {
204        return path;
205    }
206    return path.substr(nPos + 1, path.npos);
207}
208
209const char* GetProgramName()
210{
211    static char programName[PROGRAM_NAME_SIZE] = { 0 };
212    if (programName[0] != '\0') {
213        return programName;
214    }
215
216    char buf[BUF_CMD_SIZE] = { 0 };
217    int32_t ret = sprintf_s(buf, BUF_CMD_SIZE, "/proc/%d/cmdline", static_cast<int32_t>(getpid()));
218    if (ret == -1) {
219        FI_HILOGE("GetProcessInfo sprintf_s cmdline error");
220        return "";
221    }
222    FILE *fp = fopen(buf, "rb");
223    if (fp == nullptr) {
224        FI_HILOGE("The fp is nullptr, filename:%{public}s", buf);
225        return "";
226    }
227    static constexpr size_t bufLineSize = 512;
228    char bufLine[bufLineSize] = { 0 };
229    if ((fgets(bufLine, bufLineSize, fp) == nullptr)) {
230        FI_HILOGE("fgets failed");
231        if (fclose(fp) != 0) {
232            FI_HILOGW("Close file failed");
233        }
234        fp = nullptr;
235        return "";
236    }
237    if (fclose(fp) != 0) {
238        FI_HILOGW("Close file:%{public}s failed", buf);
239    }
240    fp = nullptr;
241
242    std::string tempName(bufLine);
243    tempName = GetFileName(tempName);
244    if (tempName.empty()) {
245        FI_HILOGE("tempName is empty");
246        return "";
247    }
248    size_t copySize = std::min(tempName.size(), PROGRAM_NAME_SIZE - 1);
249    if (copySize == 0) {
250        FI_HILOGE("The copySize is 0");
251        return "";
252    }
253    errno_t result = memcpy_s(programName, PROGRAM_NAME_SIZE, tempName.c_str(), copySize);
254    if (result != EOK) {
255        FI_HILOGE("memcpy_s failed");
256        return "";
257    }
258    FI_HILOGI("Get program name success, programName:%{public}s", programName);
259
260    return programName;
261}
262
263bool CheckFileExtendName(const std::string &filePath, const std::string &checkExtension)
264{
265    std::string::size_type pos = filePath.find_last_of('.');
266    if (pos == std::string::npos) {
267        FI_HILOGE("File is not found extension");
268        return false;
269    }
270    return (filePath.substr(pos + 1, filePath.npos) == checkExtension);
271}
272
273bool IsValidPath(const std::string &rootDir, const std::string &filePath)
274{
275    return (filePath.compare(0, rootDir.size(), rootDir) == 0);
276}
277
278bool IsValidSvgPath(const std::string &filePath)
279{
280    return IsValidPath(SVG_PATH, filePath);
281}
282
283bool IsValidSvgFile(const std::string &filePath)
284{
285    CALL_DEBUG_ENTER;
286    if (filePath.empty()) {
287        FI_HILOGE("FilePath is empty");
288        return false;
289    }
290    char realPath[PATH_MAX] = { 0 };
291    if (realpath(filePath.c_str(), realPath) == nullptr) {
292        FI_HILOGE("Realpath return nullptr, realPath:%{private}s", realPath);
293        return false;
294    }
295#ifndef OHOS_BUILD_ENABLE_ARKUI_X
296    if (!IsValidSvgPath(realPath)) {
297        FI_HILOGE("File path invalid");
298        return false;
299    }
300#endif // OHOS_BUILD_ENABLE_ARKUI_X
301    if (!Utility::DoesFileExist(realPath)) {
302        FI_HILOGE("File not exist");
303        return false;
304    }
305    if (!CheckFileExtendName(realPath, "svg")) {
306        FI_HILOGE("Unable to parse files other than svg format");
307        return false;
308    }
309    int32_t fileSize = Utility::GetFileSize(realPath);
310    if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
311        FI_HILOGE("File size out of read range");
312        return false;
313    }
314    return true;
315}
316
317bool IsNum(const std::string &str)
318{
319    std::istringstream sin(str);
320    double num = 0.0;
321    return (sin >> num) && sin.eof();
322}
323
324void GetRotatePolicy(bool &isScreenRotation, std::vector<std::string> &foldRotatePolicys)
325{
326#ifndef OHOS_BUILD_ENABLE_ARKUI_X
327    if (ROTATE_POLICY == ROTATE_POLICY_WINDOW_ROTATE) {
328        isScreenRotation = false;
329        return;
330    }
331    if (ROTATE_POLICY == ROTATE_POLICY_SCREEN_ROTATE) {
332        isScreenRotation = true;
333        return;
334    }
335    if (ROTATE_POLICY == ROTATE_POLICY_FOLD_MODE) {
336        isScreenRotation = false;
337        StringSplit(FOLD_ROTATE_POLICY, ",", foldRotatePolicys);
338        return;
339    }
340#endif // OHOS_BUILD_ENABLE_ARKUI_X
341}
342} // namespace DeviceStatus
343} // namespace Msdp
344} // namespace OHOS