-
-
Notifications
You must be signed in to change notification settings - Fork 283
/
server.rb
169 lines (144 loc) · 4.88 KB
/
server.rb
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#
# = Ruby Whois
#
# A pure Ruby WHOIS client.
#
#
# Category:: Net
# Package:: WWW::Delicious
# Author:: Simone Carletti <weppos@weppos.net>
# License:: MIT License
#
#--
#
#++
require 'yaml'
module Whois
class Server
# Parses an user-supplied string and tries to guess the right server.
def self.whichwhois(string)
# TODO: IPv6 address
# TODO: RPSL hierarchical objects
# Email Address
if string =~ /@/
find_for_email(string)
end
# TODO: NSI NIC
# TODO: ASN32
# TODO: IP
# Domain
find_for_domain(string)
# TODO: guessing
# TODO: game-over
end
def self.find_for_email(string)
raise ServerNotSupported, "No whois server is known for email objects"
end
def self.find_for_domain(string)
server = servers.each do |ext, srv|
break(srv) if /#{ext}$/ =~ string
end
if server.nil?
# you might want to remove this raise statement
# to make the guessing more clever.
raise ServerNotFound, "Unable to find a whois server for `#{string}'"
elsif server =~ /^WEB (.*)/
raise WebInterfaceError, "This TLD has no whois server, " +
"but you can access the whois database at `#{$1}'"
elsif server == "NONE"
raise NoInterfaceError, "This TLD has no whois server"
elsif server == "CRSNIC"
query_crsnic(string)
elsif server == "PIR"
query_pir(string)
elsif server == "AFILIAS"
query_afilias(string)
elsif server == "NICCC"
query_niccc(string)
elsif server == "ARPA"
whichwhois(inaddr_to_ip(string))
else
server
end
end
def self.servers
@@servers ||= YAML.load_file(File.dirname(__FILE__) + "/servers.yml")
end
private
def self.ask_the_socket(query, server, port = 43)
client = TCPSocket.open(server, port)
client.write("#{query}\r\n")
client.read
ensure
client.close if client
end
# FIXME: incomplete query handler
# 1. if not found, the query returns the response
# 2. if found, the query could return the response
# 3. if found, the query could return a referral
def self.query_crsnic(query)
response = ask_the_socket("=#{query}", "whois.crsnic.net")
if response =~ /Domain Name:/ && response =~ /Whois Server: (\S+)/
return $1
else
# FIXME: Here's the full response. ARGH!
end
end
# FIXME: incomplete query handler
# It behavies like query_crsnic because the whois belongs to verisign.
def self.query_niccc(query)
response = ask_the_socket("=#{query}", "whois.nic.cc")
if response =~ /Domain Name:/ && response =~ /Whois Server: (\S+)/
return $1
else
# FIXME: Here's the full response. ARGH!
end
end
# FIXME: incomplete query handler
# 1. if not found, the query returns the response
# 2. if found, the query could return the response (95% probs)
# 3. if found, the query could return a referral
def self.query_pir(query)
response = ask_the_socket("FULL #{query}", "whois.publicinterestregistry.net")
if response =~ /Registrant Name:SEE SPONSORING REGISTRAR/ &&
response =~ /Registrant Street1:Whois Server:(\S+)/
return $1
else
# FIXME: Here's the full response. ARGH!
# Usually this happens for the 95% of queries. Isn't that wonderful?
end
end
# FIXME: incomplete query handler
# 1. if not found, the query returns the response
# 2. if found, the query could return the response
# 3. if found, the query could return a referral
def self.query_afilias(query)
response = ask_the_socket(query, "whois.afilias-grs.info")
# TEST: ensure regexp matches
if response =~ /Domain Name:/ && response =~ /Whois Server:(\S+)/
return $1
else
# FIXME: Here's the full response. ARGH!
end
end
# "127.1.168.192.in-addr.arpa" => "192.168.1.127"
# "1.168.192.in-addr.arpa" => "192.168.1.0"
# "168.192.in-addr.arpa" => "192.168.0.0"
# "192.in-addr.arpa" => "192.0.0.0"
# "in-addr.arpa" => "0.0.0.0"
def self.inaddr_to_ip(query)
unless /^([0-9]{1,3}\.?){0,4}in-addr\.arpa$/ =~ query
raise ServerError, "Invalid .in-addr.arpa address"
end
a, b, c, d = query.scan(/[0-9]{1,3}\./).reverse
[a, b, c, d].map do |token|
token = (token ||= 0).to_i
if token <= 255 && token >= 0
token
else
raise ServerError, "Invalid .in-addr.arpa token `#{token}'"
end
end.join(".")
end
end
end