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