spf 0.0.13 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/spf/eval.rb +3 -3
- data/lib/spf/model.rb +61 -41
- data/lib/spf/version.rb +1 -1
- data/spf.gemspec +1 -1
- metadata +1 -4
data/lib/spf/eval.rb
CHANGED
@@ -99,9 +99,9 @@ class SPF::Server
|
|
99
99
|
rescue SPF::Result => r
|
100
100
|
result = r
|
101
101
|
rescue SPF::DNSError => e
|
102
|
-
result = self.result_class(:temperror).new(self, request, e.message)
|
102
|
+
result = self.result_class(:temperror).new([self, request, e.message])
|
103
103
|
rescue SPF::NoAcceptableRecordError => e
|
104
|
-
result = self.result_class(:none ).new(self, request, e.message)
|
104
|
+
result = self.result_class(:none ).new([self, request, e.message])
|
105
105
|
rescue SPF::RedundantAcceptableRecordsError, SPF::SyntaxError, SPF::ProcessingLimitExceededError => e
|
106
106
|
result = self.result_class(:permerror).new([self, request, e.message])
|
107
107
|
end
|
@@ -253,7 +253,7 @@ class SPF::Server
|
|
253
253
|
klass = RECORD_CLASSES_BY_VERSION[version]
|
254
254
|
begin
|
255
255
|
record = klass.new_from_string(text, {:raise_exceptions => @raise_exceptions})
|
256
|
-
rescue SPF::InvalidRecordVersionError
|
256
|
+
rescue SPF::InvalidRecordVersionError => error
|
257
257
|
# Ignore non-SPF and unknown-version records.
|
258
258
|
# Propagate other errors (including syntax errors), though.
|
259
259
|
end
|
data/lib/spf/model.rb
CHANGED
@@ -94,11 +94,12 @@ class SPF::Term
|
|
94
94
|
@ipv6_prefix_length = nil
|
95
95
|
@errors = []
|
96
96
|
@ip_netblocks = []
|
97
|
+
@raise_exceptions = options.has_key?(:raise_exceptions) ? options[:raise_exceptions] : true
|
97
98
|
end
|
98
99
|
|
99
100
|
def error(exception)
|
101
|
+
raise exception if @raise_exceptions
|
100
102
|
@errors << exception
|
101
|
-
raise exception
|
102
103
|
end
|
103
104
|
|
104
105
|
def self.new_from_string(text, options = {})
|
@@ -115,8 +116,8 @@ class SPF::Term
|
|
115
116
|
domain_spec.sub!(/^(.*?)\.?$/, $1)
|
116
117
|
@domain_spec = SPF::MacroString.new({:text => domain_spec})
|
117
118
|
elsif required
|
118
|
-
|
119
|
-
"Missing required domain-spec in '#{@text}'")
|
119
|
+
error(SPF::TermDomainSpecExpectedError.new(
|
120
|
+
"Missing required domain-spec in '#{@text}'"))
|
120
121
|
end
|
121
122
|
end
|
122
123
|
|
@@ -124,8 +125,8 @@ class SPF::Term
|
|
124
125
|
if @parse_text.sub!(/^(#{IPV4_ADDRESS_PATTERN})/x, '')
|
125
126
|
@ip_address = $1
|
126
127
|
elsif required
|
127
|
-
|
128
|
-
"Missing required IPv4 address in '#{@text}'")
|
128
|
+
error(SPF::TermIPv4AddressExpectedError.new(
|
129
|
+
"Missing or invalid required IPv4 address in '#{@text}'"))
|
129
130
|
end
|
130
131
|
end
|
131
132
|
|
@@ -133,13 +134,15 @@ class SPF::Term
|
|
133
134
|
if @parse_text.sub!(/^\/(\d+)/, '')
|
134
135
|
bits = $1.to_i
|
135
136
|
unless bits and bits >= 0 and bits <= 32 and $1 !~ /^0./
|
136
|
-
|
137
|
-
"Invalid IPv4 prefix length encountered in '#{@text}'")
|
137
|
+
error(SPF::TermIPv4PrefixLengthExpected.new(
|
138
|
+
"Invalid IPv4 prefix length encountered in '#{@text}'"))
|
139
|
+
return
|
138
140
|
end
|
139
141
|
@ipv4_prefix_length = bits
|
140
142
|
elsif required
|
141
|
-
|
142
|
-
"Missing required IPv4 prefix length in '#{@text}")
|
143
|
+
error(SPF::TermIPv4PrefixLengthExpected.new(
|
144
|
+
"Missing required IPv4 prefix length in '#{@text}"))
|
145
|
+
return
|
143
146
|
else
|
144
147
|
@ipv4_prefix_length = self.default_ipv4_prefix_length
|
145
148
|
end
|
@@ -148,15 +151,15 @@ class SPF::Term
|
|
148
151
|
def parse_ipv4_network(required = false)
|
149
152
|
self.parse_ipv4_address(required)
|
150
153
|
self.parse_ipv4_prefix_length
|
151
|
-
@ip_network = IP.new("#{@ip_address}/#{@ipv4_prefix_length}")
|
154
|
+
@ip_network = IP.new("#{@ip_address}/#{@ipv4_prefix_length}") if @ip_address and @ipv4_prefix_length
|
152
155
|
end
|
153
156
|
|
154
157
|
def parse_ipv6_address(required = false)
|
155
158
|
if @parse_text.sub!(/(#{IPV6_ADDRESS_PATTERN})(?=\/|$)/x, '')
|
156
159
|
@ip_address = $1
|
157
160
|
elsif required
|
158
|
-
|
159
|
-
"Missing required IPv6 address in '#{@text}'")
|
161
|
+
error(SPF::TermIPv6AddressExpected.new(
|
162
|
+
"Missing required IPv6 address in '#{@text}'"))
|
160
163
|
end
|
161
164
|
end
|
162
165
|
|
@@ -164,13 +167,15 @@ class SPF::Term
|
|
164
167
|
if @parse_text.sub!(/^\/(\d+)/, '')
|
165
168
|
bits = $1.to_i
|
166
169
|
unless bits and bits >= 0 and bits <= 128 and $1 !~ /^0./
|
167
|
-
|
168
|
-
"Invalid IPv6 prefix length encountered in '#{@text}'")
|
170
|
+
error(SPF::TermIPv6PrefixLengthExpectedError.new(
|
171
|
+
"Invalid IPv6 prefix length encountered in '#{@text}'"))
|
172
|
+
return
|
169
173
|
end
|
170
174
|
@ipv6_prefix_length = bits
|
171
175
|
elsif required
|
172
|
-
|
173
|
-
"Missing required IPv6 prefix length in '#{@text}'")
|
176
|
+
error(SPF::TermIPvPrefixLengthExpected.new(
|
177
|
+
"Missing required IPv6 prefix length in '#{@text}'"))
|
178
|
+
return
|
174
179
|
else
|
175
180
|
@ipv6_prefix_length = self.default_ipv6_prefix_length
|
176
181
|
end
|
@@ -179,7 +184,7 @@ class SPF::Term
|
|
179
184
|
def parse_ipv6_network(required = false)
|
180
185
|
self.parse_ipv6_address(required)
|
181
186
|
self.parse_ipv6_prefix_length
|
182
|
-
@ip_network = IP.new("#{@ip_address}/#{@ipv6_prefix_length}")
|
187
|
+
@ip_network = IP.new("#{@ip_address}/#{@ipv6_prefix_length}") if @ip_address and @ipv6_prefix_length
|
183
188
|
end
|
184
189
|
|
185
190
|
def parse_ipv4_ipv6_prefix_lengths
|
@@ -205,7 +210,9 @@ class SPF::Term
|
|
205
210
|
raise SPF::NoUnparsedTextError
|
206
211
|
end
|
207
212
|
end
|
213
|
+
end
|
208
214
|
|
215
|
+
class SPF::UnknownTerm < SPF::Term
|
209
216
|
end
|
210
217
|
|
211
218
|
class SPF::Mech < SPF::Term
|
@@ -242,17 +249,17 @@ class SPF::Mech < SPF::Term
|
|
242
249
|
raise SPF::NothingToParseError.new('Nothing to parse for mechanism')
|
243
250
|
end
|
244
251
|
parse_qualifier
|
245
|
-
parse_name
|
246
|
-
parse_params
|
247
|
-
parse_end
|
252
|
+
parse_name if @errors.empty?
|
253
|
+
parse_params if @errors.empty?
|
254
|
+
parse_end if @errors.empty?
|
248
255
|
end
|
249
256
|
|
250
257
|
def parse_qualifier
|
251
258
|
if @parse_text.sub!(/(#{QUALIFIER_PATTERN})?/x, '')
|
252
259
|
@qualifier = $1 or DEFAULT_QUALIFIER
|
253
260
|
else
|
254
|
-
|
255
|
-
"Invalid qualifier encountered in '#{@text}'")
|
261
|
+
error(SPF::InvalidMechQualifierError.new(
|
262
|
+
"Invalid qualifier encountered in '#{@text}'"))
|
256
263
|
end
|
257
264
|
end
|
258
265
|
|
@@ -260,7 +267,7 @@ class SPF::Mech < SPF::Term
|
|
260
267
|
if @parse_text.sub!(/^ (#{NAME_PATTERN}) (?: : (?=.) )? /x, '')
|
261
268
|
@name = $1
|
262
269
|
else
|
263
|
-
|
270
|
+
error(SPF::InvalidMechError.new("Unexpected mechanism encountered in '#{@text}'"))
|
264
271
|
end
|
265
272
|
end
|
266
273
|
|
@@ -273,7 +280,7 @@ class SPF::Mech < SPF::Term
|
|
273
280
|
|
274
281
|
def parse_end
|
275
282
|
unless @parse_text == ''
|
276
|
-
|
283
|
+
error(SPF::JunkInTermError.new("Junk encountered in mechanism '#{@text}'"))
|
277
284
|
end
|
278
285
|
@parse_text = nil
|
279
286
|
end
|
@@ -432,6 +439,7 @@ class SPF::Mech < SPF::Term
|
|
432
439
|
end
|
433
440
|
|
434
441
|
def match(server, request, want_result = true)
|
442
|
+
return false unless @ip_network
|
435
443
|
ip_network_v6 = IP::V4 === @ip_network ?
|
436
444
|
SPF::Util.ipv4_address_to_ipv6(@ip_network) :
|
437
445
|
@ip_network
|
@@ -607,10 +615,10 @@ class SPF::Mod < SPF::Term
|
|
607
615
|
end
|
608
616
|
|
609
617
|
def parse
|
610
|
-
|
611
|
-
self.parse_name
|
612
|
-
self.parse_params(true)
|
613
|
-
self.parse_end
|
618
|
+
error(SPF::NothingToParseError('Nothing to parse for modifier')) unless @parse_text
|
619
|
+
self.parse_name if @errors.empty?
|
620
|
+
self.parse_params(true) if @errors.empty?
|
621
|
+
self.parse_end if @errors.empty?
|
614
622
|
end
|
615
623
|
|
616
624
|
def parse_name
|
@@ -618,8 +626,8 @@ class SPF::Mod < SPF::Term
|
|
618
626
|
if $1
|
619
627
|
@name = $1
|
620
628
|
else
|
621
|
-
|
622
|
-
"Unexpected modifier name encoutered in #{@text}")
|
629
|
+
error(SPF::InvalidModError.new(
|
630
|
+
"Unexpected modifier name encoutered in #{@text}"))
|
623
631
|
end
|
624
632
|
end
|
625
633
|
|
@@ -629,14 +637,14 @@ class SPF::Mod < SPF::Term
|
|
629
637
|
if $1
|
630
638
|
@params_text = $1
|
631
639
|
elsif required
|
632
|
-
|
633
|
-
"Invalid macro string encountered in #{@text}")
|
640
|
+
error(SPF::InvalidMacroStringError.new(
|
641
|
+
"Invalid macro string encountered in #{@text}"))
|
634
642
|
end
|
635
643
|
end
|
636
644
|
|
637
645
|
def parse_end
|
638
646
|
unless @parse_text == ''
|
639
|
-
|
647
|
+
error(SPF::JunkInTermError.new("Junk encountered in modifier #{@text}"))
|
640
648
|
end
|
641
649
|
@parse_text = nil
|
642
650
|
end
|
@@ -784,6 +792,11 @@ class SPF::Record
|
|
784
792
|
return record
|
785
793
|
end
|
786
794
|
|
795
|
+
def error(exception)
|
796
|
+
raise exception if @raise_exceptions
|
797
|
+
@errors << exception
|
798
|
+
end
|
799
|
+
|
787
800
|
def ip_netblocks
|
788
801
|
@ip_netblocks.flatten!
|
789
802
|
return @ip_netblocks
|
@@ -791,7 +804,8 @@ class SPF::Record
|
|
791
804
|
|
792
805
|
def parse
|
793
806
|
unless self.instance_variable_defined?(:@parse_text) and @parse_text
|
794
|
-
|
807
|
+
error(SPF::NothingToParseError.new('Nothing to parse for record'))
|
808
|
+
return
|
795
809
|
end
|
796
810
|
self.parse_version_tag
|
797
811
|
while @parse_text.length > 0
|
@@ -805,11 +819,9 @@ class SPF::Record
|
|
805
819
|
return if SPF::JunkInRecordError === e
|
806
820
|
end
|
807
821
|
end
|
808
|
-
#self.parse_end
|
809
822
|
end
|
810
823
|
|
811
824
|
def parse_version_tag
|
812
|
-
#@parse_text.sub!(self.version_tag_pattern, '')
|
813
825
|
@parse_text.sub!(/^#{self.version_tag_pattern}\s+/ix, '')
|
814
826
|
unless $1
|
815
827
|
raise SPF::InvalidRecordVersionError.new(
|
@@ -833,9 +845,16 @@ class SPF::Record
|
|
833
845
|
# Looks like a mechanism:
|
834
846
|
mech_text = $1
|
835
847
|
mech_name = $2.downcase
|
836
|
-
mech_class = self.mech_classes[mech_name.to_sym]
|
837
|
-
|
838
|
-
|
848
|
+
mech_class = self.mech_classes[mech_name.to_sym]
|
849
|
+
exception = nil
|
850
|
+
unless mech_class
|
851
|
+
exception = SPF::InvalidMech.new("Unknown mechanism type '#{mech_name}' in '#{@version_tag}' record")
|
852
|
+
error(exception)
|
853
|
+
mech_class = SPF::Mech
|
854
|
+
end
|
855
|
+
term = mech = mech_class.new_from_string(mech_text, {:raise_exceptions => @raise_exceptions})
|
856
|
+
term.errors << exception if exception
|
857
|
+
@ip_netblocks << mech.ip_netblocks if mech.ip_netblocks
|
839
858
|
@terms << mech
|
840
859
|
if mech_class == SPF::Mech
|
841
860
|
raise SPF::InvalidMechError.new("Unknown mechanism type '#{mech_name}' in '#{@version_tag}' record")
|
@@ -856,7 +875,7 @@ class SPF::Record
|
|
856
875
|
mod_class = self.class::MOD_CLASSES[mod_name.to_sym] || SPF::Mod
|
857
876
|
if mod_class
|
858
877
|
# Known modifier.
|
859
|
-
term = mod = mod_class.new_from_string(mod_text)
|
878
|
+
term = mod = mod_class.new_from_string(mod_text, {:raise_exceptions => @raise_exceptions})
|
860
879
|
if SPF::GlobalMod === mod
|
861
880
|
# Global modifier.
|
862
881
|
if @global_mods[mod_name]
|
@@ -872,6 +891,7 @@ class SPF::Record
|
|
872
891
|
else
|
873
892
|
raise SPF::JunkInRecordError.new("Junk encountered in record '#{@text}'")
|
874
893
|
end
|
894
|
+
@errors.concat(term.errors)
|
875
895
|
return term
|
876
896
|
end
|
877
897
|
|
@@ -910,7 +930,7 @@ class SPF::Record
|
|
910
930
|
# Term is an unknown modifier. Ignore it (RFC 4408, 6/3).
|
911
931
|
else
|
912
932
|
# Invalid term object encountered:
|
913
|
-
|
933
|
+
error(SPF::UnexpectedTermObjectError.new("Unexpected term object '#{term}' encountered."))
|
914
934
|
end
|
915
935
|
end
|
916
936
|
rescue SPF::Result => result
|
data/lib/spf/version.rb
CHANGED
data/spf.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.14
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -119,9 +119,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
119
119
|
- - ! '>='
|
120
120
|
- !ruby/object:Gem::Version
|
121
121
|
version: '0'
|
122
|
-
segments:
|
123
|
-
- 0
|
124
|
-
hash: -4387479351355747049
|
125
122
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
123
|
none: false
|
127
124
|
requirements:
|