1cb7eb8c9Sopenharmony_ci/*
2cb7eb8c9Sopenharmony_ci* Copyright (c) 2024 Huawei Device Co., Ltd.
3cb7eb8c9Sopenharmony_ci* Licensed under the Apache License, Version 2.0 (the "License");
4cb7eb8c9Sopenharmony_ci* you may not use this file except in compliance with the License.
5cb7eb8c9Sopenharmony_ci* You may obtain a copy of the License at
6cb7eb8c9Sopenharmony_ci*
7cb7eb8c9Sopenharmony_ci*     http://www.apache.org/licenses/LICENSE-2.0
8cb7eb8c9Sopenharmony_ci*
9cb7eb8c9Sopenharmony_ci* Unless required by applicable law or agreed to in writing, software
10cb7eb8c9Sopenharmony_ci* distributed under the License is distributed on an "AS IS" BASIS,
11cb7eb8c9Sopenharmony_ci* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cb7eb8c9Sopenharmony_ci* See the License for the specific language governing permissions and
13cb7eb8c9Sopenharmony_ci* limitations under the License.
14cb7eb8c9Sopenharmony_ci */
15cb7eb8c9Sopenharmony_ci
16cb7eb8c9Sopenharmony_ci#include "daemon_execute.h"
17cb7eb8c9Sopenharmony_ci
18cb7eb8c9Sopenharmony_ci#include <chrono>
19cb7eb8c9Sopenharmony_ci#include <ctime>
20cb7eb8c9Sopenharmony_ci#include <filesystem>
21cb7eb8c9Sopenharmony_ci#include <memory>
22cb7eb8c9Sopenharmony_ci#include <random>
23cb7eb8c9Sopenharmony_ci#include <regex>
24cb7eb8c9Sopenharmony_ci
25cb7eb8c9Sopenharmony_ci#include "asset_callback_manager.h"
26cb7eb8c9Sopenharmony_ci#include "dfs_error.h"
27cb7eb8c9Sopenharmony_ci#include "network/softbus/softbus_asset_send_listener.h"
28cb7eb8c9Sopenharmony_ci#include "network/softbus/softbus_handler_asset.h"
29cb7eb8c9Sopenharmony_ci#include "network/softbus/softbus_session_pool.h"
30cb7eb8c9Sopenharmony_ci#include "refbase.h"
31cb7eb8c9Sopenharmony_ci#include "sandbox_helper.h"
32cb7eb8c9Sopenharmony_ci#include "utils_directory.h"
33cb7eb8c9Sopenharmony_ci#include "utils_log.h"
34cb7eb8c9Sopenharmony_ci
35cb7eb8c9Sopenharmony_ci#include "all_connect/all_connect_manager.h"
36cb7eb8c9Sopenharmony_ci#include "network/softbus/softbus_handler.h"
37cb7eb8c9Sopenharmony_ci
38cb7eb8c9Sopenharmony_cinamespace OHOS {
39cb7eb8c9Sopenharmony_cinamespace Storage {
40cb7eb8c9Sopenharmony_cinamespace DistributedFile {
41cb7eb8c9Sopenharmony_ciusing namespace OHOS::AppFileService;
42cb7eb8c9Sopenharmony_ciusing namespace OHOS::FileManagement;
43cb7eb8c9Sopenharmony_ciDaemonExecute::DaemonExecute()
44cb7eb8c9Sopenharmony_ci{
45cb7eb8c9Sopenharmony_ci    LOGI("DaemonExecute begin.");
46cb7eb8c9Sopenharmony_ci    executeFuncMap_[DEAMON_EXECUTE_PUSH_ASSET] = &DaemonExecute::ExecutePushAsset;
47cb7eb8c9Sopenharmony_ci    executeFuncMap_[DEAMON_EXECUTE_REQUEST_SEND_FILE] = &DaemonExecute::ExecuteRequestSendFile;
48cb7eb8c9Sopenharmony_ci}
49cb7eb8c9Sopenharmony_ci
50cb7eb8c9Sopenharmony_civoid DaemonExecute::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
51cb7eb8c9Sopenharmony_ci{
52cb7eb8c9Sopenharmony_ci    if (event == nullptr) {
53cb7eb8c9Sopenharmony_ci        LOGE("event is nullptr.");
54cb7eb8c9Sopenharmony_ci        return;
55cb7eb8c9Sopenharmony_ci    }
56cb7eb8c9Sopenharmony_ci    std::lock_guard<std::mutex> lock(executeFuncMapMutex_);
57cb7eb8c9Sopenharmony_ci    auto itFunc = executeFuncMap_.find(event->GetInnerEventId());
58cb7eb8c9Sopenharmony_ci    if (itFunc == executeFuncMap_.end()) {
59cb7eb8c9Sopenharmony_ci        LOGE("not find execute func.");
60cb7eb8c9Sopenharmony_ci        return;
61cb7eb8c9Sopenharmony_ci    }
62cb7eb8c9Sopenharmony_ci
63cb7eb8c9Sopenharmony_ci    auto executeFunc = itFunc->second;
64cb7eb8c9Sopenharmony_ci    (this->*executeFunc)(event);
65cb7eb8c9Sopenharmony_ci}
66cb7eb8c9Sopenharmony_ci
67cb7eb8c9Sopenharmony_civoid DaemonExecute::ExecutePushAsset(const AppExecFwk::InnerEvent::Pointer &event)
68cb7eb8c9Sopenharmony_ci{
69cb7eb8c9Sopenharmony_ci    if (event == nullptr) {
70cb7eb8c9Sopenharmony_ci        LOGI("eventhandler fail.");
71cb7eb8c9Sopenharmony_ci        return;
72cb7eb8c9Sopenharmony_ci    }
73cb7eb8c9Sopenharmony_ci    auto pushData = event->GetSharedObject<PushAssetData>();
74cb7eb8c9Sopenharmony_ci    if (pushData == nullptr) {
75cb7eb8c9Sopenharmony_ci        LOGE("pushData is nullptr.");
76cb7eb8c9Sopenharmony_ci        return;
77cb7eb8c9Sopenharmony_ci    }
78cb7eb8c9Sopenharmony_ci    int32_t userId = pushData->userId_;
79cb7eb8c9Sopenharmony_ci    auto assetObj = pushData->assetObj_;
80cb7eb8c9Sopenharmony_ci    if (assetObj == nullptr) {
81cb7eb8c9Sopenharmony_ci        LOGE("assetObj is nullptr.");
82cb7eb8c9Sopenharmony_ci        return;
83cb7eb8c9Sopenharmony_ci    }
84cb7eb8c9Sopenharmony_ci    int32_t socketId;
85cb7eb8c9Sopenharmony_ci    auto ret = SoftBusHandlerAsset::GetInstance().AssetBind(assetObj->dstNetworkId_, socketId);
86cb7eb8c9Sopenharmony_ci    if (ret != E_OK) {
87cb7eb8c9Sopenharmony_ci        LOGE("ExecutePushAsset AssetBind failed, ret %{public}d", ret);
88cb7eb8c9Sopenharmony_ci        auto taskId = assetObj->srcBundleName_ + assetObj->sessionId_;
89cb7eb8c9Sopenharmony_ci        AssetCallbackManager::GetInstance().NotifyAssetSendResult(taskId, assetObj, FileManagement::E_EVENT_HANDLER);
90cb7eb8c9Sopenharmony_ci        AssetCallbackManager::GetInstance().RemoveSendCallback(taskId);
91cb7eb8c9Sopenharmony_ci        return;
92cb7eb8c9Sopenharmony_ci    }
93cb7eb8c9Sopenharmony_ci    SoftBusHandlerAsset::GetInstance().AddAssetObj(socketId, assetObj);
94cb7eb8c9Sopenharmony_ci
95cb7eb8c9Sopenharmony_ci    auto fileList = GetFileList(assetObj->uris_, userId, assetObj->srcBundleName_);
96cb7eb8c9Sopenharmony_ci    if (fileList.empty()) {
97cb7eb8c9Sopenharmony_ci        LOGE("get fileList is empty.");
98cb7eb8c9Sopenharmony_ci        HandlePushAssetFail(socketId, assetObj);
99cb7eb8c9Sopenharmony_ci        return;
100cb7eb8c9Sopenharmony_ci    }
101cb7eb8c9Sopenharmony_ci
102cb7eb8c9Sopenharmony_ci    std::string sendFileName;
103cb7eb8c9Sopenharmony_ci    bool isSingleFile;
104cb7eb8c9Sopenharmony_ci    ret = HandleZip(fileList, assetObj, sendFileName, isSingleFile);
105cb7eb8c9Sopenharmony_ci    if (ret != E_OK) {
106cb7eb8c9Sopenharmony_ci        LOGE("zip files fail. socketId is %{public}d", socketId);
107cb7eb8c9Sopenharmony_ci        HandlePushAssetFail(socketId, assetObj);
108cb7eb8c9Sopenharmony_ci        SoftBusHandlerAsset::GetInstance().RemoveFile(sendFileName, !isSingleFile);
109cb7eb8c9Sopenharmony_ci        return;
110cb7eb8c9Sopenharmony_ci    }
111cb7eb8c9Sopenharmony_ci
112cb7eb8c9Sopenharmony_ci    ret = SoftBusHandlerAsset::GetInstance().AssetSendFile(socketId, sendFileName, isSingleFile);
113cb7eb8c9Sopenharmony_ci    if (ret != E_OK) {
114cb7eb8c9Sopenharmony_ci        LOGE("ExecutePushAsset send file fail, ret %{public}d", ret);
115cb7eb8c9Sopenharmony_ci        HandlePushAssetFail(socketId, assetObj);
116cb7eb8c9Sopenharmony_ci        SoftBusHandlerAsset::GetInstance().RemoveFile(sendFileName, !isSingleFile);
117cb7eb8c9Sopenharmony_ci        return;
118cb7eb8c9Sopenharmony_ci    }
119cb7eb8c9Sopenharmony_ci}
120cb7eb8c9Sopenharmony_ci
121cb7eb8c9Sopenharmony_civoid DaemonExecute::ExecuteRequestSendFile(const AppExecFwk::InnerEvent::Pointer &event)
122cb7eb8c9Sopenharmony_ci{
123cb7eb8c9Sopenharmony_ci    if (event == nullptr) {
124cb7eb8c9Sopenharmony_ci        LOGI("eventhandler fail.");
125cb7eb8c9Sopenharmony_ci        return;
126cb7eb8c9Sopenharmony_ci    }
127cb7eb8c9Sopenharmony_ci    auto requestSendFileData = event->GetSharedObject<RequestSendFileData>();
128cb7eb8c9Sopenharmony_ci    if (requestSendFileData == nullptr) {
129cb7eb8c9Sopenharmony_ci        LOGE("requestSendFileData is nullptr.");
130cb7eb8c9Sopenharmony_ci        return;
131cb7eb8c9Sopenharmony_ci    }
132cb7eb8c9Sopenharmony_ci
133cb7eb8c9Sopenharmony_ci    auto requestSendFileBlock  = requestSendFileData->requestSendFileBlock_;
134cb7eb8c9Sopenharmony_ci    if (requestSendFileBlock == nullptr) {
135cb7eb8c9Sopenharmony_ci        LOGE("requestSendFileBlock is nullptr.");
136cb7eb8c9Sopenharmony_ci        return;
137cb7eb8c9Sopenharmony_ci    }
138cb7eb8c9Sopenharmony_ci    std::string srcUri = requestSendFileData->srcUri_;
139cb7eb8c9Sopenharmony_ci    std::string dstPath  = requestSendFileData->dstPath_;
140cb7eb8c9Sopenharmony_ci    std::string dstDeviceId  = requestSendFileData->dstDeviceId_;
141cb7eb8c9Sopenharmony_ci    std::string sessionName  = requestSendFileData->sessionName_;
142cb7eb8c9Sopenharmony_ci    if (srcUri.empty() || dstDeviceId.empty() || sessionName.empty()) {
143cb7eb8c9Sopenharmony_ci        LOGE("params empty. %{public}s, %{public}s", sessionName.c_str(), Utils::GetAnonyString(dstDeviceId).c_str());
144cb7eb8c9Sopenharmony_ci        requestSendFileBlock->SetValue(ERR_BAD_VALUE);
145cb7eb8c9Sopenharmony_ci        return;
146cb7eb8c9Sopenharmony_ci    }
147cb7eb8c9Sopenharmony_ci
148cb7eb8c9Sopenharmony_ci    requestSendFileBlock->SetValue(RequestSendFileInner(srcUri, dstPath, dstDeviceId, sessionName));
149cb7eb8c9Sopenharmony_ci}
150cb7eb8c9Sopenharmony_ci
151cb7eb8c9Sopenharmony_ciint32_t DaemonExecute::RequestSendFileInner(const std::string &srcUri,
152cb7eb8c9Sopenharmony_ci                                            const std::string &dstPath,
153cb7eb8c9Sopenharmony_ci                                            const std::string &dstDeviceId,
154cb7eb8c9Sopenharmony_ci                                            const std::string &sessionName)
155cb7eb8c9Sopenharmony_ci{
156cb7eb8c9Sopenharmony_ci    LOGI("RequestSendFile begin dstDeviceId: %{public}s", Utils::GetAnonyString(dstDeviceId).c_str());
157cb7eb8c9Sopenharmony_ci    auto resourceReq = AllConnectManager::GetInstance().BuildResourceRequest();
158cb7eb8c9Sopenharmony_ci    int32_t ret = AllConnectManager::GetInstance().ApplyAdvancedResource(dstDeviceId, resourceReq.get());
159cb7eb8c9Sopenharmony_ci    if (ret != E_OK) {
160cb7eb8c9Sopenharmony_ci        LOGE("ApplyAdvancedResource fail, ret is %{public}d", ret);
161cb7eb8c9Sopenharmony_ci        return ERR_APPLY_RESULT;
162cb7eb8c9Sopenharmony_ci    }
163cb7eb8c9Sopenharmony_ci
164cb7eb8c9Sopenharmony_ci    int32_t socketId;
165cb7eb8c9Sopenharmony_ci    ret = SoftBusHandler::GetInstance().OpenSession(sessionName, sessionName, dstDeviceId, socketId);
166cb7eb8c9Sopenharmony_ci    if (ret != E_OK) {
167cb7eb8c9Sopenharmony_ci        LOGE("OpenSession failed, ret is %{public}d", ret);
168cb7eb8c9Sopenharmony_ci        return ret;
169cb7eb8c9Sopenharmony_ci    }
170cb7eb8c9Sopenharmony_ci    AllConnectManager::GetInstance().PublishServiceState(dstDeviceId,
171cb7eb8c9Sopenharmony_ci                                                         ServiceCollaborationManagerBussinessStatus::SCM_CONNECTED);
172cb7eb8c9Sopenharmony_ci    LOGI("RequestSendFile OpenSession success");
173cb7eb8c9Sopenharmony_ci
174cb7eb8c9Sopenharmony_ci    ret = SoftBusHandler::GetInstance().CopySendFile(socketId, sessionName, srcUri, dstPath);
175cb7eb8c9Sopenharmony_ci    if (ret != E_OK) {
176cb7eb8c9Sopenharmony_ci        LOGE("CopySendFile failed, ret is %{public}d", ret);
177cb7eb8c9Sopenharmony_ci        SoftBusHandler::GetInstance().CloseSession(socketId, sessionName);
178cb7eb8c9Sopenharmony_ci        return ret;
179cb7eb8c9Sopenharmony_ci    }
180cb7eb8c9Sopenharmony_ci    return E_OK;
181cb7eb8c9Sopenharmony_ci}
182cb7eb8c9Sopenharmony_ci
183cb7eb8c9Sopenharmony_cistd::string DaemonExecute::GetZipName(const std::string &relativePath)
184cb7eb8c9Sopenharmony_ci{
185cb7eb8c9Sopenharmony_ci    auto cppnow = std::chrono::system_clock::now();
186cb7eb8c9Sopenharmony_ci    auto cppnow_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(cppnow);
187cb7eb8c9Sopenharmony_ci    auto value = std::to_string(cppnow_ms.time_since_epoch().count());
188cb7eb8c9Sopenharmony_ci
189cb7eb8c9Sopenharmony_ci    std::random_device rd;
190cb7eb8c9Sopenharmony_ci    std::string random = std::to_string(rd());
191cb7eb8c9Sopenharmony_ci    std::string zipName = value + "_" + random + ".zip";
192cb7eb8c9Sopenharmony_ci
193cb7eb8c9Sopenharmony_ci    while (std::filesystem::exists(relativePath + zipName)) {
194cb7eb8c9Sopenharmony_ci        random = std::to_string(rd());
195cb7eb8c9Sopenharmony_ci        zipName = value + "_" + random + ".zip";
196cb7eb8c9Sopenharmony_ci    }
197cb7eb8c9Sopenharmony_ci    LOGI("zipName is %{public}s", zipName.c_str());
198cb7eb8c9Sopenharmony_ci    return zipName;
199cb7eb8c9Sopenharmony_ci}
200cb7eb8c9Sopenharmony_ci
201cb7eb8c9Sopenharmony_cistd::vector<std::string> DaemonExecute::GetFileList(const std::vector<std::string> &uris,
202cb7eb8c9Sopenharmony_ci                                                    int32_t userId,
203cb7eb8c9Sopenharmony_ci                                                    const std::string &srcBundleName)
204cb7eb8c9Sopenharmony_ci{
205cb7eb8c9Sopenharmony_ci    std::vector<std::string> fileList;
206cb7eb8c9Sopenharmony_ci    std::regex pattern("/mnt/hmdfs/\\d{3,}/account/device_view/local/data/.*");
207cb7eb8c9Sopenharmony_ci    for (const auto &uri : uris) {
208cb7eb8c9Sopenharmony_ci        size_t pos = uri.find(srcBundleName);
209cb7eb8c9Sopenharmony_ci        if (pos == std::string::npos) {
210cb7eb8c9Sopenharmony_ci            LOGE("srcBundleName not find in uri.");
211cb7eb8c9Sopenharmony_ci            return {};
212cb7eb8c9Sopenharmony_ci        }
213cb7eb8c9Sopenharmony_ci
214cb7eb8c9Sopenharmony_ci        std::string physicalPath;
215cb7eb8c9Sopenharmony_ci        int32_t ret = SandboxHelper::GetPhysicalPath(uri, std::to_string(userId), physicalPath);
216cb7eb8c9Sopenharmony_ci        if (ret != E_OK) {
217cb7eb8c9Sopenharmony_ci            LOGE("invalid uri, ret = %{public}d", ret);
218cb7eb8c9Sopenharmony_ci            return {};
219cb7eb8c9Sopenharmony_ci        }
220cb7eb8c9Sopenharmony_ci        if (!SandboxHelper::CheckValidPath(physicalPath)) {
221cb7eb8c9Sopenharmony_ci            LOGE("invalid path : %{public}s", GetAnonyString(physicalPath).c_str());
222cb7eb8c9Sopenharmony_ci            return {};
223cb7eb8c9Sopenharmony_ci        }
224cb7eb8c9Sopenharmony_ci        if (OHOS::Storage::DistributedFile::Utils::IsFolder(physicalPath)) {
225cb7eb8c9Sopenharmony_ci            LOGE("uri is folder are not supported now.");
226cb7eb8c9Sopenharmony_ci            return {};
227cb7eb8c9Sopenharmony_ci        }
228cb7eb8c9Sopenharmony_ci        if (!std::regex_match(physicalPath, pattern)) {
229cb7eb8c9Sopenharmony_ci            LOGE("physicalPath is not hmdfs path.");
230cb7eb8c9Sopenharmony_ci        }
231cb7eb8c9Sopenharmony_ci        fileList.emplace_back(physicalPath);
232cb7eb8c9Sopenharmony_ci    }
233cb7eb8c9Sopenharmony_ci    LOGI("GetFileList success, file num is %{public}s", std::to_string(fileList.size()).c_str());
234cb7eb8c9Sopenharmony_ci    return fileList;
235cb7eb8c9Sopenharmony_ci}
236cb7eb8c9Sopenharmony_ci
237cb7eb8c9Sopenharmony_ciint32_t DaemonExecute::HandleZip(const std::vector<std::string> &fileList,
238cb7eb8c9Sopenharmony_ci                                 const sptr<AssetObj> &assetObj,
239cb7eb8c9Sopenharmony_ci                                 std::string &sendFileName,
240cb7eb8c9Sopenharmony_ci                                 bool &isSingleFile)
241cb7eb8c9Sopenharmony_ci{
242cb7eb8c9Sopenharmony_ci    if (fileList.size() > 1) {
243cb7eb8c9Sopenharmony_ci        size_t pos = fileList[0].find(assetObj->srcBundleName_);
244cb7eb8c9Sopenharmony_ci        if (pos == std::string::npos) {
245cb7eb8c9Sopenharmony_ci            LOGE("srcBundleName not find in uri.");
246cb7eb8c9Sopenharmony_ci            return E_ZIP;
247cb7eb8c9Sopenharmony_ci        }
248cb7eb8c9Sopenharmony_ci        std::string relativePath = fileList[0].substr(0, pos + assetObj->srcBundleName_.length()) + "/";
249cb7eb8c9Sopenharmony_ci        sendFileName = relativePath + GetZipName(relativePath);
250cb7eb8c9Sopenharmony_ci        int32_t ret = SoftBusHandlerAsset::GetInstance().CompressFile(fileList, relativePath, sendFileName);
251cb7eb8c9Sopenharmony_ci        if (ret != E_OK) {
252cb7eb8c9Sopenharmony_ci            LOGE("zip ffiles fail.");
253cb7eb8c9Sopenharmony_ci            return E_ZIP;
254cb7eb8c9Sopenharmony_ci        }
255cb7eb8c9Sopenharmony_ci        isSingleFile = false;
256cb7eb8c9Sopenharmony_ci        SoftBusAssetSendListener::AddFileMap(assetObj->srcBundleName_ + assetObj->sessionId_, false);
257cb7eb8c9Sopenharmony_ci        return E_OK;
258cb7eb8c9Sopenharmony_ci    } else {
259cb7eb8c9Sopenharmony_ci        sendFileName = fileList[0];
260cb7eb8c9Sopenharmony_ci        isSingleFile = true;
261cb7eb8c9Sopenharmony_ci        SoftBusAssetSendListener::AddFileMap(assetObj->srcBundleName_ + assetObj->sessionId_, true);
262cb7eb8c9Sopenharmony_ci        return E_OK;
263cb7eb8c9Sopenharmony_ci    }
264cb7eb8c9Sopenharmony_ci}
265cb7eb8c9Sopenharmony_ci
266cb7eb8c9Sopenharmony_civoid DaemonExecute::HandlePushAssetFail(int32_t socketId, const sptr<AssetObj> &assetObj)
267cb7eb8c9Sopenharmony_ci{
268cb7eb8c9Sopenharmony_ci    auto taskId = assetObj->srcBundleName_ + assetObj->sessionId_;
269cb7eb8c9Sopenharmony_ci    AssetCallbackManager::GetInstance().NotifyAssetSendResult(taskId, assetObj, FileManagement::E_EVENT_HANDLER);
270cb7eb8c9Sopenharmony_ci    SoftBusHandlerAsset::GetInstance().closeAssetBind(socketId);
271cb7eb8c9Sopenharmony_ci    AssetCallbackManager::GetInstance().RemoveSendCallback(taskId);
272cb7eb8c9Sopenharmony_ci    SoftBusAssetSendListener::RemoveFileMap(taskId);
273cb7eb8c9Sopenharmony_ci}
274cb7eb8c9Sopenharmony_ci} // namespace DistributedFile
275cb7eb8c9Sopenharmony_ci} // namespace Storage
276cb7eb8c9Sopenharmony_ci} // namespace OHOS
277