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
16 #include "b_jsonutil/b_jsonutil.h"
17
18 #include <cstring>
19 #include <chrono>
20 #include <iomanip>
21 #include <sstream>
22 #include "cJSON.h"
23
24 #include "b_error/b_error.h"
25 #include "b_resources/b_constants.h"
26 #include "filemgmt_libhilog.h"
27 #include "b_utils/b_time.h"
28
29 namespace OHOS::FileManagement::Backup {
30 using namespace std;
31 namespace {
32 const static int BUNDLE_INDEX_DEFAULT_VAL = 0;
33 const static std::string BUNDLE_INDEX_SPLICE = ":";
34 }
35
ParseBundleNameIndexStr(const std::string &bundleNameStr)36 BJsonUtil::BundleDetailInfo BJsonUtil::ParseBundleNameIndexStr(const std::string &bundleNameStr)
37 {
38 size_t hasPos = bundleNameStr.find(BUNDLE_INDEX_SPLICE);
39 BundleDetailInfo bundleDetailInfo;
40 if (hasPos == std::string::npos) {
41 bundleDetailInfo.bundleName = bundleNameStr;
42 bundleDetailInfo.bundleIndex = BUNDLE_INDEX_DEFAULT_VAL;
43 return bundleDetailInfo;
44 }
45 std::string bundleName = bundleNameStr.substr(0, hasPos);
46 if (to_string(bundleNameStr.back()) != BUNDLE_INDEX_SPLICE) {
47 std::string indexStr = bundleNameStr.substr(hasPos + 1);
48 int index = std::stoi(indexStr);
49 bundleDetailInfo.bundleIndex = index;
50 } else {
51 bundleDetailInfo.bundleIndex = BUNDLE_INDEX_DEFAULT_VAL;
52 }
53 bundleDetailInfo.bundleName = bundleName;
54 HILOGI("End parse bundle name and index, bundleName:%{public}s, index:%{public}d",
55 bundleDetailInfo.bundleName.c_str(), bundleDetailInfo.bundleIndex);
56 return bundleDetailInfo;
57 }
58
BuildBundleInfos( const std::vector<std::string> &bundleNames, const std::vector<std::string> &bundleInfos, std::vector<std::string> &bundleNamesOnly, int32_t userId, std::map<std::string, bool> &isClearDataFlags)59 std::map<std::string, std::vector<BJsonUtil::BundleDetailInfo>> BJsonUtil::BuildBundleInfos(
60 const std::vector<std::string> &bundleNames, const std::vector<std::string> &bundleInfos,
61 std::vector<std::string> &bundleNamesOnly, int32_t userId,
62 std::map<std::string, bool> &isClearDataFlags)
63 {
64 std::map<std::string, std::vector<BJsonUtil::BundleDetailInfo>> bundleNameDetailMap;
65 if (bundleNames.size() != bundleInfos.size()) {
66 HILOGE("bundleNames count is not equals bundleInfos count");
67 return bundleNameDetailMap;
68 }
69 HILOGI("Start BuildBundleInfos");
70 for (size_t i = 0; i < bundleNames.size(); i++) {
71 std::string bundleName = bundleNames[i];
72 std::vector<BJsonUtil::BundleDetailInfo> bundleDetailInfos;
73 size_t pos = bundleName.find(BUNDLE_INDEX_SPLICE);
74 if (pos == 0 || pos == (bundleName.size() - 1)) {
75 HILOGE("Current bundle name is wrong");
76 continue;
77 }
78 std::string bundleNameOnly;
79 int bundleIndex;
80 if (pos == std::string::npos) {
81 bundleNameOnly = bundleName;
82 bundleIndex = BUNDLE_INDEX_DEFAULT_VAL;
83 bundleNamesOnly.emplace_back(bundleName);
84 } else {
85 std::string bundleNameSplit = bundleName.substr(0, pos);
86 if (to_string(bundleName.back()) != BUNDLE_INDEX_SPLICE) {
87 std::string indexSplit = bundleName.substr(pos + 1);
88 int index = std::stoi(indexSplit);
89 bundleIndex = index;
90 } else {
91 bundleIndex = BUNDLE_INDEX_DEFAULT_VAL;
92 }
93 bundleNameOnly = bundleNameSplit;
94 bundleNamesOnly.emplace_back(bundleNameSplit);
95 }
96 std::string bundleInfo = bundleInfos[i];
97 bool isClearData = true;
98 BJsonUtil::BundleDetailInfo bundleDetailInfo;
99 bundleDetailInfo.bundleName = bundleNameOnly;
100 bundleDetailInfo.bundleIndex = bundleIndex;
101 bundleDetailInfo.userId = userId;
102 ParseBundleInfoJson(bundleInfo, bundleDetailInfos, bundleDetailInfo, isClearData, userId);
103 isClearDataFlags[bundleName] = isClearData;
104 bundleNameDetailMap[bundleName] = bundleDetailInfos;
105 }
106 HILOGI("End BuildBundleInfos");
107 return bundleNameDetailMap;
108 }
109
110 // 传递的bundleinfo不包含unicast字段时 需要拼接unicast字段
AddUnicastInfo(std::string &bundleInfo)111 static bool AddUnicastInfo(std::string &bundleInfo)
112 {
113 cJSON *root = cJSON_Parse(bundleInfo.c_str());
114 if (root == nullptr) {
115 HILOGE("Parse json error,root is null");
116 return false;
117 }
118 cJSON *info = cJSON_CreateObject();
119 if (info == nullptr) {
120 cJSON_Delete(root);
121 return false;
122 }
123 cJSON_AddStringToObject(info, "type", "unicast");
124 cJSON *details = cJSON_CreateArray();
125 if (details == nullptr) {
126 cJSON_Delete(root);
127 cJSON_Delete(info);
128 return false;
129 }
130 cJSON_AddItemToArray(details, {});
131 cJSON_AddItemToObject(info, "details", details);
132 cJSON *infos = cJSON_GetObjectItem(root, "infos");
133 if (infos == nullptr || !cJSON_IsArray(infos)) {
134 cJSON_Delete(root);
135 cJSON_Delete(info);
136 return false;
137 }
138 cJSON_AddItemToArray(infos, info);
139 char *jsonStr = cJSON_Print(root);
140 if (jsonStr == nullptr) {
141 cJSON_Delete(root);
142 return false;
143 }
144 bundleInfo = string(jsonStr);
145 cJSON_Delete(root);
146 free(jsonStr);
147 return true;
148 }
149
HasUnicastInfo(std::string &bundleInfo)150 bool BJsonUtil::HasUnicastInfo(std::string &bundleInfo)
151 {
152 cJSON *root = cJSON_Parse(bundleInfo.c_str());
153 if (root == nullptr) {
154 HILOGE("Parse json error,root is null");
155 return false;
156 }
157 cJSON *infos = cJSON_GetObjectItem(root, "infos");
158 if (infos == nullptr || !cJSON_IsArray(infos) || cJSON_GetArraySize(infos) == 0) {
159 HILOGE("Parse json error, infos is not array");
160 cJSON_Delete(root);
161 return false;
162 }
163 int infosCount = cJSON_GetArraySize(infos);
164 for (int i = 0; i < infosCount; i++) {
165 cJSON *infoItem = cJSON_GetArrayItem(infos, i);
166 if (!cJSON_IsObject(infoItem)) {
167 HILOGE("Parse json error, info item is not an object");
168 continue;
169 }
170 cJSON *type = cJSON_GetObjectItem(infoItem, "type");
171 if (type == nullptr || !cJSON_IsString(type) || (type->valuestring == nullptr)) {
172 HILOGE("Parse json type element error");
173 continue;
174 }
175 if (string(type->valuestring).compare(BConstants::UNICAST_TYPE) == 0) {
176 cJSON_Delete(root);
177 return true;
178 }
179 }
180 cJSON_Delete(root);
181 return false;
182 }
183
InsertBundleDetailInfo(cJSON *infos, int infosCount, std::vector<BJsonUtil::BundleDetailInfo> &bundleDetails, BJsonUtil::BundleDetailInfo bundleDetailInfo, int32_t userId)184 static void InsertBundleDetailInfo(cJSON *infos, int infosCount,
185 std::vector<BJsonUtil::BundleDetailInfo> &bundleDetails,
186 BJsonUtil::BundleDetailInfo bundleDetailInfo,
187 int32_t userId)
188 {
189 for (int i = 0; i < infosCount; i++) {
190 cJSON *infoItem = cJSON_GetArrayItem(infos, i);
191 if (!cJSON_IsObject(infoItem)) {
192 HILOGE("Parse json error, info item is not an object");
193 return;
194 }
195 cJSON *type = cJSON_GetObjectItem(infoItem, "type");
196 if (type == nullptr || !cJSON_IsString(type) || (type->valuestring == nullptr)) {
197 HILOGE("Parse json type element error");
198 return;
199 }
200 bundleDetailInfo.type = type->valuestring;
201 cJSON *details = cJSON_GetObjectItem(infoItem, "details");
202 if (details == nullptr || !cJSON_IsArray(details)) {
203 HILOGE("Parse json details element error");
204 return;
205 }
206 if (bundleDetailInfo.type.compare(BConstants::UNICAST_TYPE) == 0) {
207 cJSON *detail = cJSON_CreateObject();
208 if (detail == nullptr) {
209 HILOGE("creat json error");
210 return;
211 }
212 string userIdstr = to_string(userId);
213 const char *const zeroUserId = userIdstr.c_str();
214 cJSON_AddStringToObject(detail, "type", "userId");
215 cJSON_AddStringToObject(detail, "detail", zeroUserId);
216 cJSON_AddItemToArray(details, detail);
217 }
218 char *detailInfos = cJSON_Print(details);
219 bundleDetailInfo.detail = std::string(detailInfos);
220 bundleDetails.emplace_back(bundleDetailInfo);
221 cJSON_free(detailInfos);
222 }
223 }
224
ParseBundleInfoJson(const std::string &bundleInfo, std::vector<BundleDetailInfo> &bundleDetails, BJsonUtil::BundleDetailInfo bundleDetailInfo, bool &isClearData, int32_t userId)225 void BJsonUtil::ParseBundleInfoJson(const std::string &bundleInfo, std::vector<BundleDetailInfo> &bundleDetails,
226 BJsonUtil::BundleDetailInfo bundleDetailInfo, bool &isClearData, int32_t userId)
227 {
228 string bundleInfoCopy = move(bundleInfo);
229 if (!HasUnicastInfo(bundleInfoCopy)) {
230 if (!AddUnicastInfo(bundleInfoCopy)) {
231 HILOGE("AddUnicastInfo failed");
232 return;
233 }
234 }
235 cJSON *root = cJSON_Parse(bundleInfoCopy.c_str());
236 if (root == nullptr) {
237 HILOGE("Parse json error,root is null");
238 return;
239 }
240 cJSON *clearBackupData = cJSON_GetObjectItem(root, "clearBackupData");
241 if (clearBackupData == nullptr || !cJSON_IsString(clearBackupData) || (clearBackupData->valuestring == nullptr)) {
242 HILOGE("Parse json error.");
243 } else {
244 std::string value = clearBackupData->valuestring;
245 isClearData = value.compare("false") != 0;
246 HILOGI("bundleName:%{public}s clear data falg:%{public}d", bundleDetailInfo.bundleName.c_str(), isClearData);
247 }
248 cJSON *infos = cJSON_GetObjectItem(root, "infos");
249 if (infos == nullptr || !cJSON_IsArray(infos) || cJSON_GetArraySize(infos) == 0) {
250 HILOGE("Parse json error, infos is not array");
251 cJSON_Delete(root);
252 return;
253 }
254 int infosCount = cJSON_GetArraySize(infos);
255 InsertBundleDetailInfo(infos, infosCount, bundleDetails, bundleDetailInfo, userId);
256 cJSON_Delete(root);
257 }
258
FindBundleInfoByName(std::map<std::string, std::vector<BundleDetailInfo>> &bundleNameDetailsMap, std::string &bundleName, const std::string &jobType, BundleDetailInfo &bundleDetail)259 bool BJsonUtil::FindBundleInfoByName(std::map<std::string, std::vector<BundleDetailInfo>> &bundleNameDetailsMap,
260 std::string &bundleName, const std::string &jobType, BundleDetailInfo &bundleDetail)
261 {
262 auto iter = bundleNameDetailsMap.find(bundleName);
263 if (iter == bundleNameDetailsMap.end()) {
264 return false;
265 }
266 std::vector<BJsonUtil::BundleDetailInfo> bundleDetailInfos = iter->second;
267 for (auto &bundleDetailInfo : bundleDetailInfos) {
268 if (bundleDetailInfo.type == jobType) {
269 bundleDetail = bundleDetailInfo;
270 return true;
271 }
272 }
273 return false;
274 }
275
BuildExtensionErrInfo(std::string &jsonStr, int errCode, std::string errMsg)276 bool BJsonUtil::BuildExtensionErrInfo(std::string &jsonStr, int errCode, std::string errMsg)
277 {
278 cJSON *info = cJSON_CreateObject();
279 if (info == nullptr) {
280 return false;
281 }
282
283 cJSON *errInfo = cJSON_CreateObject();
284 if (errInfo == nullptr) {
285 cJSON_Delete(info);
286 return false;
287 }
288 cJSON_AddNumberToObject(errInfo, "errorCode", errCode);
289 cJSON_AddStringToObject(errInfo, "errorInfo", errMsg.c_str());
290 cJSON_AddStringToObject(errInfo, "type", "ErrorInfo");
291
292 cJSON_AddItemToObject(info, "resultInfo", errInfo);
293
294 char *data = cJSON_Print(info);
295 if (data == nullptr) {
296 cJSON_Delete(info);
297 return false;
298 }
299 jsonStr = std::string(data);
300 cJSON_Delete(info);
301 cJSON_free(data);
302 return true;
303 }
304
BuildExtensionErrInfo(std::string &jsonStr, std::map<std::string, std::vector<int>> errFileInfo)305 bool BJsonUtil::BuildExtensionErrInfo(std::string &jsonStr, std::map<std::string, std::vector<int>> errFileInfo)
306 {
307 cJSON *errJson = cJSON_CreateObject();
308 if (errJson == nullptr) {
309 HILOGE("Creat json failed");
310 return false;
311 }
312 cJSON *arrJson = cJSON_CreateArray();
313 if (arrJson == nullptr) {
314 cJSON_Delete(errJson);
315 return false;
316 }
317 for (const auto &it : errFileInfo) {
318 for (const auto &codeIt : it.second) {
319 cJSON *eleJson = cJSON_CreateObject();
320 if (eleJson == nullptr) {
321 HILOGE("Creat eleJson failed");
322 continue;
323 }
324 cJSON_AddStringToObject(eleJson, "type", "ErrorInfo");
325 cJSON_AddStringToObject(eleJson, "errorInfo", it.first.c_str());
326 cJSON_AddNumberToObject(eleJson, "errorCode", codeIt);
327 cJSON_AddItemToArray(arrJson, eleJson);
328 }
329 }
330 cJSON_AddItemToObject(errJson, "resultInfo", arrJson);
331 char *data = cJSON_Print(errJson);
332 if (data == nullptr) {
333 cJSON_Delete(errJson);
334 return false;
335 }
336 jsonStr = std::string(data);
337 cJSON_Delete(errJson);
338 cJSON_free(data);
339 return true;
340 }
341
BuildOnProcessRetInfo(std::string &jsonStr, std::string onProcessRet)342 bool BJsonUtil::BuildOnProcessRetInfo(std::string &jsonStr, std::string onProcessRet)
343 {
344 cJSON *info = cJSON_CreateObject();
345 if (info == nullptr) {
346 return false;
347 }
348 cJSON *processInfo = cJSON_CreateObject();
349 if (processInfo == nullptr) {
350 cJSON_Delete(info);
351 return false;
352 }
353 std::string timeInfo = std::to_string(TimeUtils::GetTimeS());
354 cJSON_AddStringToObject(processInfo, "timeInfo", timeInfo.c_str());
355 cJSON_AddStringToObject(processInfo, "resultInfo", onProcessRet.c_str());
356 cJSON_AddItemToObject(info, "processResult", processInfo);
357 char *data = cJSON_Print(info);
358 if (data == nullptr) {
359 cJSON_Delete(info);
360 return false;
361 }
362 jsonStr = std::string(data);
363 cJSON_Delete(info);
364 cJSON_free(data);
365 return true;
366 }
367
BuildBundleNameIndexInfo(const std::string &bundleName, int appIndex)368 std::string BJsonUtil::BuildBundleNameIndexInfo(const std::string &bundleName, int appIndex)
369 {
370 std::string result = bundleName;
371 if (appIndex == BUNDLE_INDEX_DEFAULT_VAL) {
372 return result;
373 }
374 result += BUNDLE_INDEX_SPLICE;
375 result += std::to_string(appIndex);
376 return result;
377 }
378
BuildOnProcessErrInfo(std::string &reportInfo, std::string path, int err)379 bool BJsonUtil::BuildOnProcessErrInfo(std::string &reportInfo, std::string path, int err)
380 {
381 cJSON *info = cJSON_CreateObject();
382 if (info == nullptr) {
383 return false;
384 }
385 cJSON *item = cJSON_CreateObject();
386 if (item == nullptr) {
387 cJSON_Delete(info);
388 return false;
389 }
390 cJSON *errInfoJs = cJSON_CreateObject();
391 if (errInfoJs == nullptr) {
392 cJSON_Delete(info);
393 cJSON_Delete(item);
394 return false;
395 }
396 std::string errStr = std::to_string(err);
397 std::string timeInfo = std::to_string(TimeUtils::GetTimeS());
398 cJSON_AddStringToObject(errInfoJs, "errorCode", errStr.c_str());
399 cJSON_AddStringToObject(errInfoJs, "errorMessage", path.c_str());
400 cJSON_AddStringToObject(item, "timeInfo", timeInfo.c_str());
401 cJSON_AddItemToObject(item, "errorInfo", errInfoJs);
402 cJSON_AddItemToObject(info, "processResult", item);
403 char *data = cJSON_Print(info);
404 if (data == nullptr) {
405 cJSON_Delete(info);
406 return false;
407 }
408 reportInfo = std::string(data);
409 cJSON_Delete(info);
410 cJSON_free(data);
411 return true;
412 }
413
BuildBundleInfoJson(int32_t userId, string &detailInfo)414 bool BJsonUtil::BuildBundleInfoJson(int32_t userId, string &detailInfo)
415 {
416 cJSON *infos = cJSON_CreateArray();
417 if (infos == nullptr) {
418 return false;
419 }
420 cJSON *info = cJSON_CreateObject();
421 if (info == nullptr) {
422 cJSON_Delete(infos);
423 return false;
424 }
425 string userIdstr = to_string(userId);
426 const char *const zeroUserId = userIdstr.c_str();
427 cJSON_AddStringToObject(info, "type", "userId");
428 cJSON_AddStringToObject(info, "detail", zeroUserId);
429 cJSON_AddItemToArray(infos, info);
430 char *jsonStr = cJSON_Print(infos);
431 if (jsonStr == nullptr) {
432 cJSON_Delete(infos);
433 return false;
434 }
435 detailInfo = string(jsonStr);
436 cJSON_Delete(infos);
437 free(jsonStr);
438 return true;
439 }
440 }