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