From 9ce211c5728c5cc8aa3d4c997eda7e93d0eaa31e Mon Sep 17 00:00:00 2001 From: rapturate Date: Thu, 28 May 2026 12:33:46 -0400 Subject: [PATCH] Added documentation comments using Doxygen, changed the file structure back to the original, and wrote the getter functions for the individual entries. --- headers/log_parsing.h | 34 --------- {objects => ip_to_geo}/ip_to_geo.cpp | 0 {headers => ip_to_geo}/ip_to_geo.h | 0 log_parsing/log_parsing.cpp | 88 +++++++++++++++++++++++ log_parsing/log_parsing.h | 103 +++++++++++++++++++++++++++ main.cpp | 3 +- objects/log_parsing.cpp | 65 ----------------- 7 files changed, 192 insertions(+), 101 deletions(-) delete mode 100644 headers/log_parsing.h rename {objects => ip_to_geo}/ip_to_geo.cpp (100%) rename {headers => ip_to_geo}/ip_to_geo.h (100%) create mode 100644 log_parsing/log_parsing.cpp create mode 100644 log_parsing/log_parsing.h delete mode 100644 objects/log_parsing.cpp diff --git a/headers/log_parsing.h b/headers/log_parsing.h deleted file mode 100644 index 309e22f..0000000 --- a/headers/log_parsing.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include -#include - -struct Entry { - std::string ip; - std::string timestamp; - std::string request; - std::string status; - std::string bytes; - std::string referer; - std::string os; - std::string browser; -}; - -class parsed_logs { -private: - Entry entry; - std::vector logs; - std::string url; -public: - parsed_logs(std::string url); - void parse(const std::smatch& match); - - std::vector parse_file(std::string log_url); - std::string get_ip(); - std::string get_timestamp(); - std::string get_request(); - std::string get_status(); - std::string get_bytes(); - std::string get_referer(); - std::string get_os(); - std::string get_browser(); -}; \ No newline at end of file diff --git a/objects/ip_to_geo.cpp b/ip_to_geo/ip_to_geo.cpp similarity index 100% rename from objects/ip_to_geo.cpp rename to ip_to_geo/ip_to_geo.cpp diff --git a/headers/ip_to_geo.h b/ip_to_geo/ip_to_geo.h similarity index 100% rename from headers/ip_to_geo.h rename to ip_to_geo/ip_to_geo.h diff --git a/log_parsing/log_parsing.cpp b/log_parsing/log_parsing.cpp new file mode 100644 index 0000000..5d3f54b --- /dev/null +++ b/log_parsing/log_parsing.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include + +#include "log_parsing.h" + +parsed_logs::parsed_logs(std::string log_path) { + std::ifstream file(log_path); + if (!file.is_open()) { + std::cerr << "Error loading " << log_path << std::endl; + return; + } + + std::regex log_pattern(R"((\S+)\s+-\s+-\s+\[([^\]]+)\]\s+\"([^\"]+)\"\s+(\d+)\s+(\d+|-)\s+\"([^\"]*)\"\s+\"([^\"]*)\")"); + + std::string line; + std::smatch match; + + while (std::getline(file, line)) { + if (std::regex_search(line, match, log_pattern)) { + + Entry current_entry; + current_entry.ip = match[1].str(); + current_entry.timestamp = match[2].str(); + current_entry.request = match[3].str(); + current_entry.status = match[4].str(); + current_entry.bytes = match[5].str(); + current_entry.referer = match[6].str(); + + std::string raw_ua = match[7].str(); + + if (raw_ua.find("Windows NT 10.0") != std::string::npos) current_entry.os = "Windows 10/11"; + else if (raw_ua.find("Windows NT 6.1") != std::string::npos) current_entry.os = "Windows 7"; + else if (raw_ua.find("iPhone") != std::string::npos) current_entry.os = "iOS (iPhone)"; + else if (raw_ua.find("iPad") != std::string::npos) current_entry.os = "iOS (iPad)"; + else if (raw_ua.find("Android") != std::string::npos) current_entry.os = "Android"; + else if (raw_ua.find("Macintosh") != std::string::npos) current_entry.os = "macOS"; + else if (raw_ua.find("Linux") != std::string::npos) current_entry.os = "Linux"; + else current_entry.os = "Unknown OS"; + + if (raw_ua.find("Edg/") != std::string::npos) current_entry.browser = "Microsoft Edge"; + else if (raw_ua.find("OPR/") != std::string::npos) current_entry.browser = "Opera"; + else if (raw_ua.find("Chrome/") != std::string::npos) current_entry.browser = "Google Chrome"; + else if (raw_ua.find("Safari/") != std::string::npos) current_entry.browser = "Apple Safari"; + else if (raw_ua.find("Firefox/") != std::string::npos) current_entry.browser = "Mozilla Firefox"; + else if (raw_ua.find("curl/") != std::string::npos) current_entry.browser = "curl (CLI Tool)"; + else current_entry.browser = "Unknown Browser/Bot"; + + logs.push_back(current_entry); + } + } + file.close(); +} + +std::string parsed_logs::entryx_ip(int x){ + return logs[x].ip; +} + +std::string parsed_logs::entryx_timestamp(int x){ + return logs[x].timestamp; +} + +std::string parsed_logs::entryx_request(int x){ + return logs[x].request; +} + +std::string parsed_logs::entryx_status(int x){ + return logs[x].status; +} + +std::string parsed_logs::entryx_bytes(int x){ + return logs[x].bytes; +} + +std::string parsed_logs::entryx_referer(int x){ + return logs[x].referer; +} + +std::string parsed_logs::entryx_os(int x){ + return logs[x].os; +} + +std::string parsed_logs::entryx_browser(int x){ + return logs[x].browser; +} \ No newline at end of file diff --git a/log_parsing/log_parsing.h b/log_parsing/log_parsing.h new file mode 100644 index 0000000..ffd6927 --- /dev/null +++ b/log_parsing/log_parsing.h @@ -0,0 +1,103 @@ +/** + * @file log_parsing.h + * @author Lew Price (lewis.e.price@outlook.com) + * @brief A series of functions for parsing the access logs of an Apache2 webserver. + * @version 0.1 + * @date 2026-05-28 + * + * @copyright Copyright (c) 2026 + * + */ + +#pragma once +#include +#include + +struct Entry { + std::string ip; + std::string timestamp; + std::string request; + std::string status; + std::string bytes; + std::string referer; + std::string os; + std::string browser; +}; + +class parsed_logs { +private: + Entry entry; + std::vector logs; + std::string url; +public: + /** + * @brief Construct a new parsed logs object + * Detailed explanation: This function takes in the absolute path to a .log file and parses the lines into individual "Entry"s. These Entrys are then stored into a vector that can then be accessed via getter functions. + * @param string + */ + parsed_logs(std::string); + + /** + * @brief Getter function for a specific Entry's IP + * + * @param int + * @return std::string + */ + std::string entryx_ip(int); + + /** + * @brief Getter function for a specific Entry's time stamp + * + * @param int + * @return std::string + */ + std::string entryx_timestamp(int); + + /** + * @brief Getter function for a specific Entry's request + * + * @param int + * @return std::string + */ + std::string entryx_request(int); + + /** + * @brief Getter function for a specific Entry's status + * + * @param int + * @return std::string + */ + std::string entryx_status(int); + + /** + * @brief Getter function for a specific Entry's byte size + * + * @param int + * @return std::string + */ + std::string entryx_bytes(int); + + /** + * @brief Getter function for a specific Entry's referer + * + * @param int + * @return std::string + */ + std::string entryx_referer(int); + + /** + * @brief Getter function for a specific Entry's OS info + * + * @param int + * @return std::string + */ + std::string entryx_os(int); + + /** + * @brief Getter function for a specific Entry's browser info + * + * @param int + * @return std::string + */ + std::string entryx_browser(int); +}; \ No newline at end of file diff --git a/main.cpp b/main.cpp index 9f8ce80..312f870 100644 --- a/main.cpp +++ b/main.cpp @@ -1,5 +1,4 @@ -#include "log_parsing/log_parsing.h" int main(){ - parse logs; + } \ No newline at end of file diff --git a/objects/log_parsing.cpp b/objects/log_parsing.cpp deleted file mode 100644 index 2d24035..0000000 --- a/objects/log_parsing.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "log_parsing.h" - -parsed_logs::parse(const std::smatch& match) { - Entry entry; - entry.ip = match[1].str(); - entry.timestamp = match[2].str(); - entry.request = match[3].str(); - entry.status = match[4].str(); - entry.bytes = match[5].str(); - entry.referer = match[6].str(); - - std::string raw_ua = match[7].str(); - - if (raw_ua.find("Windows NT 10.0") != std::string::npos) entry.os = "Windows 10/11"; - else if (raw_ua.find("Windows NT 6.1") != std::string::npos) entry.os = "Windows 7"; - else if (raw_ua.find("iPhone") != std::string::npos) entry.os = "iOS (iPhone)"; - else if (raw_ua.find("iPad") != std::string::npos) entry.os = "iOS (iPad)"; - else if (raw_ua.find("Android") != std::string::npos) entry.os = "Android"; - else if (raw_ua.find("Macintosh") != std::string::npos) entry.os = "macOS"; - else if (raw_ua.find("Linux") != std::string::npos) entry.os = "Linux"; - else entry.os = "Unknown OS"; - - if (raw_ua.find("Edg/") != std::string::npos) entry.browser = "Microsoft Edge"; - else if (raw_ua.find("OPR/") != std::string::npos) entry.browser = "Opera"; - else if (raw_ua.find("Chrome/") != std::string::npos) entry.browser = "Google Chrome"; - else if (raw_ua.find("Safari/") != std::string::npos) entry.browser = "Apple Safari"; - else if (raw_ua.find("Firefox/") != std::string::npos) entry.browser = "Mozilla Firefox"; - else if (raw_ua.find("curl/") != std::string::npos) entry.browser = "curl (CLI Tool)"; - else entry.browser = "Unknown Browser/Bot"; -} - -std::vector parse_file(std::string log_url) { - std::ifstream file(log_url); - - if(!file.is_open()) { - std::cerr << "Error loading " << log_url << std::endl; - EXIT_FAILURE; - } - - std::vector lines; - std::string line; - while(std::getline(file, line)){ - lines.push_back(std::move(line)); - } - file.close(); - - std::vector all_logs; - std::regex log_pattern(R"((\S+)\s+-\s+-\s+\[([^\]]+)\]\s+\"([^\"]+)\"\s+(\d+)\s+(\d+|-)\s+\"([^\"]*)\"\s+\"([^\"]*)\")"); - - for(const auto& log_line : lines) { - std::smatch match; - if(std::regex_search(log_line, match, log_pattern)) { - all_logs.emplace_back(match); - } - } - return all_logs; -} \ No newline at end of file