Merged changes from jdong's branch into HEAD.
[selectricity] / lib / whois / whois.rb
1 #!/usr/bin/ruby -w
2
3 require 'socket'
4 require 'resolv'
5 require 'ipaddr'
6 require 'yaml'
7 require File.dirname(__FILE__) + '/server/server'
8
9 # Module for manage all Whois Class
10 module Whois
11
12     # Base exception of Whois
13     class WhoisException < Exception
14     end
15
16     # Exception of Whois who made report a bug
17     class WhoisExceptionError < WhoisException
18         def initialize (i)
19             WhoisException.initialize('Report a bug with error #{i} to http://rubyforge.org/projects/whois/')
20         end
21     end
22
23     # Class to get all information about Host or IP with the Whois request
24     class Whois
25
26         Version = '0.4.0'
27
28         attr_reader :all
29         attr_reader :server
30         attr_reader :ip
31         attr_reader :host
32         attr_accessor :host_search
33
34         # Initialize with a request. The request must be an IPv4, or a host string
35         #
36         # The first params now is :
37         #  * a string which a Ipv4, Ipv6 or a host.
38         #  * A IPAddr instance
39         #
40         # A second param, host_search is optionnal. By default he is false.
41         # If this value is true, a resolv host is made for know the host to this IPv4
42         def initialize(request, host_search=false)
43             @host_search = host_search
44             @host = nil
45             if request.instance_of? IPAddr
46                 if request.ipv4?
47                     @ip = request
48                     @server = server_ipv4
49                 elsif request.ipv6?
50                     @ip = request
51                     @server = server_ipv6
52                 else
53                     raise WhoisExceptionError.new(1)
54                 end
55             elsif Resolv::IPv4::Regex =~ request
56                 ipv4_init request
57                 unless self.server
58                     raise WhoisException.new("no server found for this IPv4 : #{request}")
59                 end
60             elsif Resolv::IPv6::Regex =~ request
61                 ipv6_init request
62                 unless self.server
63                     raise WhoisException.new("no server found for this Ipv6 : #{request}")
64                 end
65             else
66                 # Test if the request is an host or not
67                 begin
68                     ip = Resolv.getaddress request
69                     @ip = IPAddr.new ip
70                     @server = server_ipv4
71                     @host = request
72                 rescue Resolv::ResolvError
73                     raise WhoisException.new('host #{request} has no DNS result')
74                 end
75             end
76             
77             search_host unless @host
78         end
79         
80         # Ask of whois server
81         def search_whois
82             s = TCPsocket.open(self.server.server, 43)
83             s.write("#{self.ip.to_s}\n")
84             ret = ''
85             while s.gets do ret += $_ end
86             s.close
87             @all = ret
88         end
89
90
91         # Search the host for this IPv4, if the value host_search is true, else host = nil
92         def search_host
93             begin
94                 if @host_search
95                     @host = Resolv.getname self.ip.to_s
96                 else
97                     @host = nil
98                 end
99             rescue Resolv::ResolvError
100                 @host = nil
101             end
102         end
103     
104     private
105     
106         # Init value for a ipv4 request
107         def ipv4_init (ip)
108             @ip = IPAddr.new ip
109             @server = server_ipv4
110         end
111
112         # Init value for a ipv6 request
113         def ipv6_init (ip)
114             @ip = IPAddr.new ip
115             @server = server_ipv6
116         end
117
118         # Return the Server with the hash of mask
119         def server_with_hash(ip_hash)
120           # Sort by mask of Ip Range
121           arr_tmp = ip_hash.sort{|b,c| c[0][/\/(.+)/, 1].to_i <=> b[0][/\/(.+)/, 1].to_i}
122           arr_tmp.each do |l|
123             ip_range = IPAddr.new l[0]
124             if ip_range.include? self.ip
125               return Object.instance_eval("Server::#{l[1]}.new")
126             end
127           end
128         end
129
130         # Define the server of Whois in IPC6 list of YAML
131         def server_ipv6
132           ipv6_list = YAML::load_file(File.dirname(__FILE__) + '/data/ipv6.yaml')
133           server = server_with_hash(ipv6_list)
134           unless server.kind_of? Server::Server
135             raise WhoisException.new("no server found for this IPv6 : #{self.ip}")
136           else
137             return server
138           end
139         end
140         
141         # Define the server of Whois in IPV4 list of YAML
142         def server_ipv4
143           ipv4_list = YAML::load_file(File.dirname(__FILE__) + '/data/ipv4.yaml')
144           server = server_with_hash(ipv4_list)
145           unless server.kind_of? Server::Server
146             raise WhoisException.new("no server found for this IPv4 : #{self.ip}")
147           else
148             return server
149           end
150         end
151     end
152 end
153
154
155 if $0 == __FILE__
156   w = Whois::Whois.new '218.14.221.147'
157   puts w.search_whois
158 end

Benjamin Mako Hill || Want to submit a patch?