/* * Copyright (c) 2022-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "b_jsonutil/b_jsonutil.h" #include <cstring> #include <chrono> #include <iomanip> #include <sstream> #include "cJSON.h" #include "b_error/b_error.h" #include "b_resources/b_constants.h" #include "filemgmt_libhilog.h" #include "b_utils/b_time.h" namespace OHOS::FileManagement::Backup { using namespace std; namespace { const static int BUNDLE_INDEX_DEFAULT_VAL = 0; const static std::string BUNDLE_INDEX_SPLICE = ":"; } BJsonUtil::BundleDetailInfo BJsonUtil::ParseBundleNameIndexStr(const std::string &bundleNameStr) { HILOGI("Start parse bundle name and index"); size_t hasPos = bundleNameStr.find(BUNDLE_INDEX_SPLICE); BundleDetailInfo bundleDetailInfo; if (hasPos == std::string::npos) { bundleDetailInfo.bundleName = bundleNameStr; bundleDetailInfo.bundleIndex = BUNDLE_INDEX_DEFAULT_VAL; return bundleDetailInfo; } std::string bundleName = bundleNameStr.substr(0, hasPos); std::string indexStr = ""; if (to_string(bundleNameStr.back()) != BUNDLE_INDEX_SPLICE) { indexStr = bundleNameStr.substr(hasPos + 1); int index = std::stoi(indexStr); bundleDetailInfo.bundleIndex = index; } else { bundleDetailInfo.bundleIndex = BUNDLE_INDEX_DEFAULT_VAL; } bundleDetailInfo.bundleName = bundleName; HILOGI("End parse bundle name and index"); return bundleDetailInfo; } std::map<std::string, std::vector<BJsonUtil::BundleDetailInfo>> BJsonUtil::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) { std::map<std::string, std::vector<BJsonUtil::BundleDetailInfo>> bundleNameDetailMap; if (bundleNames.size() != bundleInfos.size()) { HILOGE("bundleNames count is not equals bundleInfos count"); return bundleNameDetailMap; } HILOGI("Start BuildBundleInfos"); for (size_t i = 0; i < bundleNames.size(); i++) { std::string bundleName = bundleNames[i]; if (bundleName.empty()) { HILOGE("BundleName is invalid"); continue; } std::vector<BJsonUtil::BundleDetailInfo> bundleDetailInfos; size_t pos = bundleName.find(BUNDLE_INDEX_SPLICE); if (pos == 0 || pos == (bundleName.size() - 1)) { HILOGE("Current bundle name is wrong"); continue; } std::string bundleNameOnly; int bundleIndex; if (pos == std::string::npos) { bundleNameOnly = bundleName; bundleIndex = BUNDLE_INDEX_DEFAULT_VAL; bundleNamesOnly.emplace_back(bundleName); } else { std::string bundleNameSplit = bundleName.substr(0, pos); if (to_string(bundleName.back()) != BUNDLE_INDEX_SPLICE) { std::string indexSplit = bundleName.substr(pos + 1); int index = std::atoi(indexSplit.c_str()); bundleIndex = index; } else { bundleIndex = BUNDLE_INDEX_DEFAULT_VAL; } bundleNameOnly = bundleNameSplit; bundleNamesOnly.emplace_back(bundleNameSplit); } std::string bundleInfo = bundleInfos[i]; bool isClearData = true; BJsonUtil::BundleDetailInfo bundleDetailInfo; bundleDetailInfo.bundleName = bundleNameOnly; bundleDetailInfo.bundleIndex = bundleIndex; bundleDetailInfo.userId = userId; ParseBundleInfoJson(bundleInfo, bundleDetailInfos, bundleDetailInfo, isClearData, userId); isClearDataFlags[bundleName] = isClearData; bundleNameDetailMap[bundleName] = bundleDetailInfos; } HILOGI("End BuildBundleInfos"); return bundleNameDetailMap; } // ä¼ é€’çš„bundleinfoä¸åŒ…å«unicastå—段时 需è¦æ‹¼æŽ¥unicastå—段 static bool AddUnicastInfo(std::string &bundleInfo) { cJSON *root = cJSON_Parse(bundleInfo.c_str()); if (root == nullptr) { HILOGE("Parse json error,root is null"); return false; } cJSON *info = cJSON_CreateObject(); if (info == nullptr) { cJSON_Delete(root); return false; } cJSON_AddStringToObject(info, "type", "unicast"); cJSON *details = cJSON_CreateArray(); if (details == nullptr) { cJSON_Delete(root); cJSON_Delete(info); return false; } cJSON_AddItemToArray(details, {}); cJSON_AddItemToObject(info, "details", details); cJSON *infos = cJSON_GetObjectItem(root, "infos"); if (infos == nullptr || !cJSON_IsArray(infos)) { cJSON_Delete(root); cJSON_Delete(info); return false; } cJSON_AddItemToArray(infos, info); char *jsonStr = cJSON_Print(root); if (jsonStr == nullptr) { cJSON_Delete(root); return false; } bundleInfo = string(jsonStr); cJSON_Delete(root); free(jsonStr); return true; } bool BJsonUtil::HasUnicastInfo(std::string &bundleInfo) { cJSON *root = cJSON_Parse(bundleInfo.c_str()); if (root == nullptr) { HILOGE("Parse json error,root is null"); return false; } cJSON *infos = cJSON_GetObjectItem(root, "infos"); if (infos == nullptr || !cJSON_IsArray(infos) || cJSON_GetArraySize(infos) == 0) { HILOGE("Parse json error, infos is not array"); cJSON_Delete(root); return false; } int infosCount = cJSON_GetArraySize(infos); for (int i = 0; i < infosCount; i++) { cJSON *infoItem = cJSON_GetArrayItem(infos, i); if (!cJSON_IsObject(infoItem)) { HILOGE("Parse json error, info item is not an object"); continue; } cJSON *type = cJSON_GetObjectItem(infoItem, "type"); if (type == nullptr || !cJSON_IsString(type) || (type->valuestring == nullptr)) { HILOGE("Parse json type element error"); continue; } if (string(type->valuestring).compare(BConstants::UNICAST_TYPE) == 0) { cJSON_Delete(root); return true; } } cJSON_Delete(root); return false; } static void InsertBundleDetailInfo(cJSON *infos, int infosCount, std::vector<BJsonUtil::BundleDetailInfo> &bundleDetails, BJsonUtil::BundleDetailInfo bundleDetailInfo, int32_t userId) { for (int i = 0; i < infosCount; i++) { cJSON *infoItem = cJSON_GetArrayItem(infos, i); if (!cJSON_IsObject(infoItem)) { HILOGE("Parse json error, info item is not an object"); return; } cJSON *type = cJSON_GetObjectItem(infoItem, "type"); if (type == nullptr || !cJSON_IsString(type) || (type->valuestring == nullptr)) { HILOGE("Parse json type element error"); return; } bundleDetailInfo.type = type->valuestring; cJSON *details = cJSON_GetObjectItem(infoItem, "details"); if (details == nullptr || !cJSON_IsArray(details)) { HILOGE("Parse json details element error"); return; } if (bundleDetailInfo.type.compare(BConstants::UNICAST_TYPE) == 0) { cJSON *detail = cJSON_CreateObject(); if (detail == nullptr) { HILOGE("creat json error"); return; } string userIdstr = to_string(userId); const char *const zeroUserId = userIdstr.c_str(); cJSON_AddStringToObject(detail, "type", "userId"); cJSON_AddStringToObject(detail, "detail", zeroUserId); cJSON_AddItemToArray(details, detail); } char *detailInfos = cJSON_Print(details); bundleDetailInfo.detail = std::string(detailInfos); bundleDetails.emplace_back(bundleDetailInfo); cJSON_free(detailInfos); } } void BJsonUtil::ParseBundleInfoJson(const std::string &bundleInfo, std::vector<BundleDetailInfo> &bundleDetails, BJsonUtil::BundleDetailInfo bundleDetailInfo, bool &isClearData, int32_t userId) { string bundleInfoCopy = move(bundleInfo); if (!HasUnicastInfo(bundleInfoCopy)) { if (!AddUnicastInfo(bundleInfoCopy)) { HILOGE("AddUnicastInfo failed"); return; } } cJSON *root = cJSON_Parse(bundleInfoCopy.c_str()); if (root == nullptr) { HILOGE("Parse json error,root is null"); return; } cJSON *clearBackupData = cJSON_GetObjectItem(root, "clearBackupData"); if (clearBackupData == nullptr || !cJSON_IsString(clearBackupData) || (clearBackupData->valuestring == nullptr)) { HILOGE("Parse json error."); } else { std::string value = clearBackupData->valuestring; isClearData = value.compare("false") != 0; HILOGI("bundleName:%{public}s clear data falg:%{public}d", bundleDetailInfo.bundleName.c_str(), isClearData); } cJSON *infos = cJSON_GetObjectItem(root, "infos"); if (infos == nullptr || !cJSON_IsArray(infos) || cJSON_GetArraySize(infos) == 0) { HILOGE("Parse json error, infos is not array"); cJSON_Delete(root); return; } int infosCount = cJSON_GetArraySize(infos); InsertBundleDetailInfo(infos, infosCount, bundleDetails, bundleDetailInfo, userId); cJSON_Delete(root); } bool BJsonUtil::FindBundleInfoByName(std::map<std::string, std::vector<BundleDetailInfo>> &bundleNameDetailsMap, std::string &bundleName, const std::string &jobType, BundleDetailInfo &bundleDetail) { auto iter = bundleNameDetailsMap.find(bundleName); if (iter == bundleNameDetailsMap.end()) { return false; } std::vector<BJsonUtil::BundleDetailInfo> bundleDetailInfos = iter->second; for (auto &bundleDetailInfo : bundleDetailInfos) { if (bundleDetailInfo.type == jobType) { bundleDetail = bundleDetailInfo; return true; } } return false; } bool BJsonUtil::BuildExtensionErrInfo(std::string &jsonStr, int errCode, std::string errMsg) { cJSON *info = cJSON_CreateObject(); if (info == nullptr) { return false; } cJSON *errInfo = cJSON_CreateObject(); if (errInfo == nullptr) { cJSON_Delete(info); return false; } cJSON_AddNumberToObject(errInfo, "errorCode", errCode); cJSON_AddStringToObject(errInfo, "errorInfo", errMsg.c_str()); cJSON_AddStringToObject(errInfo, "type", "ErrorInfo"); cJSON_AddItemToObject(info, "resultInfo", errInfo); char *data = cJSON_Print(info); if (data == nullptr) { cJSON_Delete(info); return false; } jsonStr = std::string(data); cJSON_Delete(info); cJSON_free(data); return true; } bool BJsonUtil::BuildExtensionErrInfo(std::string &jsonStr, std::map<std::string, std::vector<int>> errFileInfo) { cJSON *errJson = cJSON_CreateObject(); if (errJson == nullptr) { HILOGE("Creat json failed"); return false; } cJSON *arrJson = cJSON_CreateArray(); if (arrJson == nullptr) { cJSON_Delete(errJson); return false; } for (const auto &it : errFileInfo) { for (const auto &codeIt : it.second) { cJSON *eleJson = cJSON_CreateObject(); if (eleJson == nullptr) { HILOGE("Creat eleJson failed"); continue; } cJSON_AddStringToObject(eleJson, "type", "ErrorInfo"); cJSON_AddStringToObject(eleJson, "errorInfo", it.first.c_str()); cJSON_AddNumberToObject(eleJson, "errorCode", codeIt); cJSON_AddItemToArray(arrJson, eleJson); } } cJSON_AddItemToObject(errJson, "resultInfo", arrJson); char *data = cJSON_Print(errJson); if (data == nullptr) { cJSON_Delete(errJson); return false; } jsonStr = std::string(data); cJSON_Delete(errJson); cJSON_free(data); return true; } bool OHOS::FileManagement::Backup::BJsonUtil::BuildOnProcessRetInfo(std::string &jsonStr, std::string onProcessRet) { cJSON *info = cJSON_CreateObject(); if (info == nullptr) { return false; } cJSON *processInfo = cJSON_CreateObject(); if (processInfo == nullptr) { cJSON_Delete(info); return false; } std::string timeInfo = std::to_string(TimeUtils::GetTimeS()); cJSON_AddStringToObject(processInfo, "timeInfo", timeInfo.c_str()); cJSON_AddStringToObject(processInfo, "resultInfo", onProcessRet.c_str()); cJSON_AddItemToObject(info, "processResult", processInfo); char *data = cJSON_Print(info); if (data == nullptr) { cJSON_Delete(info); return false; } jsonStr = std::string(data); cJSON_Delete(info); cJSON_free(data); return true; } std::string BJsonUtil::BuildBundleNameIndexInfo(const std::string &bundleName, int appIndex) { std::string result = bundleName; if (appIndex == BUNDLE_INDEX_DEFAULT_VAL) { return result; } result += BUNDLE_INDEX_SPLICE; result += std::to_string(appIndex); return result; } bool OHOS::FileManagement::Backup::BJsonUtil::BuildOnProcessErrInfo(std::string &reportInfo, std::string path, int err) { cJSON *info = cJSON_CreateObject(); if (info == nullptr) { return false; } cJSON *item = cJSON_CreateObject(); if (item == nullptr) { cJSON_Delete(info); return false; } cJSON *errInfoJs = cJSON_CreateObject(); if (errInfoJs == nullptr) { cJSON_Delete(info); cJSON_Delete(item); return false; } std::string errStr = std::to_string(err); std::string timeInfo = std::to_string(TimeUtils::GetTimeS()); cJSON_AddStringToObject(errInfoJs, "errorCode", errStr.c_str()); cJSON_AddStringToObject(errInfoJs, "errorMessage", path.c_str()); cJSON_AddStringToObject(item, "timeInfo", timeInfo.c_str()); cJSON_AddItemToObject(item, "errorInfo", errInfoJs); cJSON_AddItemToObject(info, "processResult", item); char *data = cJSON_Print(info); if (data == nullptr) { cJSON_Delete(info); return false; } reportInfo = std::string(data); cJSON_Delete(info); cJSON_free(data); return true; } bool BJsonUtil::BuildBundleInfoJson(int32_t userId, string &detailInfo) { cJSON *infos = cJSON_CreateArray(); if (infos == nullptr) { return false; } cJSON *info = cJSON_CreateObject(); if (info == nullptr) { cJSON_Delete(infos); return false; } string userIdstr = to_string(userId); const char *const zeroUserId = userIdstr.c_str(); cJSON_AddStringToObject(info, "type", "userId"); cJSON_AddStringToObject(info, "detail", zeroUserId); cJSON_AddItemToArray(infos, info); char *jsonStr = cJSON_Print(infos); if (jsonStr == nullptr) { cJSON_Delete(infos); return false; } detailInfo = string(jsonStr); cJSON_Delete(infos); free(jsonStr); return true; } }