sqlite eingebaut

This commit is contained in:
End 2020-08-13 23:25:04 +02:00
parent d8b52dcb44
commit 075ada7d3e
4 changed files with 265 additions and 109 deletions

View file

@ -117,7 +117,15 @@ struct Request
}; };
struct Response {}; struct Response {
int status_code;
std::string http_version;
std::string reason;
std::string content;
double timestamp_start;
double timestamp_end;
std::vector<std::tuple<std::string,std::string>> headers;
};
struct Flow { struct Flow {
Request request; Request request;

View file

@ -8,3 +8,6 @@
#include <iostream> #include <iostream>
using json = nlohmann::json; using json = nlohmann::json;
//major minor patch
#define LITTLESNITCH_VERSION 010

View file

@ -9,29 +9,133 @@ Session::~Session() {
unload(); unload();
} }
void Session::open_db(std::filesystem::path path) {
void Session::load(std::filesystem::path path)
{
if(db) { if(db) {
unload(); unload();
} }
auto rc = sqlite3_open(path.c_str(), &db); auto rc = sqlite3_open(path.c_str(), &db);
if(rc) { if(rc != SQLITE_OK) {
qDebug("cannot open database"); qDebug("cannot open database");
qDebug() << sqlite3_errmsg(db); qDebug() << sqlite3_errmsg(db);
unload(); unload();
throw; throw;
} }
// check if tables exist }
// create tables or add history
void Session::prepare(const char* query, sqlite3_stmt** stmt) {
auto rc = sqlite3_prepare_v2(db, query, strlen(query), stmt, 0);
if(rc != SQLITE_OK) {
qDebug() << "cannot prepare statement";
qDebug() << query;
qDebug() << sqlite3_errmsg(db);
unload();
throw;
}
}
bool Session::prepare_and_exec(const char* query) {
sqlite3_stmt* res;
prepare(query, &res);
bool result = sqlite3_step(res)==SQLITE_OK;
sqlite3_finalize(res);
return result;
}
void Session::prepare_tables() {
sqlite3_stmt* res;
prepare(check_tbl, &res);
auto s = "session";
sqlite3_bind_text(res, 1, s, strlen(s), nullptr);
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);
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!";
unload();
throw;
}
qDebug() << "loaded session with version " << version;
sqlite3_finalize(res);
return;
} else {
qDebug("broken database, was not able to check session info");
qDebug() << sqlite3_errmsg(db);
unload();
throw;
}
}
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(last_inserted_id, &stmt_last_inserted_id);
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);
}
void Session::load(std::filesystem::path path)
{
open_db(path);
prepare_tables();
loaded = true;
} }
void Session::unload() { void Session::unload() {
if(db) { if(db) {
sqlite3_close(db); sqlite3_close(db);
} }
loaded = false;
}
bool Session::isLoaded() {
return loaded;
}
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);
} }
void Session::saveRequest(http::Flow flow) { void Session::saveRequest(http::Flow flow) {
// todo bind_text(stmt_insert_request, 1, flow.request.server_conn_id);
bind_text(stmt_insert_request, 2, flow.request.server_ip_address);
sqlite3_bind_int(stmt_insert_request, 3, flow.request.tls);
bind_text(stmt_insert_request, 4, flow.request.content);
bind_text(stmt_insert_request, 5, flow.request.scheme);
bind_text(stmt_insert_request, 6, flow.request.method);
bind_text(stmt_insert_request, 7, flow.request.host);
bind_text(stmt_insert_request, 8, flow.request.address);
sqlite3_bind_int(stmt_insert_request, 9, flow.request.port);
bind_text(stmt_insert_request, 10, flow.request.http_version);
bind_text(stmt_insert_request, 11, flow.request.path);
sqlite3_bind_double(stmt_insert_request, 12, flow.request.timestamp_start);
sqlite3_bind_double(stmt_insert_request, 13, flow.request.timestamp_end);
bind_text(stmt_insert_request, 14, flow.request.error);
auto rc = sqlite3_step(stmt_insert_request);
sqlite3_reset(stmt_insert_request);
if(rc != SQLITE_DONE) {
qDebug() << "inserting request failed" << rc;
qDebug() << sqlite3_errmsg(db);
throw;
}
} }

109
session.h
View file

@ -4,46 +4,87 @@
#include <includes.h> #include <includes.h>
#include <httpflow.h> #include <httpflow.h>
// static int callback(void *NotUsed, int argc, char **argv, char **azColName){
// int i;
// for(i=0; i<argc; i++){
// printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
// }
// printf("\n");
// return 0;
// }
//
// int main(int argc, char **argv){
// sqlite3 *db;
// char *zErrMsg = 0;
// int rc;
//
// if( argc!=3 ){
// fprintf(stderr, "Usage: %s DATABASE SQL-STATEMENT\n", argv[0]);
// return(1);
// }
// rc = sqlite3_open(argv[1], &db);
// if( rc ){
// fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
// sqlite3_close(db);
// return(1);
// }
// rc = sqlite3_exec(db, argv[2], callback, 0, &zErrMsg);
// if( rc!=SQLITE_OK ){
// fprintf(stderr, "SQL error: %s\n", zErrMsg);
// sqlite3_free(zErrMsg);
// }
// sqlite3_close(db);
// return 0;
// }
class Session : public QObject class Session : public QObject
{ {
Q_OBJECT Q_OBJECT
private: private:
const char* create_request_tbl = R"rstr( CREATE TABLE request(
id INTEGER PRIMARY KEY AUTOINCREMENT,
server_conn_id TEXT,
server_ip_address TEXT,
tls INTEGER,
content TEXT,
scheme TEXT,
method TEXT,
host TEXT,
address TEXT,
port INTEGER,
http_version TEXT,
path TEXT,
timestamp_start REAL,
timestamp_end REAL,
error TEXT
); )rstr";
const char* create_request_header_tbl = R"rstr( CREATE TABLE request_header(
id INTEGER PRIMARY KEY AUTOINCREMENT,
key TEXT,
value TEXT,
request_id INTEGER,
FOREIGN KEY(request_id) REFERENCES request(referer_id) ON UPDATE CASCADE ON DELETE CASCADE
); )rstr";
const char* create_response_tbl = R"rstr( CREATE TABLE response(
id INTEGER PRIMARY KEY AUTOINCREMENT,
status_code INTEGER,
http_version TEXT,
reason TEXT,
content TEXT,
timestamp_start REAL,
timestamp_end REAL
); )rstr";
const char* create_response_header_tbl = R"rstr( CREATE TABLE response_header(
id INTEGER PRIMARY KEY AUTOINCREMENT,
key TEXT,
value TEXT,
response_id INTEGER,
FOREIGN KEY(response_id) REFERENCES response(referer_id) ON UPDATE CASCADE ON DELETE CASCADE
); )rstr";
const char* create_flow_tbl = R"rstr( CREATE TABLE flow(
id INTEGER PRIMARY KEY AUTOINCREMENT,
request_id INTEGER,
response_id INTEGER,
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(
key TEXT UNIQUE NOT NULL PRIMARY KEY,
value TEXT
); )rstr";
const char* last_inserted_id = R"rstr( SELECT last_insert_rowid(); )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* insert_request = R"rstr( INSERT INTO request (server_conn_id, 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 (request_id, response_id) VALUES (?,?); )rstr";
const char* insert_session = R"rstr( INSERT INTO session (key, value) VALUES (?,?); )rstr";
sqlite3* db = nullptr; sqlite3* db = nullptr;
bool loaded = false; bool loaded = false;
sqlite3_stmt* stmt_last_inserted_id = 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;
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);
public: public:
explicit Session(QObject *parent = nullptr); explicit Session(QObject *parent = nullptr);
~Session(); ~Session();