Class: Whois::Server
- Inherits:
-
Object
- Object
- Whois::Server
- Defined in:
- lib/universal_ruby_whois/server.rb
Overview
Whois::Server
A Whois server object represents a single TLD mapped to a whois server hostname, and a set of regular expressions that are used to match against the raw whois output and determine various information about the domain name (currently registration status is supported on most domain TLDs, and creation date on a good number).
Defined Under Namespace
Classes: Unavailable
Constant Summary collapse
- DEFAULT_WHOIS_REGULAR_EXPRESSIONS =
The default regular expressions used when defining a new server if none are supplied.
{ :free => /(avail|free|no match|no entr|not taken|Available|Status\:\sNot\sRegistered|not registered|not found|No match for domain)/im, :registered => /(registered|Domain ID|domain name\s*\:|is active|Status\:\sActive|Not available|is not available|exists|\bregistrant\b|Created on|created\:)/im, :creation_date => /(Creation date|created on|created at|Commencement Date|Registration Date|domain_dateregistered|created\:)\s*[\:\.\]]*\s*([\w\-\:\ \/]+)[^\n\r]*[\n\r]/im, :expiration_date => /(expiration date|expires on|registered through|Renewal date|domain_datebilleduntil|expires\:)\s*[\:\.\]]*\s*([\w\-\:\ \/]+)[^\n\r]*[\n\r]/im, :error => /(error)/im, :server_unavailable => /(Sorry\. Server busy\.|too many requests|been blocked)/im }
- WHOIS_BIN =
The location of the ‘whois’ binary utility.
'/usr/bin/env whois'
Instance Attribute Summary collapse
-
#nic_server ⇒ Object
readonly
Returns the value of attribute nic_server.
-
#port ⇒ Object
readonly
Returns the value of attribute port.
-
#regexes ⇒ Object
readonly
Returns the value of attribute regexes.
-
#server_unavailable ⇒ Object
readonly
Returns the value of attribute server_unavailable.
-
#tld ⇒ Object
readonly
Returns the value of attribute tld.
-
#unavailable_response ⇒ Object
readonly
Returns the value of attribute unavailable_response.
Class Method Summary collapse
-
.define(tlds, server = nil, regexes = nil, &block) ⇒ Object
Whois Server Definition.
-
.define_from_iana(tld) ⇒ Object
Used as a fallback in case no specific WHOIS server is defined for a given TLD.
-
.define_single(*args, &block) ⇒ Object
:nodoc:.
-
.defined_tlds ⇒ Object
A list of strings representing all supported TLDs.
-
.domain_object_cache ⇒ Object
:nodoc:.
-
.domain_object_cache=(value) ⇒ Object
:nodoc:.
-
.find(domain) ⇒ Object
Look up a domain name.
-
.find_server_from_domain(domain) ⇒ Object
Find a TLD from a full domain name.
-
.list ⇒ Object
A hash of all of the known whois servers indexed by TLD.
- .list=(value) ⇒ Object
-
.run_command_with_timeout(command, timeout = 10, do_raise = false) ⇒ Object
:nodoc:.
-
.server_for_domain(domain) ⇒ Object
Determine the appropriate whois server object for a domain name.
-
.shell_escape(word) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#initialize(tld, nic_server = nil, options = nil) ⇒ Server
constructor
:nodoc:.
-
#raw_response(domain) ⇒ Object
Retrieve the raw WHOIS server output for a domain.
- #raw_response!(domain) ⇒ Object
- #unavailable? ⇒ Boolean
Constructor Details
#initialize(tld, nic_server = nil, options = nil) ⇒ Server
:nodoc:
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/universal_ruby_whois/server.rb', line 55 def initialize(tld, nic_server = nil, = nil) #:nodoc: @tld = tld.gsub(/^\.+/, '') ||= Hash.new @response_cache = Hash.new("") @nic_server = nic_server @port = .delete(:port) @regexes = .reverse_merge(DEFAULT_WHOIS_REGULAR_EXPRESSIONS) @regexes.each do |key, rx| next unless rx.kind_of?(Array) rx2 = Regexp.new(Regexp.escape(rx.first).gsub(/\s+/, '\s*')) rx2 = rx2.(rx[1]) rx2 = rx2.interpolate(/\s+/, '\s+') rx2.invert! if ((rx[2] == true) rescue false) @regexes[key] = rx2 end end |
Instance Attribute Details
#nic_server ⇒ Object (readonly)
Returns the value of attribute nic_server.
27 28 29 |
# File 'lib/universal_ruby_whois/server.rb', line 27 def nic_server @nic_server end |
#port ⇒ Object (readonly)
Returns the value of attribute port.
27 28 29 |
# File 'lib/universal_ruby_whois/server.rb', line 27 def port @port end |
#regexes ⇒ Object (readonly)
Returns the value of attribute regexes.
27 28 29 |
# File 'lib/universal_ruby_whois/server.rb', line 27 def regexes @regexes end |
#server_unavailable ⇒ Object (readonly)
Returns the value of attribute server_unavailable.
27 28 29 |
# File 'lib/universal_ruby_whois/server.rb', line 27 def server_unavailable @server_unavailable end |
#tld ⇒ Object (readonly)
Returns the value of attribute tld.
27 28 29 |
# File 'lib/universal_ruby_whois/server.rb', line 27 def tld @tld end |
#unavailable_response ⇒ Object (readonly)
Returns the value of attribute unavailable_response.
27 28 29 |
# File 'lib/universal_ruby_whois/server.rb', line 27 def unavailable_response @unavailable_response end |
Class Method Details
.define(tlds, server = nil, regexes = nil, &block) ⇒ Object
Whois Server Definition
Define a whois server for one or more TLDs. TLDs can be given as a single string or an array of strings representing TLDs that are handled by this server. The second argument should be a whois server hostname. If none is given, the generic output from the command line whois program is used (with any available redirection). An optional third argument is an array of regular expressions used to parse output from this particular server. A set of relatively liberal defaults is used if none (or only some) are given. Supported regex keys are :free, :registered, :creation_date and :error.
Regex Options
-
:registered
– If this regular expression matches the whois output, this domain is considered registered. -
:free
– If this regular expression matches the whois output, the domain is considered available. -
:error
– If this regular expression matches, an error is said to have occurred. -
:creation_date
– If this regular expression matches, the value of the second set of parentheses is parsed using ParseDate and used as the creation date for this domain.
Note, the preferred location for Whois::Server definitions is the server_list.rb file. Definitions should go from least specific to most specific, as subsequent definitions for a TLD will override previous ones.
47 48 49 50 51 52 53 |
# File 'lib/universal_ruby_whois/server.rb', line 47 def self.define(tlds, server = nil, regexes = nil, &block) tlds = tlds.kind_of?(Array) ? tlds : [tlds] tlds.each do |tld| define_single(tld, server, regexes, &block) end tlds end |
.define_from_iana(tld) ⇒ Object
Used as a fallback in case no specific WHOIS server is defined for a given TLD. An attempt will be made to search the IANA global registrar database to find a suitable whois server.
206 207 208 209 210 211 212 213 |
# File 'lib/universal_ruby_whois/server.rb', line 206 def self.define_from_iana(tld) iana_out = run_command_with_timeout("#{WHOIS_BIN} -h whois.iana.org #{shell_escape(tld.to_s)} 2>&1", 10, false) return false if iana_out.blank? return false unless iana_out =~ /Whois\s+Server\s+\(port ([\d]+)\)\: ([\w\-\.\_]+)/im port = $1 server = $2 define_single(tld.to_s, server, :port => port) end |
.define_single(*args, &block) ⇒ Object
:nodoc:
215 216 217 218 219 220 |
# File 'lib/universal_ruby_whois/server.rb', line 215 def self.define_single(*args, &block) #:nodoc: new_server = allocate new_server.send(:initialize, *args, &block) list[args.first.to_s] = new_server new_server end |
.defined_tlds ⇒ Object
A list of strings representing all supported TLDs.
90 91 92 |
# File 'lib/universal_ruby_whois/server.rb', line 90 def self.defined_tlds self.list.collect {|tld,server| tld.gsub(/^\./, '') } end |
.domain_object_cache ⇒ Object
:nodoc:
81 82 83 |
# File 'lib/universal_ruby_whois/server.rb', line 81 def self.domain_object_cache #:nodoc: @@domain_object_cache ||= Hash.new end |
.domain_object_cache=(value) ⇒ Object
:nodoc:
85 86 87 |
# File 'lib/universal_ruby_whois/server.rb', line 85 def self.domain_object_cache=(value) #:nodoc: @@domain_object_cache = value end |
.find(domain) ⇒ Object
127 128 129 130 131 132 |
# File 'lib/universal_ruby_whois/server.rb', line 127 def self.find(domain) domain = domain.to_s.strip.downcase return domain_object_cache[domain] unless domain_object_cache[domain].blank? return nil unless server = server_for_domain(domain) domain_object_cache[domain] = Whois::Domain.new(domain, server.tld) end |
.find_server_from_domain(domain) ⇒ Object
Find a TLD from a full domain name. There is special care to check for two part TLDs (such as .co.uk, .kids.us, etc) first and then to look for the last part alone.
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/universal_ruby_whois/server.rb', line 96 def self.find_server_from_domain(domain) # valid domain? return nil unless domain =~ /^((?:[-a-zA-Z0-9]+\.)+[a-zA-Z]{2,})$/ # start the searching. tld = nil parts = domain.split('.') # if the passed domain is more than two parts (. separated strings) # try to find the TLD from the last two parts (ie, .co.uk) if parts.size > 2 tld_string = parts[-2,2].join('.') tld = self.list[tld_string] end # if nothing was found, check for a match on the last part only. if tld.blank? tld_string = parts.last tld = self.list[tld_string] end return nil if !tld.kind_of?(Whois::Server) return tld end |
.list ⇒ Object
A hash of all of the known whois servers indexed by TLD
73 74 75 |
# File 'lib/universal_ruby_whois/server.rb', line 73 def self.list @@list ||= Hash.new end |
.list=(value) ⇒ Object
77 78 79 |
# File 'lib/universal_ruby_whois/server.rb', line 77 def self.list=(value) @@list = value end |
.run_command_with_timeout(command, timeout = 10, do_raise = false) ⇒ Object
:nodoc:
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/universal_ruby_whois/server.rb', line 222 def self.run_command_with_timeout(command, timeout = 10, do_raise = false) #:nodoc: @output = "" begin status = Timeout::timeout(10) do IO.popen(command, "r") do |io| @output << "#{io.read.to_s}" end end rescue Exception => e if do_raise raise "Running command \"#{command}\" timed out." end end @output.strip! @output end |
.server_for_domain(domain) ⇒ Object
Determine the appropriate whois server object for a domain name.
135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/universal_ruby_whois/server.rb', line 135 def self.server_for_domain(domain) server = self.find_server_from_domain(domain) # This will only work on single extension domains if server.blank? # && domain.scan(/(\.)/).length == 1 domain =~ /\.([\w\-]+)$/ tld = $1 self.define_from_iana(tld) return false unless server = self.find_server_from_domain(domain) end server end |
.shell_escape(word) ⇒ Object
:nodoc:
239 240 241 |
# File 'lib/universal_ruby_whois/server.rb', line 239 def self.shell_escape(word) #:nodoc: word.to_s.gsub(/[^\w\-\_\.]+/, '') rescue '' end |
Instance Method Details
#raw_response(domain) ⇒ Object
Retrieve the raw WHOIS server output for a domain.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/universal_ruby_whois/server.rb', line 152 def raw_response(domain) return nil if unavailable? return @response_cache[domain] if !@response_cache[domain].blank? @response_cache[domain] = "" if nic_server.kind_of?(Array) interpolate_vars = { '%DOMAIN%' => domain, '%DOMAIN_NO_TLD%' => domain.gsub(/\.#{tld.to_s}$/i, ''), '%TLD%' => tld } url = URI.parse(nic_server.first.dup.interpolate(interpolate_vars)) method = nic_server[1] || :post req = "Net::HTTP::#{method.to_s.capitalize}".constantize.new(url.path) form_data = nic_server[2].dup || {} form_data.each { |k,v| form_data[k] = v.interpolate(interpolate_vars) } req.set_form_data(form_data) res = begin Net::HTTP.new(url.host, url.port).start {|http| http.request(req) } rescue Net::HTTPBadResponse nil # Ignore these for now... end @response_cache[domain] = case res when Net::HTTPSuccess, Net::HTTPRedirection res.body else '' end elsif nic_server.to_s =~ /^http/ url = nic_server.gsub(/\%DOMAIN\%/, domain) @response_cache[domain] = Net::HTTP.get_response(URI.parse(url)).body else command = "#{WHOIS_BIN} #{('-h ' + @nic_server) unless @nic_server.blank?} #{self.class.shell_escape(domain)} 2>&1" @response_cache[domain] = Whois::Server.run_command_with_timeout(command, 10, true) end if match = regexes[:server_unavailable].match_with_inversion(@response_cache[domain]) @server_unavailable = true @unavailable_response = match[1] nil else @response_cache[domain] end end |
#raw_response!(domain) ⇒ Object
196 197 198 199 200 201 202 |
# File 'lib/universal_ruby_whois/server.rb', line 196 def raw_response!(domain) res = raw_response(domain) if !res || !res.respond_to?(:to_s) || res.blank? raise Whois::Server::Unavailable, "The WHOIS server for TLD #{tld.to_s} is currently unavailable. (response: #{unavailable_response})" end res end |
#unavailable? ⇒ Boolean
147 148 149 |
# File 'lib/universal_ruby_whois/server.rb', line 147 def unavailable? @server_unavailable ? true : false end |