• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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_urisensitive_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_errno.h"
26 #include "medialibrary_object_utils.h"
27 #include "medialibrary_type_const.h"
28 #include "media_file_utils.h"
29 #include "media_log.h"
30 #include "media_app_uri_sensitive_column.h"
31 #include "media_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 SENSITIVE_TYPE_INDEX = 2;
55 constexpr int32_t APP_ID_INDEX = 3;
56 
57 const string DB_OPERATION = "uriSensitive_operation";
58 
UpdateOperation(MediaLibraryCommand & cmd,NativeRdb::RdbPredicates & rdbPredicate,std::shared_ptr<TransactionOperations> trans)59 int32_t UriSensitiveOperations::UpdateOperation(MediaLibraryCommand &cmd,
60     NativeRdb::RdbPredicates &rdbPredicate, std::shared_ptr<TransactionOperations> trans)
61 {
62     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
63     if (rdbStore == nullptr) {
64         MEDIA_ERR_LOG("UriSensitive update operation, rdbStore is null.");
65         return E_HAS_DB_ERROR;
66     }
67     cmd.SetTableName(AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
68     int32_t updateRows;
69     if (trans == nullptr) {
70         updateRows = MediaLibraryRdbStore::UpdateWithDateTime(cmd.GetValueBucket(), rdbPredicate);
71     } else {
72         updateRows = trans->Update(cmd.GetValueBucket(), rdbPredicate);
73     }
74     if (updateRows < 0) {
75         MEDIA_ERR_LOG("UriSensitive Update db failed, errCode = %{public}d", updateRows);
76         return E_HAS_DB_ERROR;
77     }
78     return static_cast<int32_t>(updateRows);
79 }
80 
DeleteAllSensitiveOperation(AsyncTaskData * data)81 static void DeleteAllSensitiveOperation(AsyncTaskData *data)
82 {
83     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
84     if (rdbStore == nullptr) {
85         MEDIA_ERR_LOG("UriSensitive delete operation fail, rdbStore is null.");
86         return;
87     }
88 
89     int32_t ret = rdbStore->ExecuteSql(AppUriSensitiveColumn::CREATE_APP_URI_SENSITIVE_TABLE);
90     if (ret < 0) {
91         MEDIA_ERR_LOG("UriSensitive table delete all temporary Sensitive failed");
92         return;
93     }
94 
95     ret = rdbStore->ExecuteSql(AppUriSensitiveColumn::CREATE_URI_URITYPE_APPID_INDEX);
96     if (ret < 0) {
97         MEDIA_ERR_LOG("UriSensitive table delete all temporary Sensitive failed");
98         return;
99     }
100 
101     ret = rdbStore->ExecuteSql(AppUriSensitiveColumn::DELETE_APP_URI_SENSITIVE_TABLE);
102     if (ret < 0) {
103         MEDIA_ERR_LOG("UriSensitive table delete all temporary Sensitive failed");
104         return;
105     }
106     MEDIA_INFO_LOG("UriSensitive table delete all %{public}d rows temporary Sensitive success", ret);
107 }
108 
DeleteAllSensitiveAsync()109 void UriSensitiveOperations::DeleteAllSensitiveAsync()
110 {
111     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
112     if (asyncWorker == nullptr) {
113         MEDIA_ERR_LOG("Can not get asyncWorker");
114         return;
115     }
116     shared_ptr<MediaLibraryAsyncTask> notifyAsyncTask =
117         make_shared<MediaLibraryAsyncTask>(DeleteAllSensitiveOperation, nullptr);
118     asyncWorker->AddTask(notifyAsyncTask, true);
119 }
120 
DeleteOperation(MediaLibraryCommand & cmd)121 int32_t UriSensitiveOperations::DeleteOperation(MediaLibraryCommand &cmd)
122 {
123     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
124     if (rdbStore == nullptr) {
125         MEDIA_ERR_LOG("UriSensitive update operation, rdbStore is null.");
126         return E_HAS_DB_ERROR;
127     }
128     cmd.SetTableName(AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
129     int32_t deleteRows = -1;
130     int32_t errCode = rdbStore->Delete(cmd, deleteRows);
131     if (errCode != NativeRdb::E_OK || deleteRows < 0) {
132         MEDIA_ERR_LOG("UriSensitive delete db failed, errCode = %{public}d", errCode);
133         return E_HAS_DB_ERROR;
134     }
135     return static_cast<int32_t>(deleteRows);
136 }
137 
InsertOperation(MediaLibraryCommand & cmd)138 int32_t UriSensitiveOperations::InsertOperation(MediaLibraryCommand &cmd)
139 {
140     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
141     if (rdbStore == nullptr) {
142         MEDIA_ERR_LOG("UriSensitive insert operation, rdbStore is null.");
143         return E_HAS_DB_ERROR;
144     }
145     cmd.SetTableName(AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
146     int64_t rowId = -1;
147     int32_t errCode = rdbStore->Insert(cmd, rowId);
148     if (errCode != NativeRdb::E_OK || rowId < 0) {
149         MEDIA_ERR_LOG("UriSensitive insert db failed, errCode = %{public}d", errCode);
150         return E_HAS_DB_ERROR;
151     }
152     return static_cast<int32_t>(rowId);
153 }
154 
BatchInsertOperation(MediaLibraryCommand & cmd,const std::vector<ValuesBucket> & values,std::shared_ptr<TransactionOperations> trans)155 int32_t UriSensitiveOperations::BatchInsertOperation(MediaLibraryCommand &cmd,
156     const std::vector<ValuesBucket> &values, std::shared_ptr<TransactionOperations> trans)
157 {
158     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
159     if (rdbStore == nullptr) {
160         MEDIA_ERR_LOG("UriSensitive insert operation, rdbStore is null.");
161         return E_HAS_DB_ERROR;
162     }
163     cmd.SetTableName(AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
164     int64_t outInsertNum = -1;
165     int32_t errCode;
166     if (trans == nullptr) {
167         errCode = rdbStore->BatchInsert(cmd, outInsertNum, values);
168     } else {
169         errCode = trans->BatchInsert(cmd, outInsertNum, values);
170     }
171     if (errCode != NativeRdb::E_OK || outInsertNum < 0) {
172         MEDIA_ERR_LOG("UriSensitive Insert into db failed, errCode = %{public}d", errCode);
173         return E_HAS_DB_ERROR;
174     }
175     return static_cast<int32_t>(outInsertNum);
176 }
177 
QueryUriSensitive(MediaLibraryCommand & cmd,const std::vector<DataShareValuesBucket> & values,std::shared_ptr<OHOS::NativeRdb::ResultSet> & resultSet)178 static void QueryUriSensitive(MediaLibraryCommand &cmd, const std::vector<DataShareValuesBucket> &values,
179     std::shared_ptr<OHOS::NativeRdb::ResultSet> &resultSet)
180 {
181     vector<string> columns;
182     vector<string> predicateInColumns;
183     DataSharePredicates predicates;
184     bool isValid;
185     string appid = values.at(0).Get(AppUriSensitiveColumn::APP_ID, isValid);
186     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
187     if (rdbStore == nullptr) {
188         MEDIA_ERR_LOG("UriSensitive query operation, rdbStore is null.");
189         return;
190     }
191     cmd.SetTableName(AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
192     for (const auto &val : values) {
193         predicateInColumns.push_back(static_cast<string>(val.Get(AppUriSensitiveColumn::FILE_ID, isValid)));
194     }
195     predicates.In(AppUriSensitiveColumn::FILE_ID, predicateInColumns);
196     predicates.And()->EqualTo(AppUriSensitiveColumn::APP_ID, appid);
197     NativeRdb::RdbPredicates rdbPredicate = RdbUtils::ToPredicates(predicates, cmd.GetTableName());
198     resultSet = MediaLibraryRdbStore::QueryWithFilter(rdbPredicate, columns);
199     return;
200 }
201 
CanConvertToInt32(const std::string & str)202 static bool CanConvertToInt32(const std::string &str)
203 {
204     std::istringstream iss(str);
205     int32_t num = 0;
206     iss >> num;
207     return iss.eof() && !iss.fail();
208 }
209 
GetFileId(const DataShareValuesBucket & values,bool & isValid)210 static int32_t GetFileId(const DataShareValuesBucket &values, bool &isValid)
211 {
212     int32_t ret = E_ERR;
213     string fileIdStr = static_cast<string>(values.Get(AppUriSensitiveColumn::FILE_ID, isValid));
214     if (CanConvertToInt32(fileIdStr)) {
215         ret = static_cast<int32_t>(std::stoi(fileIdStr));
216     }
217     return ret;
218 }
219 
GetSingleDbOperation(const vector<DataShareValuesBucket> & values,vector<int32_t> & dbOperation,vector<int32_t> & querySingleResultSet,int index)220 static void GetSingleDbOperation(const vector<DataShareValuesBucket> &values, vector<int32_t> &dbOperation,
221     vector<int32_t> &querySingleResultSet, int index)
222 {
223     bool isValid;
224     int32_t fileId = GetFileId(values.at(index), isValid);
225     if (fileId == E_ERR) {
226         MEDIA_ERR_LOG("Failed GetFileId.");
227         return;
228     }
229     int32_t uriType = values.at(index).Get(AppUriSensitiveColumn::URI_TYPE, isValid);
230     int32_t sensitiveType = values.at(index).Get(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, isValid);
231     if ((fileId == querySingleResultSet.at(FILE_ID_INDEX)) && (uriType == querySingleResultSet.at(URI_TYPE_INDEX))) {
232         if (sensitiveType == querySingleResultSet.at(SENSITIVE_TYPE_INDEX)) {
233             dbOperation[index] = NO_DB_OPERATION;
234         } else {
235             dbOperation[index] = UPDATE_DB_OPERATION;
236         }
237     }
238 }
239 
GetAllUriDbOperation(const vector<DataShareValuesBucket> & values,vector<int32_t> & dbOperation,std::shared_ptr<OHOS::NativeRdb::ResultSet> & queryResult)240 static void GetAllUriDbOperation(const vector<DataShareValuesBucket> &values, vector<int32_t> &dbOperation,
241     std::shared_ptr<OHOS::NativeRdb::ResultSet> &queryResult)
242 {
243     for (const auto &val : values) {
244         dbOperation.push_back(INSERT_DB_OPERATION);
245     }
246     if ((queryResult == nullptr) || (queryResult->GoToFirstRow() != NativeRdb::E_OK)) {
247         MEDIA_INFO_LOG("UriSensitive query result is null.");
248         return;
249     }
250     do {
251         vector<int32_t> querySingleResultSet;
252         querySingleResultSet.push_back(GetInt32Val(AppUriSensitiveColumn::FILE_ID, queryResult));
253         querySingleResultSet.push_back(GetInt32Val(AppUriSensitiveColumn::URI_TYPE, queryResult));
254         querySingleResultSet.push_back(GetInt32Val(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, queryResult));
255         for (size_t i = 0; i < values.size(); i++) {
256             GetSingleDbOperation(values, dbOperation, querySingleResultSet, i);
257         }
258     } while (!queryResult->GoToNextRow());
259 }
260 
BatchUpdate(MediaLibraryCommand & cmd,std::vector<string> inColumn,int32_t tableType,const std::vector<DataShareValuesBucket> & values,std::shared_ptr<TransactionOperations> trans)261 static void BatchUpdate(MediaLibraryCommand &cmd, std::vector<string> inColumn, int32_t tableType,
262     const std::vector<DataShareValuesBucket> &values, std::shared_ptr<TransactionOperations> trans)
263 {
264     cmd.SetTableName(AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
265     bool isValid;
266     string appid = values.at(0).Get(AppUriSensitiveColumn::APP_ID, isValid);
267     int32_t sensitiveType = values.at(0).Get(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, isValid);
268     DataShareValuesBucket valuesBucket;
269     DataSharePredicates predicates;
270     predicates.In(AppUriSensitiveColumn::FILE_ID, inColumn);
271     predicates.EqualTo(AppUriSensitiveColumn::APP_ID, appid);
272     predicates.And()->EqualTo(AppUriSensitiveColumn::URI_TYPE, to_string(tableType));
273     valuesBucket.Put(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, sensitiveType);
274     ValuesBucket value = RdbUtils::ToValuesBucket(valuesBucket);
275     if (value.IsEmpty()) {
276         MEDIA_ERR_LOG("MediaLibraryDataManager Insert: Input parameter is invalid");
277         return;
278     }
279     cmd.SetValueBucket(value);
280     NativeRdb::RdbPredicates rdbPredicate = RdbUtils::ToPredicates(predicates, cmd.GetTableName());
281     UriSensitiveOperations::UpdateOperation(cmd, rdbPredicate, trans);
282 }
283 
AppstateOberserverBuild(int32_t sensitiveType)284 static void AppstateOberserverBuild(int32_t sensitiveType)
285 {
286     MedialibraryAppStateObserverManager::GetInstance().SubscribeAppState();
287 }
288 
ValueBucketCheck(const std::vector<DataShareValuesBucket> & values)289 static int32_t ValueBucketCheck(const std::vector<DataShareValuesBucket> &values)
290 {
291     bool isValidArr[] = {false, false, false, false};
292     if (values.empty()) {
293         return E_ERR;
294     }
295     for (const auto &val : values) {
296         val.Get(AppUriSensitiveColumn::FILE_ID, isValidArr[FILE_ID_INDEX]);
297         val.Get(AppUriSensitiveColumn::URI_TYPE, isValidArr[URI_TYPE_INDEX]);
298         val.Get(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, isValidArr[SENSITIVE_TYPE_INDEX]);
299         val.Get(AppUriSensitiveColumn::APP_ID, isValidArr[APP_ID_INDEX]);
300         for (size_t i = 0; i < sizeof(isValidArr); i++) {
301             if ((isValidArr[i]) == false) {
302                 return E_ERR;
303             }
304         }
305     }
306     return E_OK;
307 }
308 
InsertValueBucketPrepare(const std::vector<DataShareValuesBucket> & values,int32_t fileId,int32_t uriType,std::vector<ValuesBucket> & batchInsertBucket)309 static void InsertValueBucketPrepare(const std::vector<DataShareValuesBucket> &values, int32_t fileId,
310     int32_t uriType, std::vector<ValuesBucket> &batchInsertBucket)
311 {
312     bool isValid;
313     ValuesBucket insertValues;
314     string appid = values.at(0).Get(AppUriSensitiveColumn::APP_ID, isValid);
315     int32_t sensitiveType = values.at(0).Get(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, isValid);
316     insertValues.Put(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, sensitiveType);
317     insertValues.Put(AppUriSensitiveColumn::FILE_ID, fileId);
318     insertValues.Put(AppUriSensitiveColumn::APP_ID, appid);
319     insertValues.Put(AppUriSensitiveColumn::URI_TYPE, uriType);
320     insertValues.Put(AppUriSensitiveColumn::DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
321     batchInsertBucket.push_back(insertValues);
322 }
323 
GrantUriSensitive(MediaLibraryCommand & cmd,const std::vector<DataShareValuesBucket> & values)324 int32_t UriSensitiveOperations::GrantUriSensitive(MediaLibraryCommand &cmd,
325     const std::vector<DataShareValuesBucket> &values)
326 {
327     std::vector<string> photosValues;
328     std::vector<string> audiosValues;
329     std::vector<int32_t> dbOperation;
330     std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet;
331     std::vector<ValuesBucket>  batchInsertBucket;
332     bool photoNeedToUpdate = false;
333     bool audioNeedToUpdate = false;
334     bool needToInsert = false;
335     bool isValid = false;
336     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
337     std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
338     int32_t err = E_OK;
339     std::function<int(void)> func = [&]()->int {
340         if (ValueBucketCheck(values) != E_OK) {
341             return E_ERR;
342         }
343         string appid = values.at(0).Get(AppUriSensitiveColumn::APP_ID, isValid);
344         int32_t sensitiveType = values.at(0).Get(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, isValid);
345         AppstateOberserverBuild(sensitiveType);
346         QueryUriSensitive(cmd, values, resultSet);
347         GetAllUriDbOperation(values, dbOperation, resultSet);
348         for (size_t i = 0; i < values.size(); i++) {
349             int32_t fileId = GetFileId(values.at(i), isValid);
350             int32_t uriType = values.at(i).Get(AppUriSensitiveColumn::URI_TYPE, isValid);
351             if ((dbOperation.at(i) == UPDATE_DB_OPERATION) && (uriType == PHOTOSTYPE)) {
352                 photoNeedToUpdate = true;
353                 photosValues.push_back(static_cast<string>(values.at(i).Get(AppUriSensitiveColumn::FILE_ID, isValid)));
354             } else if ((dbOperation.at(i) == UPDATE_DB_OPERATION) && (uriType == AUDIOSTYPE)) {
355                 audioNeedToUpdate = true;
356                 audiosValues.push_back(static_cast<string>(values.at(i).Get(AppUriSensitiveColumn::FILE_ID, isValid)));
357             } else if (dbOperation.at(i) == INSERT_DB_OPERATION) {
358                 needToInsert = true;
359                 InsertValueBucketPrepare(values, fileId, uriType, batchInsertBucket);
360             }
361         }
362         if (photoNeedToUpdate) {
363             BatchUpdate(cmd, photosValues, PHOTOSTYPE, values, trans);
364         }
365         if (audioNeedToUpdate) {
366             BatchUpdate(cmd, audiosValues, AUDIOSTYPE, values, trans);
367         }
368         if (needToInsert) {
369             UriSensitiveOperations::BatchInsertOperation(cmd, batchInsertBucket, trans);
370         }
371         return err;
372     };
373     err = trans->RetryTrans(func);
374     if (err != E_OK) {
375         MEDIA_ERR_LOG("GrantUriSensitive: tans finish fail!, ret:%{public}d", err);
376         return err;
377     }
378     return E_OK;
379 }
380 
QuerySensitiveType(const std::string & appId,const std::string & fileId)381 int32_t UriSensitiveOperations::QuerySensitiveType(const std::string &appId, const std::string &fileId)
382 {
383     NativeRdb::RdbPredicates rdbPredicate(AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
384     rdbPredicate.And()->EqualTo(AppUriSensitiveColumn::APP_ID, appId);
385     rdbPredicate.And()->EqualTo(AppUriSensitiveColumn::FILE_ID, fileId);
386 
387     vector<string> columns;
388     columns.push_back(AppUriSensitiveColumn::ID);
389     columns.push_back(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE);
390 
391     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(rdbPredicate, columns);
392     if (resultSet == nullptr) {
393         return 0;
394     }
395 
396     int32_t numRows = 0;
397     resultSet->GetRowCount(numRows);
398     if (numRows == 0) {
399         return 0;
400     }
401     resultSet->GoToFirstRow();
402     return MediaLibraryRdbStore::GetInt(resultSet, AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE);
403 }
QueryAppId(const std::string & fileId)404 std::string UriSensitiveOperations::QueryAppId(const std::string &fileId)
405 {
406     NativeRdb::RdbPredicates rdbPredicate(PhotoColumn::PHOTOS_TABLE);
407     rdbPredicate.And()->EqualTo(MediaColumn::MEDIA_ID, fileId);
408 
409     vector<string> columns;
410     columns.push_back(MediaColumn::MEDIA_ID);
411     columns.push_back(MediaColumn::MEDIA_OWNER_APPID);
412 
413     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(rdbPredicate, columns);
414     if (resultSet == nullptr) {
415         return 0;
416     }
417 
418     int32_t numRows = 0;
419     resultSet->GetRowCount(numRows);
420     if (numRows == 0) {
421         return 0;
422     }
423     resultSet->GoToFirstRow();
424     return MediaLibraryRdbStore::GetString(resultSet, MediaColumn::MEDIA_OWNER_APPID);
425 }
426 }
427 }