coppertone 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/README.md +15 -3
- data/lib/coppertone/directive.rb +4 -0
- data/lib/coppertone/macro_string.rb +7 -0
- data/lib/coppertone/mechanism/domain_spec_mechanism.rb +5 -0
- data/lib/coppertone/mechanism/include.rb +9 -0
- data/lib/coppertone/mechanism.rb +4 -0
- data/lib/coppertone/modifier/base.rb +8 -0
- data/lib/coppertone/modifier/redirect.rb +11 -0
- data/lib/coppertone/modifier/unknown.rb +8 -0
- data/lib/coppertone/null_macro_context.rb +4 -5
- data/lib/coppertone/record.rb +26 -0
- data/lib/coppertone/record_evaluator.rb +6 -8
- data/lib/coppertone/record_term_parser.rb +1 -0
- data/lib/coppertone/redirect_record_finder.rb +20 -0
- data/lib/coppertone/version.rb +1 -1
- data/lib/coppertone.rb +1 -0
- data/spec/mechanism/a_spec.rb +31 -1
- data/spec/mechanism/all_spec.rb +2 -0
- data/spec/mechanism/exists_spec.rb +28 -3
- data/spec/mechanism/include_spec.rb +26 -1
- data/spec/mechanism/ip4_spec.rb +6 -0
- data/spec/mechanism/ip6_spec.rb +6 -0
- data/spec/mechanism/mx_spec.rb +62 -2
- data/spec/mechanism/ptr_spec.rb +4 -0
- data/spec/modifier/exp_spec.rb +35 -0
- data/spec/modifier/redirect_spec.rb +35 -0
- data/spec/redirect_record_finder_spec.rb +4 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d50206e3df522c6100a46e2a6f64989d10da5774
|
4
|
+
data.tar.gz: 773a9709e679f5d45e5a7a6f779112ffea0e9aff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2752ba8667d8f7d8458cfa0429a4140f59a42af7a7ad52881b5a75f1e4881d2b4038a5fb1a8ca22dff54ca7301941da42400b94f87ddf5b6972ffb9de3900c06
|
7
|
+
data.tar.gz: 90cb6889a3ed66eb50663e0681ffc011641d20329c0ffb86b7d6af780d40189beb36fac80c78f4e1107295134d643a104bd7933c10ca99d265e693ff0590b90a
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -17,13 +17,15 @@ One of the challenges of writing a gem that is intended to implement a specifica
|
|
17
17
|
3. Coppertone defaults to using the DNS term and lookup limits defined in [RFC 7208](http://tools.ietf.org/html/rfc7208#section-4.6.4), but makes these limits configurable.
|
18
18
|
4. Coppertone does not do TLD validation on domains encountered in SPF processing. Domains are syntactically validated, but the TLD value is not checked against the public access list.
|
19
19
|
|
20
|
+
To ensure compliance with [RFC 7208](http://tools.ietf.org/html/rfc7208), Coppertone includes the latest published version of the [OpenSPF specs](http://www.openspf.org/Test_Suite) in its RSpec test suite.
|
21
|
+
|
20
22
|
If you'd like to suggest amending these guidelines, please open an issue for discussion. Suggestions driven by real world behavior - divergences implemented by major mail server vendors or MTAs will be prioritized.
|
21
23
|
|
22
24
|
## Requirements
|
23
25
|
|
24
|
-
Coppertone supports MRI 2.0 and up - earlier MRI rubies are not supported. JRuby and Rubinius
|
26
|
+
Coppertone supports MRI 2.0 and up - earlier MRI rubies are not supported. JRuby 1.7.16+ and Rubinius 2.2+ are also supported.
|
25
27
|
|
26
|
-
Coppertone does not require Rails.
|
28
|
+
Coppertone does not require Rails, although it does depend on ActiveSupport.
|
27
29
|
|
28
30
|
## Installation
|
29
31
|
|
@@ -43,7 +45,17 @@ Or install it yourself as:
|
|
43
45
|
|
44
46
|
## Usage
|
45
47
|
|
46
|
-
|
48
|
+
To use Coppertone as a simple SPF checker (as you might, for example, if you were bundling it in a receiving SMTP server), you may use the `Coppertone::SpfService#authenticate_email` method.
|
49
|
+
|
50
|
+
For example, were you authenticating an email sent by an SMTP server with IP address 1.2.3.4, advertising a HELO domain of 'mailserver123.example.org' and sent from 'somerandomperson@example.org', you'd invoke the method as follows:
|
51
|
+
|
52
|
+
result = Coppertone::SpfService#authenticate_email('1.2.3.4',
|
53
|
+
'somerandomperson@example.org',
|
54
|
+
'mailserver123.example.org')
|
55
|
+
|
56
|
+
which would yield an instance of Coppertone::Result with the appropriate result code, and any explanation message. If the email was validated, then this result will also include the validating mechanism and the validated identity ('helo' or 'mailfrom').
|
57
|
+
|
58
|
+
For more sophisticated use of Coppertone, please consult the code and corresponding documentation directly.
|
47
59
|
|
48
60
|
## Contributing
|
49
61
|
|
data/lib/coppertone/directive.rb
CHANGED
@@ -30,6 +30,13 @@ module Coppertone
|
|
30
30
|
macros.any? { |m| m.is_a?(Coppertone::MacroString::MacroExpand) }
|
31
31
|
end
|
32
32
|
|
33
|
+
def includes_ptr?
|
34
|
+
expanded_macros = macros.select do |m|
|
35
|
+
m.is_a?(Coppertone::MacroString::MacroExpand)
|
36
|
+
end
|
37
|
+
expanded_macros.any?(&:ptr_macro?)
|
38
|
+
end
|
39
|
+
|
33
40
|
def ==(other)
|
34
41
|
return false unless other.instance_of? self.class
|
35
42
|
macro_text == other.macro_text
|
@@ -21,6 +21,15 @@ module Coppertone
|
|
21
21
|
RecordFinder.new(request_context.dns_client, target_name).record
|
22
22
|
end
|
23
23
|
|
24
|
+
def context_dependent_result?(request_context,
|
25
|
+
macro_context =
|
26
|
+
Coppertone::NullMacroContext.new)
|
27
|
+
target_name =
|
28
|
+
target_name_from_domain_spec(macro_context, request_context)
|
29
|
+
included_record(request_context, target_name)
|
30
|
+
.context_dependent_result?(request_context)
|
31
|
+
end
|
32
|
+
|
24
33
|
def self.label
|
25
34
|
'include'
|
26
35
|
end
|
data/lib/coppertone/mechanism.rb
CHANGED
@@ -16,6 +16,14 @@ module Coppertone
|
|
16
16
|
Coppertone::Utils::DomainUtils.macro_expanded_domain(domain)
|
17
17
|
end
|
18
18
|
|
19
|
+
def context_dependent?
|
20
|
+
domain_spec.context_dependent?
|
21
|
+
end
|
22
|
+
|
23
|
+
def includes_ptr?
|
24
|
+
domain_spec.includes_ptr?
|
25
|
+
end
|
26
|
+
|
19
27
|
def ==(other)
|
20
28
|
return false unless other.instance_of? self.class
|
21
29
|
domain_spec == other.domain_spec
|
@@ -12,6 +12,17 @@ module Coppertone
|
|
12
12
|
target_name_from_domain_spec(macro_context, request_context)
|
13
13
|
end
|
14
14
|
|
15
|
+
def included_record(macro_context, request_context)
|
16
|
+
RedirectRecordFinder.new(self, macro_context, request_context).record
|
17
|
+
end
|
18
|
+
|
19
|
+
def context_dependent_result?(request_context,
|
20
|
+
macro_context =
|
21
|
+
Coppertone::NullMacroContext.new)
|
22
|
+
included_record(macro_context, request_context)
|
23
|
+
.context_dependent_result?(request_context)
|
24
|
+
end
|
25
|
+
|
15
26
|
def self.label
|
16
27
|
'redirect'
|
17
28
|
end
|
@@ -1,8 +1,7 @@
|
|
1
1
|
module Coppertone
|
2
|
-
# A context used to evaluate records, directives, and modifiers that
|
3
|
-
# contextual dependence.
|
2
|
+
# A context used to evaluate records, directives, and modifiers that
|
3
|
+
# do not have contextual dependence.
|
4
4
|
class NullMacroContext
|
5
|
-
|
6
5
|
RESERVED_REGEXP = Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
|
7
6
|
%w(s l o d i p v h c r t).each do |m|
|
8
7
|
define_method(m.upcase) do
|
@@ -14,10 +13,10 @@ module Coppertone
|
|
14
13
|
end
|
15
14
|
end
|
16
15
|
|
17
|
-
def with_domain(
|
16
|
+
def with_domain(_new_domain)
|
18
17
|
self
|
19
18
|
end
|
20
19
|
|
21
20
|
NULL_CONTEXT = new
|
22
21
|
end
|
23
|
-
end
|
22
|
+
end
|
data/lib/coppertone/record.rb
CHANGED
@@ -38,6 +38,15 @@ module Coppertone
|
|
38
38
|
include_all?
|
39
39
|
end
|
40
40
|
|
41
|
+
def includes
|
42
|
+
@includes ||=
|
43
|
+
begin
|
44
|
+
directives.select do |d|
|
45
|
+
d.mechanism.is_a?(Coppertone::Mechanism::Include)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
41
50
|
def modifiers
|
42
51
|
@modifiers ||= @terms.select { |t| t.is_a?(Coppertone::Modifier) }
|
43
52
|
end
|
@@ -54,6 +63,23 @@ module Coppertone
|
|
54
63
|
@exp ||= find_modifier(Coppertone::Modifier::Exp)
|
55
64
|
end
|
56
65
|
|
66
|
+
def context_dependent_result?(request_context)
|
67
|
+
return true if directives.exist?(&:context_dependent)
|
68
|
+
return true if context_dependent_redirect_result?(request_context)
|
69
|
+
return false if includes.blank?
|
70
|
+
includes.exists? { |i| i.context_dependent_result?(request_context) }
|
71
|
+
end
|
72
|
+
|
73
|
+
def context_dependent_redirect_result?(request_context)
|
74
|
+
return false unless redirect
|
75
|
+
redirect.context_dependent? ||
|
76
|
+
redirect.context_dependent_result?(request_context)
|
77
|
+
end
|
78
|
+
|
79
|
+
def context_dependent_message?
|
80
|
+
exp && exp.context_dependent?
|
81
|
+
end
|
82
|
+
|
57
83
|
KNOWN_MODS =
|
58
84
|
[Coppertone::Modifier::Exp, Coppertone::Modifier::Redirect]
|
59
85
|
def unknown_modifiers
|
@@ -50,14 +50,12 @@ module Coppertone
|
|
50
50
|
|
51
51
|
def evaluate_none_result(result, macro_context, request_context)
|
52
52
|
return result unless follow_redirect?
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
rc = macro_context.with_domain(redirect_target)
|
60
|
-
RecordEvaluator.new(redirect_record).evaluate(rc, request_context)
|
53
|
+
finder =
|
54
|
+
Coppertone::RedirectRecordFinder.new(record.redirect, macro_context,
|
55
|
+
request_context)
|
56
|
+
fail InvalidRedirectError unless finder.target && finder.record
|
57
|
+
rc = macro_context.with_domain(finder.target)
|
58
|
+
RecordEvaluator.new(finder.record).evaluate(rc, request_context)
|
61
59
|
end
|
62
60
|
end
|
63
61
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Coppertone
|
2
|
+
# A helper class for finding SPF records for a redirect modifier.
|
3
|
+
class RedirectRecordFinder
|
4
|
+
attr_reader :redirect, :macro_context, :request_context
|
5
|
+
def initialize(redirect, macro_context, request_context)
|
6
|
+
@redirect = redirect
|
7
|
+
@macro_context = macro_context
|
8
|
+
@request_context = request_context
|
9
|
+
end
|
10
|
+
|
11
|
+
def target
|
12
|
+
@redirect_target ||= redirect.evaluate(macro_context, request_context)
|
13
|
+
end
|
14
|
+
|
15
|
+
def record
|
16
|
+
return unless target
|
17
|
+
@record ||= RecordFinder.new(request_context.dns_client, target).record
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/coppertone/version.rb
CHANGED
data/lib/coppertone.rb
CHANGED
data/spec/mechanism/a_spec.rb
CHANGED
@@ -9,6 +9,8 @@ describe Coppertone::Mechanism::A do
|
|
9
9
|
expect(mech.ip_v4_cidr_length).to eq(32)
|
10
10
|
expect(mech.ip_v6_cidr_length).to eq(128)
|
11
11
|
expect(mech.to_s).to eq('a')
|
12
|
+
expect(mech).not_to be_includes_ptr
|
13
|
+
expect(mech).to be_context_dependent
|
12
14
|
end
|
13
15
|
|
14
16
|
it 'should not fail if called with a blank argument' do
|
@@ -18,6 +20,8 @@ describe Coppertone::Mechanism::A do
|
|
18
20
|
expect(mech.ip_v4_cidr_length).to eq(32)
|
19
21
|
expect(mech.ip_v6_cidr_length).to eq(128)
|
20
22
|
expect(mech.to_s).to eq('a')
|
23
|
+
expect(mech).not_to be_includes_ptr
|
24
|
+
expect(mech).to be_context_dependent
|
21
25
|
end
|
22
26
|
|
23
27
|
it 'should fail if called with an invalid macrostring' do
|
@@ -26,7 +30,19 @@ describe Coppertone::Mechanism::A do
|
|
26
30
|
end.to raise_error(Coppertone::InvalidMechanismError)
|
27
31
|
end
|
28
32
|
|
29
|
-
it 'should parse a domain spec' do
|
33
|
+
it 'should parse a context independent domain spec' do
|
34
|
+
mech = Coppertone::Mechanism::A.new(':_spf.example.com')
|
35
|
+
expect(mech).not_to be_nil
|
36
|
+
expect(mech.domain_spec)
|
37
|
+
.to eq(Coppertone::DomainSpec.new('_spf.example.com'))
|
38
|
+
expect(mech.ip_v4_cidr_length).to eq(32)
|
39
|
+
expect(mech.ip_v6_cidr_length).to eq(128)
|
40
|
+
expect(mech.to_s).to eq('a:_spf.example.com')
|
41
|
+
expect(mech).not_to be_includes_ptr
|
42
|
+
expect(mech).not_to be_context_dependent
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should parse a context dependent domain spec' do
|
30
46
|
mech = Coppertone::Mechanism::A.new(':_spf.%{d}.example.com')
|
31
47
|
expect(mech).not_to be_nil
|
32
48
|
expect(mech.domain_spec)
|
@@ -34,6 +50,20 @@ describe Coppertone::Mechanism::A do
|
|
34
50
|
expect(mech.ip_v4_cidr_length).to eq(32)
|
35
51
|
expect(mech.ip_v6_cidr_length).to eq(128)
|
36
52
|
expect(mech.to_s).to eq('a:_spf.%{d}.example.com')
|
53
|
+
expect(mech).not_to be_includes_ptr
|
54
|
+
expect(mech).to be_context_dependent
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should parse a domain spec with a ptr' do
|
58
|
+
mech = Coppertone::Mechanism::A.new(':_spf.%{p}.example.com')
|
59
|
+
expect(mech).not_to be_nil
|
60
|
+
expect(mech.domain_spec)
|
61
|
+
.to eq(Coppertone::DomainSpec.new('_spf.%{p}.example.com'))
|
62
|
+
expect(mech.ip_v4_cidr_length).to eq(32)
|
63
|
+
expect(mech.ip_v6_cidr_length).to eq(128)
|
64
|
+
expect(mech.to_s).to eq('a:_spf.%{p}.example.com')
|
65
|
+
expect(mech).to be_includes_ptr
|
66
|
+
expect(mech).to be_context_dependent
|
37
67
|
end
|
38
68
|
|
39
69
|
it 'should parse a valid IP v4 CIDR length with a domain spec' do
|
data/spec/mechanism/all_spec.rb
CHANGED
@@ -5,6 +5,8 @@ describe Coppertone::Mechanism::All do
|
|
5
5
|
it 'should always return true regardless of argument' do
|
6
6
|
expect(subject.match?(double, double)).to eq(true)
|
7
7
|
expect(subject.to_s).to eq('all')
|
8
|
+
expect(subject).not_to be_includes_ptr
|
9
|
+
expect(subject).not_to be_context_dependent
|
8
10
|
end
|
9
11
|
|
10
12
|
it 'should not allow creation of new instances' do
|
@@ -20,9 +20,34 @@ describe Coppertone::Mechanism::Exists do
|
|
20
20
|
end.to raise_error(Coppertone::InvalidMechanismError)
|
21
21
|
end
|
22
22
|
|
23
|
-
it 'should
|
24
|
-
mech = Coppertone::Mechanism::Exists.new('
|
25
|
-
expect(mech
|
23
|
+
it 'should parse a context independent domain spec' do
|
24
|
+
mech = Coppertone::Mechanism::Exists.new(':_spf.example.com')
|
25
|
+
expect(mech).not_to be_nil
|
26
|
+
expect(mech.domain_spec)
|
27
|
+
.to eq(Coppertone::DomainSpec.new('_spf.example.com'))
|
28
|
+
expect(mech.to_s).to eq('exists:_spf.example.com')
|
29
|
+
expect(mech).not_to be_includes_ptr
|
30
|
+
expect(mech).not_to be_context_dependent
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should parse a context dependent domain spec' do
|
34
|
+
mech = Coppertone::Mechanism::Exists.new(':_spf.%{d}.example.com')
|
35
|
+
expect(mech).not_to be_nil
|
36
|
+
expect(mech.domain_spec)
|
37
|
+
.to eq(Coppertone::DomainSpec.new('_spf.%{d}.example.com'))
|
38
|
+
expect(mech.to_s).to eq('exists:_spf.%{d}.example.com')
|
39
|
+
expect(mech).not_to be_includes_ptr
|
40
|
+
expect(mech).to be_context_dependent
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should parse a domain spec with a ptr' do
|
44
|
+
mech = Coppertone::Mechanism::Exists.new(':_spf.%{p}.example.com')
|
45
|
+
expect(mech).not_to be_nil
|
46
|
+
expect(mech.domain_spec)
|
47
|
+
.to eq(Coppertone::DomainSpec.new('_spf.%{p}.example.com'))
|
48
|
+
expect(mech.to_s).to eq('exists:_spf.%{p}.example.com')
|
49
|
+
expect(mech).to be_includes_ptr
|
50
|
+
expect(mech).to be_context_dependent
|
26
51
|
end
|
27
52
|
end
|
28
53
|
|
@@ -20,9 +20,34 @@ describe Coppertone::Mechanism::Include do
|
|
20
20
|
end.to raise_error(Coppertone::InvalidMechanismError)
|
21
21
|
end
|
22
22
|
|
23
|
-
it '
|
23
|
+
it 'should parse a context independent domain spec' do
|
24
24
|
mech = Coppertone::Mechanism::Include.new(':_spf.example.com')
|
25
|
+
expect(mech).not_to be_nil
|
26
|
+
expect(mech.domain_spec)
|
27
|
+
.to eq(Coppertone::DomainSpec.new('_spf.example.com'))
|
25
28
|
expect(mech.to_s).to eq('include:_spf.example.com')
|
29
|
+
expect(mech).not_to be_includes_ptr
|
30
|
+
expect(mech).not_to be_context_dependent
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should parse a context dependent domain spec' do
|
34
|
+
mech = Coppertone::Mechanism::Include.new(':_spf.%{d}.example.com')
|
35
|
+
expect(mech).not_to be_nil
|
36
|
+
expect(mech.domain_spec)
|
37
|
+
.to eq(Coppertone::DomainSpec.new('_spf.%{d}.example.com'))
|
38
|
+
expect(mech.to_s).to eq('include:_spf.%{d}.example.com')
|
39
|
+
expect(mech).not_to be_includes_ptr
|
40
|
+
expect(mech).to be_context_dependent
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should parse a domain spec with a ptr' do
|
44
|
+
mech = Coppertone::Mechanism::Include.new(':_spf.%{p}.example.com')
|
45
|
+
expect(mech).not_to be_nil
|
46
|
+
expect(mech.domain_spec)
|
47
|
+
.to eq(Coppertone::DomainSpec.new('_spf.%{p}.example.com'))
|
48
|
+
expect(mech.to_s).to eq('include:_spf.%{p}.example.com')
|
49
|
+
expect(mech).to be_includes_ptr
|
50
|
+
expect(mech).to be_context_dependent
|
26
51
|
end
|
27
52
|
end
|
28
53
|
|
data/spec/mechanism/ip4_spec.rb
CHANGED
@@ -24,18 +24,24 @@ describe Coppertone::Mechanism::IP4 do
|
|
24
24
|
mech = Coppertone::Mechanism::IP4.new(':fe80::202:b3ff:fe1e:8329')
|
25
25
|
expect(mech.ip_network).to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
|
26
26
|
expect(mech.to_s).to eq('ip4:fe80::202:b3ff:fe1e:8329')
|
27
|
+
expect(mech).not_to be_includes_ptr
|
28
|
+
expect(mech).not_to be_context_dependent
|
27
29
|
end
|
28
30
|
|
29
31
|
it 'should work if called with an IP4' do
|
30
32
|
mech = Coppertone::Mechanism::IP4.new(':1.2.3.4')
|
31
33
|
expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
|
32
34
|
expect(mech.to_s).to eq('ip4:1.2.3.4')
|
35
|
+
expect(mech).not_to be_includes_ptr
|
36
|
+
expect(mech).not_to be_context_dependent
|
33
37
|
end
|
34
38
|
|
35
39
|
it 'should work if called with an IP4 with a pfxlen' do
|
36
40
|
mech = Coppertone::Mechanism::IP4.new(':1.2.3.4/4')
|
37
41
|
expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4/4'))
|
38
42
|
expect(mech.to_s).to eq('ip4:1.2.3.4/4')
|
43
|
+
expect(mech).not_to be_includes_ptr
|
44
|
+
expect(mech).not_to be_context_dependent
|
39
45
|
end
|
40
46
|
end
|
41
47
|
|
data/spec/mechanism/ip6_spec.rb
CHANGED
@@ -67,18 +67,24 @@ describe Coppertone::Mechanism::IP6 do
|
|
67
67
|
it 'should not fail if called with an IP v4' do
|
68
68
|
mech = Coppertone::Mechanism::IP6.create(':1.2.3.4')
|
69
69
|
expect(mech.ip_network).to eq(IPAddr.new('1.2.3.4'))
|
70
|
+
expect(mech).not_to be_includes_ptr
|
71
|
+
expect(mech).not_to be_context_dependent
|
70
72
|
end
|
71
73
|
|
72
74
|
it 'should work if called with an IP6' do
|
73
75
|
mech = Coppertone::Mechanism::IP6.create(':fe80::202:b3ff:fe1e:8329')
|
74
76
|
expect(mech.ip_network)
|
75
77
|
.to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329'))
|
78
|
+
expect(mech).not_to be_includes_ptr
|
79
|
+
expect(mech).not_to be_context_dependent
|
76
80
|
end
|
77
81
|
|
78
82
|
it 'should work if called with an IP6 with a pfxlen' do
|
79
83
|
mech = Coppertone::Mechanism::IP6.create(':fe80::202:b3ff:fe1e:8329/64')
|
80
84
|
expect(mech.ip_network)
|
81
85
|
.to eq(IPAddr.new('fe80::202:b3ff:fe1e:8329/64'))
|
86
|
+
expect(mech).not_to be_includes_ptr
|
87
|
+
expect(mech).not_to be_context_dependent
|
82
88
|
end
|
83
89
|
end
|
84
90
|
|
data/spec/mechanism/mx_spec.rb
CHANGED
@@ -9,6 +9,8 @@ describe Coppertone::Mechanism::MX do
|
|
9
9
|
expect(mech.ip_v4_cidr_length).to eq(32)
|
10
10
|
expect(mech.ip_v6_cidr_length).to eq(128)
|
11
11
|
expect(mech.to_s).to eq('mx')
|
12
|
+
expect(mech).not_to be_includes_ptr
|
13
|
+
expect(mech).to be_context_dependent
|
12
14
|
end
|
13
15
|
|
14
16
|
it 'should not fail if called with a blank argument' do
|
@@ -18,6 +20,8 @@ describe Coppertone::Mechanism::MX do
|
|
18
20
|
expect(mech.ip_v4_cidr_length).to eq(32)
|
19
21
|
expect(mech.ip_v6_cidr_length).to eq(128)
|
20
22
|
expect(mech.to_s).to eq('mx')
|
23
|
+
expect(mech).not_to be_includes_ptr
|
24
|
+
expect(mech).to be_context_dependent
|
21
25
|
end
|
22
26
|
|
23
27
|
it 'should fail if called with an invalid macrostring' do
|
@@ -33,6 +37,8 @@ describe Coppertone::Mechanism::MX do
|
|
33
37
|
expect(mech.ip_v4_cidr_length).to eq(24)
|
34
38
|
expect(mech.ip_v6_cidr_length).to eq(128)
|
35
39
|
expect(mech.to_s).to eq('mx/24')
|
40
|
+
expect(mech).not_to be_includes_ptr
|
41
|
+
expect(mech).to be_context_dependent
|
36
42
|
end
|
37
43
|
|
38
44
|
it 'should process the domain spec if it includes a IP v6 CIDR' do
|
@@ -42,6 +48,8 @@ describe Coppertone::Mechanism::MX do
|
|
42
48
|
expect(mech.ip_v4_cidr_length).to eq(32)
|
43
49
|
expect(mech.ip_v6_cidr_length).to eq(96)
|
44
50
|
expect(mech.to_s).to eq('mx//96')
|
51
|
+
expect(mech).not_to be_includes_ptr
|
52
|
+
expect(mech).to be_context_dependent
|
45
53
|
end
|
46
54
|
|
47
55
|
it 'should process the domain spec if it includes an IP v4 CIDR and an IP v6 CIDR' do
|
@@ -51,9 +59,11 @@ describe Coppertone::Mechanism::MX do
|
|
51
59
|
expect(mech.ip_v4_cidr_length).to eq(28)
|
52
60
|
expect(mech.ip_v6_cidr_length).to eq(96)
|
53
61
|
expect(mech.to_s).to eq('mx/28//96')
|
62
|
+
expect(mech).not_to be_includes_ptr
|
63
|
+
expect(mech).to be_context_dependent
|
54
64
|
end
|
55
65
|
|
56
|
-
it 'should not fail if called with a
|
66
|
+
it 'should not fail if called with a fixed domain spec without explicit CIDRs' do
|
57
67
|
mech = Coppertone::Mechanism::MX.new(':mx.example.com')
|
58
68
|
expect(mech).not_to be_nil
|
59
69
|
expect(mech.domain_spec)
|
@@ -61,9 +71,11 @@ describe Coppertone::Mechanism::MX do
|
|
61
71
|
expect(mech.ip_v4_cidr_length).to eq(32)
|
62
72
|
expect(mech.ip_v6_cidr_length).to eq(128)
|
63
73
|
expect(mech.to_s).to eq('mx:mx.example.com')
|
74
|
+
expect(mech).not_to be_includes_ptr
|
75
|
+
expect(mech).not_to be_context_dependent
|
64
76
|
end
|
65
77
|
|
66
|
-
it 'should not fail if called with a
|
78
|
+
it 'should not fail if called with a fixed domain spec with explicit CIDRs' do
|
67
79
|
mech = Coppertone::Mechanism::MX.new(':mx.example.com/28//96')
|
68
80
|
expect(mech).not_to be_nil
|
69
81
|
expect(mech.domain_spec)
|
@@ -72,6 +84,54 @@ describe Coppertone::Mechanism::MX do
|
|
72
84
|
expect(mech.ip_v6_cidr_length).to eq(96)
|
73
85
|
expect(mech.to_s).to eq('mx:mx.example.com/28//96')
|
74
86
|
end
|
87
|
+
|
88
|
+
it 'should not fail if called with a context-dependent domain spec without explicit CIDRs' do
|
89
|
+
mech = Coppertone::Mechanism::MX.new(':%{d}.example.com')
|
90
|
+
expect(mech).not_to be_nil
|
91
|
+
expect(mech.domain_spec)
|
92
|
+
.to eq(Coppertone::DomainSpec.new('%{d}.example.com'))
|
93
|
+
expect(mech.ip_v4_cidr_length).to eq(32)
|
94
|
+
expect(mech.ip_v6_cidr_length).to eq(128)
|
95
|
+
expect(mech.to_s).to eq('mx:%{d}.example.com')
|
96
|
+
expect(mech).not_to be_includes_ptr
|
97
|
+
expect(mech).to be_context_dependent
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should not fail if called with a fixed domain spec with explicit CIDRs' do
|
101
|
+
mech = Coppertone::Mechanism::MX.new(':%{d}.example.com/28//96')
|
102
|
+
expect(mech).not_to be_nil
|
103
|
+
expect(mech.domain_spec)
|
104
|
+
.to eq(Coppertone::DomainSpec.new('%{d}.example.com'))
|
105
|
+
expect(mech.ip_v4_cidr_length).to eq(28)
|
106
|
+
expect(mech.ip_v6_cidr_length).to eq(96)
|
107
|
+
expect(mech.to_s).to eq('mx:%{d}.example.com/28//96')
|
108
|
+
expect(mech).not_to be_includes_ptr
|
109
|
+
expect(mech).to be_context_dependent
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should not fail if called with a context-dependent domain spec without explicit CIDRs with PTR' do
|
113
|
+
mech = Coppertone::Mechanism::MX.new(':%{p}.example.com')
|
114
|
+
expect(mech).not_to be_nil
|
115
|
+
expect(mech.domain_spec)
|
116
|
+
.to eq(Coppertone::DomainSpec.new('%{p}.example.com'))
|
117
|
+
expect(mech.ip_v4_cidr_length).to eq(32)
|
118
|
+
expect(mech.ip_v6_cidr_length).to eq(128)
|
119
|
+
expect(mech.to_s).to eq('mx:%{p}.example.com')
|
120
|
+
expect(mech).to be_includes_ptr
|
121
|
+
expect(mech).to be_context_dependent
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should not fail if called with a fixed domain spec with explicit CIDRs with PTR' do
|
125
|
+
mech = Coppertone::Mechanism::MX.new(':%{p}.example.com/28//96')
|
126
|
+
expect(mech).not_to be_nil
|
127
|
+
expect(mech.domain_spec)
|
128
|
+
.to eq(Coppertone::DomainSpec.new('%{p}.example.com'))
|
129
|
+
expect(mech.ip_v4_cidr_length).to eq(28)
|
130
|
+
expect(mech.ip_v6_cidr_length).to eq(96)
|
131
|
+
expect(mech.to_s).to eq('mx:%{p}.example.com/28//96')
|
132
|
+
expect(mech).to be_includes_ptr
|
133
|
+
expect(mech).to be_context_dependent
|
134
|
+
end
|
75
135
|
end
|
76
136
|
|
77
137
|
context '#create' do
|
data/spec/mechanism/ptr_spec.rb
CHANGED
@@ -6,12 +6,16 @@ describe Coppertone::Mechanism::Ptr do
|
|
6
6
|
mech = Coppertone::Mechanism::Ptr.new(nil)
|
7
7
|
expect(mech).not_to be_nil
|
8
8
|
expect(mech.domain_spec).to be_nil
|
9
|
+
expect(mech).not_to be_includes_ptr
|
10
|
+
expect(mech).to be_context_dependent
|
9
11
|
end
|
10
12
|
|
11
13
|
it 'should not fail if called with a blank argument' do
|
12
14
|
mech = Coppertone::Mechanism::Ptr.new('')
|
13
15
|
expect(mech).not_to be_nil
|
14
16
|
expect(mech.domain_spec).to be_nil
|
17
|
+
expect(mech).not_to be_includes_ptr
|
18
|
+
expect(mech).to be_context_dependent
|
15
19
|
end
|
16
20
|
|
17
21
|
it 'should fail if called with an invalid macrostring' do
|
data/spec/modifier/exp_spec.rb
CHANGED
@@ -1,6 +1,41 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Coppertone::Modifier::Exp do
|
4
|
+
context '#new' do
|
5
|
+
it 'should work with a context independent domain spec' do
|
6
|
+
modifier = Coppertone::Modifier::Exp.new('test.example.com')
|
7
|
+
expect(modifier).not_to be_nil
|
8
|
+
expect(modifier.domain_spec)
|
9
|
+
.to eq(Coppertone::DomainSpec.new('test.example.com'))
|
10
|
+
expect(modifier.to_s)
|
11
|
+
.to eq('exp=test.example.com')
|
12
|
+
expect(modifier).not_to be_includes_ptr
|
13
|
+
expect(modifier).not_to be_context_dependent
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should work with a context independent domain spec' do
|
17
|
+
modifier = Coppertone::Modifier::Exp.new('%{d}.example.com')
|
18
|
+
expect(modifier).not_to be_nil
|
19
|
+
expect(modifier.domain_spec)
|
20
|
+
.to eq(Coppertone::DomainSpec.new('%{d}.example.com'))
|
21
|
+
expect(modifier.to_s)
|
22
|
+
.to eq('exp=%{d}.example.com')
|
23
|
+
expect(modifier).not_to be_includes_ptr
|
24
|
+
expect(modifier).to be_context_dependent
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should work with a context independent domain spec with a PTR' do
|
28
|
+
modifier = Coppertone::Modifier::Exp.new('%{p}.example.com')
|
29
|
+
expect(modifier).not_to be_nil
|
30
|
+
expect(modifier.domain_spec)
|
31
|
+
.to eq(Coppertone::DomainSpec.new('%{p}.example.com'))
|
32
|
+
expect(modifier.to_s)
|
33
|
+
.to eq('exp=%{p}.example.com')
|
34
|
+
expect(modifier).to be_includes_ptr
|
35
|
+
expect(modifier).to be_context_dependent
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
4
39
|
context 'to_s' do
|
5
40
|
it 'should result in the expected string' do
|
6
41
|
expect(Coppertone::Modifier::Exp.new('test.example.com').to_s)
|
@@ -1,6 +1,41 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Coppertone::Modifier::Redirect do
|
4
|
+
context '#new' do
|
5
|
+
it 'should work with a context independent domain spec' do
|
6
|
+
modifier = Coppertone::Modifier::Redirect.new('test.example.com')
|
7
|
+
expect(modifier).not_to be_nil
|
8
|
+
expect(modifier.domain_spec)
|
9
|
+
.to eq(Coppertone::DomainSpec.new('test.example.com'))
|
10
|
+
expect(modifier.to_s)
|
11
|
+
.to eq('redirect=test.example.com')
|
12
|
+
expect(modifier).not_to be_includes_ptr
|
13
|
+
expect(modifier).not_to be_context_dependent
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should work with a context independent domain spec' do
|
17
|
+
modifier = Coppertone::Modifier::Redirect.new('%{d}.example.com')
|
18
|
+
expect(modifier).not_to be_nil
|
19
|
+
expect(modifier.domain_spec)
|
20
|
+
.to eq(Coppertone::DomainSpec.new('%{d}.example.com'))
|
21
|
+
expect(modifier.to_s)
|
22
|
+
.to eq('redirect=%{d}.example.com')
|
23
|
+
expect(modifier).not_to be_includes_ptr
|
24
|
+
expect(modifier).to be_context_dependent
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should work with a context independent domain spec with a PTR' do
|
28
|
+
modifier = Coppertone::Modifier::Redirect.new('%{p}.example.com')
|
29
|
+
expect(modifier).not_to be_nil
|
30
|
+
expect(modifier.domain_spec)
|
31
|
+
.to eq(Coppertone::DomainSpec.new('%{p}.example.com'))
|
32
|
+
expect(modifier.to_s)
|
33
|
+
.to eq('redirect=%{p}.example.com')
|
34
|
+
expect(modifier).to be_includes_ptr
|
35
|
+
expect(modifier).to be_context_dependent
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
4
39
|
context 'to_s' do
|
5
40
|
it 'should result in the expected string' do
|
6
41
|
expect(Coppertone::Modifier::Redirect.new('test.example.com').to_s)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coppertone
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter M. Goldstein
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -175,6 +175,7 @@ files:
|
|
175
175
|
- lib/coppertone/record_evaluator.rb
|
176
176
|
- lib/coppertone/record_finder.rb
|
177
177
|
- lib/coppertone/record_term_parser.rb
|
178
|
+
- lib/coppertone/redirect_record_finder.rb
|
178
179
|
- lib/coppertone/request.rb
|
179
180
|
- lib/coppertone/request_context.rb
|
180
181
|
- lib/coppertone/request_count_limiter.rb
|
@@ -228,6 +229,7 @@ files:
|
|
228
229
|
- spec/record_evaluator_spec.rb
|
229
230
|
- spec/record_finder_spec.rb
|
230
231
|
- spec/record_spec.rb
|
232
|
+
- spec/redirect_record_finder_spec.rb
|
231
233
|
- spec/request_context_spec.rb
|
232
234
|
- spec/request_count_limiter_spec.rb
|
233
235
|
- spec/result_spec.rb
|
@@ -304,6 +306,7 @@ test_files:
|
|
304
306
|
- spec/record_evaluator_spec.rb
|
305
307
|
- spec/record_finder_spec.rb
|
306
308
|
- spec/record_spec.rb
|
309
|
+
- spec/redirect_record_finder_spec.rb
|
307
310
|
- spec/request_context_spec.rb
|
308
311
|
- spec/request_count_limiter_spec.rb
|
309
312
|
- spec/result_spec.rb
|