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