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 #define MLOG_TAG "MediaLibraryExtendManager"
16
17 #include "media_library_extend_manager.h"
18
19 #include "accesstoken_kit.h"
20 #include "datashare_abs_result_set.h"
21 #include "datashare_predicates.h"
22 #include "file_uri.h"
23 #include "iservice_registry.h"
24 #include "media_file_uri.h"
25 #include "media_file_utils.h"
26 #include "media_log.h"
27 #include "medialibrary_errno.h"
28 #include "medialibrary_tracer.h"
29 #include "medialibrary_type_const.h"
30 #include "media_app_uri_permission_column.h"
31 #include "media_app_uri_sensitive_column.h"
32 #include "moving_photo_file_utils.h"
33 #include "os_account_manager.h"
34 #include "permission_utils.h"
35 #include "result_set_utils.h"
36 #include "string_ex.h"
37 #include "system_ability_definition.h"
38 #include "unique_fd.h"
39 #include "userfilemgr_uri.h"
40
41 using namespace std;
42 using namespace OHOS::NativeRdb;
43 using namespace OHOS::Security::AccessToken;
44 namespace OHOS {
45 namespace Media {
46 constexpr int32_t URI_MAX_SIZE = 1000;
47 constexpr uint32_t URI_PERMISSION_FLAG_READ = 1;
48 constexpr uint32_t URI_PERMISSION_FLAG_WRITE = 2;
49 constexpr uint32_t URI_PERMISSION_FLAG_READWRITE = 3;
50 constexpr int32_t DEFUALT_USER_ID = 100;
51 constexpr int32_t DATASHARE_ERR = -1;
52
53 static map<string, TableType> tableMap = {
54 { MEDIALIBRARY_TYPE_IMAGE_URI, TableType::TYPE_PHOTOS },
55 { MEDIALIBRARY_TYPE_VIDEO_URI, TableType::TYPE_PHOTOS },
56 { MEDIALIBRARY_TYPE_AUDIO_URI, TableType::TYPE_AUDIOS },
57 { PhotoColumn::PHOTO_TYPE_URI, TableType::TYPE_PHOTOS },
58 { AudioColumn::AUDIO_TYPE_URI, TableType::TYPE_AUDIOS }
59 };
60
GetMediaLibraryExtendManager()61 MediaLibraryExtendManager *MediaLibraryExtendManager::GetMediaLibraryExtendManager()
62 {
63 static MediaLibraryExtendManager mediaLibMgr;
64 return &mediaLibMgr;
65 }
66
InitToken()67 static sptr<IRemoteObject> InitToken()
68 {
69 auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
70 CHECK_AND_RETURN_RET_LOG(saManager != nullptr, nullptr, "get system ability mgr failed.");
71
72 auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID);
73 CHECK_AND_RETURN_RET_LOG(remoteObj != nullptr, nullptr, "GetSystemAbility Service failed.");
74 return remoteObj;
75 }
76
GetCurrentAccountId()77 static int32_t GetCurrentAccountId()
78 {
79 int32_t activeUserId = DEFUALT_USER_ID;
80 ErrCode ret = OHOS::AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(activeUserId);
81 if (ret != ERR_OK) {
82 MEDIA_ERR_LOG("fail to get activeUser:%{public}d", ret);
83 }
84 return activeUserId;
85 }
86
InitMediaLibraryExtendManager()87 void MediaLibraryExtendManager::InitMediaLibraryExtendManager()
88 {
89 int32_t activeUser = GetCurrentAccountId();
90 if (dataShareHelper_ == nullptr || activeUser != userId_) {
91 auto token = InitToken();
92 if (token == nullptr) {
93 MEDIA_ERR_LOG("fail to get token.");
94 return;
95 }
96 dataShareHelper_ = DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
97 userId_ = activeUser;
98 }
99 }
100
ForceReconnect()101 bool MediaLibraryExtendManager::ForceReconnect()
102 {
103 dataShareHelper_ = nullptr;
104 InitMediaLibraryExtendManager();
105 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, false, "init manager fail");
106 return true;
107 }
108
UrisSourceMediaTypeClassify(const vector<string> & urisSource,vector<string> & photoFileIds,vector<string> & audioFileIds)109 static int32_t UrisSourceMediaTypeClassify(const vector<string> &urisSource,
110 vector<string> &photoFileIds, vector<string> &audioFileIds)
111 {
112 for (const auto &uri : urisSource) {
113 int32_t tableType = -1;
114 for (const auto &iter : tableMap) {
115 if (uri.find(iter.first) != string::npos) {
116 tableType = static_cast<int32_t>(iter.second);
117 }
118 }
119
120 CHECK_AND_RETURN_RET_LOG(tableType != -1, E_ERR, "Uri invalid error, uri:%{private}s", uri.c_str());
121 string fileId = MediaFileUtils::GetIdFromUri(uri);
122 if (tableType == static_cast<int32_t>(TableType::TYPE_PHOTOS)) {
123 photoFileIds.emplace_back(fileId);
124 } else if (tableType == static_cast<int32_t>(TableType::TYPE_AUDIOS)) {
125 audioFileIds.emplace_back(fileId);
126 } else {
127 MEDIA_ERR_LOG("Uri invalid error, uri:%{private}s", uri.c_str());
128 return E_ERR;
129 }
130 }
131 return E_SUCCESS;
132 }
133
CheckAccessTokenPermissionExecute(uint32_t tokenId,uint32_t checkFlag,TableType mediaType,bool & isReadable,bool & isWritable)134 static void CheckAccessTokenPermissionExecute(uint32_t tokenId, uint32_t checkFlag, TableType mediaType,
135 bool &isReadable, bool &isWritable)
136 {
137 static map<TableType, string> readPermmisionMap = {
138 { TableType::TYPE_PHOTOS, PERM_READ_IMAGEVIDEO },
139 { TableType::TYPE_AUDIOS, PERM_READ_AUDIO }
140 };
141 static map<TableType, string> writePermmisionMap = {
142 { TableType::TYPE_PHOTOS, PERM_WRITE_IMAGEVIDEO },
143 { TableType::TYPE_AUDIOS, PERM_WRITE_AUDIO }
144 };
145 int checkReadResult = -1;
146 int checkWriteResult = -1;
147 if (checkFlag == URI_PERMISSION_FLAG_READ) {
148 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, readPermmisionMap[mediaType]);
149 if (checkReadResult != PermissionState::PERMISSION_GRANTED) {
150 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
151 }
152 } else if (checkFlag == URI_PERMISSION_FLAG_WRITE) {
153 checkWriteResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
154 } else if (checkFlag == URI_PERMISSION_FLAG_READWRITE) {
155 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, readPermmisionMap[mediaType]);
156 if (checkReadResult != PermissionState::PERMISSION_GRANTED) {
157 checkReadResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
158 }
159 checkWriteResult = AccessTokenKit::VerifyAccessToken(tokenId, writePermmisionMap[mediaType]);
160 }
161 isReadable = checkReadResult == PermissionState::PERMISSION_GRANTED;
162 isWritable = checkWriteResult == PermissionState::PERMISSION_GRANTED;
163 }
CheckAccessTokenPermission(uint32_t tokenId,uint32_t checkFlag,TableType mediaType,int64_t & queryFlag)164 static void CheckAccessTokenPermission(uint32_t tokenId, uint32_t checkFlag,
165 TableType mediaType, int64_t &queryFlag)
166 {
167 bool isReadable = false;
168 bool isWritable = false;
169 CheckAccessTokenPermissionExecute(tokenId, checkFlag, mediaType, isReadable, isWritable);
170
171 if (checkFlag == URI_PERMISSION_FLAG_READ) {
172 queryFlag = isReadable ? -1 : URI_PERMISSION_FLAG_READ;
173 } else if (checkFlag == URI_PERMISSION_FLAG_WRITE) {
174 queryFlag = isWritable ? -1 : URI_PERMISSION_FLAG_WRITE;
175 } else if (checkFlag == URI_PERMISSION_FLAG_READWRITE) {
176 if (isReadable && isWritable) {
177 queryFlag = -1;
178 } else if (isReadable) {
179 queryFlag = URI_PERMISSION_FLAG_WRITE;
180 } else if (isWritable) {
181 queryFlag = URI_PERMISSION_FLAG_READ;
182 } else {
183 queryFlag = URI_PERMISSION_FLAG_READWRITE;
184 }
185 }
186 }
187
MakePredicatesForCheckPhotoUriPermission(int64_t & checkFlag,DataSharePredicates & predicates,uint32_t targetTokenId,TableType mediaType,vector<string> & fileIds)188 static void MakePredicatesForCheckPhotoUriPermission(int64_t &checkFlag, DataSharePredicates &predicates,
189 uint32_t targetTokenId, TableType mediaType, vector<string> &fileIds)
190 {
191 predicates.EqualTo(AppUriPermissionColumn::TARGET_TOKENID, (int64_t)targetTokenId);
192 predicates.And()->EqualTo(AppUriPermissionColumn::URI_TYPE, to_string(static_cast<int32_t>(mediaType)));
193 predicates.And()->In(AppUriPermissionColumn::FILE_ID, fileIds);
194 vector<string> permissionTypes;
195 switch (checkFlag) {
196 case URI_PERMISSION_FLAG_READ:
197 permissionTypes.emplace_back(
198 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO)));
199 permissionTypes.emplace_back(
200 to_string(static_cast<int32_t>(PhotoPermissionType::PERSIST_READ_IMAGEVIDEO)));
201 permissionTypes.emplace_back(
202 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO)));
203 permissionTypes.emplace_back(
204 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
205 permissionTypes.emplace_back(
206 to_string(static_cast<int32_t>(AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE)));
207 break;
208 case URI_PERMISSION_FLAG_WRITE:
209 permissionTypes.emplace_back(
210 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO)));
211 permissionTypes.emplace_back(
212 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
213 permissionTypes.emplace_back(
214 to_string(static_cast<int32_t>(AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE)));
215 break;
216 case URI_PERMISSION_FLAG_READWRITE:
217 permissionTypes.emplace_back(
218 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO)));
219 permissionTypes.emplace_back(
220 to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
221 permissionTypes.emplace_back(
222 to_string(static_cast<int32_t>(AppUriPermissionColumn::PERMISSION_PERSIST_READ_WRITE)));
223 break;
224 default:
225 MEDIA_ERR_LOG("error flag object: %{public}ld", (long)checkFlag);
226 return;
227 }
228 predicates.And()->In(AppUriPermissionColumn::PERMISSION_TYPE, permissionTypes);
229 predicates.OrderByDesc(AppUriPermissionColumn::PERMISSION_TYPE);
230 }
231
CheckPhotoUriPermissionQueryOperation(const DataSharePredicates & predicates,map<string,int32_t> & resultMap)232 int32_t MediaLibraryExtendManager::CheckPhotoUriPermissionQueryOperation(const DataSharePredicates &predicates,
233 map<string, int32_t> &resultMap)
234 {
235 vector<string> columns = {
236 AppUriPermissionColumn::FILE_ID,
237 AppUriPermissionColumn::PERMISSION_TYPE
238 };
239 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, E_ERR,
240 "Failed to checkPhotoUriPermission, datashareHelper is nullptr");
241
242 Uri uri(MEDIALIBRARY_CHECK_URIPERM_URI);
243 auto queryResultSet = dataShareHelper_->Query(uri, predicates, columns);
244 if (queryResultSet == nullptr && ForceReconnect()) {
245 MEDIA_WARN_LOG("resultset is null, reconnect and retry");
246 queryResultSet = dataShareHelper_->Query(uri, predicates, columns);
247 }
248 CHECK_AND_RETURN_RET_LOG(queryResultSet != nullptr, E_ERR, "queryResultSet is null!");
249
250 while (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
251 string fileId = GetStringVal(AppUriPermissionColumn::FILE_ID, queryResultSet);
252 int32_t permissionType = GetInt32Val(AppUriPermissionColumn::PERMISSION_TYPE, queryResultSet);
253 resultMap[fileId] = permissionType;
254 }
255 return E_SUCCESS;
256 }
257
SetCheckPhotoUriPermissionResult(const vector<string> & urisSource,const map<string,int32_t> & photoResultMap,const map<string,int32_t> & audioResultMap,int32_t queryPhotoFlag,int32_t queryAudioFlag)258 static vector<bool> SetCheckPhotoUriPermissionResult(const vector<string> &urisSource,
259 const map<string, int32_t> &photoResultMap, const map<string, int32_t> &audioResultMap,
260 int32_t queryPhotoFlag, int32_t queryAudioFlag)
261 {
262 vector<bool> results;
263 for (const auto &uri : urisSource) {
264 int32_t tableType = -1;
265 for (const auto &iter : tableMap) {
266 if (uri.find(iter.first) != string::npos) {
267 tableType = static_cast<int32_t>(iter.second);
268 }
269 }
270 string fileId = MediaFileUtils::GetIdFromUri(uri);
271 if (tableType == static_cast<int32_t>(TableType::TYPE_PHOTOS)) {
272 if (queryPhotoFlag == -1 || photoResultMap.find(fileId) != photoResultMap.end()) {
273 results.emplace_back(true);
274 } else {
275 results.emplace_back(false);
276 }
277 } else if (tableType == static_cast<int32_t>(TableType::TYPE_AUDIOS)) {
278 if (queryAudioFlag == -1 || audioResultMap.find(fileId) != audioResultMap.end()) {
279 results.emplace_back(true);
280 } else {
281 results.emplace_back(false);
282 }
283 }
284 }
285 return results;
286 }
287
CheckInputParameters(const vector<string> & urisSource,uint32_t flag)288 static int32_t CheckInputParameters(const vector<string> &urisSource, uint32_t flag)
289 {
290 CHECK_AND_RETURN_RET_LOG(!urisSource.empty(), E_ERR, "Media Uri list is empty");
291 CHECK_AND_RETURN_RET_LOG(urisSource.size() <= URI_MAX_SIZE, E_ERR,
292 "Uri list is exceed one Thousand, current list size: %{public}d", (int)urisSource.size());
293 bool cond = (flag == 0 || flag > URI_PERMISSION_FLAG_READWRITE);
294 CHECK_AND_RETURN_RET_LOG(!cond, E_ERR, "Flag is invalid, current flag is: %{public}d", flag);
295 return E_SUCCESS;
296 }
297
CheckPhotoUriPermission(uint32_t tokenId,const vector<string> & urisSource,vector<bool> & results,uint32_t flag)298 int32_t MediaLibraryExtendManager::CheckPhotoUriPermission(uint32_t tokenId,
299 const vector<string> &urisSource, vector<bool> &results, uint32_t flag)
300 {
301 MediaLibraryTracer tracer;
302 tracer.Start("MediaLibraryExtendManager::CheckPhotoUriPermission");
303 auto ret = CheckInputParameters(urisSource, flag);
304 CHECK_AND_RETURN_RET(ret == E_SUCCESS, E_ERR);
305 vector<string> photoFileIds;
306 vector<string> audioFileIds;
307 ret = UrisSourceMediaTypeClassify(urisSource, photoFileIds, audioFileIds);
308 CHECK_AND_RETURN_RET(ret == E_SUCCESS, E_ERR);
309
310 int64_t queryPhotoFlag = URI_PERMISSION_FLAG_READWRITE;
311 int64_t queryAudioFlag = URI_PERMISSION_FLAG_READWRITE;
312 if (photoFileIds.empty()) {
313 queryPhotoFlag = -1;
314 } else {
315 CheckAccessTokenPermission(tokenId, flag, TableType::TYPE_PHOTOS, queryPhotoFlag);
316 }
317 if (audioFileIds.empty()) {
318 queryAudioFlag = -1;
319 } else {
320 CheckAccessTokenPermission(tokenId, flag, TableType::TYPE_AUDIOS, queryAudioFlag);
321 }
322 map<string, int32_t> photoResultMap;
323 map<string, int32_t> audioResultMap;
324 if (queryPhotoFlag != -1) {
325 DataSharePredicates predicates;
326 MakePredicatesForCheckPhotoUriPermission(queryPhotoFlag, predicates,
327 tokenId, TableType::TYPE_PHOTOS, photoFileIds);
328 auto ret = CheckPhotoUriPermissionQueryOperation(predicates, photoResultMap);
329 CHECK_AND_RETURN_RET(ret == E_SUCCESS, E_ERR);
330 }
331 if (queryAudioFlag != -1) {
332 DataSharePredicates predicates;
333 MakePredicatesForCheckPhotoUriPermission(queryAudioFlag, predicates,
334 tokenId, TableType::TYPE_AUDIOS, audioFileIds);
335 auto ret = CheckPhotoUriPermissionQueryOperation(predicates, audioResultMap);
336 CHECK_AND_RETURN_RET(ret == E_SUCCESS, E_ERR);
337 }
338 results = SetCheckPhotoUriPermissionResult(urisSource, photoResultMap, audioResultMap,
339 queryPhotoFlag, queryAudioFlag);
340 return E_SUCCESS;
341 }
342
GrantPhotoUriPermission(uint32_t srcTokenId,uint32_t targetTokenId,const std::vector<string> & uris,PhotoPermissionType photoPermissionType,HideSensitiveType hideSensitiveTpye)343 int32_t MediaLibraryExtendManager::GrantPhotoUriPermission(uint32_t srcTokenId, uint32_t targetTokenId,
344 const std::vector<string> &uris, PhotoPermissionType photoPermissionType, HideSensitiveType hideSensitiveTpye)
345 {
346 MediaLibraryTracer tracer;
347 tracer.Start("MediaLibraryExtendManager::GrantPhotoUriPermission");
348 vector<DataShareValuesBucket> valueSet;
349 bool cond = ((uris.empty()) || (uris.size() > URI_MAX_SIZE));
350 CHECK_AND_RETURN_RET_LOG(!cond, E_ERR, "Media Uri list error, please check!");
351 cond = (photoPermissionType != PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO &&
352 photoPermissionType != PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO &&
353 photoPermissionType != PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO);
354 CHECK_AND_RETURN_RET_LOG(!cond, E_ERR, "photoPermissionType error, please check param!");
355
356 cond = (hideSensitiveTpye < HideSensitiveType::ALL_DESENSITIZE ||
357 hideSensitiveTpye > HideSensitiveType::NO_DESENSITIZE);
358 CHECK_AND_RETURN_RET_LOG(!cond, E_ERR, "HideSensitiveType error, please check param!");
359 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, E_ERR, "dataShareHelper is nullptr");
360
361 for (const auto &uri : uris) {
362 int32_t tableType = -1;
363 for (const auto &iter : tableMap) {
364 if (uri.find(iter.first) != string::npos) {
365 tableType = static_cast<int32_t>(iter.second);
366 }
367 }
368
369 CHECK_AND_RETURN_RET_LOG(tableType != -1, E_ERR, "Uri invalid error, uri:%{private}s", uri.c_str());
370 string fileId = MediaFileUtils::GetIdFromUri(uri);
371 DataShareValuesBucket valuesBucket;
372 valuesBucket.Put(AppUriPermissionColumn::SOURCE_TOKENID, (int64_t)srcTokenId);
373 valuesBucket.Put(AppUriPermissionColumn::TARGET_TOKENID, (int64_t)targetTokenId);
374 valuesBucket.Put(AppUriPermissionColumn::FILE_ID, fileId);
375 valuesBucket.Put(AppUriPermissionColumn::URI_TYPE, tableType);
376 valuesBucket.Put(AppUriPermissionColumn::PERMISSION_TYPE, static_cast<int32_t>(photoPermissionType));
377 valuesBucket.Put(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, static_cast<int32_t>(hideSensitiveTpye));
378 valueSet.push_back(valuesBucket);
379 }
380 Uri insertUri(MEDIALIBRARY_GRANT_URIPERM_URI);
381 auto ret = dataShareHelper_->BatchInsert(insertUri, valueSet);
382 if (ret == DATASHARE_ERR && ForceReconnect()) {
383 MEDIA_WARN_LOG("Failed to BatchInsert and retry");
384 ret = dataShareHelper_->BatchInsert(insertUri, valueSet);
385 }
386 return ret;
387 }
388
CancelPhotoUriPermission(uint32_t srcTokenId,uint32_t targetTokenId,const std::vector<string> & uris)389 int32_t MediaLibraryExtendManager::CancelPhotoUriPermission(uint32_t srcTokenId, uint32_t targetTokenId,
390 const std::vector<string> &uris)
391 {
392 MediaLibraryTracer tracer;
393 tracer.Start("MediaLibraryExtendManager::CancelPhotoUriPermission");
394 MEDIA_DEBUG_LOG("CancelPermission begin, srcToken:%{private}d, targetToken:%{private}d", srcTokenId, targetTokenId);
395 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, E_ERR, "dataShareHelper is nullptr");
396 vector<DataShareValuesBucket> valueSet;
397 bool cond = ((uris.empty()) || (uris.size() > URI_MAX_SIZE));
398 CHECK_AND_RETURN_RET_LOG(!cond, E_ERR, "Media Uri list error, please check!");
399
400 DataSharePredicates predicates;
401 for (size_t i = 0; i < uris.size(); i++) {
402 string uri = uris[i];
403 int32_t tableType = -1;
404 for (const auto &iter : tableMap) {
405 if (uri.find(iter.first) != string::npos) {
406 tableType = static_cast<int32_t>(iter.second);
407 }
408 }
409 CHECK_AND_RETURN_RET_LOG(tableType != -1, E_ERR, "Uri invalid error, uri:%{private}s", uri.c_str());
410 string fileId = MediaFileUtils::GetIdFromUri(uri);
411 if (i > 0) {
412 predicates.Or();
413 }
414 MEDIA_DEBUG_LOG("CancelPermission fileId:%{private}s, tableType:%{private}d", fileId.c_str(), tableType);
415 predicates.BeginWrap();
416 predicates.BeginWrap();
417 predicates.EqualTo(AppUriPermissionColumn::SOURCE_TOKENID, (int64_t)srcTokenId);
418 predicates.Or();
419 predicates.EqualTo(AppUriPermissionColumn::TARGET_TOKENID, (int64_t)srcTokenId);
420 predicates.EndWrap();
421 predicates.EqualTo(AppUriPermissionColumn::FILE_ID, fileId);
422 predicates.EqualTo(AppUriPermissionColumn::TARGET_TOKENID, (int64_t)targetTokenId);
423 predicates.EqualTo(AppUriPermissionColumn::URI_TYPE, tableType);
424 predicates.NotEqualTo(AppUriPermissionColumn::PERMISSION_TYPE,
425 static_cast<int>(PhotoPermissionType::PERSIST_READ_IMAGEVIDEO));
426 predicates.NotEqualTo(AppUriPermissionColumn::PERMISSION_TYPE,
427 static_cast<int>(PhotoPermissionType::PERSIST_READWRITE_IMAGEVIDEO));
428 predicates.EndWrap();
429 }
430 Uri deleteUri(MEDIALIBRARY_GRANT_URIPERM_URI);
431 return dataShareHelper_->Delete(deleteUri, predicates);
432 }
433
CheckUri(string & uri)434 static bool CheckUri(string &uri)
435 {
436 if (uri.find("../") != string::npos) {
437 return false;
438 }
439 string uriprex = "file://media";
440 return uri.substr(0, uriprex.size()) == uriprex;
441 }
442
OpenAsset(string & uri,const string openMode,HideSensitiveType type)443 int32_t MediaLibraryExtendManager::OpenAsset(string &uri, const string openMode, HideSensitiveType type)
444 {
445 CHECK_AND_RETURN_RET(!openMode.empty(), E_ERR);
446 CHECK_AND_RETURN_RET_LOG(CheckUri(uri), E_ERR, "invalid uri");
447
448 string originOpenMode = openMode;
449 std::transform(originOpenMode.begin(), originOpenMode.end(),
450 originOpenMode.begin(), [](unsigned char c) {return std::tolower(c);});
451 CHECK_AND_RETURN_RET(MEDIA_OPEN_MODES.count(originOpenMode), E_ERR);
452 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, E_ERR, "Failed to open Asset, datashareHelper is nullptr");
453
454 string assetUri = uri;
455 MediaFileUtils::UriAppendKeyValue(assetUri, "type", to_string(static_cast<int32_t>(type)));
456 MEDIA_DEBUG_LOG("merged uri = %{public}s", assetUri.c_str());
457 Uri openUri(assetUri);
458 int ret = dataShareHelper_->OpenFile(openUri, openMode);
459 if (ret == DATASHARE_ERR && ForceReconnect()) {
460 MEDIA_WARN_LOG("Failed to OpenFile and retry");
461 ret = dataShareHelper_->OpenFile(openUri, openMode);
462 }
463 return ret;
464 }
465
ReadPrivateMovingPhoto(string & uri,const HideSensitiveType type)466 int32_t MediaLibraryExtendManager::ReadPrivateMovingPhoto(string &uri, const HideSensitiveType type)
467 {
468 CHECK_AND_RETURN_RET_LOG(CheckUri(uri), E_ERR, "invalid uri: %{public}s", uri.c_str());
469 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, E_ERR,
470 "Failed to read video of moving photo, datashareHelper is nullptr");
471
472 string movingPhotoUri = uri;
473 MediaFileUtils::UriAppendKeyValue(movingPhotoUri, "type", to_string(static_cast<int32_t>(type)));
474 MediaFileUtils::UriAppendKeyValue(movingPhotoUri, MEDIA_MOVING_PHOTO_OPRN_KEYWORD, OPEN_PRIVATE_LIVE_PHOTO);
475 Uri openMovingPhotoUri(movingPhotoUri);
476 int ret = dataShareHelper_->OpenFile(openMovingPhotoUri, MEDIA_FILEMODE_READONLY);
477 if (ret == DATASHARE_ERR && ForceReconnect()) {
478 MEDIA_WARN_LOG("Failed to OpenFile and retry");
479 ret = dataShareHelper_->OpenFile(openMovingPhotoUri, MEDIA_FILEMODE_READONLY);
480 }
481 return ret;
482 }
483
CheckPhotoUri(const string & uri)484 static bool CheckPhotoUri(const string &uri)
485 {
486 if (uri.find("../") != string::npos) {
487 return false;
488 }
489 string photoUriPrefix = "file://media/Photo/";
490 return MediaFileUtils::StartsWith(uri, photoUriPrefix);
491 }
492
GetResultSetFromPhotos(const string & value,vector<string> & columns)493 std::shared_ptr<DataShareResultSet> MediaLibraryExtendManager::GetResultSetFromPhotos(const string &value,
494 vector<string> &columns)
495 {
496 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, nullptr, "datashareHelper is nullptr");
497 if (!CheckPhotoUri(value)) {
498 MEDIA_ERR_LOG("Failed to check invalid uri: %{public}s", value.c_str());
499 return nullptr;
500 }
501 Uri queryUri(PAH_QUERY_PHOTO);
502 DataSharePredicates predicates;
503 string fileId = MediaFileUtils::GetIdFromUri(value);
504 predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
505 DatashareBusinessError businessError;
506 auto resultSet = dataShareHelper_->Query(queryUri, predicates, columns, &businessError);
507 if (resultSet == nullptr && ForceReconnect()) {
508 MEDIA_WARN_LOG("resultset is null, reconnect and retry");
509 return dataShareHelper_->Query(queryUri, predicates, columns, &businessError);
510 } else {
511 return resultSet;
512 }
513 }
514
GetResultSetFromDb(string columnName,const string & value,vector<string> & columns)515 std::shared_ptr<DataShareResultSet> MediaLibraryExtendManager::GetResultSetFromDb(string columnName,
516 const string &value, vector<string> &columns)
517 {
518 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, nullptr, "dataShareHelper is null");
519 if (columnName == MEDIA_DATA_DB_URI) {
520 return GetResultSetFromPhotos(value, columns);
521 }
522 Uri uri(MEDIALIBRARY_MEDIA_PREFIX);
523 DataSharePredicates predicates;
524 predicates.EqualTo(columnName, value);
525 predicates.And()->EqualTo(MEDIA_DATA_DB_IS_TRASH, to_string(NOT_TRASHED));
526 DatashareBusinessError businessError;
527 auto resultSet = dataShareHelper_->Query(uri, predicates, columns, &businessError);
528 if (resultSet == nullptr && ForceReconnect()) {
529 MEDIA_WARN_LOG("resultset is null, reconnect and retry");
530 return dataShareHelper_->Query(uri, predicates, columns, &businessError);
531 } else {
532 return resultSet;
533 }
534 }
535 } // namespace Media
536 } // namespace OHOS