zonefile 1.00 → 1.01

Sign up to get free protection for your applications and to get access to all the features.
@@ -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