• 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 #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