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