1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
extern crate rustc_serialize;

use std::net::TcpStream;
use std::io::prelude::*;
use std::collections::HashMap;
use rustc_serialize::json;

pub struct WhoIs {
    server: String,
    follow: isize,
    new_whois: String,
    query: String
}

impl WhoIs {
    pub fn new(x: String)-> WhoIs {
        WhoIs {
            server: x,
            follow: 0,
            new_whois: String::new(),
            query: String::new()
        }
    }
    ///
    ///
    ///  This function will get whois server from the `get_server` function decide the appropriate
    ///  query for the server and parse the whois data into JSON by calling parse_data()
    ///  If there is another whois server in the whois data then it calls 'parse_whois'
    ///  so it can get the whois data from that
    ///
    pub fn lookup(&mut self) -> Result<String, &'static str> {
        let mut result = String::new();
        let mut server = self.new_whois.to_owned();
        let target = self.server.to_owned();
        let tld = match target.split(".").last() {
            Some(tld) => tld,
            None => return Err("Invalid URL?")
        };
        if self.follow == 0 {
            self.query = match tld {
                "com" | "net" => "DOMAIN ".into(),
                _ => "".into()
            };
            server = self.get_server(&tld).unwrap();
        }
        let mut client = TcpStream::connect((&*server, 43u16)).expect("Could not connect to server!!");
        match client.write_all(format!("{}{}\n", self.query, target).as_bytes()) {
            Ok(_) => (),
            Err(_) => return Err("Could not write to client {}")
        }
        client.read_to_string(&mut result).unwrap();
        if result.contains("Whois Server:") {
            self.query = "".into();
            self.follow += 1;                                             // If there is another Whois Server, take that server and pass it to
            return Ok(self.parse_whois(&*result))                             // pass it to parse_whois
        }
        else {
            let clean = result.replace("http:", "").replace("https:",""); // I'm splitting via ':' so the urls needs to be omitted
            return Ok(self.parse_data(clean))
        }
    }
    fn parse_data(&self, result: String) -> String {
        let mut data = HashMap::new();
        for c in result.lines() {
            let mut line = c.split(':');
            let key = line.next().unwrap();
            let value = match line.next() {
                Some(value) => value,
                None => continue
            };
            data.insert(key, value.trim());
        }
        return json::encode(&data).unwrap()
    }
    ///
    /// This function calls lookup() again if there is a another whois server
    ///
    ///
    fn parse_whois(&mut self, result: &str) -> String {
        let line = &result.lines().find(|i| i.contains("Whois Server:")).unwrap();
        let target = line.split_whitespace().last().unwrap().to_owned();
        self.new_whois = target;
        self.lookup().unwrap()
    }

    fn get_server(&self, target: &str) -> Result<String, &'static str> {
        let mut result = String::new();
        let mut client = TcpStream::connect("whois.iana.org:43").expect("Could not connect to server!");
        match client.write_all(format!("{}\n", target).as_bytes()) {
            Ok(_) => (),
            Err(_) => return Err("Could not write to client")
        }
        client.read_to_string(&mut result).unwrap();
        let line = &result.lines().find(|i| i.starts_with("whois:")).unwrap();
        let foo = line.split_whitespace().last().unwrap().to_owned();
        Ok(foo)
    }
}