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