• 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 
16 #include "photo_accesshelper_utils.h"
17 
18 #include "media_device_column.h"
19 #include "medialibrary_napi_enum_comm.h"
20 
21 using namespace std;
22 using namespace OHOS::DataShare;
23 using namespace OHOS::FFI;
24 
25 namespace OHOS {
26 namespace Media {
27 
28 static const int32_t FIELD_IDX = 0;
29 static const int32_t VALUE_IDX = 1;
30 
MallocCString(const std::string & origin)31 char *MallocCString(const std::string &origin)
32 {
33     if (origin.empty()) {
34         return nullptr;
35     }
36     auto len = origin.length() + 1;
37     char *res = static_cast<char *>(malloc(sizeof(char) * len));
38     if (res == nullptr) {
39         return nullptr;
40     }
41     return std::char_traits<char>::copy(res, origin.c_str(), len);
42 }
43 
HandleSpecialDateTypePredicate(const OperationItem & item,vector<OperationItem> & operations,const FetchOptionType & fetchOptType)44 static bool HandleSpecialDateTypePredicate(const OperationItem &item,
45     vector<OperationItem> &operations, const FetchOptionType &fetchOptType)
46 {
47     vector<string>dateTypes = { MEDIA_DATA_DB_DATE_ADDED, MEDIA_DATA_DB_DATE_TRASHED, MEDIA_DATA_DB_DATE_MODIFIED,
48         MEDIA_DATA_DB_DATE_TAKEN};
49     string dateType = item.GetSingle(FIELD_IDX);
50     auto it = find(dateTypes.begin(), dateTypes.end(), dateType);
51     if (it != dateTypes.end() && item.operation != DataShare::ORDER_BY_ASC &&
52         item.operation != DataShare::ORDER_BY_DESC) {
53         dateType += "_s";
54         operations.push_back({ item.operation, { dateType, static_cast<double>(item.GetSingle(VALUE_IDX)) } });
55         return true;
56     }
57     if (DATE_TRANSITION_MAP.count(dateType) != 0) {
58         dateType = DATE_TRANSITION_MAP.at(dateType);
59         operations.push_back({ item.operation, { dateType, static_cast<double>(item.GetSingle(VALUE_IDX)) } });
60         return true;
61     }
62     return false;
63 }
64 
HandleSpecialPredicate(shared_ptr<DataSharePredicates> & predicatePtr,DataSharePredicates & predicates,ExtraInfo & extraInfo)65 static bool HandleSpecialPredicate(shared_ptr<DataSharePredicates> &predicatePtr,
66     DataSharePredicates &predicates, ExtraInfo &extraInfo)
67 {
68     vector<OperationItem> operations;
69     auto &items = predicatePtr->GetOperationList();
70     for (auto &item : items) {
71         if (item.singleParams.empty()) {
72             operations.push_back(item);
73             continue;
74         }
75         if (HandleSpecialDateTypePredicate(item, operations, extraInfo.fetchOptType)) {
76             continue;
77         }
78         if (static_cast<string>(item.GetSingle(FIELD_IDX)) == DEVICE_DB_NETWORK_ID) {
79             if (item.operation != DataShare::EQUAL_TO || static_cast<string>(item.GetSingle(VALUE_IDX)).empty()) {
80                 LOGE("DEVICE_DB_NETWORK_ID predicates not support %{public}d", item.operation);
81                 return false;
82             }
83             extraInfo.networkId = static_cast<string>(item.GetSingle(VALUE_IDX));
84             continue;
85         } else if (static_cast<string>(item.GetSingle(FIELD_IDX)) == MEDIA_DATA_DB_URI) {
86             if (item.operation != DataShare::EQUAL_TO) {
87                 LOGE("MEDIA_DATA_DB_URI predicates not support %{public}d", item.operation);
88                 return false;
89             }
90             string uri = static_cast<string>(item.GetSingle(VALUE_IDX));
91             MediaFileUri::RemoveAllFragment(uri);
92             MediaFileUri fileUri(uri);
93             extraInfo.uri = uri;
94             if ((extraInfo.fetchOptType != ALBUM_FETCH_OPT) && (!fileUri.IsApi10())) {
95                 fileUri = MediaFileUri(MediaFileUtils::GetRealUriFromVirtualUri(uri));
96             }
97             extraInfo.networkId = fileUri.GetNetworkId();
98             string field = (extraInfo.fetchOptType == ALBUM_FETCH_OPT) ? PhotoAlbumColumns::ALBUM_ID : MEDIA_DATA_DB_ID;
99             operations.push_back({ item.operation, { field, fileUri.GetFileId() } });
100             continue;
101         }
102         if (static_cast<string>(item.GetSingle(FIELD_IDX)) == PENDING_STATUS) {
103             continue;
104         }
105         if (LOCATION_PARAM_MAP.find(static_cast<string>(item.GetSingle(FIELD_IDX))) != LOCATION_PARAM_MAP.end()) {
106             continue;
107         }
108         operations.push_back(item);
109     }
110     predicates = DataSharePredicates(move(operations));
111     return true;
112 }
113 
GetLocationPredicate(shared_ptr<DataSharePredicates> & predicatePtr,DataSharePredicates & predicates,vector<string> & fetchColumn)114 static bool GetLocationPredicate(shared_ptr<DataSharePredicates> &predicatePtr,
115     DataSharePredicates &predicates, vector<string> &fetchColumn)
116 {
117     map<string, string> locationMap;
118     auto &items = predicatePtr->GetOperationList();
119     for (auto &item : items) {
120         if (item.singleParams.empty()) {
121             continue;
122         }
123         if (LOCATION_PARAM_MAP.find(static_cast<string>(item.GetSingle(FIELD_IDX))) != LOCATION_PARAM_MAP.end()) {
124             if (item.operation != DataShare::EQUAL_TO) {
125                 LOGE("location predicates not support %{public}d", item.operation);
126                 return false;
127             }
128             string param = static_cast<string>(item.GetSingle(FIELD_IDX));
129             string value = static_cast<string>(item.GetSingle(VALUE_IDX));
130             locationMap.insert(make_pair(param, value));
131             if (param == DIAMETER) {
132                 continue;
133             }
134             if (LOCATION_PARAM_MAP.at(param).second == DataShare::GREATER_THAN_OR_EQUAL_TO) {
135                 predicates.GreaterThanOrEqualTo(LOCATION_PARAM_MAP.at(param).first, value);
136                 continue;
137             }
138             if (LOCATION_PARAM_MAP.at(param).second == DataShare::LESS_THAN) {
139                 predicates.LessThan(LOCATION_PARAM_MAP.at(param).first, value);
140                 continue;
141             }
142             if (LOCATION_PARAM_MAP.at(param).second == DataShare::EQUAL_TO) {
143                 predicates.EqualTo(LOCATION_PARAM_MAP.at(param).first, value);
144                 continue;
145             }
146         }
147     }
148     if (locationMap.count(DIAMETER) == 1 && locationMap.count(START_LATITUDE) == 1
149         && locationMap.count(START_LONGITUDE) == 1) {
150         // 0.5:Used for rounding down
151         string latitudeIndex = "round((latitude - " + locationMap.at(START_LATITUDE) + ") / " +
152             locationMap.at(DIAMETER) + " - 0.5)";
153         string longitudeIndex = "round((longitude - " + locationMap.at(START_LONGITUDE) + ") / " +
154             locationMap.at(DIAMETER) + " - 0.5)";
155         string albumName = LATITUDE + "||'_'||" + LONGITUDE + "||'_'||" + latitudeIndex + "||'_'||" +
156             longitudeIndex + " AS " + ALBUM_NAME;
157         fetchColumn.push_back(albumName);
158         string locationGroup = latitudeIndex + "," + longitudeIndex;
159         predicates.GroupBy({ locationGroup });
160     }
161     return true;
162 }
163 
GetPredicate(COptions options,DataSharePredicates & predicates,vector<string> & fetchColumn,ExtraInfo & extraInfo,int32_t & errCode)164 bool GetPredicate(COptions options, DataSharePredicates &predicates, vector<string> &fetchColumn,
165     ExtraInfo &extraInfo, int32_t &errCode)
166 {
167     auto native = FFIData::GetData<DataSharePredicatesImpl>(options.predicates);
168     if (native == nullptr) {
169         LOGE("get DataSharePredicatesImpl failed.");
170         errCode = JS_INNER_FAIL;
171         return false;
172     }
173     auto predicatePtr = native->GetPredicates();
174     if (predicatePtr == nullptr) {
175         LOGE("DataSharePredicates is null");
176         errCode = JS_INNER_FAIL;
177         return false;
178     }
179     if (!HandleSpecialPredicate(predicatePtr, predicates, extraInfo) ||
180         (!GetLocationPredicate(predicatePtr, predicates, fetchColumn))) {
181         LOGE("invalid predicate");
182         errCode = JS_ERR_PARAMETER_INVALID;
183         return false;
184     }
185     return true;
186 }
187 
GetArrayProperty(COptions options,vector<string> & fetchColumn,int32_t & errCode)188 static bool GetArrayProperty(COptions options,
189     vector<string> &fetchColumn, int32_t &errCode)
190 {
191     if (errCode != E_SUCCESS) {
192         return false;
193     }
194     for (int64_t i = 0; i < options.fetchColumns.size; i++) {
195         fetchColumn.emplace_back(string(options.fetchColumns.head[i]));
196     }
197     return true;
198 }
199 
GetFetchOption(COptions options,DataSharePredicates & predicates,vector<string> & fetchColumn,ExtraInfo & extraInfo,int32_t & errCode)200 void GetFetchOption(COptions options, DataSharePredicates &predicates,
201     vector<string> &fetchColumn, ExtraInfo &extraInfo, int32_t &errCode)
202 {
203     errCode = E_SUCCESS;
204     if (!GetPredicate(options, predicates, fetchColumn, extraInfo, errCode)) {
205         LOGE("invalid predicate");
206         return;
207     }
208     if (!GetArrayProperty(options, fetchColumn, errCode)) {
209         LOGE("Failed to parse fetchColumn");
210         return;
211     }
212 }
213 
AddDefaultAssetColumns(vector<string> & fetchColumn,function<bool (const string & columnName)> isValidColumn,NapiAssetType assetType,int32_t & errCode,const PhotoAlbumSubType subType)214 void AddDefaultAssetColumns(vector<string> &fetchColumn,
215     function<bool(const string &columnName)> isValidColumn, NapiAssetType assetType,
216     int32_t &errCode, const PhotoAlbumSubType subType)
217 {
218     auto validFetchColumns = MediaColumn::DEFAULT_FETCH_COLUMNS;
219     if (assetType == TYPE_PHOTO) {
220         validFetchColumns.insert(
221             PhotoColumn::DEFAULT_FETCH_COLUMNS.begin(), PhotoColumn::DEFAULT_FETCH_COLUMNS.end());
222     }
223     switch (subType) {
224         case PhotoAlbumSubType::FAVORITE:
225             validFetchColumns.insert(MediaColumn::MEDIA_IS_FAV);
226             break;
227         case PhotoAlbumSubType::VIDEO:
228             validFetchColumns.insert(MediaColumn::MEDIA_TYPE);
229             break;
230         case PhotoAlbumSubType::HIDDEN:
231             validFetchColumns.insert(MediaColumn::MEDIA_HIDDEN);
232             break;
233         case PhotoAlbumSubType::TRASH:
234             validFetchColumns.insert(MediaColumn::MEDIA_DATE_TRASHED);
235             break;
236         case PhotoAlbumSubType::SCREENSHOT:
237         case PhotoAlbumSubType::CAMERA:
238             validFetchColumns.insert(PhotoColumn::PHOTO_SUBTYPE);
239             break;
240         default:
241             break;
242     }
243     for (const auto &column : fetchColumn) {
244         if (column == PENDING_STATUS) {
245             validFetchColumns.insert(MediaColumn::MEDIA_TIME_PENDING);
246         } else if (isValidColumn(column)) {
247             validFetchColumns.insert(column);
248         } else if (column == MEDIA_DATA_DB_URI) {
249             continue;
250         } else if (DATE_TRANSITION_MAP.count(column) != 0) {
251             validFetchColumns.insert(DATE_TRANSITION_MAP.at(column));
252         } else {
253             errCode = JS_ERR_PARAMETER_INVALID;
254             return;
255         }
256     }
257     fetchColumn.assign(validFetchColumns.begin(), validFetchColumns.end());
258 }
259 }
260 }