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 "b_json/b_json_entity_extension_config.h"
17 
18 #include <any>
19 #include <fcntl.h>
20 #include <string_view>
21 #include <sys/types.h>
22 #include <unistd.h>
23 
24 #include "b_error/b_error.h"
25 #include "b_filesystem/b_file.h"
26 #include "b_ohos/startup/backup_para.h"
27 #include "b_resources/b_constants.h"
28 #include "filemgmt_libhilog.h"
29 
30 namespace OHOS::FileManagement::Backup {
31 using namespace std;
32 
GetIncludes() const33 vector<string> BJsonEntityExtensionConfig::GetIncludes() const
34 {
35     if (!obj_) {
36         HILOGE("Uninitialized JSon Object reference");
37         return {BConstants::PATHES_TO_BACKUP.begin(), BConstants::PATHES_TO_BACKUP.end()};
38     }
39     if (!obj_.isMember("includes")) {
40         HILOGE("'includes' field not found");
41         return {BConstants::PATHES_TO_BACKUP.begin(), BConstants::PATHES_TO_BACKUP.end()};
42     }
43     if (!obj_["includes"].isArray()) {
44         HILOGE("'includes' field must be an array");
45         return {BConstants::PATHES_TO_BACKUP.begin(), BConstants::PATHES_TO_BACKUP.end()};
46     }
47 
48     vector<string> dirs;
49     for (auto &&item : obj_["includes"]) {
50         if (!item.isString() || item.empty()) {
51             HILOGE("Each item of array 'includes' must be of the type string");
52             continue;
53         }
54         dirs.push_back(item.asString());
55     }
56 
57     if (dirs.empty()) {
58         dirs.emplace_back("");
59     }
60     return dirs;
61 }
62 
GetExcludes() const63 vector<string> BJsonEntityExtensionConfig::GetExcludes() const
64 {
65     if (!obj_) {
66         HILOGE("Uninitialized JSon Object reference");
67         return {};
68     }
69     if (!obj_.isMember("excludes")) {
70         HILOGD("'excludes' field not found");
71         return {};
72     }
73     if (!obj_["excludes"].isArray()) {
74         HILOGE("'excludes' field must be an array");
75         return {};
76     }
77 
78     vector<string> dirs;
79     for (auto &&item : obj_["excludes"]) {
80         if (!item.isString() || item.empty()) {
81             HILOGE("Each item of array 'excludes' must be of the type string");
82             continue;
83         }
84         dirs.push_back(item.asString());
85     }
86     return dirs;
87 }
88 
GetAllowToBackupRestore() const89 bool BJsonEntityExtensionConfig::GetAllowToBackupRestore() const
90 {
91     if (!obj_ || !obj_.isMember("allowToBackupRestore") || !obj_["allowToBackupRestore"].isBool()) {
92         HILOGD("Failed to get field allowToBackupRestore");
93         return false;
94     }
95 
96     return obj_["allowToBackupRestore"].asBool();
97 }
98 
GetFullBackupOnly() const99 bool BJsonEntityExtensionConfig::GetFullBackupOnly() const
100 {
101     if (!obj_ || !obj_.isMember("fullBackupOnly") || !obj_["fullBackupOnly"].isBool()) {
102         HILOGD("Failed to get field fullBackupOnly");
103         return false;
104     }
105 
106     return obj_["fullBackupOnly"].asBool();
107 }
108 
GetSupportScene() const109 string BJsonEntityExtensionConfig::GetSupportScene() const
110 {
111     if (!obj_ || !obj_.isMember("supportScene") || !obj_["supportScene"].isString()) {
112         HILOGD("Failed to get field supportScene");
113         return "";
114     }
115 
116     return obj_["supportScene"].asString();
117 }
118 
GetExtraInfo() const119 Json::Value BJsonEntityExtensionConfig::GetExtraInfo() const
120 {
121     if (!obj_ || !obj_.isMember("extraInfo") || !obj_["extraInfo"].isObject()) {
122         HILOGD("Failed to get field extraInfo");
123         return Json::Value();
124     }
125 
126     return obj_["extraInfo"];
127 }
128 
GetJSonSource(string_view jsonFromRealWorld,any option)129 string BJsonEntityExtensionConfig::GetJSonSource(string_view jsonFromRealWorld, any option)
130 {
131     if (!BackupPara().GetBackupDebugOverrideExtensionConfig()) {
132         return string(jsonFromRealWorld);
133     }
134 
135     /* Server for test case, the user function does not execute the following code. */
136     if (!option.has_value()) {
137         if (getuid() == static_cast<uid_t>(BConstants::BACKUP_UID)) {
138             throw BError(BError::Codes::SA_INVAL_ARG, "Current process is not extension process");
139         }
140         string jsonFilePath = string(BConstants::BACKUP_CONFIG_EXTENSION_PATH).append(BConstants::BACKUP_CONFIG_JSON);
141         UniqueFd fd(open(jsonFilePath.c_str(), O_RDONLY));
142         if (fd < 0) {
143             throw BError(BError::Codes::TOOL_INVAL_ARG, "open json file failed");
144         }
145         return BFile::ReadFile(std::move(fd)).get();
146     }
147 
148     if (getuid() != static_cast<uid_t>(BConstants::BACKUP_UID)) {
149         throw BError(BError::Codes::SA_INVAL_ARG, "Current process is not service process");
150     }
151     string bundleName;
152     try {
153         bundleName = any_cast<string>(option);
154     } catch (const bad_any_cast &e) {
155         throw BError(BError::Codes::SA_INVAL_ARG, e.what());
156     }
157     string jsonFilePath = string(BConstants::GetSaBundleBackupRootDir(BConstants::DEFAULT_USER_ID)).
158                                 append(bundleName).
159                                 append("/").
160                                 append(BConstants::BACKUP_CONFIG_JSON);
161     if (access(jsonFilePath.c_str(), F_OK) != 0) {
162         HILOGI("Failed to access jsonFilePath : %{public}s", jsonFilePath.c_str());
163         return string(jsonFromRealWorld);
164     }
165     UniqueFd fd(open(jsonFilePath.c_str(), O_RDONLY));
166     if (fd < 0) {
167         throw BError(BError::Codes::TOOL_INVAL_ARG, "open json file failed");
168     }
169     return BFile::ReadFile(std::move(fd)).get();
170 }
171 
GetRestoreDeps() const172 string BJsonEntityExtensionConfig::GetRestoreDeps() const
173 {
174     if (!obj_ || !obj_.isMember("restoreDeps") || !obj_["restoreDeps"].isString()) {
175         HILOGD("Failed to get field restoreDeps");
176         return "";
177     }
178 
179     return obj_["restoreDeps"].asString();
180 }
181 
182 } // namespace OHOS::FileManagement::Backup
183