PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/whois/server.rb

https://github.com/sandropaganotti/whois
Ruby | 206 lines | 100 code | 24 blank | 82 comment | 21 complexity | 36597fced29c1ebacb33dc3cffae4a9c MD5 | raw file
Possible License(s): MIT
  1. #
  2. # = Ruby Whois
  3. #
  4. # An intelligent pure Ruby WHOIS client.
  5. #
  6. #
  7. # Category:: Net
  8. # Package:: Whois
  9. # Author:: Simone Carletti <weppos@weppos.net>
  10. # License:: MIT License
  11. #
  12. #--
  13. #
  14. #++
  15. require 'ipaddr'
  16. require 'whois/server/adapters/base'
  17. require 'whois/server/adapters/afilias'
  18. require 'whois/server/adapters/arpa'
  19. require 'whois/server/adapters/formatted'
  20. require 'whois/server/adapters/none'
  21. require 'whois/server/adapters/not_implemented'
  22. require 'whois/server/adapters/pir'
  23. require 'whois/server/adapters/standard'
  24. require 'whois/server/adapters/verisign'
  25. require 'whois/server/adapters/web'
  26. module Whois
  27. class Server
  28. @@definitions = {}
  29. # Searches the /definitions folder for definition files and loads them.
  30. # This method is automatically invoked when this file is parsed by the Ruby interpreter
  31. # (scroll down to the bottom of this file).
  32. def self.load_definitions
  33. Dir[File.dirname(__FILE__) + '/definitions/*.rb'].each { |file| load(file) }
  34. end
  35. # Returns the active definition list.
  36. # If <tt>type</tt>, returns only the definitions matching given type or
  37. # nil if no definition exists.
  38. #
  39. # Whois::Server.definitions
  40. # # => { :tld => [...], :ipv4 => [], ... }
  41. # Whois::Server.definitions(:tld)
  42. # # => [...]
  43. # Whois::Server.definitions(:invalid)
  44. # # => nil
  45. #
  46. def self.definitions(type = nil)
  47. if type.nil?
  48. @@definitions
  49. else
  50. @@definitions[type]
  51. end
  52. end
  53. # Defines a new server for <tt>:type</tt> queries.
  54. #
  55. # == Parameters
  56. #
  57. # type::
  58. # The type of whois server to define.
  59. # Allowed values are :tld, :ipv4, :ipv6.
  60. # allocation::
  61. # The allocation, range or hostname this server is responsible for.
  62. # host::
  63. # The server hostname.
  64. # options::
  65. # Additional options to customize Adpter behavior.
  66. #
  67. # ==== Examples
  68. #
  69. # # Define a server for the .it extension
  70. # Whois::Server.define :tld, ".it", "whois.nic.it"
  71. # # Define a new server for an range of IPv4 addresses
  72. # Whois::Server.define :ipv4, "61.192.0.0/12", "whois.nic.ad.jp"
  73. # # Define a new server for an range of IPv6 addresses
  74. # Whois::Server.define :ipv6, "2001:2000::/19", "whois.ripe.net"
  75. #
  76. def self.define(type, allocation, host, options = {})
  77. @@definitions[type] ||= []
  78. @@definitions[type] << [allocation, host, options]
  79. end
  80. # Creates a new server adapter from given arguments
  81. # and returns the server instance.
  82. #
  83. # By default returns a new Whois::Servers::Adapter::Standard instance.
  84. # You can customize the behavior passing a custom adapter class as :adapter option.
  85. #
  86. # Whois::Server.factory :tld, ".it", "whois.nic.it"
  87. # # => #<Whois::Servers::Adapter::Standard>
  88. # Whois::Server.factory :tld, ".it", "whois.nic.it", :option => Whois::Servers::Adapter::Custom
  89. # # => #<Whois::Servers::Adapter::Custom>
  90. #
  91. def self.factory(type, allocation, host, options = {})
  92. options = options.dup
  93. (options.delete(:adapter) || Adapters::Standard).new(type, allocation, host, options)
  94. end
  95. # Parses <tt>qstring</tt> and tries to guess the right server.
  96. #
  97. # It successfully detects the following query types:
  98. # * ipv6
  99. # * ipv4
  100. # * top level domains
  101. # * emails
  102. #
  103. # ==== Raises
  104. #
  105. # ServerNotFound::
  106. # When unable to find an appropriate whois server for <tt>qstring</tt>.
  107. #
  108. def self.guess(qstring)
  109. # IPv6 address (secure match)
  110. if valid_ipv6?(qstring)
  111. return find_for_ipv6(qstring)
  112. end
  113. # IPv4 address (secure match)
  114. if valid_ipv4?(qstring)
  115. return find_for_ipv4(qstring)
  116. end
  117. # Email Address (secure match)
  118. if qstring =~ /@/
  119. return find_for_email(qstring)
  120. end
  121. # TLD
  122. if server = find_for_tld(qstring)
  123. return server
  124. end
  125. # Gave Over
  126. raise ServerNotFound, "Unable to find a whois server for `#{qstring}'"
  127. end
  128. private
  129. def self.find_for_ipv6(qstring)
  130. ip = IPAddr.new(qstring)
  131. definitions(:ipv6).each do |definition|
  132. if IPAddr.new(definition.first).include?(ip)
  133. return factory(:ipv6, *definition)
  134. end
  135. end
  136. raise AllocationUnknown,
  137. "IP Allocation for `#{qstring}' unknown." +
  138. "Server definitions might be outdated."
  139. end
  140. def self.find_for_ipv4(qstring)
  141. ip = IPAddr.new(qstring)
  142. definitions(:ipv4).each do |definition|
  143. if IPAddr.new(definition.first).include?(ip)
  144. return factory(:ipv4, *definition)
  145. end
  146. end
  147. raise AllocationUnknown,
  148. "IP Allocation for `#{qstring}' unknown." +
  149. "Server definitions might be outdated."
  150. end
  151. def self.find_for_email(qstring)
  152. raise ServerNotSupported, "No whois server is known for email objects"
  153. end
  154. def self.find_for_tld(qstring)
  155. definitions(:tld).each do |definition|
  156. return factory(:tld, *definition) if /#{definition.first}$/ =~ qstring
  157. end
  158. nil
  159. end
  160. def self.valid_ipv4?(addr)
  161. if /\A(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\Z/ =~ addr
  162. return $~.captures.all? {|i| i.to_i < 256}
  163. end
  164. false
  165. end
  166. def self.valid_ipv6?(addr)
  167. # IPv6 (normal)
  168. return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*\Z/ =~ addr
  169. return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*)?\Z/ =~ addr
  170. return true if /\A::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*)?\Z/ =~ addr
  171. # IPv6 (IPv4 compat)
  172. return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*:/ =~ addr && valid_v4?($')
  173. return true if /\A[\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*:)?/ =~ addr && valid_v4?($')
  174. return true if /\A::([\dA-Fa-f]{1,4}(:[\dA-Fa-f]{1,4})*:)?/ =~ addr && valid_v4?($')
  175. false
  176. end
  177. end
  178. end
  179. Whois::Server.load_definitions