mirror of
https://github.com/epi052/feroxbuster.git
synced 2026-06-08 19:31:12 -03:00
cleaned up a few things during PR review
This commit is contained in:
@@ -325,7 +325,12 @@ impl Configuration {
|
||||
.map(|code| {
|
||||
StatusCode::from_bytes(code.as_bytes())
|
||||
.unwrap_or_else(|e| {
|
||||
eprintln!("[!] Error encountered: {}", e); // todo normalize error output
|
||||
eprintln!(
|
||||
"{} {}: {}",
|
||||
status_colorizer("ERROR"),
|
||||
module_colorizer("Configuration::new"),
|
||||
e
|
||||
);
|
||||
exit(1)
|
||||
})
|
||||
.as_u16()
|
||||
@@ -347,7 +352,12 @@ impl Configuration {
|
||||
.unwrap() // already known good
|
||||
.map(|size| {
|
||||
size.parse::<u64>().unwrap_or_else(|e| {
|
||||
eprintln!("[!] Error encountered: {}", e); // todo normalize error output
|
||||
eprintln!(
|
||||
"{} {}: {}",
|
||||
status_colorizer("ERROR"),
|
||||
module_colorizer("Configuration::new"),
|
||||
e
|
||||
);
|
||||
exit(1)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::config::PROGRESS_PRINTER;
|
||||
use crate::config::{CONFIGURATION, PROGRESS_PRINTER};
|
||||
use crate::reporter::{get_cached_file_handle, safe_file_write};
|
||||
use console::{style, Color};
|
||||
use env_logger::Builder;
|
||||
@@ -39,7 +39,7 @@ pub fn initialize(verbosity: u8) {
|
||||
//
|
||||
// The workaround was to have a RwLock around the file and allow both the logger and the
|
||||
// file handler to both write independent of each other.
|
||||
let locked_file = get_cached_file_handle();
|
||||
let locked_file = get_cached_file_handle(&CONFIGURATION.output);
|
||||
|
||||
builder
|
||||
.format(move |_, record| {
|
||||
|
||||
38
src/main.rs
38
src/main.rs
@@ -120,16 +120,18 @@ async fn get_targets() -> FeroxResult<Vec<String>> {
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// setup logging based on the number of -v's used
|
||||
logger::initialize(CONFIGURATION.verbosity);
|
||||
|
||||
// can't trace main until after logger is initialized
|
||||
log::trace!("enter: main");
|
||||
log::debug!("{:#?}", *CONFIGURATION);
|
||||
|
||||
let save_output = !CONFIGURATION.output.is_empty(); // was -o used?
|
||||
|
||||
let (tx_term, tx_file, term_handle, file_handle) =
|
||||
reporter::initialize(&CONFIGURATION.output, save_output);
|
||||
|
||||
logger::initialize(CONFIGURATION.verbosity);
|
||||
|
||||
log::trace!("enter: main");
|
||||
log::debug!("{:#?}", *CONFIGURATION);
|
||||
|
||||
// get targets from command line or stdin
|
||||
let targets = match get_targets().await {
|
||||
Ok(t) => t,
|
||||
@@ -157,9 +159,10 @@ async fn main() {
|
||||
// discard non-responsive targets
|
||||
let live_targets = heuristics::connectivity_test(&targets).await;
|
||||
|
||||
// kick off a scan against any targets determined to be responsive
|
||||
match scan(live_targets, tx_term.clone(), tx_file.clone()).await {
|
||||
Ok(_) => {
|
||||
log::info!("Done");
|
||||
log::info!("All scans complete!");
|
||||
}
|
||||
Err(e) => log::error!("An error occurred: {}", e),
|
||||
};
|
||||
@@ -168,32 +171,37 @@ async fn main() {
|
||||
drop(tx_term);
|
||||
log::trace!("dropped terminal output handler's transmitter");
|
||||
|
||||
log::trace!("awaiting terminal output receiver");
|
||||
log::trace!("awaiting terminal output handler's receiver");
|
||||
// after dropping tx, we can await the future where rx lived
|
||||
match term_handle.await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::error!("error awaiting terminal output's receiver: {}", e);
|
||||
log::error!("error awaiting terminal output handler's receiver: {}", e);
|
||||
}
|
||||
}
|
||||
log::trace!("done awaiting terminal output receiver");
|
||||
log::trace!("done awaiting terminal output handler's receiver");
|
||||
|
||||
log::trace!("tx_file: {:?}", tx_file);
|
||||
// the same drop/await process used on the terminal handler is repeated for the file handler
|
||||
// we drop the file transmitter every time, because it's created no matter what
|
||||
drop(tx_file);
|
||||
|
||||
log::trace!("dropped file output handler's transmitter");
|
||||
|
||||
if save_output {
|
||||
log::trace!("awaiting file output receiver");
|
||||
// but we only await if -o was specified
|
||||
log::trace!("awaiting file output handler's receiver");
|
||||
match file_handle.unwrap().await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::error!("error awaiting file output's receiver: {}", e);
|
||||
log::error!("error awaiting file output handler's receiver: {}", e);
|
||||
}
|
||||
}
|
||||
log::trace!("done awaiting file output receiver");
|
||||
log::trace!("done awaiting file output handler's receiver");
|
||||
}
|
||||
|
||||
PROGRESS_PRINTER.finish();
|
||||
|
||||
log::trace!("exit: main");
|
||||
|
||||
// clean-up function for the MultiProgress bar; must be called last in order to still see
|
||||
// the final trace message above
|
||||
PROGRESS_PRINTER.finish();
|
||||
}
|
||||
|
||||
@@ -9,7 +9,12 @@ use std::{fs, io};
|
||||
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
/// Singleton buffered file behind an Arc/RwLock; used for file writes from two locations:
|
||||
/// - [logger::initialize](../logger/fn.initialize.html) (specifically a closure on the global logger instance)
|
||||
/// - `reporter::spawn_file_handler`
|
||||
pub static mut LOCKED_FILE: Option<Arc<RwLock<io::BufWriter<fs::File>>>> = None;
|
||||
|
||||
/// An initializer Once variable used to create `LOCKED_FILE`
|
||||
static INIT: Once = Once::new();
|
||||
|
||||
// Accessing a `static mut` is unsafe much of the time, but if we do so
|
||||
@@ -18,18 +23,17 @@ static INIT: Once = Once::new();
|
||||
//
|
||||
// This function will only call `open_file` once, and will
|
||||
// otherwise always return the value returned from the first invocation.
|
||||
pub fn get_cached_file_handle() -> Option<Arc<RwLock<io::BufWriter<fs::File>>>> {
|
||||
pub fn get_cached_file_handle(filename: &str) -> Option<Arc<RwLock<io::BufWriter<fs::File>>>> {
|
||||
unsafe {
|
||||
INIT.call_once(|| {
|
||||
LOCKED_FILE = open_file(&CONFIGURATION.output);
|
||||
LOCKED_FILE = open_file(&filename);
|
||||
});
|
||||
LOCKED_FILE.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates all required output handlers (terminal, file) and returns
|
||||
/// the transmitter side of an mpsc and the primary output handler's JoinHandle
|
||||
/// to be awaited
|
||||
/// the transmitter sides of each mpsc along with each receiver's future's JoinHandle to be awaited
|
||||
///
|
||||
/// Any other module that needs to write a Response to stdout or output results to a file should
|
||||
/// be passed a clone of the appropriate returned transmitter
|
||||
@@ -133,7 +137,7 @@ async fn spawn_terminal_reporter(
|
||||
/// The consumer simply receives responses and writes them to the given output file if they meet
|
||||
/// the given reporting criteria
|
||||
async fn spawn_file_reporter(mut report_channel: UnboundedReceiver<String>, output_file: &str) {
|
||||
let buffered_file = match get_cached_file_handle() {
|
||||
let buffered_file = match get_cached_file_handle(&CONFIGURATION.output) {
|
||||
Some(file) => file,
|
||||
None => {
|
||||
log::trace!("exit: spawn_file_reporter");
|
||||
@@ -212,3 +216,15 @@ pub fn safe_file_write(contents: &str, locked_file: Arc<RwLock<io::BufWriter<fs:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
/// asserts that an empty string for a filename returns None
|
||||
fn reporter_get_cached_file_handle_without_filename_returns_none() {
|
||||
let _used = get_cached_file_handle(&"").unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ async fn try_recursion(
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
"could not send {}/ to recursion handler: {}",
|
||||
"Could not send {}/ to recursion handler: {}",
|
||||
response.url(),
|
||||
e
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user