dns-zonefile 1.1.0 → 1.1.9
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.
- checksums.yaml +5 -5
- data/.gitignore +10 -3
- data/.rspec +2 -0
- data/.travis.yml +8 -2
- data/CONTRIBUTING.md +36 -0
- data/Dockerfile +1 -1
- data/Gemfile +1 -1
- data/README.md +11 -15
- data/Rakefile +2 -7
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/circle.yml +6 -0
- data/dns-zonefile.gemspec +34 -24
- data/examples/basic.rb +12 -0
- data/examples/basic_origin.rb +15 -0
- data/examples/example.com.no-origin.zonefile +16 -0
- data/examples/example.com.zonefile +17 -0
- data/lib/dns/zonefile.rb +197 -200
- data/lib/dns/zonefile.treetop +47 -12
- data/lib/dns/zonefile/version.rb +1 -1
- metadata +57 -36
- data/spec/dns/zonefile_spec.rb +0 -435
- data/spec/spec_helper.rb +0 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 | 
            -
             | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: 4edd1610f1ecdf845654917cd1f3ea2aa83f1196a87be9bf97c59a34d10392ec
         | 
| 4 | 
            +
              data.tar.gz: cf115e357d4763424d310592ebf0eb5d18366fff4a2bb451c61a80371317b62e
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 3416c7cc446f189fe4c03e128f37c2b2b9b886c911a7a11345ade49c6ae6bc2a138cf95cc76f77721950ff820bd5817d1e874b9fc90420af42333f54572b4592
         | 
| 7 | 
            +
              data.tar.gz: e0ee661f673016703e919225b9fc04b3e40ce59effbba2417c0f5489c9db6109f4c8aac23ffed06f2252fbb08c5d65f6c4f5860bd8caa4ccb384adbccc0d178b
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.rspec
    ADDED
    
    
    
        data/.travis.yml
    CHANGED
    
    
    
        data/CONTRIBUTING.md
    ADDED
    
    | @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            # Contributing to dns-zonefile
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            ## Getting started
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Clone the repository and move into it:
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            ```
         | 
| 8 | 
            +
            $ git clone git@github.com:craigw/dns-zonefile.git
         | 
| 9 | 
            +
            $ cd dns-zonefile
         | 
| 10 | 
            +
            ```
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            Install the dependencies using [Bundler](http://bundler.io/):
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            ```
         | 
| 15 | 
            +
            $ bundle
         | 
| 16 | 
            +
            ```
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            [Run the test suite](#testing) to check everything works as expected.
         | 
| 19 | 
            +
             | 
| 20 | 
            +
             | 
| 21 | 
            +
            ## Testing
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            To run the test suite:
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            ```
         | 
| 26 | 
            +
            $ rake
         | 
| 27 | 
            +
            ```
         | 
| 28 | 
            +
             | 
| 29 | 
            +
             | 
| 30 | 
            +
            ## Tests
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            Submit unit tests for your changes. You can test your changes on your machine by [running the test suite](#testing).
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            ## Publishing
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            Once a PR is merged into master, bump the version in `lib/dns/zonefile/version.rb` and commit that change. Next, add a new tag with that version number and push the tag to GitHub. Finally, if you are a maintainer with access rights for rubygems.org, run `gem build dnsimple-zonefile.gemspec` followed by `gem push dnsimple-zonefile-x.x.x.gem` where x.x.x is the version number you just set.
         | 
    
        data/Dockerfile
    CHANGED
    
    
    
        data/Gemfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -11,21 +11,14 @@ some canonical form. | |
| 11 11 |  | 
| 12 12 | 
             
            ## Getting setup
         | 
| 13 13 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
            the hard work. Thanks!
         | 
| 14 | 
            +
            Add `gem dns-zonefile` to your Gemfile
         | 
| 16 15 |  | 
| 17 | 
            -
             | 
| 16 | 
            +
            or
         | 
| 18 17 |  | 
| 19 | 
            -
             | 
| 20 | 
            -
            that I've hacked together.
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                rake generate_grammar
         | 
| 18 | 
            +
            `gem install dns-zonefile`
         | 
| 23 19 |  | 
| 24 20 | 
             
            Okay, you're ready to move onto the examples now.
         | 
| 25 21 |  | 
| 26 | 
            -
            The above steps should not be necessary if you install the gem via rubygems.
         | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 22 | 
             
            ## Examples
         | 
| 30 23 |  | 
| 31 24 | 
             
            Using raw data from the parser. Note that "@" isn't translated in this mode.
         | 
| @@ -54,19 +47,22 @@ handled in this mode. | |
| 54 47 | 
             
                # get all MX records
         | 
| 55 48 | 
             
                puts zone.records_of(DNS::Zonefile::MX)
         | 
| 56 49 |  | 
| 50 | 
            +
            Open the examples in the `./examples` directory to see more examples.
         | 
| 57 51 |  | 
| 58 52 | 
             
            ## Authors
         | 
| 59 53 |  | 
| 60 | 
            -
            Original code and concept:
         | 
| 54 | 
            +
            ### Original code and concept:
         | 
| 55 | 
            +
             | 
| 61 56 | 
             
            Craig R Webster <http://barkingiguana.com/>
         | 
| 62 57 |  | 
| 63 | 
            -
            Additions:
         | 
| 64 | 
            -
             | 
| 58 | 
            +
            ### Additions:
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            - t.e.morgan <http://zerigo.com/>
         | 
| 61 | 
            +
            - Anthony Eden <https://dnsimple.com/>
         | 
| 65 62 |  | 
| 66 63 |  | 
| 67 64 | 
             
            ## Contributing
         | 
| 68 65 |  | 
| 69 | 
            -
            See the TODO.  | 
| 70 | 
            -
            GitHub.
         | 
| 66 | 
            +
            See the TODO. Read CONTRIBUTING.md for more details on how to contribute to this project.
         | 
| 71 67 |  | 
| 72 68 | 
             
            [](http://travis-ci.org/craigw/dns-zonefile)
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -1,11 +1,6 @@ | |
| 1 1 | 
             
            require "bundler/gem_tasks"
         | 
| 2 | 
            +
            require "rspec/core/rake_task"
         | 
| 2 3 |  | 
| 3 | 
            -
            require 'rake'
         | 
| 4 | 
            -
            require 'rspec/core/rake_task'
         | 
| 5 4 | 
             
            RSpec::Core::RakeTask.new(:spec)
         | 
| 6 5 |  | 
| 7 | 
            -
            task : | 
| 8 | 
            -
             | 
| 9 | 
            -
            task :build do
         | 
| 10 | 
            -
              puts %x[gem build dns-zonefile.gemspec]
         | 
| 11 | 
            -
            end
         | 
| 6 | 
            +
            task default: :spec
         | 
    
        data/bin/console
    ADDED
    
    | @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "bundler/setup"
         | 
| 4 | 
            +
            require "dns/zonefile"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            # You can add fixtures and/or initialization code here to make experimenting
         | 
| 7 | 
            +
            # with your gem easier. You can also use a different console, if you like.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            # (If you use this, don't forget to add pry to your Gemfile!)
         | 
| 10 | 
            +
            # require "pry"
         | 
| 11 | 
            +
            # Pry.start
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            require "irb"
         | 
| 14 | 
            +
            IRB.start
         | 
    
        data/bin/setup
    ADDED
    
    
    
        data/circle.yml
    ADDED
    
    
    
        data/dns-zonefile.gemspec
    CHANGED
    
    | @@ -1,31 +1,41 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 1 | 
            +
            lib = File.expand_path("../lib", __FILE__)
         | 
| 2 | 
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 3 3 | 
             
            require "dns/zonefile/version"
         | 
| 4 4 |  | 
| 5 | 
            -
            Gem::Specification.new do | | 
| 6 | 
            -
               | 
| 7 | 
            -
               | 
| 8 | 
            -
               | 
| 9 | 
            -
               | 
| 10 | 
            -
              s.homepage    = ""
         | 
| 11 | 
            -
              s.summary     = %q{Work with zonefiles (RFC 1035 section 5 and RFC 1034 section 3.6.1)}
         | 
| 12 | 
            -
              s.description = %q{The format of a DNS Zonefile is defined in RFC 1035 section 5 and RFC
         | 
| 13 | 
            -
            1034 section 3.6.1. To anyone who's using BIND they'll look very
         | 
| 14 | 
            -
            familiar.
         | 
| 5 | 
            +
            Gem::Specification.new do |spec|
         | 
| 6 | 
            +
              spec.name = "dns-zonefile"
         | 
| 7 | 
            +
              spec.version = DNS::Zonefile::VERSION
         | 
| 8 | 
            +
              spec.authors = ["Craig R Webster", "Anthony Eden"]
         | 
| 9 | 
            +
              spec.email = ["craig@barkingiguana.com", "anthonyeden@gmail.com"]
         | 
| 15 10 |  | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 11 | 
            +
              spec.summary = "Work with zonefiles (RFC 1035 section 5 and RFC 1034 section 3.6.1)"
         | 
| 12 | 
            +
              spec.description = <<~EOD
         | 
| 13 | 
            +
                The format of a DNS Zonefile is defined in RFC 1035 section 5 and RFC
         | 
| 14 | 
            +
                1034 section 3.6.1. To anyone who's using BIND they'll look very
         | 
| 15 | 
            +
                familiar.
         | 
| 16 | 
            +
                
         | 
| 17 | 
            +
                This is an attempt to use Ruby parse them into an object graph which can
         | 
| 18 | 
            +
                be investigated programatically, manipulated, validated or printed into
         | 
| 19 | 
            +
                some canonical form.
         | 
| 20 | 
            +
              EOD
         | 
| 21 | 
            +
              spec.homepage = "https://github.com/craigw/dns-zonefile"
         | 
| 19 22 |  | 
| 20 | 
            -
               | 
| 23 | 
            +
              # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
         | 
| 24 | 
            +
              # delete this section to allow pushing this gem to any host.
         | 
| 25 | 
            +
              if spec.respond_to?(:metadata)
         | 
| 26 | 
            +
                spec.metadata["allowed_push_host"] = "https://rubygems.org"
         | 
| 27 | 
            +
              else
         | 
| 28 | 
            +
                raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
         | 
| 29 | 
            +
              end
         | 
| 21 30 |  | 
| 22 | 
            -
               | 
| 23 | 
            -
               | 
| 24 | 
            -
               | 
| 25 | 
            -
               | 
| 31 | 
            +
              spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
         | 
| 32 | 
            +
              spec.bindir = "exe"
         | 
| 33 | 
            +
              spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
         | 
| 34 | 
            +
              spec.require_paths = ["lib"]
         | 
| 26 35 |  | 
| 27 | 
            -
               | 
| 28 | 
            -
               | 
| 29 | 
            -
               | 
| 30 | 
            -
               | 
| 36 | 
            +
              spec.add_dependency "treetop", "~> 1.6"
         | 
| 37 | 
            +
              spec.add_dependency "polyglot", "~> 0.3"
         | 
| 38 | 
            +
              spec.add_development_dependency "bundler", "~> 2.1"
         | 
| 39 | 
            +
              spec.add_development_dependency "rake", "~> 13.0"
         | 
| 40 | 
            +
              spec.add_development_dependency "rspec", "~> 3.0"
         | 
| 31 41 | 
             
            end
         | 
    
        data/examples/basic.rb
    ADDED
    
    | @@ -0,0 +1,12 @@ | |
| 1 | 
            +
            # First make sure you have installed the `dns-zonefile` gem.
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # Run this script with `ruby basic.rb`
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require "dns/zonefile"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            zonefile = "example.com.zonefile"
         | 
| 8 | 
            +
            zone = DNS::Zonefile.parse(File.read(zonefile))
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            puts zone.soa.origin.to_s
         | 
| 11 | 
            +
            puts zone.soa.ns.to_s
         | 
| 12 | 
            +
            puts zone.rr[0].to_s
         | 
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            # First make sure you have installed the `dns-zonefile` gem.
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # Run this script with `ruby basic.rb`
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require "dns/zonefile"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            zonefile = "example.com.zonefile"
         | 
| 8 | 
            +
            zone = DNS::Zonefile.load(File.read(zonefile), "example.com.")
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            puts zone.soa.origin
         | 
| 11 | 
            +
            puts zone.soa.nameserver
         | 
| 12 | 
            +
            # get all MX records
         | 
| 13 | 
            +
            zone.records_of(DNS::Zonefile::MX).each do |rec|
         | 
| 14 | 
            +
              puts "#{rec.host} #{rec.klass} #{rec.ttl} #{rec.priority} #{rec.domainname}"
         | 
| 15 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            $TTL 1h                  ; default expiration time of all resource records without their own TTL value
         | 
| 2 | 
            +
            example.com.  IN  SOA   ns.example.com. username.example.com. ( 2007120710 1d 2h 4w 1h )
         | 
| 3 | 
            +
            example.com.  IN  NS    ns                    ; ns.example.com is a nameserver for example.com
         | 
| 4 | 
            +
            example.com.  IN  NS    ns.somewhere.example. ; ns.somewhere.example is a backup nameserver for example.com
         | 
| 5 | 
            +
            example.com.  IN  MX    10 mail.example.com.  ; mail.example.com is the mailserver for example.com
         | 
| 6 | 
            +
            @             IN  MX    20 mail2.example.com. ; equivalent to above line, "@" represents zone origin
         | 
| 7 | 
            +
            @             IN  MX    50 mail3              ; equivalent to above line, but using a relative host name
         | 
| 8 | 
            +
            example.com.  IN  A     192.0.2.1             ; IPv4 address for example.com
         | 
| 9 | 
            +
                          IN  AAAA  2001:db8:10::1        ; IPv6 address for example.com
         | 
| 10 | 
            +
            ns            IN  A     192.0.2.2             ; IPv4 address for ns.example.com
         | 
| 11 | 
            +
                          IN  AAAA  2001:db8:10::2        ; IPv6 address for ns.example.com
         | 
| 12 | 
            +
            www           IN  CNAME example.com.          ; www.example.com is an alias for example.com
         | 
| 13 | 
            +
            wwwtest       IN  CNAME www                   ; wwwtest.example.com is another alias for www.example.com
         | 
| 14 | 
            +
            mail          IN  A     192.0.2.3             ; IPv4 address for mail.example.com
         | 
| 15 | 
            +
            mail2         IN  A     192.0.2.4             ; IPv4 address for mail2.example.com
         | 
| 16 | 
            +
            mail3         IN  A     192.0.2.5             ; IPv4 address for mail3.example.com
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            $ORIGIN example.com.     ; designates the start of this zone file in the namespace
         | 
| 2 | 
            +
            $TTL 1h                  ; default expiration time of all resource records without their own TTL value
         | 
| 3 | 
            +
            example.com.  IN  SOA   ns.example.com. username.example.com. ( 2007120710 1d 2h 4w 1h )
         | 
| 4 | 
            +
            example.com.  IN  NS    ns                    ; ns.example.com is a nameserver for example.com
         | 
| 5 | 
            +
            example.com.  IN  NS    ns.somewhere.example. ; ns.somewhere.example is a backup nameserver for example.com
         | 
| 6 | 
            +
            example.com.  IN  MX    10 mail.example.com.  ; mail.example.com is the mailserver for example.com
         | 
| 7 | 
            +
            @             IN  MX    20 mail2.example.com. ; equivalent to above line, "@" represents zone origin
         | 
| 8 | 
            +
            @             IN  MX    50 mail3              ; equivalent to above line, but using a relative host name
         | 
| 9 | 
            +
            example.com.  IN  A     192.0.2.1             ; IPv4 address for example.com
         | 
| 10 | 
            +
                          IN  AAAA  2001:db8:10::1        ; IPv6 address for example.com
         | 
| 11 | 
            +
            ns            IN  A     192.0.2.2             ; IPv4 address for ns.example.com
         | 
| 12 | 
            +
                          IN  AAAA  2001:db8:10::2        ; IPv6 address for ns.example.com
         | 
| 13 | 
            +
            www           IN  CNAME example.com.          ; www.example.com is an alias for example.com
         | 
| 14 | 
            +
            wwwtest       IN  CNAME www                   ; wwwtest.example.com is another alias for www.example.com
         | 
| 15 | 
            +
            mail          IN  A     192.0.2.3             ; IPv4 address for mail.example.com
         | 
| 16 | 
            +
            mail2         IN  A     192.0.2.4             ; IPv4 address for mail2.example.com
         | 
| 17 | 
            +
            mail3         IN  A     192.0.2.5             ; IPv4 address for mail3.example.com
         | 
    
        data/lib/dns/zonefile.rb
    CHANGED
    
    | @@ -1,113 +1,84 @@ | |
| 1 | 
            -
            require  | 
| 2 | 
            -
            require  | 
| 3 | 
            -
            Treetop.load  | 
| 1 | 
            +
            require "dns/zonefile/version"
         | 
| 2 | 
            +
            require "treetop"
         | 
| 3 | 
            +
            Treetop.load File.expand_path("../zonefile", __FILE__)
         | 
| 4 4 |  | 
| 5 5 | 
             
            module DNS
         | 
| 6 6 | 
             
              module Zonefile
         | 
| 7 7 | 
             
                class << self
         | 
| 8 8 | 
             
                  def parse(zone_string)
         | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
            	  raise ParsingError, parser.failure_reason
         | 
| 14 | 
            -
            	end
         | 
| 9 | 
            +
                    parser = ZonefileParser.new
         | 
| 10 | 
            +
                    result = parser.parse(zone_string)
         | 
| 11 | 
            +
                    return result if result
         | 
| 12 | 
            +
                    raise ParsingError, parser.failure_reason
         | 
| 15 13 | 
             
                  end
         | 
| 16 14 |  | 
| 17 | 
            -
                  def load(zone_string, alternate_origin=nil)
         | 
| 18 | 
            -
             | 
| 15 | 
            +
                  def load(zone_string, alternate_origin = nil)
         | 
| 16 | 
            +
                    Zone.new(parse(zone_string).entries, alternate_origin)
         | 
| 19 17 | 
             
                  end
         | 
| 20 18 | 
             
                end
         | 
| 21 19 |  | 
| 22 | 
            -
                class ParsingError < RuntimeError | 
| 23 | 
            -
                class UnknownRecordType < RuntimeError | 
| 20 | 
            +
                class ParsingError < RuntimeError; end
         | 
| 21 | 
            +
                class UnknownRecordType < RuntimeError; end
         | 
| 24 22 | 
             
                class Zone
         | 
| 25 | 
            -
                  attr_reader :origin | 
| 23 | 
            +
                  attr_reader :origin
         | 
| 26 24 | 
             
                  attr_reader :records
         | 
| 27 25 |  | 
| 28 | 
            -
                  def initialize(entries, alternate_origin=nil)
         | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 26 | 
            +
                  def initialize(entries, alternate_origin = nil)
         | 
| 27 | 
            +
                    alternate_origin ||= "."
         | 
| 28 | 
            +
                    @records = []
         | 
| 29 | 
            +
                    @vars = {"origin" => alternate_origin, :last_host => "."}
         | 
| 30 | 
            +
                    entries.each do |e|
         | 
| 31 | 
            +
                      case e.parse_type
         | 
| 32 | 
            +
                      when :variable
         | 
| 33 | 
            +
                        key = e.name.text_value.downcase
         | 
| 34 | 
            +
                        @vars[key] = case key
         | 
| 35 | 
            +
                        when "ttl"
         | 
| 36 | 
            +
                          e.value.text_value.to_i
         | 
| 37 | 
            +
                        else
         | 
| 38 | 
            +
                          e.value.text_value
         | 
| 39 | 
            +
                        end
         | 
| 40 | 
            +
                      when :soa
         | 
| 41 | 
            +
                        @records << SOA.new(@vars, e)
         | 
| 42 | 
            +
                      when :record
         | 
| 43 | 
            +
                        case e.record_type
         | 
| 44 | 
            +
                        when "A" then @records << A.new(@vars, e)
         | 
| 45 | 
            +
                        when "AAAA" then @records << AAAA.new(@vars, e)
         | 
| 46 | 
            +
                        when "CAA" then @records << CAA.new(@vars, e)
         | 
| 47 | 
            +
                        when "CNAME" then @records << CNAME.new(@vars, e)
         | 
| 48 | 
            +
                        when "MX" then @records << MX.new(@vars, e)
         | 
| 49 | 
            +
                        when "NAPTR" then @records << NAPTR.new(@vars, e)
         | 
| 50 | 
            +
                        when "NS" then @records << NS.new(@vars, e)
         | 
| 51 | 
            +
                        when "PTR" then @records << PTR.new(@vars, e)
         | 
| 52 | 
            +
                        when "SRV" then @records << SRV.new(@vars, e)
         | 
| 53 | 
            +
                        when "SPF" then @records << SPF.new(@vars, e)
         | 
| 54 | 
            +
                        when "SSHFP" then @records << SSHFP.new(@vars, e)
         | 
| 55 | 
            +
                        when "TXT" then @records << TXT.new(@vars, e)
         | 
| 56 | 
            +
                        when "SOA" then
         | 
| 57 | 
            +
                          # No-op
         | 
| 58 | 
            +
                        else
         | 
| 59 | 
            +
                          raise UnknownRecordType, "Unknown record type: #{e.record_type}"
         | 
| 60 | 
            +
                        end
         | 
| 61 | 
            +
                      end
         | 
| 62 | 
            +
                    end
         | 
| 61 63 | 
             
                  end
         | 
| 62 64 |  | 
| 63 65 | 
             
                  def soa
         | 
| 64 | 
            -
             | 
| 66 | 
            +
                    records_of(SOA).first
         | 
| 65 67 | 
             
                  end
         | 
| 66 68 |  | 
| 67 69 | 
             
                  def records_of(kl)
         | 
| 68 | 
            -
             | 
| 70 | 
            +
                    @records.select { |r| r.instance_of? kl }
         | 
| 69 71 | 
             
                  end
         | 
| 70 72 | 
             
                end
         | 
| 71 73 |  | 
| 72 74 | 
             
                class Record
         | 
| 73 | 
            -
                  # assign, with handling for '@'
         | 
| 74 | 
            -
                  def self.writer_for_at(*attribs)
         | 
| 75 | 
            -
            	attribs.each do |attrib|
         | 
| 76 | 
            -
            	  c = <<-MTH
         | 
| 77 | 
            -
            	    def #{attrib}=(val)
         | 
| 78 | 
            -
            	      @#{attrib} = val.gsub('@', @vars['origin'])
         | 
| 79 | 
            -
            	    end
         | 
| 80 | 
            -
            	  MTH
         | 
| 81 | 
            -
            	  class_eval c, __FILE__, __LINE__
         | 
| 82 | 
            -
            	end
         | 
| 83 | 
            -
                  end
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                  # assign, with handling for '@', with inheritance
         | 
| 86 | 
            -
                  def self.inheriting_writer_for_at(*attribs)
         | 
| 87 | 
            -
            	attribs.each do |attrib|
         | 
| 88 | 
            -
            	  c = <<-MTH
         | 
| 89 | 
            -
            	    def #{attrib}=(val)
         | 
| 90 | 
            -
            	      if val.strip.empty?
         | 
| 91 | 
            -
            		@#{attrib} = @vars[:last_host]
         | 
| 92 | 
            -
            	      else
         | 
| 93 | 
            -
            		@#{attrib} = val.gsub('@', @vars['origin'])
         | 
| 94 | 
            -
            	      end
         | 
| 95 | 
            -
            	    end
         | 
| 96 | 
            -
            	  MTH
         | 
| 97 | 
            -
            	  class_eval c, __FILE__, __LINE__
         | 
| 98 | 
            -
            	end
         | 
| 99 | 
            -
                  end
         | 
| 100 | 
            -
             | 
| 101 75 | 
             
                  # assign, with handling for global TTL
         | 
| 102 76 | 
             
                  def self.writer_for_ttl(*attribs)
         | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
            	  MTH
         | 
| 109 | 
            -
            	  class_eval c, __FILE__, __LINE__
         | 
| 110 | 
            -
            	end
         | 
| 77 | 
            +
                    attribs.each do |attrib|
         | 
| 78 | 
            +
                      define_method "#{attrib}=" do |val|
         | 
| 79 | 
            +
                        instance_variable_set("@#{attrib}", val || @vars["ttl"])
         | 
| 80 | 
            +
                      end
         | 
| 81 | 
            +
                    end
         | 
| 111 82 | 
             
                  end
         | 
| 112 83 |  | 
| 113 84 | 
             
                  attr_reader :ttl
         | 
| @@ -115,192 +86,218 @@ module DNS | |
| 115 86 | 
             
                  writer_for_ttl :ttl
         | 
| 116 87 |  | 
| 117 88 | 
             
                  def klass
         | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 89 | 
            +
                    @klass = nil if @klass == ""
         | 
| 90 | 
            +
                    @klass ||= "IN"
         | 
| 120 91 | 
             
                  end
         | 
| 121 92 |  | 
| 93 | 
            +
                  private
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  def qualify_host(host)
         | 
| 96 | 
            +
                    origin = vars["origin"]
         | 
| 97 | 
            +
                    host = vars[:last_host] if /^\s*$/.match?(host)
         | 
| 98 | 
            +
                    host = host.gsub(/@/, origin)
         | 
| 99 | 
            +
                    if /\.$/.match?(host)
         | 
| 100 | 
            +
                      host
         | 
| 101 | 
            +
                    elsif /^\./.match?(origin)
         | 
| 102 | 
            +
                      host + origin
         | 
| 103 | 
            +
                    else
         | 
| 104 | 
            +
                      host + "." + origin
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                  attr_accessor :vars
         | 
| 122 108 | 
             
                end
         | 
| 123 109 |  | 
| 124 110 | 
             
                class SOA < Record
         | 
| 125 111 | 
             
                  attr_accessor :origin, :nameserver, :responsible_party, :serial, :refresh_time, :retry_time, :expiry_time, :nxttl
         | 
| 126 112 |  | 
| 127 | 
            -
                   | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
            	  self.nxttl             = zonefile_soa.nxttl.to_i
         | 
| 143 | 
            -
            	end
         | 
| 113 | 
            +
                  def initialize(vars, zonefile_soa = nil)
         | 
| 114 | 
            +
                    @vars = vars
         | 
| 115 | 
            +
                    if zonefile_soa
         | 
| 116 | 
            +
                      self.origin = qualify_host(zonefile_soa.origin.to_s)
         | 
| 117 | 
            +
                      @vars[:last_host] = origin
         | 
| 118 | 
            +
                      self.ttl = zonefile_soa.ttl.to_i
         | 
| 119 | 
            +
                      self.klass = zonefile_soa.klass.to_s
         | 
| 120 | 
            +
                      self.nameserver = qualify_host(zonefile_soa.ns.to_s)
         | 
| 121 | 
            +
                      self.responsible_party = qualify_host(zonefile_soa.rp.to_s)
         | 
| 122 | 
            +
                      self.serial = zonefile_soa.serial.to_i
         | 
| 123 | 
            +
                      self.refresh_time = zonefile_soa.refresh.to_i
         | 
| 124 | 
            +
                      self.retry_time = zonefile_soa.reretry.to_i
         | 
| 125 | 
            +
                      self.expiry_time = zonefile_soa.expiry.to_i
         | 
| 126 | 
            +
                      self.nxttl = zonefile_soa.nxttl.to_i
         | 
| 127 | 
            +
                    end
         | 
| 144 128 | 
             
                  end
         | 
| 145 129 | 
             
                end
         | 
| 146 130 |  | 
| 147 131 | 
             
                class A < Record
         | 
| 148 132 | 
             
                  attr_accessor :host, :address
         | 
| 149 133 |  | 
| 150 | 
            -
                  inheriting_writer_for_at  :host
         | 
| 151 | 
            -
             | 
| 152 134 | 
             
                  def initialize(vars, zonefile_record)
         | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 135 | 
            +
                    @vars = vars
         | 
| 136 | 
            +
                    if zonefile_record
         | 
| 137 | 
            +
                      self.host = qualify_host(zonefile_record.host.to_s)
         | 
| 138 | 
            +
                      @vars[:last_host] = host
         | 
| 139 | 
            +
                      self.ttl = zonefile_record.ttl.to_i
         | 
| 140 | 
            +
                      self.klass = zonefile_record.klass.to_s
         | 
| 141 | 
            +
                      self.address = zonefile_record.ip_address.to_s
         | 
| 142 | 
            +
                    end
         | 
| 161 143 | 
             
                  end
         | 
| 162 144 | 
             
                end
         | 
| 163 145 |  | 
| 164 146 | 
             
                class AAAA < A
         | 
| 165 147 | 
             
                end
         | 
| 166 148 |  | 
| 149 | 
            +
                class CAA < Record
         | 
| 150 | 
            +
                  attr_accessor :host, :flags, :tag, :value
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                  def initialize(vars, zonefile_record)
         | 
| 153 | 
            +
                    @vars = vars
         | 
| 154 | 
            +
                    if zonefile_record
         | 
| 155 | 
            +
                      self.host = qualify_host(zonefile_record.host.to_s)
         | 
| 156 | 
            +
                      @vars[:last_host] = host
         | 
| 157 | 
            +
                      self.ttl = zonefile_record.ttl.to_i
         | 
| 158 | 
            +
                      self.klass = zonefile_record.klass.to_s
         | 
| 159 | 
            +
                      self.flags = zonefile_record.flags.to_i
         | 
| 160 | 
            +
                      self.tag = zonefile_record.tag.to_s
         | 
| 161 | 
            +
                      self.value = zonefile_record.value.to_s
         | 
| 162 | 
            +
                    end
         | 
| 163 | 
            +
                  end
         | 
| 164 | 
            +
                end
         | 
| 165 | 
            +
             | 
| 167 166 | 
             
                class CNAME < Record
         | 
| 168 167 | 
             
                  attr_accessor :host, :domainname
         | 
| 169 168 |  | 
| 170 | 
            -
                  inheriting_writer_for_at  :host
         | 
| 171 | 
            -
                  writer_for_at :domainname
         | 
| 172 | 
            -
             | 
| 173 169 | 
             
                  def initialize(vars, zonefile_record)
         | 
| 174 | 
            -
             | 
| 175 | 
            -
             | 
| 176 | 
            -
             | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 170 | 
            +
                    @vars = vars
         | 
| 171 | 
            +
                    if zonefile_record
         | 
| 172 | 
            +
                      self.host = qualify_host(zonefile_record.host.to_s)
         | 
| 173 | 
            +
                      @vars[:last_host] = host
         | 
| 174 | 
            +
                      self.ttl = zonefile_record.ttl.to_i
         | 
| 175 | 
            +
                      self.klass = zonefile_record.klass.to_s
         | 
| 176 | 
            +
                      self.domainname = qualify_host(zonefile_record.target.to_s)
         | 
| 177 | 
            +
                    end
         | 
| 182 178 | 
             
                  end
         | 
| 183 179 |  | 
| 184 | 
            -
                  alias  | 
| 185 | 
            -
                  alias  | 
| 180 | 
            +
                  alias target domainname
         | 
| 181 | 
            +
                  alias alias host
         | 
| 186 182 | 
             
                end
         | 
| 187 183 |  | 
| 188 184 | 
             
                class MX < Record
         | 
| 189 185 | 
             
                  attr_accessor :host, :priority, :domainname
         | 
| 190 186 |  | 
| 191 | 
            -
                  inheriting_writer_for_at  :host
         | 
| 192 | 
            -
                  writer_for_at :domainname
         | 
| 193 | 
            -
             | 
| 194 187 | 
             
                  def initialize(vars, zonefile_record)
         | 
| 195 | 
            -
             | 
| 196 | 
            -
             | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 199 | 
            -
             | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 202 | 
            -
             | 
| 203 | 
            -
             | 
| 188 | 
            +
                    @vars = vars
         | 
| 189 | 
            +
                    if zonefile_record
         | 
| 190 | 
            +
                      self.host = qualify_host(zonefile_record.host.to_s)
         | 
| 191 | 
            +
                      @vars[:last_host] = host
         | 
| 192 | 
            +
                      self.ttl = zonefile_record.ttl.to_i
         | 
| 193 | 
            +
                      self.klass = zonefile_record.klass.to_s
         | 
| 194 | 
            +
                      self.priority = zonefile_record.priority.to_i
         | 
| 195 | 
            +
                      self.domainname = qualify_host(zonefile_record.exchanger.to_s)
         | 
| 196 | 
            +
                    end
         | 
| 204 197 | 
             
                  end
         | 
| 205 198 |  | 
| 206 | 
            -
                  alias  | 
| 207 | 
            -
                  alias  | 
| 199 | 
            +
                  alias exchange domainname
         | 
| 200 | 
            +
                  alias exchanger domainname
         | 
| 208 201 | 
             
                end
         | 
| 209 202 |  | 
| 210 203 | 
             
                class NAPTR < Record
         | 
| 211 204 | 
             
                  attr_accessor :host, :data
         | 
| 212 205 |  | 
| 213 | 
            -
                  inheriting_writer_for_at  :host
         | 
| 214 | 
            -
             | 
| 215 206 | 
             
                  def initialize(vars, zonefile_record)
         | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 220 | 
            -
             | 
| 221 | 
            -
             | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 207 | 
            +
                    @vars = vars
         | 
| 208 | 
            +
                    if zonefile_record
         | 
| 209 | 
            +
                      self.host = qualify_host(zonefile_record.host.to_s)
         | 
| 210 | 
            +
                      @vars[:last_host] = host
         | 
| 211 | 
            +
                      self.ttl = zonefile_record.ttl.to_i
         | 
| 212 | 
            +
                      self.klass = zonefile_record.klass.to_s
         | 
| 213 | 
            +
                      self.data = zonefile_record.data.to_s
         | 
| 214 | 
            +
                    end
         | 
| 224 215 | 
             
                  end
         | 
| 225 216 | 
             
                end
         | 
| 226 217 |  | 
| 227 218 | 
             
                class NS < Record
         | 
| 228 219 | 
             
                  attr_accessor :host, :domainname
         | 
| 229 220 |  | 
| 230 | 
            -
                  inheriting_writer_for_at  :host
         | 
| 231 | 
            -
                  writer_for_at :domainname
         | 
| 232 | 
            -
             | 
| 233 221 | 
             
                  def initialize(vars, zonefile_record)
         | 
| 234 | 
            -
             | 
| 235 | 
            -
             | 
| 236 | 
            -
             | 
| 237 | 
            -
             | 
| 238 | 
            -
             | 
| 239 | 
            -
             | 
| 240 | 
            -
             | 
| 241 | 
            -
             | 
| 222 | 
            +
                    @vars = vars
         | 
| 223 | 
            +
                    if zonefile_record
         | 
| 224 | 
            +
                      self.host = qualify_host(zonefile_record.host.to_s)
         | 
| 225 | 
            +
                      @vars[:last_host] = host
         | 
| 226 | 
            +
                      self.ttl = zonefile_record.ttl.to_i
         | 
| 227 | 
            +
                      self.klass = zonefile_record.klass.to_s
         | 
| 228 | 
            +
                      self.domainname = qualify_host(zonefile_record.nameserver.to_s)
         | 
| 229 | 
            +
                    end
         | 
| 242 230 | 
             
                  end
         | 
| 243 231 |  | 
| 244 | 
            -
                  alias  | 
| 232 | 
            +
                  alias nameserver domainname
         | 
| 245 233 | 
             
                end
         | 
| 246 234 |  | 
| 247 235 | 
             
                class PTR < Record
         | 
| 248 236 | 
             
                  attr_accessor :host, :domainname
         | 
| 249 237 |  | 
| 250 | 
            -
                  inheriting_writer_for_at  :host
         | 
| 251 | 
            -
                  writer_for_at :domainname
         | 
| 252 | 
            -
             | 
| 253 238 | 
             
                  def initialize(vars, zonefile_record)
         | 
| 254 | 
            -
             | 
| 255 | 
            -
             | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 258 | 
            -
             | 
| 259 | 
            -
             | 
| 260 | 
            -
             | 
| 261 | 
            -
             | 
| 239 | 
            +
                    @vars = vars
         | 
| 240 | 
            +
                    if zonefile_record
         | 
| 241 | 
            +
                      self.host = qualify_host(zonefile_record.host.to_s)
         | 
| 242 | 
            +
                      @vars[:last_host] = host
         | 
| 243 | 
            +
                      self.ttl = zonefile_record.ttl.to_i
         | 
| 244 | 
            +
                      self.klass = zonefile_record.klass.to_s
         | 
| 245 | 
            +
                      self.domainname = qualify_host(zonefile_record.target.to_s)
         | 
| 246 | 
            +
                    end
         | 
| 262 247 | 
             
                  end
         | 
| 263 248 |  | 
| 264 | 
            -
                  alias  | 
| 249 | 
            +
                  alias target domainname
         | 
| 265 250 | 
             
                end
         | 
| 266 251 |  | 
| 267 252 | 
             
                class SRV < Record
         | 
| 268 253 | 
             
                  attr_accessor :host, :priority, :weight, :port, :domainname
         | 
| 269 254 |  | 
| 270 | 
            -
                  inheriting_writer_for_at  :host
         | 
| 271 | 
            -
                  writer_for_at :domainname
         | 
| 272 | 
            -
             | 
| 273 255 | 
             
                  def initialize(vars, zonefile_record)
         | 
| 274 | 
            -
             | 
| 275 | 
            -
             | 
| 276 | 
            -
             | 
| 277 | 
            -
             | 
| 278 | 
            -
             | 
| 279 | 
            -
             | 
| 280 | 
            -
             | 
| 281 | 
            -
             | 
| 282 | 
            -
             | 
| 283 | 
            -
             | 
| 284 | 
            -
             | 
| 256 | 
            +
                    @vars = vars
         | 
| 257 | 
            +
                    if zonefile_record
         | 
| 258 | 
            +
                      self.host = qualify_host(zonefile_record.host.to_s)
         | 
| 259 | 
            +
                      @vars[:last_host] = host
         | 
| 260 | 
            +
                      self.ttl = zonefile_record.ttl.to_i
         | 
| 261 | 
            +
                      self.klass = zonefile_record.klass.to_s
         | 
| 262 | 
            +
                      self.priority = zonefile_record.priority.to_i
         | 
| 263 | 
            +
                      self.weight = zonefile_record.weight.to_i
         | 
| 264 | 
            +
                      self.port = zonefile_record.port.to_i
         | 
| 265 | 
            +
                      self.domainname = qualify_host(zonefile_record.target.to_s)
         | 
| 266 | 
            +
                    end
         | 
| 285 267 | 
             
                  end
         | 
| 286 268 |  | 
| 287 | 
            -
                  alias  | 
| 269 | 
            +
                  alias target domainname
         | 
| 270 | 
            +
                end
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                class SSHFP < Record
         | 
| 273 | 
            +
                  attr_accessor :host, :alg, :fptype, :fp
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                  def initialize(vars, zonefile_record)
         | 
| 276 | 
            +
                    @vars = vars
         | 
| 277 | 
            +
                    if zonefile_record
         | 
| 278 | 
            +
                      self.host = qualify_host(zonefile_record.host.to_s)
         | 
| 279 | 
            +
                      @vars[:last_host] = host
         | 
| 280 | 
            +
                      self.ttl = zonefile_record.ttl.to_i
         | 
| 281 | 
            +
                      self.klass = zonefile_record.klass.to_s
         | 
| 282 | 
            +
                      self.alg = zonefile_record.alg.to_i
         | 
| 283 | 
            +
                      self.fptype = zonefile_record.fptype.to_i
         | 
| 284 | 
            +
                      self.fp = zonefile_record.fp.to_s
         | 
| 285 | 
            +
                    end
         | 
| 286 | 
            +
                  end
         | 
| 288 287 | 
             
                end
         | 
| 289 288 |  | 
| 290 289 | 
             
                class TXT < Record
         | 
| 291 290 | 
             
                  attr_accessor :host, :data
         | 
| 292 291 |  | 
| 293 | 
            -
                  inheriting_writer_for_at  :host
         | 
| 294 | 
            -
             | 
| 295 292 | 
             
                  def initialize(vars, zonefile_record)
         | 
| 296 | 
            -
             | 
| 297 | 
            -
             | 
| 298 | 
            -
             | 
| 299 | 
            -
             | 
| 300 | 
            -
             | 
| 301 | 
            -
             | 
| 302 | 
            -
             | 
| 303 | 
            -
             | 
| 293 | 
            +
                    @vars = vars
         | 
| 294 | 
            +
                    if zonefile_record
         | 
| 295 | 
            +
                      self.host = qualify_host(zonefile_record.host.to_s)
         | 
| 296 | 
            +
                      @vars[:last_host] = host
         | 
| 297 | 
            +
                      self.ttl = zonefile_record.ttl.to_i
         | 
| 298 | 
            +
                      self.klass = zonefile_record.klass.to_s
         | 
| 299 | 
            +
                      self.data = zonefile_record.data.to_s
         | 
| 300 | 
            +
                    end
         | 
| 304 301 | 
             
                  end
         | 
| 305 302 | 
             
                end
         | 
| 306 303 |  |