Class: Whois::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/whois/server.rb,
lib/whois/server/adapters/web.rb,
lib/whois/server/adapters/arin.rb,
lib/whois/server/adapters/arpa.rb,
lib/whois/server/adapters/base.rb,
lib/whois/server/adapters/none.rb,
lib/whois/server/socket_handler.rb,
lib/whois/server/adapters/afilias.rb,
lib/whois/server/adapters/standard.rb,
lib/whois/server/adapters/verisign.rb,
lib/whois/server/adapters/formatted.rb,
lib/whois/server/adapters/not_implemented.rb

Overview

The Server class has two important roles:

  1. it acts as a database for the WHOIS server definitions

  2. it is responsible for selecting the right adapter used to handle the query to the WHOIS server(s).

Defined Under Namespace

Modules: Adapters Classes: SocketHandler

Constant Summary collapse

TYPES =

Returns the definition types.

Returns:

  • (Array<Symbol>)

    the definition types

[
  TYPE_TLD = :tld,
  TYPE_IPV4  = :ipv4,
  TYPE_IPV6  = :ipv6,
  TYPE_ASN16 = :asn16,
  TYPE_ASN32 = :asn32,
].freeze

Class Method Summary collapse

Class Method Details

.clear_definitionsvoid

This method returns an undefined value.

Clears the definition and reset them to an empty list.



59
60
61
# File 'lib/whois/server.rb', line 59

def clear_definitions
  @definitions = {}
end

.define(type, allocation, host, options = EMPTY_HASH) ⇒ void

This method returns an undefined value.

Defines a new server for :type queries.

Examples:


# Define a server for the .it extension
Whois::Server.define :tld, "it", "whois.nic.it"

# Define a new server for an range of IPv4 addresses
Whois::Server.define :ipv4, "61.192.0.0/12", "whois.nic.ad.jp"

# Define a new server for an range of IPv6 addresses
Whois::Server.define :ipv6, "2001:2000::/19", "whois.ripe.net"

# Define a new server with a custom adapter
Whois::Server.define :tld, "test", nil,
  :adapter => Whois::Server::Adapter::None

# Define a new server with a custom adapter and options
Whois::Server.define :tld, "ar", nil,
  :adapter => Whois::Server::Adapters::Web,
  :url => "http://www.nic.ar/"

Parameters:

  • type (Symbol)

    The type of WHOIS server to define. Known values are :tld, :ipv4, :ipv6.

  • allocation (String)

    The allocation, range or hostname, this server is responsible for.

  • host (String, nil)

    The server hostname. Use nil if unknown or not available.

  • options (Hash) (defaults to: EMPTY_HASH)

    Optional definition properties.

Options Hash (options):

  • :adapter (Class) — default: Whois::Server::Adapters::Standard

    This option has a special meaning and determines the adapter Class to use. Defaults to Whois::Server::Adapters::Standard unless specified. All the other options are passed directly to the adapter which can decide how to use them.



158
159
160
161
162
163
# File 'lib/whois/server.rb', line 158

def define(type, allocation, host, options = EMPTY_HASH)
  TYPES.include?(type) or
    raise(ArgumentError, "`#{type}` is not a valid definition type")

  _definitions(type)[allocation] = [allocation, host, options.freeze]
end

.definitions(type) ⇒ { Symbol => Array }, Array<Hash>

Lookup and returns the definition list for given ‘type`.

Examples:

Return the definitions for given key.


Whois::Server.definitions(:tld)
# => [...]

Whois::Server.definitions(:invalid)
# => nil

Parameters:

  • type (Symbol)

    The type of WHOIS server to lookup. See Whois::Server::TYPES for valid types.

Returns:

  • ({ Symbol => Array })

    The definition Hash if type is nil.

  • (Array<Hash>)

    The definitions for given type if type is not nil and type exists.



114
115
116
117
118
119
# File 'lib/whois/server.rb', line 114

def definitions(type)
  TYPES.include?(type) or
    raise(ArgumentError, "`#{type}` is not a valid definition type")

  _definitions(type).values
end

.factory(type, allocation, host, options = {}) ⇒ Whois::Server::Adapters::Base

Creates a new server adapter from given arguments and returns the server instance.

By default, returns a new Whois::Server::Adapters::Standard instance. You can customize the behavior passing a custom adapter class as :adapter option.

Whois::Server.factory :tld, "it", "whois.nic.it"
# => #<Whois::Servers::Adapter::Standard>

Whois::Server.factory :tld, "it", "whois.nic.it",
  :option => Whois::Servers::Adapter::Custom
# => #<Whois::Servers::Adapter::Custom>

Please note that any adapter is responsible for a limited set of queries, which should be included in the range of the allocation parameter. Use guess if you are not sure which adapter is the right one for a specific string.

Parameters:

  • type (Symbol)

    The type of WHOIS server to define. Known values are :tld, :ipv4, :ipv6.

  • allocation (String)

    The allocation, range or hostname, this server is responsible for.

  • host (String, nil)

    The server hostname. Use nil if unknown or not available.

  • options (Hash) (defaults to: {})

    Optional definition properties.

Options Hash (options):

  • :adapter (Class) — default: Whois::Server::Adapters::Standard

    This option has a special meaning and determines the adapter Class to use. Defaults to Whois::Server::Adapters::Standard unless specified. All the other options are passed directly to the adapter which can decide how to use them.

Returns:



199
200
201
202
203
204
# File 'lib/whois/server.rb', line 199

def factory(type, allocation, host, options = {})
  options = options.dup
  adapter = options.delete(:adapter) || Adapters::Standard
  adapter = Adapters.const_get(camelize(adapter)) unless adapter.respond_to?(:new)
  adapter.new(type, allocation, host, options)
end

.find_for_asn(string) ⇒ Whois::Server::Adapters::Base?

Searches for definition that matches given ASN string.

Parameters:

  • string (String)

Returns:

Raises:

  • (Whois::AllocationUnknown)

    when the IP doesn’t have a specific known allocation that matches one of the existing server definitions.



321
322
323
324
325
326
327
328
329
330
# File 'lib/whois/server.rb', line 321

def find_for_asn(string)
  asn = string[/\d+/].to_i
  asn_type = asn <= 65_535 ? TYPE_ASN16 : TYPE_ASN32
  _definitions(asn_type).each_value do |definition|
    if (range = definition.first.split.map(&:to_i)) && asn >= range.first && asn <= range.last
      return factory(asn_type, *definition)
    end
  end
  raise AllocationUnknown, "Unknown AS number - `#{asn}'."
end

.find_for_domain(string) ⇒ Whois::Server::Adapters::Base?

Searches for definition that matches given domain.

Parameters:

  • string (String)

Returns:



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/whois/server.rb', line 295

def find_for_domain(string)
  token = string
  defs  = _definitions(TYPE_TLD)

  while token != ""
    if (found = defs[token])
      return factory(:tld, *found)
    else
      index = token.index(".")
      break if index.nil?

      token = token[(index + 1)..]
    end
  end

  nil
end

.find_for_email(string) ⇒ Object

Searches for definition that matches given email.

Parameters:

  • string (String)

Raises:



286
287
288
# File 'lib/whois/server.rb', line 286

def find_for_email(string)
  raise ServerNotSupported, "No WHOIS server is known for email objects"
end

.find_for_ip(string) ⇒ Whois::Server::Adapters::Base?

Searches for definition that matches given IP.

Parameters:

  • string (String)

Returns:

Raises:

  • (Whois::AllocationUnknown)

    when the IP doesn’t have a specific known allocation that matches one of the existing server definitions.



267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/whois/server.rb', line 267

def find_for_ip(string)
  begin
    ip = IPAddr.new(string)
    type = ip.ipv4? ? TYPE_IPV4 : TYPE_IPV6
    _definitions(type).each_value do |definition|
      return factory(type, *definition) if IPAddr.new(definition.first).include?(ip)
    end
  rescue ArgumentError
    # continue
    nil
  end
  raise AllocationUnknown, "IP Allocation for `#{string}' unknown"
end

.guess(string) ⇒ Whois::Server::Adapters::Base

Parses string and tries to guess the right server.

It successfully detects the following query types:

  • ipv6

  • ipv4

  • top level domains (e.g. .com, .net, .it)

  • domain names (e.g. google.com, google.net, google.it)

  • emails

Note that not all query types actually have a corresponding adapter. For instance, the following request will result in a Whois::ServerNotSupported exception.

Whois::Server.guess "[email protected]"

Parameters:

  • string (String)

Returns:

Raises:

  • (Whois::AllocationUnknown)

    when the input is an IP, but the IP doesn’t have a specific known allocation that matches one of the existing server definitions.

  • (Whois::ServerNotFound)

    when unable to find an appropriate WHOIS adapter. In most of the cases, the input is not recognised as one of the supported query types.

  • (Whois::ServerNotSupported)

    when the string type is detected, but the object type doesn’t have any supported WHOIS adapter associated.



236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/whois/server.rb', line 236

def guess(string)
  # Top Level Domain match
  return factory(:tld, ".", "whois.iana.org") if matches_tld?(string)

  # IP address (secure match)
  return find_for_ip(string) if matches_ip?(string)

  # Email Address (secure match)
  return find_for_email(string) if matches_email?(string)

  # Domain Name match
  if (server = find_for_domain(string))
    return server
  end

  # ASN match
  return find_for_asn(string) if matches_asn?(string)

  # Game Over
  raise ServerNotFound, "Unable to find a WHOIS server for `#{string}'"
end

.load_definitionsvoid

This method returns an undefined value.

Searches the /definitions folder for definition files and loads them. This method is automatically invoked when this file is parsed by the Ruby interpreter (scroll down to the bottom of this file).



68
69
70
71
# File 'lib/whois/server.rb', line 68

def load_definitions
  clear_definitions
  Dir[File.expand_path('../../data/*.json', __dir__)].each { |f| load_json(f) }
end

.load_json(file) ⇒ void

This method returns an undefined value.

Loads the definitions from a JSON file.

Parameters:

  • file (String)

    The path to the definition file.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/whois/server.rb', line 78

def load_json(file)
  type = File.basename(file, File.extname(file)).to_sym
  JSON.parse(File.read(file)).each do |allocation, settings|
    next if allocation == "_"

    settings.reject! { |k, _| k.start_with?("_") }
    host = settings.delete("host")
    host = intern_string(host) if host
    options = if settings.empty?
                EMPTY_HASH
              else
                settings.to_h { |k, v| [k.to_sym, v.is_a?(String) ? intern_string(v) : v] }.freeze
              end
    define(type, allocation, host, options)
  end
end