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