1 /*
2  * Copyright (c) 2023-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_session_listener.h"
17 
18 #include "dfs_error.h"
19 #include "network/softbus/softbus_session_pool.h"
20 #include "os_account_manager.h"
21 #include "sandbox_helper.h"
22 #include "string"
23 #include "uri.h"
24 #include "utils_directory.h"
25 #include "utils_log.h"
26 
27 namespace OHOS {
28 namespace Storage {
29 namespace DistributedFile {
30 constexpr size_t MAX_SIZE = 500;
31 constexpr int32_t DEFAULT_USER_ID = 100;
32 const std::string FILE_SCHEMA = "file://";
33 const std::string DOCS = "docs";
34 const std::string NETWORK_ID = "?networkid=";
35 const std::string FILE_SEPARATOR = "/";
36 const std::string DISTRIBUTED_PATH = "distributedfiles/.remote_share/";
37 const std::string MEDIA = "media";
38 using namespace OHOS::AppFileService;
39 using namespace OHOS::FileManagement;
40 
QueryActiveUserId()41 int32_t SoftBusSessionListener::QueryActiveUserId()
42 {
43     std::vector<int32_t> ids;
44     ErrCode errCode = AccountSA::OsAccountManager::QueryActiveOsAccountIds(ids);
45     if (errCode != FileManagement::ERR_OK || ids.empty()) {
46         LOGE("Query active userid failed, errCode: %{public}d, ", errCode);
47         return DEFAULT_USER_ID;
48     }
49     return ids[0];
50 }
51 
GetFileName(const std::vector<std::string> & fileList,const std::string & path,const std::string & dstPath)52 std::vector<std::string> SoftBusSessionListener::GetFileName(const std::vector<std::string> &fileList,
53                                                              const std::string &path,
54                                                              const std::string &dstPath)
55 {
56     std::vector<std::string> tmp;
57     if (Utils::IsFolder(path)) {
58         for (const auto &it : fileList) {
59             tmp.push_back(it.substr(path.size() + 1));
60         }
61         return tmp;
62     }
63     if (dstPath.find("??") == 0) {
64         auto pos = dstPath.rfind("/");
65         tmp.push_back(dstPath.substr(pos + 1));
66     } else {
67         auto pos = path.rfind("/");
68         tmp.push_back(path.substr(pos + 1));
69     }
70     return tmp;
71 }
72 
OnSessionOpened(int32_t sessionId,PeerSocketInfo info)73 void SoftBusSessionListener::OnSessionOpened(int32_t sessionId, PeerSocketInfo info)
74 {
75     LOGI("OnSessionOpened sessionId = %{public}d", sessionId);
76     if (!SoftBusHandler::IsSameAccount(info.networkId)) {
77         LOGI("The source and sink device is not same account, not support.");
78         Shutdown(sessionId);
79         return;
80     }
81     std::string sessionName = info.name;
82     SoftBusSessionPool::SessionInfo sessionInfo;
83     auto ret = SoftBusSessionPool::GetInstance().GetSessionInfo(sessionName, sessionInfo);
84     if (!ret) {
85         LOGE("GetSessionInfo failed");
86         return;
87     }
88 
89     std::string physicalPath = GetRealPath(sessionInfo.srcUri);
90     if (physicalPath.empty()) {
91         LOGE("GetRealPath failed");
92         return;
93     }
94 
95     auto fileList = OHOS::Storage::DistributedFile::Utils::GetFilePath(physicalPath);
96     if (fileList.empty()) {
97         LOGE("GetFilePath failed or file is empty");
98         return;
99     }
100 
101     const char *src[MAX_SIZE] = {};
102     for (size_t i = 0; i < fileList.size() && fileList.size() < MAX_SIZE; i++) {
103         src[i] = fileList.at(i).c_str();
104     }
105 
106     auto fileNameList = GetFileName(fileList, physicalPath, sessionInfo.dstPath);
107     if (fileNameList.empty()) {
108         LOGE("GetFileName failed or file is empty");
109         return;
110     }
111     const char *dst[MAX_SIZE] = {};
112     for (size_t i = 0; i < fileNameList.size() && fileList.size() < MAX_SIZE; i++) {
113         dst[i] = fileNameList.at(i).c_str();
114     }
115     LOGI("Enter SendFile.");
116     ret = ::SendFile(sessionId, src, dst, static_cast<uint32_t>(fileList.size()));
117     if (ret != E_OK) {
118         LOGE("SendFile failed, sessionId = %{public}d", sessionId);
119         RadarDotsSendFile("OpenSession", sessionName, sessionName, ret, Utils::StageRes::STAGE_FAIL);
120     }
121     SoftBusSessionPool::GetInstance().DeleteSessionInfo(sessionName);
122     RadarDotsSendFile("OpenSession", sessionName, sessionName, ret, Utils::StageRes::STAGE_SUCCESS);
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, physicalPath = %{public}s", GetAnonyString(physicalPath).c_str());
179         return "";
180     }
181     if (physicalPath.empty() || physicalPath.size() >= PATH_MAX) {
182         LOGE("PhysicalPath.size() = %{public}zu", physicalPath.size());
183         return "";
184     }
185     char realPath[PATH_MAX] = { 0x00 };
186     if (realpath(physicalPath.c_str(), realPath) == nullptr) {
187         LOGE("realpath failed, error: %{public}d, path is %{public}s", errno, GetAnonyString(physicalPath).c_str());
188         return "";
189     }
190     return physicalPath;
191 }
192 } // namespace DistributedFile
193 } // namespace Storage
194 } // namespace OHOS