lib/spf/model.rb in spf-0.0.1 vs lib/spf/model.rb in spf-0.0.2

- old
+ new

@@ -83,10 +83,19 @@ :: (?: #{HEXWORD_PATTERN} : ){0,5} #{TWO_HEXWORDS_OR_IPV4_ADDRESS_PATTERN} | # :: | - :: " + attr_reader :ip_address, :ip_network, :ipv4_prefix_length, :ipv6_prefix_length + + def initialize + @ip_address = nil + @ip_network = nil + @ipv4_prefix_length = nil + @ipv6_prefix_length = nil + end + def self.new_from_string(text, options = {}) #term = SPF::Term.new(options, {:text => text}) options[:text] = text term = self.new(options) term.parse @@ -208,11 +217,11 @@ @text = options[:text] if not self.instance_variable_defined?(:@parse_text) @parse_text = @text.dup end if self.instance_variable_defined?(:@domain_spec) and - not @domain_spec.is_a?(SPF::MacroString) + not SPF::MacroString === @domain_spec @domain_spec = SPF::MacroString.new({:text => @domain_spec}) end end def parse @@ -349,11 +358,11 @@ params += '//' + @ipv6_prefix_length end return params end - def match(server, request) + def match(server, request, want_result = true) server.count_dns_interactive_term(request) return self.match_in_domain(server, request) end end @@ -364,11 +373,11 @@ def parse_params # No parameters. end - def match(server, request) + def match(server, request, want_result = true) return true end end @@ -382,11 +391,11 @@ def params return @domain_spec ? ':' + @domain_spec : nill end - def match(server, request) + def match(server, request, want_result = true) server.count_dns_interactive_term(request) domain = self.domain(server, request) packet = server.dns_lookup(domain, 'A') rrs = (packet.answer or server.count_void_dns_lookup(request)) @@ -412,12 +421,12 @@ result += "/#{@ip_network.masklen}" end return result end - def match(server, request) - ip_network_v6 = @ip_network.is_a?(IP::V4) ? + def match(server, request, want_result = true) + ip_network_v6 = IP::V4 === @ip_network ? SPF::Util.ipv4_address_to_ipv6(@ip_network) : @ip_network return ip_network_v6.contains?(request.ip_address_v6) end @@ -436,11 +445,11 @@ params += '/' + @ip_network.masklen if @ip_network.masklen != DEFAULT_IPV6_PREFIX_LENGTH return params end - def match(server, request) + def match(server, request, want_result = true) return @ip_network.contains?(request.ip_address_v6) end end @@ -454,11 +463,12 @@ def params return @domain_spec ? ':' + @domain_spec : nil end - def match(server, request) + def match(server, request, want_result = true) + server.count_dns_interactive_term(request) # Create sub-request with mutated authority domain: authority_domain = self.domain(server, request) sub_request = request.new_sub_request({:authority_domain => authority_domain}) @@ -466,21 +476,22 @@ # Process sub-request: result = server.process(sub_request) # Translate result of sub-request (RFC 4408, 5.9): - return true if - result.is_a?(SPF::Result::Pass) + return false unless want_result + return true if SPF::Result::Pass === result + return false if - result.is_a?(SPF::Result::Fail) or - result.is_a?(SPF::Result::SoftFail) or - result.is_a?(SPF::Result::Neutral) + SPF::Result::Fail === result or + SPF::Result::SoftFail === result or + SPF::Result::Neutral === result or server.throw_result('permerror', request, "Include domain '#{authority_domain}' has no applicable sender policy") if - result.is_a?(SPF::Result::None) + SPF::Result::None === result # Propagate any other results (including {Perm,Temp}Error) as-is: raise result end end @@ -506,11 +517,11 @@ params += '//' + @ipv6_prefix_length end return params end - def match(server, request) + def match(server, request, want_result = true) server.count_dns_interactive_term(request) target_domain = self.domain(server, request) mx_packet = server.dns_lookup(target_domain, 'MX') @@ -547,11 +558,11 @@ def params return @domain_spec ? ':' + @domain_spec : nil end - def match(server, request) + def match(server, request, want_result = true) return SPF::Util.valid_domain_for_ip_address( server, request, request.ip_address, self.domain(server, request)) ? true : false end end @@ -564,11 +575,11 @@ @text = options[:text] @domain_spec = options[:domain_spec] @parse_text = @text.dup unless @parse_text - if @domain_spec and not @domain_spec.is_a?(SPF::MacroString) + if @domain_spec and not SPF::MacroString === @domain_spec @domain_spec = SPF::MacroString.new({:text => @domain_spec}) end end def parse @@ -682,21 +693,21 @@ def process(server, request, result) server.count_dns_interactive_term(request) # Only perform redirection if no mechanism matched (RFC 4408, 6.1/1): - return unless result.is_a?(SPF::Result::NeutralByDefault) + return unless SPF::Result::NeutralByDefault === result # Create sub-request with mutated authorithy domain: authority_domain = @domain_spec.new({:server => server, :request => request}) sub_request = request.new_sub_request({:authority_domain => authority_domain}) # Process sub-request: result = server.process(sub_request) # Translate result of sub-request (RFC 4408, 6.1/4): - if result.is_a?(SPF::Result::None) + if SPF::Result::None === result server.throw_result(:permerror, request, "Redirect domain '#{authority_domain}' has no applicable sender policy") end # Propagate any other results as-is: @@ -787,17 +798,17 @@ mod_name = $2.downcase mod_class = MOD_CLASSES[mod_name] if mod_class # Known modifier. mod = mod_class.new_from_string(mod_text) - if mod.is_a?(SPF::GlobalMod) + if SPF::GlobalMod === mod # Global modifier. unless @global_mods[mod_name] raise SPF::DuplicateGlobalMod.new("Duplicate global modifier '#{mod_name}' encountered") end @global_mods[mod_name] = mod - elsif mod.is_a?(SPF::PositionalMod) + elsif SPF::PositionalMod === mod # Positional modifier, queue normally: @terms << mod end end else @@ -820,30 +831,30 @@ def eval(server, request) raise SPF::OptionRequiredError.new('SPF server object required for record evaluation') unless server raise SPF::OptionRequiredError.new('Request object required for record evaluation') unless request begin @terms.each do |term| - if term.is_a?(SPF::Mech) + if SPF::Mech === term + #if term.is_a?(SPF::Mech) # Term is a mechanism. mech = term - if mech.match(server, request) + if mech.match(server, request, request.ip_address != nil) result_name = RESULTS_BY_QUALIFIER[mech.qualifier] result_class = server.result_class(result_name) result = result_class.new([server, request, "Mechanism '#{term}' matched"]) mech.explain(server, request, result) raise result end - elsif term.is_a?(SPF::PositionalMod) + elsif SPF::PositionalMod === term # Term is a positional modifier. mod = term mod.process(server, request) - elsif term.is_a?(SPF::UnknownMod) + elsif SPF::UnknownMod === term # Term is an unknown modifier. Ignore it (RFC 4408, 6/3). else # Invalid term object encountered: - raise SPF::UnexpectedTermObjectError.new( - "Unexpected term object '#{term}' encountered.") + raise SPF::UnexpectedTermObjectError.new("Unexpected term object '#{term}' encountered.") end end rescue SPF::Result => result # Process global modifiers in ascending order of precedence: @global_mods.each do |global_mod| @@ -875,9 +886,13 @@ def scopes [:helo, :mfrom] end def version_tag + 'v=spf1' + end + + def self.version_tag 'v=spf1' end def version_tag_pattern " v=spf(1) (?= \\x20+ | $ ) "