From 4e077a26e54758458b9e08f18fa1eb09e70c11cd Mon Sep 17 00:00:00 2001 From: End Date: Tue, 18 Aug 2020 17:14:48 +0200 Subject: [PATCH] settings + version --- session.cpp | 112 +++++++++++++++++++++++++++++++++++++++------------- session.h | 22 ++++++++--- 2 files changed, 102 insertions(+), 32 deletions(-) diff --git a/session.cpp b/session.cpp index f704fd7..a31bbd4 100644 --- a/session.cpp +++ b/session.cpp @@ -43,53 +43,53 @@ bool Session::prepare_and_exec(const char* query) { return result; } -void Session::prepare_tables() { +bool Session::table_exists(std::string name) { sqlite3_stmt* res; - prepare(check_tbl, &res); - auto s = "session"; - sqlite3_bind_text(res, 1, s, strlen(s), nullptr); + prepare(get_tbl, &res); + bind_text(res, 1, name); auto rc = sqlite3_step(res); sqlite3_finalize(res); - if(rc == SQLITE_ROW) { - prepare(check_session_info, &res); - auto v = "version"; - sqlite3_bind_text(res, 1, v, strlen(v), nullptr); - rc = sqlite3_step(res); + return rc == SQLITE_ROW; +} - if(rc == SQLITE_ROW) { - const char* version = (const char*)sqlite3_column_text(res, 1); - if(std::atoi(version) != LITTLESNITCH_VERSION) { - qDebug() << "version " << version << " is not supported!"; +void Session::prepare_tables() { + if(table_exists("setting")) { + prepare(get_setting, &stmt_get_setting); + auto v = getSetting("version"); + if(v) { + if(std::stoi(*v) != LITTLESNITCH_VERSION) { + qDebug() << "version " << v.value().c_str() << " is not supported!"; unload(); throw; } - - qDebug() << "loaded session with version " << version; - sqlite3_finalize(res); - return; + qDebug() << "loaded session with version " << v.value().c_str(); } else { - qDebug("broken database, was not able to check session info"); - qDebug() << sqlite3_errmsg(db); + qDebug() << "setting table but no version found, aborting"; unload(); throw; } + } else { + prepare_and_exec(create_request_tbl); + prepare_and_exec(create_request_header_tbl); + prepare_and_exec(create_response_tbl); + prepare_and_exec(create_response_header_tbl); + prepare_and_exec(create_flow_tbl); + prepare_and_exec(create_setting_tbl); + prepare(get_setting, &stmt_get_setting); } - prepare_and_exec(create_request_tbl); - prepare_and_exec(create_request_header_tbl); - prepare_and_exec(create_response_tbl); - prepare_and_exec(create_response_header_tbl); - prepare_and_exec(create_flow_tbl); - prepare_and_exec(create_session_tbl); + prepare(update_setting, &stmt_update_setting); prepare(insert_request, &stmt_insert_request); prepare(insert_request_header, &stmt_insert_request_header); prepare(insert_response, &stmt_insert_response); prepare(insert_response_header, &stmt_insert_response_header); prepare(insert_flow, &stmt_insert_flow); - prepare(insert_session, &stmt_insert_session); + prepare(insert_setting, &stmt_insert_setting); + + saveSetting("version", std::to_string(LITTLESNITCH_VERSION)); } void Session::load(std::filesystem::path path) @@ -110,6 +110,28 @@ bool Session::isLoaded() { return loaded; } +std::optional Session::getSetting(std::string key) { + sqlite3_reset(stmt_get_setting); + + int j = 1; + + bind_text(stmt_get_setting, j++, key); + + auto rc = sqlite3_step(stmt_get_setting); + if(rc == SQLITE_ROW) { + auto value = std::string((const char*)sqlite3_column_text(stmt_get_setting, 0)); + + return value; + } else if(rc == SQLITE_DONE) { + return std::nullopt; + } else { + qDebug() << "getting setting failed " << rc; + qDebug() << sqlite3_errmsg(db); + return std::nullopt; + } + return std::nullopt; +} + void Session::bind_text(sqlite3_stmt* stmt, int id, std::string text) { //qDebug() << id << " " << text.c_str() << " " << strlen(text.c_str()); sqlite3_bind_text(stmt, id, text.c_str(), -1, SQLITE_TRANSIENT); @@ -221,6 +243,8 @@ int Session::saveResponseHeader(std::string key, std::string value, int id) { } int Session::saveFlow(http::Flow flow) { + sqlite3_reset(stmt_insert_flow); + int request_id = saveRequest(flow); int response_id = saveResponse(flow); @@ -231,7 +255,6 @@ int Session::saveFlow(http::Flow flow) { sqlite3_bind_int(stmt_insert_flow, j++, response_id); auto rc = sqlite3_step(stmt_insert_flow); - sqlite3_reset(stmt_insert_flow); if(rc != SQLITE_DONE) { qDebug() << "inserting flow failed" << rc; qDebug() << sqlite3_errmsg(db); @@ -240,3 +263,38 @@ int Session::saveFlow(http::Flow flow) { return sqlite3_last_insert_rowid(db); } + +bool Session::saveSetting(std::string key, std::string value) { + auto old_value = getSetting(key); + if(!old_value) { + sqlite3_reset(stmt_insert_setting); + int j = 1; + + bind_text(stmt_insert_setting, j++, key); + bind_text(stmt_insert_setting, j++, value); + + auto rc = sqlite3_step(stmt_insert_setting); + if(rc != SQLITE_DONE) { + qDebug() << "inserting setting failed" << rc; + qDebug() << sqlite3_errmsg(db); + return false; + } + + return sqlite3_last_insert_rowid(db); + } else { + sqlite3_reset(stmt_update_setting); + int j = 1; + + bind_text(stmt_update_setting, j++, value); + bind_text(stmt_insert_setting, j++, key); + + auto rc = sqlite3_step(stmt_update_setting); + if(rc != SQLITE_DONE) { + qDebug() << "updating setting failed" << rc; + qDebug() << sqlite3_errmsg(db); + return false; + } + return true; + } + return false; +} diff --git a/session.h b/session.h index e5ca9fc..76cc1da 100644 --- a/session.h +++ b/session.h @@ -3,6 +3,7 @@ #include #include #include +#include class Session : public QObject { @@ -56,34 +57,43 @@ private: FOREIGN KEY(request_id) REFERENCES request(id) ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY(response_id) REFERENCES response(id) ON UPDATE CASCADE ON DELETE CASCADE ); )rstr"; - const char* create_session_tbl = R"rstr( CREATE TABLE session( + const char* create_setting_tbl = R"rstr( CREATE TABLE setting( key TEXT UNIQUE NOT NULL PRIMARY KEY, value TEXT ); )rstr"; - const char* check_tbl = R"rstr( SELECT name FROM sqlite_master WHERE type='table' AND name=?; )rstr"; - const char* check_session_info = R"rstr( SELECT value FROM session WHERE key=?; )rstr"; + + const char* get_tbl = R"rstr( SELECT name FROM sqlite_master WHERE type='table' AND name=?; )rstr"; + const char* get_setting = R"rstr( SELECT value FROM setting WHERE key=?; )rstr"; + const char* insert_request = R"rstr( INSERT INTO request (server_ip_address, tls, content, scheme, method, host, address, port, http_version, path, timestamp_start, timestamp_end, error) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?); )rstr"; const char* insert_request_header = R"rstr( INSERT INTO request_header (key, value, request_id) VALUES (?,?,?); )rstr"; const char* insert_response = R"rstr( INSERT INTO response (status_code, http_version, reason, content, timestamp_start, timestamp_end) VALUES (?,?,?,?,?,?); )rstr"; const char* insert_response_header = R"rstr( INSERT INTO response_header (key, value, response_id) VALUES (?,?,?); )rstr"; const char* insert_flow = R"rstr( INSERT INTO flow (uid, request_id, response_id) VALUES (?,?,?); )rstr"; - const char* insert_session = R"rstr( INSERT INTO session (key, value) VALUES (?,?); )rstr"; + const char* insert_setting = R"rstr( INSERT INTO setting (key, value) VALUES (?,?); )rstr"; + + const char* update_setting = R"rstr( UPDATE setting SET value=? WHERE key=?; )rstr"; sqlite3* db = nullptr; bool loaded = false; + sqlite3_stmt* stmt_get_setting = nullptr; + sqlite3_stmt* stmt_insert_request = nullptr; sqlite3_stmt* stmt_insert_request_header = nullptr; sqlite3_stmt* stmt_insert_response = nullptr; sqlite3_stmt* stmt_insert_response_header = nullptr; sqlite3_stmt* stmt_insert_flow = nullptr; - sqlite3_stmt* stmt_insert_session = nullptr; + sqlite3_stmt* stmt_insert_setting = nullptr; + + sqlite3_stmt* stmt_update_setting = nullptr; void open_db(std::filesystem::path path); void prepare_tables(); void prepare(const char* query, sqlite3_stmt** stmt); bool prepare_and_exec(const char* query); void bind_text(sqlite3_stmt* stmt, int id, std::string text); + bool table_exists(std::string name); public: explicit Session(QObject *parent = nullptr); ~Session(); @@ -91,12 +101,14 @@ public: void load(std::filesystem::path path); void unload(); bool isLoaded(); + std::optional getSetting(std::string key); public slots: int saveRequest(http::Flow flow); int saveRequestHeader(std::string key, std::string value, int id); int saveResponse(http::Flow flow); int saveResponseHeader(std::string key, std::string value, int id); int saveFlow(http::Flow flow); + bool saveSetting(std::string key, std::string value); signals: };