PageRenderTime 61ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/whois/server.rb

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