File Coverage

blib/lib/DNS/Zone/File/Default.pm
Criterion Covered Total %
statement 116 133 87.2
branch 34 52 65.3
condition 6 12 50.0
subroutine 12 13 92.3
pod 0 4 0.0
total 168 214 78.5


line stmt bran cond sub pod time code
1             #!/usr/local/bin/perl -w
2             ######################################################################
3             #
4             # DNS/Zone/File/Default.pm
5             #
6             # $Id: Default.pm,v 1.4 2003/02/04 15:38:01 awolf Exp $
7             # $Revision: 1.4 $
8             # $Author: awolf $
9             # $Date: 2003/02/04 15:38:01 $
10             #
11             # Copyright (C)2001-2003 Andy Wolf. All rights reserved.
12             #
13             # This library is free software; you can redistribute it and/or
14             # modify it under the same terms as Perl itself.
15             #
16             ######################################################################
17              
18             package DNS::Zone::File::Default;
19              
20 2     2   724 no warnings 'portable';
  2         4  
  2         89  
21 2     2   27 use 5.6.0;
  2         1112  
  2         94  
22 2     2   12 use strict;
  2         4  
  2         62  
23 2     2   24 use warnings;
  2         3  
  2         172  
24              
25 2     2   17 use vars qw(@ISA);
  2         4  
  2         109  
26              
27 2     2   11 use DNS::Zone;
  2         5  
  2         57  
28 2     2   10 use DNS::Zone::Label;
  2         3  
  2         59  
29 2     2   10 use DNS::Zone::Record;
  2         5  
  2         44  
30 2     2   9 use DNS::Zone::File;
  2         4  
  2         9448  
31              
32             @ISA = qw(DNS::Zone::File);
33              
34             my $VERSION = '0.85';
35             my $REVISION = sprintf("%d.%02d", q$Revision: 1.4 $ =~ /(\d+)\.(\d+)/);
36              
37             my @known_classes = ( 'IN' );
38              
39             sub new {
40 1     1 0 4 my($pkg, $zone, $file) = @_;
41 1   33     11 my $class = ref($pkg) || $pkg;
42              
43 1 50       7 return undef unless($zone);
44              
45 1 50       13 my $self = {
46             'ZONE' => (ref($zone)) ? $zone : new DNS::Zone($zone)
47             };
48            
49 1 50       5 $self->{'FILE'} = $file if($file);
50            
51 1         4 bless $self, $class;
52            
53 1         4 return $self;
54             }
55              
56             sub zone {
57 1     1 0 9 my($self) = @_;
58            
59 1         5 return($self->{'ZONE'});
60             }
61              
62             sub parse {
63 1     1 0 16 my($self, $file) = @_;
64              
65 1 50       8 return undef unless($self->{'ZONE'});
66              
67 1         12 my @lines = $self->read($file);
68              
69             # substitute include statements completely
70             # $INCLUDE [] []
71 1         9 for(my $i=0 ; defined $lines[$i] ; $i++) {
72 28 50       107 if($lines[$i] =~ /^\s*\$INCLUDE\s+(.+)\s*(.*)\s*.*$/i) {
73 0         0 my @included = $self->read($1);
74 0 0       0 my $origin = "\$ORIGIN " . ($2) ? $self->zone()->name() : $2; ###FIXME
75 0         0 splice @lines, $i, 1, ($origin, @included, $origin);
76             }
77             }
78              
79 1 50       5 return undef unless(scalar @lines);
80            
81 1         3 my $zone = $self->{'ZONE'};
82 1         4 my $origin = $zone->{'NAME'} . '.';
83            
84 1         2 my $fullline;
85             my @result;
86              
87 1         3 for(@lines) {
88 28 100       92 if(!m/^[\s\;]*$/) {
89 23         103 s/\s+/ /g;
90 23         52 s/\s+$//;
91            
92 23 100 100     93 if(m/\(/ || $fullline) {
93 7         23 s/\s*\;.*$//g;
94 7         11 $fullline .= $_;
95              
96 7         11 $_ = $fullline;
97              
98 7         10 my $open = tr/\(/\(/;
99 7         9 my $close = tr/\)/\)/;
100 7         11 my $count = ($open - $close);
101              
102 7 100       19 if (!$count) {
103 1         2 push @result, ($fullline);
104 1         2 $fullline = '';
105             }
106             }
107             else {
108 16         32 push @result, ($_);
109             }
110             }
111             }
112              
113 1         7 @lines = @result;
114              
115 1         2 my $label = $origin;
116              
117 1         2 foreach my $line(@lines) {
118 17 100       58 if($line =~ /^\$ORIGIN\s+(.+)\s*\;*\s*$/) {
    100          
119 1         6 my $new = $1;
120 1         2 my $old = $origin;
121            
122 1 50       5 if($new =~ /\.$/) {
123 0         0 $origin = $new;
124             }
125             else {
126 1         4 $origin = $new . '.' . $old;
127             }
128             }
129             elsif($line !~ s/^\@/$origin/) {
130 15         57 $line =~ s/^\s+/$label /;
131            
132 15 100       131 if($line =~ s/^([-\*\w]+(\.[-\*\w]+)*)\s+/$1\.$origin /) {
133 3         1164 $label = "$1\.$origin";
134             }
135             }
136 1         3 else { $label = $origin; }
137             }
138              
139 1         3 $label = "\;";
140 1         6 for (my $i = -1 ; defined $lines[$i] ; $i--) {
141 17         29 $lines[$i] =~ s/^\;/$label \; \; /;
142 17         21 $label = $lines[$i];
143 17         61 $label =~ s/\s+.*//g;
144             }
145              
146 1         3 my $ttl_default = 0;
147            
148 1         4 for (@lines) {
149 17         67 my @parts = split " ", $_;
150              
151 17 50       40 next unless defined $parts[0];
152            
153 17 100       50 if($parts[0] eq '$TTL') {
    100          
154 1         4 $ttl_default = $parts[1];
155             }
156             elsif($parts[0] ne '$ORIGIN') {
157 15         28 my $label = lc shift @parts;
158 15         184 $label =~ s/\.$origin$//;
159 15 100       80 $label = '@' if($label eq $origin);
160              
161 15         14 my $ttl;
162 15 50       41 if($parts[0] =~ /^\d+$/) {
163 0         0 $ttl = shift @parts;
164             }
165             else {
166 15         22 $ttl = $ttl_default;
167             }
168            
169 15         16 my $class = 'IN';
170 15         26 my $type = uc shift @parts;
171 15         28 foreach (@known_classes) {
172 15 100       42 if(uc $_ eq $type) {
173 13         14 $class = $type;
174 13         19 $type = uc shift @parts;
175 13         20 last;
176             }
177             }
178 15         26 my $classtype = $class . " " . $type;
179              
180 15         66 my ($data, @comments) = split /\s*\;\s*/, join ' ', @parts;
181              
182 15   66     78 my $label_ref = $zone->label({'NAME'=>$label}) || $zone->add(DNS::Zone::Label->new($label));
183 15         74 my $record_ref = DNS::Zone::Record->new($ttl, $classtype, $data);
184 15         43 $label_ref->add($record_ref);
185              
186 15         53 for (@comments) {
187 2         7 my $record_ref = DNS::Zone::Record->new(0, '', $_);
188 2         7 $label_ref->add($record_ref);
189             }
190             }
191             }
192              
193 1 50       4 warn "\$TTL not set using SOA minimum instead !" if(!$ttl_default);
194              
195 1         2 my $minimum;
196 1         5 my @labels = $zone->labels();
197            
198 1         4 for (@labels) {
199 4         17 my @records = $_->records();
200            
201 4         9 for (@records) {
202 17 100       91 $minimum = $_->minimum() if($_->type() eq 'IN SOA');
203             }
204             }
205            
206 1         4 for (@labels) {
207 4         14 my @records = $_->records();
208            
209 4         8 for (@records) {
210 17 100       91 $_->ttl($minimum) if($_->ttl() == 0);
211             }
212             }
213              
214 1         23 return $self;
215             }
216              
217             sub dump {
218 0     0 0   my($self, $file) = @_;
219              
220 0   0       $file = $file || $self->{'FILE'};
221              
222 0 0         return undef unless($self->{'ZONE'});
223              
224 0 0         if($file) {
225 0 0         if (open(FILE, ">$file")) {
226 0           my $old_fh = select(FILE);
227            
228 0           $self->{'ZONE'}->dump();
229              
230 0           select($old_fh);
231 0           close FILE;
232             }
233 0           else { return undef; }
234             }
235             else {
236 0           $self->{'ZONE'}->dump();
237             }
238              
239 0           return $self;
240             }
241              
242             1;
243              
244             __END__