# # = Ruby Whois # # An intelligent pure Ruby WHOIS client and parser. # # # Category:: Net # Package:: Whois # Author:: Simone Carletti # License:: MIT License # #-- # #++ require 'whois/answer/parser' require 'whois/answer/parser/base' module Whois class Answer attr_reader :server attr_reader :parts def initialize(server, parts) @parts = parts @server = server end def to_s content.to_s end def inspect content.inspect end # Invokes match on answer @content # and returns the MatchData or nil. def match(pattern) content.match(pattern) end # Invokes match and returns true if pattern # matches @content, false otherwise. def match?(pattern) !content.match(pattern).nil? end # Returns true if the object is the same object, # or is a string and has the same content. def ==(other) (other.equal?(self)) || # This option should be deprecated (other.instance_of?(String) && other == self.to_s) || (other.instance_of?(Answer) && other.to_s == self.to_s) end # Delegates to ==. def eql?(other) self == other end # Returns the content of this answer as a string. # This method joins all answer parts into a single string # and separates each response with a newline character. # # answer = Whois::Answer.new([Whois::Answer::Part.new("First answer.")]) # answer.content # # => "First answer." # # answer = Whois::Answer.new([Whois::Answer::Part.new("First answer."), Whois::Answer::Part.new("Second answer.")]) # answer.content # # => "First answer.\nSecond answer." # def content @content ||= parts.map(&:response).join("\n") end # Returns whether this answer changed compared to other. # # Comparing the Answer contents is not always as trivial as it seems. # Whois servers sometimes inject dynamic method into the whois answer such as # the timestamp the request was generated. # This causes two answers to be different even if they actually should be considered equal # because the registry data didn't change. # # This method should provide a bulletproof way to detect whether this answer # changed if compared with other. def changed?(other) !unchanged?(other) end # The opposite of changed?. def unchanged?(other) self == other || parser.unchanged?(other.parser) end # Lazy-loads and returns a Whois::Answer::Parser proxy for current answer. def parser @parser ||= Parser.new(self) end # Returns a Hash containing all supported properties for this Answer # along with corresponding values. def properties hash = {} Parser.properties.each { |property| hash[property] = send(property) } hash end # Returns true if the property passed as symbol # is supported by any available parser for this answer. # See also Whois::Answer::Parser.supported?. def property_supported?(property) parser.property_supported?(property) end protected # Delegates all method calls to the internal parser. def method_missing(method, *args, &block) if Parser.properties.include?(method) self.class.class_eval foo = %{ def #{method}(*args, &block) if property_supported?(:#{method}) parser.#{method}(*args, &block) else nil end end }, __FILE__, __LINE__ send(method, *args, &block) elsif method.to_s =~ /([a-z_]+)\?/ and Parser.properties.include?($1.to_sym) self.class.class_eval %{ def #{$1}? !#{$1}.nil? end }, __FILE__, __LINE__ send($1) else super end end end end