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