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 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: