dns-zone2 0.3.2
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 +7 -0
- data/Gemfile +2 -0
- data/HISTORY.md +45 -0
- data/README.md +151 -0
- data/Rakefile +15 -0
- data/dns-zone2.gemspec +41 -0
- data/lib/dns/zone.rb +207 -0
- data/lib/dns/zone/rr.rb +87 -0
- data/lib/dns/zone/rr/a.rb +21 -0
- data/lib/dns/zone/rr/aaaa.rb +5 -0
- data/lib/dns/zone/rr/cdnskey.rb +5 -0
- data/lib/dns/zone/rr/cds.rb +5 -0
- data/lib/dns/zone/rr/cname.rb +21 -0
- data/lib/dns/zone/rr/dlv.rb +5 -0
- data/lib/dns/zone/rr/dnskey.rb +38 -0
- data/lib/dns/zone/rr/ds.rb +38 -0
- data/lib/dns/zone/rr/hinfo.rb +31 -0
- data/lib/dns/zone/rr/mx.rb +33 -0
- data/lib/dns/zone/rr/naptr.rb +44 -0
- data/lib/dns/zone/rr/ns.rb +21 -0
- data/lib/dns/zone/rr/nsec.rb +32 -0
- data/lib/dns/zone/rr/nsec3.rb +45 -0
- data/lib/dns/zone/rr/nsec3param.rb +38 -0
- data/lib/dns/zone/rr/ptr.rb +21 -0
- data/lib/dns/zone/rr/record.rb +88 -0
- data/lib/dns/zone/rr/rrsig.rb +54 -0
- data/lib/dns/zone/rr/soa.rb +51 -0
- data/lib/dns/zone/rr/spf.rb +5 -0
- data/lib/dns/zone/rr/srv.rb +38 -0
- data/lib/dns/zone/rr/sshfp.rb +35 -0
- data/lib/dns/zone/rr/txt.rb +24 -0
- data/lib/dns/zone/test_case.rb +27 -0
- data/lib/dns/zone/version.rb +6 -0
- data/test/rr/a_test.rb +37 -0
- data/test/rr/aaaa_test.rb +27 -0
- data/test/rr/cdnskey_test.rb +31 -0
- data/test/rr/cds_test.rb +28 -0
- data/test/rr/cname_test.rb +19 -0
- data/test/rr/dlv_test.rb +28 -0
- data/test/rr/dnskey_test.rb +31 -0
- data/test/rr/ds_test.rb +28 -0
- data/test/rr/hinfo_test.rb +44 -0
- data/test/rr/mx_test.rb +26 -0
- data/test/rr/naptr_test.rb +60 -0
- data/test/rr/ns_test.rb +18 -0
- data/test/rr/nsec3_test.rb +33 -0
- data/test/rr/nsec3param_test.rb +29 -0
- data/test/rr/nsec_test.rb +24 -0
- data/test/rr/ptr_test.rb +19 -0
- data/test/rr/record_test.rb +37 -0
- data/test/rr/rrsig_test.rb +40 -0
- data/test/rr/soa_test.rb +34 -0
- data/test/rr/spf_test.rb +20 -0
- data/test/rr/srv_test.rb +24 -0
- data/test/rr/sshfp_test.rb +24 -0
- data/test/rr/txt_test.rb +44 -0
- data/test/rr_test.rb +50 -0
- data/test/version_test.rb +9 -0
- data/test/zone_test.rb +273 -0
- metadata +217 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6f75671d72916d9ca1b4905cd91300b37126d716
|
4
|
+
data.tar.gz: b5a7f7f754bc0c3145efd379c29812dcee7f365f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7b05d6fcc4b0209db6c000e7febc9cec4c55fa6d3d5caae968a34540f8ece38546f04ca4bf130fdebbbd4c9008fe7f636b554d53002966124e062304656a9b8e
|
7
|
+
data.tar.gz: 3f3f32885b598a05e9bdc64d34264c85e4fe55a173038380e7f8292e20a332d479d34a302212917faeaf04272e0c11a9c7a5bc36ec449dbc90dc70de185bec26
|
data/Gemfile
ADDED
data/HISTORY.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
## HEAD
|
2
|
+
|
3
|
+
## 0.3.1 (2015-12-23)
|
4
|
+
|
5
|
+
* Fix edge case when zone file has multiple `ORIGIN` directives.
|
6
|
+
|
7
|
+
## 0.3.0 (2015-12-23)
|
8
|
+
|
9
|
+
* Requires Ruby version >= 2.0
|
10
|
+
* Ability to parse zone file with multiple `ORIGIN` directives.
|
11
|
+
|
12
|
+
## 0.2.0 (2015-10-20)
|
13
|
+
|
14
|
+
Development sponsored by Peter J. Philipp [centroid.eu](http://centroid.eu)
|
15
|
+
|
16
|
+
* Add support for DNSSEC focused RR Types:
|
17
|
+
- RFC 3403: NAPTR
|
18
|
+
- RFC 4255: SSHFP
|
19
|
+
- RFC 4034: DNSKEY, DS, RRSIG, NSEC
|
20
|
+
- RFC 7344: CDNSKEY, CDS
|
21
|
+
- RFC 4431: DLV
|
22
|
+
- RFC 5155: NSEC3, NSEC3PARAM
|
23
|
+
* Allow unqualified `domain-name` labels.
|
24
|
+
* Allow `ORIGIN` to be specified as an optional parameter when loading a zone, e.g. `zone = DNS::Zone.load(zone_as_string, 'example.com.')`
|
25
|
+
|
26
|
+
# 0.1.4 (no gem release)
|
27
|
+
|
28
|
+
* Add helper method to quickly access (or create) SOA.
|
29
|
+
* Add `dump_pretty` method to `DNS::Zone`.
|
30
|
+
|
31
|
+
## 0.1.3 (2014-10-21)
|
32
|
+
|
33
|
+
* Fix TXT record parsing bug, when quote enclosed RDATA contained semicolons.
|
34
|
+
|
35
|
+
## 0.1.1 (2014-03-30)
|
36
|
+
|
37
|
+
* Remove `required_ruby_version` from gemspec.
|
38
|
+
|
39
|
+
## 0.1.0 (2014-03-30)
|
40
|
+
|
41
|
+
* Initial non-alpha release with support for common resource records.
|
42
|
+
|
43
|
+
## 0.0.0 (2014-02-16)
|
44
|
+
|
45
|
+
* Initial development/hacking initiated.
|
data/README.md
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
dns-zone
|
2
|
+
========
|
3
|
+
|
4
|
+
[](http://travis-ci.org/lantins/dns-zone)
|
5
|
+
[](http://badge.fury.io/rb/dns-zone)
|
6
|
+
[](https://github.com/lantins/dns-zone/blob/master/LICENSE)
|
7
|
+
[](http://rubydoc.info/github/lantins/dns-zone/master/frames)
|
8
|
+
|
9
|
+
A Ruby library for building, parsing and manipulating DNS zone files.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your Gemfile:
|
14
|
+
|
15
|
+
gem 'dns-zone'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
bundle install
|
20
|
+
|
21
|
+
Require the gem in your code:
|
22
|
+
|
23
|
+
require 'dns/zone'
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
### Loading a zone file
|
28
|
+
|
29
|
+
zone = DNS::Zone.load(zone_as_string)
|
30
|
+
|
31
|
+
### Loading a zone file, without an `$ORIGIN` directive
|
32
|
+
|
33
|
+
zone = DNS::Zone.load(zone_as_string, "example.com.")
|
34
|
+
|
35
|
+
### Creating a new zone programmatically
|
36
|
+
|
37
|
+
zone = DNS::Zone.new
|
38
|
+
zone.origin = 'example.com.'
|
39
|
+
zone.ttl = '1d'
|
40
|
+
|
41
|
+
# quick access to SOA RR
|
42
|
+
zone.soa.nameserver = 'ns0.lividpenguin.com.'
|
43
|
+
zone.soa.email = 'hostmaster.lividpenguin.com.'
|
44
|
+
|
45
|
+
# add an A RR
|
46
|
+
rec = DNS::Zone::RR::A.new
|
47
|
+
rec.address = '127.0.0.1'
|
48
|
+
zone.records << rec
|
49
|
+
|
50
|
+
# output using dns zone file format
|
51
|
+
zone.dump
|
52
|
+
|
53
|
+
# Development
|
54
|
+
|
55
|
+
## Development Commands
|
56
|
+
|
57
|
+
# install external gem dependencies first
|
58
|
+
bundle install
|
59
|
+
|
60
|
+
# run all tests and build code coverage
|
61
|
+
bundle exec rake test
|
62
|
+
|
63
|
+
# hints where to improve docs
|
64
|
+
bundle exec inch
|
65
|
+
|
66
|
+
# watch for changes and run development commands (tests, documentation, etc)
|
67
|
+
bundle exec guard
|
68
|
+
|
69
|
+
# Acknowledgement
|
70
|
+
|
71
|
+
Special thanks to Peter J. Philipp [centroid.eu](http://centroid.eu) for sponsoring the 0.2.0 release of dns-zone.
|
72
|
+
|
73
|
+
---
|
74
|
+
|
75
|
+
# TODO
|
76
|
+
|
77
|
+
## Must have
|
78
|
+
|
79
|
+
[x] Ability to load a zone made of multiple RR's
|
80
|
+
[x] Add support for RR Type: SOA
|
81
|
+
[x] Add support for RR Type: NS
|
82
|
+
[x] Add support for RR Type: MX
|
83
|
+
[x] Add support for RR Type: AAAA
|
84
|
+
[x] Add support for RR Type: A
|
85
|
+
[x] Add support for RR Type: CNAME
|
86
|
+
[x] Add support for RR Type: TXT
|
87
|
+
[x] Add support for RR Type: SRV
|
88
|
+
[x] Add support for RR Type: PTR
|
89
|
+
[x] Add support for RR Type: SPF
|
90
|
+
[x] Add support for RR Type: HINFO
|
91
|
+
[x] Support loading zone where some records have an empty label
|
92
|
+
|
93
|
+
[x] Add support for RR Type: NAPTR (RFC 3403)
|
94
|
+
[x] Add support for RR Type: SSHFP (RFC 4255)
|
95
|
+
|
96
|
+
[ ] Add test using real bind zone file, with DNSSEC RR's.
|
97
|
+
[ ] Add support for DNSSEC (RFC 4034) RR Types:
|
98
|
+
[x] DNSKEY
|
99
|
+
[ ] Algorithm may be integer or mnemonic.
|
100
|
+
[x] RRSIG
|
101
|
+
[ ] Algorithm may be integer or mnemonic.
|
102
|
+
[x] NSEC
|
103
|
+
[ ] Handle "Type Bit Maps" better, much better...
|
104
|
+
[x] DS
|
105
|
+
[ ] Add support for DNSSEC (RFC 5155) RR Types:
|
106
|
+
[x] NSEC3
|
107
|
+
[x] NSEC3PARAM
|
108
|
+
[ ] Correctly handle "Presentation Format" as defined in RFC.
|
109
|
+
|
110
|
+
[x] Add support for DNSSEC (RFC 4431 & RFC 7344) RR Types:
|
111
|
+
[x] CDNSKEY (identical to DNSKEY)
|
112
|
+
[x] CDS (identical to DS)
|
113
|
+
[x] DLV (identical to DS)
|
114
|
+
|
115
|
+
[ ] Look at newly added DNSSEC RR's and rename fields to be more appropriate, where required.
|
116
|
+
|
117
|
+
## Would be nice
|
118
|
+
|
119
|
+
[ ] Basic validation, error checking:
|
120
|
+
[ ] Only one SOA per zone.
|
121
|
+
[ ] CNAMEs can't use a label of `@`.
|
122
|
+
[ ] PTR zones have some extra conditions:
|
123
|
+
[ ] labels cant be repeated
|
124
|
+
[ ] names should end in a dot, otherwise they are invalid after expansion
|
125
|
+
[ ] IPv4 and IPv6 cant be mixed
|
126
|
+
|
127
|
+
[ ] Ability to 'include' defaults/records into a zone.
|
128
|
+
This may or may not mean supporting the `$INCLUDE` directive.
|
129
|
+
|
130
|
+
## At some point; low priority
|
131
|
+
|
132
|
+
[ ] Configuration options:
|
133
|
+
[ ] spaces/tabs used between RR params in zone file output
|
134
|
+
[ ] time format used in output (should parse both formats, seconds or bind time format (e.g. 1d))
|
135
|
+
[ ] add comments to explain TTL's that are in seconds
|
136
|
+
[ ] Ability to add comment to RR (n.b. currently we strip comments when parsing)
|
137
|
+
[ ] Add support for RR Type: LOC (RFC 1876)
|
138
|
+
[ ] Add support for RR Type: DNAME (RFC 2672)
|
139
|
+
[ ] Add support for RR Type: KEY
|
140
|
+
[ ] Add support for RR Type: RP
|
141
|
+
[ ] Add support for RR Type: RT
|
142
|
+
|
143
|
+
# Misc. Development Notes
|
144
|
+
|
145
|
+
- RR Format: `[<TTL>] [<class>] <type> <RDATA>`
|
146
|
+
- A DNS zone is built from RR's and a couple of other special directives.
|
147
|
+
- If zone file does not include $ORIGIN, it will be inferred by the `zone "<zone-name>" {}` clause from bind.conf
|
148
|
+
In general we should always explicitly define an $ORIGIN directive unless there is a very good reason not to.
|
149
|
+
- [RFC 1035 - Domain Names - Implementation and Specification](http://www.ietf.org/rfc/rfc1035.txt)
|
150
|
+
- [RFC 2308 - Negative Caching of DNS Queries (DNS NCACHE)](http://www.ietf.org/rfc/rfc2308.txt)
|
151
|
+
- [RFC 3596 - DNS Extensions to Support IP Version 6](http://www.ietf.org/rfc/rfc3596.txt)
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems' unless defined?(Gem)
|
2
|
+
require 'bundler'
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
# by default run unit tests.
|
7
|
+
task :default => 'test'
|
8
|
+
|
9
|
+
desc 'Run full test suite and generate code coverage -- COVERAGE=false to disable code coverage'
|
10
|
+
Rake::TestTask.new(:test) do |task|
|
11
|
+
ENV['COVERAGE'] ||= 'yes'
|
12
|
+
task.libs << 'test'
|
13
|
+
task.pattern = 'test/**/*_test.rb'
|
14
|
+
task.verbose = true
|
15
|
+
end
|
data/dns-zone2.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require './lib/dns/zone/version'
|
2
|
+
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
# gem information/details
|
5
|
+
s.name = 'dns-zone2'
|
6
|
+
s.version = DNS::Zone::Version
|
7
|
+
s.date = Time.now.strftime('%Y-%m-%d')
|
8
|
+
s.summary = 'A Ruby library for building and parsing DNS zone files.'
|
9
|
+
s.license = 'MIT'
|
10
|
+
s.homepage = 'https://github.com/hetznerZA/dns-zone2'
|
11
|
+
s.authors = ['Hetzner']
|
12
|
+
s.email = ['seals@hetzner.co.za ']
|
13
|
+
|
14
|
+
# gem settings for what files to include.
|
15
|
+
s.files = %w(Rakefile README.md HISTORY.md Gemfile dns-zone2.gemspec)
|
16
|
+
s.files += Dir.glob('{test/**/*,lib/**/*}')
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
#s.executables = ['dns-zone']
|
19
|
+
#s.default_executable = 'dns-zone'
|
20
|
+
|
21
|
+
# min ruby version
|
22
|
+
s.required_ruby_version = ::Gem::Requirement.new(">= 2.0")
|
23
|
+
|
24
|
+
# cross platform gem dependencies
|
25
|
+
#s.add_dependency('gli')
|
26
|
+
#s.add_dependency('paint')
|
27
|
+
s.add_development_dependency('bundler', '~> 1.0')
|
28
|
+
s.add_development_dependency('rake', '>= 9.0')
|
29
|
+
s.add_development_dependency('minitest', '~> 5.0')
|
30
|
+
s.add_development_dependency('simplecov', '~> 0.7.1')
|
31
|
+
s.add_development_dependency('yard', '~> 0.8')
|
32
|
+
s.add_development_dependency('inch', '~> 0.6')
|
33
|
+
s.add_development_dependency('guard-minitest', '~> 2.0')
|
34
|
+
s.add_development_dependency('guard-bundler', '~> 2.0')
|
35
|
+
|
36
|
+
# long description.
|
37
|
+
s.description = <<-EOL
|
38
|
+
A Ruby library for building and parsing DNS zone files for use with
|
39
|
+
Bind and PowerDNS (with Bind backend) DNS servers.
|
40
|
+
EOL
|
41
|
+
end
|
data/lib/dns/zone.rb
ADDED
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'dns/zone/rr'
|
2
|
+
require 'dns/zone/version'
|
3
|
+
|
4
|
+
# :nodoc:
|
5
|
+
module DNS
|
6
|
+
|
7
|
+
# Represents a 'whole' zone of many resource records (RRs).
|
8
|
+
#
|
9
|
+
# This is also the primary namespace for the `dns-zone` gem.
|
10
|
+
class Zone
|
11
|
+
|
12
|
+
# The default $TTL (directive) of the zone.
|
13
|
+
attr_accessor :ttl
|
14
|
+
# The primary $ORIGIN (directive) of the zone.
|
15
|
+
attr_accessor :origin
|
16
|
+
# Array of all the zones RRs (including the SOA).
|
17
|
+
attr_accessor :records
|
18
|
+
|
19
|
+
# Create an empty instance of a DNS zone that you can drive programmatically.
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
def initialize
|
23
|
+
@records = []
|
24
|
+
soa = DNS::Zone::RR::SOA.new
|
25
|
+
# set a couple of defaults on the SOA
|
26
|
+
soa.serial = Time.now.utc.strftime("%Y%m%d01")
|
27
|
+
soa.refresh_ttl = '3h'
|
28
|
+
soa.retry_ttl = '15m'
|
29
|
+
soa.expiry_ttl = '4w'
|
30
|
+
soa.minimum_ttl = '30m'
|
31
|
+
end
|
32
|
+
|
33
|
+
# Helper method to access the zones SOA RR.
|
34
|
+
#
|
35
|
+
# @api public
|
36
|
+
def soa
|
37
|
+
# return the first SOA we find in the records array.
|
38
|
+
rr = @records.find { |rr| rr.type == "SOA" }
|
39
|
+
return rr if rr
|
40
|
+
# otherwise create a new SOA
|
41
|
+
rr = DNS::Zone::RR::SOA.new
|
42
|
+
rr.serial = Time.now.utc.strftime("%Y%m%d01")
|
43
|
+
rr.refresh_ttl = '3h'
|
44
|
+
rr.retry_ttl = '15m'
|
45
|
+
rr.expiry_ttl = '4w'
|
46
|
+
rr.minimum_ttl = '30m'
|
47
|
+
# store and return new SOA
|
48
|
+
@records << rr
|
49
|
+
return rr
|
50
|
+
end
|
51
|
+
|
52
|
+
# Generates output of the zone and its records.
|
53
|
+
#
|
54
|
+
# @api public
|
55
|
+
def dump
|
56
|
+
content = []
|
57
|
+
|
58
|
+
@records.each do |rr|
|
59
|
+
content << rr.dump
|
60
|
+
end
|
61
|
+
|
62
|
+
content.join("\n") << "\n"
|
63
|
+
end
|
64
|
+
|
65
|
+
# Generates pretty output of the zone and its records.
|
66
|
+
#
|
67
|
+
# @api public
|
68
|
+
def dump_pretty
|
69
|
+
content = []
|
70
|
+
|
71
|
+
last_type = "SOA"
|
72
|
+
sorted_records.each do |rr|
|
73
|
+
content << '' if last_type != rr.type
|
74
|
+
content << rr.dump
|
75
|
+
last_type = rr.type
|
76
|
+
end
|
77
|
+
|
78
|
+
content.join("\n") << "\n"
|
79
|
+
end
|
80
|
+
|
81
|
+
# Load the provided zone file data into a new DNS::Zone object.
|
82
|
+
#
|
83
|
+
# @api public
|
84
|
+
def self.load(string, default_origin = "")
|
85
|
+
# get entries
|
86
|
+
entries = self.extract_entries(string)
|
87
|
+
|
88
|
+
instance = self.new
|
89
|
+
|
90
|
+
options = {}
|
91
|
+
entries.each do |entry|
|
92
|
+
# read in special statments like $TTL and $ORIGIN
|
93
|
+
if entry =~ /\$(ORIGIN|TTL)\s+(.+)/
|
94
|
+
instance.ttl = $2 if $1 == 'TTL'
|
95
|
+
if $1 == 'ORIGIN'
|
96
|
+
instance.origin ||= $2
|
97
|
+
options[:origin] ||= $2
|
98
|
+
options[:last_origin] = $2
|
99
|
+
end
|
100
|
+
next
|
101
|
+
end
|
102
|
+
|
103
|
+
# parse each RR and create a Ruby object for it
|
104
|
+
if entry =~ DNS::Zone::RR::REGEX_RR
|
105
|
+
rec = DNS::Zone::RR.load(entry, options)
|
106
|
+
next unless rec
|
107
|
+
instance.records << rec
|
108
|
+
options[:last_label] = rec.label
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# use default_origin if we didn't see a ORIGIN directive in the zone
|
113
|
+
if instance.origin.to_s.empty? && !default_origin.empty?
|
114
|
+
instance.origin = default_origin
|
115
|
+
end
|
116
|
+
|
117
|
+
return instance
|
118
|
+
end
|
119
|
+
|
120
|
+
# Extract entries from a zone file that will be later parsed as RRs.
|
121
|
+
#
|
122
|
+
# @api private
|
123
|
+
def self.extract_entries(string)
|
124
|
+
# FROM RFC:
|
125
|
+
# The format of these files is a sequence of entries. Entries are
|
126
|
+
# predominantly line-oriented, though parentheses can be used to continue
|
127
|
+
# a list of items across a line boundary, and text literals can contain
|
128
|
+
# CRLF within the text. Any combination of tabs and spaces act as a
|
129
|
+
# delimiter between the separate items that make up an entry. The end of
|
130
|
+
# any line in the master file can end with a comment. The comment starts
|
131
|
+
# with a ";" (semicolon).
|
132
|
+
|
133
|
+
entries = []
|
134
|
+
mode = :line
|
135
|
+
entry = ''
|
136
|
+
|
137
|
+
parentheses_ref_count = 0
|
138
|
+
|
139
|
+
string.lines.each do |line|
|
140
|
+
# strip comments unless escaped
|
141
|
+
# strip comments, unless its escaped.
|
142
|
+
# skip semicolons within "quote segments" (TXT records)
|
143
|
+
line = line.gsub(/((?<!\\);)(?=(?:[^"]|"[^"]*")*$).*/o, "").chomp
|
144
|
+
|
145
|
+
next if line.gsub(/\s+/, '').empty?
|
146
|
+
|
147
|
+
# append to entry line
|
148
|
+
entry << line
|
149
|
+
|
150
|
+
quotes = entry.count('"')
|
151
|
+
has_quotes = quotes > 0
|
152
|
+
|
153
|
+
parentheses = entry.count('()')
|
154
|
+
has_parentheses = parentheses > 0
|
155
|
+
|
156
|
+
if has_quotes
|
157
|
+
character_strings = entry.scan(/("(?:[^"\\]+|\\.)*")/).join(' ')
|
158
|
+
without = entry.gsub(/"((?:[^"\\]+|\\.)*)"/, '')
|
159
|
+
parentheses_ref_count = without.count('(') - without.count(')')
|
160
|
+
else
|
161
|
+
parentheses_ref_count = entry.count('(') - entry.count(')')
|
162
|
+
end
|
163
|
+
|
164
|
+
# are parentheses balanced?
|
165
|
+
if parentheses_ref_count == 0
|
166
|
+
if has_quotes
|
167
|
+
without.gsub!(/[()]/, '')
|
168
|
+
without.gsub!(/[ ]{2,}/, ' ')
|
169
|
+
#entries << (without + character_strings)
|
170
|
+
entry = (without + character_strings)
|
171
|
+
else
|
172
|
+
entry.gsub!(/[()]/, '')
|
173
|
+
entry.gsub!(/[ ]{2,}/, ' ')
|
174
|
+
entry.gsub!(/[ ]+$/, '')
|
175
|
+
#entries << entry
|
176
|
+
end
|
177
|
+
entries << entry
|
178
|
+
entry = ''
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
return entries
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
# Records sorted with more important types being at the top.
|
189
|
+
#
|
190
|
+
# @api private
|
191
|
+
def sorted_records
|
192
|
+
# pull out RRs we want to stick near the top
|
193
|
+
top_rrs = {}
|
194
|
+
top = %w{SOA NS MX SPF TXT}
|
195
|
+
top.each { |t| top_rrs[t] = @records.select { |rr| rr.type == t } }
|
196
|
+
|
197
|
+
remaining = @records.reject { |rr| top.include?(rr.type) }
|
198
|
+
|
199
|
+
# sort remaining RRs by type, alphabeticly
|
200
|
+
remaining.sort! { |a,b| a.type <=> b.type }
|
201
|
+
|
202
|
+
top_rrs.values.flatten + remaining
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|