Changed whois system to trait based system
This commit is contained in:
parent
9d71ba17a5
commit
4515f35181
47
Cargo.lock
generated
47
Cargo.lock
generated
@ -2,6 +2,17 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr"
|
||||||
|
version = "0.15.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a93b8a41dbe230ad5087cc721f8d41611de654542180586b315d9f4cf6b72bef"
|
||||||
|
dependencies = [
|
||||||
|
"psl",
|
||||||
|
"psl-types",
|
||||||
|
"publicsuffix",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
@ -308,6 +319,7 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5"
|
|||||||
name = "dns_lookup_project"
|
name = "dns_lookup_project"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"addr",
|
||||||
"chrono",
|
"chrono",
|
||||||
"configparser",
|
"configparser",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
@ -563,6 +575,16 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "idna"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-bidi",
|
||||||
|
"unicode-normalization",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@ -857,6 +879,21 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "psl"
|
||||||
|
version = "2.1.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe63c1c8bb438205c1245719638a0b14fe6e3b33f4406ac36b4770a706655345"
|
||||||
|
dependencies = [
|
||||||
|
"psl-types",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "psl-types"
|
||||||
|
version = "2.0.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ptr_meta"
|
name = "ptr_meta"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
@ -877,6 +914,16 @@ dependencies = [
|
|||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "publicsuffix"
|
||||||
|
version = "2.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457"
|
||||||
|
dependencies = [
|
||||||
|
"idna 0.3.0",
|
||||||
|
"psl-types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-error"
|
name = "quick-error"
|
||||||
version = "1.2.3"
|
version = "1.2.3"
|
||||||
|
|||||||
13
Cargo.toml
13
Cargo.toml
@ -6,12 +6,13 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
configparser = "3.0.4"
|
configparser = "*"
|
||||||
crossterm = "0.27.0"
|
crossterm = "*"
|
||||||
hickory-resolver = { version = "0.24.0" }
|
hickory-resolver = { version = "0.24.0" }
|
||||||
ratatui = "0.26.1"
|
ratatui = "*"
|
||||||
regex = "1.10.3"
|
regex = "*"
|
||||||
whois-rust = "1.6.0"
|
whois-rust = "*"
|
||||||
serde = { version = "*", features = ["derive"] }
|
serde = { version = "*", features = ["derive"] }
|
||||||
serde_json = "*"
|
serde_json = "*"
|
||||||
chrono = "0.4.37"
|
chrono = "*"
|
||||||
|
addr = { version = "0.15.6", features = ["publicsuffix"] }
|
||||||
|
|||||||
@ -25,7 +25,6 @@ pub struct App {
|
|||||||
pub current_state: CurrentState,
|
pub current_state: CurrentState,
|
||||||
pub menu_state: MenuState,
|
pub menu_state: MenuState,
|
||||||
pub config: Config,
|
pub config: Config,
|
||||||
pub state: ListState,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
@ -38,7 +37,6 @@ impl App {
|
|||||||
current_state: CurrentState::Lookup,
|
current_state: CurrentState::Lookup,
|
||||||
menu_state: MenuState::Main,
|
menu_state: MenuState::Main,
|
||||||
config: Config::from_file("test.ini".to_string()),
|
config: Config::from_file("test.ini".to_string()),
|
||||||
state: ListState::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,9 +53,9 @@ impl fmt::Display for Domain {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Domain {
|
impl Domain {
|
||||||
pub fn new(domain: String) -> Domain {
|
pub fn new(domain: &String) -> Domain {
|
||||||
Domain {
|
Domain {
|
||||||
domain_name: domain,
|
domain_name: String::from(domain),
|
||||||
subdomains: vec![],
|
subdomains: vec![],
|
||||||
a_records: vec![],
|
a_records: vec![],
|
||||||
aaaa_records: vec![],
|
aaaa_records: vec![],
|
||||||
@ -116,7 +116,7 @@ impl Domain {
|
|||||||
let mut new_domain = String::from(subdomain);
|
let mut new_domain = String::from(subdomain);
|
||||||
new_domain.push_str(".");
|
new_domain.push_str(".");
|
||||||
new_domain.push_str(&self.domain_name);
|
new_domain.push_str(&self.domain_name);
|
||||||
let subdomain = Domain::new(new_domain);
|
let subdomain = Domain::new(&new_domain);
|
||||||
self.subdomains.push(subdomain);
|
self.subdomains.push(subdomain);
|
||||||
// println!("Added: {}", new_domain);
|
// println!("Added: {}", new_domain);
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/main.rs
20
src/main.rs
@ -4,9 +4,6 @@ use crate::domain::Domain;
|
|||||||
mod config;
|
mod config;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
||||||
mod whois;
|
|
||||||
use crate::whois::WhoisData;
|
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
use crate::app::*;
|
use crate::app::*;
|
||||||
|
|
||||||
@ -16,6 +13,10 @@ use crate::ui::*;
|
|||||||
mod fsutil;
|
mod fsutil;
|
||||||
use crate::fsutil::*;
|
use crate::fsutil::*;
|
||||||
|
|
||||||
|
mod whois;
|
||||||
|
use whois::default;
|
||||||
|
use whois::selector::*;
|
||||||
|
|
||||||
use crossterm::event::{
|
use crossterm::event::{
|
||||||
self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind,
|
self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind,
|
||||||
};
|
};
|
||||||
@ -78,12 +79,19 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> io::Result<
|
|||||||
// Ignore empty input
|
// Ignore empty input
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mut domain = Domain::new(app.domain_input.clone());
|
let mut domain = Domain::new(&app.domain_input);
|
||||||
domain.apply_config(&app.config);
|
domain.apply_config(&app.config);
|
||||||
domain.lookup_all_records();
|
domain.lookup_all_records();
|
||||||
app.dns_info = domain.to_vec();
|
app.dns_info = domain.to_vec();
|
||||||
let whois = WhoisData::new(app.domain_input.clone());
|
let whois_server = select_whois_server(app.domain_input.clone());
|
||||||
app.whois_info = whois.to_vec();
|
match whois_server {
|
||||||
|
Ok(mut whois_data) => {
|
||||||
|
app.whois_info = whois_data.lookup(app.domain_input.clone());
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
// let whois = WhoisData::new(app.domain_input.clone());
|
||||||
|
// app.whois_info = whois.to_vec();
|
||||||
}
|
}
|
||||||
KeyCode::Delete => {
|
KeyCode::Delete => {
|
||||||
app.domain_input = String::new();
|
app.domain_input = String::new();
|
||||||
|
|||||||
65
src/ui.rs
65
src/ui.rs
@ -1,9 +1,10 @@
|
|||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::{Constraint, Direction, Layout, Rect},
|
layout::{Constraint, Direction, Layout, Rect},
|
||||||
|
prelude::*,
|
||||||
style::{Color, Modifier, Style, Styled},
|
style::{Color, Modifier, Style, Styled},
|
||||||
text::{Line, Span, Text},
|
text::{Line, Span, Text},
|
||||||
widgets::{
|
widgets::{
|
||||||
Block, Borders, Clear, HighlightSpacing, List, ListDirection, ListItem, ListState,
|
Block, Borders, Clear, HighlightSpacing, List, ListDirection, ListItem, ListState, Padding,
|
||||||
Paragraph, Wrap,
|
Paragraph, Wrap,
|
||||||
},
|
},
|
||||||
Frame,
|
Frame,
|
||||||
@ -14,6 +15,61 @@ use crate::{
|
|||||||
CurrentState, DomainData, MenuState,
|
CurrentState, DomainData, MenuState,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct StatefulList<'a> {
|
||||||
|
state: ListState,
|
||||||
|
items: Vec<ListItem<'a>>,
|
||||||
|
last_selected: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StatefulList<'_> {
|
||||||
|
fn with_items<'a>(items: Vec<String>) -> StatefulList<'a> {
|
||||||
|
let mut veclist = Vec::<ListItem>::new();
|
||||||
|
for item in items {
|
||||||
|
veclist.push(ListItem::new(Line::from(item)));
|
||||||
|
}
|
||||||
|
StatefulList {
|
||||||
|
state: ListState::default(),
|
||||||
|
items: veclist,
|
||||||
|
last_selected: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next(&mut self) {
|
||||||
|
let i = match self.state.selected() {
|
||||||
|
Some(i) => {
|
||||||
|
if i >= self.items.len() - 1 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => self.last_selected.unwrap_or(0),
|
||||||
|
};
|
||||||
|
self.state.select(Some(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn previous(&mut self) {
|
||||||
|
let i = match self.state.selected() {
|
||||||
|
Some(i) => {
|
||||||
|
if i == 0 {
|
||||||
|
self.items.len() - 1
|
||||||
|
} else {
|
||||||
|
i - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => self.last_selected.unwrap_or(0),
|
||||||
|
};
|
||||||
|
self.state.select(Some(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unselect(&mut self) {
|
||||||
|
let offset = self.state.offset();
|
||||||
|
self.last_selected = self.state.selected();
|
||||||
|
self.state.select(None);
|
||||||
|
*self.state.offset_mut() = offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ui(f: &mut Frame, app: &mut App) {
|
pub fn ui(f: &mut Frame, app: &mut App) {
|
||||||
if f.size().width > 100 {
|
if f.size().width > 100 {
|
||||||
app.render_direction = AppRenderDir::Horizontal;
|
app.render_direction = AppRenderDir::Horizontal;
|
||||||
@ -44,11 +100,12 @@ pub fn ui(f: &mut Frame, app: &mut App) {
|
|||||||
|
|
||||||
let title_block = Block::default()
|
let title_block = Block::default()
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.style(Style::default());
|
.style(Style::default())
|
||||||
|
.padding(Padding::horizontal(2));
|
||||||
|
|
||||||
let title = Paragraph::new(Span::styled(
|
let title = Paragraph::new(Span::styled(
|
||||||
"Dns Lookup tool",
|
"Dns Lookup tool",
|
||||||
Style::default().fg(Color::White),
|
Style::default().fg(Color::Yellow),
|
||||||
))
|
))
|
||||||
.block(title_block);
|
.block(title_block);
|
||||||
|
|
||||||
@ -277,7 +334,7 @@ pub fn ui(f: &mut Frame, app: &mut App) {
|
|||||||
.highlight_symbol(">>")
|
.highlight_symbol(">>")
|
||||||
.highlight_spacing(HighlightSpacing::Always)
|
.highlight_spacing(HighlightSpacing::Always)
|
||||||
.repeat_highlight_symbol(true);
|
.repeat_highlight_symbol(true);
|
||||||
f.render_stateful_widget(items, chunks[1], &mut app.state);
|
// f.render_stateful_widget(items, chunks[1], &mut app.state);
|
||||||
|
|
||||||
let footer_block = Block::new().borders(Borders::ALL).style(Style::default());
|
let footer_block = Block::new().borders(Borders::ALL).style(Style::default());
|
||||||
|
|
||||||
|
|||||||
23
src/whois/au.rs
Normal file
23
src/whois/au.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use crate::whois::whois_base::{
|
||||||
|
NameServer, RegexQuery, Registrant, RegistrantType, Whois, WhoisData,
|
||||||
|
};
|
||||||
|
use whois_rust::{WhoIs, WhoIsLookupOptions};
|
||||||
|
pub struct _Whois {
|
||||||
|
base: WhoisData,
|
||||||
|
elegibility: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Whois for _Whois {
|
||||||
|
fn new() -> Self {
|
||||||
|
_Whois {
|
||||||
|
base: WhoisData::new(),
|
||||||
|
elegibility: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn to_vec(&self) -> Vec<String> {
|
||||||
|
vec![String::new()]
|
||||||
|
}
|
||||||
|
fn lookup(&mut self, domain: String) -> Vec<String> {
|
||||||
|
self.to_vec()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,168 +1,34 @@
|
|||||||
use core::fmt;
|
use crate::whois::whois_base::{
|
||||||
use hickory_resolver::proto::{
|
NameServer, RegexQuery, Registrant, RegistrantType, Whois, WhoisData,
|
||||||
rr::{domain, rdata::name},
|
|
||||||
xfer::dns_handle,
|
|
||||||
};
|
};
|
||||||
use regex::Regex;
|
|
||||||
use whois_rust::{WhoIs, WhoIsLookupOptions};
|
use whois_rust::{WhoIs, WhoIsLookupOptions};
|
||||||
|
pub struct _Whois {
|
||||||
#[derive(Debug, Clone)]
|
base: WhoisData,
|
||||||
enum RegistrantType {
|
|
||||||
Registrant,
|
|
||||||
Admin,
|
|
||||||
Tech,
|
|
||||||
Billing,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RegexQuery {
|
impl Whois for _Whois {
|
||||||
re: Regex,
|
fn new() -> _Whois {
|
||||||
}
|
_Whois {
|
||||||
|
base: WhoisData::new(),
|
||||||
impl RegexQuery {
|
|
||||||
fn new(expression: String) -> RegexQuery {
|
|
||||||
let re = Regex::new(&expression).unwrap();
|
|
||||||
RegexQuery { re }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_matches(&self, haystack: &str) -> Vec<String> {
|
|
||||||
let mut results = vec![];
|
|
||||||
for (_, [_, rex2]) in self.re.captures_iter(haystack).map(|c| c.extract()) {
|
|
||||||
results.push(String::from(rex2.trim()));
|
|
||||||
}
|
|
||||||
results
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct NameServer {
|
|
||||||
host: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NameServer {
|
|
||||||
fn new(host: String) -> NameServer {
|
|
||||||
NameServer { host }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
struct Registrant {
|
|
||||||
name: String,
|
|
||||||
org: String,
|
|
||||||
email: String,
|
|
||||||
rtype: RegistrantType,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Registrant {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Registrant {
|
|
||||||
fn new(name: String, org: String, email: String, rtype: RegistrantType) -> Registrant {
|
|
||||||
Registrant {
|
|
||||||
name,
|
|
||||||
org,
|
|
||||||
email,
|
|
||||||
rtype,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Eligibility {
|
|
||||||
e_type: String,
|
|
||||||
id: String,
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WhoisData {
|
|
||||||
registrar: Option<String>,
|
|
||||||
domain_status: Option<String>,
|
|
||||||
registrant: Option<Vec<Registrant>>,
|
|
||||||
nameservers: Option<Vec<NameServer>>,
|
|
||||||
dnssec: Option<String>,
|
|
||||||
eligibility_type: Option<Eligibility>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for WhoisData {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"Registrar: {}\nStatus: {}\nRegistrant: {:?}\nNameservers: {:?}\nDNSSEC: {}",
|
|
||||||
self.registrar.clone().unwrap(),
|
|
||||||
self.domain_status.clone().unwrap(),
|
|
||||||
self.registrant.clone().unwrap(),
|
|
||||||
self.nameservers.clone().unwrap(),
|
|
||||||
self.dnssec.clone().unwrap()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WhoisData {
|
|
||||||
pub fn new(domain: String) -> WhoisData {
|
|
||||||
let whois = WhoIs::from_path("servers.json").unwrap();
|
|
||||||
let result: String = whois
|
|
||||||
.lookup(WhoIsLookupOptions::from_string(domain).unwrap())
|
|
||||||
.unwrap();
|
|
||||||
let registrar_regex =
|
|
||||||
RegexQuery::new(String::from(r"(?i)(.*registrar:|registrar *name:)(.*)"));
|
|
||||||
let domain_status_regex =
|
|
||||||
RegexQuery::new(String::from(r"(?i)(.*domain status:|.*status:)(.*)"));
|
|
||||||
// TODO: Capture the registrant info for each type
|
|
||||||
let registrant_name_regex = RegexQuery::new(String::from(r"(?i)(registrant.*name:)(.*)"));
|
|
||||||
let registrant_org_regex =
|
|
||||||
RegexQuery::new(String::from(r"(?i)(registrant org.*:|registrant:)(.*)"));
|
|
||||||
let registrant_email_regex = RegexQuery::new(String::from(r"(?i)(registrant email:)(.*)"));
|
|
||||||
let nameserver_regex =
|
|
||||||
RegexQuery::new(String::from(r"(?i)(nameservers*:|name servers*:)(.*)"));
|
|
||||||
let dnssec_regex = RegexQuery::new(String::from(r"(?i)(.*dnssec:)(.*)"));
|
|
||||||
|
|
||||||
let registrar = WhoisData::return_regex(registrar_regex.get_matches(&result), 0);
|
|
||||||
let domain_status = WhoisData::return_regex(domain_status_regex.get_matches(&result), 0);
|
|
||||||
let reg_name = WhoisData::return_regex(registrant_name_regex.get_matches(&result), 0);
|
|
||||||
let reg_org = WhoisData::return_regex(registrant_org_regex.get_matches(&result), 0);
|
|
||||||
let reg_email = WhoisData::return_regex(registrant_email_regex.get_matches(&result), 0);
|
|
||||||
|
|
||||||
let mut nameservers = vec![];
|
|
||||||
for nameserver in nameserver_regex.get_matches(&result) {
|
|
||||||
nameservers.push(NameServer::new(nameserver));
|
|
||||||
}
|
|
||||||
let mut dnssec = dnssec_regex.get_matches(&result);
|
|
||||||
if dnssec.len() == 0 {
|
|
||||||
dnssec = vec![String::from("Failed to get DNSSEC")];
|
|
||||||
}
|
|
||||||
// println!("{:?}", registrar[0]);
|
|
||||||
WhoisData {
|
|
||||||
registrar: Some(registrar.clone()),
|
|
||||||
domain_status: Some(domain_status.clone()),
|
|
||||||
registrant: Some(vec![Registrant::new(
|
|
||||||
reg_name.clone(),
|
|
||||||
reg_org.clone(),
|
|
||||||
reg_email,
|
|
||||||
RegistrantType::Registrant,
|
|
||||||
)]),
|
|
||||||
nameservers: Some(nameservers),
|
|
||||||
dnssec: Some(dnssec[0].clone()),
|
|
||||||
eligibility_type: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_vec(&self) -> Vec<String> {
|
fn to_vec(&self) -> Vec<String> {
|
||||||
let mut ret_vec: Vec<String> = vec![];
|
let mut ret_vec: Vec<String> = vec![];
|
||||||
let mut registrar = String::from("Registrar: ");
|
let mut registrar = String::from("Registrar: ");
|
||||||
registrar.push_str(&self.registrar.clone().unwrap());
|
registrar.push_str(&self.base.registrar.clone().unwrap());
|
||||||
ret_vec.push(registrar);
|
ret_vec.push(registrar);
|
||||||
|
|
||||||
let mut domain_status = String::from("Status: ");
|
let mut domain_status = String::from("Status: ");
|
||||||
domain_status.push_str(&self.domain_status.clone().unwrap());
|
domain_status.push_str(&self.base.domain_status.clone().unwrap());
|
||||||
ret_vec.push(domain_status);
|
ret_vec.push(domain_status);
|
||||||
|
|
||||||
let mut dnssec = String::from("DNSSEC: ");
|
let mut dnssec = String::from("DNSSEC: ");
|
||||||
dnssec.push_str(&self.dnssec.clone().unwrap());
|
dnssec.push_str(&self.base.dnssec.clone().unwrap());
|
||||||
ret_vec.push(dnssec);
|
ret_vec.push(dnssec);
|
||||||
|
|
||||||
let mut registrant_type = String::new();
|
let mut registrant_type = String::new();
|
||||||
for registrant in &self.registrant.clone().unwrap() {
|
for registrant in &self.base.registrant.clone().unwrap() {
|
||||||
match registrant.rtype {
|
match registrant.rtype {
|
||||||
RegistrantType::Admin => {
|
RegistrantType::Admin => {
|
||||||
registrant_type.push_str("Admin ");
|
registrant_type.push_str("Admin ");
|
||||||
@ -193,7 +59,7 @@ impl WhoisData {
|
|||||||
ret_vec.push(email);
|
ret_vec.push(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
for nameserver in &self.nameservers.clone().unwrap() {
|
for nameserver in &self.base.nameservers.clone().unwrap() {
|
||||||
let mut tmp = String::from("Nameserver: ");
|
let mut tmp = String::from("Nameserver: ");
|
||||||
tmp.push_str(&nameserver.host);
|
tmp.push_str(&nameserver.host);
|
||||||
ret_vec.push(tmp);
|
ret_vec.push(tmp);
|
||||||
@ -202,16 +68,50 @@ impl WhoisData {
|
|||||||
return ret_vec;
|
return ret_vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn return_regex(caps: Vec<String>, index: usize) -> String {
|
fn lookup(&mut self, domain: String) -> Vec<String> {
|
||||||
let data: String;
|
let whois = WhoIs::from_path("servers.json").unwrap();
|
||||||
match caps.get(index) {
|
let result: String = whois
|
||||||
Some(tmp) => {
|
.lookup(WhoIsLookupOptions::from_string(domain).unwrap())
|
||||||
data = tmp.to_string();
|
.unwrap();
|
||||||
}
|
let registrar_regex =
|
||||||
None => {
|
RegexQuery::new(String::from(r"(?i)(.*registrar:|registrar *name:)(.*)"));
|
||||||
data = String::from("None");
|
let domain_status_regex =
|
||||||
}
|
RegexQuery::new(String::from(r"(?i)(.*domain status:|.*status:)(.* )"));
|
||||||
|
// TODO: Capture the registrant info for each type
|
||||||
|
let registrant_name_regex = RegexQuery::new(String::from(r"(?i)(registrant.*name:)(.*)"));
|
||||||
|
let registrant_org_regex =
|
||||||
|
RegexQuery::new(String::from(r"(?i)(registrant org.*:|registrant:)(.*)"));
|
||||||
|
let registrant_email_regex = RegexQuery::new(String::from(r"(?i)(registrant email:)(.*)"));
|
||||||
|
let nameserver_regex =
|
||||||
|
RegexQuery::new(String::from(r"(?i)(nameservers*:|name servers*:)(.*)"));
|
||||||
|
let dnssec_regex = RegexQuery::new(String::from(r"(?i)(.*dnssec:)(.*)"));
|
||||||
|
|
||||||
|
let registrar = WhoisData::return_regex(registrar_regex.get_matches(&result), 0);
|
||||||
|
let domain_status = WhoisData::return_regex(domain_status_regex.get_matches(&result), 0);
|
||||||
|
let reg_name = WhoisData::return_regex(registrant_name_regex.get_matches(&result), 0);
|
||||||
|
let reg_org = WhoisData::return_regex(registrant_org_regex.get_matches(&result), 0);
|
||||||
|
let reg_email = WhoisData::return_regex(registrant_email_regex.get_matches(&result), 0);
|
||||||
|
|
||||||
|
let mut nameservers = vec![];
|
||||||
|
for nameserver in nameserver_regex.get_matches(&result) {
|
||||||
|
nameservers.push(NameServer::new(nameserver));
|
||||||
}
|
}
|
||||||
data
|
let mut dnssec = dnssec_regex.get_matches(&result);
|
||||||
|
if dnssec.len() == 0 {
|
||||||
|
dnssec = vec![String::from("Failed to get DNSSEC")];
|
||||||
|
}
|
||||||
|
// println!("{:?}", registrar[0]);
|
||||||
|
self.base.domain_status = Some(domain_status.clone());
|
||||||
|
self.base.registrant = Some(vec![Registrant::new(
|
||||||
|
reg_name.clone(),
|
||||||
|
reg_org.clone(),
|
||||||
|
reg_email,
|
||||||
|
RegistrantType::Registrant,
|
||||||
|
)]);
|
||||||
|
self.base.nameservers = Some(nameservers);
|
||||||
|
self.base.dnssec = Some(dnssec[0].clone());
|
||||||
|
self.base.registrar = Some(registrar.clone());
|
||||||
|
|
||||||
|
self.to_vec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
4
src/whois/mod.rs
Normal file
4
src/whois/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub mod au;
|
||||||
|
pub mod default;
|
||||||
|
pub mod selector;
|
||||||
|
pub mod whois_base;
|
||||||
30
src/whois/selector.rs
Normal file
30
src/whois/selector.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
use crate::whois::default;
|
||||||
|
use addr::parse_domain_name;
|
||||||
|
|
||||||
|
use super::{au, whois_base::Whois};
|
||||||
|
|
||||||
|
pub fn select_whois_server(domain: String) -> Result<Box<dyn Whois>, String> {
|
||||||
|
let domain = parse_domain_name(&domain.as_str());
|
||||||
|
match domain {
|
||||||
|
Ok(val) => match val.suffix() {
|
||||||
|
".com.au" => Ok(Box::new(au::_Whois::new())),
|
||||||
|
_ => Ok(Box::new(default::_Whois::new())),
|
||||||
|
},
|
||||||
|
Err(_) => Err(String::from("Failed to select whois server")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl RegexQuery {
|
||||||
|
// pub fn new(expression: String) -> RegexQuery {
|
||||||
|
// let re = Regex::new(&expression).unwrap();
|
||||||
|
// RegexQuery { re }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn get_matches(&self, haystack: &str) -> Vec<String> {
|
||||||
|
// let mut results = vec![];
|
||||||
|
// for (_, [_, rex2]) in self.re.captures_iter(haystack).map(|c| c.extract()) {
|
||||||
|
// results.push(String::from(rex2.trim()));
|
||||||
|
// }
|
||||||
|
// results
|
||||||
|
// }
|
||||||
|
// }
|
||||||
104
src/whois/whois_base.rs
Normal file
104
src/whois/whois_base.rs
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
use core::fmt;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
pub trait Whois {
|
||||||
|
fn new() -> Self
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
fn lookup(&mut self, domain: String) -> Vec<String>;
|
||||||
|
fn to_vec(&self) -> Vec<String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum RegistrantType {
|
||||||
|
Registrant,
|
||||||
|
Admin,
|
||||||
|
Tech,
|
||||||
|
Billing,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RegexQuery {
|
||||||
|
re: Regex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegexQuery {
|
||||||
|
pub fn new(expression: String) -> RegexQuery {
|
||||||
|
let re = Regex::new(&expression).unwrap();
|
||||||
|
RegexQuery { re }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_matches(&self, haystack: &str) -> Vec<String> {
|
||||||
|
let mut results = vec![];
|
||||||
|
for (_, [_, rex2]) in self.re.captures_iter(haystack).map(|c| c.extract()) {
|
||||||
|
results.push(String::from(rex2.trim()));
|
||||||
|
}
|
||||||
|
results
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct NameServer {
|
||||||
|
pub host: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NameServer {
|
||||||
|
pub fn new(host: String) -> NameServer {
|
||||||
|
NameServer { host }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Registrant {
|
||||||
|
pub name: String,
|
||||||
|
pub org: String,
|
||||||
|
pub email: String,
|
||||||
|
pub rtype: RegistrantType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Registrant {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Registrant {
|
||||||
|
pub fn new(name: String, org: String, email: String, rtype: RegistrantType) -> Registrant {
|
||||||
|
Registrant {
|
||||||
|
name,
|
||||||
|
org,
|
||||||
|
email,
|
||||||
|
rtype,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub struct WhoisData {
|
||||||
|
pub registrar: Option<String>,
|
||||||
|
pub domain_status: Option<String>,
|
||||||
|
pub registrant: Option<Vec<Registrant>>,
|
||||||
|
pub nameservers: Option<Vec<NameServer>>,
|
||||||
|
pub dnssec: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WhoisData {
|
||||||
|
pub fn new() -> WhoisData {
|
||||||
|
WhoisData {
|
||||||
|
registrar: None,
|
||||||
|
domain_status: None,
|
||||||
|
registrant: None,
|
||||||
|
nameservers: None,
|
||||||
|
dnssec: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn return_regex(caps: Vec<String>, index: usize) -> String {
|
||||||
|
let data: String;
|
||||||
|
match caps.get(index) {
|
||||||
|
Some(tmp) => {
|
||||||
|
data = tmp.to_string();
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
data = String::from("None");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user