From 188792e65d4881d1d332a2c14911fc03e920c259 Mon Sep 17 00:00:00 2001 From: Benjamin Quorning Date: Sat, 11 Jul 2026 12:38:02 +0200 Subject: [PATCH 1/4] Compute IPv6 hex representation without IP#to_hex Replace the ruby-ip-specific IP#to_hex helper with a computation based on the integer address value, which produces an identical zero-padded 32-nibble lowercase hex string. This is a behavior-preserving refactor (verified equal for the values used here) that removes reliance on a ruby-ip-only method, paving the way for switching to the standard library ipaddr, which has no to_hex. Co-Authored-By: Claude Opus 4.8 --- lib/spf/macro_string.rb | 2 +- lib/spf/util.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/spf/macro_string.rb b/lib/spf/macro_string.rb index 946a8a2..3101679 100644 --- a/lib/spf/macro_string.rb +++ b/lib/spf/macro_string.rb @@ -81,7 +81,7 @@ def expand(context = nil) if IP::V4 === ip_address value = ip_address.to_addr elsif IP::V6 === ip_address - value = ip_address.to_hex.upcase.split('').join('.') + value = ip_address.to_i.to_s(16).rjust(32, '0').upcase.split('').join('.') else server.throw_result(:permerror, request, "Unexpected IP address version in request") end diff --git a/lib/spf/util.rb b/lib/spf/util.rb index 2539d8c..2b24ddb 100644 --- a/lib/spf/util.rb +++ b/lib/spf/util.rb @@ -86,7 +86,7 @@ def self.ip_address_reverse(ip_address) octets = ip_address.to_addr.split('.').first(ip_address.pfxlen / 8) return "#{octets .reverse.join('.')}.in-addr.arpa." when IP::V6 - nibbles = ip_address.to_hex .split('') .first(ip_address.pfxlen / 4) + nibbles = ip_address.to_i.to_s(16).rjust(32, '0').split('').first(ip_address.pfxlen / 4) return "#{nibbles.reverse.join('.')}.ip6.arpa." end end From 076580235b2aa9267a20d22bb5d93ef3142d2acc Mon Sep 17 00:00:00 2001 From: Benjamin Quorning Date: Sat, 11 Jul 2026 12:39:20 +0200 Subject: [PATCH 2/4] Extract CIDR host-bits detection into SPF::Util helper The ip4 and ip6 mechanisms both duplicate the check that flags a CIDR netblock whose address has bits set outside its network prefix. Move it into a single SPF::Util.ip_network_has_host_bits? predicate so the detection logic lives in one place. This is behavior-preserving; it also isolates the one piece of address math that must change when switching from ruby-ip (which exposes #offset) to ipaddr (which masks host bits away on construction), keeping that later switch a localized change. Co-Authored-By: Claude Opus 4.8 --- lib/spf/model.rb | 4 ++-- lib/spf/util.rb | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/spf/model.rb b/lib/spf/model.rb index dc61859..fa933c4 100644 --- a/lib/spf/model.rb +++ b/lib/spf/model.rb @@ -468,7 +468,7 @@ def parse_params(required = true) self.parse_ipv4_network(required) if IP === @ip_network @ip_netblocks << @ip_network - if @ip_network.respond_to?(:offset) && @ip_network.offset != 0 + if SPF::Util.ip_network_has_host_bits?(@ip_network) @errors << SPF::InvalidMechCIDRError.new( "Invalid CIDR netblock - bits in host portion of address of #{@ip_network}" ) @@ -503,7 +503,7 @@ class SPF::Mech::IP6 < SPF::Mech def parse_params(required = true) self.parse_ipv6_network(required) @ip_netblocks << @ip_network if IP === @ip_network - if @ip_network.respond_to?(:offset) && @ip_network.offset != 0 + if SPF::Util.ip_network_has_host_bits?(@ip_network) @errors << SPF::InvalidMechCIDRError.new( "Invalid CIDR netblock - bits in host portion of address of #{@ip_network}" ) diff --git a/lib/spf/util.rb b/lib/spf/util.rb index 2b24ddb..5dadeb9 100644 --- a/lib/spf/util.rb +++ b/lib/spf/util.rb @@ -68,6 +68,12 @@ def self.ipv6_address_is_ipv4_mapped(ipv6_address) return ipv6_address.ipv4_mapped? end + # Whether the address portion of a CIDR netblock has bits set outside the + # network prefix (e.g. "1.2.3.4/24" has host bits set, "1.2.3.0/24" does not). + def self.ip_network_has_host_bits?(ip_network) + return ip_network.respond_to?(:offset) && ip_network.offset != 0 + end + def self.ip_address_to_string(ip_address) unless IP::V4 === ip_address or IP::V6 === ip_address raise SPF::InvalidOptionValueError.new('IP::V4 or IP::V6 address expected') From 25454ba911df98cbb9d5ac69a488835fa75d3b33 Mon Sep 17 00:00:00 2001 From: Benjamin Quorning Date: Sat, 11 Jul 2026 12:40:23 +0200 Subject: [PATCH 3/4] Render ip4/ip6 mech params from the unmasked address Derive the ip4 and ip6 mechanism's textual params from the parsed address string (@ip_address) rather than from the @ip_network object, and reuse #params when building the InvalidMechCIDRError message instead of interpolating @ip_network directly. Under ruby-ip these produce identical output, so this is behavior-preserving (verified for the ip4/ip6 rendering cases). It matters for the upcoming switch to ipaddr: ipaddr masks host bits away on construction (1.2.3.4/24 becomes 1.2.3.0/24), so rendering from the network object would silently drop the host bits that SPF preserves in the mechanism's textual form and in the diagnostic. Sourcing params from the original address keeps that behavior across the switch. Co-Authored-By: Claude Opus 4.8 --- lib/spf/model.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/spf/model.rb b/lib/spf/model.rb index fa933c4..45e1ef1 100644 --- a/lib/spf/model.rb +++ b/lib/spf/model.rb @@ -470,7 +470,7 @@ def parse_params(required = true) @ip_netblocks << @ip_network if SPF::Util.ip_network_has_host_bits?(@ip_network) @errors << SPF::InvalidMechCIDRError.new( - "Invalid CIDR netblock - bits in host portion of address of #{@ip_network}" + "Invalid CIDR netblock - bits in host portion of address of #{self.params}" ) end end @@ -479,7 +479,8 @@ def parse_params(required = true) def params return nil unless @ip_network return @ip_network if String === @ip_network - result = @ip_network.to_addr + # Render the mechanism's original, unmasked address. + result = IP.new(@ip_address).to_addr if @ip_network.pfxlen != @default_ipv4_prefix_length result += "/#{@ip_network.pfxlen}" end @@ -505,7 +506,7 @@ def parse_params(required = true) @ip_netblocks << @ip_network if IP === @ip_network if SPF::Util.ip_network_has_host_bits?(@ip_network) @errors << SPF::InvalidMechCIDRError.new( - "Invalid CIDR netblock - bits in host portion of address of #{@ip_network}" + "Invalid CIDR netblock - bits in host portion of address of #{self.params}" ) end end @@ -513,7 +514,8 @@ def parse_params(required = true) def params return nil unless @ip_network return @ip_network if String === @ip_network - params = @ip_network.to_addr + # Render the mechanism's original, unmasked address. + params = IP.new(@ip_address).to_addr params += '/' + @ip_network.pfxlen.to_s if @ip_network.pfxlen != self.default_ipv6_prefix_length return params From daa7e8d0281cac92b45c4ba07da0392e744e0568 Mon Sep 17 00:00:00 2001 From: Benjamin Quorning Date: Sat, 11 Jul 2026 13:14:42 +0200 Subject: [PATCH 4/4] Switch from ruby-ip to standard library ipaddr Replace all use of the unmaintained ruby-ip gem with the standard library's IPAddr across lib/ and the specs, and drop the gem dependency. The prior refactors reduced the code changes to a near-mechanical substitution: IP.new(str) -> IPAddr.new(str) IP === x -> IPAddr === x IP::V4 === x -> x.ipv4? IP::V6 === x -> x.ipv6? #to_addr -> #to_s #pfxlen -> #prefix #contains?(o) -> #include?(o) (removes the IP#contains? monkey-patch) Two spots are not 1:1, both isolated by the earlier commits: - IPAddr masks host bits away on construction, so it cannot report them after the fact the way ruby-ip's #offset did. SPF::Util .ip_network_has_host_bits? now takes the original address string and compares it against the masked network. #params already renders from that unmasked address, so mechanism text and the InvalidMechCIDRError diagnostic are unchanged. - IPAddr::InvalidAddressError is an ArgumentError, so the existing "rescue ArgumentError" fallbacks in the network parsers still apply. The require 'ip' in eval.rb was unused and is dropped. With no code referencing ruby-ip any more, remove it from the gemspec and regenerate Gemfile.lock; this retires an unmaintained dependency (ruby-ip's last release was 0.9.3) with no replacement gem added. Full suite passes (95 examples); ip4/ip6 mechanism params and error output verified byte-identical to the ruby-ip behavior. Co-Authored-By: Claude Opus 4.8 --- Gemfile.lock | 2 -- lib/spf/eval.rb | 1 - lib/spf/macro_string.rb | 10 ++++---- lib/spf/model.rb | 49 ++++++++++++++++------------------------ lib/spf/request.rb | 12 +++++----- lib/spf/test/scenario.rb | 4 ++-- lib/spf/util.rb | 40 +++++++++++++++++--------------- spec/macrostring_spec.rb | 6 ++--- spec/request_spec.rb | 12 +++++----- spec/util_spec.rb | 16 ++++++------- spf.gemspec | 3 --- 11 files changed, 72 insertions(+), 83 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 921b06b..8e04e86 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,7 +2,6 @@ PATH remote: . specs: spf (0.1.1) - ruby-ip (~> 0.9.1) GEM remote: http://rubygems.org/ @@ -32,7 +31,6 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.10.0) rspec-support (3.10.3) - ruby-ip (0.9.3) simplecov (0.21.2) docile (~> 1.1) simplecov-html (~> 0.11) diff --git a/lib/spf/eval.rb b/lib/spf/eval.rb index 06ab245..10a6444 100644 --- a/lib/spf/eval.rb +++ b/lib/spf/eval.rb @@ -1,5 +1,4 @@ # encoding: ASCII-8BIT -require 'ip' require 'resolv' require 'spf/error' diff --git a/lib/spf/macro_string.rb b/lib/spf/macro_string.rb index 3101679..74eaff3 100644 --- a/lib/spf/macro_string.rb +++ b/lib/spf/macro_string.rb @@ -78,9 +78,9 @@ def expand(context = nil) elsif char == 'i' # RFC 4408, 8.1/20, 8.1/21 ip_address = request.ip_address ip_address = SPF::Util.ipv6_address_to_ipv4(ip_address) if SPF::Util.ipv6_address_is_ipv4_mapped(ip_address) - if IP::V4 === ip_address - value = ip_address.to_addr - elsif IP::V6 === ip_address + if ip_address.ipv4? + value = ip_address.to_s + elsif ip_address.ipv6? value = ip_address.to_i.to_s(16).rjust(32, '0').upcase.split('').join('.') else server.throw_result(:permerror, request, "Unexpected IP address version in request") @@ -92,9 +92,9 @@ def expand(context = nil) rh_parts = nil reverse = nil elsif char == 'v' # RFC 4408, 8.1/6/7 - if IP::V4 === request.ip_address + if request.ip_address.ipv4? value = 'in-addr' - elsif IP::V6 === request.ip_address + elsif request.ip_address.ipv6? value = 'ip6' else # Unexpected IP address version. diff --git a/lib/spf/model.rb b/lib/spf/model.rb index 45e1ef1..0c19082 100644 --- a/lib/spf/model.rb +++ b/lib/spf/model.rb @@ -1,18 +1,9 @@ # encoding: ASCII-8BIT -require 'ip' +require 'ipaddr' require 'spf/util' -class IP - def contains?(ip_address) - return ( - self.to_irange.first <= ip_address.to_i and - self.to_irange.last >= ip_address.to_i) - end -end - - class SPF::Record DEFAULT_QUALIFIER = '+'; end @@ -161,7 +152,7 @@ def parse_ipv4_network(required = false) self.parse_ipv4_address(required) self.parse_ipv4_prefix_length begin - @ip_network = IP.new("#{@ip_address}/#{@ipv4_prefix_length}") if @ip_address and @ipv4_prefix_length + @ip_network = IPAddr.new("#{@ip_address}/#{@ipv4_prefix_length}") if @ip_address and @ipv4_prefix_length rescue ArgumentError @ip_network = @ip_address end @@ -200,7 +191,7 @@ def parse_ipv6_network(required = false) self.parse_ipv6_address(required) self.parse_ipv6_prefix_length begin - @ip_network = IP.new("#{@ip_address}/#{@ipv6_prefix_length}") if @ip_address and @ipv6_prefix_length + @ip_network = IPAddr.new("#{@ip_address}/#{@ipv6_prefix_length}") if @ip_address and @ipv6_prefix_length rescue ArgumentError @ip_network = @ip_address end @@ -349,13 +340,13 @@ def match_in_domain(server, request, domain) rrs.each do |rr| if Resolv::DNS::Resource::IN::A === rr - network = IP.new("#{rr.address}/#{ipv4_prefix_length}") + network = IPAddr.new("#{rr.address}/#{ipv4_prefix_length}") @ip_netblocks << network - return true if network.contains?(request.ip_address) + return true if network.include?(request.ip_address) elsif Resolv::DNS::Resource::IN::AAAA === rr - network = IP.new("#{rr.address}/#{ipv6_prefix_length}") + network = IPAddr.new("#{rr.address}/#{ipv6_prefix_length}") @ip_netblocks << network - return true if network.contains?(request.ip_address_v6) + return true if network.include?(request.ip_address_v6) else # Unexpected RR type. # TODO: Generate debug info or ignore silently. @@ -466,9 +457,9 @@ class SPF::Mech::IP4 < SPF::Mech def parse_params(required = true) self.parse_ipv4_network(required) - if IP === @ip_network + if IPAddr === @ip_network @ip_netblocks << @ip_network - if SPF::Util.ip_network_has_host_bits?(@ip_network) + if SPF::Util.ip_network_has_host_bits?(@ip_address, @ip_network) @errors << SPF::InvalidMechCIDRError.new( "Invalid CIDR netblock - bits in host portion of address of #{self.params}" ) @@ -480,19 +471,19 @@ def params return nil unless @ip_network return @ip_network if String === @ip_network # Render the mechanism's original, unmasked address. - result = IP.new(@ip_address).to_addr - if @ip_network.pfxlen != @default_ipv4_prefix_length - result += "/#{@ip_network.pfxlen}" + result = IPAddr.new(@ip_address).to_s + if @ip_network.prefix != @default_ipv4_prefix_length + result += "/#{@ip_network.prefix}" end return result end def match(server, request, want_result = true) return false unless @ip_network - ip_network_v6 = IP::V4 === @ip_network ? + ip_network_v6 = (IPAddr === @ip_network and @ip_network.ipv4?) ? SPF::Util.ipv4_address_to_ipv6(@ip_network) : @ip_network - return ip_network_v6.contains?(request.ip_address_v6) + return ip_network_v6.include?(request.ip_address_v6) end end @@ -503,8 +494,8 @@ class SPF::Mech::IP6 < SPF::Mech def parse_params(required = true) self.parse_ipv6_network(required) - @ip_netblocks << @ip_network if IP === @ip_network - if SPF::Util.ip_network_has_host_bits?(@ip_network) + @ip_netblocks << @ip_network if IPAddr === @ip_network + if SPF::Util.ip_network_has_host_bits?(@ip_address, @ip_network) @errors << SPF::InvalidMechCIDRError.new( "Invalid CIDR netblock - bits in host portion of address of #{self.params}" ) @@ -515,14 +506,14 @@ def params return nil unless @ip_network return @ip_network if String === @ip_network # Render the mechanism's original, unmasked address. - params = IP.new(@ip_address).to_addr - params += '/' + @ip_network.pfxlen.to_s if - @ip_network.pfxlen != self.default_ipv6_prefix_length + params = IPAddr.new(@ip_address).to_s + params += '/' + @ip_network.prefix.to_s if + @ip_network.prefix != self.default_ipv6_prefix_length return params end def match(server, request, want_result = true) - return @ip_network.contains?(request.ip_address_v6) + return @ip_network.include?(request.ip_address_v6) end end diff --git a/lib/spf/request.rb b/lib/spf/request.rb index e5e2248..07e1f72 100644 --- a/lib/spf/request.rb +++ b/lib/spf/request.rb @@ -1,5 +1,5 @@ # encoding: ASCII-8BIT -require 'ip' +require 'ipaddr' require 'spf/error' @@ -101,9 +101,9 @@ def initialize(options = {}) return unless @ip_address - # Ensure ip_address is an IP object: - unless IP === @ip_address - @ip_address = IP.new(@ip_address) + # Ensure ip_address is an IPAddr object: + unless IPAddr === @ip_address + @ip_address = IPAddr.new(@ip_address) end # Convert IPv4 address to IPv4-mapped IPv6 address: @@ -111,9 +111,9 @@ def initialize(options = {}) if SPF::Util.ipv6_address_is_ipv4_mapped(@ip_address) @ip_address_v6 = @ip_address # Accept as IPv6 address as-is @ip_address = SPF::Util.ipv6_address_to_ipv4(@ip_address) - elsif IP::V4 === @ip_address + elsif @ip_address.ipv4? @ip_address_v6 = SPF::Util.ipv4_address_to_ipv6(@ip_address) - elsif IP::V6 === @ip_address + elsif @ip_address.ipv6? @ip_address_v6 = @ip_address else raise SPF::InvalidOptionValueError.new("Unexpected IP address version"); diff --git a/lib/spf/test/scenario.rb b/lib/spf/test/scenario.rb index 6e7940c..8aa60a2 100644 --- a/lib/spf/test/scenario.rb +++ b/lib/spf/test/scenario.rb @@ -1,6 +1,6 @@ require 'spf/test' -require 'ip' +require 'ipaddr' require 'yaml' #class Resolv::DNS::Resource::IN::SPF < Resolv::DNS::Resource::IN::TXT @@ -56,7 +56,7 @@ def self.new_from_yaml_struct(yaml_struct, options = {}) end end elsif type == 'A' or type == 'AAAA' - address = IP.new(data_struct).to_s + address = IPAddr.new(data_struct).to_s if type == 'A' record = Resolv::DNS::Resource::IN::A.new(address) else diff --git a/lib/spf/util.rb b/lib/spf/util.rb index 5dadeb9..df5d3bc 100644 --- a/lib/spf/util.rb +++ b/lib/spf/util.rb @@ -1,5 +1,5 @@ # encoding: ASCII-8BIT -require 'ip' +require 'ipaddr' require 'socket' require 'spf/error' @@ -51,15 +51,15 @@ def self.hostname end def self.ipv4_address_to_ipv6(ipv4_address) - unless IP::V4 === ipv4_address - raise SPF::InvalidOptionValueError.new('IP::V4 address expected') + unless IPAddr === ipv4_address and ipv4_address.ipv4? + raise SPF::InvalidOptionValueError.new('IPv4 address expected') end - return IP.new("::ffff:#{ipv4_address.to_addr}/#{ipv4_address.pfxlen - 32 + 128}") + return IPAddr.new("::ffff:#{ipv4_address.to_s}/#{ipv4_address.prefix - 32 + 128}") end def self.ipv6_address_to_ipv4(ipv6_address) - unless IP::V6 === ipv6_address and ipv6_address.ipv4_mapped? - raise SPF::InvalidOptionValueError, 'IPv4-mapped IP::V6 address expected' + unless IPAddr === ipv6_address and ipv6_address.ipv6? and ipv6_address.ipv4_mapped? + raise SPF::InvalidOptionValueError, 'IPv4-mapped IPv6 address expected' end return ipv6_address.native end @@ -70,29 +70,33 @@ def self.ipv6_address_is_ipv4_mapped(ipv6_address) # Whether the address portion of a CIDR netblock has bits set outside the # network prefix (e.g. "1.2.3.4/24" has host bits set, "1.2.3.0/24" does not). - def self.ip_network_has_host_bits?(ip_network) - return ip_network.respond_to?(:offset) && ip_network.offset != 0 + # IPAddr masks such bits away on construction, so detection compares the + # original, unmasked address string against the masked network. + def self.ip_network_has_host_bits?(ip_address_string, ip_network) + return false unless IPAddr === ip_network + return IPAddr.new(ip_address_string.to_s).to_i != ip_network.to_i + rescue IPAddr::Error + return false end def self.ip_address_to_string(ip_address) - unless IP::V4 === ip_address or IP::V6 === ip_address - raise SPF::InvalidOptionValueError.new('IP::V4 or IP::V6 address expected') + unless IPAddr === ip_address + raise SPF::InvalidOptionValueError.new('IP address expected') end - return ip_address.to_addr + return ip_address.to_s end def self.ip_address_reverse(ip_address) - unless IP::V4 === ip_address or IP::V6 === ip_address - raise SPF::InvalidOptionValueError.new('IP::V4 or IP::V6 address expected') + unless IPAddr === ip_address + raise SPF::InvalidOptionValueError.new('IP address expected') end # Treat IPv4-mapped IPv6 addresses as IPv4 addresses: ip_address = ipv6_address_to_ipv4(ip_address) if ip_address.ipv4_mapped? - case ip_address - when IP::V4 - octets = ip_address.to_addr.split('.').first(ip_address.pfxlen / 8) + if ip_address.ipv4? + octets = ip_address.to_s.split('.').first(ip_address.prefix / 8) return "#{octets .reverse.join('.')}.in-addr.arpa." - when IP::V6 - nibbles = ip_address.to_i.to_s(16).rjust(32, '0').split('').first(ip_address.pfxlen / 4) + elsif ip_address.ipv6? + nibbles = ip_address.to_i.to_s(16).rjust(32, '0').split('').first(ip_address.prefix / 4) return "#{nibbles.reverse.join('.')}.ip6.arpa." end end diff --git a/spec/macrostring_spec.rb b/spec/macrostring_spec.rb index e18dad7..a434a42 100644 --- a/spec/macrostring_spec.rb +++ b/spec/macrostring_spec.rb @@ -4,7 +4,7 @@ before(:each) do @request = SPF::Request.new( identity: 'strong-bad@email.example.com', - ip_address: IP.new('192.0.2.3') + ip_address: IPAddr.new('192.0.2.3') ) @server = SPF::Server.new end @@ -96,7 +96,7 @@ it 'expands the "v" macro letter to the string "ip6" if is ipv6' do request = SPF::Request.new( identity: 'strong-bad@email.example.com', - ip_address: IP.new('2001:DB8::CB01') + ip_address: IPAddr.new('2001:DB8::CB01') ) macro_str = described_class.new( text: '%{v}', @@ -215,7 +215,7 @@ it 'expands "%{ir}.%{v}._spf.%{d2}" correctly with an IPv6 request' do request = SPF::Request.new( identity: 'strong-bad@email.example.com', - ip_address: IP.new('2001:DB8::CB01') + ip_address: IPAddr.new('2001:DB8::CB01') ) macro_str = described_class.new( text: '%{ir}.%{v}._spf.%{d2}', diff --git a/spec/request_spec.rb b/spec/request_spec.rb index 92d4594..e94375b 100644 --- a/spec/request_spec.rb +++ b/spec/request_spec.rb @@ -38,8 +38,8 @@ end it 'has correct ip address' do - expect(request.ip_address.is_a?(IP)).to be_truthy - expect(request.ip_address).to eq IP.new('192.168.0.1') + expect(request.ip_address.is_a?(IPAddr)).to be_truthy + expect(request.ip_address).to eq IPAddr.new('192.168.0.1') end it 'has correct helo identity' do @@ -49,7 +49,7 @@ it 'creates sub-request object' do clone = request.new_sub_request(ip_address: '192.168.0.254') expect(clone.identity).to eq 'fred@example.com' - expect(clone.ip_address).to eq IP.new('192.168.0.254') + expect(clone.ip_address).to eq IPAddr.new('192.168.0.254') end end @@ -199,8 +199,8 @@ describe 'IP address validation' do - it 'accepts IP object for ip_address' do - ip_address = IP.new('192.168.0.1') + it 'accepts IPAddr object for ip_address' do + ip_address = IPAddr.new('192.168.0.1') request = SPF::Request.new( identity: 'fred@example.com', ip_address: ip_address @@ -213,7 +213,7 @@ identity: 'fred@example.com', ip_address: '::ffff:192.168.0.1' ) - expect(request.ip_address).to eq IP.new('192.168.0.1') + expect(request.ip_address).to eq IPAddr.new('192.168.0.1') end end diff --git a/spec/util_spec.rb b/spec/util_spec.rb index c13b0b2..de5f523 100644 --- a/spec/util_spec.rb +++ b/spec/util_spec.rb @@ -1,14 +1,14 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper') -require 'ip' +require 'ipaddr' -ipv4_address = IP.new('192.168.0.1') -ipv6_address_v4mapped = IP.new('::ffff:192.168.0.1') -ipv6_address = IP.new('2001:db8::1') +ipv4_address = IPAddr.new('192.168.0.1') +ipv6_address_v4mapped = IPAddr.new('::ffff:192.168.0.1') +ipv6_address = IPAddr.new('2001:db8::1') describe "SPF::Util.ipv4_address_to_ipv6" do - it "returns IP object" do - expect(SPF::Util.ipv4_address_to_ipv6(ipv4_address).is_a?(IP)).to be_truthy + it "returns IPAddr object" do + expect(SPF::Util.ipv4_address_to_ipv6(ipv4_address).is_a?(IPAddr)).to be_truthy end it "yields correct IPv4-mapped IPv6 address" do @@ -25,8 +25,8 @@ end describe "SPF::Util.ipv6_address_to_ipv4" do - it "returns IP object" do - expect(SPF::Util.ipv6_address_to_ipv4(ipv6_address_v4mapped).is_a?(IP)).to be_truthy + it "returns IPAddr object" do + expect(SPF::Util.ipv6_address_to_ipv4(ipv6_address_v4mapped).is_a?(IPAddr)).to be_truthy end it "yields correct IPv4 address" do diff --git a/spf.gemspec b/spf.gemspec index c20d0b7..dfcaa70 100644 --- a/spf.gemspec +++ b/spf.gemspec @@ -44,14 +44,12 @@ Gem::Specification.new do |s| s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then - s.add_runtime_dependency(%q, ["~> 0.9.1"]) s.add_development_dependency(%q, [">= 10"]) s.add_development_dependency(%q, ["~> 3.10"]) s.add_development_dependency(%q, [">= 6.3.0"]) s.add_development_dependency(%q, [">= 2.4.13"]) s.add_development_dependency(%q) else - s.add_dependency(%q, ["~> 0.9.1"]) s.add_dependency(%q, [">= 10"]) s.add_dependency(%q, ["~> 3.10"]) s.add_dependency(%q, [">= 6.3.0"]) @@ -59,7 +57,6 @@ Gem::Specification.new do |s| s.add_dependency(%q) end else - s.add_dependency(%q, ["~> 0.9.1"]) s.add_dependency(%q, [">= 10"]) s.add_dependency(%q, ["~> 3.10"]) s.add_dependency(%q, [">= 6.3.0"])