Use new arguments handling implementation.

This commit is contained in:
Eduard Tolosa 2024-10-11 04:24:02 -05:00
parent 2888858d4e
commit 17ea7f983b
2 changed files with 60 additions and 113 deletions

36
src/args.rs Normal file
View file

@ -0,0 +1,36 @@
use clap::Parser;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Cli {
#[clap(short, long, default_value = "50")]
/// Number of threads to use
pub threads: usize,
#[clap(long, default_value = "3")]
/// Timeout in seconds
pub timeout: u64,
#[clap(short, long)]
/// Show HTTP status codes
pub show_codes: bool,
#[clap(short, long)]
/// Domain to check - can be omitted if using stdin
pub domain: Option<String>,
#[clap(short, long, default_value = "1")]
/// Number of retries
pub retries: usize,
#[clap(short = 'L', long, default_value = "10")]
/// Maximum number of redirects
pub max_redirects: usize,
#[clap(short, long)]
/// Enable bruteforce mode
pub bruteforce: bool,
#[clap(short, long)]
/// Filter status codes. A comma separated list can be used
pub filter_codes: Option<String>,
#[clap(short, long)]
/// Exclude status codes. A comma separated list can be used
pub exclude_codes: Option<String>,
#[clap(short, long)]
/// Quiet mode. This will suppress all fancy output except for the final results
pub quiet: bool,
}

View file

@ -1,6 +1,6 @@
use {
clap::{value_t, App, Arg},
fhc::{httplib, structs::LibOptions, utils},
clap::Parser,
fhc::{args, httplib, structs::LibOptions, utils},
std::collections::HashSet,
tokio::io::{self, AsyncReadExt},
};
@ -8,114 +8,16 @@ use {
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Eval args
let matches = App::new("FHC")
.version(clap::crate_version!())
.author("Eduard Tolosa <edu4rdshl@protonmail.com>")
.about("Fast HTTP Checker.")
.arg(
Arg::with_name("threads")
.short("t")
.long("threads")
.takes_value(true)
.help("Number of threads. Default: 50"),
)
.arg(
Arg::with_name("timeout")
.long("timeout")
.takes_value(true)
.help("Timeout in seconds. Default: 3"),
)
.arg(
Arg::with_name("show-codes")
.short("s")
.long("show-codes")
.takes_value(false)
.help("Show status codes for discovered hosts."),
)
.arg(
Arg::with_name("domain")
.short("d")
.long("domain")
.takes_value(true)
.help("Target domain. When it's specified, a wordlist can be used from stdin for bruteforcing."),
)
.arg(
Arg::with_name("retries")
.short("r")
.long("retries")
.takes_value(true)
.help("Max number of http probes per target."),
).arg(
Arg::with_name("max-redirects")
.short("L")
.long("max-redirects")
.takes_value(true)
.help("Max number of redirects. Default: 0"),
)
.arg(
Arg::with_name("bruteforce")
.short("b")
.long("bruteforce")
.takes_value(false)
.help("Bruteforce subdomains."),
)
.arg(
Arg::with_name("1xx")
.short("1")
.long("1xx")
.takes_value(false)
.help("Show URLs with 100-199 response codes only."),
)
.arg(
Arg::with_name("2xx")
.short("2")
.long("2xx")
.takes_value(false)
.help("Show URLs with 200-299 response codes only."),
)
.arg(
Arg::with_name("3xx")
.short("3")
.long("3xx")
.takes_value(false)
.help("Show URLs with 300-399 response codes only."),
)
.arg(
Arg::with_name("4xx")
.short("4")
.long("4xx")
.takes_value(false)
.help("Show URLs with 400-499 response codes only."),
)
.arg(
Arg::with_name("5xx")
.short("5")
.long("5xx")
.takes_value(false)
.help("Show URLs with 500-599 response codes only."),
)
.get_matches();
let args = args::Cli::parse();
// Assign values or use defaults
let conditional_response_code = if matches.is_present("1xx") {
100
} else if matches.is_present("2xx") {
200
} else if matches.is_present("3xx") {
300
} else if matches.is_present("4xx") {
400
} else if matches.is_present("5xx") {
500
} else {
0
};
let threads = value_t!(matches.value_of("threads"), usize).unwrap_or_else(|_| 50);
let retries = value_t!(matches.value_of("retries"), usize).unwrap_or_else(|_| 1);
let timeout = value_t!(matches.value_of("timeout"), u64).unwrap_or_else(|_| 3);
let max_redirects = value_t!(matches.value_of("max-redirects"), usize).unwrap_or_else(|_| 0);
let filter_codes = args.filter_codes;
let exclude_codes = args.exclude_codes;
let threads = args.threads;
let retries = args.retries;
let timeout = args.timeout;
let max_redirects = args.max_redirects;
let user_agents_list = utils::user_agents();
let show_status_codes = matches.is_present("show-codes");
let show_status_codes = args.show_codes;
let client = httplib::return_http_client(timeout, max_redirects);
@ -123,9 +25,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut hosts = HashSet::new();
if matches.is_present("domain") {
let domain = value_t!(matches, "domain", String).unwrap();
if matches.is_present("bruteforce") {
if args.domain.is_some() {
let domain = args.domain.expect("Error getting domain");
if args.bruteforce {
io::stdin().read_to_string(&mut buffer).await?;
hosts = buffer
.lines()
@ -145,12 +47,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
user_agents: user_agents_list,
retries,
threads,
conditional_response_code,
filter_codes,
exclude_codes,
show_status_codes,
..Default::default()
};
httplib::return_http_data(&lib_options).await;
if !args.quiet {
if show_status_codes {
println!("DOMAIN,[FINAL_URL],[STATUS_CODE]");
} else {
println!("DOMAIN,[FINAL_URL]");
}
}
let _ = httplib::return_http_data(&lib_options).await;
Ok(())
}