zonefile 1.00 → 1.01

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.
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # == Description
5
5
  # This class can read, manipulate and create DNS zone files. It supports A, AAAA, MX, NS, SOA,
6
- # TXT, CNAME and SRV records. The data can be accessed by the instance method of the same
6
+ # TXT, CNAME, PTR and SRV records. The data can be accessed by the instance method of the same
7
7
  # name. All except SOA return an array of hashes containing the named data. SOA directly returns the
8
8
  # hash since there can only be one SOA information.
9
9
  #
@@ -23,6 +23,8 @@
23
23
  # - :name, :ttl, :class, :text
24
24
  # * A4 (AAAA)
25
25
  # - :name, :ttl, :class, :host
26
+ # * PTR
27
+ # - :name, :ttl, :class, :host
26
28
  # * SRV
27
29
  # - :name, :ttl, :class, :pri, :weight, :port, :host
28
30
  #
@@ -69,10 +71,14 @@
69
71
  class Zonefile
70
72
 
71
73
  RECORDS = %w{ mx a a4 ns cname txt ptr srv soa }
72
- attr :records
74
+ attr :records
73
75
  attr :soa
74
76
  attr :data
75
-
77
+ # global $ORIGIN option
78
+ attr :origin
79
+ # global $TTL option
80
+ attr :ttl
81
+
76
82
  def method_missing(m)
77
83
  return super unless RECORDS.include?(m.to_s)
78
84
  @records[m]
@@ -97,7 +103,7 @@ class Zonefile
97
103
  def initialize(zonefile = '', file_name= nil, origin= nil)
98
104
  @data = zonefile
99
105
  @filename = file_name
100
- @origin = origin
106
+ @origin = origin || (file_name ? file_name.split('/').last : '')
101
107
 
102
108
  @records = {}
103
109
  @soa = {}
@@ -105,6 +111,14 @@ class Zonefile
105
111
  parse
106
112
  end
107
113
 
114
+ # True if no records (except sao) is defined in this file
115
+ def empty?
116
+ RECORDS.each do |r|
117
+ return false unless @records[r.intern].empty?
118
+ end
119
+ true
120
+ end
121
+
108
122
  # Create a new object by reading the content of a file
109
123
  def self.from_file(file_name, origin = nil)
110
124
  Zonefile.new(File.read(file_name), file_name.split('/').last, origin)
@@ -118,17 +132,17 @@ class Zonefile
118
132
  def new_serial
119
133
  base = "%04d%02d%02d" % [Time.now.year, Time.now.month, Time.now.day ]
120
134
 
121
- if ((self.soa[:serial].to_i / 100) > base.to_i) then
122
- ns = self.soa[:serial].to_i + 1
123
- self.soa[:serial] = ns.to_s
135
+ if ((@soa[:serial].to_i / 100) > base.to_i) then
136
+ ns = @soa[:serial].to_i + 1
137
+ @soa[:serial] = ns.to_s
124
138
  return ns.to_s
125
139
  end
126
140
 
127
141
  ii = 0
128
- while (("#{base}%02d" % ii).to_i <= self.soa[:serial].to_i) do
142
+ while (("#{base}%02d" % ii).to_i <= @soa[:serial].to_i) do
129
143
  ii += 1
130
144
  end
131
- self.soa[:serial] = "#{base}%02d" % ii
145
+ @soa[:serial] = "#{base}%02d" % ii
132
146
  end
133
147
 
134
148
  def parse_line(line)
@@ -140,7 +154,9 @@ class Zonefile
140
154
  ttl_cls = Regexp.new("(?:(#{rr_ttl})\s)?(?:(#{rr_class})\s)?")
141
155
 
142
156
  data = {}
143
- if line =~ /^(#{valid_name})? \s*
157
+ if line =~ /^\$ORIGIN\s*(#{valid_name})/ix then
158
+ @origin = $1
159
+ elsif line =~ /^(#{valid_name})? \s*
144
160
  #{ttl_cls}
145
161
  (#{rr_type}) \s
146
162
  (#{valid_name})
@@ -203,7 +219,7 @@ class Zonefile
203
219
  elsif line =~ /(#{valid_name})? \s #{ttl_cls} TXT \s \"([^\"]*)\"/ix
204
220
  add_record('txt', :name => $1, :ttl => $2, :class => $3, :text => $4)
205
221
  elsif line =~ /\$TTL\s+(#{rr_ttl})/i
206
- @soa[:ttl] = $1
222
+ @ttl = $1
207
223
  end
208
224
  end
209
225
 
@@ -222,7 +238,8 @@ class Zonefile
222
238
  ; Database file #{@filename || 'unknown'} for #{@origin || 'unknown'} zone.
223
239
  ; Zone version: #{self.soa[:serial]}
224
240
  ;
225
- #{self.soa[:ttl] ? "$TTL #{self.soa[:ttl]}" : ''}
241
+ #{@origin ? "$ORIGIN #{@origin}" : ''}
242
+ #{@ttl ? "$TTL #{@ttl}" : ''}
226
243
  #{self.soa[:origin]} #{self.soa[:ttl]} IN SOA #{self.soa[:primary]} #{self.soa[:email]} (
227
244
  #{self.soa[:serial]} ; serial number
228
245
  #{self.soa[:refresh]} ; refresh
@@ -255,6 +272,9 @@ ENDH
255
272
  self.srv.each do |srv|
256
273
  out << "#{srv[:name]} #{srv[:ttl]} #{srv[:class]} SRV #{srv[:pri]} #{srv[:weight]} #{srv[:port]} #{srv[:host]}\n"
257
274
  end
275
+ self.ptr.each do |ptr|
276
+ out << "#{ptr[:name]} #{ptr[:ttl]} #{ptr[:class]} PTR #{ptr[:host]}\n"
277
+ end
258
278
 
259
279
  out
260
280
  end
@@ -1,6 +1,7 @@
1
1
  ; Database file dns-zoneparse-test.net.dns for dns-zoneparse-test.net zone.
2
2
  ; Zone version: 2000100501
3
3
  $TTL 1H
4
+ $ORIGIN test-zone.db
4
5
  @ 3600 IN SOA ns0.dns-zoneparse-test.net. support.dns-zoneparse-test.net. (
5
6
  2000100501 ; serial number
6
7
  10800 ; refresh
@@ -29,4 +30,5 @@ icarus IN AAAA fe80::0260:83ff:fe7c:3a2a
29
30
  soup IN TXT "This is a text message"
30
31
  txta TXT "This is another text message"
31
32
  _sip._tcp.example.com. 86400 IN SRV 0 5 5060 sipserver.example.com.
33
+ 12.23.21.23.in-addr.arpa IN PTR www.myhost.example.com.
32
34
 
@@ -17,6 +17,13 @@ class TC_Zonefile < Test::Unit::TestCase
17
17
  @zf = Zonefile.new(@zf.output, 'test-origin')
18
18
  end
19
19
 
20
+ def test_empty
21
+ zf = Zonefile.new
22
+ zf.soa[:refresh] = 1234
23
+ assert zf.empty?
24
+ end
25
+
26
+
20
27
  def test_soa
21
28
  assert_equal '86400', @zf.soa[:minimumTTL]
22
29
  assert_equal '691200', @zf.soa[:expire]
@@ -128,14 +135,29 @@ class TC_Zonefile < Test::Unit::TestCase
128
135
  @zf.soa[:serial] = '9999889901'
129
136
  @zf.new_serial
130
137
  assert_equal '9999889902', @zf.soa[:serial]
138
+ end
131
139
 
140
+ def test_ptr
141
+ assert_equal '12.23.21.23.in-addr.arpa', @zf.ptr[0][:name]
142
+ assert_equal 'www.myhost.example.com.', @zf.ptr[0][:host]
143
+ begin
144
+ @swap_ptr = true
145
+ swap
146
+ test_ptr
147
+ end unless @swap_ptr
148
+ end
149
+
150
+ def test_origin
151
+ assert_equal 'test-zone.db', @zf.origin
152
+ swap
153
+ assert_equal 'test-zone.db', @zf.origin
132
154
  end
133
155
 
134
156
 
135
157
  def test_output
136
- # puts @zf.data
137
- # puts '==================='
138
- # puts @zf.output
158
+ puts @zf.data
159
+ puts '==================='
160
+ puts @zf.output
139
161
  end
140
162
 
141
163
  end
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zonefile
3
3
  version: !ruby/object:Gem::Version
4
- version: "1.00"
4
+ hash: 13
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 1
9
+ version: "1.01"
5
10
  platform: ruby
6
11
  authors:
7
12
  - Martin Boese
@@ -9,7 +14,7 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2009-09-04 00:00:00 +01:00
17
+ date: 2011-01-24 00:00:00 +01:00
13
18
  default_executable:
14
19
  dependencies: []
15
20
 
@@ -22,36 +27,43 @@ extensions: []
22
27
  extra_rdoc_files: []
23
28
 
24
29
  files:
25
- - lib/zonefile
26
30
  - lib/zonefile/zonefile.rb
27
31
  - lib/zonefile.rb
28
32
  - tests/test-zone.db
29
33
  - tests/zonefile.rb
30
34
  has_rdoc: true
31
35
  homepage: http://zonefile.rubyforge.org/
36
+ licenses: []
37
+
32
38
  post_install_message:
33
39
  rdoc_options: []
34
40
 
35
41
  require_paths:
36
42
  - lib
37
43
  required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
38
45
  requirements:
39
46
  - - ">="
40
47
  - !ruby/object:Gem::Version
48
+ hash: 3
49
+ segments:
50
+ - 0
41
51
  version: "0"
42
- version:
43
52
  required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
44
54
  requirements:
45
55
  - - ">="
46
56
  - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
47
60
  version: "0"
48
- version:
49
61
  requirements: []
50
62
 
51
63
  rubyforge_project: zonefile
52
- rubygems_version: 1.2.0
64
+ rubygems_version: 1.3.7
53
65
  signing_key:
54
- specification_version: 2
66
+ specification_version: 3
55
67
  summary: BIND 8/9 Zonefile Reader and Writer
56
68
  test_files: []
57
69