• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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