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