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