13ceed64fSopenharmony_ci/*
23ceed64fSopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
33ceed64fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43ceed64fSopenharmony_ci * you may not use this file except in compliance with the License.
53ceed64fSopenharmony_ci * You may obtain a copy of the License at
63ceed64fSopenharmony_ci *
73ceed64fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
83ceed64fSopenharmony_ci *
93ceed64fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103ceed64fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113ceed64fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123ceed64fSopenharmony_ci * See the License for the specific language governing permissions and
133ceed64fSopenharmony_ci * limitations under the License.
143ceed64fSopenharmony_ci */
153ceed64fSopenharmony_ci
163ceed64fSopenharmony_ci#include "form_util.h"
173ceed64fSopenharmony_ci
183ceed64fSopenharmony_ci#include <set>
193ceed64fSopenharmony_ci#include <thread>
203ceed64fSopenharmony_ci#include <chrono>
213ceed64fSopenharmony_ci#include <cinttypes>
223ceed64fSopenharmony_ci#include <regex>
233ceed64fSopenharmony_ci
243ceed64fSopenharmony_ci#include "accesstoken_kit.h"
253ceed64fSopenharmony_ci#include "bundle_constants.h"
263ceed64fSopenharmony_ci#include "fms_log_wrapper.h"
273ceed64fSopenharmony_ci#include "form_constants.h"
283ceed64fSopenharmony_ci#include "ipc_skeleton.h"
293ceed64fSopenharmony_ci#include "os_account_manager_wrapper.h"
303ceed64fSopenharmony_ci
313ceed64fSopenharmony_cinamespace OHOS {
323ceed64fSopenharmony_cinamespace AppExecFwk {
333ceed64fSopenharmony_cinamespace {
343ceed64fSopenharmony_ciconstexpr int64_t SEC_TO_NANOSEC = 1000000000;
353ceed64fSopenharmony_ciconstexpr int64_t SEC_TO_MILLISEC = 1000;
363ceed64fSopenharmony_ciconstexpr int64_t MILLISEC_TO_NANOSEC = 1000000;
373ceed64fSopenharmony_ciconstexpr int64_t INVALID_UDID_HASH = 0;
383ceed64fSopenharmony_ciconstexpr int32_t SYSTEM_UID = 1000;
393ceed64fSopenharmony_ciconstexpr int INT_64_LENGTH = 19;
403ceed64fSopenharmony_ciconstexpr int ZERO_VALUE = 0;
413ceed64fSopenharmony_ciconstexpr int BASE_NUMBER = 9;
423ceed64fSopenharmony_ciconstexpr int64_t HEAD_BIT_NUM = 9000000000000000000;
433ceed64fSopenharmony_ci} // namespace
443ceed64fSopenharmony_ci
453ceed64fSopenharmony_ciusing namespace std;
463ceed64fSopenharmony_ciusing namespace std::chrono;
473ceed64fSopenharmony_ci
483ceed64fSopenharmony_cistatic std::set<uint64_t> s_memFormIds;
493ceed64fSopenharmony_cistatic std::mutex s_memFormIdsMutex;
503ceed64fSopenharmony_ci
513ceed64fSopenharmony_ci/**
523ceed64fSopenharmony_ci * @brief create form id for form.
533ceed64fSopenharmony_ci * @param udidHash udid hash
543ceed64fSopenharmony_ci * @return new form id.
553ceed64fSopenharmony_ci */
563ceed64fSopenharmony_ciint64_t FormUtil::GenerateFormId(int64_t udidHash)
573ceed64fSopenharmony_ci{
583ceed64fSopenharmony_ci    set<uint64_t>::iterator it;
593ceed64fSopenharmony_ci    const int retryTimes = 5;
603ceed64fSopenharmony_ci    const int delayMs = 1;
613ceed64fSopenharmony_ci    int64_t elapsedTime = 0;
623ceed64fSopenharmony_ci    size_t elapsedHash = 0;
633ceed64fSopenharmony_ci    uint64_t unsignedUdidHash = 0;
643ceed64fSopenharmony_ci    uint64_t formId = 0;
653ceed64fSopenharmony_ci    int64_t ret = -1;
663ceed64fSopenharmony_ci    struct timespec t;
673ceed64fSopenharmony_ci    t.tv_sec = 0;
683ceed64fSopenharmony_ci    t.tv_nsec = 0;
693ceed64fSopenharmony_ci    for (int i = 0; i < retryTimes; i++) {
703ceed64fSopenharmony_ci        clock_gettime(CLOCK_REALTIME, &t);
713ceed64fSopenharmony_ci        elapsedTime = (t.tv_sec) * SEC_TO_NANOSEC + t.tv_nsec;
723ceed64fSopenharmony_ci        elapsedHash = std::hash<std::string>()(std::to_string(elapsedTime));
733ceed64fSopenharmony_ci        unsignedUdidHash = static_cast<uint64_t>(udidHash);
743ceed64fSopenharmony_ci        formId = unsignedUdidHash | (uint32_t)(elapsedHash & 0x000000007fffffffL);
753ceed64fSopenharmony_ci        ret = static_cast<int64_t>(formId);
763ceed64fSopenharmony_ci        it = s_memFormIds.find(formId);
773ceed64fSopenharmony_ci        if (it != s_memFormIds.end()) {
783ceed64fSopenharmony_ci            HILOG_INFO("repeated formId:%{public}" PRId64, ret);
793ceed64fSopenharmony_ci            std::this_thread::sleep_for(std::chrono::milliseconds(delayMs));
803ceed64fSopenharmony_ci        } else {
813ceed64fSopenharmony_ci            std::lock_guard<std::mutex> lock(s_memFormIdsMutex);
823ceed64fSopenharmony_ci            s_memFormIds.insert(formId);
833ceed64fSopenharmony_ci            break;
843ceed64fSopenharmony_ci        }
853ceed64fSopenharmony_ci    }
863ceed64fSopenharmony_ci    HILOG_INFO("generate elapsed hash %{public}zu, formId:%{public}" PRId64, elapsedHash, ret);
873ceed64fSopenharmony_ci    return ret;
883ceed64fSopenharmony_ci}
893ceed64fSopenharmony_ci
903ceed64fSopenharmony_ci/**
913ceed64fSopenharmony_ci@brief delete form id for form.
923ceed64fSopenharmony_ci@param formId The id of the form.
933ceed64fSopenharmony_ci*/
943ceed64fSopenharmony_civoid FormUtil::DeleteFormId(int64_t formId)
953ceed64fSopenharmony_ci{
963ceed64fSopenharmony_ci    std::lock_guard<std::mutex> lock(s_memFormIdsMutex);
973ceed64fSopenharmony_ci    s_memFormIds.erase(static_cast<uint64_t>(formId));
983ceed64fSopenharmony_ci}
993ceed64fSopenharmony_ci
1003ceed64fSopenharmony_ci/**
1013ceed64fSopenharmony_ci * @brief padding form id.
1023ceed64fSopenharmony_ci * @param formId The id of the form.
1033ceed64fSopenharmony_ci * @param udidHash udid hash
1043ceed64fSopenharmony_ci * @return new form id.
1053ceed64fSopenharmony_ci */
1063ceed64fSopenharmony_ciint64_t FormUtil::PaddingUdidHash(uint64_t formId, uint64_t udidHash)
1073ceed64fSopenharmony_ci{
1083ceed64fSopenharmony_ci    // Compatible with int form id.
1093ceed64fSopenharmony_ci    if ((formId & 0xffffffff00000000L) == 0) {
1103ceed64fSopenharmony_ci        return udidHash | formId;
1113ceed64fSopenharmony_ci    }
1123ceed64fSopenharmony_ci
1133ceed64fSopenharmony_ci    return formId;
1143ceed64fSopenharmony_ci}
1153ceed64fSopenharmony_ci/**
1163ceed64fSopenharmony_ci * @brief create udid hash.
1173ceed64fSopenharmony_ci * @param udidHash udid hash.
1183ceed64fSopenharmony_ci * @return Returns true on success, false on failure.
1193ceed64fSopenharmony_ci */
1203ceed64fSopenharmony_cibool FormUtil::GenerateUdidHash(int64_t &udidHash)
1213ceed64fSopenharmony_ci{
1223ceed64fSopenharmony_ci    HILOG_INFO("udidHash:%{private}s", std::to_string(udidHash).c_str());
1233ceed64fSopenharmony_ci    if (udidHash != INVALID_UDID_HASH) {
1243ceed64fSopenharmony_ci        return true;
1253ceed64fSopenharmony_ci    }
1263ceed64fSopenharmony_ci
1273ceed64fSopenharmony_ci    u_int64_t hashId = 0L;
1283ceed64fSopenharmony_ci    const int32_t thirtyTwo = 32;
1293ceed64fSopenharmony_ci    udidHash = (hashId & 0x0000000000ffffffL) << thirtyTwo;
1303ceed64fSopenharmony_ci    if (udidHash < 0) {
1313ceed64fSopenharmony_ci        udidHash = 0L;
1323ceed64fSopenharmony_ci    }
1333ceed64fSopenharmony_ci    HILOG_INFO("generate hash %{private}s", std::to_string(udidHash).c_str());
1343ceed64fSopenharmony_ci    return true;
1353ceed64fSopenharmony_ci}
1363ceed64fSopenharmony_ci/**
1373ceed64fSopenharmony_ci * @brief Get current system nanosecond.
1383ceed64fSopenharmony_ci * @return Current system nanosecond.
1393ceed64fSopenharmony_ci */
1403ceed64fSopenharmony_ciint64_t FormUtil::GetCurrentNanosecond()
1413ceed64fSopenharmony_ci{
1423ceed64fSopenharmony_ci    struct timespec ts;
1433ceed64fSopenharmony_ci    ts.tv_sec = 0;
1443ceed64fSopenharmony_ci    ts.tv_nsec = 0;
1453ceed64fSopenharmony_ci    clock_gettime(CLOCK_MONOTONIC, &ts);
1463ceed64fSopenharmony_ci    return (ts.tv_sec * SEC_TO_NANOSEC + ts.tv_nsec);
1473ceed64fSopenharmony_ci}
1483ceed64fSopenharmony_ci/**
1493ceed64fSopenharmony_ci * @brief Get current system millisecond.
1503ceed64fSopenharmony_ci * @return Current system millisecond.
1513ceed64fSopenharmony_ci */
1523ceed64fSopenharmony_ciint64_t FormUtil::GetCurrentMillisecond()
1533ceed64fSopenharmony_ci{
1543ceed64fSopenharmony_ci    struct timespec ts;
1553ceed64fSopenharmony_ci    clock_gettime(CLOCK_REALTIME, &ts);
1563ceed64fSopenharmony_ci    return (ts.tv_sec * SEC_TO_MILLISEC + ts.tv_nsec / MILLISEC_TO_NANOSEC);
1573ceed64fSopenharmony_ci}
1583ceed64fSopenharmony_ci
1593ceed64fSopenharmony_ciint64_t FormUtil::GetCurrentSteadyClockMillseconds()
1603ceed64fSopenharmony_ci{
1613ceed64fSopenharmony_ci    return std::chrono::duration_cast<std::chrono::milliseconds>(
1623ceed64fSopenharmony_ci        std::chrono::steady_clock::now().time_since_epoch()).count();
1633ceed64fSopenharmony_ci}
1643ceed64fSopenharmony_ci
1653ceed64fSopenharmony_ciint64_t FormUtil::GetNowMillisecond()
1663ceed64fSopenharmony_ci{
1673ceed64fSopenharmony_ci    system_clock::time_point pointTime = system_clock::now();
1683ceed64fSopenharmony_ci    auto timeMilliseconds = chrono::duration_cast<chrono::milliseconds>(pointTime.time_since_epoch());
1693ceed64fSopenharmony_ci    return timeMilliseconds.count();
1703ceed64fSopenharmony_ci}
1713ceed64fSopenharmony_ci
1723ceed64fSopenharmony_ci/**
1733ceed64fSopenharmony_ci * @brief Get millisecond from tm.
1743ceed64fSopenharmony_ci * @param tmAtTime tm time.
1753ceed64fSopenharmony_ci * @return Millisecond.
1763ceed64fSopenharmony_ci */
1773ceed64fSopenharmony_ciint64_t FormUtil::GetMillisecondFromTm(struct tm &tmAtTime)
1783ceed64fSopenharmony_ci{
1793ceed64fSopenharmony_ci    time_t inputTime = mktime(&tmAtTime);
1803ceed64fSopenharmony_ci    if (inputTime == -1) {
1813ceed64fSopenharmony_ci        HILOG_ERROR("mktime failed");
1823ceed64fSopenharmony_ci        return -1;
1833ceed64fSopenharmony_ci    }
1843ceed64fSopenharmony_ci    system_clock::time_point pointTime = system_clock::from_time_t(inputTime);
1853ceed64fSopenharmony_ci    auto timeMilliseconds = chrono::duration_cast<chrono::milliseconds>(pointTime.time_since_epoch());
1863ceed64fSopenharmony_ci    return timeMilliseconds.count();
1873ceed64fSopenharmony_ci}
1883ceed64fSopenharmony_ci
1893ceed64fSopenharmony_ci/**
1903ceed64fSopenharmony_ci* @brief split string.
1913ceed64fSopenharmony_ci * @param in string.
1923ceed64fSopenharmony_ci * @param delim delimiter.
1933ceed64fSopenharmony_ci * @return string list.
1943ceed64fSopenharmony_ci */
1953ceed64fSopenharmony_cistd::vector<std::string> FormUtil::StringSplit(const std::string &in, const std::string &delim)
1963ceed64fSopenharmony_ci{
1973ceed64fSopenharmony_ci    std::regex reg { delim };
1983ceed64fSopenharmony_ci    return std::vector<std::string> {
1993ceed64fSopenharmony_ci        std::sregex_token_iterator(in.begin(), in.end(), reg, -1),
2003ceed64fSopenharmony_ci        std::sregex_token_iterator()
2013ceed64fSopenharmony_ci    };
2023ceed64fSopenharmony_ci}
2033ceed64fSopenharmony_ci
2043ceed64fSopenharmony_ci/**
2053ceed64fSopenharmony_ci * @brief get current active account id.
2063ceed64fSopenharmony_ci * @return int current active account id.
2073ceed64fSopenharmony_ci */
2083ceed64fSopenharmony_ciint FormUtil::GetCurrentAccountId()
2093ceed64fSopenharmony_ci{
2103ceed64fSopenharmony_ci    std::vector<int32_t> activeList;
2113ceed64fSopenharmony_ci    ErrCode errCode = DelayedSingleton<OsAccountManagerWrapper>::GetInstance()->QueryActiveOsAccountIds(activeList);
2123ceed64fSopenharmony_ci    if (errCode != ERR_OK) {
2133ceed64fSopenharmony_ci        HILOG_ERROR("QueryActiveOsAccountIds failed");
2143ceed64fSopenharmony_ci        return Constants::ANY_USERID;
2153ceed64fSopenharmony_ci    }
2163ceed64fSopenharmony_ci    if (activeList.empty()) {
2173ceed64fSopenharmony_ci        HILOG_ERROR("empty QueryActiveOsAccountIds,no accounts");
2183ceed64fSopenharmony_ci        return Constants::ANY_USERID;
2193ceed64fSopenharmony_ci    }
2203ceed64fSopenharmony_ci
2213ceed64fSopenharmony_ci    return activeList.front();
2223ceed64fSopenharmony_ci}
2233ceed64fSopenharmony_ci
2243ceed64fSopenharmony_cibool FormUtil::IsSACall()
2253ceed64fSopenharmony_ci{
2263ceed64fSopenharmony_ci    auto callerToken = IPCSkeleton::GetCallingTokenID();
2273ceed64fSopenharmony_ci    HILOG_DEBUG("callerToken : %{private}u", callerToken);
2283ceed64fSopenharmony_ci
2293ceed64fSopenharmony_ci    auto tokenType = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(callerToken);
2303ceed64fSopenharmony_ci    if (tokenType == Security::AccessToken::ATokenTypeEnum::TOKEN_NATIVE) {
2313ceed64fSopenharmony_ci        HILOG_DEBUG("caller tokenType is native, verify success");
2323ceed64fSopenharmony_ci        return true;
2333ceed64fSopenharmony_ci    }
2343ceed64fSopenharmony_ci
2353ceed64fSopenharmony_ci    if (IPCSkeleton::GetCallingUid() == SYSTEM_UID) {
2363ceed64fSopenharmony_ci        HILOG_DEBUG("callingUid is native,verify success");
2373ceed64fSopenharmony_ci        return true;
2383ceed64fSopenharmony_ci    }
2393ceed64fSopenharmony_ci
2403ceed64fSopenharmony_ci    HILOG_DEBUG("call");
2413ceed64fSopenharmony_ci    return false;
2423ceed64fSopenharmony_ci}
2433ceed64fSopenharmony_ci
2443ceed64fSopenharmony_cibool FormUtil::VerifyCallingPermission(const std::string &permissionName)
2453ceed64fSopenharmony_ci{
2463ceed64fSopenharmony_ci    HILOG_DEBUG("call.permission name is:%{public}s", permissionName.c_str());
2473ceed64fSopenharmony_ci    auto callerToken = IPCSkeleton::GetCallingTokenID();
2483ceed64fSopenharmony_ci    int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken, permissionName);
2493ceed64fSopenharmony_ci    if (ret == Security::AccessToken::PermissionState::PERMISSION_DENIED) {
2503ceed64fSopenharmony_ci        HILOG_ERROR("permission %{public}s: PERMISSION_DENIED", permissionName.c_str());
2513ceed64fSopenharmony_ci        return false;
2523ceed64fSopenharmony_ci    }
2533ceed64fSopenharmony_ci    HILOG_DEBUG("Verify calling permission success");
2543ceed64fSopenharmony_ci    return true;
2553ceed64fSopenharmony_ci}
2563ceed64fSopenharmony_ci
2573ceed64fSopenharmony_cibool FormUtil::ConvertStringToInt64(const std::string &strInfo, int64_t &int64Value)
2583ceed64fSopenharmony_ci{
2593ceed64fSopenharmony_ci    size_t strLength = strInfo.size();
2603ceed64fSopenharmony_ci    if (strLength == ZERO_VALUE) {
2613ceed64fSopenharmony_ci        int64Value = ZERO_VALUE;
2623ceed64fSopenharmony_ci        return true;
2633ceed64fSopenharmony_ci    }
2643ceed64fSopenharmony_ci    std::regex pattern("^0|-?[1-9][0-9]{0,18}$"); // "^-?[0-9]{1,19}$"
2653ceed64fSopenharmony_ci    std::smatch match;
2663ceed64fSopenharmony_ci    if (regex_match(strInfo, match, pattern)) {
2673ceed64fSopenharmony_ci        HILOG_DEBUG("regex_match successed");
2683ceed64fSopenharmony_ci        if (strInfo.substr(ZERO_VALUE, ZERO_VALUE + 1) != "-") { // maximum: 9223372036854775807
2693ceed64fSopenharmony_ci            if (strLength < INT_64_LENGTH) {
2703ceed64fSopenharmony_ci                int64Value = std::stoll(strInfo);
2713ceed64fSopenharmony_ci                return true;
2723ceed64fSopenharmony_ci            }
2733ceed64fSopenharmony_ci            int maxSubValue = std::stoi(strInfo.substr(ZERO_VALUE, ZERO_VALUE + 1));
2743ceed64fSopenharmony_ci            if (strLength == INT_64_LENGTH && maxSubValue < BASE_NUMBER) {
2753ceed64fSopenharmony_ci                int64Value = std::stoll(strInfo);
2763ceed64fSopenharmony_ci                return true;
2773ceed64fSopenharmony_ci            }
2783ceed64fSopenharmony_ci            // Means 0x7FFFFFFFFFFFFFFF remove the first number:(2^63 - 1 - 9 * 10 ^ 19)
2793ceed64fSopenharmony_ci            int64_t subValue = std::stoll(strInfo.substr(ZERO_VALUE + 1, INT_64_LENGTH - 1));
2803ceed64fSopenharmony_ci            if (strLength == INT_64_LENGTH && subValue <= (INT64_MAX - HEAD_BIT_NUM)) {
2813ceed64fSopenharmony_ci                int64Value = std::stoll(strInfo);
2823ceed64fSopenharmony_ci                return true;
2833ceed64fSopenharmony_ci            }
2843ceed64fSopenharmony_ci            return false;
2853ceed64fSopenharmony_ci        }
2863ceed64fSopenharmony_ci        if (strLength < INT_64_LENGTH + 1) { // The minimum value: -9223372036854775808
2873ceed64fSopenharmony_ci            int64Value = std::stoll(strInfo);
2883ceed64fSopenharmony_ci            return true;
2893ceed64fSopenharmony_ci        }
2903ceed64fSopenharmony_ci        if (strLength == INT_64_LENGTH + 1) {
2913ceed64fSopenharmony_ci            int minSubValue = std::stoi(strInfo.substr(1, 1));
2923ceed64fSopenharmony_ci            if (minSubValue < BASE_NUMBER) {
2933ceed64fSopenharmony_ci                int64Value = std::stoll(strInfo);
2943ceed64fSopenharmony_ci                return true;
2953ceed64fSopenharmony_ci            }
2963ceed64fSopenharmony_ci
2973ceed64fSopenharmony_ci            // Means 0x8000000000000000 remove the first number:-(2^63 - 9 * 10 ^ 19)
2983ceed64fSopenharmony_ci            int64_t subValue = std::stoll(strInfo.substr(ZERO_VALUE + 2, INT_64_LENGTH - 1));
2993ceed64fSopenharmony_ci            if (subValue <= (INT64_MAX - HEAD_BIT_NUM + 1)) {
3003ceed64fSopenharmony_ci                int64Value = std::stoll(strInfo);
3013ceed64fSopenharmony_ci                return true;
3023ceed64fSopenharmony_ci            }
3033ceed64fSopenharmony_ci        }
3043ceed64fSopenharmony_ci    }
3053ceed64fSopenharmony_ci    HILOG_DEBUG("regex_match failed");
3063ceed64fSopenharmony_ci    return false;
3073ceed64fSopenharmony_ci}
3083ceed64fSopenharmony_ci} // namespace AppExecFwk
3093ceed64fSopenharmony_ci} // namespace OHOS