• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "medialibrary_uripermission_operations.h"
17 
18 #include <iostream>
19 #include <sstream>
20 #include <string>
21 #include <cstdint>
22 
23 #include "common_func.h"
24 #include "ipc_skeleton.h"
25 #include "medialibrary_bundle_manager.h"
26 #include "medialibrary_errno.h"
27 #include "medialibrary_object_utils.h"
28 #include "medialibrary_type_const.h"
29 #include "media_file_utils.h"
30 #include "media_log.h"
31 #include "media_app_uri_permission_column.h"
32 #include "medialibrary_appstate_observer.h"
33 #include "medialibrary_rdb_transaction.h"
34 #include "media_library_manager.h"
35 #include "permission_utils.h"
36 #include "result_set_utils.h"
37 #include "rdb_utils.h"
38 #include "userfilemgr_uri.h"
39 #include "media_file_uri.h"
40 #include "data_secondary_directory_uri.h"
41 
42 namespace OHOS {
43 namespace Media {
44 using namespace std;
45 using namespace OHOS::NativeRdb;
46 using namespace OHOS::DataShare;
47 using namespace OHOS::RdbDataShareAdapter;
48 
49 constexpr int32_t NO_DB_OPERATION = -1;
50 constexpr int32_t UPDATE_DB_OPERATION = 0;
51 constexpr int32_t INSERT_DB_OPERATION = 1;
52 constexpr int32_t PHOTOSTYPE = 1;
53 constexpr int32_t AUDIOSTYPE = 2;
54 
55 constexpr int32_t FILE_ID_INDEX = 0;
56 constexpr int32_t URI_TYPE_INDEX = 1;
57 constexpr int32_t PERMISSION_TYPE_INDEX = 2;
58 constexpr int32_t SRC_TOKEN_ID_INDEX = 3;
59 constexpr int32_t TARGET_TOKEN_ID_INDEX = 4;
60 
61 const string DB_OPERATION = "uriPermission_operation";
62 
CheckMode(string & mode)63 static bool CheckMode(string& mode)
64 {
65     transform(mode.begin(), mode.end(), mode.begin(), ::tolower);
66     if (MEDIA_OPEN_MODES.find(mode) == MEDIA_OPEN_MODES.end()) {
67         MEDIA_ERR_LOG("mode format is error: %{private}s", mode.c_str());
68         return false;
69     }
70     string tempMode;
71     if (mode.find(MEDIA_FILEMODE_READONLY) != string::npos) {
72         tempMode += MEDIA_FILEMODE_READONLY;
73     }
74     if (mode.find(MEDIA_FILEMODE_WRITEONLY) != string::npos) {
75         tempMode += MEDIA_FILEMODE_WRITEONLY;
76     }
77     mode = tempMode;
78     return true;
79 }
80 
UpdateOperation(MediaLibraryCommand & cmd,std::shared_ptr<TransactionOperations> trans)81 int32_t UriPermissionOperations::UpdateOperation(MediaLibraryCommand &cmd,
82     std::shared_ptr<TransactionOperations> trans)
83 {
84     cmd.SetTableName(AppUriPermissionColumn::APP_URI_PERMISSION_TABLE);
85     int32_t updateRows = -1;
86     int errCode;
87     if (trans == nullptr) {
88         auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
89         CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr,
90             E_HAS_DB_ERROR, "UriPermission update operation, rdbStore is null.");
91         errCode = rdbStore->Update(cmd, updateRows);
92     } else {
93         errCode = trans->Update(cmd, updateRows);
94     }
95     bool cond = (errCode != NativeRdb::E_OK || updateRows < 0);
96     CHECK_AND_RETURN_RET_LOG(!cond, E_HAS_DB_ERROR, "UriPermission Update db failed, errCode = %{public}d", errCode);
97     return updateRows;
98 }
99 
DeleteAllTemporaryOperation(AsyncTaskData * data)100 static void DeleteAllTemporaryOperation(AsyncTaskData *data)
101 {
102     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
103     if (rdbStore == nullptr) {
104         MEDIA_ERR_LOG("UriPermission update operation, rdbStore is null.");
105         return;
106     }
107     NativeRdb::RdbPredicates rdbPredicate(AppUriPermissionColumn::APP_URI_PERMISSION_TABLE);
108     vector<string> permissionTypes;
109     permissionTypes.emplace_back(to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READ_IMAGEVIDEO)));
110     permissionTypes.emplace_back(to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_WRITE_IMAGEVIDEO)));
111     permissionTypes.emplace_back(to_string(static_cast<int32_t>(PhotoPermissionType::TEMPORARY_READWRITE_IMAGEVIDEO)));
112     rdbPredicate.And()->In(AppUriPermissionColumn::PERMISSION_TYPE, permissionTypes);
113     int32_t ret = rdbStore->Delete(rdbPredicate);
114     CHECK_AND_RETURN_LOG(ret >= 0, "UriPermission table delete all temporary permission failed");
115     MEDIA_INFO_LOG("UriPermission table delete all %{public}d rows temporary permission success", ret);
116 }
117 
DeleteAllTemporaryAsync()118 void UriPermissionOperations::DeleteAllTemporaryAsync()
119 {
120     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
121     if (asyncWorker == nullptr) {
122         MEDIA_ERR_LOG("Can not get asyncWorker");
123         return;
124     }
125     shared_ptr<MediaLibraryAsyncTask> notifyAsyncTask =
126         make_shared<MediaLibraryAsyncTask>(DeleteAllTemporaryOperation, nullptr);
127     if (notifyAsyncTask != nullptr) {
128         asyncWorker->AddTask(notifyAsyncTask, false);
129     } else {
130         MEDIA_ERR_LOG("Failed to create async task for UriPermission");
131     }
132 }
133 
DeleteOperation(MediaLibraryCommand & cmd)134 int32_t UriPermissionOperations::DeleteOperation(MediaLibraryCommand &cmd)
135 {
136     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
137     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "UriPermission update operation, rdbStore is null.");
138     cmd.SetTableName(AppUriPermissionColumn::APP_URI_PERMISSION_TABLE);
139     int32_t deleteRows = -1;
140     int32_t errCode = rdbStore->Delete(cmd, deleteRows);
141     if (errCode != NativeRdb::E_OK || deleteRows < 0) {
142         MEDIA_ERR_LOG("UriPermission delete db failed, errCode = %{public}d", errCode);
143         return E_HAS_DB_ERROR;
144     }
145     return static_cast<int32_t>(deleteRows);
146 }
147 
InsertOperation(MediaLibraryCommand & cmd)148 int32_t UriPermissionOperations::InsertOperation(MediaLibraryCommand &cmd)
149 {
150     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
151     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "UriPermission insert operation, rdbStore is null.");
152 
153     cmd.SetTableName(AppUriPermissionColumn::APP_URI_PERMISSION_TABLE);
154     int64_t rowId = -1;
155     int32_t errCode = rdbStore->Insert(cmd, rowId);
156     bool cond = (errCode != NativeRdb::E_OK || rowId < 0);
157     CHECK_AND_RETURN_RET_LOG(!cond, E_HAS_DB_ERROR, "UriPermission insert db failed, errCode = %{public}d", errCode);
158     return static_cast<int32_t>(rowId);
159 }
160 
BatchInsertOperation(MediaLibraryCommand & cmd,std::vector<ValuesBucket> & values,std::shared_ptr<TransactionOperations> trans)161 int32_t UriPermissionOperations::BatchInsertOperation(MediaLibraryCommand &cmd,
162     std::vector<ValuesBucket> &values, std::shared_ptr<TransactionOperations> trans)
163 {
164     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
165     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "UriPermission insert operation, rdbStore is null.");
166 
167     cmd.SetTableName(AppUriPermissionColumn::APP_URI_PERMISSION_TABLE);
168     int64_t outInsertNum = -1;
169     int32_t errCode;
170     if (trans == nullptr) {
171         errCode = rdbStore->BatchInsert(cmd, outInsertNum, values);
172     } else {
173         errCode = trans->BatchInsert(cmd, outInsertNum, values);
174     }
175     bool cond = (errCode != NativeRdb::E_OK || outInsertNum < 0);
176     CHECK_AND_RETURN_RET_LOG(!cond, E_HAS_DB_ERROR,
177         "UriPermission Insert into db failed, errCode = %{public}d", errCode);
178     return static_cast<int32_t>(outInsertNum);
179 }
180 
QueryUriPermission(MediaLibraryCommand & cmd,const std::vector<DataShareValuesBucket> & values,std::shared_ptr<OHOS::NativeRdb::ResultSet> & resultSet)181 static void QueryUriPermission(MediaLibraryCommand &cmd, const std::vector<DataShareValuesBucket> &values,
182     std::shared_ptr<OHOS::NativeRdb::ResultSet> &resultSet)
183 {
184     vector<string> columns;
185     vector<string> predicateInColumns;
186     DataSharePredicates predicates;
187     bool isValid;
188     int64_t targetTokenId = values.at(0).Get(AppUriPermissionColumn::TARGET_TOKENID, isValid);
189     int64_t srcTokenId = values.at(0).Get(AppUriPermissionColumn::SOURCE_TOKENID, isValid);
190     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
191     if (rdbStore == nullptr) {
192         MEDIA_ERR_LOG("UriPermission query operation, rdbStore is null.");
193         return;
194     }
195     cmd.SetTableName(AppUriPermissionColumn::APP_URI_PERMISSION_TABLE);
196     for (const auto &val : values) {
197         predicateInColumns.push_back(static_cast<string>(val.Get(AppUriPermissionColumn::FILE_ID, isValid)));
198     }
199     predicates.In(AppUriPermissionColumn::FILE_ID, predicateInColumns);
200     predicates.And()->EqualTo(AppUriPermissionColumn::TARGET_TOKENID, (int64_t)targetTokenId);
201     predicates.And()->EqualTo(AppUriPermissionColumn::SOURCE_TOKENID, (int64_t)srcTokenId);
202     cmd.SetDataSharePred(predicates);
203     NativeRdb::RdbPredicates rdbPredicate = RdbUtils::ToPredicates(predicates, cmd.GetTableName());
204     cmd.GetAbsRdbPredicates()->SetWhereClause(rdbPredicate.GetWhereClause());
205     cmd.GetAbsRdbPredicates()->SetWhereArgs(rdbPredicate.GetWhereArgs());
206     resultSet = rdbStore->Query(cmd, columns);
207 }
208 
CanConvertToInt32(const std::string & str)209 static bool CanConvertToInt32(const std::string &str)
210 {
211     std::istringstream iss(str);
212     int32_t num = 0;
213     iss >> num;
214     return iss.eof() && !iss.fail();
215 }
216 
GetFileId(const DataShareValuesBucket & values,bool & isValid)217 static int32_t GetFileId(const DataShareValuesBucket &values, bool &isValid)
218 {
219     int32_t ret = E_ERR;
220     string fileIdStr = static_cast<string>(values.Get(AppUriPermissionColumn::FILE_ID, isValid));
221     if (CanConvertToInt32(fileIdStr)) {
222         ret = static_cast<int32_t>(std::stoi(fileIdStr));
223     }
224     return ret;
225 }
226 
GetSingleDbOperation(const vector<DataShareValuesBucket> & values,vector<int32_t> & dbOperation,vector<int32_t> & querySingleResultSet,int index)227 static void GetSingleDbOperation(const vector<DataShareValuesBucket> &values, vector<int32_t> &dbOperation,
228     vector<int32_t> &querySingleResultSet, int index)
229 {
230     bool isValid;
231     int32_t fileId = GetFileId(values.at(index), isValid);
232     if (fileId == E_ERR) {
233         MEDIA_ERR_LOG("Failed GetFileId");
234         return;
235     }
236     int32_t uriType = values.at(index).Get(AppUriPermissionColumn::URI_TYPE, isValid);
237     int32_t permissionType = values.at(index).Get(AppUriPermissionColumn::PERMISSION_TYPE, isValid);
238     if ((fileId == querySingleResultSet.at(FILE_ID_INDEX)) && (uriType == querySingleResultSet.at(URI_TYPE_INDEX))
239         && (permissionType == querySingleResultSet.at(PERMISSION_TYPE_INDEX))) {
240         dbOperation[index] = NO_DB_OPERATION;
241     }
242 }
243 
GetMediafileQueryResult(const vector<string> & predicateInColumns,OperationObject object,std::vector<int32_t> & fileIdList)244 static void GetMediafileQueryResult(const vector<string>& predicateInColumns, OperationObject object,
245     std::vector<int32_t>& fileIdList)
246 {
247     MediaLibraryCommand queryCmd(object, OperationType::QUERY);
248     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
249     if (rdbStore == nullptr) {
250         MEDIA_ERR_LOG("UriPermission query operation, rdbStore is null.");
251         return;
252     }
253     vector<string> columns;
254     queryCmd.GetAbsRdbPredicates()->In(AppUriPermissionColumn::FILE_ID, predicateInColumns);
255     auto queryResult = rdbStore->Query(queryCmd, columns);
256     if ((queryResult == nullptr) || (queryResult->GoToFirstRow() != NativeRdb::E_OK)) {
257         MEDIA_INFO_LOG("UriPermission query result is null.");
258         return;
259     }
260     do {
261         fileIdList.push_back(GetInt32Val(AppUriPermissionColumn::FILE_ID, queryResult));
262     } while (!queryResult->GoToNextRow());
263 }
264 
FilterNotExistUri(const std::vector<DataShareValuesBucket> & values,vector<int32_t> & dbOperation)265 static void FilterNotExistUri(const std::vector<DataShareValuesBucket> &values, vector<int32_t>& dbOperation)
266 {
267     vector<int32_t> photoFileIdList;
268     vector<int32_t> audioFileIdList;
269     vector<string> photosColumns;
270     vector<string> audioColumns;
271     bool isValid;
272     for (const auto &val : values) {
273         if (static_cast<int32_t>(val.Get(AppUriPermissionColumn::URI_TYPE, isValid)) == PHOTOSTYPE) {
274             photosColumns.push_back(val.Get(AppUriPermissionColumn::FILE_ID, isValid));
275         } else if (static_cast<int32_t>(val.Get(AppUriPermissionColumn::URI_TYPE, isValid)) == AUDIOSTYPE) {
276             audioColumns.push_back(val.Get(AppUriPermissionColumn::FILE_ID, isValid));
277         }
278     }
279     if (!photosColumns.empty()) {
280         GetMediafileQueryResult(photosColumns, OperationObject::FILESYSTEM_PHOTO, photoFileIdList);
281     }
282     if (!audioColumns.empty()) {
283         GetMediafileQueryResult(audioColumns, OperationObject::FILESYSTEM_AUDIO, audioFileIdList);
284     }
285     for (size_t i = 0; i < values.size(); i++) {
286         int32_t fileId = GetFileId(values.at(i), isValid);
287         int32_t uriType = values[i].Get(AppUriPermissionColumn::URI_TYPE, isValid);
288         if (uriType == PHOTOSTYPE) {
289             auto notExistIt = std::find(photoFileIdList.begin(), photoFileIdList.end(), fileId);
290             if (notExistIt == photoFileIdList.end()) {
291                 dbOperation[i] = NO_DB_OPERATION;
292             }
293         } else if (uriType == AUDIOSTYPE) {
294             auto it = std::find(audioFileIdList.begin(), audioFileIdList.end(), fileId);
295             if (it == audioFileIdList.end()) {
296                 dbOperation[i] = NO_DB_OPERATION;
297             }
298         }
299     }
300 }
301 
GetAllUriDbOperation(const vector<DataShareValuesBucket> & values,vector<int32_t> & dbOperation,std::shared_ptr<OHOS::NativeRdb::ResultSet> & queryResult)302 static void GetAllUriDbOperation(const vector<DataShareValuesBucket> &values, vector<int32_t> &dbOperation,
303     std::shared_ptr<OHOS::NativeRdb::ResultSet> &queryResult)
304 {
305     for (const auto &val : values) {
306         dbOperation.push_back(INSERT_DB_OPERATION);
307     }
308     if ((queryResult == nullptr) || (queryResult->GoToFirstRow() != NativeRdb::E_OK)) {
309         MEDIA_INFO_LOG("UriPermission query result is null.");
310         return;
311     }
312     do {
313         vector<int32_t> querySingleResultSet;
314         querySingleResultSet.push_back(GetInt32Val(AppUriPermissionColumn::FILE_ID, queryResult));
315         querySingleResultSet.push_back(GetInt32Val(AppUriPermissionColumn::URI_TYPE, queryResult));
316         querySingleResultSet.push_back(GetInt32Val(AppUriPermissionColumn::PERMISSION_TYPE, queryResult));
317         for (size_t i = 0; i < values.size(); i++) {
318             GetSingleDbOperation(values, dbOperation, querySingleResultSet, i);
319         }
320     } while (!queryResult->GoToNextRow());
321 }
322 
ValueBucketCheck(const std::vector<DataShareValuesBucket> & values)323 static int32_t ValueBucketCheck(const std::vector<DataShareValuesBucket> &values)
324 {
325     bool isValidArr[] = {false, false, false, false, false};
326     if (values.empty()) {
327         return E_ERR;
328     }
329     for (const auto &val : values) {
330         val.Get(AppUriPermissionColumn::FILE_ID, isValidArr[FILE_ID_INDEX]);
331         val.Get(AppUriPermissionColumn::URI_TYPE, isValidArr[URI_TYPE_INDEX]);
332         val.Get(AppUriPermissionColumn::PERMISSION_TYPE, isValidArr[PERMISSION_TYPE_INDEX]);
333         val.Get(AppUriPermissionColumn::SOURCE_TOKENID, isValidArr[SRC_TOKEN_ID_INDEX]);
334         val.Get(AppUriPermissionColumn::TARGET_TOKENID, isValidArr[TARGET_TOKEN_ID_INDEX]);
335         for (size_t i = 0; i < sizeof(isValidArr); i++) {
336             if ((isValidArr[i]) == false) {
337                 return E_ERR;
338             }
339         }
340     }
341     return E_OK;
342 }
343 
InsertValueBucketPrepare(const std::vector<DataShareValuesBucket> & values,int32_t fileId,int32_t uriType,int32_t permissionType,std::vector<ValuesBucket> & batchInsertBucket)344 static void InsertValueBucketPrepare(const std::vector<DataShareValuesBucket> &values, int32_t fileId,
345     int32_t uriType, int32_t permissionType, std::vector<ValuesBucket> &batchInsertBucket)
346 {
347     bool isValid;
348     ValuesBucket insertValues;
349     int64_t srcTokenId = values.at(0).Get(AppUriPermissionColumn::SOURCE_TOKENID, isValid);
350     int64_t targetTokenId = values.at(0).Get(AppUriPermissionColumn::TARGET_TOKENID, isValid);
351     insertValues.Put(AppUriPermissionColumn::PERMISSION_TYPE, permissionType);
352     insertValues.Put(AppUriPermissionColumn::FILE_ID, fileId);
353     insertValues.Put(AppUriPermissionColumn::TARGET_TOKENID, (int64_t)targetTokenId);
354     insertValues.Put(AppUriPermissionColumn::SOURCE_TOKENID, (int64_t)srcTokenId);
355     insertValues.Put(AppUriPermissionColumn::URI_TYPE, uriType);
356     insertValues.Put(AppUriPermissionColumn::DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
357     batchInsertBucket.push_back(insertValues);
358 }
359 
360 // SubscribeAppState && add tokenid to cache
DoSubscribeForAppStop(const std::vector<DataShare::DataShareValuesBucket> & values)361 static void DoSubscribeForAppStop(const std::vector<DataShare::DataShareValuesBucket> &values)
362 {
363     if (values.size() == 0) {
364         MEDIA_WARN_LOG("values is empty");
365         return;
366     }
367     auto it = values.begin();
368     ValuesBucket valueBucket = RdbUtils::ToValuesBucket(*it);
369     int64_t destTokenId = -1;
370     ValueObject valueObject;
371     if (valueBucket.GetObject(AppUriPermissionColumn::TARGET_TOKENID, valueObject)) {
372         valueObject.GetLong(destTokenId);
373     }
374     int permissionTypeParam = -1;
375     if (valueBucket.GetObject(AppUriPermissionColumn::PERMISSION_TYPE, valueObject)) {
376         valueObject.GetInt(permissionTypeParam);
377     }
378     if (AppUriPermissionColumn::PERMISSION_TYPES_TEMPORARY.find(permissionTypeParam) !=
379         AppUriPermissionColumn::PERMISSION_TYPES_TEMPORARY.end()) {
380         MedialibraryAppStateObserverManager::GetInstance().SubscribeAppState();
381         MedialibraryAppStateObserverManager::GetInstance().AddTokenId(destTokenId, false);
382     }
383 }
384 
GrantPermissionPrepareHandle(MediaLibraryCommand & cmd,const std::vector<DataShareValuesBucket> & values,std::vector<int32_t> & dbOperation)385 static void GrantPermissionPrepareHandle(MediaLibraryCommand &cmd, const std::vector<DataShareValuesBucket> &values,
386     std::vector<int32_t>& dbOperation)
387 {
388     DoSubscribeForAppStop(values);
389     std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet;
390     QueryUriPermission(cmd, values, resultSet);
391     GetAllUriDbOperation(values, dbOperation, resultSet);
392     FilterNotExistUri(values, dbOperation);
393 }
394 
GrantUriPermission(MediaLibraryCommand & cmd,const std::vector<DataShareValuesBucket> & values)395 int32_t UriPermissionOperations::GrantUriPermission(MediaLibraryCommand &cmd,
396     const std::vector<DataShareValuesBucket> &values)
397 {
398     std::vector<int32_t> dbOperation;
399     std::vector<ValuesBucket>  batchInsertBucket;
400     bool needToInsert = false;
401     bool isValid = false;
402     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
403     if (ValueBucketCheck(values) != E_OK || rdbStore == nullptr) {
404         return E_ERR;
405     }
406     GrantPermissionPrepareHandle(cmd, values, dbOperation);
407     for (size_t i = 0; i < values.size(); i++) {
408         int32_t fileId = GetFileId(values.at(i), isValid);
409         int32_t uriType = values.at(i).Get(AppUriPermissionColumn::URI_TYPE, isValid);
410         int32_t permissioinType = values.at(i).Get(AppUriPermissionColumn::PERMISSION_TYPE, isValid);
411         if (dbOperation.at(i) == INSERT_DB_OPERATION) {
412             needToInsert = true;
413             InsertValueBucketPrepare(values, fileId, uriType, permissioinType, batchInsertBucket);
414         }
415     }
416     if (!needToInsert) {
417         MEDIA_INFO_LOG("GrantUriPermission: no data need to insert!");
418         return E_OK;
419     }
420     std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
421     int32_t errCode = E_OK;
422     std::function<int(void)> func = [&]()->int {
423         UriPermissionOperations::BatchInsertOperation(cmd, batchInsertBucket, trans);
424         return errCode;
425     };
426     errCode = trans->RetryTrans(func);
427     if (errCode != E_OK) {
428         MEDIA_ERR_LOG("GrantUriPermission: trans retry fail!, ret:%{public}d", errCode);
429         return errCode;
430     }
431     return E_OK;
432 }
433 
HandleUriPermOperations(MediaLibraryCommand & cmd)434 int32_t UriPermissionOperations::HandleUriPermOperations(MediaLibraryCommand &cmd)
435 {
436     if (!PermissionUtils::CheckIsSystemAppByUid()) {
437         MEDIA_ERR_LOG("the caller is not system app");
438         return E_PERMISSION_DENIED;
439     }
440     string bundleName = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
441 
442     int32_t errCode = E_FAIL;
443     switch (cmd.GetOprnType()) {
444         case OperationType::INSERT_PERMISSION:
445             errCode = HandleUriPermInsert(cmd);
446             break;
447         default:
448             MEDIA_ERR_LOG("unknown operation type %{public}d", cmd.GetOprnType());
449             break;
450     }
451     return errCode;
452 }
453 
GetUriPermissionMode(const string & fileId,const string & bundleName,int32_t tableType,string & mode)454 int32_t UriPermissionOperations::GetUriPermissionMode(const string &fileId, const string &bundleName,
455     int32_t tableType, string &mode)
456 {
457     MediaLibraryCommand cmd(Uri(MEDIALIBRARY_BUNDLEPERM_URI), OperationType::QUERY);
458     cmd.GetAbsRdbPredicates()->EqualTo(PERMISSION_FILE_ID, fileId);
459     cmd.GetAbsRdbPredicates()->And()->EqualTo(PERMISSION_BUNDLE_NAME, bundleName);
460     cmd.GetAbsRdbPredicates()->And()->EqualTo(PERMISSION_TABLE_TYPE, to_string(tableType));
461     auto queryResult = MediaLibraryObjectUtils::QueryWithCondition(cmd, {}, "");
462     CHECK_AND_RETURN_RET_LOG(queryResult != nullptr, E_HAS_DB_ERROR, "Failed to obtain value from database");
463     int count = -1;
464     CHECK_AND_RETURN_RET_LOG(queryResult->GetRowCount(count) == NativeRdb::E_OK, E_HAS_DB_ERROR,
465         "Failed to get query result row count");
466     if (count <= 0) {
467         return E_PERMISSION_DENIED;
468     }
469     CHECK_AND_RETURN_RET_LOG(queryResult->GoToFirstRow() == NativeRdb::E_OK, E_HAS_DB_ERROR,
470         "Failed to go to first row");
471     mode = GetStringVal(PERMISSION_MODE, queryResult);
472     return E_SUCCESS;
473 }
474 
CheckUriPermValues(ValuesBucket & valuesBucket,int32_t & fileId,string & bundleName,int32_t & tableType,string & inputMode)475 static int32_t CheckUriPermValues(ValuesBucket &valuesBucket, int32_t &fileId, string &bundleName, int32_t &tableType,
476     string &inputMode)
477 {
478     ValueObject valueObject;
479     if (valuesBucket.GetObject(PERMISSION_FILE_ID, valueObject)) {
480         valueObject.GetInt(fileId);
481     } else {
482         MEDIA_ERR_LOG("ValueBucket does not have PERMISSION_FILE_ID");
483         return E_INVALID_VALUES;
484     }
485 
486     if (valuesBucket.GetObject(PERMISSION_BUNDLE_NAME, valueObject)) {
487         valueObject.GetString(bundleName);
488     } else {
489         MEDIA_ERR_LOG("ValueBucket does not have PERMISSION_BUNDLE_NAME");
490         return E_INVALID_VALUES;
491     }
492 
493     if (valuesBucket.GetObject(PERMISSION_MODE, valueObject)) {
494         valueObject.GetString(inputMode);
495     } else {
496         MEDIA_ERR_LOG("ValueBucket does not have PERMISSION_MODE");
497         return E_INVALID_VALUES;
498     }
499 
500     if (valuesBucket.GetObject(PERMISSION_TABLE_TYPE, valueObject)) {
501         valueObject.GetInt(tableType);
502     } else {
503         MEDIA_ERR_LOG("ValueBucket does not have PERMISSION_TABLE_TYPE");
504         return E_INVALID_VALUES;
505     }
506     if (!CheckMode(inputMode)) {
507         return E_INVALID_MODE;
508     }
509     valuesBucket.Delete(PERMISSION_MODE);
510     valuesBucket.PutString(PERMISSION_MODE, inputMode);
511     return E_SUCCESS;
512 }
513 
514 #ifdef MEDIALIBRARY_COMPATIBILITY
ConvertVirtualIdToRealId(ValuesBucket & valuesBucket,int32_t & fileId,int32_t tableType)515 static void ConvertVirtualIdToRealId(ValuesBucket &valuesBucket, int32_t &fileId, int32_t tableType)
516 {
517     if (tableType == static_cast<int32_t>(TableType::TYPE_PHOTOS)) {
518         fileId = MediaFileUtils::GetRealIdByTable(fileId, PhotoColumn::PHOTOS_TABLE);
519     } else if (tableType == static_cast<int32_t>(TableType::TYPE_AUDIOS)) {
520         fileId = MediaFileUtils::GetRealIdByTable(fileId, AudioColumn::AUDIOS_TABLE);
521     } else {
522         fileId = MediaFileUtils::GetRealIdByTable(fileId, MEDIALIBRARY_TABLE);
523     }
524 
525     valuesBucket.Delete(PERMISSION_FILE_ID);
526     valuesBucket.PutInt(PERMISSION_FILE_ID, fileId);
527 }
528 #endif
529 
530 
HandleUriPermInsert(MediaLibraryCommand & cmd)531 int32_t UriPermissionOperations::HandleUriPermInsert(MediaLibraryCommand &cmd)
532 {
533     return E_SUCCESS;
534 }
535 
GetTableTypeFromTableName(const std::string & tableName)536 static inline int32_t GetTableTypeFromTableName(const std::string &tableName)
537 {
538     if (tableName == PhotoColumn::PHOTOS_TABLE) {
539         return static_cast<int32_t>(TableType::TYPE_PHOTOS);
540     } else if (tableName == AudioColumn::AUDIOS_TABLE) {
541         return static_cast<int32_t>(TableType::TYPE_AUDIOS);
542     } else {
543         return static_cast<int32_t>(TableType::TYPE_FILES);
544     }
545 }
546 
InsertBundlePermission(const int32_t & fileId,const std::string & bundleName,const std::string & mode,const std::string & tableName)547 int32_t UriPermissionOperations::InsertBundlePermission(const int32_t &fileId, const std::string &bundleName,
548     const std::string &mode, const std::string &tableName)
549 {
550     string curMode;
551     int32_t tableType = GetTableTypeFromTableName(tableName);
552     auto ret = GetUriPermissionMode(to_string(fileId), bundleName, tableType, curMode);
553     if ((ret != E_SUCCESS) && (ret != E_PERMISSION_DENIED)) {
554         return ret;
555     }
556     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
557     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "uniStore is nullptr!");
558     if (ret == E_PERMISSION_DENIED) {
559         ValuesBucket addValues;
560         addValues.PutInt(PERMISSION_FILE_ID, fileId);
561         addValues.PutString(PERMISSION_BUNDLE_NAME, bundleName);
562         addValues.PutString(PERMISSION_MODE, mode);
563         addValues.PutInt(PERMISSION_TABLE_TYPE, tableType);
564         MediaLibraryCommand cmd(Uri(MEDIALIBRARY_BUNDLEPERM_URI), addValues);
565         int64_t outRowId = -1;
566         return uniStore->Insert(cmd, outRowId);
567     }
568     CHECK_AND_RETURN_RET(curMode.find(mode) == string::npos, E_SUCCESS);
569     ValuesBucket updateValues;
570     updateValues.PutString(PERMISSION_MODE, mode);
571     MediaLibraryCommand updateCmd(Uri(MEDIALIBRARY_BUNDLEPERM_URI), updateValues);
572     updateCmd.GetAbsRdbPredicates()->EqualTo(PERMISSION_FILE_ID, to_string(fileId))->And()->
573         EqualTo(PERMISSION_BUNDLE_NAME, bundleName)->And()->
574         EqualTo(PERMISSION_TABLE_TYPE, to_string(tableType));
575     int32_t updatedRows = -1;
576     return uniStore->Update(updateCmd, updatedRows);
577 }
578 
DeleteBundlePermission(const std::string & fileId,const std::string & bundleName,const std::string & tableName)579 int32_t UriPermissionOperations::DeleteBundlePermission(const std::string &fileId, const std::string &bundleName,
580     const std::string &tableName)
581 {
582     int32_t tableType = GetTableTypeFromTableName(tableName);
583 
584     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
585     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "uniStore is nullptr!");
586     Uri uri(MEDIALIBRARY_BUNDLEPERM_URI);
587     MediaLibraryCommand deleteCmd(uri);
588     deleteCmd.GetAbsRdbPredicates()->EqualTo(PERMISSION_FILE_ID, fileId)->And()->
589         EqualTo(PERMISSION_BUNDLE_NAME, bundleName)->And()->
590         EqualTo(PERMISSION_TABLE_TYPE, to_string(tableType));
591     int32_t deleteRows = -1;
592     int32_t ret = uniStore->Delete(deleteCmd, deleteRows);
593     if (deleteRows > 0 && ret == NativeRdb::E_OK) {
594         MEDIA_DEBUG_LOG("DeleteBundlePermission success:fileId:%{private}s, bundleName:%{private}s, table:%{private}s",
595             fileId.c_str(), bundleName.c_str(), tableName.c_str());
596         return E_OK;
597     }
598     return E_HAS_DB_ERROR;
599 }
600 
CheckUriPermission(const std::string & fileUri,std::string mode)601 int32_t UriPermissionOperations::CheckUriPermission(const std::string &fileUri, std::string mode)
602 {
603     if (!CheckMode(mode)) {
604         return E_INVALID_MODE;
605     }
606     string bundleName = MediaLibraryBundleManager::GetInstance()->GetClientBundleName();
607     string fileId = MediaFileUtils::GetIdFromUri(fileUri);
608     TableType tableType = TableType::TYPE_FILES;
609     static map<string, TableType> tableMap = {
610         { MEDIALIBRARY_TYPE_IMAGE_URI, TableType::TYPE_PHOTOS },
611         { MEDIALIBRARY_TYPE_VIDEO_URI, TableType::TYPE_PHOTOS },
612         { MEDIALIBRARY_TYPE_AUDIO_URI, TableType::TYPE_AUDIOS },
613         { MEDIALIBRARY_TYPE_FILE_URI, TableType::TYPE_FILES },
614         { PhotoColumn::PHOTO_TYPE_URI, TableType::TYPE_PHOTOS },
615         { AudioColumn::AUDIO_TYPE_URI, TableType::TYPE_AUDIOS }
616     };
617     for (const auto &iter : tableMap) {
618         if (fileUri.find(iter.first) != string::npos) {
619             tableType = iter.second;
620         }
621     }
622     string permissionMode;
623     int32_t ret = GetUriPermissionMode(fileId, bundleName, static_cast<int32_t>(tableType), permissionMode);
624     CHECK_AND_RETURN_RET(ret == E_SUCCESS, ret);
625     return (permissionMode.find(mode) != string::npos) ? E_SUCCESS : E_PERMISSION_DENIED;
626 }
627 }   // Media
628 }   // OHOS
629