diff --git a/lib/dns/zone/rr/record.rb b/lib/dns/zone/rr/record.rb index c55cb4c..729b315 100644 --- a/lib/dns/zone/rr/record.rb +++ b/lib/dns/zone/rr/record.rb @@ -1,7 +1,7 @@ # Parent class of all RR types, common resource record code lives here. # Is responsible for building a Ruby object given a RR string. # -# @abstract Each RR TYPE should subclass and override: {#load} and #{dump} +# @abstract Each RR TYPE should subclass and override: {#load} and #{dump} class DNS::Zone::RR::Record attr_accessor :label, :ttl @@ -69,16 +69,23 @@ def load_general_and_get_rdata(string, options = {}) captures = string.match(DNS::Zone::RR::REGEX_RR) return nil unless captures - if [' ', nil].include?(captures[:label]) + unrolled_origin = options[:last_origin] + .sub(options[:origin], '') + .chomp('.') if options[:last_origin] + + @label = captures[:label] + + if [' ', nil].include?(@label) + # Empty labels indicate to use the previous value @label = options[:last_label] - else - @label = captures[:label] - end - # unroll records nested under other origins - unrolled_origin = options[:last_origin].sub(options[:origin], '').chomp('.') if options[:last_origin] - if unrolled_origin && !unrolled_origin.empty? - @label = @label == '@' ? unrolled_origin : "#{@label}.#{unrolled_origin}" + elsif @label == '@' && unrolled_origin && !unrolled_origin.empty? + # '@' and an unrolled origin set the current origin + @label = unrolled_origin + + elsif unrolled_origin && !unrolled_origin.empty? + # Set the 'sub' $origin + @label = "#{@label}.#{unrolled_origin}" end @ttl = captures[:ttl] diff --git a/test/zone_test.rb b/test/zone_test.rb index f307ae8..a97f005 100644 --- a/test/zone_test.rb +++ b/test/zone_test.rb @@ -88,6 +88,25 @@ class ZoneTest < DNS::Zone::TestCase @ 3600 A 1.1.1.1 app1 60 A 4.3.2.1 +EOL + + # basic zone file example + ZONE_FILE_MULTIPLE_ORIGINS_MISSING_ATS_EXAMPLE =<<-EOL +$ORIGIN lividpenguin.com. +$TTL 3d +@ IN SOA ns0.lividpenguin.com. luke.lividpenguin.com. ( + 2013101406 ; zone serial number + 12h ; refresh ttl + 15m ; retry ttl + 3w ; expiry ttl + 3h ; minimum ttl + ) + +$ORIGIN sub.lividpenguin.com. +@ 60 A 1.2.3.4 + 60 TXT "foo" +app1 60 A 4.3.2.1 + 60 TXT "bar" EOL def test_create_new_instance @@ -200,6 +219,24 @@ def test_load_multiple_origins assert_equal '4.3.2.1', zone.records[11].address end + def test_load_multiple_origins_with_missing_ats + zone = DNS::Zone.load(ZONE_FILE_MULTIPLE_ORIGINS_MISSING_ATS_EXAMPLE) + assert_equal 'lividpenguin.com.', zone.origin + assert_equal 5, zone.records.length, 'we should have multiple records (including SOA)' + assert_equal 'A', zone.records[1].type + assert_equal 'sub', zone.records[1].label + assert_equal '1.2.3.4', zone.records[1].address + assert_equal 'TXT', zone.records[2].type + assert_equal 'sub', zone.records[2].label + assert_equal 'foo', zone.records[2].text + assert_equal 'A', zone.records[3].type + assert_equal 'app1.sub', zone.records[3].label + assert_equal '4.3.2.1', zone.records[3].address + assert_equal 'TXT', zone.records[4].type + assert_equal 'app1.sub', zone.records[4].label + assert_equal 'bar', zone.records[4].text + end + def test_extract_entry_from_one_line entries = DNS::Zone.extract_entries(%Q{maiow IN TXT "purr"}) assert_equal 1, entries.length, 'we should have 1 entry'