1 /*
2 * Copyright (C) 2021-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 #define MLOG_TAG "MediaLibraryHandler"
16
17 #include "media_library_handler.h"
18
19 #include <sys/stat.h>
20 #include <unistd.h>
21 #include <string>
22 #include <sstream>
23 #include <vector>
24 #include <securec.h>
25 #include "accesstoken_kit.h"
26 #include "datashare_abs_result_set.h"
27 #include "datashare_predicates.h"
28 #include "iservice_registry.h"
29 #include "media_log.h"
30 #include "medialibrary_db_const.h"
31 #include "medialibrary_errno.h"
32 #include "medialibrary_type_const.h"
33 #include "string_ex.h"
34 #include "system_ability_definition.h"
35 #include "userfilemgr_uri.h"
36 #include "rdb_errno.h"
37 #include "os_account_manager.h"
38
39 using namespace std;
40 using namespace OHOS::NativeRdb;
41 using namespace OHOS::Security::AccessToken;
42
43 extern "C" {
ConvertFileUriToMntPath(const vector<string> & uris,vector<string> & results)44 void ConvertFileUriToMntPath(const vector<string> &uris, vector<string> &results)
45 {
46 int32_t userId = 0;
47 OHOS::ErrCode errCode = OHOS::AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(userId);
48 if (errCode != OHOS::ERR_OK) {
49 MEDIA_ERR_LOG("GetForegroundOsAccountLocalId fail, code %{public}d", errCode);
50 results.clear();
51 return;
52 }
53
54 vector<string> dataUris;
55 auto handler = OHOS::Media::MediaLibraryHandler::GetMediaLibraryHandler();
56 handler->InitMediaLibraryHandler();
57 int32_t ret = handler->GetDataUris(uris, dataUris);
58 if (ret != OHOS::Media::E_SUCCESS) {
59 results.clear();
60 MEDIA_ERR_LOG("Failed to GetDataPath: %{public}d", ret);
61 return;
62 }
63 results.clear();
64 for (vector<string>::size_type i = 0; i < dataUris.size(); i++) {
65 if (dataUris[i].empty()) {
66 results.clear();
67 return;
68 }
69 std::ostringstream oss;
70 oss << OHOS::Media::HMDFS << userId << OHOS::Media::CLOUD_MERGE_VIEW << dataUris[i];
71 results.emplace_back(oss.str());
72 }
73 }
74 }
75
76 namespace OHOS {
77 namespace Media {
78 shared_ptr<DataShare::DataShareHelper> MediaLibraryHandler::sDataShareHelper_ = nullptr;
79 sptr<IRemoteObject> MediaLibraryHandler::token_ = nullptr;
80
GetMediaLibraryHandler()81 MediaLibraryHandler *MediaLibraryHandler::GetMediaLibraryHandler()
82 {
83 static MediaLibraryHandler mediaLibHandler;
84 return &mediaLibHandler;
85 }
86
InitToken()87 sptr<IRemoteObject> MediaLibraryHandler::InitToken()
88 {
89 auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
90 if (saManager == nullptr) {
91 MEDIA_ERR_LOG("get system ability mgr failed.");
92 return nullptr;
93 }
94 auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID);
95 if (remoteObj == nullptr) {
96 MEDIA_ERR_LOG("GetSystemAbility Service failed.");
97 return nullptr;
98 }
99 return remoteObj;
100 }
101
InitMediaLibraryHandler()102 void MediaLibraryHandler::InitMediaLibraryHandler()
103 {
104 if (sDataShareHelper_ == nullptr) {
105 token_ = InitToken();
106 if (token_ != nullptr) {
107 sDataShareHelper_ = DataShare::DataShareHelper::Creator(token_, MEDIALIBRARY_DATA_URI);
108 }
109 }
110 }
111
GetResultSetFromPhotos(const string & columnName,const vector<string> & values,vector<string> & columns,shared_ptr<DataShare::DataShareHelper> & dataShareHelper)112 std::shared_ptr<DataShareResultSet> GetResultSetFromPhotos(const string &columnName, const vector<string> &values,
113 vector<string> &columns, shared_ptr<DataShare::DataShareHelper> &dataShareHelper)
114 {
115 Uri queryUri(PAH_QUERY_CONVERT_PHOTOS);
116 DataSharePredicates predicates;
117 predicates.In(columnName, values);
118 DatashareBusinessError businessError;
119 return dataShareHelper->Query(queryUri, predicates, columns, &businessError);
120 }
121
StartWith(const string & str,const string & prefix)122 inline bool StartWith(const string &str, const string &prefix)
123 {
124 return str.compare(0, prefix.size(), prefix) == 0;
125 }
126
GetFileIds(const vector<string> & uris,vector<string> & results,vector<string> & realIds)127 bool GetFileIds(const vector<string> &uris, vector<string> &results, vector<string> &realIds)
128 {
129 for (vector<string>::size_type i = 0; i < uris.size(); i++) {
130 string uri = uris[i];
131 if (!StartWith(uri, MEDIA_PHOTO_URI)) {
132 MEDIA_ERR_LOG("%{private}s fails to start with: %{private}s", uri.c_str(), MEDIA_PHOTO_URI.c_str());
133 return false;
134 }
135
136 size_t size_media_photo = MEDIA_PHOTO_URI.size();
137 size_t index = uri.find("/", size_media_photo);
138 if (index == string::npos) {
139 MEDIA_ERR_LOG("failed to find /, path is %{private}s", uri.c_str());
140 return false;
141 }
142
143 string fileId = uri.substr(size_media_photo, index - size_media_photo);
144 if (!all_of(fileId.begin(), fileId.end(), ::isdigit)) {
145 MEDIA_ERR_LOG("fileId is not digit, fileId is %{private}s", fileId.c_str());
146 return false;
147 }
148 results.push_back(fileId);
149
150 auto it = std::find(realIds.begin(), realIds.end(), fileId);
151 if (it == realIds.end()) {
152 realIds.push_back(fileId);
153 }
154 }
155 return true;
156 }
157
GetDataUris(const vector<string> & uris,vector<string> & dataUris)158 int32_t MediaLibraryHandler::GetDataUris(const vector<string> &uris, vector<string> &dataUris)
159 {
160 if (uris.empty()) {
161 MEDIA_ERR_LOG("uris is empty");
162 return E_FAIL;
163 }
164 if (sDataShareHelper_ == nullptr) {
165 MEDIA_ERR_LOG("dataShareHelper is nullptr");
166 return E_FAIL;
167 }
168
169 vector<string> fileIds;
170 vector<string> realIds;
171 if (!GetFileIds(uris, fileIds, realIds)) {
172 return E_FAIL;
173 }
174
175 vector<string> columns = {MEDIA_DATA_DB_ID, MEDIA_DATA_DB_FILE_PATH};
176 auto resultSet = GetResultSetFromPhotos(MEDIA_DATA_DB_ID, realIds, columns, sDataShareHelper_);
177 if (resultSet == nullptr) {
178 MEDIA_ERR_LOG("resultSet is nullptr");
179 return E_FAIL;
180 }
181 if (ProcessResultSet(resultSet, dataUris, fileIds) != E_SUCCESS) {
182 resultSet->Close();
183 return E_FAIL;
184 }
185 resultSet->Close();
186 return E_SUCCESS;
187 }
188
ProcessResultSet(shared_ptr<DataShareResultSet> & resultSet,vector<string> & dataUris,vector<string> & fileIds)189 int32_t MediaLibraryHandler::ProcessResultSet(shared_ptr<DataShareResultSet> &resultSet,
190 vector<string> &dataUris, vector<string> &fileIds)
191 {
192 int32_t row = 0;
193 if (CheckResultSet(resultSet, row) != E_SUCCESS) {
194 return E_FAIL;
195 }
196
197 dataUris = vector<string>(fileIds.size());
198
199 size_t count = 0;
200 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
201 string fileId;
202 string path;
203 if (resultSet->GetString(0, fileId) != NativeRdb::E_OK) {
204 return E_FAIL;
205 }
206
207 if (resultSet->GetString(1, path) != NativeRdb::E_OK) {
208 return E_FAIL;
209 }
210
211 if (!StartWith(path, ROOT_MEDIA_DIR)) {
212 MEDIA_ERR_LOG("%{private}s fails to start with: %{private}s", path.c_str(), ROOT_MEDIA_DIR.c_str());
213 return E_FAIL;
214 }
215
216 for (vector<string>::size_type j = 0; j < dataUris.size(); j++) {
217 if (dataUris[j].empty() && fileIds[j] == fileId) {
218 dataUris[j] = path.substr(ROOT_MEDIA_DIR.length());
219 count++;
220 }
221 }
222 }
223
224 if (count != dataUris.size()) {
225 return E_FAIL;
226 }
227 return E_SUCCESS;
228 }
229
CheckResultSet(shared_ptr<DataShareResultSet> & resultSet,int32_t & row)230 int32_t MediaLibraryHandler::CheckResultSet(shared_ptr<DataShareResultSet> &resultSet, int32_t &row)
231 {
232 auto ret = resultSet->GetRowCount(row);
233 if (ret != NativeRdb::E_OK) {
234 MEDIA_ERR_LOG("Failed to get resultset row count, ret: %{public}d", ret);
235 return ret;
236 }
237 if (row <= 0) {
238 MEDIA_ERR_LOG("Failed to get count, count: %{public}d", row);
239 return E_FAIL;
240 }
241 return E_SUCCESS;
242 }
243 } // namespace Media
244 } // namespace OHOS
245