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 Sensitives and
13  * limitations under the License.
14  */
15 
16 #include <vector>
17 #include <map>
18 #include "medialibrary_app_uri_sensitive_operations.h"
19 #include "medialibrary_unistore_manager.h"
20 #include "medialibrary_rdbstore.h"
21 #include "medialibrary_rdb_utils.h"
22 #include "media_column.h"
23 #include "datashare_predicates.h"
24 #include "rdb_utils.h"
25 #include "media_file_uri.h"
26 #include "medialibrary_asset_operations.h"
27 #include "medialibrary_rdb_transaction.h"
28 #include "media_file_utils.h"
29 #include "medialibrary_appstate_observer.h"
30 #include "datashare_predicates_objects.h"
31 
32 using namespace OHOS::DataShare;
33 using namespace std;
34 using namespace OHOS::NativeRdb;
35 using namespace OHOS::RdbDataShareAdapter;
36 
37 namespace OHOS {
38 namespace Media {
39 
40 const int MediaLibraryAppUriSensitiveOperations::ERROR = -1;
41 const int MediaLibraryAppUriSensitiveOperations::SUCCEED = 0;
42 const int MediaLibraryAppUriSensitiveOperations::ALREADY_EXIST = 1;
43 const int MediaLibraryAppUriSensitiveOperations::NO_DATA = 0;
44 
HandleInsertOperation(MediaLibraryCommand & cmd)45 int32_t MediaLibraryAppUriSensitiveOperations::HandleInsertOperation(MediaLibraryCommand &cmd)
46 {
47     MEDIA_INFO_LOG("insert appUriSensitive begin");
48     // sensitiveType from param
49     int sensitiveTypeParam = -1;
50     if (!GetIntFromValuesBucket(cmd.GetValueBucket(), AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE,
51         sensitiveTypeParam)) {
52         return ERROR;
53     }
54     if (!IsValidSensitiveType(sensitiveTypeParam)) {
55         return ERROR;
56     }
57 
58     // query sensitive data before insert
59     int queryFlag = ERROR;
60     shared_ptr<ResultSet> resultSet = QueryNewData(cmd.GetValueBucket(), queryFlag);
61     // Update the sensitiveType
62     if (queryFlag > 0) {
63         return UpdateSensitiveType(resultSet, sensitiveTypeParam);
64     }
65     if (queryFlag < 0) {
66         return ERROR;
67     }
68 
69     // delete the temporary Sensitive when the app dies
70     MedialibraryAppStateObserverManager::GetInstance().SubscribeAppState();
71 
72     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
73     if (rdbStore == nullptr) {
74         MEDIA_ERR_LOG("get rdbStore error");
75         return ERROR;
76     }
77     // insert data
78     int64_t outRowId = -1;
79     cmd.GetValueBucket().PutLong(AppUriSensitiveColumn::DATE_MODIFIED,
80         MediaFileUtils::UTCTimeMilliSeconds());
81 
82     int permissionTypeParam = -1;
83     if (!GetIntFromValuesBucket(cmd.GetValueBucket(), AppUriPermissionColumn::PERMISSION_TYPE,
84         permissionTypeParam)) {
85         return ERROR;
86     }
87     cmd.GetValueBucket().Delete(AppUriPermissionColumn::PERMISSION_TYPE);
88     cmd.SetTableName(AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
89 
90     int32_t errCode = rdbStore->Insert(cmd, outRowId);
91     if (errCode != NativeRdb::E_OK) {
92         MEDIA_ERR_LOG("insert into db error, errCode=%{public}d", errCode);
93         return ERROR;
94     }
95     cmd.GetValueBucket().PutInt(AppUriPermissionColumn::PERMISSION_TYPE,
96         permissionTypeParam);
97     MEDIA_INFO_LOG("insert appUriSensitive ok");
98     return SUCCEED;
99 }
100 
BatchInsert(MediaLibraryCommand & cmd,const std::vector<DataShare::DataShareValuesBucket> & values)101 int32_t MediaLibraryAppUriSensitiveOperations::BatchInsert(
102     MediaLibraryCommand &cmd, const std::vector<DataShare::DataShareValuesBucket> &values)
103 {
104     MEDIA_INFO_LOG("batch insert begin");
105     std::vector<ValuesBucket> insertVector;
106     for (auto it = values.begin(); it != values.end(); it++) {
107         ValuesBucket value = RdbUtils::ToValuesBucket(*it);
108         int queryFlag = -1;
109         std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet = QueryNewData(value, queryFlag);
110         if (queryFlag < 0) {
111             return ERROR;
112         }
113         // sensitiveType from param
114         int sensitiveTypeParam = -1;
115         if (!GetIntFromValuesBucket(value, AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE,
116             sensitiveTypeParam)) {
117             return ERROR;
118         }
119 
120         value.Delete(AppUriPermissionColumn::PERMISSION_TYPE);
121 
122         if (queryFlag == 0) {
123             // delete the temporary sensitive when the app dies
124             MedialibraryAppStateObserverManager::GetInstance().SubscribeAppState();
125             value.PutLong(AppUriSensitiveColumn::DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
126             insertVector.push_back(value);
127         } else if (UpdateSensitiveType(resultSet, sensitiveTypeParam) == ERROR) {
128             return ERROR;
129         }
130     }
131     if (!insertVector.empty()) {
132         int64_t outRowId = -1;
133         int32_t ret = MediaLibraryRdbStore::BatchInsert(outRowId, AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE,
134             insertVector);
135         if (ret != NativeRdb::E_OK) {
136             MEDIA_ERR_LOG("batch insert err=%{public}d", ret);
137             return ERROR;
138         }
139     }
140     MEDIA_INFO_LOG("batch insert ok");
141     return SUCCEED;
142 }
143 
DeleteOperation(NativeRdb::RdbPredicates & predicates)144 int32_t MediaLibraryAppUriSensitiveOperations::DeleteOperation(NativeRdb::RdbPredicates &predicates)
145 {
146     MEDIA_INFO_LOG("delete begin");
147     int deleteRow = MediaLibraryRdbStore::Delete(predicates);
148     MEDIA_INFO_LOG("deleted row=%{public}d", deleteRow);
149     return deleteRow < 0 ? ERROR : SUCCEED;
150 }
151 
QueryOperation(DataShare::DataSharePredicates & predicates,std::vector<std::string> & fetchColumns)152 std::shared_ptr<OHOS::NativeRdb::ResultSet> MediaLibraryAppUriSensitiveOperations::QueryOperation(
153     DataShare::DataSharePredicates &predicates, std::vector<std::string> &fetchColumns)
154 {
155     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates,
156         AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
157     std::shared_ptr<OHOS::NativeRdb::ResultSet> resultSet =
158         MediaLibraryRdbStore::QueryWithFilter(rdbPredicates, fetchColumns);
159     if (resultSet == nullptr) {
160         return nullptr;
161     }
162     int32_t numRows = 0;
163     resultSet->GetRowCount(numRows);
164     if (numRows == 0) {
165         return nullptr;
166     }
167     resultSet->GoToFirstRow();
168     return resultSet;
169 }
170 
QueryNewData(OHOS::NativeRdb::ValuesBucket & valueBucket,int & resultFlag)171 std::shared_ptr<OHOS::NativeRdb::ResultSet> MediaLibraryAppUriSensitiveOperations::QueryNewData(
172     OHOS::NativeRdb::ValuesBucket &valueBucket, int &resultFlag)
173 {
174     // parse appid
175     ValueObject appidVO;
176     bool appIdRet = valueBucket.GetObject(AppUriSensitiveColumn::APP_ID, appidVO);
177     if (!appIdRet) {
178         MEDIA_ERR_LOG("param without appId");
179         resultFlag = ERROR;
180         return nullptr;
181     }
182     string appId = appidVO;
183 
184     // parse fileId
185     int fileId = -1;
186     if (!GetIntFromValuesBucket(valueBucket, AppUriSensitiveColumn::FILE_ID, fileId)) {
187         resultFlag = ERROR;
188         return nullptr;
189     }
190 
191     // parse uriType
192     int uriType = -1;
193     if (!GetIntFromValuesBucket(valueBucket, AppUriSensitiveColumn::URI_TYPE, uriType)) {
194         resultFlag = ERROR;
195         return nullptr;
196     }
197 
198     OHOS::DataShare::DataSharePredicates sensitivePredicates;
199     sensitivePredicates.And()->EqualTo(AppUriSensitiveColumn::FILE_ID, fileId);
200     sensitivePredicates.And()->EqualTo(AppUriSensitiveColumn::URI_TYPE, uriType);
201     sensitivePredicates.And()->EqualTo(AppUriSensitiveColumn::APP_ID, appId);
202 
203     vector<string> fetchColumns;
204     fetchColumns.push_back(AppUriSensitiveColumn::ID);
205     fetchColumns.push_back(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE);
206 
207     shared_ptr<ResultSet> resultSet = QueryOperation(sensitivePredicates, fetchColumns);
208     resultFlag = (resultSet == nullptr ? NO_DATA : ALREADY_EXIST);
209     return resultSet;
210 }
211 
GetIntFromValuesBucket(OHOS::NativeRdb::ValuesBucket & valueBucket,const std::string & column,int & result)212 bool MediaLibraryAppUriSensitiveOperations::GetIntFromValuesBucket(
213     OHOS::NativeRdb::ValuesBucket &valueBucket, const std::string &column, int &result)
214 {
215     ValueObject valueObject;
216     bool ret = valueBucket.GetObject(column, valueObject);
217     if (!ret) {
218         MEDIA_ERR_LOG("valueBucket param without %{public}s", column.c_str());
219         return false;
220     }
221     result = valueObject;
222     return true;
223 }
224 
UpdateSensitiveType(shared_ptr<ResultSet> & resultSetDB,int & sensitiveTypeParam)225 int MediaLibraryAppUriSensitiveOperations::UpdateSensitiveType(shared_ptr<ResultSet> &resultSetDB,
226     int &sensitiveTypeParam)
227 {
228     // delete the temporary Sensitive when the app dies
229     MedialibraryAppStateObserverManager::GetInstance().SubscribeAppState();
230 
231     // update sensitive type
232     ValuesBucket updateVB;
233     updateVB.PutInt(AppUriSensitiveColumn::HIDE_SENSITIVE_TYPE, sensitiveTypeParam);
234     updateVB.PutLong(AppUriSensitiveColumn::DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
235     int32_t idDB = MediaLibraryRdbStore::GetInt(resultSetDB, AppUriSensitiveColumn::ID);
236 
237     OHOS::DataShare::DataSharePredicates updatePredicates;
238     updatePredicates.EqualTo(AppUriSensitiveColumn::ID, idDB);
239     RdbPredicates updateRdbPredicates =
240         RdbUtils::ToPredicates(updatePredicates, AppUriSensitiveColumn::APP_URI_SENSITIVE_TABLE);
241     int32_t updateRows = MediaLibraryRdbStore::UpdateWithDateTime(updateVB, updateRdbPredicates);
242     if (updateRows < 1) {
243         MEDIA_ERR_LOG("upgrade SensitiveType error,idDB=%{public}d", idDB);
244         return ERROR;
245     }
246     MEDIA_INFO_LOG("update ok,Rows=%{public}d", updateRows);
247     return SUCCEED;
248 }
249 
IsValidSensitiveType(int & sensitiveType)250 bool MediaLibraryAppUriSensitiveOperations::IsValidSensitiveType(int &sensitiveType)
251 {
252     bool isValid = AppUriSensitiveColumn::SENSITIVE_TYPES_ALL.find(sensitiveType)
253         != AppUriSensitiveColumn::SENSITIVE_TYPES_ALL.end();
254     if (!isValid) {
255         MEDIA_ERR_LOG("invalid SensitiveType=%{public}d", sensitiveType);
256     }
257     return isValid;
258 }
259 } // namespace Media
260 } // namespace OHOS