spf 0.0.13 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
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
- raise SPF::TermDomainSpecExpectedError.new(
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
- raise SPF::TermIPv4AddressExpectedError.new(
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
- raise SPF::TermIPv4PrefixLengthExpected.new(
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
- raise SPF::TermIPv4PrefixLengthExpected.new(
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
- raise SPF::TermIPv6AddressExpected.new(
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
- raise SPF::TermIPv6PrefixLengthExpectedError.new(
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
- raise SPF::TermIPvPrefixLengthExpected.new(
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
- raise SPF::InvalidMechQualifierError.new(
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
- raise SPF::InvalidMechError.new("Unexpected mechanism encountered in '#{@text}'")
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
- raise SPF::JunkInTermError.new("Junk encountered in mechanism '#{@text}'")
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
- raise SPF::NothingToParseError('Nothing to parse for modifier') unless @parse_text
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
- raise SPF::InvalidModError.new(
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
- raise SPF::InvalidMacroStringError.new(
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
- raise SPF::JunkInTermError("Junk encountered in modifier #{@text}")
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
- raise SPF::NothingToParseError.new('Nothing to parse for record')
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] || SPF::Mech
837
- term = mech = mech_class.new_from_string(mech_text)
838
- @ip_netblocks << mech.ip_netblocks
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
- raise SPF::UnexpectedTermObjectError.new("Unexpected term object '#{term}' encountered.")
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
@@ -1,5 +1,5 @@
1
1
  module SPF
2
- VERSION = '0.0.13'
2
+ VERSION = '0.0.14'
3
3
  end
4
4
 
5
5
  # vim:sw=2 sts=2
data/spf.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "spf"
8
- s.version = "0.0.13"
8
+ s.version = "0.0.14"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andrew Flury", "Julian Mehnle"]
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.13
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: