• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 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 "daemon_execute.h"
17 
18 #include <chrono>
19 #include <ctime>
20 #include <filesystem>
21 #include <memory>
22 #include <random>
23 #include <regex>
24 
25 #include "asset_callback_manager.h"
26 #include "daemon.h"
27 #include "dfs_error.h"
28 #include "network/softbus/softbus_asset_send_listener.h"
29 #include "network/softbus/softbus_handler_asset.h"
30 #include "network/softbus/softbus_session_pool.h"
31 #include "refbase.h"
32 #include "sandbox_helper.h"
33 #include "utils_directory.h"
34 #include "utils_log.h"
35 
36 #include "all_connect/all_connect_manager.h"
37 #include "network/softbus/softbus_handler.h"
38 
39 namespace OHOS {
40 namespace Storage {
41 namespace DistributedFile {
42 using namespace OHOS::AppFileService;
43 using namespace OHOS::FileManagement;
44 namespace {
45 const std::string FILE_MANAGER_AUTHORITY = "docs";
46 const std::string MEDIA_AUTHORITY = "media";
47 }
DaemonExecute()48 DaemonExecute::DaemonExecute()
49 {
50     LOGI("DaemonExecute begin.");
51     executeFuncMap_[DEAMON_EXECUTE_PUSH_ASSET] = &DaemonExecute::ExecutePushAsset;
52     executeFuncMap_[DEAMON_EXECUTE_REQUEST_SEND_FILE] = &DaemonExecute::ExecuteRequestSendFile;
53     executeFuncMap_[DEAMON_EXECUTE_PREPARE_SESSION] = &DaemonExecute::ExecutePrepareSession;
54 }
55 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)56 void DaemonExecute::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
57 {
58     if (event == nullptr) {
59         LOGE("event is nullptr.");
60         return;
61     }
62     std::lock_guard<std::mutex> lock(executeFuncMapMutex_);
63     auto itFunc = executeFuncMap_.find(event->GetInnerEventId());
64     if (itFunc == executeFuncMap_.end()) {
65         LOGE("not find execute func.");
66         return;
67     }
68 
69     auto executeFunc = itFunc->second;
70     (this->*executeFunc)(event);
71 }
72 
ExecutePushAsset(const AppExecFwk::InnerEvent::Pointer & event)73 void DaemonExecute::ExecutePushAsset(const AppExecFwk::InnerEvent::Pointer &event)
74 {
75     if (event == nullptr) {
76         LOGI("eventhandler fail.");
77         return;
78     }
79     auto pushData = event->GetSharedObject<PushAssetData>();
80     if (pushData == nullptr) {
81         LOGE("pushData is nullptr.");
82         return;
83     }
84     int32_t userId = pushData->userId_;
85     auto assetObj = pushData->assetObj_;
86     if (assetObj == nullptr) {
87         LOGE("assetObj is nullptr.");
88         return;
89     }
90     int32_t socketId;
91     auto ret = SoftBusHandlerAsset::GetInstance().AssetBind(assetObj->dstNetworkId_, socketId);
92     if (ret != E_OK) {
93         LOGE("ExecutePushAsset AssetBind failed, ret %{public}d", ret);
94         auto taskId = assetObj->srcBundleName_ + assetObj->sessionId_;
95         AssetCallbackManager::GetInstance().NotifyAssetSendResult(taskId, assetObj, FileManagement::E_EVENT_HANDLER);
96         AssetCallbackManager::GetInstance().RemoveSendCallback(taskId);
97         return;
98     }
99     SoftBusHandlerAsset::GetInstance().AddAssetObj(socketId, assetObj);
100 
101     auto fileList = GetFileList(assetObj->uris_, userId, assetObj->srcBundleName_);
102     if (fileList.empty()) {
103         LOGE("get fileList is empty.");
104         HandlePushAssetFail(socketId, assetObj);
105         return;
106     }
107 
108     std::string sendFileName;
109     bool isSingleFile;
110     ret = HandleZip(fileList, assetObj, sendFileName, isSingleFile);
111     if (ret != E_OK) {
112         LOGE("zip files fail. socketId is %{public}d", socketId);
113         HandlePushAssetFail(socketId, assetObj);
114         SoftBusHandlerAsset::GetInstance().RemoveFile(sendFileName, !isSingleFile);
115         return;
116     }
117 
118     ret = SoftBusHandlerAsset::GetInstance().AssetSendFile(socketId, sendFileName, isSingleFile);
119     if (ret != E_OK) {
120         LOGE("ExecutePushAsset send file fail, ret %{public}d", ret);
121         HandlePushAssetFail(socketId, assetObj);
122         SoftBusHandlerAsset::GetInstance().RemoveFile(sendFileName, !isSingleFile);
123         return;
124     }
125 }
126 
ExecuteRequestSendFile(const AppExecFwk::InnerEvent::Pointer & event)127 void DaemonExecute::ExecuteRequestSendFile(const AppExecFwk::InnerEvent::Pointer &event)
128 {
129     if (event == nullptr) {
130         LOGI("eventhandler fail.");
131         return;
132     }
133     auto requestSendFileData = event->GetSharedObject<RequestSendFileData>();
134     if (requestSendFileData == nullptr) {
135         LOGE("requestSendFileData is nullptr.");
136         return;
137     }
138 
139     auto requestSendFileBlock  = requestSendFileData->requestSendFileBlock_;
140     if (requestSendFileBlock == nullptr) {
141         LOGE("requestSendFileBlock is nullptr.");
142         return;
143     }
144     std::string srcUri = requestSendFileData->srcUri_;
145     std::string dstPath  = requestSendFileData->dstPath_;
146     std::string dstDeviceId  = requestSendFileData->dstDeviceId_;
147     std::string sessionName  = requestSendFileData->sessionName_;
148     if (srcUri.empty() || dstDeviceId.empty() || sessionName.empty()) {
149         LOGE("params empty. %{public}s, %{public}s", sessionName.c_str(), Utils::GetAnonyString(dstDeviceId).c_str());
150         requestSendFileBlock->SetValue(ERR_BAD_VALUE);
151         return;
152     }
153 
154     requestSendFileBlock->SetValue(RequestSendFileInner(srcUri, dstPath, dstDeviceId, sessionName));
155 }
156 
RequestSendFileInner(const std::string & srcUri,const std::string & dstPath,const std::string & dstDeviceId,const std::string & sessionName)157 int32_t DaemonExecute::RequestSendFileInner(const std::string &srcUri,
158                                             const std::string &dstPath,
159                                             const std::string &dstDeviceId,
160                                             const std::string &sessionName)
161 {
162     LOGI("RequestSendFile begin dstDeviceId: %{public}s", Utils::GetAnonyString(dstDeviceId).c_str());
163     auto resourceReq = AllConnectManager::GetInstance().BuildResourceRequest();
164     int32_t ret = AllConnectManager::GetInstance().ApplyAdvancedResource(dstDeviceId, resourceReq.get());
165     if (ret != E_OK) {
166         LOGE("ApplyAdvancedResource fail, ret is %{public}d", ret);
167         return ERR_APPLY_RESULT;
168     }
169 
170     int32_t socketId;
171     ret = SoftBusHandler::GetInstance().OpenSession(sessionName, sessionName, dstDeviceId, socketId);
172     if (ret != E_OK) {
173         LOGE("OpenSession failed, ret is %{public}d", ret);
174         return ret;
175     }
176     AllConnectManager::GetInstance().PublishServiceState(DfsConnectCode::COPY_FILE, dstDeviceId,
177                                                          ServiceCollaborationManagerBussinessStatus::SCM_CONNECTED);
178     LOGI("RequestSendFile OpenSession success");
179 
180     ret = SoftBusHandler::GetInstance().CopySendFile(socketId, sessionName, srcUri, dstPath);
181     if (ret != E_OK) {
182         LOGE("CopySendFile failed, ret is %{public}d", ret);
183         SoftBusHandler::GetInstance().CloseSession(socketId, sessionName);
184         return ret;
185     }
186     return E_OK;
187 }
188 
ExecutePrepareSession(const AppExecFwk::InnerEvent::Pointer & event)189 void DaemonExecute::ExecutePrepareSession(const AppExecFwk::InnerEvent::Pointer &event)
190 {
191     if (event == nullptr) {
192         LOGI("eventhandler fail.");
193         return;
194     }
195     auto prepareSessionData = event->GetSharedObject<PrepareSessionData>();
196     if (prepareSessionData == nullptr) {
197         LOGE("prepareSessionData is nullptr.");
198         return;
199     }
200 
201     auto prepareSessionBlock  = prepareSessionData->prepareSessionBlock_;
202     if (prepareSessionBlock == nullptr) {
203         LOGE("prepareSessionBlock is nullptr.");
204         return;
205     }
206     std::string srcUri = prepareSessionData->srcUri_;
207     std::string physicalPath  = prepareSessionData->physicalPath_;
208     std::string sessionName  = prepareSessionData->sessionName_;
209     sptr<IDaemon> daemon  = prepareSessionData->daemon_;
210     HmdfsInfo &info = prepareSessionData->info_;
211 
212     prepareSessionBlock->SetValue(PrepareSessionInner(srcUri, physicalPath, sessionName, daemon, info));
213 }
214 
PrepareSessionInner(const std::string & srcUri,std::string & physicalPath,const std::string & sessionName,const sptr<IDaemon> & daemon,HmdfsInfo & info)215 int32_t DaemonExecute::PrepareSessionInner(const std::string &srcUri,
216                                            std::string &physicalPath,
217                                            const std::string &sessionName,
218                                            const sptr<IDaemon> &daemon,
219                                            HmdfsInfo &info)
220 {
221     LOGI("PrepareSessionInner begin.");
222     auto socketId = SoftBusHandler::GetInstance().CreateSessionServer(IDaemon::SERVICE_NAME, sessionName,
223                                                                       DFS_CHANNLE_ROLE_SINK, physicalPath);
224     if (socketId <= 0) {
225         LOGE("CreateSessionServer failed, socketId = %{public}d", socketId);
226         Daemon::DeleteSessionAndListener(sessionName, socketId);
227         return E_SOFTBUS_SESSION_FAILED;
228     }
229     physicalPath.clear();
230     if (info.authority == FILE_MANAGER_AUTHORITY || info.authority == MEDIA_AUTHORITY) {
231         LOGI("authority is media or docs");
232         physicalPath = "??" + info.dstPhysicalPath;
233     }
234     auto ret = Daemon::Copy(srcUri, physicalPath, daemon, sessionName);
235     if (ret != E_OK) {
236         LOGE("Remote copy failed,ret = %{public}d", ret);
237         Daemon::DeleteSessionAndListener(sessionName, socketId);
238         return ret;
239     }
240     return ret;
241 }
242 
GetZipName(const std::string & relativePath)243 std::string DaemonExecute::GetZipName(const std::string &relativePath)
244 {
245     auto cppnow = std::chrono::system_clock::now();
246     auto cppnow_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(cppnow);
247     auto value = std::to_string(cppnow_ms.time_since_epoch().count());
248 
249     std::random_device rd;
250     std::string random = std::to_string(rd());
251     std::string zipName = value + "_" + random + ".zip";
252 
253     while (std::filesystem::exists(relativePath + zipName)) {
254         random = std::to_string(rd());
255         zipName = value + "_" + random + ".zip";
256     }
257     LOGI("zipName is %{public}s", zipName.c_str());
258     return zipName;
259 }
260 
GetFileList(const std::vector<std::string> & uris,int32_t userId,const std::string & srcBundleName)261 std::vector<std::string> DaemonExecute::GetFileList(const std::vector<std::string> &uris,
262                                                     int32_t userId,
263                                                     const std::string &srcBundleName)
264 {
265     std::vector<std::string> fileList;
266     for (const auto &uri : uris) {
267         size_t pos = uri.find(srcBundleName);
268         if (pos == std::string::npos) {
269             LOGE("srcBundleName not find in uri.");
270             return {};
271         }
272 
273         std::string physicalPath;
274         int32_t ret = SandboxHelper::GetPhysicalPath(uri, std::to_string(userId), physicalPath);
275         if (ret != E_OK) {
276             LOGE("invalid uri, ret = %{public}d", ret);
277             return {};
278         }
279         if (!SandboxHelper::CheckValidPath(physicalPath)) {
280             LOGE("invalid path : %{public}s", GetAnonyString(physicalPath).c_str());
281             return {};
282         }
283         if (OHOS::Storage::DistributedFile::Utils::IsFolder(physicalPath)) {
284             LOGE("uri is folder are not supported now.");
285             return {};
286         }
287 
288         fileList.emplace_back(physicalPath);
289     }
290     LOGI("GetFileList success, file num is %{public}s", std::to_string(fileList.size()).c_str());
291     return fileList;
292 }
293 
HandleZip(const std::vector<std::string> & fileList,const sptr<AssetObj> & assetObj,std::string & sendFileName,bool & isSingleFile)294 int32_t DaemonExecute::HandleZip(const std::vector<std::string> &fileList,
295                                  const sptr<AssetObj> &assetObj,
296                                  std::string &sendFileName,
297                                  bool &isSingleFile)
298 {
299     if (fileList.size() > 1) {
300         size_t pos = fileList[0].find(assetObj->srcBundleName_);
301         if (pos == std::string::npos) {
302             LOGE("srcBundleName not find in uri.");
303             return E_ZIP;
304         }
305         std::string relativePath = fileList[0].substr(0, pos + assetObj->srcBundleName_.length()) + "/";
306         sendFileName = relativePath + GetZipName(relativePath);
307         int32_t ret = SoftBusHandlerAsset::GetInstance().CompressFile(fileList, relativePath, sendFileName);
308         if (ret != E_OK) {
309             LOGE("zip ffiles fail.");
310             return E_ZIP;
311         }
312         isSingleFile = false;
313         SoftBusAssetSendListener::AddFileMap(assetObj->srcBundleName_ + assetObj->sessionId_, sendFileName, false);
314         return E_OK;
315     } else {
316         sendFileName = fileList[0];
317         isSingleFile = true;
318         SoftBusAssetSendListener::AddFileMap(assetObj->srcBundleName_ + assetObj->sessionId_, sendFileName, true);
319         return E_OK;
320     }
321 }
322 
HandlePushAssetFail(int32_t socketId,const sptr<AssetObj> & assetObj)323 void DaemonExecute::HandlePushAssetFail(int32_t socketId, const sptr<AssetObj> &assetObj)
324 {
325     auto taskId = assetObj->srcBundleName_ + assetObj->sessionId_;
326     AssetCallbackManager::GetInstance().NotifyAssetSendResult(taskId, assetObj, FileManagement::E_EVENT_HANDLER);
327     SoftBusHandlerAsset::GetInstance().closeAssetBind(socketId);
328     AssetCallbackManager::GetInstance().RemoveSendCallback(taskId);
329     SoftBusAssetSendListener::RemoveFileMap(taskId);
330 }
331 } // namespace DistributedFile
332 } // namespace Storage
333 } // namespace OHOS
334