diff --git a/src/main.c b/src/main.c index 898e587..6019a3c 100644 --- a/src/main.c +++ b/src/main.c @@ -32,13 +32,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND #define TOP_X 20 // definiert die Anzahl der Einträge, die in den Top-Listen angezeigt werden sollen #define SUSPICIOUS_REQUEST_LEN_THRESHOLD 256 -// definiert Variablen für den Filtermodus. FILTER_INCLUDE=0, FILTER_EXCLUDE=1. Verbessert die Lesbarkeit des Codes. -// TODO entfernen? -typedef enum { - FILTER_INCLUDE, - FILTER_EXCLUDE -} filter_mode_t; - // struct für die Darstellung von Timestamps. Die granulare Trennung in verschiedene int-Werte macht die spätere Verarbeitung modular anpassbar/erweiterbar und erleichtert die Verarbeitung. struct simple_time { int day; @@ -68,47 +61,47 @@ struct log_entry { // Struktur für einen Status-Filtereintrag mit Inhalt & Modus struct status_filter { int code; - filter_mode_t mode; + int filter_exclude_flag; }; struct method_filter { char pattern[10]; - filter_mode_t mode; + int filter_exclude_flag; }; // für IP-Adressen struct ip_filter { char ip_address[50]; - filter_mode_t mode; + int filter_exclude_flag; }; // für Zeit, Start- und Endzeit struct time_filter { struct simple_time start_time; struct simple_time end_time; - filter_mode_t mode; + int filter_exclude_flag; }; // Filter für User-Agent struct user_agent_filter { char pattern[256]; - filter_mode_t mode; + int filter_exclude_flag; }; // Filter für URL-Pfad/Request struct url_filter { char pattern[MAX_REQUEST_LENGTH]; - filter_mode_t mode; + int filter_exclude_flag; }; struct annotation_flag_filter { int annotation_flag_is_present; - filter_mode_t mode; + int filter_exclude_flag; }; struct annotation_filter { char pattern[64]; - filter_mode_t mode; + int filter_exclude_flag; }; // Struktur zum erhalten aller Filtereinträge, kann im Dialogbetrieb bearbeitet werden. Mit Zähler. @@ -140,12 +133,20 @@ struct filter_system { int combination_mode; // 0=AND-Filter oder 1=OR-Filter }; +// Definition einer Datenstruktur für die IP-Adressen Topliste +struct ip_stat { + char ip_address[50]; + int count; +}; + // Initialisierung eines Arrays für die Logeinträge und weiterer Startvariablen struct log_entry *all_entries = NULL; int max_entries = 0; int total_entries = 0; int suspicious_patterns_count = 0; struct filter_system filters = {0}; +// für -v option +int flag_verbose = 0; // Hilfsfunktion für die Erkennung von Leerzeichen int is_space(char c) { @@ -246,7 +247,7 @@ void cleanup_memory(){ // sauberes Schließen und bereinigen bei Fehlerstatus, sofern Speicher nicht alloziert werden kann void cleanup_and_exit(){ - printf("Programmende. Speicher wird freigegeben und mit NULL überschrieben.\n"); + if (flag_verbose) printf("DEBUG: Programmende. Speicher wird freigegeben und mit NULL überschrieben.\n"); cleanup_memory(); exit(1); } @@ -258,7 +259,7 @@ void mem_expand_dynamically(){ int old_max = max_entries; max_entries = max_entries * GROWTH_FACTOR; - printf("DEBUG: Dynamische Speichererweiterung von %d auf %d Einträge um Faktor %f\n", old_max, max_entries, GROWTH_FACTOR); + if (flag_verbose) printf("DEBUG: Dynamische Speichererweiterung von %d auf %d Einträge um Faktor %f\n", old_max, max_entries, GROWTH_FACTOR); struct log_entry *new_ptr = realloc(all_entries, max_entries * sizeof(struct log_entry)); @@ -269,7 +270,7 @@ void mem_expand_dynamically(){ } all_entries = new_ptr; - printf("DEBUG: Speicher erfolgreich erweitert auf %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry))); + if (flag_verbose) printf("DEBUG: Speicher erfolgreich erweitert auf %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry))); } } @@ -283,7 +284,7 @@ void allocate_initial_memory(){ exit(1); // cleanup_and_exit() nicht nötig, da der Speicherbereich nicht beschrieben wurde - use-after-free unproblematisch } - printf("DEBUG: Speicher erfolgreich alloziert für %d Log-Einträge (%lu Bytes)\n", max_entries, (unsigned long)(max_entries * sizeof(struct log_entry))); + if (flag_verbose) printf("DEBUG: Speicher erfolgreich alloziert für %d Log-Einträge (%lu Bytes)\n", max_entries, (unsigned long)(max_entries * sizeof(struct log_entry))); } void get_current_timestamp(char* buffer, int buffer_size) { @@ -310,25 +311,31 @@ int is_directory(char* path) { } // Hilfsfunktion zum prüfen, ob es sich um eine plausible nginx-Logdatei handelt (Metrik: Dateiname - BESSER: Regex oder Magic Bytes?) -int is_log_file(char* filename) { - char* log_pos = strstr(filename, ".log"); // Sucht und findet den Pointer auf die Startposition des Suchstrings - if (log_pos == NULL) return 0; - - char* after_log = log_pos + 4; - - if (*after_log == '\0') return 1; // true, wenn die Datei mit .log endet - - if (*after_log == '.') { - after_log++; - if (*after_log == '\0') return 0; // false, wenn die Datei mit einem Punkt nach .log endet - - while (*after_log != '\0') { - if (*after_log < '0' || *after_log > '9') return 0; // wenn was anderes als Zahlen nach dem . kommen, gib False zurück - after_log++; - } - return 1; // true, wenn nach .log. noch Zahlen vorhanden sind, wie typisch bei NGINX-Logrotation +int is_log_file(char* filename) { + // versteckte Dateien sowie . oder .. überspringen + if (filename[0] == '.') { + return 0; } - return 0; // false, wenn nichts zutrifft + + // Mögliche Bestandteile von NGINX-Logfile-Dateinamen + char* log_patterns[] = { + ".log", + "access", + "error", + "combined", + "redirect", + NULL + }; + + // Vergleich der vorhandenen Dateinamen mit den Suchmustern + for (int i = 0; log_patterns[i] != NULL; i++) { + if (strstr(filename, log_patterns[i]) != NULL) { + if ((strstr(filename, "error")!= NULL)||(strstr(filename, ".gz")!= NULL)) continue; + return 1; + } + } + + return 0; } // Funktion zum suchen eines Suchbegriffs innerhalb eines Strings (lowercase) @@ -374,12 +381,25 @@ int search_in_string(char* raw_string, char* search_string) { // Fügt eine Annotation zu einem bestimmten Eintrag hinzu +// https://stackoverflow.com/questions/5901181/c-string-append void annotate_entry(int index, char* annotation_string) { if (index >= 0 && index < total_entries) { - strncpy(all_entries[index].annotation, annotation_string, sizeof(all_entries[index].annotation) - 1); - all_entries[index].annotation[sizeof(all_entries[index].annotation) - 1] = '\0'; - all_entries[index].annotated_flag = 1; - //printf("DEBUG: Annotation zu Eintrag %d: %s\n", index, annotation_string); + if (all_entries[index].annotation== NULL){ + strncpy(all_entries[index].annotation, annotation_string, sizeof(all_entries[index].annotation) - 1); + all_entries[index].annotation[sizeof(all_entries[index].annotation) - 1] = '\0'; + all_entries[index].annotated_flag = 1; + } else { + char * new_str ; + if((new_str = malloc(strlen(all_entries[index].annotation)+strlen(",")+strlen(annotation_string)+1)) != NULL){ + new_str[0] = '\0'; // ensures the memory is an empty string + strcat(new_str,","); + strcat(new_str,annotation_string); + strncpy(all_entries[index].annotation, new_str, sizeof(all_entries[index].annotation) - 1); + all_entries[index].annotation[sizeof(all_entries[index].annotation) - 1] = '\0'; + free(new_str); + new_str=NULL; + } + } } } @@ -387,7 +407,7 @@ void annotate_entry(int index, char* annotation_string) { // TRANSPARENZ: Diese Funktion ist KI-generiert void annotate_suspicious_entries(struct log_entry* dataset) { - printf("DEBUG: Prüfe %d Einträge auf verdächtige Muster...\n", total_entries); + if (flag_verbose) printf("DEBUG: Prüfe %d Einträge auf verdächtige Muster...\n", total_entries); for (int i = 0; i < total_entries; i++) { // Initialisierung der Annotation falls noch nicht gesetzt @@ -616,7 +636,7 @@ void annotate_suspicious_entries(struct log_entry* dataset) { } } - printf("DEBUG: Analyse abgeschlossen. %d verdächtige Muster erkannt.\n", suspicious_patterns_count); + if (flag_verbose) printf("DEBUG: Analyse abgeschlossen. %d verdächtige Muster erkannt.\n", suspicious_patterns_count); } /* @@ -921,8 +941,8 @@ void load_log_file(char* path) { char full_path[512]; if (is_directory(path)) { - printf("DEBUG: Verzeichnis erkannt: %s\n", path); - printf("DEBUG: Suche nach .log Dateien...\n"); + if (flag_verbose) printf("DEBUG: Verzeichnis erkannt: %s\n", path); + if (flag_verbose) printf("DEBUG: Suche nach .log Dateien...\n"); DIR* dir = opendir(path); if (dir == NULL) { @@ -962,7 +982,7 @@ void load_log_file(char* path) { printf("INFO: Insgesamt %d .log Dateien verarbeitet.\n", files_found); } } else { - printf("DEBUG: Einzelne Datei erkannt: %s\n", path); + if (flag_verbose) printf("DEBUG: Einzelne Datei erkannt: %s\n", path); if (strstr(path, ".gz") != NULL) { load_gz_file(path); } else { @@ -972,9 +992,8 @@ void load_log_file(char* path) { printf("INFO: Erfolgreich %d Einträge insgesamt geladen.\n", total_entries); // die aufgerufene Funktion ist KI-generiert und annotiert verdächtige Requests automatisch. - // TODO annotate_suspicious_entries(all_entries); - printf("DEBUG: Aktueller Speicherverbrauch: %lu Bytes für %d Einträge\n", + if (flag_verbose) printf("DEBUG: Aktueller Speicherverbrauch: %lu Bytes für %d Einträge\n", (unsigned long)(max_entries * sizeof(struct log_entry)), max_entries); } @@ -983,7 +1002,7 @@ int user_agent_matches(char* user_agent) { if (filters.user_agent_count == 0) return 1; // Ausschluss-Filter geht vor for (int i = 0; i < filters.user_agent_count; i++) { - if (filters.user_agent_filters[i].mode == FILTER_EXCLUDE) { + if (filters.user_agent_filters[i].filter_exclude_flag == 1) { int pattern_found = search_in_string(user_agent, filters.user_agent_filters[i].pattern); if (pattern_found) { return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft @@ -995,7 +1014,7 @@ int user_agent_matches(char* user_agent) { int include_matches = 0; for (int i = 0; i < filters.user_agent_count; i++) { - if (filters.user_agent_filters[i].mode == FILTER_INCLUDE) { + if (filters.user_agent_filters[i].filter_exclude_flag == 0) { include_count++; int pattern_found = search_in_string(user_agent, filters.user_agent_filters[i].pattern); if (pattern_found) { @@ -1024,7 +1043,7 @@ int url_matches(char* url_path) { if (filters.url_count == 0) return 1; // Ausschluss-Filter geht vor for (int i = 0; i < filters.url_count; i++) { - if (filters.url_filters[i].mode == FILTER_EXCLUDE) { + if (filters.url_filters[i].filter_exclude_flag == 1) { int pattern_found = search_in_string(url_path, filters.url_filters[i].pattern); if (pattern_found) { return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft @@ -1036,7 +1055,7 @@ int url_matches(char* url_path) { int include_matches = 0; for (int i = 0; i < filters.url_count; i++) { - if (filters.url_filters[i].mode == FILTER_INCLUDE) { + if (filters.url_filters[i].filter_exclude_flag == 0) { include_count++; int pattern_found = search_in_string(url_path, filters.url_filters[i].pattern); if (pattern_found) { @@ -1065,7 +1084,7 @@ int method_matches(char* request_method) { if (filters.method_count == 0) return 1; // Ausschluss-Filter geht vor for (int i = 0; i < filters.method_count; i++) { - if (filters.method_filters[i].mode == FILTER_EXCLUDE) { + if (filters.method_filters[i].filter_exclude_flag == 1) { int pattern_found = search_in_string(request_method, filters.method_filters[i].pattern); if (pattern_found) { return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft @@ -1077,7 +1096,7 @@ int method_matches(char* request_method) { int include_matches = 0; for (int i = 0; i < filters.method_count; i++) { - if (filters.method_filters[i].mode == FILTER_INCLUDE) { + if (filters.method_filters[i].filter_exclude_flag == 0) { include_count++; int pattern_found = search_in_string(request_method, filters.method_filters[i].pattern); if (pattern_found) { @@ -1105,7 +1124,7 @@ int status_code_matches(int status_code) { if (filters.status_count == 0) return 1; // Ausschluss-Filter prüfen: immer übergeordnet gültig for (int i = 0; i < filters.status_count; i++) { - if (filters.status_filters[i].mode == FILTER_EXCLUDE) { + if (filters.status_filters[i].filter_exclude_flag == 1) { if (filters.status_filters[i].code == status_code) { return 0; } @@ -1117,7 +1136,7 @@ int status_code_matches(int status_code) { int include_matches = 0; for (int i = 0; i < filters.status_count; i++) { - if (filters.status_filters[i].mode == FILTER_INCLUDE) { + if (filters.status_filters[i].filter_exclude_flag == 0) { include_count++; if (filters.status_filters[i].code == status_code) { include_matches++; @@ -1144,7 +1163,7 @@ int ip_address_matches(char* ip_address) { // Prüfen der Ausschlussfilter, sind dem Rest vorgelagert for (int i = 0; i < filters.ip_count; i++) { - if (filters.ip_filters[i].mode == FILTER_EXCLUDE) { + if (filters.ip_filters[i].filter_exclude_flag == 1) { if (strcmp(filters.ip_filters[i].ip_address, ip_address) == 0) { return 0; // zutreffender Ausschlussfilter führt zu negativem Rückgabewert } @@ -1156,7 +1175,7 @@ int ip_address_matches(char* ip_address) { int include_matches = 0; for (int i = 0; i < filters.ip_count; i++) { - if (filters.ip_filters[i].mode == FILTER_INCLUDE) { + if (filters.ip_filters[i].filter_exclude_flag == 0) { include_count++; if (strcmp(filters.ip_filters[i].ip_address, ip_address) == 0) { include_matches++; @@ -1179,14 +1198,14 @@ int ip_address_matches(char* ip_address) { } int is_annotated(int annotated_flag){ - if (filters.annotation_flag_filter.mode == FILTER_EXCLUDE && filters.annotation_flag_filter_enabled == 1 && annotated_flag == 1) { + if (filters.annotation_flag_filter.filter_exclude_flag == 1 && filters.annotation_flag_filter_enabled == 1 && annotated_flag == 1) { return 0; // zutreffender Ausschlussfilter führt zu negativem Rückgabewert } - else if (filters.annotation_flag_filter.mode == FILTER_INCLUDE && filters.annotation_flag_filter_enabled == 1 && annotated_flag == 1) { + else if (filters.annotation_flag_filter.filter_exclude_flag == 0 && filters.annotation_flag_filter_enabled == 1 && annotated_flag == 1) { return 1; // zutreffender Einschlussfilter führt zu positivem Rückgabewert } // nichtannotiert, aber inklusiver Filter aktiv -> Eintrag nicht anzeigen - else if (annotated_flag == 0 && filters.annotation_flag_filter.mode == FILTER_INCLUDE && filters.annotation_flag_filter_enabled == 1){ + else if (annotated_flag == 0 && filters.annotation_flag_filter.filter_exclude_flag == 0 && filters.annotation_flag_filter_enabled == 1){ return 0; } // Filter nicht aktiv, positiver Rückgabewert @@ -1198,7 +1217,7 @@ int annotation_matches(char* annotation) { if (filters.annotation_count == 0) return 1; // Ausschluss-Filter geht vor for (int i = 0; i < filters.annotation_count; i++) { - if (filters.annotation_filters[i].mode == FILTER_EXCLUDE) { + if (filters.annotation_filters[i].filter_exclude_flag == 1) { int pattern_found = search_in_string(annotation, filters.annotation_filters[i].pattern); if (pattern_found) { return 0; // früheres Verlassen der Schleife, sobald Ausschlussfilter zutrifft @@ -1210,7 +1229,7 @@ int annotation_matches(char* annotation) { int include_matches = 0; for (int i = 0; i < filters.annotation_count; i++) { - if (filters.annotation_filters[i].mode == FILTER_INCLUDE) { + if (filters.annotation_filters[i].filter_exclude_flag == 0) { include_count++; int pattern_found = search_in_string(annotation, filters.annotation_filters[i].pattern); if (pattern_found) { @@ -1240,7 +1259,7 @@ int time_matches(struct simple_time entry_time) { // Übergeordneter Ausschlussfilter for (int i = 0; i < filters.time_count; i++) { - if (filters.time_filters[i].mode == FILTER_EXCLUDE) { + if (filters.time_filters[i].filter_exclude_flag == 1) { int in_range = (compare_times(entry_time, filters.time_filters[i].start_time) >= 0 && compare_times(entry_time, filters.time_filters[i].end_time) <= 0); if (in_range) { @@ -1253,7 +1272,7 @@ int time_matches(struct simple_time entry_time) { int include_count = 0; int include_matches = 0; for (int i = 0; i < filters.time_count; i++) { - if (filters.time_filters[i].mode == FILTER_INCLUDE) { + if (filters.time_filters[i].filter_exclude_flag == 0) { include_count++; int in_range = (compare_times(entry_time, filters.time_filters[i].start_time) >= 0 && compare_times(entry_time, filters.time_filters[i].end_time) <= 0); @@ -1387,7 +1406,7 @@ void export_filtered_entries(char *filepath) { } // CSV-Kopfzeile für Timesketch-Kompatibilität - fprintf(file, "datetime,timestamp_desc,ip_address,method,url_path,status_code,bytes_sent,user_agent,source_file,parsing_timestamp,annotation\n"); + fprintf(file, "datetime,message,timestamp_desc,ip_address,method,url_path,status_code,bytes_sent,user_agent,parsing_timestamp,tag\n"); int exported_count = 0; char iso_datetime[32]; @@ -1396,20 +1415,44 @@ void export_filtered_entries(char *filepath) { if (passes_filter(i)) { format_iso8601_time(all_entries[i].time, iso_datetime, sizeof(iso_datetime)); + // https://stackoverflow.com/questions/5901181/c-string-append + // https://www.quora.com/How-can-we-count-the-number-of-special-characters-in-a-string-in-the-C-language-using-fgets + char* tag_str; + int num_delimiters = 0; + int c=0; + while(all_entries[i].annotation[c]!='\0'){ + num_delimiters++; + } + if (tag_str=malloc(sizeof(all_entries[i].annotation)+sizeof("[ ]")+(sizeof(','))*num_delimiters)+1)!=NULL){ + tag_str[0] = '\0'; + + + char* token = strtok(all_entries[i].annotation, ","); + if (!token) return; + strcat(tag_str, "[ "); + for (i=0;i= 0) { + // inkrementieren des counters für Anzahl wie oft gefunden ip_stats[found_index].count++; } else { + // wenn nicht gefunden (found_index == -1) wird die IP mit count = 1 neu angelegt if (unique_ips < 1000) { strcpy(ip_stats[unique_ips].ip_address, current_ip); ip_stats[unique_ips].count = 1; @@ -1490,6 +1538,8 @@ void show_top_x_ips(){ } } + // iterieren über alle unique ips + // Bubble sort: https://www.proggen.org/doku.php?id=training:sorting:bubblesort:solution for (int i = 0; i < unique_ips - 1; i++) { for (int j = 0; j < unique_ips - i - 1; j++) { if (ip_stats[j].count < ip_stats[j + 1].count) { @@ -1500,6 +1550,7 @@ void show_top_x_ips(){ } } + // visuelle Darstellung printf("\nTOP %d IP-ADRESSEN\n", TOP_X); printf("Rang | IP-Adresse | Anzahl Anfragen\n"); printf("-----|------------------|----------------\n"); @@ -1516,7 +1567,7 @@ void show_top_x_ips(){ } } -// TODO doku +// gleiche Mechanik wie in show_top_x_ips - könnte wahrscheinlich vereinheitlicht werden void show_top_user_agents(){ struct user_agent_stat { char user_agent[256]; @@ -1633,7 +1684,7 @@ void print_filter_args(){ printf("--status="); for (int i = 0; i < filters.status_count; i++) { if (i > 0) {printf(",");}; - if (filters.status_filters[i].mode == FILTER_EXCLUDE) printf("!"); + if (filters.status_filters[i].filter_exclude_flag == 1) printf("!"); printf("%d", filters.status_filters[i].code); } printf(" "); @@ -1643,7 +1694,7 @@ void print_filter_args(){ printf("--method="); for (int i = 0; i < filters.method_count; i++) { if (i > 0) {printf(",");} - if (filters.method_filters[i].mode == FILTER_EXCLUDE) printf("!"); + if (filters.method_filters[i].filter_exclude_flag == 1) printf("!"); printf("%s", filters.method_filters[i].pattern); } printf(" "); @@ -1653,7 +1704,7 @@ void print_filter_args(){ printf("--ip="); for (int i = 0; i < filters.ip_count; i++) { if (i > 0) {printf(",");}; - if (filters.ip_filters[i].mode == FILTER_EXCLUDE) printf("!"); + if (filters.ip_filters[i].filter_exclude_flag == 1) printf("!"); printf("%s", filters.ip_filters[i].ip_address); } printf(" "); @@ -1663,7 +1714,7 @@ void print_filter_args(){ printf("--useragent="); for (int i = 0; i < filters.user_agent_count; i++) { if (i > 0) {printf(",");}; - if (filters.user_agent_filters[i].mode == FILTER_EXCLUDE) printf("!"); + if (filters.user_agent_filters[i].filter_exclude_flag == 1) printf("!"); printf("%s", filters.user_agent_filters[i].pattern); } printf(" "); @@ -1673,7 +1724,7 @@ void print_filter_args(){ printf("--url="); for (int i = 0; i < filters.url_count; i++) { if (i > 0) {printf(",");}; - if (filters.url_filters[i].mode == FILTER_EXCLUDE) printf("!"); + if (filters.url_filters[i].filter_exclude_flag == 1) printf("!"); printf("%s", filters.url_filters[i].pattern); } printf(" "); @@ -1683,7 +1734,7 @@ void print_filter_args(){ printf("--timerange="); for(int i =0; i < filters.time_count;i++){ if(i > 0) {printf(",");}; - if (filters.time_filters[i].mode == FILTER_EXCLUDE) {printf("!");}; + if (filters.time_filters[i].filter_exclude_flag == 1) {printf("!");}; // die führenden 0 sind hier wichtig printf("%04d-%02d-%02d-%02d-%02d-%02d:%04d-%02d-%02d-%02d-%02d-%02d ", filters.time_filters[i].start_time.year, @@ -1704,7 +1755,7 @@ void print_filter_args(){ // macht nicht viel Sinn, diese hier zu integrieren, so lang der User nicht weiß, wie die Annotationen lauten if (filters.annotation_flag_filter_enabled) { printf("--annotated="); - if (filters.annotation_flag_filter.mode == FILTER_EXCLUDE) printf("!"); + if (filters.annotation_flag_filter.filter_exclude_flag == 1) printf("!"); printf("true "); } @@ -1712,7 +1763,7 @@ void print_filter_args(){ printf("--annotation="); for (int i = 0; i < filters.annotation_count; i++) { if (i > 0) printf(","); - if (filters.annotation_filters[i].mode == FILTER_EXCLUDE) printf("!"); + if (filters.annotation_filters[i].filter_exclude_flag == 1) printf("!"); printf("%s", filters.annotation_filters[i].pattern); } printf(" "); @@ -1982,7 +2033,7 @@ int menu_set_filters(){ if (filter_type < 0) continue; filters.status_filters[filters.status_count].code = status; - filters.status_filters[filters.status_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE; + filters.status_filters[filters.status_count].filter_exclude_flag = (filter_type == 2) ? 1 : 0; filters.status_count++; printf("Status-Code Filter hinzugefügt. Gesamt: %d\n", filters.status_count); @@ -2004,7 +2055,7 @@ int menu_set_filters(){ if (filter_type < 0) continue; strcpy(filters.ip_filters[filters.ip_count].ip_address, ip); - filters.ip_filters[filters.ip_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE; + filters.ip_filters[filters.ip_count].filter_exclude_flag = (filter_type == 2) ? 1 : 0; filters.ip_count++; printf("IP-Filter hinzugefügt. Gesamt: %d\n", filters.ip_count); @@ -2076,7 +2127,7 @@ int menu_set_filters(){ new_time_filter.end_time.minute = end_minute; new_time_filter.end_time.second = end_second; - new_time_filter.mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE; + new_time_filter.filter_exclude_flag = (filter_type == 2) ? 1 : 0; filters.time_filters[filters.time_count] = new_time_filter; filters.time_count++; @@ -2101,7 +2152,7 @@ int menu_set_filters(){ if (filter_type < 0) continue; strcpy(filters.user_agent_filters[filters.user_agent_count].pattern, pattern); - filters.user_agent_filters[filters.user_agent_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE; + filters.user_agent_filters[filters.user_agent_count].filter_exclude_flag = (filter_type == 2) ? 1 : 0; filters.user_agent_count++; printf("User-Agent Filter hinzugefügt. Gesamt: %d\n", filters.user_agent_count); @@ -2123,7 +2174,7 @@ int menu_set_filters(){ if (filter_type < 0) continue; strcpy(filters.method_filters[filters.method_count].pattern, pattern); - filters.method_filters[filters.method_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE; + filters.method_filters[filters.method_count].filter_exclude_flag = (filter_type == 2) ? 1 : 0; filters.method_count++; printf("Method-Filter hinzugefügt. Gesamt: %d\n", filters.method_count); @@ -2145,7 +2196,7 @@ int menu_set_filters(){ if (filter_type < 0) continue; strcpy(filters.url_filters[filters.url_count].pattern, pattern); - filters.url_filters[filters.url_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE; + filters.url_filters[filters.url_count].filter_exclude_flag = (filter_type == 2) ? 1 : 0; filters.url_count++; printf("URL-Filter hinzugefügt. Gesamt: %d\n", filters.url_count); } else if (choice == 7) { @@ -2155,7 +2206,7 @@ int menu_set_filters(){ int filter_type = safe_read_integer("Auswahl: ", 1, 2); if (filter_type < 0) continue; - filters.annotation_flag_filter.mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE; + filters.annotation_flag_filter.filter_exclude_flag = (filter_type == 2) ? 1 : 0; filters.annotation_flag_filter_enabled = 1; } else if (choice == 8) { if (filters.annotation_count >= MAX_FILTERS) { @@ -2175,7 +2226,7 @@ int menu_set_filters(){ if (filter_type < 0) continue; strcpy(filters.annotation_filters[filters.annotation_count].pattern, pattern); - filters.annotation_filters[filters.annotation_count].mode = (filter_type == 2) ? FILTER_EXCLUDE : FILTER_INCLUDE; + filters.annotation_filters[filters.annotation_count].filter_exclude_flag = (filter_type == 2) ? 1 : 0; filters.annotation_count++; printf("Annotations-Filter hinzugefügt. Gesamt: %d\n", filters.annotation_count); } else if (choice == -2) { @@ -2203,32 +2254,32 @@ void menu_delete_filters(){ int filter_index = 1; for (int i = 0; i < filters.status_count; i++) { - char* mode_str = (filters.status_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; + char* mode_str = (filters.status_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen"; printf("%2d. Status-Code: %d (%s)\n", filter_index++, filters.status_filters[i].code, mode_str); } for (int i = 0; i < filters.method_count; i++) { - char* mode_str = (filters.method_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; + char* mode_str = (filters.method_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen"; printf("%2d. HTTP-Methode: \"%s\" (%s)\n", filter_index++, filters.method_filters[i].pattern, mode_str); } for (int i = 0; i < filters.ip_count; i++) { - char* mode_str = (filters.ip_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; + char* mode_str = (filters.ip_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen"; printf("%2d. IP-Adresse: %s (%s)\n", filter_index++, filters.ip_filters[i].ip_address, mode_str); } for (int i = 0; i < filters.user_agent_count; i++) { - char* mode_str = (filters.user_agent_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; + char* mode_str = (filters.user_agent_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen"; printf("%2d. User-Agent: \"%s\" (%s)\n", filter_index++, filters.user_agent_filters[i].pattern, mode_str); } for (int i = 0; i < filters.url_count; i++) { - char* mode_str = (filters.url_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; + char* mode_str = (filters.url_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen"; printf("%2d. URL-Pfad: \"%s\" (%s)\n", filter_index++, filters.url_filters[i].pattern, mode_str); } for (int i = 0; i < filters.time_count; i++) { - char* mode_str = (filters.time_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; + char* mode_str = (filters.time_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen"; printf("%2d. Zeitraum: %02d.%02d.%d %02d:%02d:%02d - %02d.%02d.%d %02d:%02d:%02d (%s)\n", filter_index++, filters.time_filters[i].start_time.day, @@ -2247,12 +2298,12 @@ void menu_delete_filters(){ } if (filters.annotation_flag_filter_enabled){ - char* mode_str = (filters.annotation_flag_filter.mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; + char* mode_str = (filters.annotation_flag_filter.filter_exclude_flag == 1) ? "ausschließen" : "einschließen"; printf("%2d. Annotierte Einträge %s", filter_index++, mode_str); } for (int i = 0; i < filters.annotation_count; i++) { - char* mode_str = (filters.annotation_filters[i].mode == FILTER_EXCLUDE) ? "ausschließen" : "einschließen"; + char* mode_str = (filters.annotation_filters[i].filter_exclude_flag == 1) ? "ausschließen" : "einschließen"; printf("%2d. Annotations-Filter: \"%s\" (%s)\n", filter_index++, filters.annotation_filters[i].pattern, mode_str); } @@ -2531,7 +2582,7 @@ void menu_show_entries(){ } // Funktionen zum setzen der Filter (existierende Datenstrukturen) -void add_parsed_status_filter(char* value, filter_mode_t mode) { +void add_parsed_status_filter(char* value, int filter_exclude_flag) { if (filters.status_count >= MAX_FILTERS) { printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); return; @@ -2539,7 +2590,7 @@ void add_parsed_status_filter(char* value, filter_mode_t mode) { // Kovertierung des Statuscodes zu long mit Error handling char* endptr; int status_code = strtol(value, &endptr, 10); - if (*endptr != '\n'){ + if (*endptr != '\0'){ printf("ERROR: Ungültiger Wert im Statuscode-Filter: %s", value); } if (status_code < 100 || status_code > 599) { @@ -2549,13 +2600,13 @@ void add_parsed_status_filter(char* value, filter_mode_t mode) { // setzen des Filters filters.status_filters[filters.status_count].code = status_code; - filters.status_filters[filters.status_count].mode = mode; + filters.status_filters[filters.status_count].filter_exclude_flag = filter_exclude_flag; filters.status_count++; - printf("DEBUG: Filter hinzugefügt: %s%d\n", mode == FILTER_EXCLUDE ? "!" : "", status_code); + if (flag_verbose) printf("DEBUG: Filter hinzugefügt: %s%d\n", filter_exclude_flag == 1 ? "!" : "", status_code); } -void add_parsed_ip_filter(char* value, filter_mode_t mode) { +void add_parsed_ip_filter(char* value, int filter_exclude_flag) { if (filters.ip_count >= MAX_FILTERS) { printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); return; @@ -2569,14 +2620,14 @@ void add_parsed_ip_filter(char* value, filter_mode_t mode) { // setzen des Filters strcpy(filters.ip_filters[filters.ip_count].ip_address, value); - filters.ip_filters[filters.ip_count].mode = mode; + filters.ip_filters[filters.ip_count].filter_exclude_flag = filter_exclude_flag; filters.ip_count++; - printf("DEBUG: IP-Adressfilter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); + if (flag_verbose) printf("DEBUG: IP-Adressfilter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value); } // gleiche Mechanik wie bei IP-Adresse -void add_parsed_method_filter(char* value, filter_mode_t mode) { +void add_parsed_method_filter(char* value, int filter_exclude_flag) { if (filters.method_count >= MAX_FILTERS) { printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); return; @@ -2588,14 +2639,14 @@ void add_parsed_method_filter(char* value, filter_mode_t mode) { } strcpy(filters.method_filters[filters.method_count].pattern, value); - filters.method_filters[filters.method_count].mode = mode; + filters.method_filters[filters.method_count].filter_exclude_flag = filter_exclude_flag; filters.method_count++; - printf("DEBUG: Methoden-Filter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); + if (flag_verbose) printf("DEBUG: Methoden-Filter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value); } // gleiche Mechanik wie bei IP-Adresse -void add_parsed_useragent_filter(char* value, filter_mode_t mode) { +void add_parsed_useragent_filter(char* value, int filter_exclude_flag) { if (filters.user_agent_count >= MAX_FILTERS) { printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); return; @@ -2607,14 +2658,14 @@ void add_parsed_useragent_filter(char* value, filter_mode_t mode) { } strcpy(filters.user_agent_filters[filters.user_agent_count].pattern, value); - filters.user_agent_filters[filters.user_agent_count].mode = mode; + filters.user_agent_filters[filters.user_agent_count].filter_exclude_flag = filter_exclude_flag; filters.user_agent_count++; - printf("DEBUG: User Agent Filter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); + if (flag_verbose) printf("DEBUG: User Agent Filter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value); } // gleiche Mechanik wie bei IP-Adresse -void add_parsed_url_filter(char* value, filter_mode_t mode) { +void add_parsed_url_filter(char* value, int filter_exclude_flag) { if (filters.url_count >= MAX_FILTERS) { printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); return; @@ -2626,14 +2677,14 @@ void add_parsed_url_filter(char* value, filter_mode_t mode) { } strcpy(filters.url_filters[filters.url_count].pattern, value); - filters.url_filters[filters.url_count].mode = mode; + filters.url_filters[filters.url_count].filter_exclude_flag = filter_exclude_flag; filters.url_count++; - printf("DEBUG: URL/Payload-Filter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); + if (flag_verbose) printf("DEBUG: URL/Payload-Filter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value); } // Parsen des Timestamp-Filters ist etwas komplexer, da er in die Datenstruktur geschrieben werden muss. -void add_parsed_timerange_filter(char* value, filter_mode_t mode) { +void add_parsed_timerange_filter(char* value, int filter_exclude_flag) { if (filters.time_count >= MAX_FILTERS) { printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); return; @@ -2760,14 +2811,14 @@ void add_parsed_timerange_filter(char* value, filter_mode_t mode) { new_time_filter.end_time.minute = end_minute; new_time_filter.end_time.second = end_second; - new_time_filter.mode = mode; + new_time_filter.filter_exclude_flag = filter_exclude_flag; // Logik hier: der neue Filter wird stets an einen neuen Index geschrieben. Dieser ergibt sich aus der aktuellen ANZAHL der existierenden Zeitfilter. Das funktioniert, weil der index bei 0 beginnt filters.time_filters[filters.time_count] = new_time_filter; filters.time_count++; - printf("DEBUG: Zeitraum-Filter hinzugefügt (%s): %04d-%02d-%02d %02d:%02d:%02d bis %04d-%02d-%02d %02d:%02d:%02d\n", - mode == FILTER_EXCLUDE ? "ausschließen" : "einschließen", + if (flag_verbose) printf("DEBUG: Zeitraum-Filter hinzugefügt (%s): %04d-%02d-%02d %02d:%02d:%02d bis %04d-%02d-%02d %02d:%02d:%02d\n", + filter_exclude_flag == 1 ? "ausschließen" : "einschließen", new_time_filter.start_time.year, new_time_filter.start_time.month, new_time_filter.start_time.day, new_time_filter.start_time.hour, new_time_filter.start_time.minute, new_time_filter.start_time.second, new_time_filter.end_time.year, new_time_filter.end_time.month, new_time_filter.end_time.day, @@ -2775,25 +2826,25 @@ void add_parsed_timerange_filter(char* value, filter_mode_t mode) { } // recht einfache Mechanik für den Bool´schen Filter für annotierte Einträge -void add_parsed_annotated_filter(char* value, filter_mode_t mode) { +void add_parsed_annotated_filter(char* value, int filter_exclude_flag) { if (strcmp(value, "true") == 0) { filters.annotation_flag_filter.annotation_flag_is_present = 1; - filters.annotation_flag_filter.mode = mode; + filters.annotation_flag_filter.filter_exclude_flag = filter_exclude_flag; filters.annotation_flag_filter_enabled = 1; - printf("DEBUG: Annotations-Flag-Filter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); + if (flag_verbose) printf("DEBUG: Annotations-Flag-Filter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value); // falls doch mal jemand false eingibt } else if (strcmp(value, "false") == 0) { filters.annotation_flag_filter.annotation_flag_is_present = 0; - filters.annotation_flag_filter.mode = mode; + filters.annotation_flag_filter.filter_exclude_flag = filter_exclude_flag; filters.annotation_flag_filter_enabled = 1; - printf("DEBUG: Annotations-Flag-Filter hinzugefügt: %s%s\n", mode == FILTER_EXCLUDE ? "!" : "", value); + if (flag_verbose) printf("DEBUG: Annotations-Flag-Filter hinzugefügt: %s%s\n", filter_exclude_flag == 1 ? "!" : "", value); } else { printf("WARNING: Ungültiger Wert für --annotated Filter: %s (nur 'true' unterstützt)\n", value); } } // Wieder gleiche Mechanik wie beim User Agent etc -void add_parsed_annotation_filter(char* value, filter_mode_t mode) { +void add_parsed_annotation_filter(char* value, int filter_exclude_flag) { if (filters.annotation_count >= MAX_FILTERS) { printf("WARNING: MAX_FILTERS überschritten, ignoriere: %s\n", value); return; @@ -2805,11 +2856,11 @@ void add_parsed_annotation_filter(char* value, filter_mode_t mode) { } strcpy(filters.annotation_filters[filters.annotation_count].pattern, value); - filters.annotation_filters[filters.annotation_count].mode = mode; + filters.annotation_filters[filters.annotation_count].filter_exclude_flag = filter_exclude_flag; filters.annotation_count++; - printf("DEBUG: Annotations-Filter hinzugefügt: %s%s\n", - mode == FILTER_EXCLUDE ? "!" : "", value); + if (flag_verbose) printf("DEBUG: Annotations-Filter hinzugefügt: %s%s\n", + filter_exclude_flag == 1 ? "!" : "", value); } // Funktion zum Parsen der Filter-Werte, die mit --= übergeben werden. @@ -2828,31 +2879,31 @@ void parse_filter_values(char* values_str, char* filter_type) { // Sollte der Nutzer Leerzeichen verwendet haben, müssen diese übersprungen werden while (*token == ' ') token++; // setzen des Modus, Standard inklusiv - filter_mode_t mode = FILTER_INCLUDE; + int filter_exclude_flag = 0; // ..mit !-Präfix exklusiv. if (*token == '!') { - mode = FILTER_EXCLUDE; + filter_exclude_flag = 1; token++; // den Pointer vom ! weiteriterieren, dieser ist nicht Teil des Filters } if (strlen(token) > 0) { // wenn das token Werte hat, werden die entsprechenden Funktionen aufgerufen, die die Filter setzen if (strcmp(filter_type, "status") == 0) { - add_parsed_status_filter(token, mode); + add_parsed_status_filter(token, filter_exclude_flag); } else if (strcmp(filter_type, "ip") == 0) { - add_parsed_ip_filter(token, mode); + add_parsed_ip_filter(token, filter_exclude_flag); } else if (strcmp(filter_type, "method") == 0) { - add_parsed_method_filter(token, mode); + add_parsed_method_filter(token, filter_exclude_flag); } else if (strcmp(filter_type, "useragent") == 0) { - add_parsed_useragent_filter(token, mode); + add_parsed_useragent_filter(token, filter_exclude_flag); } else if (strcmp(filter_type, "url") == 0) { - add_parsed_url_filter(token, mode); + add_parsed_url_filter(token, filter_exclude_flag); } else if (strcmp(filter_type, "timerange") == 0) { - add_parsed_timerange_filter(token, mode); + add_parsed_timerange_filter(token, filter_exclude_flag); } else if (strcmp(filter_type, "annotated") == 0) { - add_parsed_annotated_filter(token, mode); + add_parsed_annotated_filter(token, filter_exclude_flag); } else if (strcmp(filter_type, "annotation") == 0) { - add_parsed_annotation_filter(token, mode); + add_parsed_annotation_filter(token, filter_exclude_flag); } } // nächste Iteration - nächstes token einlesen, damit die while-Schleife weiteriteriert @@ -2903,10 +2954,10 @@ int parse_filter_argument(char* arg) { } else if (strstr(filter_type, "mode") != NULL) { if (strstr(values, "and") != NULL || strstr(values, "AND") != NULL) { filters.combination_mode = 0; - printf("DEBUG: AND-Modus gesetzt\n"); + if (flag_verbose) printf("DEBUG: AND-Modus gesetzt\n"); } else if (strstr(values, "or") != NULL || strstr(values, "OR") != NULL) { filters.combination_mode = 1; - printf("DEBUG: OR-Modus gesetzt\n"); + if (flag_verbose) printf("DEBUG: OR-Modus gesetzt\n"); } else { printf("WARNING: ungültiger Modus-Wert: %s ('and' oder 'oder' möglich)\n", values); } @@ -3010,6 +3061,7 @@ int main(int argc, char* argv[]) { int flag_interactive = 0; int flag_export = 0; int flag_help = 0; + // int flag_verbose = 0; - global definiert char export_filename[90]; int flag_has_filename = 0; @@ -3039,6 +3091,8 @@ int main(int argc, char* argv[]) { } else if (strcmp(argv[i], "-h")==0) { flag_help = 1; + } else if (strcmp(argv[i], "-v")==0) { + flag_verbose = 1; } } } @@ -3074,7 +3128,7 @@ int main(int argc, char* argv[]) { } else if (choice == 3) { export_filtered_entries(0); } else if (choice == 4) { - printf("Programmende\n"); + if (flag_verbose) printf("DEBUG: Programmende\n"); break; } else if (choice == -4) { break;