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 }