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 <filesystem>
17 #include <system_error>
18 
19 #include "hilog/log.h"
20 #include "netmgr_ext_log_wrapper.h"
21 #include "netfirewall_database.h"
22 
23 using namespace OHOS::NativeRdb;
24 
25 namespace OHOS {
26 namespace NetManagerStandard {
27 std::shared_ptr<NetFirewallDataBase> NetFirewallDataBase::instance_ = nullptr;
28 
NetFirewallDataBase()29 NetFirewallDataBase::NetFirewallDataBase()
30 {
31     if (!std::filesystem::exists(FIREWALL_DB_PATH)) {
32         std::error_code ec;
33         if (std::filesystem::create_directories(FIREWALL_DB_PATH, ec)) {
34             NETMGR_EXT_LOG_D("create_directories success :%{public}s", FIREWALL_DB_PATH.c_str());
35         } else {
36             NETMGR_EXT_LOG_E("create_directories error :%{public}s : %s", FIREWALL_DB_PATH.c_str(),
37                 ec.message().c_str());
38         }
39     }
40     std::string firewallDatabaseName = FIREWALL_DB_PATH + FIREWALL_DB_NAME;
41     int32_t errCode = OHOS::NativeRdb::E_OK;
42     OHOS::NativeRdb::RdbStoreConfig config(firewallDatabaseName);
43     config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
44     NetFirewallDataBaseCallBack sqliteOpenHelperCallback;
45     store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION, sqliteOpenHelperCallback, errCode);
46     if (errCode == OHOS::NativeRdb::E_SQLITE_CORRUPT) {
47         if (!RestoreDatabaseWhenInit()) {
48             NETMGR_EXT_LOG_E("Create and restore db error");
49             return;
50         }
51         NETMGR_EXT_LOG_I("Create db error, restore db success");
52         errCode = OHOS::NativeRdb::E_OK;
53     }
54     if (errCode != OHOS::NativeRdb::E_OK) {
55         NETMGR_EXT_LOG_E("GetRdbStore errCode :%{public}d", errCode);
56     } else {
57         NETMGR_EXT_LOG_D("GetRdbStore success :%{public}d", errCode);
58     }
59 }
60 
GetInstance()61 std::shared_ptr<NetFirewallDataBase> NetFirewallDataBase::GetInstance()
62 {
63     if (instance_ == nullptr) {
64         NETMGR_EXT_LOG_W("reset to new instance");
65         instance_.reset(new NetFirewallDataBase());
66         return instance_;
67     }
68     return instance_;
69 }
70 
BeginTransaction()71 int32_t NetFirewallDataBase::BeginTransaction()
72 {
73     if (store_ == nullptr) {
74         NETMGR_EXT_LOG_E("BeginTransaction store_ is nullptr");
75         return FIREWALL_RDB_NO_INIT;
76     }
77     int32_t ret = store_->BeginTransaction();
78     if (ret != OHOS::NativeRdb::E_OK) {
79         NETMGR_EXT_LOG_E("BeginTransaction fail :%{public}d", ret);
80         return FIREWALL_RDB_EXECUTE_FAILTURE;
81     }
82     return FIREWALL_OK;
83 }
84 
Commit()85 int32_t NetFirewallDataBase::Commit()
86 {
87     if (store_ == nullptr) {
88         NETMGR_EXT_LOG_E("Commit store_ is nullptr");
89         return FIREWALL_RDB_NO_INIT;
90     }
91     int32_t ret = store_->Commit();
92     if (ret != OHOS::NativeRdb::E_OK) {
93         NETMGR_EXT_LOG_E("Commit fail :%{public}d", ret);
94         return FIREWALL_RDB_EXECUTE_FAILTURE;
95     }
96     return FIREWALL_OK;
97 }
98 
RollBack()99 int32_t NetFirewallDataBase::RollBack()
100 {
101     if (store_ == nullptr) {
102         NETMGR_EXT_LOG_E("RollBack store_ is nullptr");
103         return FIREWALL_RDB_NO_INIT;
104     }
105     int32_t ret = store_->RollBack();
106     if (ret != OHOS::NativeRdb::E_OK) {
107         NETMGR_EXT_LOG_E("RollBack fail :%{public}d", ret);
108         return FIREWALL_RDB_EXECUTE_FAILTURE;
109     }
110     return FIREWALL_OK;
111 }
112 
Insert(const OHOS::NativeRdb::ValuesBucket &insertValues, const std::string tableName)113 int64_t NetFirewallDataBase::Insert(const OHOS::NativeRdb::ValuesBucket &insertValues, const std::string tableName)
114 {
115     if (store_ == nullptr) {
116         NETMGR_EXT_LOG_E("Insert store_ is  nullptr");
117         return FIREWALL_RDB_NO_INIT;
118     }
119     int64_t outRowId = 0;
120     int32_t ret = store_->Insert(outRowId, tableName, insertValues);
121     NETMGR_EXT_LOG_D("Insert id=%{public}" PRIu64 "", outRowId);
122     if (ret == OHOS::NativeRdb::E_SQLITE_CORRUPT) {
123         NETMGR_EXT_LOG_E("Insert error, restore db");
124         if (RestoreDatabase()) {
125             int32_t ret = store_->Insert(outRowId, tableName, insertValues);
126         }
127     }
128     if (ret != OHOS::NativeRdb::E_OK) {
129         NETMGR_EXT_LOG_E("Insert ret :%{public}d", ret);
130         return FIREWALL_RDB_EXECUTE_FAILTURE;
131     }
132     if (tableName == FIREWALL_TABLE_NAME) {
133         BackupDatebase();
134     }
135     return outRowId;
136 }
137 
138 
Update(const std::string &tableName, int32_t &changedRows, const OHOS::NativeRdb::ValuesBucket &values, const std::string &whereClause, const std::vector<std::string> &whereArgs)139 int32_t NetFirewallDataBase::Update(const std::string &tableName, int32_t &changedRows,
140     const OHOS::NativeRdb::ValuesBucket &values, const std::string &whereClause,
141     const std::vector<std::string> &whereArgs)
142 {
143     if (store_ == nullptr) {
144         NETMGR_EXT_LOG_E("Update(whereClause) store_ is nullptr");
145         return FIREWALL_RDB_NO_INIT;
146     }
147     int32_t ret = store_->Update(changedRows, tableName, values, whereClause, whereArgs);
148     if (ret == OHOS::NativeRdb::E_SQLITE_CORRUPT) {
149         NETMGR_EXT_LOG_E("Update error, restore db");
150         if (RestoreDatabase()) {
151             int32_t ret = store_->Update(changedRows, tableName, values, whereClause, whereArgs);
152         }
153     }
154     if (ret != OHOS::NativeRdb::E_OK) {
155         NETMGR_EXT_LOG_E("Update(whereClause) ret :%{public}d", ret);
156         return FIREWALL_RDB_EXECUTE_FAILTURE;
157     }
158     if (tableName == FIREWALL_TABLE_NAME) {
159         BackupDatebase();
160     }
161     return FIREWALL_OK;
162 }
163 
164 
Delete(const std::string &tableName, int32_t &changedRows, const std::string &whereClause, const std::vector<std::string> &whereArgs)165 int32_t NetFirewallDataBase::Delete(const std::string &tableName, int32_t &changedRows, const std::string &whereClause,
166     const std::vector<std::string> &whereArgs)
167 {
168     if (store_ == nullptr) {
169         NETMGR_EXT_LOG_E("Delete store_ is nullptr");
170         return FIREWALL_RDB_NO_INIT;
171     }
172     int32_t ret = store_->Delete(changedRows, tableName, whereClause, whereArgs);
173     if (ret == OHOS::NativeRdb::E_SQLITE_CORRUPT) {
174         NETMGR_EXT_LOG_E("Delete error, restore db");
175         if (RestoreDatabase()) {
176             int32_t ret = store_->Delete(changedRows, tableName, whereClause, whereArgs);
177         }
178     }
179     if (ret != OHOS::NativeRdb::E_OK) {
180         NETMGR_EXT_LOG_E("Delete(whereClause) ret :%{public}d", ret);
181         return FIREWALL_RDB_EXECUTE_FAILTURE;
182     }
183     if (tableName == FIREWALL_TABLE_NAME) {
184         BackupDatebase();
185     }
186     return FIREWALL_OK;
187 }
188 
189 
Query( const OHOS::NativeRdb::AbsRdbPredicates &predicates, const std::vector<std::string> &columns)190 std::shared_ptr<OHOS::NativeRdb::ResultSet> NetFirewallDataBase::Query(
191     const OHOS::NativeRdb::AbsRdbPredicates &predicates, const std::vector<std::string> &columns)
192 {
193     if (store_ == nullptr) {
194         NETMGR_EXT_LOG_E("Query(AbsRdbPredicates) store_ is nullptr");
195         return nullptr;
196     }
197     return store_->Query(predicates, columns);
198 }
199 
Count(int64_t &outValue, const OHOS::NativeRdb::AbsRdbPredicates &predicates)200 int32_t NetFirewallDataBase::Count(int64_t &outValue, const OHOS::NativeRdb::AbsRdbPredicates &predicates)
201 {
202     if (store_ == nullptr) {
203         NETMGR_EXT_LOG_E("Count(AbsRdbPredicates) store_ is nullptr");
204         return FIREWALL_RDB_NO_INIT;
205     }
206     return store_->Count(outValue, predicates);
207 }
208 
QuerySql(const std::string &sql, const std::vector<std::string> &selectionArgs)209 std::shared_ptr<OHOS::NativeRdb::ResultSet> NetFirewallDataBase::QuerySql(const std::string &sql,
210     const std::vector<std::string> &selectionArgs)
211 {
212     if (store_ == nullptr) {
213         NETMGR_EXT_LOG_E("QuerySql(AbsRdbPredicates) store_ is nullptr");
214         return nullptr;
215     }
216     return store_->QuerySql(sql, selectionArgs);
217 }
218 
BackupDatebase()219 void NetFirewallDataBase::BackupDatebase()
220 {
221     if (store_ == nullptr) {
222         NETMGR_EXT_LOG_E("store_ is null");
223         return;
224     }
225 
226     if (backing_.exchange(true)) {
227         NETMGR_EXT_LOG_I("Backup is processing");
228         return;
229     }
230     std::string fileName = FIREWALL_DB_PATH + FIREWALL_BACKUP_DB_NAME;
231     std::thread thread([fileName, rdbStore = store_] {
232         auto errCode = rdbStore->Backup(fileName);
233         NetFirewallDataBase::GetInstance()->backing_ = false;
234         if (errCode != E_OK) {
235             NETMGR_EXT_LOG_E("Backup Datebase error");
236             return;
237         }
238         NETMGR_EXT_LOG_D("Backup Datebase success");
239     });
240     thread.detach();
241 }
242 
RestoreDatabaseWhenInit()243 bool NetFirewallDataBase::RestoreDatabaseWhenInit()
244 {
245     std::string backupFile = FIREWALL_DB_PATH + FIREWALL_BACKUP_DB_NAME;
246     if (access(backupFile.c_str(), F_OK) != 0) {
247         NETMGR_EXT_LOG_I("Backup db is not exist");
248         return false;
249     }
250     std::string firewallFile = FIREWALL_DB_PATH + FIREWALL_DB_NAME;
251     if (rename(backupFile.c_str(), firewallFile.c_str()) != 0) {
252         return false;
253     }
254     int32_t errCode = OHOS::NativeRdb::E_OK;
255     OHOS::NativeRdb::RdbStoreConfig config(firewallFile);
256     config.SetSecurityLevel(NativeRdb::SecurityLevel::S1);
257     NetFirewallDataBaseCallBack sqliteOpenHelperCallback;
258     store_ = OHOS::NativeRdb::RdbHelper::GetRdbStore(config, DATABASE_OPEN_VERSION, sqliteOpenHelperCallback, errCode);
259     if (errCode != OHOS::NativeRdb::E_OK) {
260         NETMGR_EXT_LOG_E("Restore GetRdbStore errCode :%{public}d", errCode);
261         return false;
262     } else {
263         NETMGR_EXT_LOG_D("Restore GetRdbStore success");
264     }
265     return true;
266 }
267 
RestoreDatabase()268 bool NetFirewallDataBase::RestoreDatabase()
269 {
270     if (store_ == nullptr) {
271         NETMGR_EXT_LOG_E("store_ is null");
272         return false;
273     }
274     auto fileName = FIREWALL_DB_PATH + FIREWALL_BACKUP_DB_NAME;
275     if (access(fileName.c_str(), F_OK) != 0) {
276         NETMGR_EXT_LOG_I("Backup db is not exist");
277         return false;
278     }
279     int32_t errCode = store_->Restore(fileName);
280     if (errCode == E_OK) {
281         NETMGR_EXT_LOG_I("Restore db success");
282         return true;
283     }
284 
285     // Failed to restore the db. Try to rebuild the db from the backup db.
286     store_ = nullptr;
287     return RestoreDatabaseWhenInit();
288 }
289 
OnCreate(OHOS::NativeRdb::RdbStore &store)290 int32_t NetFirewallDataBaseCallBack::OnCreate(OHOS::NativeRdb::RdbStore &store)
291 {
292     std::map<std::string, std::string> netfirewallTableMap;
293     netfirewallTableMap.insert(std::pair<std::string, std::string>(FIREWALL_TABLE_NAME, CREATE_FIREWALL_TABLE));
294     netfirewallTableMap.insert(std::pair<std::string, std::string>(INTERCEPT_RECORD_TABLE, CREATE_RECORD_TABLE));
295     for (const auto &pair : netfirewallTableMap) {
296         std::string sql = pair.second;
297         int32_t ret = store.ExecuteSql(sql);
298         if (ret != OHOS::NativeRdb::E_OK) {
299             NETMGR_EXT_LOG_E("OnCreate %{public}s, failed: %{public}d", pair.first.c_str(), ret);
300             return FIREWALL_RDB_EXECUTE_FAILTURE;
301         }
302         NETMGR_EXT_LOG_D("DB OnCreate Done %{public}s ", pair.first.c_str());
303     }
304     return FIREWALL_OK;
305 }
306 
OnUpgrade(OHOS::NativeRdb::RdbStore &store, int32_t oldVersion, int32_t newVersion)307 int32_t NetFirewallDataBaseCallBack::OnUpgrade(OHOS::NativeRdb::RdbStore &store, int32_t oldVersion, int32_t newVersion)
308 {
309     NETMGR_EXT_LOG_D("DB OnUpgrade Enter");
310     (void)store;
311     (void)oldVersion;
312     (void)newVersion;
313     return FIREWALL_OK;
314 }
315 
OnDowngrade(OHOS::NativeRdb::RdbStore &store, int32_t oldVersion, int32_t newVersion)316 int32_t NetFirewallDataBaseCallBack::OnDowngrade(OHOS::NativeRdb::RdbStore &store, int32_t oldVersion,
317     int32_t newVersion)
318 {
319     NETMGR_EXT_LOG_D("DB OnDowngrade Enter");
320     (void)store;
321     (void)oldVersion;
322     (void)newVersion;
323     return FIREWALL_OK;
324 }
325 } // namespace NetManagerStandard
326 } // namespace OHOS