settings + version

This commit is contained in:
End 2020-08-18 17:14:48 +02:00
parent e2d1cdfede
commit 4e077a26e5
2 changed files with 102 additions and 32 deletions

View file

@ -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<std::string> 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;
}

View file

@ -3,6 +3,7 @@
#include <QObject>
#include <includes.h>
#include <httpflow.h>
#include <optional>
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<std::string> 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:
};