1 /*
2 * Copyright (c) 2023-2025 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_session_listener.h"
17
18 #include "copy/file_size_utils.h"
19 #include "dfs_error.h"
20 #include "network/softbus/softbus_session_pool.h"
21 #include "network/softbus/softbus_permission_check.h"
22 #include "os_account_manager.h"
23 #include "sandbox_helper.h"
24 #include "string"
25 #include "uri.h"
26 #include "utils_directory.h"
27 #include "utils_log.h"
28
29 namespace OHOS {
30 namespace Storage {
31 namespace DistributedFile {
32 constexpr size_t MAX_SIZE = 500;
33 constexpr int32_t DEFAULT_USER_ID = 100;
34 const std::string FILE_SCHEMA = "file://";
35 const std::string DOCS = "docs";
36 const std::string NETWORK_ID = "?networkid=";
37 const std::string FILE_SEPARATOR = "/";
38 const std::string DISTRIBUTED_PATH = "distributedfiles/.remote_share/";
39 const std::string MEDIA = "media";
40 using namespace OHOS::AppFileService;
41 using namespace OHOS::FileManagement;
42
QueryActiveUserId()43 int32_t SoftBusSessionListener::QueryActiveUserId()
44 {
45 std::vector<int32_t> ids;
46 ErrCode errCode = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
47 if (errCode != FileManagement::ERR_OK || ids.empty()) {
48 LOGE("Query active userid failed, errCode: %{public}d, ", errCode);
49 return DEFAULT_USER_ID;
50 }
51 return ids[0];
52 }
53
GetFileName(const std::vector<std::string> & fileList,const std::string & path,const std::string & dstPath)54 std::vector<std::string> SoftBusSessionListener::GetFileName(const std::vector<std::string> &fileList,
55 const std::string &path,
56 const std::string &dstPath)
57 {
58 std::vector<std::string> tmp;
59 if (Utils::IsFolder(path)) {
60 for (const auto &it : fileList) {
61 tmp.push_back(it.substr(path.size() + 1));
62 }
63 return tmp;
64 }
65 if (dstPath.find("??") == 0) {
66 auto pos = dstPath.rfind("/");
67 tmp.push_back(dstPath.substr(pos + 1));
68 } else {
69 auto pos = path.rfind("/");
70 tmp.push_back(path.substr(pos + 1));
71 }
72 return tmp;
73 }
74
OnSessionOpened(int32_t sessionId,PeerSocketInfo info)75 void SoftBusSessionListener::OnSessionOpened(int32_t sessionId, PeerSocketInfo info)
76 {
77 LOGI("OnSessionOpened sessionId = %{public}d", sessionId);
78 if (!SoftBusPermissionCheck::IsSameAccount(info.networkId)) {
79 LOGI("The source and sink device is not same account, not support.");
80 Shutdown(sessionId);
81 return;
82 }
83 std::string sessionName = info.name;
84 SoftBusSessionPool::SessionInfo sessionInfo;
85 auto ret = SoftBusSessionPool::GetInstance().GetSessionInfo(sessionName, sessionInfo);
86 if (!ret) {
87 LOGE("GetSessionInfo failed");
88 return;
89 }
90
91 std::string physicalPath = GetRealPath(sessionInfo.srcUri);
92 if (physicalPath.empty()) {
93 LOGE("GetRealPath failed");
94 return;
95 }
96
97 auto fileList = OHOS::Storage::DistributedFile::Utils::GetFilePath(physicalPath);
98 if (fileList.empty()) {
99 LOGE("GetFilePath failed or file is empty");
100 return;
101 }
102
103 const char *src[MAX_SIZE] = {};
104 for (size_t i = 0; i < fileList.size() && fileList.size() < MAX_SIZE; i++) {
105 src[i] = fileList.at(i).c_str();
106 }
107
108 auto fileNameList = GetFileName(fileList, physicalPath, sessionInfo.dstPath);
109 if (fileNameList.empty()) {
110 LOGE("GetFileName failed or file is empty");
111 return;
112 }
113 const char *dst[MAX_SIZE] = {};
114 for (size_t i = 0; i < fileNameList.size() && fileList.size() < MAX_SIZE; i++) {
115 dst[i] = fileNameList.at(i).c_str();
116 }
117 LOGI("Enter SendFile.");
118 ret = ::SendFile(sessionId, src, dst, static_cast<uint32_t>(fileList.size()));
119 if (ret != E_OK) {
120 LOGE("SendFile failed, sessionId = %{public}d", sessionId);
121 }
122 SoftBusSessionPool::GetInstance().DeleteSessionInfo(sessionName);
123 }
124
OnSessionClosed(int32_t sessionId,ShutdownReason reason)125 void SoftBusSessionListener::OnSessionClosed(int32_t sessionId, ShutdownReason reason)
126 {
127 (void)reason;
128 std::string sessionName = "";
129 sessionName = SoftBusHandler::GetSessionName(sessionId);
130 LOGI("OnSessionClosed, sessionId = %{public}d", sessionId);
131 SoftBusHandler::GetInstance().CloseSessionWithSessionName(sessionName);
132 }
133
GetLocalUri(const std::string & uri)134 std::string SoftBusSessionListener::GetLocalUri(const std::string &uri)
135 {
136 auto pos = uri.find(NETWORK_ID);
137 if (pos == std::string::npos) {
138 return "";
139 }
140 return uri.substr(0, pos);
141 }
142
GetBundleName(const std::string & uri)143 std::string SoftBusSessionListener::GetBundleName(const std::string &uri)
144 {
145 auto pos = uri.find(FILE_SCHEMA);
146 if (pos == std::string::npos) {
147 return "";
148 }
149 auto tmpUri = uri.substr(pos + FILE_SCHEMA.size());
150 if (tmpUri.empty()) {
151 return "";
152 }
153 auto bundleNamePos = tmpUri.find(FILE_SEPARATOR);
154 if (bundleNamePos == std::string::npos) {
155 return "";
156 }
157 return tmpUri.substr(0, bundleNamePos);
158 }
159
GetSandboxPath(const std::string & uri)160 std::string SoftBusSessionListener::GetSandboxPath(const std::string &uri)
161 {
162 auto pos = uri.find(DISTRIBUTED_PATH);
163 if (pos == std::string::npos) {
164 return "";
165 }
166 return uri.substr(pos + DISTRIBUTED_PATH.size());
167 }
168
GetRealPath(const std::string & srcUri)169 std::string SoftBusSessionListener::GetRealPath(const std::string &srcUri)
170 {
171 std::string localUri = GetLocalUri(srcUri);
172 if (localUri.empty()) {
173 LOGE("get local uri failed.");
174 return localUri;
175 }
176 std::string physicalPath;
177 if (SandboxHelper::GetPhysicalPath(localUri, std::to_string(QueryActiveUserId()), physicalPath) != E_OK) {
178 LOGE("GetPhysicalPath failed, invalid uri");
179 return "";
180 }
181 if (physicalPath.empty() || physicalPath.size() >= PATH_MAX) {
182 LOGE("PhysicalPath.size() = %{public}zu", physicalPath.size());
183 return "";
184 }
185 if (!FileSizeUtils::IsFilePathValid(physicalPath)) {
186 LOGE("Check physicalPath err, physicalPath is forbidden");
187 return "";
188 }
189 char realPath[PATH_MAX] = { 0x00 };
190 if (realpath(physicalPath.c_str(), realPath) == nullptr) {
191 LOGE("realpath failed, error: %{public}d", errno);
192 return "";
193 }
194 return physicalPath;
195 }
196 } // namespace DistributedFile
197 } // namespace Storage
198 } // namespace OHOS