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::atoi(indexStr.c_str());
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 if (bundleName.empty()) {
73 HILOGE("BundleName is invalid");
74 continue;
75 }
76 std::vector<BJsonUtil::BundleDetailInfo> bundleDetailInfos;
77 size_t pos = bundleName.find(BUNDLE_INDEX_SPLICE);
78 if (pos == 0 || pos == (bundleName.size() - 1)) {
79 HILOGE("Current bundle name is wrong");
80 continue;
81 }
82 std::string bundleNameOnly;
83 int bundleIndex;
84 if (pos == std::string::npos) {
85 bundleNameOnly = bundleName;
86 bundleIndex = BUNDLE_INDEX_DEFAULT_VAL;
87 bundleNamesOnly.emplace_back(bundleName);
88 } else {
89 std::string bundleNameSplit = bundleName.substr(0, pos);
90 if (to_string(bundleName.back()) != BUNDLE_INDEX_SPLICE) {
91 std::string indexSplit = bundleName.substr(pos + 1);
92 int index = std::atoi(indexSplit.c_str());
93 bundleIndex = index;
94 } else {
95 bundleIndex = BUNDLE_INDEX_DEFAULT_VAL;
96 }
97 bundleNameOnly = bundleNameSplit;
98 bundleNamesOnly.emplace_back(bundleNameSplit);
99 }
100 std::string bundleInfo = bundleInfos[i];
101 bool isClearData = true;
102 BJsonUtil::BundleDetailInfo bundleDetailInfo;
103 bundleDetailInfo.bundleName = bundleNameOnly;
104 bundleDetailInfo.bundleIndex = bundleIndex;
105 bundleDetailInfo.userId = userId;
106 ParseBundleInfoJson(bundleInfo, bundleDetailInfos, bundleDetailInfo, isClearData, userId);
107 isClearDataFlags[bundleName] = isClearData;
108 bundleNameDetailMap[bundleName] = bundleDetailInfos;
109 }
110 HILOGI("End BuildBundleInfos");
111 return bundleNameDetailMap;
112 }
113
114 // 传递的bundleinfo不包含unicast字段时 需要拼接unicast字段
AddUnicastInfo(std::string & bundleInfo)115 static bool AddUnicastInfo(std::string &bundleInfo)
116 {
117 cJSON *root = cJSON_Parse(bundleInfo.c_str());
118 if (root == nullptr) {
119 HILOGE("Parse json error,root is null");
120 return false;
121 }
122 cJSON *info = cJSON_CreateObject();
123 if (info == nullptr) {
124 cJSON_Delete(root);
125 return false;
126 }
127 cJSON_AddStringToObject(info, "type", "unicast");
128 cJSON *details = cJSON_CreateArray();
129 if (details == nullptr) {
130 cJSON_Delete(root);
131 cJSON_Delete(info);
132 return false;
133 }
134 cJSON_AddItemToArray(details, {});
135 cJSON_AddItemToObject(info, "details", details);
136 cJSON *infos = cJSON_GetObjectItem(root, "infos");
137 if (infos == nullptr || !cJSON_IsArray(infos)) {
138 cJSON_Delete(root);
139 cJSON_Delete(info);
140 return false;
141 }
142 cJSON_AddItemToArray(infos, info);
143 char *jsonStr = cJSON_Print(root);
144 if (jsonStr == nullptr) {
145 cJSON_Delete(root);
146 return false;
147 }
148 bundleInfo = string(jsonStr);
149 cJSON_Delete(root);
150 free(jsonStr);
151 return true;
152 }
153
HasUnicastInfo(std::string & bundleInfo)154 bool BJsonUtil::HasUnicastInfo(std::string &bundleInfo)
155 {
156 cJSON *root = cJSON_Parse(bundleInfo.c_str());
157 if (root == nullptr) {
158 HILOGE("Parse json error,root is null");
159 return false;
160 }
161 cJSON *infos = cJSON_GetObjectItem(root, "infos");
162 if (infos == nullptr || !cJSON_IsArray(infos) || cJSON_GetArraySize(infos) == 0) {
163 HILOGE("Parse json error, infos is not array");
164 cJSON_Delete(root);
165 return false;
166 }
167 int infosCount = cJSON_GetArraySize(infos);
168 for (int i = 0; i < infosCount; i++) {
169 cJSON *infoItem = cJSON_GetArrayItem(infos, i);
170 if (!cJSON_IsObject(infoItem)) {
171 HILOGE("Parse json error, info item is not an object");
172 continue;
173 }
174 cJSON *type = cJSON_GetObjectItem(infoItem, "type");
175 if (type == nullptr || !cJSON_IsString(type) || (type->valuestring == nullptr)) {
176 HILOGE("Parse json type element error");
177 continue;
178 }
179 if (string(type->valuestring).compare(BConstants::UNICAST_TYPE) == 0) {
180 cJSON_Delete(root);
181 return true;
182 }
183 }
184 cJSON_Delete(root);
185 return false;
186 }
187
InsertBundleDetailInfo(cJSON * infos,int infosCount,std::vector<BJsonUtil::BundleDetailInfo> & bundleDetails,BJsonUtil::BundleDetailInfo bundleDetailInfo,int32_t userId)188 static void InsertBundleDetailInfo(cJSON *infos, int infosCount,
189 std::vector<BJsonUtil::BundleDetailInfo> &bundleDetails,
190 BJsonUtil::BundleDetailInfo bundleDetailInfo,
191 int32_t userId)
192 {
193 for (int i = 0; i < infosCount; i++) {
194 cJSON *infoItem = cJSON_GetArrayItem(infos, i);
195 if (!cJSON_IsObject(infoItem)) {
196 HILOGE("Parse json error, info item is not an object");
197 return;
198 }
199 cJSON *type = cJSON_GetObjectItem(infoItem, "type");
200 if (type == nullptr || !cJSON_IsString(type) || (type->valuestring == nullptr)) {
201 HILOGE("Parse json type element error");
202 return;
203 }
204 bundleDetailInfo.type = type->valuestring;
205 cJSON *details = cJSON_GetObjectItem(infoItem, "details");
206 if (details == nullptr || !cJSON_IsArray(details)) {
207 HILOGE("Parse json details element error");
208 return;
209 }
210 if (bundleDetailInfo.type.compare(BConstants::UNICAST_TYPE) == 0) {
211 cJSON *detail = cJSON_CreateObject();
212 if (detail == nullptr) {
213 HILOGE("creat json error");
214 return;
215 }
216 string userIdstr = to_string(userId);
217 const char *const zeroUserId = userIdstr.c_str();
218 cJSON_AddStringToObject(detail, "type", "userId");
219 cJSON_AddStringToObject(detail, "detail", zeroUserId);
220 cJSON_AddItemToArray(details, detail);
221 }
222 char *detailInfos = cJSON_Print(details);
223 bundleDetailInfo.detail = std::string(detailInfos);
224 bundleDetails.emplace_back(bundleDetailInfo);
225 cJSON_free(detailInfos);
226 }
227 }
228
ParseBundleInfoJson(const std::string & bundleInfo,std::vector<BundleDetailInfo> & bundleDetails,BJsonUtil::BundleDetailInfo bundleDetailInfo,bool & isClearData,int32_t userId)229 void BJsonUtil::ParseBundleInfoJson(const std::string &bundleInfo, std::vector<BundleDetailInfo> &bundleDetails,
230 BJsonUtil::BundleDetailInfo bundleDetailInfo, bool &isClearData, int32_t userId)
231 {
232 string bundleInfoCopy = move(bundleInfo);
233 if (!HasUnicastInfo(bundleInfoCopy)) {
234 if (!AddUnicastInfo(bundleInfoCopy)) {
235 HILOGE("AddUnicastInfo failed");
236 return;
237 }
238 }
239 cJSON *root = cJSON_Parse(bundleInfoCopy.c_str());
240 if (root == nullptr) {
241 HILOGE("Parse json error,root is null");
242 return;
243 }
244 cJSON *clearBackupData = cJSON_GetObjectItem(root, "clearBackupData");
245 if (clearBackupData == nullptr || !cJSON_IsString(clearBackupData) || (clearBackupData->valuestring == nullptr)) {
246 HILOGE("Parse json error.");
247 } else {
248 std::string value = clearBackupData->valuestring;
249 isClearData = value.compare("false") != 0;
250 HILOGI("bundleName:%{public}s clear data falg:%{public}d", bundleDetailInfo.bundleName.c_str(), isClearData);
251 }
252 cJSON *infos = cJSON_GetObjectItem(root, "infos");
253 if (infos == nullptr || !cJSON_IsArray(infos) || cJSON_GetArraySize(infos) == 0) {
254 HILOGE("Parse json error, infos is not array");
255 cJSON_Delete(root);
256 return;
257 }
258 int infosCount = cJSON_GetArraySize(infos);
259 InsertBundleDetailInfo(infos, infosCount, bundleDetails, bundleDetailInfo, userId);
260 cJSON_Delete(root);
261 }
262
FindBundleInfoByName(std::map<std::string,std::vector<BundleDetailInfo>> & bundleNameDetailsMap,std::string & bundleName,const std::string & jobType,BundleDetailInfo & bundleDetail)263 bool BJsonUtil::FindBundleInfoByName(std::map<std::string, std::vector<BundleDetailInfo>> &bundleNameDetailsMap,
264 std::string &bundleName, const std::string &jobType, BundleDetailInfo &bundleDetail)
265 {
266 auto iter = bundleNameDetailsMap.find(bundleName);
267 if (iter == bundleNameDetailsMap.end()) {
268 return false;
269 }
270 std::vector<BJsonUtil::BundleDetailInfo> bundleDetailInfos = iter->second;
271 for (const auto &bundleDetailInfo : bundleDetailInfos) {
272 if (bundleDetailInfo.type == jobType) {
273 bundleDetail = bundleDetailInfo;
274 return true;
275 }
276 }
277 return false;
278 }
279
BuildExtensionErrInfo(std::string & jsonStr,int errCode,std::string errMsg)280 bool BJsonUtil::BuildExtensionErrInfo(std::string &jsonStr, int errCode, std::string errMsg)
281 {
282 cJSON *info = cJSON_CreateObject();
283 if (info == nullptr) {
284 return false;
285 }
286
287 cJSON *errInfo = cJSON_CreateObject();
288 if (errInfo == nullptr) {
289 cJSON_Delete(info);
290 return false;
291 }
292 cJSON_AddNumberToObject(errInfo, "errorCode", errCode);
293 cJSON_AddStringToObject(errInfo, "errorInfo", errMsg.c_str());
294 cJSON_AddStringToObject(errInfo, "type", "ErrorInfo");
295
296 cJSON_AddItemToObject(info, "resultInfo", errInfo);
297
298 char *data = cJSON_Print(info);
299 if (data == nullptr) {
300 cJSON_Delete(info);
301 return false;
302 }
303 jsonStr = std::string(data);
304 cJSON_Delete(info);
305 cJSON_free(data);
306 return true;
307 }
308
BuildExtensionErrInfo(std::string & jsonStr,std::map<std::string,std::vector<int>> errFileInfo)309 bool BJsonUtil::BuildExtensionErrInfo(std::string &jsonStr, std::map<std::string, std::vector<int>> errFileInfo)
310 {
311 cJSON *errJson = cJSON_CreateObject();
312 if (errJson == nullptr) {
313 HILOGE("Creat json failed");
314 return false;
315 }
316 cJSON *arrJson = cJSON_CreateArray();
317 if (arrJson == nullptr) {
318 cJSON_Delete(errJson);
319 return false;
320 }
321 for (const auto &it : errFileInfo) {
322 for (const auto &codeIt : it.second) {
323 cJSON *eleJson = cJSON_CreateObject();
324 if (eleJson == nullptr) {
325 HILOGE("Creat eleJson failed");
326 continue;
327 }
328 cJSON_AddStringToObject(eleJson, "type", "ErrorInfo");
329 cJSON_AddStringToObject(eleJson, "errorInfo", it.first.c_str());
330 cJSON_AddNumberToObject(eleJson, "errorCode", codeIt);
331 cJSON_AddItemToArray(arrJson, eleJson);
332 }
333 }
334 cJSON_AddItemToObject(errJson, "resultInfo", arrJson);
335 char *data = cJSON_Print(errJson);
336 if (data == nullptr) {
337 cJSON_Delete(errJson);
338 return false;
339 }
340 jsonStr = std::string(data);
341 cJSON_Delete(errJson);
342 cJSON_free(data);
343 return true;
344 }
345
BuildOnProcessRetInfo(std::string & jsonStr,std::string onProcessRet)346 bool BJsonUtil::BuildOnProcessRetInfo(std::string &jsonStr, std::string onProcessRet)
347 {
348 cJSON *info = cJSON_CreateObject();
349 if (info == nullptr) {
350 return false;
351 }
352 cJSON *processInfo = cJSON_CreateObject();
353 if (processInfo == nullptr) {
354 cJSON_Delete(info);
355 return false;
356 }
357 std::string timeInfo = std::to_string(TimeUtils::GetTimeS());
358 cJSON_AddStringToObject(processInfo, "timeInfo", timeInfo.c_str());
359 cJSON_AddStringToObject(processInfo, "resultInfo", onProcessRet.c_str());
360 cJSON_AddItemToObject(info, "processResult", processInfo);
361 char *data = cJSON_Print(info);
362 if (data == nullptr) {
363 cJSON_Delete(info);
364 return false;
365 }
366 jsonStr = std::string(data);
367 cJSON_Delete(info);
368 cJSON_free(data);
369 return true;
370 }
371
BuildBundleNameIndexInfo(const std::string & bundleName,int appIndex)372 std::string BJsonUtil::BuildBundleNameIndexInfo(const std::string &bundleName, int appIndex)
373 {
374 std::string result = bundleName;
375 if (appIndex == BUNDLE_INDEX_DEFAULT_VAL) {
376 return result;
377 }
378 result += BUNDLE_INDEX_SPLICE;
379 result += std::to_string(appIndex);
380 return result;
381 }
382
BuildOnProcessErrInfo(std::string & reportInfo,std::string path,int err)383 bool BJsonUtil::BuildOnProcessErrInfo(std::string &reportInfo, std::string path, int err)
384 {
385 cJSON *info = cJSON_CreateObject();
386 if (info == nullptr) {
387 return false;
388 }
389 cJSON *item = cJSON_CreateObject();
390 if (item == nullptr) {
391 cJSON_Delete(info);
392 return false;
393 }
394 cJSON *errInfoJs = cJSON_CreateObject();
395 if (errInfoJs == nullptr) {
396 cJSON_Delete(info);
397 cJSON_Delete(item);
398 return false;
399 }
400 std::string errStr = std::to_string(err);
401 std::string timeInfo = std::to_string(TimeUtils::GetTimeS());
402 cJSON_AddStringToObject(errInfoJs, "errorCode", errStr.c_str());
403 cJSON_AddStringToObject(errInfoJs, "errorMessage", path.c_str());
404 cJSON_AddStringToObject(item, "timeInfo", timeInfo.c_str());
405 cJSON_AddItemToObject(item, "errorInfo", errInfoJs);
406 cJSON_AddItemToObject(info, "processResult", item);
407 char *data = cJSON_Print(info);
408 if (data == nullptr) {
409 cJSON_Delete(info);
410 return false;
411 }
412 reportInfo = std::string(data);
413 cJSON_Delete(info);
414 cJSON_free(data);
415 return true;
416 }
417
BuildBundleInfoJson(int32_t userId,string & detailInfo)418 bool BJsonUtil::BuildBundleInfoJson(int32_t userId, string &detailInfo)
419 {
420 cJSON *infos = cJSON_CreateArray();
421 if (infos == nullptr) {
422 return false;
423 }
424 cJSON *info = cJSON_CreateObject();
425 if (info == nullptr) {
426 cJSON_Delete(infos);
427 return false;
428 }
429 string userIdstr = to_string(userId);
430 const char *const zeroUserId = userIdstr.c_str();
431 cJSON_AddStringToObject(info, "type", "userId");
432 cJSON_AddStringToObject(info, "detail", zeroUserId);
433 cJSON_AddItemToArray(infos, info);
434 char *jsonStr = cJSON_Print(infos);
435 if (jsonStr == nullptr) {
436 cJSON_Delete(infos);
437 return false;
438 }
439 detailInfo = string(jsonStr);
440 cJSON_Delete(infos);
441 free(jsonStr);
442 return true;
443 }
444
ParseBackupVersion()445 std::string BJsonUtil::ParseBackupVersion()
446 {
447 std::string backupVersion;
448 cJSON *root = cJSON_Parse(BConstants::BACKUP_VERSION.c_str());
449 if (root == nullptr) {
450 HILOGE("Parse json error,root is null");
451 return "";
452 }
453 cJSON *value = cJSON_GetObjectItem(root, "backupVersion");
454 if (value == nullptr || !cJSON_IsString(value) || (value->valuestring == nullptr)) {
455 HILOGE("Parse json backupVersion element error");
456 cJSON_Delete(root);
457 return "";
458 }
459 backupVersion = value->valuestring;
460 cJSON_Delete(root);
461 return backupVersion;
462 }
463
BuildInitSessionErrInfo(int32_t userId,std::string callerName,std::string activeTime)464 std::string BJsonUtil::BuildInitSessionErrInfo(int32_t userId, std::string callerName, std::string activeTime)
465 {
466 cJSON *info = cJSON_CreateObject();
467 if (info == nullptr) {
468 HILOGE("Failed to create cJSON object info, update errMsg failed");
469 return "";
470 }
471 cJSON *sessionInfoArray = cJSON_CreateArray();
472 if (sessionInfoArray == nullptr) {
473 HILOGE("Failed to create cJSON array sessionInfoArray, update errMsg failed");
474 cJSON_Delete(info);
475 return "";
476 }
477 cJSON_AddItemToObject(info, "sessionInfo", sessionInfoArray);
478 cJSON *sessionInfoObject = cJSON_CreateObject();
479 if (sessionInfoObject == nullptr) {
480 HILOGE("Failed to create cJSON object sessionInfoObject, update errMsg failed");
481 cJSON_Delete(info);
482 return "";
483 }
484 cJSON_AddItemToArray(sessionInfoArray, sessionInfoObject);
485 cJSON_AddStringToObject(sessionInfoObject, "userId", to_string(userId).c_str());
486 cJSON_AddStringToObject(sessionInfoObject, "name", callerName.c_str());
487 cJSON_AddStringToObject(sessionInfoObject, "activeTime", activeTime.c_str());
488 char *jsonStr = cJSON_Print(info);
489 if (jsonStr == nullptr) {
490 HILOGE("update errMsg failed");
491 cJSON_Delete(info);
492 return "";
493 }
494 std::string errMsg = jsonStr;
495 cJSON_Delete(info);
496 cJSON_free(jsonStr);
497 return errMsg;
498 }
499
WriteToStr(std::vector<BundleDataSize> & bundleDataList,size_t listSize,std::string scanning,std::string & jsonStr)500 bool BJsonUtil::WriteToStr(std::vector<BundleDataSize> &bundleDataList,
501 size_t listSize,
502 std::string scanning,
503 std::string &jsonStr)
504 {
505 cJSON *root = cJSON_CreateObject();
506 if (root == nullptr) {
507 HILOGE("CreateObject failed");
508 return false;
509 }
510 cJSON *scannedArray = cJSON_CreateArray();
511 if (scannedArray == nullptr) {
512 HILOGE("CreateArray failed");
513 cJSON_Delete(root);
514 return false;
515 }
516 cJSON_AddItemToObject(root, "scaned", scannedArray);
517 for (size_t i = 0; i < listSize; i++) {
518 cJSON *item = cJSON_CreateObject();
519 if (item == nullptr) {
520 HILOGE("cJSON_CreateObject failed");
521 continue;
522 }
523 cJSON_AddStringToObject(item, "bundleName", bundleDataList[i].bundleName.c_str());
524 cJSON_AddNumberToObject(item, "dataSize", bundleDataList[i].dataSize);
525 cJSON_AddNumberToObject(item, "incDataSize", bundleDataList[i].incDataSize);
526 cJSON_AddItemToArray(scannedArray, item);
527 }
528 cJSON_AddStringToObject(root, "scanning", scanning.c_str());
529 HILOGI("end to add item");
530 char *jsonString = cJSON_Print(root);
531 if (jsonString == nullptr) {
532 HILOGE("cJSON_Print failed");
533 cJSON_Delete(root);
534 return false;
535 }
536 jsonStr = string(jsonString);
537 cJSON_Delete(root);
538 free(jsonString);
539 HILOGI("write json str ok, scanned size is %{public}zu", listSize);
540 return true;
541 }
542 }