Skip to content

Commit f201bcd

Browse files
committed
new pattern
1 parent 79fb59d commit f201bcd

36 files changed

+524
-571
lines changed

Cargo.toml

+4-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ readme = "README.md"
1111

1212
[[bin]]
1313
name = "lotus"
14-
path = "src/cli/main.rs"
14+
path = "src/main.rs"
1515
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1616

1717
[dependencies]
@@ -25,16 +25,18 @@ tealr = {version="0.9.0-alpha1", features=["mlua", "mlua_lua54", "mlua_vendored"
2525

2626
# Threading
2727
futures = "0.3.24"
28+
crossbeam-channel = "0.5.6"
2829
tokio = { version = "1.21.0", features = ["full"] }
2930

3031
# LOGGING & Console
3132
log = "0.4.17"
32-
clap = "3.2.21"
33+
structopt = "0.3.20"
3334
fern = "0.6.1"
3435
chrono = "0.4.22"
3536
console = "0.15.1"
3637
atty = "0.2.14"
3738
indicatif = "0.17.0"
39+
thiserror = "1.0.37"
3840

3941
# REGEX AND MATCHES
4042
fancy-regex = "0.10.0"

examples/main.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use lotus::threader::Threader;
2+
3+
#[tokio::main]
4+
async fn main() {
5+
let threader = Threader::init(30,30);
6+
threader.start(vec!["http://nokia.com","http://php.net","http://google.com"],|url| {
7+
println!("SOMETIMES I THINK {}",url);
8+
}).await;
9+
}

src/cli/args.rs

+65-100
Original file line numberDiff line numberDiff line change
@@ -1,103 +1,68 @@
1-
/*
2-
* This file is part of Lotus Project, an Web Security Scanner written in Rust based on Lua Scripts
3-
* For details, please see https://github.com/rusty-sec/lotus/
4-
*
5-
* Copyright (c) 2022 - Khaled Nassar
6-
*
7-
* Please note that this file was originally released under the
8-
* GNU General Public License as published by the Free Software Foundation;
9-
* either version 2 of the License, or (at your option) any later version.
10-
*
11-
*
12-
* Unless required by applicable law or agreed to in writing, software
13-
* distributed under the License is distributed on an "AS IS" BASIS,
14-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15-
* See the License for the specific language governing permissions and
16-
* limitations under the License.
17-
*/
1+
use reqwest::header::HeaderMap;
2+
use reqwest::header::{HeaderName, HeaderValue};
3+
use std::collections::HashMap;
4+
use std::path::PathBuf;
5+
use structopt::StructOpt;
186

19-
use clap::{App, Arg, ArgMatches};
20-
mod validator;
21-
pub fn cmd_args() -> ArgMatches {
22-
App::new("Lotus")
23-
.version("0.3-beta")
24-
.author("Khaled Nassar <knassar702@gmail.com>")
25-
.about("Fast Web Security Scanner written in Rust based on Lua Scripts ")
26-
.arg(
27-
Arg::with_name("out_script")
28-
.help("Use Custom Lua for reporting")
29-
.long("--lua-report")
30-
.validator(validator::file_exists)
31-
.takes_value(true)
32-
.required_unless_present("output"),
33-
)
34-
.arg(
35-
Arg::with_name("default_headers")
36-
.help("Default Request Headers")
37-
.validator(validator::valid_json)
38-
.takes_value(true)
39-
.default_value("{}")
40-
.long("headers"),
41-
)
42-
.arg(
43-
Arg::with_name("redirects")
44-
.help("Set limit of http redirects")
45-
.long("redirects")
46-
.default_value("10"),
47-
)
48-
.arg(
49-
Arg::with_name("timeout")
50-
.help("Set Connection timeout")
51-
.long("timeout")
52-
.default_value("10"),
53-
)
54-
.arg(
55-
Arg::with_name("proxy")
56-
.help("Forward all connection through a proxy (eg: --proxy http://localhost:8080)")
57-
.required(false)
58-
.takes_value(true)
59-
.validator(url::Url::parse)
60-
.long("proxy"),
61-
)
62-
.arg(
63-
Arg::with_name("workers")
64-
.help("Number of works of urls")
65-
.short('w')
66-
.takes_value(true)
67-
.default_value("10")
68-
.long("workers"),
69-
)
70-
.arg(
71-
Arg::with_name("log")
72-
.help("Save all logs to custom file")
73-
.takes_value(true)
74-
.short('l')
75-
.long("log"),
76-
)
77-
.arg(
78-
Arg::with_name("script_threads")
79-
.help("Workers for lua scripts")
80-
.short('t')
81-
.long("script-threads")
82-
.takes_value(true)
83-
.default_value("5"),
84-
)
85-
.arg(
86-
Arg::with_name("scripts")
87-
.help("Path of scripts dir")
88-
.takes_value(true)
89-
.short('s')
90-
.long("scripts")
91-
.required(true),
92-
)
93-
.arg(
94-
Arg::with_name("output")
95-
.help("Path of the JSON output fiel")
96-
.required_if_eq("out_script", "")
97-
.takes_value(true)
98-
.long("output")
99-
.short('o'),
7+
fn parse_headers(raw_headers: &str) -> Result<HeaderMap, serde_json::Error> {
8+
let parsed_json = serde_json::from_str::<HashMap<String, String>>(raw_headers);
9+
10+
if parsed_json.is_err() {
11+
return Err(parsed_json.unwrap_err());
12+
}
13+
let mut user_headers = HeaderMap::new();
14+
user_headers.insert(
15+
HeaderName::from_bytes("User-agent".as_bytes()).unwrap(),
16+
HeaderValue::from_bytes(
17+
"Mozilla/5.0 (X11; Manjaro; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0"
18+
.as_bytes(),
10019
)
101-
.arg(Arg::with_name("nolog").help("no logging"))
102-
.get_matches()
20+
.unwrap(),
21+
);
22+
parsed_json
23+
.unwrap()
24+
.iter()
25+
.for_each(|(headername, headervalue)| {
26+
user_headers.insert(
27+
HeaderName::from_bytes(headername.as_bytes()).unwrap(),
28+
HeaderValue::from_bytes(headervalue.as_bytes()).unwrap(),
29+
);
30+
});
31+
Ok(user_headers)
32+
}
33+
34+
#[derive(Debug, StructOpt)]
35+
#[structopt(
36+
name = "Lotus",
37+
about = "Fast Web Security Scanner written in Rust based on Lua Scripts"
38+
)]
39+
pub struct Opts {
40+
// redirects limit
41+
#[structopt(short, long, default_value = "10")]
42+
pub redirects: u32,
43+
44+
// threads
45+
#[structopt(short = "w", long = "workers", default_value = "10")]
46+
pub workers: usize,
47+
48+
// timeout
49+
#[structopt(short = "t", long = "timeout", default_value = "10")]
50+
pub timeout: u64,
51+
52+
/// Input file
53+
#[structopt(parse(from_os_str))]
54+
pub script_path: PathBuf,
55+
56+
/// Output file, stdout if not present
57+
#[structopt(short = "o", long = "output", parse(from_os_str))]
58+
pub output: Option<PathBuf>,
59+
60+
#[structopt(short = "p", long = "proxy")]
61+
pub proxy: Option<String>,
62+
63+
#[structopt(long = "log")]
64+
pub log: Option<PathBuf>,
65+
66+
#[structopt(long = "headers", parse(try_from_str = parse_headers), required = false, default_value = "{}")]
67+
pub headers: HeaderMap,
10368
}

src/cli/args/validator.rs

-16
This file was deleted.
File renamed without changes.

src/cli/errors.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
use thiserror::Error;
2+
3+
#[derive(Error, Debug)]
4+
pub enum CliErrors {
5+
#[error("There is no URLS in the Stdin ")]
6+
EmptyStdin,
7+
#[error("File not found")]
8+
ReadingError,
9+
}

src/cli/logger.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
*/
1818

1919
// Lotus init logger
20-
pub fn init_log(log_path: &str) -> Result<(), std::io::Error> {
20+
use std::path::PathBuf;
21+
22+
pub fn init_log(log_file: Option<PathBuf>) -> Result<(), std::io::Error> {
2123
let logger = fern::Dispatch::new()
2224
.format(|out, message, record| {
2325
out.finish(format_args!(
@@ -34,10 +36,15 @@ pub fn init_log(log_path: &str) -> Result<(), std::io::Error> {
3436
.level_for("isahc", log::LevelFilter::Warn)
3537
.level_for("selectors", log::LevelFilter::Warn)
3638
.level_for("html5ever", log::LevelFilter::Warn);
37-
// Disalbe unwanted loggers
38-
logger
39-
.chain(fern::log_file(log_path).unwrap())
40-
.apply()
41-
.unwrap();
39+
match log_file {
40+
Some(log_path) => {
41+
// Disalbe unwanted loggers
42+
logger
43+
.chain(fern::log_file(log_path).unwrap())
44+
.apply()
45+
.unwrap();
46+
}
47+
None => {}
48+
}
4249
Ok(())
4350
}

src/cli/logo.rs

-1
This file was deleted.

src/cli/main.rs

-86
This file was deleted.

src/cli/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
pub mod args;
2+
pub mod bar;
3+
pub mod errors;
4+
pub mod logger;

src/cli/txt/logo.txt

-8
This file was deleted.

0 commit comments

Comments
 (0)