1/*
2 * Copyright (c) 2022-2024 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#include "accessibility_ability_utils.h"
16
17#include <fstream>
18
19#include "accesstoken_kit.h"
20#include "hilog_tag_wrapper.h"
21#include "nativetoken_kit.h"
22#include "token_setproc.h"
23
24using namespace OHOS::Security::AccessToken;
25
26namespace OHOS {
27namespace AAFwk {
28namespace {
29const int32_t NUM_COLUMN_WIDTH = 10;
30const int32_t BUNDLE_NAME_COLUMN_WIDTH = 50;
31const int32_t ABILITY_NAME_COLUMN_WIDTH = 30;
32const int32_t CAPABILITIES_ABBR_COLUMN_WIDTH = 20;
33const int32_t DCAPS_NUM = 0;
34const int32_t PERMS_NUM = 2;
35const int32_t ACLS_NUM = 0;
36const std::string PROCESS_NAME = "aa";
37const std::string APL_STR = "system_basic";
38} // namespace
39
40std::string AccessibilityUtils::GetStaticCapabilityNames(const Accessibility::AccessibilityAbilityInfo& abilityInfo)
41{
42    std::string capabilityNames = "";
43    std::map<uint32_t, std::string> capabilityNameMap = {
44        {0x0001, "r"}, {0x0002, "t"},
45        {0x0004, "g"}, {0x0008, "k"},
46        {0x0010, "z"},
47    };
48    for (auto it = capabilityNameMap.begin(); it != capabilityNameMap.end(); it++) {
49        if (it->first & abilityInfo.GetStaticCapabilityValues()) {
50            capabilityNames.append(it->second);
51        }
52    }
53    return capabilityNames;
54}
55
56std::string AccessibilityUtils::FormatAbilityInfos(
57    const std::vector<Accessibility::AccessibilityAbilityInfo>& installedAbilities)
58{
59    std::string result = "";
60    std::stringstream headerStream;
61    headerStream << std::left << std::setw(NUM_COLUMN_WIDTH) << "NO"
62        << std::left << std::setw(BUNDLE_NAME_COLUMN_WIDTH) << "bundleName"
63        << std::left << std::setw(ABILITY_NAME_COLUMN_WIDTH) << "abilityName"
64        << std::left << std::setw(CAPABILITIES_ABBR_COLUMN_WIDTH) << "capabilities-abbr" << std::endl;
65    result.append(headerStream.str());
66    int num = 1;
67    for (auto& ability : installedAbilities) {
68        std::stringstream lineStream;
69        std::string capabilityNames = GetStaticCapabilityNames(ability);
70        lineStream << std::left << std::setw(NUM_COLUMN_WIDTH) << std::to_string(num)
71            << std::left << std::setw(BUNDLE_NAME_COLUMN_WIDTH) << ability.GetPackageName()
72            << std::left << std::setw(ABILITY_NAME_COLUMN_WIDTH) << ability.GetName()
73            << std::left << capabilityNames << std::endl;
74        num++;
75        result.append(lineStream.str());
76    }
77    return result;
78}
79
80std::uint32_t AccessibilityUtils::GetCapabilityValue(const std::string& capabilityNames)
81{
82    uint32_t result = 0;
83    std::map<char, uint32_t> capabilityValueMap = {
84        {'r', 0x0001}, {'t', 0x0002}, {'g', 0x0004}, {'k', 0x0008}, {'z', 0x0010}
85    };
86    for (uint32_t i = 0; i < capabilityNames.size(); i++) {
87        result |= capabilityValueMap[capabilityNames[i]];
88    }
89    return result;
90}
91
92std::string AccessibilityUtils::GetInvalidCapabilityNames(const std::string& enabledCapabilityNames,
93    const std::string& installedCapabilityNames)
94{
95    std::string result = "";
96    std::set<char> installedCapabilityNameSet;
97    for (uint32_t i = 0; i < installedCapabilityNames.size(); i++) {
98        installedCapabilityNameSet.insert(installedCapabilityNames[i]);
99    }
100    for (uint32_t i = 0; i < enabledCapabilityNames.size(); i++) {
101        if (installedCapabilityNameSet.count(enabledCapabilityNames[i]) == 0) {
102            result.push_back(enabledCapabilityNames[i]);
103        }
104    }
105    return result;
106}
107
108std::string AccessibilityUtils::GetUnknownArgumentsMsg(const std::vector<std::string>& unknownArguments)
109{
110    std::string result = "";
111    for (const auto& argument : unknownArguments) {
112        result.append(argument + " ");
113    };
114    return result;
115}
116
117bool AccessibilityUtils::IsValidStateString(std::string& stateString)
118{
119    std::string valueStr = Trim(stateString);
120    if (valueStr.size() != 1) {
121        return false;
122    }
123    if (valueStr[0] == '0' || valueStr[0] == '1') {
124        return true;
125    }
126    return false;
127}
128
129bool AccessibilityUtils::IsValidIntString(std::string& intString, const int32_t lowBound, const int32_t highBound)
130{
131    int32_t value = 0;
132    const int32_t base = 10;
133    std::string valueStr = Trim(intString);
134    if (valueStr.empty()) {
135        return false;
136    }
137    bool flag = true;
138    uint32_t index = 0;
139    if (valueStr[0] == '-' || valueStr[0] == '+') {
140        index++;
141        if (valueStr[0] == '-') {
142            flag = false;
143        }
144    }
145    while (index < valueStr.size()) {
146        if (valueStr[index] >= '0' && valueStr[index] <= '9') {
147            value = value * base + valueStr[index] - '0';
148            if (value > highBound) {
149                return false;
150            }
151        } else {
152            return false;
153        }
154        index++;
155    }
156    if (!flag) {
157        value = -value;
158    }
159    return value >= lowBound;
160}
161
162std::string& AccessibilityUtils::Trim(std::string& inputStr)
163{
164    if (inputStr.empty()) {
165        return inputStr;
166    }
167    inputStr.erase(0, inputStr.find_first_not_of(" "));
168    inputStr.erase(inputStr.find_last_not_of(" ") + 1);
169    return inputStr;
170}
171
172int32_t AccessibilityUtils::AddPermission()
173{
174    const char* perms[2];
175    perms[0] = OHOS::Accessibility::OHOS_PERMISSION_READ_ACCESSIBILITY_CONFIG.c_str();
176    perms[1] = OHOS::Accessibility::OHOS_PERMISSION_WRITE_ACCESSIBILITY_CONFIG.c_str();
177    NativeTokenInfoParams infoInstance = {
178        .dcapsNum = DCAPS_NUM,
179        .permsNum = PERMS_NUM,
180        .aclsNum = ACLS_NUM,
181        .dcaps = nullptr,
182        .perms = perms,
183        .acls = nullptr,
184        .processName = PROCESS_NAME.c_str(),
185        .aplStr = APL_STR.c_str(),
186    };
187    uint64_t tokenId = GetAccessTokenId(&infoInstance);
188    if (!tokenId) {
189        TAG_LOGE(AAFwkTag::AA_TOOL, "Set token failed");
190        return -1;
191    }
192    int32_t setTokenResult = SetSelfTokenID(tokenId);
193    if (setTokenResult != 0) {
194        TAG_LOGE(AAFwkTag::AA_TOOL, "Set token failed");
195        return -1;
196    }
197    return AccessTokenKit::ReloadNativeTokenInfo();
198}
199
200}
201}