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 #include "media_library_tab_old_photos_client.h"
16
17 #include <limits>
18 #include <string>
19 #include <vector>
20 #include <unordered_map>
21
22 #include "userfilemgr_uri.h"
23 #include "media_column.h"
24 #include "media_log.h"
25 #include "media_old_photos_column.h"
26 #include "medialibrary_errno.h"
27 #include "result_set_utils.h"
28 #include "datashare_helper.h"
29
30 using namespace std;
31
32 namespace OHOS::Media {
GetUrisByOldUris(std::vector<std::string> & uris)33 std::unordered_map<std::string, std::string> TabOldPhotosClient::GetUrisByOldUris(std::vector<std::string>& uris)
34 {
35 std::unordered_map<std::string, std::string> resultMap;
36 if (uris.empty() || static_cast<std::int32_t>(uris.size()) > this->URI_MAX_SIZE) {
37 MEDIA_ERR_LOG("the size is invalid, size = %{public}d", static_cast<std::int32_t>(uris.size()));
38 return resultMap;
39 }
40 std::string queryUri = QUERY_TAB_OLD_PHOTO;
41 Uri uri(queryUri);
42 DataShare::DataSharePredicates predicates;
43 int ret = BuildPredicates(uris, predicates);
44 if (ret != E_OK) {
45 MEDIA_ERR_LOG("build predicates failed");
46 return resultMap;
47 }
48 std::vector<std::string> column;
49 column.push_back(TabOldPhotosColumn::OLD_PHOTOS_TABLE + "." + "file_id");
50 column.push_back(TabOldPhotosColumn::OLD_PHOTOS_TABLE + "." + "data");
51 column.push_back(TabOldPhotosColumn::OLD_PHOTOS_TABLE + "." + "old_file_id");
52 column.push_back(TabOldPhotosColumn::OLD_PHOTOS_TABLE + "." + "old_data");
53 column.push_back(PhotoColumn::PHOTOS_TABLE + "." + "display_name");
54 int errCode = 0;
55 std::shared_ptr<DataShare::DataShareResultSet> dataShareResultSet =
56 this->GetResultSetFromTabOldPhotos(uri, predicates, column, errCode);
57 if (dataShareResultSet == nullptr) {
58 MEDIA_ERR_LOG("query failed");
59 return resultMap;
60 }
61 return this->GetResultMap(dataShareResultSet, uris);
62 }
63
GetResultSetFromTabOldPhotos(Uri & uri,const DataShare::DataSharePredicates & predicates,std::vector<std::string> & columns,int & errCode)64 std::shared_ptr<DataShare::DataShareResultSet> TabOldPhotosClient::GetResultSetFromTabOldPhotos(
65 Uri &uri, const DataShare::DataSharePredicates &predicates, std::vector<std::string> &columns, int &errCode)
66 {
67 std::shared_ptr<DataShare::DataShareResultSet> resultSet;
68 DataShare::DatashareBusinessError businessError;
69 sptr<IRemoteObject> token = this->mediaLibraryManager_.InitToken();
70 std::shared_ptr<DataShare::DataShareHelper> dataShareHelper =
71 DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
72 if (dataShareHelper == nullptr) {
73 MEDIA_ERR_LOG("dataShareHelper is nullptr");
74 return nullptr;
75 }
76 resultSet = dataShareHelper->Query(uri, predicates, columns, &businessError);
77 int count = 0;
78 if (resultSet == nullptr) {
79 MEDIA_ERR_LOG("Query failed, code: %{public}d", businessError.GetCode());
80 return nullptr;
81 }
82 auto ret = resultSet->GetRowCount(count);
83 if (ret != NativeRdb::E_OK) {
84 MEDIA_ERR_LOG("Resultset check failed, ret: %{public}d", ret);
85 return nullptr;
86 }
87 return resultSet;
88 }
89
BuildPredicates(const std::vector<std::string> & queryTabOldPhotosUris,DataShare::DataSharePredicates & predicates)90 int TabOldPhotosClient::BuildPredicates(const std::vector<std::string> &queryTabOldPhotosUris,
91 DataShare::DataSharePredicates &predicates)
92 {
93 const std::string GALLERY_URI_PREFIX = "//media";
94 const std::string GALLERY_PATH = "/storage/emulated";
95
96 vector<string> clauses;
97 clauses.push_back(PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_ID + " = " +
98 TabOldPhotosColumn::OLD_PHOTOS_TABLE + "." + TabOldPhotosColumn::MEDIA_ID);
99 predicates.InnerJoin(PhotoColumn::PHOTOS_TABLE)->On(clauses);
100
101 int conditionCount = 0;
102 for (const auto &uri : queryTabOldPhotosUris) {
103 if (uri.find(GALLERY_URI_PREFIX) != std::string::npos) {
104 size_t lastSlashPos = uri.rfind('/');
105 if (lastSlashPos != std::string::npos && lastSlashPos + 1 < uri.length()) {
106 std::string idStr = uri.substr(lastSlashPos + 1);
107 predicates.Or()->EqualTo(TabOldPhotosColumn::MEDIA_OLD_ID, idStr);
108 conditionCount += 1;
109 }
110 } else if (uri.find(GALLERY_PATH) != std::string::npos) {
111 predicates.Or()->EqualTo(TabOldPhotosColumn::MEDIA_OLD_FILE_PATH, uri);
112 conditionCount += 1;
113 } else if (!uri.empty() && std::all_of(uri.begin(), uri.end(), ::isdigit)) {
114 predicates.Or()->EqualTo(TabOldPhotosColumn::MEDIA_OLD_ID, uri);
115 conditionCount += 1;
116 }
117 }
118 if (conditionCount == 0) {
119 MEDIA_ERR_LOG("Zero uri condition");
120 return E_FAIL;
121 }
122
123 return E_OK;
124 }
125
Parse(std::shared_ptr<DataShare::DataShareResultSet> & resultSet)126 std::vector<TabOldPhotosClient::TabOldPhotosClientObj> TabOldPhotosClient::Parse(
127 std::shared_ptr<DataShare::DataShareResultSet> &resultSet)
128 {
129 std::vector<TabOldPhotosClient::TabOldPhotosClientObj> result;
130 if (resultSet == nullptr) {
131 MEDIA_ERR_LOG("resultSet is null");
132 return result;
133 }
134 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
135 TabOldPhotosClient::TabOldPhotosClientObj obj;
136 obj.fileId = GetInt32Val(this->COLUMN_FILE_ID, resultSet);
137 obj.data = GetStringVal(this->COLUMN_DATA, resultSet);
138 obj.displayName = GetStringVal(this->COLUMN_DISPLAY_NAME, resultSet);
139 obj.oldFileId = GetInt32Val(this->COLUMN_OLD_FILE_ID, resultSet);
140 obj.oldData = GetStringVal(this->COLUMN_OLD_DATA, resultSet);
141 result.emplace_back(obj);
142 }
143 return result;
144 }
145
StoiBoundCheck(std::string toCheck)146 static bool StoiBoundCheck(std::string toCheck)
147 {
148 const std::string intMax = std::to_string(std::numeric_limits<int>::max());
149
150 return toCheck.length() < intMax.length();
151 }
152
Parse(std::vector<std::string> & queryTabOldPhotosUris)153 std::vector<TabOldPhotosClient::RequestUriObj> TabOldPhotosClient::Parse(
154 std::vector<std::string> &queryTabOldPhotosUris)
155 {
156 const std::string GALLERY_URI_PREFIX = "//media";
157 const std::string GALLERY_PATH = "/storage/emulated";
158 std::vector<TabOldPhotosClient::RequestUriObj> result;
159 for (const auto &uri : queryTabOldPhotosUris) {
160 TabOldPhotosClient::RequestUriObj obj;
161 obj.type = URI_TYPE_DEFAULT;
162 obj.requestUri = uri;
163
164 if (uri.find(GALLERY_URI_PREFIX) != std::string::npos) {
165 size_t lastSlashPos = uri.rfind('/');
166 if (lastSlashPos == std::string::npos || lastSlashPos + 1 >= uri.length()) {
167 MEDIA_ERR_LOG("Error locating media id in media uri: %{public}s", uri.c_str());
168 continue;
169 }
170 std::string idStr = uri.substr(lastSlashPos + 1);
171 if (!(!idStr.empty() && std::all_of(idStr.begin(), idStr.end(), ::isdigit)) || !StoiBoundCheck(idStr)) {
172 MEDIA_ERR_LOG("Media id is invalid in uri: %{public}s", uri.c_str());
173 continue;
174 }
175 obj.type = URI_TYPE_ID_LINK;
176 obj.oldFileId = std::stoi(idStr);
177 } else if (uri.find(GALLERY_PATH) != std::string::npos) {
178 obj.type = URI_TYPE_PATH;
179 obj.oldData = uri;
180 } else if (!uri.empty() && std::all_of(uri.begin(), uri.end(), ::isdigit) && StoiBoundCheck(uri)) {
181 int oldFileId = std::stoi(uri);
182 obj.type = URI_TYPE_ID;
183 obj.oldFileId = oldFileId;
184 }
185 if (obj.type == URI_TYPE_DEFAULT) {
186 continue;
187 }
188 result.emplace_back(obj);
189 }
190 return result;
191 }
192
BuildRequestUri(const TabOldPhotosClient::TabOldPhotosClientObj & dataObj)193 std::string TabOldPhotosClient::BuildRequestUri(const TabOldPhotosClient::TabOldPhotosClientObj &dataObj)
194 {
195 std::string filePath = dataObj.data;
196 std::string displayName = dataObj.displayName;
197 int32_t fileId = dataObj.fileId;
198 std::string baseUri = "file://media";
199 size_t lastSlashInData = filePath.rfind('/');
200 std::string fileNameInData =
201 (lastSlashInData != std::string::npos) ? filePath.substr(lastSlashInData + 1) : filePath;
202 size_t dotPos = fileNameInData.rfind('.');
203 if (dotPos != std::string::npos) {
204 fileNameInData = fileNameInData.substr(0, dotPos);
205 }
206 return baseUri + "/Photo/" + std::to_string(fileId) + "/" + fileNameInData + "/" + displayName;
207 }
208
Build(const TabOldPhotosClient::RequestUriObj & requestUriObj,const std::vector<TabOldPhotosClient::TabOldPhotosClientObj> & dataMapping)209 std::pair<std::string, std::string> TabOldPhotosClient::Build(const TabOldPhotosClient::RequestUriObj &requestUriObj,
210 const std::vector<TabOldPhotosClient::TabOldPhotosClientObj> &dataMapping)
211 {
212 if (requestUriObj.type == URI_TYPE_ID_LINK || requestUriObj.type == URI_TYPE_ID) {
213 int32_t oldFileId = requestUriObj.oldFileId;
214 auto it = std::find_if(dataMapping.begin(),
215 dataMapping.end(),
216 [oldFileId](const TabOldPhotosClient::TabOldPhotosClientObj &obj) {return obj.oldFileId == oldFileId;});
217 if (it != dataMapping.end()) {
218 return std::make_pair(requestUriObj.requestUri, this->BuildRequestUri(*it));
219 }
220 }
221 if (requestUriObj.type == URI_TYPE_PATH) {
222 std::string oldData = requestUriObj.oldData;
223 auto it = std::find_if(dataMapping.begin(),
224 dataMapping.end(),
225 [oldData](const TabOldPhotosClient::TabOldPhotosClientObj &obj) {return obj.oldData == oldData;});
226 if (it != dataMapping.end()) {
227 return std::make_pair(requestUriObj.requestUri, this->BuildRequestUri(*it));
228 }
229 }
230 return std::make_pair(requestUriObj.requestUri, "");
231 }
232
Parse(const std::vector<TabOldPhotosClient::TabOldPhotosClientObj> & dataMapping,std::vector<RequestUriObj> & uriList)233 std::unordered_map<std::string, std::string> TabOldPhotosClient::Parse(
234 const std::vector<TabOldPhotosClient::TabOldPhotosClientObj> &dataMapping, std::vector<RequestUriObj> &uriList)
235 {
236 std::unordered_map<std::string, std::string> resultMap;
237 for (const auto &requestUriObj : uriList) {
238 std::pair<std::string, std::string> pair = this->Build(requestUriObj, dataMapping);
239 resultMap[pair.first] = pair.second;
240 }
241 return resultMap;
242 }
243
GetResultMap(std::shared_ptr<DataShareResultSet> & resultSet,std::vector<std::string> & queryTabOldPhotosUris)244 std::unordered_map<std::string, std::string> TabOldPhotosClient::GetResultMap(
245 std::shared_ptr<DataShareResultSet> &resultSet, std::vector<std::string> &queryTabOldPhotosUris)
246 {
247 std::unordered_map<std::string, std::string> resultMap;
248 if (resultSet == nullptr) {
249 MEDIA_ERR_LOG("resultSet is null");
250 return resultMap;
251 }
252 std::vector<TabOldPhotosClient::TabOldPhotosClientObj> dataMapping = this->Parse(resultSet);
253 std::vector<TabOldPhotosClient::RequestUriObj> uriList = this->Parse(queryTabOldPhotosUris);
254 return this->Parse(dataMapping, uriList);
255 }
256 } // namespace OHOS::Media
257