From 43fab73d71282c2ffabde4d706cfe952bae571b2 Mon Sep 17 00:00:00 2001 From: epi Date: Sat, 30 Jan 2021 20:43:31 -0600 Subject: [PATCH] moved FeroxMessage from lib.rs --- src/ferox_message.rs | 121 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 119 ++---------------------------------------- src/logger.rs | 23 ++++---- 3 files changed, 138 insertions(+), 125 deletions(-) create mode 100644 src/ferox_message.rs diff --git a/src/ferox_message.rs b/src/ferox_message.rs new file mode 100644 index 0000000..c8b4142 --- /dev/null +++ b/src/ferox_message.rs @@ -0,0 +1,121 @@ +use anyhow::Context; +use console::{style, Color}; + +use crate::traits::FeroxSerialize; +use crate::utils::fmt_err; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Default)] +/// Representation of a log entry, can be represented as a human readable string or JSON +pub struct FeroxMessage { + #[serde(rename = "type")] + /// Name of this type of struct, used for serialization, i.e. `{"type":"log"}` + pub(crate) kind: String, + + /// The log message + pub(crate) message: String, + + /// The log level + pub(crate) level: String, + + /// The number of seconds elapsed since the scan started + pub(crate) time_offset: f32, + + /// The module from which log::* was called + pub(crate) module: String, +} + +/// Implementation of FeroxMessage +impl FeroxSerialize for FeroxMessage { + /// Create a string representation of the log message + /// + /// ex: 301 10l 16w 173c https://localhost/api + fn as_str(&self) -> String { + let (level_name, level_color) = match self.level.as_str() { + "ERROR" => ("ERR", Color::Red), + "WARN" => ("WRN", Color::Red), + "INFO" => ("INF", Color::Cyan), + "DEBUG" => ("DBG", Color::Yellow), + "TRACE" => ("TRC", Color::Magenta), + "WILDCARD" => ("WLD", Color::Cyan), + _ => ("UNK", Color::White), + }; + + format!( + "{} {:10.03} {} {}\n", + style(level_name).bg(level_color).black(), + style(self.time_offset).dim(), + self.module, + style(&self.message).dim(), + ) + } + + /// Create an NDJSON representation of the log message + /// + /// (expanded for clarity) + /// ex: + /// { + /// "type": "log", + /// "message": "Sent https://localhost/api to file handler", + /// "level": "DEBUG", + /// "time_offset": 0.86333454, + /// "module": "feroxbuster::reporter" + /// }\n + fn as_json(&self) -> anyhow::Result { + let mut json = serde_json::to_string(&self).with_context(|| { + fmt_err(&format!( + "Could not convert {}:{} to JSON", + self.level, self.message + )) + })?; + json.push('\n'); + Ok(json) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + /// test as_str method of FeroxMessage + fn ferox_message_as_str_returns_string_with_newline() { + let message = FeroxMessage { + message: "message".to_string(), + module: "utils".to_string(), + time_offset: 1.0, + level: "INFO".to_string(), + kind: "log".to_string(), + }; + let message_str = message.as_str(); + + assert!(message_str.contains("INF")); + assert!(message_str.contains("1.000")); + assert!(message_str.contains("utils")); + assert!(message_str.contains("message")); + assert!(message_str.ends_with('\n')); + } + + #[test] + /// test as_json method of FeroxMessage + fn ferox_message_as_json_returns_json_representation_of_ferox_message_with_newline() { + let message = FeroxMessage { + message: "message".to_string(), + module: "utils".to_string(), + time_offset: 1.0, + level: "INFO".to_string(), + kind: "log".to_string(), + }; + + let message_str = message.as_json().unwrap(); + + let error_margin = f32::EPSILON; + + let json: FeroxMessage = serde_json::from_str(&message_str).unwrap(); + assert_eq!(json.module, message.module); + assert_eq!(json.message, message.message); + assert!((json.time_offset - message.time_offset).abs() < error_margin); + assert_eq!(json.level, message.level); + assert_eq!(json.kind, message.kind); + } +} diff --git a/src/lib.rs b/src/lib.rs index 1682856..24573de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,13 @@ -use anyhow::{Context, Result}; -use console::{style, Color}; +use anyhow::Result; use reqwest::StatusCode; -use serde::{Deserialize, Serialize}; use tokio::{ sync::mpsc::{UnboundedReceiver, UnboundedSender}, task::JoinHandle, }; -use crate::{event_handlers::Command, traits::FeroxSerialize, utils::fmt_err}; +// todo should FeroxSerialize be imported from traits all the places its used? currently most do crate::FeroxSerialize +// the other option would be to expose all the Ferox stuff here and make them internally private +use crate::{event_handlers::Command, traits::FeroxSerialize}; pub mod banner; pub mod config; @@ -27,6 +27,7 @@ mod extractor; mod macros; mod ferox_url; mod ferox_response; +mod ferox_message; /// Alias for tokio::sync::mpsc::UnboundedSender pub(crate) type CommandSender = UnboundedSender; @@ -88,74 +89,6 @@ pub const DEFAULT_STATUS_CODES: [StatusCode; 9] = [ /// Expected location is in the same directory as the feroxbuster binary. pub const DEFAULT_CONFIG_NAME: &str = "ferox-config.toml"; -#[derive(Serialize, Deserialize, Default)] -/// Representation of a log entry, can be represented as a human readable string or JSON -pub struct FeroxMessage { - #[serde(rename = "type")] - /// Name of this type of struct, used for serialization, i.e. `{"type":"log"}` - kind: String, - - /// The log message - pub message: String, - - /// The log level - pub level: String, - - /// The number of seconds elapsed since the scan started - pub time_offset: f32, - - /// The module from which log::* was called - pub module: String, -} - -/// Implementation of FeroxMessage -impl FeroxSerialize for FeroxMessage { - /// Create a string representation of the log message - /// - /// ex: 301 10l 16w 173c https://localhost/api - fn as_str(&self) -> String { - let (level_name, level_color) = match self.level.as_str() { - "ERROR" => ("ERR", Color::Red), - "WARN" => ("WRN", Color::Red), - "INFO" => ("INF", Color::Cyan), - "DEBUG" => ("DBG", Color::Yellow), - "TRACE" => ("TRC", Color::Magenta), - "WILDCARD" => ("WLD", Color::Cyan), - _ => ("UNK", Color::White), - }; - - format!( - "{} {:10.03} {} {}\n", - style(level_name).bg(level_color).black(), - style(self.time_offset).dim(), - self.module, - style(&self.message).dim(), - ) - } - - /// Create an NDJSON representation of the log message - /// - /// (expanded for clarity) - /// ex: - /// { - /// "type": "log", - /// "message": "Sent https://localhost/api to file handler", - /// "level": "DEBUG", - /// "time_offset": 0.86333454, - /// "module": "feroxbuster::reporter" - /// }\n - fn as_json(&self) -> Result { - let mut json = serde_json::to_string(&self).with_context(|| { - fmt_err(&format!( - "Could not convert {}:{} to JSON", - self.level, self.message - )) - })?; - json.push('\n'); - Ok(json) - } -} - #[cfg(test)] mod tests { use super::*; @@ -180,46 +113,4 @@ mod tests { fn default_version() { assert_eq!(VERSION, env!("CARGO_PKG_VERSION")); } - - #[test] - /// test as_str method of FeroxMessage - fn ferox_message_as_str_returns_string_with_newline() { - let message = FeroxMessage { - message: "message".to_string(), - module: "utils".to_string(), - time_offset: 1.0, - level: "INFO".to_string(), - kind: "log".to_string(), - }; - let message_str = message.as_str(); - - assert!(message_str.contains("INF")); - assert!(message_str.contains("1.000")); - assert!(message_str.contains("utils")); - assert!(message_str.contains("message")); - assert!(message_str.ends_with('\n')); - } - - #[test] - /// test as_json method of FeroxMessage - fn ferox_message_as_json_returns_json_representation_of_ferox_message_with_newline() { - let message = FeroxMessage { - message: "message".to_string(), - module: "utils".to_string(), - time_offset: 1.0, - level: "INFO".to_string(), - kind: "log".to_string(), - }; - - let message_str = message.as_json().unwrap(); - - let error_margin = f32::EPSILON; - - let json: FeroxMessage = serde_json::from_str(&message_str).unwrap(); - assert_eq!(json.module, message.module); - assert_eq!(json.message, message.message); - assert!((json.time_offset - message.time_offset).abs() < error_margin); - assert_eq!(json.level, message.level); - assert_eq!(json.kind, message.kind); - } } diff --git a/src/logger.rs b/src/logger.rs index 86be8b8..ee3d7ee 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -1,18 +1,19 @@ use std::env; use std::fs::OpenOptions; -use std::time::Instant; - -use env_logger::Builder; - -use crate::utils::write_to; -use crate::{ - config::{Configuration, PROGRESS_PRINTER}, - utils::fmt_err, - FeroxMessage, FeroxSerialize, -}; -use anyhow::{Context, Result}; use std::io::BufWriter; use std::sync::{Arc, RwLock}; +use std::time::Instant; + +use anyhow::{Context, Result}; +use env_logger::Builder; + +use crate::{ + config::{Configuration, PROGRESS_PRINTER}, + ferox_message::FeroxMessage, + utils::fmt_err, + utils::write_to, + FeroxSerialize, +}; /// Create a customized instance of /// [env_logger::Logger](https://docs.rs/env_logger/latest/env_logger/struct.Logger.html)