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