diff --git a/httpflow.h b/httpflow.h index b9bf209..4a1734f 100644 --- a/httpflow.h +++ b/httpflow.h @@ -104,7 +104,6 @@ struct Request std::string scheme; std::string method; std::string host; - std::string address; unsigned short port; std::string http_version; std::string path; @@ -132,6 +131,20 @@ struct Flow { Response response; }; +struct HistoryItem { + int id; + double timestamp; + std::string method; + std::string scheme; + std::string host; + unsigned short port; + std::string path; + int status_code; + std::string reason; + double rtt; + int size; +}; + inline void to_json(json& j, const Flow& flow) {} inline void from_json(const json& j, Flow& flow) { diff --git a/mainwindow.cpp b/mainwindow.cpp index 74bae7f..feb16ac 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -24,7 +24,7 @@ MainWindow::MainWindow(QWidget *parent) ui->setupUi(this); ui->historyHTTPTable->setShowGrid(true); ui->historyHTTPTable->setEditTriggers(QAbstractItemView::NoEditTriggers); - ui->historyHTTPTable->setColumnCount(4); + ui->historyHTTPTable->setColumnCount(7); ui->historyHTTPTable->setRowCount(1); /* @@ -42,6 +42,24 @@ MainWindow::~MainWindow() } void MainWindow::updateHistory() { + int i = 0; + auto items = current_session->getHistoryItems(); + for(auto& item : *items) { + ui->historyHTTPTable->setRowCount(i+1); + int j = 0; + ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(QString::number(item.id))); + QDateTime timestamp; + timestamp.setTime_t(item.timestamp); + ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(timestamp.toString(Qt::SystemLocaleShortDate))); + std::string url = item.scheme + "://" + item.host + ":" + std::to_string(item.port) + item.path; + ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(QString::fromStdString(url))); + ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(item.status_code)); + ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(QString::fromStdString(item.reason))); + ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(item.rtt)); + ui->historyHTTPTable->setItem(i,j++,new QTableWidgetItem(item.size)); + i++; + } + delete items; //ui->historyHTTPTable->setItem(0,0,new QTableWidgetItem(QString::fromStdString(flow.request.server_conn_id))); //ui->historyHTTPTable->setItem(0,1,new QTableWidgetItem(QString::fromStdString(flow.request.method))); //ui->historyHTTPTable->setItem(0,2,new QTableWidgetItem(QString::fromStdString(flow.request.host))); diff --git a/session.cpp b/session.cpp index a31bbd4..50f8d73 100644 --- a/session.cpp +++ b/session.cpp @@ -80,6 +80,7 @@ void Session::prepare_tables() { prepare(get_setting, &stmt_get_setting); } + prepare(get_all_history, &stmt_get_all_history); prepare(update_setting, &stmt_update_setting); prepare(insert_request, &stmt_insert_request); @@ -132,6 +133,41 @@ std::optional Session::getSetting(std::string key) { return std::nullopt; } +std::vector* Session::getHistoryItems() { + sqlite3_reset(stmt_get_all_history); + + std::vector* result = new std::vector(); + + auto rc = sqlite3_step(stmt_get_all_history); + while(rc == SQLITE_ROW) { + int j = 0; + http::HistoryItem i; + i.id = sqlite3_column_int(stmt_get_all_history, j++); + i.timestamp = sqlite3_column_double(stmt_get_all_history, j++); + i.method = std::string((const char*)sqlite3_column_text(stmt_get_all_history, j++)); + i.scheme = std::string((const char*)sqlite3_column_text(stmt_get_all_history, j++)); + i.host = std::string((const char*)sqlite3_column_text(stmt_get_all_history, j++)); + i.port = sqlite3_column_int(stmt_get_all_history, j++); + i.path = std::string((const char*)sqlite3_column_text(stmt_get_all_history, j++)); + i.status_code = sqlite3_column_int(stmt_get_all_history, j++); + i.reason = std::string((const char*)sqlite3_column_text(stmt_get_all_history, j++)); + i.rtt = sqlite3_column_double(stmt_get_all_history, j++); + i.size = sqlite3_column_int(stmt_get_all_history, j++); + + result->push_back(i); + + rc = sqlite3_step(stmt_get_all_history); + } + if(rc != SQLITE_DONE) { + qDebug() << "error getting history items" << rc; + qDebug() << sqlite3_errmsg(db); + delete result; + return nullptr; + } + + return result; +} + 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); @@ -149,7 +185,6 @@ int Session::saveRequest(http::Flow flow) { bind_text(stmt_insert_request, j++, flow.request.scheme); bind_text(stmt_insert_request, j++, flow.request.method); bind_text(stmt_insert_request, j++, flow.request.host); - bind_text(stmt_insert_request, j++, flow.request.address); sqlite3_bind_int(stmt_insert_request, j++, flow.request.port); diff --git a/session.h b/session.h index 76cc1da..dd71a9a 100644 --- a/session.h +++ b/session.h @@ -18,7 +18,6 @@ private: scheme TEXT, method TEXT, host TEXT, - address TEXT, port INTEGER, http_version TEXT, path TEXT, @@ -64,8 +63,9 @@ private: 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_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) 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, address, port, http_version, path, timestamp_start, timestamp_end, error) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?); )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"; @@ -78,6 +78,7 @@ private: bool loaded = false; sqlite3_stmt* stmt_get_setting = nullptr; + sqlite3_stmt* stmt_get_all_history = nullptr; sqlite3_stmt* stmt_insert_request = nullptr; sqlite3_stmt* stmt_insert_request_header = nullptr; @@ -102,6 +103,7 @@ public: 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); diff --git a/test.sh b/test.sh index 76ea444..8518492 100755 --- a/test.sh +++ b/test.sh @@ -5,7 +5,33 @@ mitmdump -k -p 8080 -s mitmaddon/littlesnitch.py & sleep 1 curl -x http://localhost:8080 -k https://get.yolo.jetzt -sleep 1 +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt +curl -x http://localhost:8080 -k https://get.yolo.jetzt curl -x http://localhost:8080 -k https://get.yolo.jetzt killall mitmdump