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 "network/softbus/softbus_asset_recv_listener.h"
17
18 #include <filesystem>
19 #include <memory>
20
21 #include "accesstoken_kit.h"
22 #include "asset_callback_manager.h"
23 #include "dfs_error.h"
24 #include "ipc_skeleton.h"
25 #include "network/softbus/softbus_handler_asset.h"
26 #include "os_account_manager.h"
27 #include "refbase.h"
28 #include "utils_log.h"
29
30 namespace OHOS {
31 namespace Storage {
32 namespace DistributedFile {
33 const std::string HMDFS_PATH = "/mnt/hmdfs/{userId}/account/device_view/local/data/";
34 const std::string USRT_ID_FLAG = "{userId}";
35 const std::string TEMP_DIR = "ASSET_TEMP/";
36 const std::string ASSET_FLAG_SINGLE = ".asset_single?";
37 const std::string ASSET_FLAG_ZIP = ".asset_zip?";
OnFile(int32_t socket,FileEvent * event)38 void SoftbusAssetRecvListener::OnFile(int32_t socket, FileEvent *event)
39 {
40 if (event == nullptr) {
41 LOGE("invalid parameter");
42 return;
43 }
44 switch (event->type) {
45 case FILE_EVENT_RECV_UPDATE_PATH:
46 event->UpdateRecvPath = GetRecvPath;
47 break;
48 case FILE_EVENT_RECV_START:
49 OnRecvAssetStart(socket, event->files, event->fileCnt);
50 break;
51 case FILE_EVENT_RECV_FINISH:
52 OnRecvAssetFinished(socket, event->files, event->fileCnt);
53 break;
54 case FILE_EVENT_RECV_ERROR:
55 OnRecvAssetError(socket, event->errorCode);
56 break;
57 default:
58 LOGI("Other situations");
59 break;
60 }
61 }
62
GetRecvPath()63 const char* SoftbusAssetRecvListener::GetRecvPath()
64 {
65 int32_t userId = GetCurrentUserId();
66
67 std::string path = HMDFS_PATH;
68 auto pos = path.find(USRT_ID_FLAG);
69 if (pos == std::string::npos) {
70 return "";
71 }
72
73 path_ = path.replace(pos, USRT_ID_FLAG.length(), std::to_string(userId));
74 const char* recvPath = path_.c_str();
75 LOGI("SoftbusAssetRecvListener GetRecvPath: %{public}s", recvPath);
76 return recvPath;
77 }
78
OnRecvAssetStart(int32_t socketId,const char ** fileList,int32_t fileCnt)79 void SoftbusAssetRecvListener::OnRecvAssetStart(int32_t socketId, const char **fileList, int32_t fileCnt)
80 {
81 LOGI("OnRecvFileStart, sessionId = %{public}d, fileCnt = %{public}d", socketId, fileCnt);
82 if (fileCnt == 0) {
83 LOGE("fileList has no file");
84 return;
85 }
86 auto srcNetworkId = SoftBusHandlerAsset::GetInstance().GetClientInfo(socketId);
87 if (srcNetworkId.empty()) {
88 LOGE("get srcNetworkId fail");
89 return;
90 }
91 std::string filePath(path_ + fileList[0]);
92 sptr<AssetObj> assetObj (new (std::nothrow) AssetObj());
93 int32_t ret = SoftBusHandlerAsset::GetInstance().GenerateAssetObjInfo(socketId, filePath, assetObj);
94 if (ret != FileManagement::ERR_OK) {
95 LOGE("Generate assetObjInfo fail");
96 return;
97 }
98 AssetCallbackManager::GetInstance().NotifyAssetRecvStart(srcNetworkId,
99 assetObj->dstNetworkId_,
100 assetObj->sessionId_,
101 assetObj->dstBundleName_);
102 }
103
OnRecvAssetFinished(int32_t socketId,const char ** fileList,int32_t fileCnt)104 void SoftbusAssetRecvListener::OnRecvAssetFinished(int32_t socketId, const char **fileList, int32_t fileCnt)
105 {
106 LOGI("OnRecvFileFinished, sessionId = %{public}d, fileCnt = %{public}d", socketId, fileCnt);
107 if (fileCnt == 0) {
108 LOGE("fileList has no file");
109 return;
110 }
111 auto srcNetworkId = SoftBusHandlerAsset::GetInstance().GetClientInfo(socketId);
112 if (srcNetworkId.empty()) {
113 LOGE("get srcNetworkId fail");
114 return;
115 }
116 std::string firstFilePath(path_ + fileList[0]);
117 sptr<AssetObj> assetObj (new (std::nothrow) AssetObj());
118 int32_t ret = SoftBusHandlerAsset::GetInstance().GenerateAssetObjInfo(socketId, firstFilePath, assetObj);
119 if (ret != FileManagement::ERR_OK) {
120 LOGE("Generate assetObjInfo fail");
121 return;
122 }
123 for (int32_t i = 0; i < fileCnt; i++) {
124 std::string filePath(path_ + fileList[i]);
125 if (JudgeSingleFile(filePath)) {
126 ret = HandleSingleFile(socketId, filePath, assetObj);
127 } else {
128 ret = HandleZipFile(socketId, filePath, assetObj);
129 }
130
131 if (ret != FileManagement::ERR_OK) {
132 LOGE("MoveAsset fail, socket %{public}d", socketId);
133 AssetCallbackManager::GetInstance().NotifyAssetRecvFinished(srcNetworkId, assetObj,
134 FileManagement::ERR_BAD_VALUE);
135 SoftBusHandlerAsset::GetInstance().RemoveClientInfo(socketId);
136 return;
137 }
138 }
139 RemoveAsset(firstFilePath);
140 AssetCallbackManager::GetInstance().NotifyAssetRecvFinished(srcNetworkId, assetObj, FileManagement::ERR_OK);
141 SoftBusHandlerAsset::GetInstance().RemoveClientInfo(socketId);
142 }
143
OnRecvAssetError(int32_t socketId,int32_t errorCode)144 void SoftbusAssetRecvListener::OnRecvAssetError(int32_t socketId, int32_t errorCode)
145 {
146 LOGE("OnRecvAssetError, sessionId = %{public}d, errorCode = %{public}d", socketId, errorCode);
147 auto srcNetworkId = SoftBusHandlerAsset::GetInstance().GetClientInfo(socketId);
148 if (srcNetworkId.empty()) {
149 LOGE("get srcNetworkId fail");
150 return;
151 }
152 sptr<AssetObj> nullAssetObj (new (std::nothrow) AssetObj());
153
154 AssetCallbackManager::GetInstance().NotifyAssetRecvFinished(srcNetworkId, nullAssetObj,
155 FileManagement::ERR_BAD_VALUE);
156 SoftBusHandlerAsset::GetInstance().RemoveClientInfo(socketId);
157 }
158
OnAssetRecvBind(int32_t sessionId,PeerSocketInfo info)159 void SoftbusAssetRecvListener::OnAssetRecvBind(int32_t sessionId, PeerSocketInfo info)
160 {
161 LOGI("OnAssetRecvBind begin, sessionId %{public}d", sessionId);
162 SoftBusHandlerAsset::GetInstance().OnAssetRecvBind(sessionId, info.networkId);
163 }
164
GetCurrentUserId()165 int32_t SoftbusAssetRecvListener::GetCurrentUserId()
166 {
167 std::vector<int32_t> userIds{};
168 auto ret = AccountSA::OsAccountManager::QueryActiveOsAccountIds(userIds);
169 if (ret != NO_ERROR || userIds.empty()) {
170 LOGE("query active os account id failed, ret = %{public}d", ret);
171 return FileManagement::E_GET_USER_ID;
172 }
173 LOGI("GetCurrentUserId end.");
174 return userIds[0];
175 }
176
MoveAsset(const std::vector<std::string> & fileList,bool isSingleFile)177 bool SoftbusAssetRecvListener::MoveAsset(const std::vector<std::string> &fileList, bool isSingleFile)
178 {
179 if (isSingleFile) {
180 std::string oldPath = fileList[0];
181 std::string newPath = oldPath;
182 size_t pos = newPath.find(TEMP_DIR);
183 if (pos == std::string::npos) {
184 LOGE("get asset temp dir fail, file name is %{public}s", GetAnonyString(oldPath).c_str());
185 return false;
186 }
187 newPath.replace(pos, TEMP_DIR.length(), "");
188 pos = newPath.find(ASSET_FLAG_SINGLE);
189 if (pos == std::string::npos) {
190 LOGE("get asset flag fail, file name is %{public}s", GetAnonyString(oldPath).c_str());
191 return false;
192 }
193 newPath.resize(pos);
194 try {
195 SoftBusHandlerAsset::GetInstance().MkDirRecurse(newPath, S_IRWXU | S_IRWXG | S_IXOTH);
196 std::filesystem::rename(oldPath.c_str(), newPath.c_str());
197 } catch (const std::filesystem::filesystem_error &e) {
198 LOGE("rename file fail, file name is %{public}s", e.what());
199 return false;
200 }
201 return true;
202 }
203
204 for (auto oldPath : fileList) {
205 std::string newPath = oldPath;
206 size_t pos = newPath.find(TEMP_DIR);
207 if (pos == std::string::npos) {
208 LOGE("get asset temp dir fail, file name is %{public}s", GetAnonyString(oldPath).c_str());
209 return false;
210 }
211 newPath.replace(pos, TEMP_DIR.length(), "");
212 try {
213 SoftBusHandlerAsset::GetInstance().MkDirRecurse(newPath, S_IRWXU | S_IRWXG | S_IXOTH);
214 std::filesystem::rename(oldPath.c_str(), newPath.c_str());
215 } catch (const std::filesystem::filesystem_error &e) {
216 LOGE("rename file fail, file name is %{public}s", e.what());
217 return false;
218 }
219 }
220 return true;
221 }
222
RemoveAsset(const std::string & file)223 bool SoftbusAssetRecvListener::RemoveAsset(const std::string &file)
224 {
225 size_t pos = file.find(TEMP_DIR);
226 if (pos == std::string::npos) {
227 LOGE("get asset temp dir fail, file name is %{public}s", GetAnonyString(file).c_str());
228 return false;
229 }
230 std::string removePath = file.substr(0, pos + TEMP_DIR.length() - 1);
231 bool ret = std::filesystem::remove_all(removePath.c_str());
232 if (!ret) {
233 LOGE("remove file fail, remove path is %{public}s", GetAnonyString(removePath).c_str());
234 return false;
235 }
236 return true;
237 }
238
HandleSingleFile(int32_t socketId,const std::string & filePath,const sptr<AssetObj> & assetObj)239 int32_t SoftbusAssetRecvListener::HandleSingleFile(int32_t socketId,
240 const std::string &filePath,
241 const sptr<AssetObj> &assetObj)
242 {
243 LOGI("HandleSingleFile begin.");
244 std::vector<std::string> fileList = {filePath};
245 auto uris = SoftBusHandlerAsset::GetInstance().GenerateUris(fileList, assetObj->dstBundleName_, true);
246 if (uris.size() == 0) {
247 LOGE("Generate uris fail");
248 return FileManagement::ERR_BAD_VALUE;
249 }
250 assetObj->uris_.emplace_back(uris[0]);
251
252 bool moveRet = MoveAsset(fileList, true);
253 if (!moveRet) {
254 LOGE("MoveAsset fail, socket %{public}d", socketId);
255 return FileManagement::ERR_BAD_VALUE;
256 }
257 LOGI("HandleOneFile end.");
258 return FileManagement::ERR_OK;
259 }
260
HandleZipFile(int32_t socketId,const std::string & filePath,const sptr<AssetObj> & assetObj)261 int32_t SoftbusAssetRecvListener::HandleZipFile(int32_t socketId,
262 const std::string &filePath,
263 const sptr<AssetObj> &assetObj)
264 {
265 LOGI("HandleZipFile begin.");
266 size_t pos = filePath.find(ASSET_FLAG_ZIP);
267 if (pos == std::string::npos) {
268 LOGE("filePath is not a zip file : %{public}s", GetAnonyString(filePath).c_str());
269 return FileManagement::ERR_BAD_VALUE;
270 }
271 std::string zipfilePath = filePath.substr(0, pos);
272 try {
273 std::filesystem::rename(filePath.c_str(), zipfilePath.c_str());
274 } catch (const std::filesystem::filesystem_error &e) {
275 LOGE("rename file fail, file name is %{public}s", e.what());
276 return FileManagement::ERR_BAD_VALUE;
277 }
278 pos = zipfilePath.rfind("/");
279 if (pos == std::string::npos) {
280 LOGE("filePath is not a zip file : %{public}s", GetAnonyString(filePath).c_str());
281 return FileManagement::ERR_BAD_VALUE;
282 }
283 std::string relativePath = zipfilePath.substr(0, pos + 1);
284 std::vector<std::string> fileList = SoftBusHandlerAsset::GetInstance().DecompressFile(zipfilePath, relativePath);
285 if (fileList.empty()) {
286 LOGE("unzip fail");
287 return FileManagement::ERR_BAD_VALUE;
288 }
289
290 auto uris = SoftBusHandlerAsset::GetInstance().GenerateUris(fileList, assetObj->dstBundleName_, false);
291 if (uris.size() == 0) {
292 LOGE("Generate uris fail");
293 return FileManagement::ERR_BAD_VALUE;
294 }
295 assetObj->uris_.insert(assetObj->uris_.end(), uris.begin(), uris.end());
296
297 bool moveRet = MoveAsset(fileList, false);
298 if (!moveRet) {
299 LOGE("MoveAsset fail, socket %{public}d", socketId);
300 return FileManagement::ERR_BAD_VALUE;
301 }
302 LOGI("HandleMoreFile end.");
303 return FileManagement::ERR_OK;
304 }
305
JudgeSingleFile(const std::string & filePath)306 bool SoftbusAssetRecvListener::JudgeSingleFile(const std::string &filePath)
307 {
308 size_t pos = filePath.find(ASSET_FLAG_SINGLE);
309 if (pos == std::string::npos) {
310 LOGI("this file is zip file");
311 return false;
312 }
313 return true;
314 }
315
OnRecvShutdown(int32_t sessionId,ShutdownReason reason)316 void SoftbusAssetRecvListener::OnRecvShutdown(int32_t sessionId, ShutdownReason reason)
317 {
318 LOGI("OnSessionClosed, sessionId = %{public}d, reason = %{public}d", sessionId, reason);
319 }
320 } // namespace DistributedFile
321 } // namespace Storage
322 } // namespace OHOS