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