• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }