mod first_run;
pub use first_run::run_first_time_setup;
use std::{fs::File, io::Read};
use crate::cli_pretty_printing;
use crate::cli_pretty_printing::panic_failure_both_input_and_fail_provided;
use crate::config::{get_config_file_into_struct, load_wordlist, Config};
use clap::Parser;
use log::trace;
#[derive(Parser)]
#[command(author = "Bee <bee@skerritt.blog>", about, long_about = None)]
pub struct Opts {
#[arg(short, long)]
text: Option<String>,
#[arg(short, long, action = clap::ArgAction::Count)]
verbose: u8,
#[arg(short, long)]
disable_human_checker: bool,
#[arg(short, long)]
cracking_timeout: Option<u32>,
#[arg(short, long)]
api_mode: Option<bool>,
#[arg(short, long)]
file: Option<String>,
#[arg(short, long)]
regex: Option<String>,
#[arg(
long,
help = "Path to a wordlist file with newline-separated words for exact matching"
)]
wordlist: Option<String>,
#[arg(long)]
top_results: bool,
#[arg(long)]
enable_enhanced_detection: bool,
}
pub fn parse_cli_args() -> (String, Config) {
let mut opts: Opts = Opts::parse();
let min_log_level = match opts.verbose {
0 => "Warn",
1 => "Info",
2 => "Debug",
_ => "Trace",
};
env_logger::init_from_env(
env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, min_log_level),
);
if opts.file.is_some() && opts.text.is_some() {
panic_failure_both_input_and_fail_provided();
}
let input_text: String = if opts.file.is_some() {
read_and_parse_file(opts.file.unwrap())
} else {
opts.text
.expect("Error. No input was provided. Please use ares --help")
};
opts.text = None;
opts.file = None;
trace!("Program was called with CLI 😉");
trace!("Parsed the arguments");
trace!("The inputted text is {}", &input_text);
cli_args_into_config_struct(opts, input_text)
}
pub fn read_and_parse_file(file_path: String) -> String {
let mut file = File::open(file_path).unwrap();
let mut contents = String::new();
file.read_to_string(&mut contents).unwrap();
if contents.ends_with(['\n', '\r']) {
contents.strip_suffix(['\n', '\r']).unwrap().to_owned()
} else {
contents
}
}
fn cli_args_into_config_struct(opts: Opts, text: String) -> (String, Config) {
let mut config = get_config_file_into_struct();
config.verbose = opts.verbose;
config.human_checker_on = !opts.disable_human_checker;
if let Some(timeout) = opts.cracking_timeout {
config.timeout = timeout;
}
if let Some(api_mode) = opts.api_mode {
config.api_mode = api_mode;
}
if let Some(regex) = opts.regex {
config.regex = Some(regex);
}
if let Some(wordlist_path) = opts.wordlist {
config.wordlist_path = Some(wordlist_path.clone());
match load_wordlist(&wordlist_path) {
Ok(wordlist) => {
config.wordlist = Some(wordlist);
}
Err(e) => {
eprintln!("Can't load wordlist at '{}': {}", wordlist_path, e);
std::process::exit(1);
}
}
}
config.top_results = opts.top_results;
if config.top_results {
config.human_checker_on = false;
}
if opts.enable_enhanced_detection {
config.enhanced_detection = true;
eprintln!(
"{}",
cli_pretty_printing::statement("Enhanced detection enabled.", None)
);
}
(text, config)
}