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