use crate::error::Error;
use crate::ufw_log::UfwLog;
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::str::FromStr;
pub fn read_lines(path: impl AsRef<Path>) -> Result<Vec<String>, Error> {
let file = File::open(path);
if file.is_err() {
return Err(Error::from(file.err().unwrap()));
}
BufReader::new(file?)
.lines()
.map(|line| line.map_err(Error::from))
.collect::<Result<Vec<String>, Error>>()
}
pub fn split_by_space(log: &str) -> Vec<&str> {
log.split(" ").filter(|&x| !x.is_empty()).collect()
}
pub fn to_hashmap(log: &str) -> HashMap<&str, String> {
let split_log = split_by_space(log);
let mut associative = HashMap::new();
let mut is_event_range = false; let mut event_name = vec![];
associative.insert("origin", log.to_owned());
for (index, value) in split_log.iter().enumerate() {
if value.contains("=") {
let key_and_value: Vec<&str> = value.split("=").collect();
associative.insert(
key_and_value.first().unwrap().trim(),
key_and_value.get(1).unwrap().to_string(),
);
continue;
}
match index {
0 => {
associative.insert("month", value.to_string());
}
1 => {
associative.insert("day", value.to_string());
}
2 => {
associative.insert("time", value.to_string());
}
3 => {
associative.insert("hostname", value.to_string());
}
5 => {
if value.len() == 1 {
associative.insert("uptime", remove_brackets(split_log.get(6).unwrap()));
} else {
associative.insert("uptime", remove_brackets(value));
}
}
_ => {
if index <= 9 && index > 6 {
if value.contains("]") {
is_event_range = false;
event_name.push(remove_brackets(value));
associative.insert("event", event_name.join(" ").trim().to_string());
continue;
}
if is_event_range {
event_name.push(value.parse().unwrap());
}
if value.contains("[UFW") {
is_event_range = true;
}
}
}
};
match value.trim() {
"SYN" => associative.insert("syn", "1".to_string()),
"ACK" => associative.insert("ack", "1".to_string()),
"FIN" => associative.insert("fin", "1".to_string()),
"RST" => associative.insert("rst", "1".to_string()),
"PSH" => associative.insert("psh", "1".to_string()),
"CWR" => associative.insert("cwr", "1".to_string()),
"ECE" => associative.insert("ece", "1".to_string()),
"DF" => associative.insert("df", "1".to_string()),
_ => None,
};
}
associative
}
fn remove_brackets(string: &str) -> String {
string.replace("[", "").replace("]", "")
}
pub fn get_ufwlog_vec(path: impl AsRef<Path>) -> Result<Vec<UfwLog>, Error> {
let log_by_line = read_lines(path)?;
let mut ufw_log_vec: Vec<UfwLog> = vec![];
for log in log_by_line.iter() {
match UfwLog::from_str(log) {
Ok(log) => ufw_log_vec.push(log),
Err(e) => return Err(e),
}
}
Ok(ufw_log_vec)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_split() {
let some_log: String = String::from("Apr 11 20:28:26");
assert_eq!(split_by_space(&some_log), vec!["Apr", "11", "20:28:26"]);
}
#[test]
fn test_split_has_empty_string() {
let some_log: String = String::from("Apr 7 20:28:26");
assert_eq!(split_by_space(&some_log), vec!["Apr", "7", "20:28:26"]);
}
#[test]
fn test_remove_brackets() {
let string: &str = "[UFW LOG]";
assert_eq!(remove_brackets(string), String::from("UFW LOG"));
}
}