#pragma once #include #include #include #include #include class Session : public QObject { Q_OBJECT 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, 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(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(id) ON UPDATE CASCADE ON DELETE CASCADE ); )rstr"; const char* create_flow_tbl = R"rstr( CREATE TABLE flow( id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT UNIQUE NOT NULL, 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_setting_tbl = R"rstr( CREATE TABLE setting( key TEXT UNIQUE NOT NULL PRIMARY KEY, value TEXT ); )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* get_request_headers = R"rstr( SELECT key,value FROM response_header WHERE response_id=?; )rstr"; const char* get_response_headers = R"rstr( SELECT key,value FROM request_header WHERE request_id=?; )rstr"; const char* get_all_history = R"rstr( SELECT f.id,req.timestamp_start,req.method,req.scheme,req.host,req.port,req.path,res.status_code,res.reason,res.timestamp_end-res.timestamp_start,length(res.content),req.http_version,req.content,res.http_version,res.content FROM flow f JOIN request req ON f.request_id=req.id JOIN response res ON f.response_id=res.id; )rstr"; const char* insert_request = R"rstr( INSERT INTO request (server_ip_address, tls, content, scheme, method, host, 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_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_get_request_headers = nullptr; sqlite3_stmt* stmt_get_response_headers = nullptr; sqlite3_stmt* stmt_get_all_history = 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_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); bool reset(sqlite3_stmt* stmt); inline std::map getHeaders(int id, bool get); std::map getRequestHeader(int id); std::map getResponseHeader(int id); public: explicit Session(QObject *parent = nullptr); ~Session(); void load(std::filesystem::path path); void unload(); bool isLoaded(); std::optional getSetting(std::string key); std::vector* getHistoryItems(); 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: };