Permalink
Browse files

Added support for multipart answers. This is useful in case of thin s…

…ervers such as .com or .net because the parser needs to know all different responses in order to load all single scanners.
  • Loading branch information...
weppos committed Sep 20, 2009
1 parent f507e9e commit 3b9938c76c25c93a211073cf8c796fdb543ab9b4
View
@@ -5,6 +5,8 @@
* ADDED: whois.denic.de (.de TLD) parser [Aaron Mueller]
+* ADDED: support for multipart answers. This is useful in case of thin servers such as .com or .net because the parser needs to know all different responses in order to load all single scanners.
+
* CHANGED: extracted all scanners into separated classes in order to make easier extract shared features.
View
@@ -20,26 +20,28 @@
module Whois
class Response
+
attr_reader :server
- attr_reader :content
-
- def initialize(content, server = nil)
- @content = content
- @server = server
+ attr_reader :parts
+
+ def initialize(server, parts)
+ @parts = parts
+ @server = server
end
+
def to_s
- @content.to_s
+ content.to_s
end
def inspect
- @content.inspect
+ content.inspect
end
# Invokes <tt>match</tt> on response <tt>@content</tt>
# and returns the <tt>MatchData</tt> or <tt>nil</tt>.
def match(pattern)
- @content.match(pattern)
+ content.match(pattern)
end
# Returns true if the <tt>object</tt> is the same object,
@@ -56,6 +58,11 @@ def eql?(other)
self == other
end
+
+ def content
+ @content ||= parts.map { |response, host| response }.join("\n")
+ end
+
# Returns whether this response changed compared to <tt>other</tt>.
#
# Comparing the Response contents is not always as trivial as it seems.
@@ -80,7 +87,7 @@ def unchanged?(other)
# Invokes <tt>match</tt> and returns <tt>true</tt> if <tt>pattern</tt>
# matches <tt>@content</tt>, <tt>false</tt> otherwise.
def match?(pattern)
- !@content.match(pattern).nil?
+ !content.match(pattern).nil?
end
# Invokes <tt>match</tt> and returns the first useful match,
@@ -103,7 +110,7 @@ def i_m_feeling_lucky(pattern, &block)
# Lazy-loads and returns current response parser.
def parser
- @parser ||= self.class.parser_klass(@server).new(self)
+ @parser ||= self.class.parser_klass(parts.first.last).new(self)
end
@@ -119,24 +126,20 @@ def method_missing(method, *args, &block)
end
- def self.parser_klass(server)
- raise ParserError,
- "Unable to select a parser. " +
- "The server for this response is either nil or invalid." if server.nil? || server.host.nil?
-
- file = "whois/response/parsers/#{server.host}.rb"
+ def self.parser_klass(host)
+ file = "whois/response/parsers/#{host}.rb"
require file
- name = host_to_parser(server)
+ name = host_to_parser(host)
Parsers.const_get(name)
rescue LoadError
raise ParserNotFound,
- "Unable to find a parser for the server `#{server.host}'"
+ "Unable to find a parser for the server `#{host}'"
end
- def self.host_to_parser(server)
- server.host.to_s.
+ def self.host_to_parser(host)
+ host.to_s.
gsub(/\./, '_').
gsub(/(?:^|_)(.)/) { $1.upcase }
end
@@ -22,11 +22,11 @@ class Afilias < Base
def request(qstring)
response = ask_the_socket(qstring, "whois.afilias-grs.info", DEFAULT_WHOIS_PORT)
- endpoint = extract_referral(response)
- if endpoint
- response + "\n" + ask_the_socket(qstring, endpoint, DEFAULT_WHOIS_PORT)
- else
- response
+ push_buffer response, "whois.afilias-grs.info"
+
+ if endpoint = extract_referral(response)
+ response = ask_the_socket(qstring, endpoint, DEFAULT_WHOIS_PORT)
+ push_buffer response, endpoint
end
end
@@ -20,33 +20,55 @@ module Adapters
class Base
+ # Default Whois request port.
DEFAULT_WHOIS_PORT = 43
attr_reader :type
attr_reader :allocation
attr_reader :host
attr_reader :options
+ attr_reader :buffer
-
def initialize(type, allocation, host, options = {})
@type = type
@allocation = allocation
@host = host
@options = options || {}
end
-
+
+ # Performs a Whois query for <tt>qstring</tt>
+ # using current server adapter and returns a <tt>Whois::Response</tt>
+ # instance with the result of the request.
+ #
+ # server.query("google.com")
+ # # => Whois::Response
+ #
def query(qstring)
- response = request(qstring)
- Response.new(response, self)
+ with_buffer do |buffer|
+ request(qstring)
+ Response.new(self, buffer)
+ end
end
def request(qstring)
raise NotImplementedError
end
-
+
protected
+ def with_buffer(&block)
+ @buffer = []
+ result = yield(@buffer)
+ # @buffer = []
+ # result
+ end
+
+ # Store a pair of response and host in <tt>@buffer</tt>.
+ def push_buffer(response, host)
+ @buffer << [response, host]
+ end
+
def query_the_socket(qstring, host, port = nil)
ask_the_socket(qstring, host, port || options[:port] || DEFAULT_WHOIS_PORT)
end
@@ -22,11 +22,11 @@ class Pir < Base
def request(qstring)
response = ask_the_socket("FULL #{qstring}", "whois.publicinterestregistry.net", DEFAULT_WHOIS_PORT)
- endpoint = extract_referral(response)
- if endpoint
- response + "\n" + ask_the_socket(qstring, endpoint, DEFAULT_WHOIS_PORT)
- else
- response
+ push_buffer response, "whois.publicinterestregistry.net"
+
+ if endpoint = extract_referral(response)
+ response = ask_the_socket(qstring, endpoint, DEFAULT_WHOIS_PORT)
+ push_buffer response, endpoint
end
end
@@ -21,7 +21,8 @@ module Adapters
class Standard < Base
def request(qstring)
- query_the_socket(qstring, host)
+ response = query_the_socket(qstring, host)
+ push_buffer response, host
end
end
@@ -22,11 +22,11 @@ class Verisign < Base
def request(qstring)
response = ask_the_socket("=#{qstring}", host, DEFAULT_WHOIS_PORT)
- endpoint = extract_referral(response)
- if endpoint
- response + "\n" + ask_the_socket(qstring, endpoint, DEFAULT_WHOIS_PORT)
- else
- response
+ push_buffer response, host
+
+ if endpoint = extract_referral(response)
+ response = ask_the_socket(qstring, endpoint, DEFAULT_WHOIS_PORT)
+ push_buffer response, endpoint
end
end
@@ -14,6 +14,7 @@ def test_query
expected = response
@server.expects(:ask_the_socket).with("domain.foo", "whois.afilias-grs.info", 43).returns(response)
assert_equal expected, @server.query("domain.foo").to_s
+ assert_equal [[response, "whois.afilias-grs.info"]], @server.buffer
end
def test_query_with_referral
@@ -23,6 +24,7 @@ def test_query_with_referral
@server.expects(:ask_the_socket).with("domain.foo", "whois.afilias-grs.info", 43).returns(referral)
@server.expects(:ask_the_socket).with("domain.foo", "whois.belizenic.bz", 43).returns(response)
assert_equal expected, @server.query("domain.foo").to_s
+ assert_equal [[referral, "whois.afilias-grs.info"], [response, "whois.belizenic.bz"]], @server.buffer
end
end
@@ -14,6 +14,7 @@ def test_query
expected = response
@server.expects(:ask_the_socket).with("FULL domain.foo", "whois.publicinterestregistry.net", 43).returns(response)
assert_equal expected, @server.query("domain.foo").to_s
+ assert_equal [[response, "whois.publicinterestregistry.net"]], @server.buffer
end
def test_query_with_referral
@@ -23,6 +24,7 @@ def test_query_with_referral
@server.expects(:ask_the_socket).with("FULL domain.foo", "whois.publicinterestregistry.net", 43).returns(referral)
@server.expects(:ask_the_socket).with("domain.foo", "whois.iana.org", 43).returns(response)
assert_equal expected, @server.query("domain.foo").to_s
+ assert_equal [[referral, "whois.publicinterestregistry.net"], [response, "whois.iana.org"]], @server.buffer
end
end
@@ -13,13 +13,15 @@ def test_query
@server.expects(:ask_the_socket).with("domain.foo", "whois.foo", 43).returns("Whois Response")
response = @server.query("domain.foo")
assert_equal response, "Whois Response"
+ assert_equal [[response, "whois.foo"]], @server.buffer
end
def test_query_with_port
@server = @klass.new(:tld, ".foo", "whois.foo", { :port => 20 })
@server.expects(:ask_the_socket).with("domain.foo", "whois.foo", 20).returns("Whois Response")
response = @server.query("domain.foo")
assert_equal response, "Whois Response"
+ assert_equal [[response, "whois.foo"]], @server.buffer
end
end
@@ -14,6 +14,7 @@ def test_query
expected = response
@server.expects(:ask_the_socket).with("=domain.foo", "whois.foo", 43).returns(response)
assert_equal expected, @server.query("domain.foo").to_s
+ assert_equal [[response, "whois.foo"]], @server.buffer
end
def test_query_with_referral
@@ -23,6 +24,7 @@ def test_query_with_referral
@server.expects(:ask_the_socket).with("=domain.foo", "whois.foo", 43).returns(referral)
@server.expects(:ask_the_socket).with("domain.foo", "whois.tucows.com", 43).returns(response)
assert_equal expected, @server.query("domain.foo").to_s
+ assert_equal [[referral, "whois.foo"], [response, "whois.tucows.com"]], @server.buffer
end
end
@@ -2,6 +2,7 @@
require 'whois/response/parsers/whois.denic.de'
class WhoisDenicDeTest < Test::Unit::TestCase
+
TESTCASE_PATH = File.expand_path(File.dirname(__FILE__) + '/../testcases/responses/de')
def setup
@@ -135,20 +136,29 @@ def test_technical
end
def test_technical_for_avalable_domain
- assert_equal(nil, @class.new(load_response('/available.txt')).technical)
+ assert_equal nil,
+ @class.new(load_response('/available.txt')).technical
end
def test_nameservers
- assert_equal(%w(ns1.google.com ns4.google.com ns3.google.com ns2.google.com),
- @class.new(load_response('/registered.txt')).nameservers)
+ assert_equal %w(ns1.google.com ns4.google.com ns3.google.com ns2.google.com),
+ @class.new(load_response('/registered.txt')).nameservers
end
def test_nameservers_for_available_domain
- assert_equal(nil, @class.new(load_response('/available.txt')).nameservers)
+ assert_equal nil,
+ @class.new(load_response('/available.txt')).nameservers
end
+
protected
- def load_response(path)
- @response.new(File.read(TESTCASE_PATH + path), @server)
- end
+
+ def load_response(path)
+ new_response(@server, File.read(TESTCASE_PATH + path))
+ end
+
+ def new_response(server, content)
+ @response.new(server, [[content, server.host]])
+ end
+
end
Oops, something went wrong.

0 comments on commit 3b9938c

Please sign in to comment.