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 #include "data_secondary_directory_uri.h"
41 #include "user_inner_ipc_client.h"
42 #include "medialibrary_business_code.h"
43 #include "get_result_set_from_db_vo.h"
44 #include "get_result_set_from_photos_extend_vo.h"
45 #include "cancel_photo_uri_permission_inner_vo.h"
46 #include "grant_photo_uri_permission_inner_vo.h"
47 #include "check_photo_uri_permission_inner_vo.h"
48
49 using namespace std;
50 using namespace OHOS::NativeRdb;
51 using namespace OHOS::Security::AccessToken;
52 namespace OHOS {
53 namespace Media {
54 constexpr int32_t URI_MAX_SIZE = 1000;
55 constexpr uint32_t URI_PERMISSION_FLAG_READ = 1;
56 constexpr uint32_t URI_PERMISSION_FLAG_WRITE = 2;
57 constexpr uint32_t URI_PERMISSION_FLAG_READWRITE = 3;
58 constexpr int32_t DEFUALT_USER_ID = 100;
59 constexpr int32_t DATASHARE_ERR = -1;
60
61 static map<string, TableType> tableMap = {
62 { MEDIALIBRARY_TYPE_IMAGE_URI, TableType::TYPE_PHOTOS },
63 { MEDIALIBRARY_TYPE_VIDEO_URI, TableType::TYPE_PHOTOS },
64 { MEDIALIBRARY_TYPE_AUDIO_URI, TableType::TYPE_AUDIOS },
65 { PhotoColumn::PHOTO_TYPE_URI, TableType::TYPE_PHOTOS },
66 { AudioColumn::AUDIO_TYPE_URI, TableType::TYPE_AUDIOS }
67 };
68
GetMediaLibraryExtendManager()69 MediaLibraryExtendManager *MediaLibraryExtendManager::GetMediaLibraryExtendManager()
70 {
71 static MediaLibraryExtendManager mediaLibMgr;
72 return &mediaLibMgr;
73 }
74
InitToken()75 static sptr<IRemoteObject> InitToken()
76 {
77 auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
78 CHECK_AND_RETURN_RET_LOG(saManager != nullptr, nullptr, "get system ability mgr failed.");
79
80 auto remoteObj = saManager->GetSystemAbility(STORAGE_MANAGER_MANAGER_ID);
81 CHECK_AND_RETURN_RET_LOG(remoteObj != nullptr, nullptr, "GetSystemAbility Service failed.");
82 return remoteObj;
83 }
84
GetCurrentAccountId()85 static int32_t GetCurrentAccountId()
86 {
87 int32_t activeUserId = DEFUALT_USER_ID;
88 ErrCode ret = OHOS::AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(activeUserId);
89 if (ret != ERR_OK) {
90 MEDIA_ERR_LOG("fail to get activeUser:%{public}d", ret);
91 }
92 return activeUserId;
93 }
94
InitMediaLibraryExtendManager()95 void MediaLibraryExtendManager::InitMediaLibraryExtendManager()
96 {
97 int32_t activeUser = GetCurrentAccountId();
98 if (dataShareHelper_ == nullptr || activeUser != userId_) {
99 auto token = InitToken();
100 if (token == nullptr) {
101 MEDIA_ERR_LOG("fail to get token.");
102 return;
103 }
104 dataShareHelper_ = DataShare::DataShareHelper::Creator(token, MEDIALIBRARY_DATA_URI);
105 userId_ = activeUser;
106 }
107 }
108
ForceReconnect()109 bool MediaLibraryExtendManager::ForceReconnect()
110 {
111 dataShareHelper_ = nullptr;
112 InitMediaLibraryExtendManager();
113 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, false, "init manager fail");
114 return true;
115 }
116
CheckInputParameters(const vector<string> & urisSource,vector<uint32_t> flags)117 static int32_t CheckInputParameters(const vector<string> &urisSource, vector<uint32_t> flags)
118 {
119 CHECK_AND_RETURN_RET_LOG(!urisSource.empty(), E_ERR, "Media Uri list is empty");
120 CHECK_AND_RETURN_RET_LOG(urisSource.size() <= URI_MAX_SIZE, E_ERR,
121 "Uri list is exceed one Thousand, current list size: %{public}d", (int)urisSource.size());
122 CHECK_AND_RETURN_RET_LOG(flags.size() == urisSource.size(), E_ERR,
123 "uri size not equal flag size: %{public}d", (int)flags.size());
124 for (uint32_t flag : flags) {
125 bool cond = (flag == 0 || flag > URI_PERMISSION_FLAG_READWRITE);
126 CHECK_AND_RETURN_RET_LOG(!cond, E_ERR, "Flag is invalid, current flag is: %{public}d", flag);
127 }
128 return E_SUCCESS;
129 }
130
SaveCheckPermission(const string & fileId,map<std::string,pair<bool,bool>> & permissionMap,PhotoPermissionType currentType)131 static void SaveCheckPermission(const string &fileId, map<std::string, pair<bool, bool>> &permissionMap,
132 PhotoPermissionType currentType)
133 {
134 switch (currentType) {
135 case PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO:
136 permissionMap[fileId].first = true;
137 break;
138 case PhotoPermissionType::PERSIST_READ_IMAGEVIDEO:
139 permissionMap[fileId].first = true;
140 break;
141 case PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO:
142 permissionMap[fileId].first = true;
143 permissionMap[fileId].second = true;
144 break;
145 case PhotoPermissionType::PERSIST_WRITE_IMAGEVIDEO:
146 permissionMap[fileId].second = true;
147 break;
148 case PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO:
149 permissionMap[fileId].first = true;
150 permissionMap[fileId].second = true;
151 break;
152 case PhotoPermissionType::PERSIST_READWRITE_IMAGEVIDEO:
153 permissionMap[fileId].first = true;
154 permissionMap[fileId].second = true;
155 break;
156 default:
157 MEDIA_WARN_LOG("invalid permission, break");
158 }
159 }
160
QueryGrantedIndex(uint32_t targetTokenId,const std::string & uriType,const std::vector<string> & fileIds,std::map<string,pair<bool,bool>> & permissionMap,uint32_t businessCode)161 int32_t MediaLibraryExtendManager::QueryGrantedIndex(uint32_t targetTokenId,
162 const std::string &uriType, const std::vector<string> &fileIds,
163 std::map<string, pair<bool, bool>> &permissionMap, uint32_t businessCode)
164 {
165 CheckUriPermissionInnerReqBody reqBody;
166 reqBody.targetTokenId = static_cast<int64_t>(targetTokenId);
167 reqBody.uriType = uriType;
168 reqBody.fileIds = fileIds;
169 reqBody.columns.emplace_back(AppUriPermissionColumn::FILE_ID);
170 reqBody.columns.emplace_back(AppUriPermissionColumn::PERMISSION_TYPE);
171 CheckUriPermissionInnerRespBody respBody;
172 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, E_ERR,
173 "Failed to checkPhotoUriPermission, datashareHelper is nullptr");
174 MEDIA_INFO_LOG("before IPC::UserDefineIPCClient().Call, INNER_CHECK_URI_PERMISSION");
175 int32_t result = IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper_).Call(businessCode,
176 reqBody, respBody);
177 if (result != E_SUCCESS && ForceReconnect()) {
178 MEDIA_WARN_LOG("QueryGrantedIndex Failed, reconnect and retry");
179 result = IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper_).Call(businessCode, reqBody, respBody);
180 }
181 CHECK_AND_RETURN_RET_LOG(result == E_SUCCESS, E_ERR, "QueryGrantedIndex Failed");
182 auto fileIds_size = respBody.fileIds.size();
183 auto permissionTypes_size = respBody.permissionTypes.size();
184 bool isValid = (fileIds_size == permissionTypes_size);
185 CHECK_AND_RETURN_RET_LOG(isValid, E_ERR, "Failed cause fileIds_size:%{public}zu"
186 " not same to permissionTypes_size:%{public}zu", fileIds_size, permissionTypes_size);
187 for (size_t i = 0; i < respBody.fileIds.size(); i++) {
188 string fileId = respBody.fileIds[i];
189 int32_t permissionType = respBody.permissionTypes[i];
190 SaveCheckPermission(fileId, permissionMap, static_cast<PhotoPermissionType>(permissionType));
191 }
192 return E_SUCCESS;
193 }
194
ClassifyUri(const vector<string> & urisSource,vector<string> & photoIds,vector<string> & audioIds)195 static int32_t ClassifyUri(const vector<string> &urisSource, vector<string> &photoIds, vector<string> &audioIds)
196 {
197 for (string uri : urisSource) {
198 int32_t tableType = -1;
199 for (const auto &iter : tableMap) {
200 if (uri.find(iter.first) != string::npos) {
201 tableType = static_cast<int32_t>(iter.second);
202 }
203 }
204
205 CHECK_AND_RETURN_RET_LOG(tableType != -1, E_ERR, "Uri invalid error, uri:%{private}s", uri.c_str());
206 string fileId = MediaFileUtils::GetIdFromUri(uri);
207 if (tableType == static_cast<int32_t>(TableType::TYPE_PHOTOS)) {
208 photoIds.push_back(fileId);
209 } else if (tableType == static_cast<int32_t>(TableType::TYPE_AUDIOS)) {
210 audioIds.push_back(fileId);
211 } else {
212 MEDIA_ERR_LOG("Uri invalid error, uri:%{private}s", uri.c_str());
213 return E_ERR;
214 }
215 }
216 return E_SUCCESS;
217 }
218
CheckAccessTokenPermission(uint32_t tokenId,const vector<string> & photoIds,const vector<string> & audioIds,map<string,pair<bool,bool>> & photoPermissionMap,map<string,pair<bool,bool>> & audioPermissionMap)219 static void CheckAccessTokenPermission(uint32_t tokenId, const vector<string> &photoIds, const vector<string> &audioIds,
220 map<string, pair<bool, bool>> &photoPermissionMap, map<string, pair<bool, bool>> &audioPermissionMap)
221 {
222 if (photoIds.size() > 0) {
223 bool haveReadPermission = AccessTokenKit::VerifyAccessToken(tokenId, PERM_READ_IMAGEVIDEO) == 0;
224 bool haveWritePermission = AccessTokenKit::VerifyAccessToken(tokenId, PERM_WRITE_IMAGEVIDEO) == 0;
225 for (string fileId : photoIds) {
226 if (haveReadPermission) {
227 photoPermissionMap[fileId].first = true;
228 }
229 if (haveWritePermission) {
230 photoPermissionMap[fileId].first = true;
231 photoPermissionMap[fileId].second = true;
232 }
233 }
234 }
235 if (audioIds.size() > 0) {
236 bool haveReadPermission = AccessTokenKit::VerifyAccessToken(tokenId, PERM_READ_AUDIO) == 0;
237 bool haveWritePermission = AccessTokenKit::VerifyAccessToken(tokenId, PERM_WRITE_AUDIO) == 0;
238 for (string fileId : audioIds) {
239 if (haveReadPermission) {
240 audioPermissionMap[fileId].first = true;
241 }
242 if (haveWritePermission) {
243 audioPermissionMap[fileId].first = true;
244 audioPermissionMap[fileId].second = true;
245 }
246 }
247 }
248 }
249
CheckPermissionByMap(const string & fileId,uint32_t flag,const map<string,pair<bool,bool>> & permissionMap)250 static bool CheckPermissionByMap(const string &fileId, uint32_t flag,
251 const map<string, pair<bool, bool>> &permissionMap)
252 {
253 auto it = permissionMap.find(fileId);
254 if (it == permissionMap.end()) {
255 return false;
256 }
257 switch (flag) {
258 case URI_PERMISSION_FLAG_READ:
259 return it->second.first;
260 case URI_PERMISSION_FLAG_WRITE:
261 return it->second.second;
262 case URI_PERMISSION_FLAG_READWRITE:
263 return it->second.first && it->second.second;
264 default:
265 MEDIA_WARN_LOG("invalid check flag!");
266 return false;
267 }
268 }
269
CheckPhotoUriPermission(uint32_t tokenId,const vector<string> & urisSource,vector<bool> & results,const vector<uint32_t> & flags)270 int32_t MediaLibraryExtendManager::CheckPhotoUriPermission(uint32_t tokenId,
271 const vector<string> &urisSource, vector<bool> &results, const vector<uint32_t> &flags)
272 {
273 MediaLibraryTracer tracer;
274 tracer.Start("MediaLibraryExtendManager::CheckPhotoUriPermission");
275 auto ret = CheckInputParameters(urisSource, flags);
276 CHECK_AND_RETURN_RET(ret == E_SUCCESS, E_ERR);
277 map<string, pair<bool, bool>> photoPermissionMap;
278 map<string, pair<bool, bool>> audioPermissionMap;
279 vector<string> photoIds;
280 vector<string> audioIds;
281 ret = ClassifyUri(urisSource, photoIds, audioIds);
282 CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, E_ERR, "invalid uri");
283 CheckAccessTokenPermission(tokenId, photoIds, audioIds, photoPermissionMap, audioPermissionMap);
284 if (photoIds.size() > 0) {
285 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_CHECK_PHOTO_URI_PERMISSION);
286 ret = QueryGrantedIndex(tokenId, to_string(static_cast<int32_t>(TableType::TYPE_PHOTOS)),
287 photoIds, photoPermissionMap, businessCode);
288 }
289 if (audioIds.size() > 0) {
290 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_CHECK_AUDIO_URI_PERMISSION);
291 ret = QueryGrantedIndex(tokenId, to_string(static_cast<int32_t>(TableType::TYPE_AUDIOS)),
292 audioIds, audioPermissionMap, businessCode);
293 }
294 CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, E_ERR, "query db fail!");
295
296 results.resize(urisSource.size(), false);
297 for (size_t i = 0; i < urisSource.size(); i++) {
298 string uri = urisSource.at(i);
299 int32_t tableType = -1;
300 for (const auto &iter : tableMap) {
301 if (uri.find(iter.first) != string::npos) {
302 tableType = static_cast<int32_t>(iter.second);
303 }
304 }
305 string fileId = MediaFileUtils::GetIdFromUri(uri);
306 if (tableType == static_cast<int32_t>(TableType::TYPE_AUDIOS)) {
307 results[i] = CheckPermissionByMap(fileId, flags.at(i), audioPermissionMap);
308 } else {
309 results[i] = CheckPermissionByMap(fileId, flags.at(i), photoPermissionMap);
310 }
311 }
312 return E_SUCCESS;
313 }
314
CheckGrantPermission(const vector<string> & urisSource,vector<PhotoPermissionType> photoPermissionTypes,HideSensitiveType hideSensitiveTpye)315 static int32_t CheckGrantPermission(const vector<string> &urisSource, vector<PhotoPermissionType> photoPermissionTypes,
316 HideSensitiveType hideSensitiveTpye)
317 {
318 bool cond = ((urisSource.empty()) || (urisSource.size() > URI_MAX_SIZE));
319 CHECK_AND_RETURN_RET_LOG(!cond, E_ERR, "Media Uri list error, please check!");
320 CHECK_AND_RETURN_RET_LOG(urisSource.size() == photoPermissionTypes.size(), E_ERR,
321 "uris size not equal PermissionTypes size!");
322 for (PhotoPermissionType photoPermissionType : photoPermissionTypes) {
323 cond = (photoPermissionType < PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO ||
324 photoPermissionType > PhotoPermissionType::GRANT_PERSIST_READWRITE_IMAGEVIDEO ||
325 photoPermissionType == PhotoPermissionType::PERSIST_READWRITE_IMAGEVIDEO);
326 CHECK_AND_RETURN_RET_LOG(!cond, E_ERR, "photoPermissionType error, please check param!");
327 }
328
329 cond = (hideSensitiveTpye < HideSensitiveType::ALL_DESENSITIZE ||
330 hideSensitiveTpye > HideSensitiveType::NO_DESENSITIZE);
331 CHECK_AND_RETURN_RET_LOG(!cond, E_ERR, "HideSensitiveType error, please check param!");
332 return E_SUCCESS;
333 }
334
GrantPhotoUriPermission(uint32_t srcTokenId,uint32_t targetTokenId,const std::vector<string> & uris,const vector<PhotoPermissionType> & photoPermissionTypes,HideSensitiveType hideSensitiveTpye)335 int32_t MediaLibraryExtendManager::GrantPhotoUriPermission(uint32_t srcTokenId, uint32_t targetTokenId,
336 const std::vector<string> &uris, const vector<PhotoPermissionType> &photoPermissionTypes,
337 HideSensitiveType hideSensitiveTpye)
338 {
339 MediaLibraryTracer tracer;
340 tracer.Start("MediaLibraryExtendManager::GrantPhotoUriPermission");
341 auto ret = CheckGrantPermission(uris, photoPermissionTypes, hideSensitiveTpye);
342 CHECK_AND_RETURN_RET(ret == E_SUCCESS, E_ERR);
343 MEDIA_INFO_LOG("MediaLibraryExtendManager::GrantPhotoUriPermission Start");
344 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, E_ERR, "dataShareHelper is nullptr");
345 GrantUrisPermissionInnerReqBody reqBody;
346 reqBody.tokenId = (int64_t)targetTokenId;
347 reqBody.srcTokenId = (int64_t)srcTokenId;
348 reqBody.hideSensitiveType = static_cast<int32_t>(hideSensitiveTpye);
349 for (size_t i = 0; i < uris.size(); i++) {
350 auto uri = uris.at(i);
351 auto photoPermissionType = photoPermissionTypes.at(i);
352 int32_t tableType = -1;
353 for (const auto &iter : tableMap) {
354 if (uri.find(iter.first) != string::npos) {
355 tableType = static_cast<int32_t>(iter.second);
356 }
357 }
358 CHECK_AND_RETURN_RET_LOG(tableType != -1, E_ERR, "Uri invalid error, uri:%{private}s", uri.c_str());
359 string fileId = MediaFileUtils::GetIdFromUri(uri);
360 reqBody.fileIds.emplace_back(fileId);
361 reqBody.uriTypes.emplace_back(tableType);
362 if (photoPermissionType == PhotoPermissionType::GRANT_PERSIST_READWRITE_IMAGEVIDEO) {
363 reqBody.permissionTypes.emplace_back(static_cast<int32_t>(PhotoPermissionType::PERSIST_WRITE_IMAGEVIDEO));
364 reqBody.fileIds.emplace_back(fileId);
365 reqBody.uriTypes.emplace_back(tableType);
366 reqBody.permissionTypes.emplace_back(static_cast<int32_t>(PhotoPermissionType::PERSIST_READ_IMAGEVIDEO));
367 continue;
368 }
369 reqBody.permissionTypes.emplace_back(static_cast<int32_t>(photoPermissionType));
370 }
371 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_GRANT_PHOTO_URI_PERMISSION);
372 MEDIA_INFO_LOG("before IPC::UserDefineIPCClient().Call, INNER_GRANT_PHOTO_URI_PERMISSION");
373 int32_t result = IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper_).Call(businessCode, reqBody);
374 if (result == E_ERR && ForceReconnect()) {
375 MEDIA_WARN_LOG("Failed to Call INNER_GRANT_PHOTO_URI_PERMISSION and retry");
376 result = IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper_).Call(businessCode, reqBody);
377 }
378 return result;
379 }
380
BuildPermissionType(const bool persistFlag,const OperationMode mode)381 static vector<string> BuildPermissionType(const bool persistFlag, const OperationMode mode)
382 {
383 vector<string> permissionTypes;
384 if (persistFlag) {
385 if (static_cast<uint32_t>(mode) & static_cast<uint32_t>(OperationMode::READ_MODE)) {
386 permissionTypes.push_back(
387 to_string(static_cast<uint32_t>(PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO)));
388 permissionTypes.push_back(
389 to_string(static_cast<uint32_t>(PhotoPermissionType::PERSIST_READ_IMAGEVIDEO)));
390 }
391 if (static_cast<uint32_t>(mode) & static_cast<uint32_t>(OperationMode::WRITE_MODE)) {
392 permissionTypes.push_back(
393 to_string(static_cast<uint32_t>(PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO)));
394 permissionTypes.push_back(
395 to_string(static_cast<uint32_t>(PhotoPermissionType::PERSIST_WRITE_IMAGEVIDEO)));
396 }
397 if (static_cast<uint32_t>(mode) & static_cast<uint32_t>(OperationMode::READ_MODE) &&
398 static_cast<uint32_t>(mode) & static_cast<uint32_t>(OperationMode::WRITE_MODE)) {
399 permissionTypes.push_back(to_string(
400 static_cast<uint32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
401 permissionTypes.push_back(
402 to_string(static_cast<uint32_t>(PhotoPermissionType::GRANT_PERSIST_READWRITE_IMAGEVIDEO)));
403 }
404 } else {
405 permissionTypes.push_back(
406 to_string(static_cast<uint32_t>(PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO)));
407 permissionTypes.push_back(
408 to_string(static_cast<uint32_t>(PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO)));
409 permissionTypes.push_back(
410 to_string(static_cast<uint32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
411 }
412 return permissionTypes;
413 }
414
CancelPhotoUriPermission(uint32_t srcTokenId,uint32_t targetTokenId,const std::vector<string> & uris,const bool persistFlag,const vector<OperationMode> & operationModes)415 int32_t MediaLibraryExtendManager::CancelPhotoUriPermission(uint32_t srcTokenId, uint32_t targetTokenId,
416 const std::vector<string> &uris, const bool persistFlag, const vector<OperationMode> &operationModes)
417 {
418 MediaLibraryTracer tracer;
419 tracer.Start("MediaLibraryExtendManager::CancelPhotoUriPermission");
420 MEDIA_DEBUG_LOG("CancelPermission begin, srcToken:%{private}d, targetToken:%{private}d", srcTokenId, targetTokenId);
421 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, E_ERR, "dataShareHelper is nullptr");
422 vector<OperationMode> operModesCopy;
423 if (persistFlag) {
424 operModesCopy.insert(operModesCopy.end(), operationModes.begin(), operationModes.end());
425 } else {
426 operModesCopy.resize(uris.size(), OperationMode::READ_WRITE_MODE);
427 }
428 vector<DataShareValuesBucket> valueSet;
429 bool cond = ((uris.empty()) || (uris.size() > URI_MAX_SIZE) || (uris.size() != operModesCopy.size()));
430 CHECK_AND_RETURN_RET_LOG(!cond, E_ERR, "Media Uri list error, please check!");
431 CancelUriPermissionInnerReqBody reqBody;
432 reqBody.targetTokenId = (int64_t)targetTokenId;
433 reqBody.srcTokenId = (int64_t)srcTokenId;
434 for (size_t i = 0; i < uris.size(); i++) {
435 string uri = uris[i];
436 int32_t tableType = -1;
437 for (const auto &iter : tableMap) {
438 if (uri.find(iter.first) != string::npos) {
439 tableType = static_cast<int32_t>(iter.second);
440 }
441 }
442 CHECK_AND_RETURN_RET_LOG(tableType != -1, E_ERR, "Uri invalid error, uri:%{private}s", uri.c_str());
443 string fileId = MediaFileUtils::GetIdFromUri(uri);
444 MEDIA_DEBUG_LOG("CancelPermission fileId:%{private}s, tableType:%{private}d", fileId.c_str(), tableType);
445 reqBody.fileIds.emplace_back(fileId);
446 reqBody.uriTypes.emplace_back(tableType);
447 vector<string> permissionTypes = BuildPermissionType(persistFlag, operModesCopy[i]);
448 reqBody.permissionTypes.emplace_back(permissionTypes);
449 }
450 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_CANCEL_PHOTO_URI_PERMISSION);
451 MEDIA_INFO_LOG("before IPC::UserDefineIPCClient().Call, INNER_CANCEL_PHOTO_URI_PERMISSION");
452 int32_t result = IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper_).Call(businessCode, reqBody);
453 return result;
454 }
455
CheckUri(string & uri)456 static bool CheckUri(string &uri)
457 {
458 if (uri.find("../") != string::npos) {
459 return false;
460 }
461 string uriprex = "file://media";
462 return uri.substr(0, uriprex.size()) == uriprex;
463 }
464
OpenAsset(string & uri,const string openMode,HideSensitiveType type)465 int32_t MediaLibraryExtendManager::OpenAsset(string &uri, const string openMode, HideSensitiveType type)
466 {
467 CHECK_AND_RETURN_RET(!openMode.empty(), E_ERR);
468 CHECK_AND_RETURN_RET_LOG(CheckUri(uri), E_ERR, "invalid uri");
469
470 string originOpenMode = openMode;
471 std::transform(originOpenMode.begin(), originOpenMode.end(),
472 originOpenMode.begin(), [](unsigned char c) {return std::tolower(c);});
473 CHECK_AND_RETURN_RET(MEDIA_OPEN_MODES.count(originOpenMode), E_ERR);
474 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, E_ERR, "Failed to open Asset, datashareHelper is nullptr");
475
476 string assetUri = uri;
477 MediaFileUtils::UriAppendKeyValue(assetUri, "type", to_string(static_cast<int32_t>(type)));
478 MEDIA_DEBUG_LOG("merged uri = %{public}s", assetUri.c_str());
479 Uri openUri(assetUri);
480 int ret = dataShareHelper_->OpenFile(openUri, openMode);
481 if (ret == DATASHARE_ERR && ForceReconnect()) {
482 MEDIA_WARN_LOG("Failed to OpenFile and retry");
483 ret = dataShareHelper_->OpenFile(openUri, openMode);
484 }
485 return ret;
486 }
487
ReadPrivateMovingPhoto(string & uri,const HideSensitiveType type)488 int32_t MediaLibraryExtendManager::ReadPrivateMovingPhoto(string &uri, const HideSensitiveType type)
489 {
490 CHECK_AND_RETURN_RET_LOG(CheckUri(uri), E_ERR, "invalid uri: %{public}s", uri.c_str());
491 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, E_ERR,
492 "Failed to read video of moving photo, datashareHelper is nullptr");
493
494 string movingPhotoUri = uri;
495 MediaFileUtils::UriAppendKeyValue(movingPhotoUri, "type", to_string(static_cast<int32_t>(type)));
496 MediaFileUtils::UriAppendKeyValue(movingPhotoUri, MEDIA_MOVING_PHOTO_OPRN_KEYWORD, OPEN_PRIVATE_LIVE_PHOTO);
497 Uri openMovingPhotoUri(movingPhotoUri);
498 int ret = dataShareHelper_->OpenFile(openMovingPhotoUri, MEDIA_FILEMODE_READONLY);
499 if (ret == DATASHARE_ERR && ForceReconnect()) {
500 MEDIA_WARN_LOG("Failed to OpenFile and retry");
501 ret = dataShareHelper_->OpenFile(openMovingPhotoUri, MEDIA_FILEMODE_READONLY);
502 }
503 return ret;
504 }
505
CheckPhotoUri(const string & uri)506 static bool CheckPhotoUri(const string &uri)
507 {
508 if (uri.find("../") != string::npos) {
509 return false;
510 }
511 string photoUriPrefix = "file://media/Photo/";
512 return MediaFileUtils::StartsWith(uri, photoUriPrefix);
513 }
514
GetResultSetFromPhotos(const string & value,vector<string> & columns)515 std::shared_ptr<DataShareResultSet> MediaLibraryExtendManager::GetResultSetFromPhotos(const string &value,
516 vector<string> &columns)
517 {
518 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, nullptr, "datashareHelper is nullptr");
519 if (!CheckPhotoUri(value)) {
520 MEDIA_ERR_LOG("Failed to check invalid uri: %{public}s", value.c_str());
521 return nullptr;
522 }
523
524 GetResultSetFromPhotosExtendReqBody reqBody;
525 reqBody.value = value;
526 reqBody.columns = columns;
527 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_GET_RESULT_SET_FROM_PHOTOS_EXTEND);
528 GetResultSetFromDbRespBody respBody;
529 int32_t errCode =
530 IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper_).Call(businessCode, reqBody, respBody);
531 if (errCode != E_OK) {
532 MEDIA_WARN_LOG("errCode: %{public}d, reconnect and retry", errCode);
533 if (ForceReconnect()) {
534 errCode =
535 IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper_).Call(businessCode, reqBody, respBody);
536 }
537 if (errCode != E_OK) {
538 MEDIA_ERR_LOG("errCode: %{public}d", errCode);
539 return nullptr;
540 }
541 }
542 return respBody.resultSet;
543 }
544
GetResultSetFromDb(string columnName,const string & value,vector<string> & columns)545 std::shared_ptr<DataShareResultSet> MediaLibraryExtendManager::GetResultSetFromDb(string columnName,
546 const string &value, vector<string> &columns)
547 {
548 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, nullptr, "dataShareHelper is null");
549 if (columnName == MEDIA_DATA_DB_URI) {
550 return GetResultSetFromPhotos(value, columns);
551 }
552
553 GetResultSetFromDbReqBody reqBody;
554 reqBody.columnName = columnName;
555 reqBody.value = value;
556 reqBody.columns = columns;
557 uint32_t businessCode = static_cast<uint32_t>(MediaLibraryBusinessCode::INNER_GET_RESULT_SET_FROM_DB_EXTEND);
558 GetResultSetFromDbRespBody respBody;
559 int32_t errCode =
560 IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper_).Call(businessCode, reqBody, respBody);
561 if (errCode != E_OK) {
562 MEDIA_WARN_LOG("errCode: %{public}d, reconnect and retry", errCode);
563 if (ForceReconnect()) {
564 errCode =
565 IPC::UserInnerIPCClient().SetDataShareHelper(dataShareHelper_).Call(businessCode, reqBody, respBody);
566 }
567 if (errCode != E_OK) {
568 MEDIA_ERR_LOG("errCode: %{public}d", errCode);
569 return nullptr;
570 }
571 }
572 return respBody.resultSet;
573 }
574
CheckPermissionType(const string & fileId,map<string,pair<bool,bool>> & permissionMap,PhotoPermissionType checkType)575 static bool CheckPermissionType(const string &fileId, map<string, pair<bool, bool>> &permissionMap,
576 PhotoPermissionType checkType)
577 {
578 auto it = permissionMap.find(fileId);
579 if (it == permissionMap.end()) {
580 return false;
581 }
582 switch (checkType) {
583 case PhotoPermissionType::PERSIST_READ_IMAGEVIDEO:
584 return it->second.first;
585 case PhotoPermissionType::PERSIST_WRITE_IMAGEVIDEO:
586 return it->second.second;
587 case PhotoPermissionType::GRANT_PERSIST_READWRITE_IMAGEVIDEO:
588 return it->second.first && it->second.second;
589 default:
590 MEDIA_WARN_LOG("invalid permissiontype");
591 return false;
592 }
593 }
594
SavePermission(const string & fileId,map<string,pair<bool,bool>> & permissionMap,PhotoPermissionType currentType)595 static void SavePermission(const string &fileId, map<string, pair<bool, bool>> &permissionMap,
596 PhotoPermissionType currentType)
597 {
598 switch (currentType) {
599 case PhotoPermissionType::PERSIST_READ_IMAGEVIDEO:
600 permissionMap[fileId].first = true;
601 break;
602 case PhotoPermissionType::PERSIST_WRITE_IMAGEVIDEO:
603 permissionMap[fileId].second = true;
604 break;
605 default:
606 MEDIA_WARN_LOG("invalid permission, break");
607 return;
608 }
609 }
610
GetPhotoUrisPermission(uint32_t targetTokenId,const std::vector<string> & uris,PhotoPermissionType photoPermissionType,std::vector<bool> & result)611 int32_t MediaLibraryExtendManager::GetPhotoUrisPermission(uint32_t targetTokenId, const std::vector<string> &uris,
612 PhotoPermissionType photoPermissionType, std::vector<bool> &result)
613 {
614 CHECK_AND_RETURN_RET_LOG(dataShareHelper_ != nullptr, E_ERR, "dataShareHelper is nullptr");
615 MEDIA_DEBUG_LOG("GetPhotoUrisPermission begin, targetTokenId:%{private}d", targetTokenId);
616
617 vector<string> columns = {
618 AppUriPermissionColumn::FILE_ID,
619 AppUriPermissionColumn::PERMISSION_TYPE,
620 AppUriPermissionColumn::TARGET_TOKENID
621 };
622
623 DataSharePredicates predicates;
624 predicates.EqualTo(AppUriPermissionColumn::TARGET_TOKENID, static_cast<int64_t>(targetTokenId));
625
626 result.resize(uris.size(), false);
627
628 std::vector<std::string> fileIds;
629 for (const auto &uri : uris) {
630 fileIds.push_back(MediaFileUtils::GetIdFromUri(uri));
631 }
632 predicates.In(AppUriPermissionColumn::FILE_ID, fileIds);
633
634 Uri queryUri(MEDIALIBRARY_CHECK_URIPERM_URI);
635 auto queryResultSet = dataShareHelper_->Query(queryUri, predicates, columns);
636 if (queryResultSet == nullptr) {
637 MEDIA_ERR_LOG("Failed to query Uris");
638 return E_ERR;
639 }
640
641 map<string, pair<bool, bool>> permissionMap;
642 while (queryResultSet->GoToNextRow() == NativeRdb::E_OK) {
643 string fileId = GetStringVal(AppUriPermissionColumn::FILE_ID, queryResultSet);
644 int32_t permissionType = GetInt32Val(AppUriPermissionColumn::PERMISSION_TYPE, queryResultSet);
645 SavePermission(fileId, permissionMap, static_cast<PhotoPermissionType>(permissionType));
646 }
647
648 for (size_t i = 0; i < uris.size(); ++i) {
649 string fileId = MediaFileUtils::GetIdFromUri(uris[i]);
650 result[i] = CheckPermissionType(fileId, permissionMap, photoPermissionType);
651 }
652 return E_SUCCESS;
653 }
654
GetPhotoUrisPermission(uint32_t targetTokenId,const std::vector<string> & uris,const vector<PhotoPermissionType> & photoPermissionTypes,std::vector<bool> & result)655 int32_t MediaLibraryExtendManager::GetPhotoUrisPermission(uint32_t targetTokenId, const std::vector<string> &uris,
656 const vector<PhotoPermissionType> &photoPermissionTypes, std::vector<bool> &result)
657 {
658 MediaLibraryTracer tracer;
659 tracer.Start("MediaLibraryExtendManager::GetPhotoUrisPermission");
660 CHECK_AND_RETURN_RET_LOG(!uris.empty() && uris.size() <= URI_MAX_SIZE && uris.size() == photoPermissionTypes.size(),
661 E_ERR, "Uri or photoPermissionType list error, please check!");
662
663 std::set<PhotoPermissionType> queryTypes;
664 for (auto &photoPermissionType : photoPermissionTypes) {
665 if (photoPermissionType != PhotoPermissionType::PERSIST_READ_IMAGEVIDEO &&
666 photoPermissionType != PhotoPermissionType::GRANT_PERSIST_READWRITE_IMAGEVIDEO &&
667 photoPermissionType != PhotoPermissionType::PERSIST_WRITE_IMAGEVIDEO) {
668 MEDIA_ERR_LOG("photoPermissionType error, please check param!");
669 return E_ERR;
670 }
671 queryTypes.insert(photoPermissionType);
672 }
673
674 std::vector<bool> persistReadResult(uris.size(), false);
675 std::vector<bool> persistReadWriteResult(uris.size(), false);
676 std::vector<bool> persistWriteResult(uris.size(), false);
677 map<PhotoPermissionType, std::vector<bool>> typeMap = {
678 { PhotoPermissionType::PERSIST_READ_IMAGEVIDEO, persistReadResult },
679 { PhotoPermissionType::PERSIST_WRITE_IMAGEVIDEO, persistWriteResult },
680 { PhotoPermissionType::GRANT_PERSIST_READWRITE_IMAGEVIDEO, persistReadWriteResult },
681 };
682 for (auto& type : queryTypes) {
683 int32_t ret = GetPhotoUrisPermission(targetTokenId, uris, type, typeMap[type]);
684 if (ret != E_SUCCESS) {
685 MEDIA_ERR_LOG("Failed to get permission: %d", type);
686 return E_ERR;
687 }
688 }
689
690 result.resize(uris.size(), false);
691 for (size_t i = 0; i < uris.size(); ++i) {
692 result[i] = typeMap[photoPermissionTypes[i]][i];
693 }
694 return E_SUCCESS;
695 }
696
GetUrisFromFusePaths(const std::vector<std::string> paths,std::vector<std::string> & uris)697 int32_t MediaLibraryExtendManager::GetUrisFromFusePaths(const std::vector<std::string> paths,
698 std::vector<std::string> &uris)
699 {
700 MediaLibraryTracer tracer;
701 tracer.Start("MediaLibraryExtendManager::GetUrisFromFusePaths");
702
703 if ((paths.empty()) || (paths.size() > URI_MAX_SIZE)) {
704 MEDIA_ERR_LOG("Path list error, please check!");
705 return E_ERR;
706 }
707 const std::string FUSE_PATH_PREFIX_1 = "/data/storage/el2/media/";
708 const std::string FUSE_PATH_PREFIX_2 = "/mnt/data/100/media_fuse/";
709 const std::string URI_PREFIX = "file://media/";
710
711 for (const auto &path : paths) {
712 if (path.compare(0, FUSE_PATH_PREFIX_1.length(), FUSE_PATH_PREFIX_1) == 0) {
713 std::string uri = URI_PREFIX + path.substr(FUSE_PATH_PREFIX_1.length());
714 uris.push_back(uri);
715 } else if (path.compare(0, FUSE_PATH_PREFIX_2.length(), FUSE_PATH_PREFIX_2) == 0) {
716 std::string uri = URI_PREFIX + path.substr(FUSE_PATH_PREFIX_2.length());
717 uris.push_back(uri);
718 } else {
719 MEDIA_ERR_LOG("Invalid path: %{private}s", path.c_str());
720 return E_ERR;
721 }
722 }
723 return E_SUCCESS;
724 }
725 } // namespace Media
726 } // namespace OHOS