Passage à Net::DNS
parent
0dc7cdea82
commit
e6da9f192e
|
@ -84,17 +84,17 @@ get '/' => sub {
|
|||
|
||||
prefix '/domain' => sub {
|
||||
|
||||
any ['post', 'get'] => '/updateraw/:domain' => sub {
|
||||
post '/updateraw/:domain' => sub {
|
||||
what_is_next rt_dom_updateraw
|
||||
get_session( qw/login passwd/ )
|
||||
, get_param( qw/domain zoneupdated/)
|
||||
, get_request( qw/address referer/ );
|
||||
};
|
||||
|
||||
any ['post', 'get'] => '/update/:domain' => sub {
|
||||
post '/update/:domain' => sub {
|
||||
what_is_next rt_dom_update
|
||||
get_session( qw/login passwd/ )
|
||||
, get_param( qw/type name value ttl priority domain/ );
|
||||
, get_param( qw/domain name type priority rdata ttl/ );
|
||||
};
|
||||
|
||||
get '/details/:domain' => sub {
|
||||
|
@ -117,25 +117,26 @@ prefix '/domain' => sub {
|
|||
, get_request( qw/address referer/ );
|
||||
};
|
||||
|
||||
get '/del/:domain/:name/:type/:host/:ttl' => sub {
|
||||
get '/del/:domain/:name/:ttl/:type/:rdata' => sub {
|
||||
what_is_next rt_dom_del_entry
|
||||
get_session( qw/login passwd/ )
|
||||
, get_param( qw/domain name type host ttl/ )
|
||||
, get_param( qw/domain name type ttl rdata/ )
|
||||
, get_request( qw/address referer/ );
|
||||
};
|
||||
|
||||
get '/mod/:domain/:name/:type/:host/:ttl' => sub {
|
||||
post '/mod/:domain' => sub {
|
||||
what_is_next rt_dom_mod_entry
|
||||
get_session( qw/login passwd/ )
|
||||
, get_param( qw/type name ttl domain name type host ttl
|
||||
newpriority newtype newhost newname newttl / )
|
||||
, get_param( qw/domain
|
||||
oldpriority oldtype oldname oldttl oldrdata
|
||||
newpriority newtype newname newttl newrdata/ )
|
||||
, get_request( qw/address referer/ );
|
||||
};
|
||||
|
||||
get '/cli/:login/:pass/:domain/:name/:type/:host/:ttl/:ip' => sub {
|
||||
get '/cli/:login/:pass/:domain/:name/:type/:rdata/:ttl/:ip' => sub {
|
||||
what_is_next rt_dom_cli_mod_entry
|
||||
get_session( qw/login/ )
|
||||
, get_param( qw/passwd domain name type host ttl ip/ );
|
||||
, get_param( qw/passwd domain name type rdata ttl ip/ );
|
||||
};
|
||||
};
|
||||
|
||||
|
|
34
lib/app.pm
34
lib/app.pm
|
@ -70,7 +70,7 @@ sub is_owning_domain {
|
|||
|
||||
# DOMAIN
|
||||
|
||||
sub _get_zone {
|
||||
sub get_zone {
|
||||
my ($self, $domain) = @_;
|
||||
|
||||
# say "";
|
||||
|
@ -93,41 +93,13 @@ sub _get_zone {
|
|||
sub add_domain {
|
||||
my ($self, $login, $domain) = @_;
|
||||
$self->db->add_domain($login, $domain);
|
||||
$self->_get_zone($domain)->addzone()
|
||||
$self->get_zone($domain)->addzone()
|
||||
}
|
||||
|
||||
sub delete_domain {
|
||||
my ($self, $domain) = @_;
|
||||
$self->db->delete_domain($domain);
|
||||
$self->_get_zone($domain)->del()
|
||||
}
|
||||
|
||||
sub modify_entry {
|
||||
my ($self, $domain, $entryToModify, $newEntry) = @_;
|
||||
my $zone = $self->_get_zone($domain)->modify_entry(
|
||||
$entryToModify, $newEntry );
|
||||
$self->update_domain($zone, $domain)
|
||||
}
|
||||
|
||||
sub delete_entry {
|
||||
my ($self, $domain, $entryToDelete) = @_;
|
||||
my $zone = $self->_get_zone($domain)->delete_entry( $entryToDelete );
|
||||
$self->update_domain($zone, $domain)
|
||||
}
|
||||
|
||||
sub update_domain_raw {
|
||||
my ($self, $zone, $domain) = @_;
|
||||
$self->_get_zone($domain)->update_raw($zone)
|
||||
}
|
||||
|
||||
sub update_domain {
|
||||
my ($self, $zone, $domain) = @_;
|
||||
$self->_get_zone($domain)->update($zone)
|
||||
}
|
||||
|
||||
sub get_domain {
|
||||
my ($self, $domain) = @_;
|
||||
$self->_get_zone($domain)->get()
|
||||
$self->get_zone($domain)->del()
|
||||
}
|
||||
|
||||
sub get_domains {
|
||||
|
|
149
lib/rt/domain.pm
149
lib/rt/domain.pm
|
@ -52,20 +52,13 @@ sub rt_dom_cli_mod_entry {
|
|||
return $res;
|
||||
}
|
||||
|
||||
$app->modify_entry( $$param{domain}
|
||||
, {
|
||||
type => $$param{type}
|
||||
, name => $$param{name}
|
||||
, host => $$param{host}
|
||||
, ttl => $$param{ttl}
|
||||
}
|
||||
, {
|
||||
newtype => $$param{type}
|
||||
, newname => $$param{name}
|
||||
, newhost => $$param{ip}
|
||||
, newttl => $$param{ttl}
|
||||
, newpriority => ''
|
||||
});
|
||||
my $zone = $app->get_zone( $$param{domain} );
|
||||
my $zf = $zone->get_zonefile();
|
||||
$zf->rr_mod(
|
||||
"$$param{name} $$param{ttl} $$param{type} $$param{rdata}"
|
||||
, "$$param{name} $$param{ttl} $$param{type} $$param{ip}"
|
||||
);
|
||||
$zone->update( $zf );
|
||||
|
||||
$app->disconnect();
|
||||
};
|
||||
|
@ -88,12 +81,13 @@ sub rt_dom_mod_entry {
|
|||
|
||||
my @missingitems;
|
||||
|
||||
for(qw/type name ttl domain name type host ttl
|
||||
newtype newhost newname newttl/) {
|
||||
for(qw/domain
|
||||
oldtype oldname oldrdata oldttl
|
||||
newtype newname newrdata newttl/) {
|
||||
push @missingitems, $_ unless($$param{$_});
|
||||
}
|
||||
|
||||
if($$param{type} eq 'MX' && ! $$param{newpriority}) {
|
||||
if($$param{oldtype} eq 'MX' && ! $$param{newpriority}) {
|
||||
push @missingitems, "newpriority";
|
||||
}
|
||||
|
||||
|
@ -102,8 +96,9 @@ sub rt_dom_mod_entry {
|
|||
return $res;
|
||||
}
|
||||
|
||||
for(qw/type name ttl domain name type host ttl
|
||||
newpriority newtype newhost newname newttl/) {
|
||||
for(qw/domain
|
||||
oldtype oldname oldrdata oldttl
|
||||
newtype newname newrdata newttl/) {
|
||||
say "$_ : $$param{$_}" if $$param{$_};
|
||||
}
|
||||
|
||||
|
@ -124,20 +119,23 @@ sub rt_dom_mod_entry {
|
|||
return $res;
|
||||
}
|
||||
|
||||
$app->modify_entry( $$param{domain}
|
||||
, {
|
||||
type => $$param{type}
|
||||
, name => $$param{name}
|
||||
, host => $$param{host}
|
||||
, ttl => $$param{ttl}
|
||||
}
|
||||
, {
|
||||
newtype => $$param{newtype}
|
||||
, newname => $$param{newname}
|
||||
, newhost => $$param{newhost}
|
||||
, newttl => $$param{newttl}
|
||||
, newpriority => $$param{newpriority}
|
||||
});
|
||||
my $zone = $app->get_zone( $$param{domain} );
|
||||
my $zf = $zone->get_zonefile();
|
||||
my $str_old =
|
||||
"$$param{oldname} $$param{oldttl} $$param{oldtype} $$param{oldrdata}";
|
||||
my $str_new = "$$param{newname} $$param{newttl} $$param{newtype} ";
|
||||
if($$param{newtype} eq "MX") {
|
||||
$str_new .= "$$param{newpriority} $$param{newrdata}";
|
||||
}
|
||||
else {
|
||||
$str_new .= "$$param{newrdata}";
|
||||
}
|
||||
|
||||
say "old : $str_old";
|
||||
say "new : $str_new";
|
||||
$zf->rr_mod( $str_old, $str_new);
|
||||
$zone->update( $zf );
|
||||
|
||||
$app->disconnect();
|
||||
};
|
||||
|
||||
|
@ -168,12 +166,13 @@ sub rt_dom_del_entry {
|
|||
return $res;
|
||||
}
|
||||
|
||||
$app->delete_entry( $$param{domain}, {
|
||||
type => $$param{type},
|
||||
name => $$param{name},
|
||||
host => $$param{host},
|
||||
ttl => $$param{ttl}
|
||||
});
|
||||
my $zone = $app->get_zone( $$param{domain} );
|
||||
my $zf = $zone->get_zonefile();
|
||||
$zf->rr_del_raw(
|
||||
"$$param{name} $$param{ttl} $$param{type} $$param{rdata}"
|
||||
);
|
||||
$zone->update( $zf );
|
||||
|
||||
$app->disconnect();
|
||||
};
|
||||
|
||||
|
@ -324,7 +323,8 @@ sub rt_dom_details {
|
|||
return $res;
|
||||
}
|
||||
|
||||
my $zone = $app->get_domain($$param{domain});
|
||||
my $zone = $app->get_zone( $$param{domain} );
|
||||
my $zf = $zone->get_zonefile();
|
||||
|
||||
$app->disconnect();
|
||||
|
||||
|
@ -333,7 +333,7 @@ sub rt_dom_details {
|
|||
login => $$session{login}
|
||||
, admin => $$user{admin}
|
||||
, domain => $$param{domain}
|
||||
, domain_zone => $zone->output()
|
||||
, domain_zone => $zf->dump()
|
||||
, user_ip => $$request{address}
|
||||
};
|
||||
|
||||
|
@ -341,17 +341,7 @@ sub rt_dom_details {
|
|||
$$res{params}{expert} = 1;
|
||||
}
|
||||
else {
|
||||
$$res{params}{a} = $zone->a();
|
||||
$$res{params}{aaaa} = $zone->aaaa();
|
||||
$$res{params}{cname} = $zone->cname();
|
||||
$$res{params}{ptr} = $zone->ptr();
|
||||
$$res{params}{mx} = $zone->mx();
|
||||
$$res{params}{ns} = $zone->ns();
|
||||
|
||||
for(qw/a aaaa cname ptr mx ns/) {
|
||||
my $t = $_;
|
||||
map { $$_{type} = uc $t } @{$$res{params}{$t}};
|
||||
}
|
||||
$$res{params}{zone} = $zf->rr_array_to_array();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -378,7 +368,7 @@ sub rt_dom_update {
|
|||
|
||||
my @missingitems;
|
||||
|
||||
for(qw/type name value ttl domain/) {
|
||||
for(qw/name ttl type rdata domain/) {
|
||||
push @missingitems, $_ unless($$param{$_});
|
||||
}
|
||||
|
||||
|
@ -403,34 +393,29 @@ sub rt_dom_update {
|
|||
return $res;
|
||||
}
|
||||
|
||||
my $zone = $app->get_domain( $$param{domain} );
|
||||
my $zone = $app->get_zone( $$param{domain} );
|
||||
my $zf = $zone->get_zonefile();
|
||||
|
||||
# TODO better naming convention
|
||||
my $entries;
|
||||
for( $$param{type} ) {
|
||||
if($_ eq 'A') { $entries = $zone->a }
|
||||
elsif( $_ eq 'AAAA') { $entries = $zone->aaaa }
|
||||
elsif( $_ eq 'CNAME') { $entries = $zone->cname }
|
||||
elsif( $_ eq 'MX') { $entries = $zone->mx }
|
||||
elsif( $_ eq 'PTR') { $entries = $zone->ptr }
|
||||
elsif( $_ eq 'NS') { $entries = $zone->ns }
|
||||
elsif( $_ eq 'TXT') { $entries = $zone->txt } # TODO verify this
|
||||
my $name = $$param{name};
|
||||
$name .= ".$$param{domain}" unless $name =~ /$$param{domain}$/;
|
||||
my $str_new = "$name $$param{ttl} $$param{type} ";
|
||||
|
||||
my $rdata = $$param{rdata};
|
||||
|
||||
if($$param{type} =~ /^(CNAME|MX|NS|PTR)$/ && $rdata !~ /\.$/) {
|
||||
$rdata .= ".$$param{domain}";
|
||||
}
|
||||
|
||||
my $new_entry = {
|
||||
name => $$param{name}
|
||||
, class => "IN"
|
||||
, host => $$param{value}
|
||||
, ttl => $$param{ttl}
|
||||
, ORIGIN => $zone->origin
|
||||
};
|
||||
if($$param{type} eq "MX") {
|
||||
$str_new .= "$$param{priority} $$param{rdata}";
|
||||
}
|
||||
else {
|
||||
$str_new .= "$$param{rdata}";
|
||||
}
|
||||
$zf->rr_add_raw($str_new);
|
||||
$zf->new_serial();
|
||||
$zone->update( $zf );
|
||||
|
||||
$$new_entry{priority} = $$param{priority} if $$param{type} eq 'MX';
|
||||
push @$entries, $new_entry;
|
||||
|
||||
$zone->new_serial();
|
||||
|
||||
$app->update_domain( $zone , $$param{domain} );
|
||||
$app->disconnect();
|
||||
};
|
||||
|
||||
|
@ -478,13 +463,9 @@ sub rt_dom_updateraw {
|
|||
return $res;
|
||||
}
|
||||
else {
|
||||
my $success =
|
||||
$app->update_domain_raw($$param{zoneupdated}, $$param{domain});
|
||||
|
||||
unless($success) {
|
||||
$$res{deferred}{errmsg} = q{Problème de mise à jour du domaine.};
|
||||
}
|
||||
|
||||
my $zone = $app->get_zone( $$param{domain} );
|
||||
my $zf = $zone->update_raw( $$param{zoneupdated} );
|
||||
$zone->update( $zf );
|
||||
$$res{route} = '/domain/details/' . $$param{domain};
|
||||
}
|
||||
|
||||
|
|
101
lib/zone.pm
101
lib/zone.pm
|
@ -10,7 +10,7 @@ use getiface ':all';
|
|||
use copycat ':all';
|
||||
use fileutil ':all';
|
||||
use configuration ':all';
|
||||
use Data::Dump qw( dump );
|
||||
#use Data::Dump qw( dump );
|
||||
|
||||
use zonefile;
|
||||
|
||||
|
@ -86,103 +86,17 @@ sub get_remote_zf_ {
|
|||
"$$self{dnsi}{mycfg}{zonedir}/$$self{domain}"
|
||||
}
|
||||
|
||||
sub are_same_records_ {
|
||||
my ($a, $b) = @_;
|
||||
|
||||
#debug({ a => $a });
|
||||
#debug({ b => $b });
|
||||
|
||||
#$a->{priority} eq $b->{priority} &&
|
||||
( $$a{name} eq $$b{name} &&
|
||||
$$a{host} eq $$b{host} &&
|
||||
$$a{ttl} == $$b{ttl} )
|
||||
}
|
||||
|
||||
# returns the lists of domains of a certain type
|
||||
sub get_records_ {
|
||||
my ($zone, $entry) = @_;
|
||||
|
||||
for( lc $$entry{type} ) {
|
||||
if ($_ eq 'a') { return $zone->a }
|
||||
elsif ($_ eq 'aaaa') { return $zone->aaaa }
|
||||
elsif ($_ eq 'cname') { return $zone->cname }
|
||||
elsif ($_ eq 'ns') { return $zone->ns }
|
||||
elsif ($_ eq 'mx') { return $zone->mx }
|
||||
elsif ($_ eq 'ptr') { return $zone->ptr }
|
||||
}
|
||||
|
||||
die 'Impossible to get the entry type.'
|
||||
}
|
||||
|
||||
sub reload_secondary_dns_servers {
|
||||
my $self = shift;
|
||||
$_->reload_sec($$self{slavedzones}) for(@{$$self{dnsisec}})
|
||||
}
|
||||
|
||||
sub delete_entry {
|
||||
my ($self, $entryToDelete) = @_;
|
||||
|
||||
my $zone = $self->get();
|
||||
|
||||
my $records = get_records_ $zone, $entryToDelete;
|
||||
|
||||
if( defined $records ) {
|
||||
foreach my $i ( 0 .. scalar @{$records}-1 ) {
|
||||
if(are_same_records_($records->[$i], $entryToDelete)) {
|
||||
delete $records->[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$zone
|
||||
}
|
||||
|
||||
sub modify_entry {
|
||||
my ($self, $entryToModify, $newEntry) = @_;
|
||||
|
||||
my $zone = $self->get();
|
||||
|
||||
my $records = get_records_ $zone, $entryToModify;
|
||||
|
||||
if( defined $records ) {
|
||||
|
||||
foreach my $i ( 0 .. scalar @{$records}-1 ) {
|
||||
|
||||
if(are_same_records_($records->[$i], $entryToModify)) {
|
||||
|
||||
say "ENTRY TO MODIFY";
|
||||
|
||||
say $records->[$i]->{name} . ' = ' . $newEntry->{newname};
|
||||
say $records->[$i]->{host} . ' = ' . $newEntry->{newhost};
|
||||
say $records->[$i]->{ttl} . ' = ' . $newEntry->{newttl};
|
||||
#say $records->[$i]->{type} . ' = ' . $newEntry->{newtype};
|
||||
|
||||
$records->[$i]->{name} = $newEntry->{newname};
|
||||
$records->[$i]->{host} = $newEntry->{newhost};
|
||||
$records->[$i]->{ttl} = $newEntry->{newttl};
|
||||
#$records->[$i]->{type} = $newEntry->{newtype};
|
||||
|
||||
if( $$newEntry{newtype} eq 'MX' ) {
|
||||
say
|
||||
$records->[$i]->{priority}.' = '.$newEntry->{newpriority};
|
||||
$records->[$i]->{priority} = $newEntry->{newpriority};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dump($records);
|
||||
|
||||
$zone
|
||||
}
|
||||
|
||||
sub get {
|
||||
sub get_zonefile {
|
||||
my $self = shift;
|
||||
my $file = $self->get_remote_zf_();
|
||||
my $dest = $self->get_ztmp_file_();
|
||||
|
||||
copycat ($file, $dest);
|
||||
|
||||
zonefile->new(domain => $$self{domain}, zonefile => $dest);
|
||||
}
|
||||
|
||||
|
@ -212,7 +126,7 @@ sub addzone {
|
|||
$zonefile->new_serial(); # update the serial number
|
||||
|
||||
# write the new zone tmpfile to disk
|
||||
write_file $f->path, $zonefile->output();
|
||||
write_file $f->path, $zonefile->dump();
|
||||
|
||||
my $file = $self->get_remote_zf_();
|
||||
copycat ($tmpfile, $file); # put the final zone on the server
|
||||
|
@ -239,7 +153,7 @@ sub update {
|
|||
my $tmpfile = $self->get_ztmp_file_();
|
||||
|
||||
# write the new zone tmpfile to disk
|
||||
write_file $tmpfile, $zonefile->output();
|
||||
write_file $tmpfile, $zonefile->dump();
|
||||
|
||||
my $file = $self->get_remote_zf_();
|
||||
copycat ($tmpfile, $file); # put the final zone on the server
|
||||
|
@ -258,11 +172,10 @@ sub update_raw {
|
|||
my $zonefile;
|
||||
my $file = $self->get_ztmp_file_();
|
||||
|
||||
# write the updated zone file to disk
|
||||
# write the updated zone file to disk
|
||||
write_file $file, $zonetext;
|
||||
|
||||
eval { $zonefile = zonefile->new(zonefile => $file
|
||||
, domain => $$self{domain}); };
|
||||
eval { $zonefile = zonefile->new(zonefile => $file); };
|
||||
|
||||
if( $@ ) {
|
||||
unlink($file);
|
||||
|
@ -271,7 +184,7 @@ sub update_raw {
|
|||
|
||||
unlink($file);
|
||||
|
||||
$self->update($zonefile)
|
||||
$zonefile
|
||||
}
|
||||
|
||||
sub del {
|
||||
|
|
186
lib/zonefile.pm
186
lib/zonefile.pm
|
@ -1,52 +1,180 @@
|
|||
package zonefile;
|
||||
use v5.14;
|
||||
use Net::DNS::RR;
|
||||
use Net::DNS::ZoneFile;
|
||||
use Moo;
|
||||
use DNS::ZoneParse;
|
||||
use utf8;
|
||||
use URI;
|
||||
use Data::Dumper;
|
||||
|
||||
has zone => qw/is rw/ ;
|
||||
has [ qw/domain/ ] => qw/ is ro required 1/;
|
||||
has [ qw/zonefile/ ] => qw/ is rw required 1/;
|
||||
|
||||
# Simple functions to manipulate lists of Net::DNS::RR
|
||||
|
||||
sub rr_array_del {
|
||||
my ($zones, $rr) = @_;
|
||||
my @z = grep { $_->plain ne $rr->plain } @$zones;
|
||||
[ @z ]
|
||||
}
|
||||
|
||||
sub rr_array_add {
|
||||
my ($zone, $rr) = @_;
|
||||
my @already_present = grep { $_->plain eq $rr->plain } @$zone;
|
||||
push @$zone, $rr unless @already_present;
|
||||
$zone
|
||||
}
|
||||
|
||||
sub rr_array_new_serial {
|
||||
my $zones = shift;
|
||||
|
||||
for(@{$zones}) {
|
||||
if($_->type =~ /SOA/) {
|
||||
my $serial = $_->serial;
|
||||
$_->serial($serial + 1);
|
||||
}
|
||||
}
|
||||
|
||||
$zones
|
||||
}
|
||||
|
||||
sub rr_array_serial {
|
||||
my $zones = shift;
|
||||
|
||||
for(@{$zones}) {
|
||||
if($_->type =~ /SOA/) {
|
||||
return $_->serial;
|
||||
}
|
||||
}
|
||||
|
||||
die "Impossible to get the zone serial."
|
||||
}
|
||||
|
||||
sub rr_array_dump {
|
||||
my $zone = shift;
|
||||
my $dump = '';
|
||||
|
||||
# write the SOA record first
|
||||
for(@{$zone}) {
|
||||
if($_->type =~ /SOA/i) {
|
||||
$dump .= $_->string . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
for(@{$zone}) {
|
||||
if($_->type !~ /SOA/i) {
|
||||
$dump .= $_->string . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$dump
|
||||
}
|
||||
|
||||
|
||||
sub BUILD {
|
||||
my ($self) = @_;
|
||||
|
||||
my $filename = $$self{zonefile};
|
||||
if($filename =~ "://")
|
||||
{
|
||||
my $fileuri = URI->new($filename);
|
||||
$filename = $fileuri->path;
|
||||
}
|
||||
my $path = $$self{zonefile};
|
||||
|
||||
$$self{zone} = DNS::ZoneParse->new($filename, $$self{domain});
|
||||
# zonefile is the filename
|
||||
if($$self{zonefile} =~ "://") {
|
||||
my $fileuri = URI->new($$self{zonefile});
|
||||
$path = $fileuri->path;
|
||||
}
|
||||
|
||||
my $zonefile = Net::DNS::ZoneFile->new( $path );
|
||||
my @zone = $zonefile->read;
|
||||
$$self{zone} = [ @zone ];
|
||||
}
|
||||
|
||||
sub new_serial {
|
||||
my $self = shift;
|
||||
$self->zone->new_serial();
|
||||
}
|
||||
|
||||
sub origin {
|
||||
my $self = shift;
|
||||
$self->zone->origin();
|
||||
}
|
||||
|
||||
sub output {
|
||||
my $self = shift;
|
||||
$self->zone->output();
|
||||
$$self{zone} = rr_array_new_serial $$self{zone}
|
||||
}
|
||||
|
||||
sub dump {
|
||||
my $self = shift;
|
||||
$self->zone->dump();
|
||||
rr_array_dump $$self{zone}
|
||||
}
|
||||
|
||||
# better encapsulation
|
||||
sub a { my $self = shift; $self->zone->a }
|
||||
sub aaaa { my $self = shift; $self->zone->aaaa }
|
||||
sub cname { my $self = shift; $self->zone->cname }
|
||||
sub ns { my $self = shift; $self->zone->ns }
|
||||
sub mx { my $self = shift; $self->zone->mx }
|
||||
sub ptr { my $self = shift; $self->zone->ptr }
|
||||
sub txt { my $self = shift; $self->zone->txt } # TODO TEST THIS
|
||||
sub serial {
|
||||
my ($self, $rr) = @_;
|
||||
rr_array_serial $$self{zone}
|
||||
}
|
||||
|
||||
# remove a raw line that represents the RR
|
||||
sub rr_del_raw {
|
||||
my ($self, $rrline) = @_;
|
||||
my $rr = Net::DNS::RR->new($rrline);
|
||||
$self->rr_del($rr)
|
||||
}
|
||||
|
||||
sub rr_del {
|
||||
my ($self, $rr) = @_;
|
||||
$$self{zone} = rr_array_del $$self{zone}, $rr
|
||||
}
|
||||
|
||||
# add a raw line that represents the RR
|
||||
sub rr_add_raw {
|
||||
my ($self, $rrline) = @_;
|
||||
my $rr = Net::DNS::RR->new($rrline);
|
||||
$self->rr_add($rr)
|
||||
}
|
||||
|
||||
sub rr_add {
|
||||
my ($self, $rr) = @_;
|
||||
$$self{zone} = rr_array_add $$self{zone}, $rr
|
||||
}
|
||||
|
||||
sub rr_mod {
|
||||
my ($self, $rrline_old, $rrline_new) = @_;
|
||||
$self->rr_del_raw($rrline_old);
|
||||
$self->rr_add_raw($rrline_new);
|
||||
}
|
||||
|
||||
|
||||
sub rr_array_to_array {
|
||||
my ($self) = shift;
|
||||
my $rr_list;
|
||||
|
||||
for(@{$$self{zone}}) {
|
||||
|
||||
my @list = split / /, $_->plain;
|
||||
|
||||
my $rr;
|
||||
$$rr{name} = $list[0];
|
||||
$$rr{ttl} = $list[1];
|
||||
$$rr{class} = $list[2];
|
||||
$$rr{type} = $list[3];
|
||||
|
||||
if($list[3] =~ /SOA/) {
|
||||
$$rr{ns} = $list[4];
|
||||
$$rr{postmaster} = $list[5];
|
||||
$$rr{serial} = $list[6];
|
||||
$$rr{refresh} = $list[7];
|
||||
$$rr{retry} = $list[8];
|
||||
$$rr{expire} = $list[9];
|
||||
$$rr{minimum} = $list[10];
|
||||
}
|
||||
elsif($list[3] =~ /^(A(AAA)?|CNAME|NS)$/) {
|
||||
$$rr{rdata} = $list[4];
|
||||
}
|
||||
elsif($list[3] =~ /^MX$/) {
|
||||
$$rr{priority} = $list[4];
|
||||
$$rr{rdata} = $list[5];
|
||||
}
|
||||
elsif($list[3] =~ /^TXT$/) {
|
||||
$$rr{rdata} = $_->rdstring;
|
||||
}
|
||||
else {
|
||||
die "This RR is not available : " . $_->plain;
|
||||
}
|
||||
|
||||
push @$rr_list, $rr;
|
||||
|
||||
}
|
||||
|
||||
$rr_list
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -7,7 +7,7 @@ Ce qui permet d'être un remplaçant de DynDNS.
|
|||
## Outils
|
||||
|
||||
* [Dancer2](http://perldancer.org/)
|
||||
* [DNS::ZoneParse](https://metacpan.org/pod/DNS::ZoneParse)
|
||||
* [Net::DNS](https://metacpan.org/pod/Net::DNS)
|
||||
* [Bootstrap](http://twitter.github.io/bootstrap/)
|
||||
* [DBD::mysql](https://metacpan.org/module/DBD::mysql)
|
||||
* [Moo](https://metacpan.org/pod/Moo)
|
||||
|
@ -17,6 +17,6 @@ Ce qui permet d'être un remplaçant de DynDNS.
|
|||
|
||||
* captcha
|
||||
* demander confirmation avant suppression d'une zone
|
||||
* rajouter les types de RR manquants dans l'interface (remplacement de
|
||||
DNS::ZoneParse, ou amélioration)
|
||||
* rajouter les types de RR manquants dans l'interface (amélioration)
|
||||
* déléguer les zones
|
||||
* revoir le script de màj automatique d'IP
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
use Test::More;
|
||||
use Modern::Perl;
|
||||
use lib 'lib';
|
||||
use util ':all';
|
||||
use zonefile;
|
||||
|
||||
chdir 'lib'; # TODO hack at 2am
|
||||
|
||||
#map {
|
||||
# ok
|
||||
# ( ( is_domain_name $_ ), "is '$_' a domain name" )
|
||||
#} qw( foo.bar bar localhost. localhost );
|
||||
#
|
||||
#done_testing;
|
||||
|
||||
my $zf = zonefile->new( zonefile => "../t/zonefile.txt" );
|
||||
$zf->new_serial();
|
||||
print $zf->dump();
|
|
@ -0,0 +1,17 @@
|
|||
$ORIGIN example.com. ; designates the start of this zone file in the namespace
|
||||
$TTL 1h ; default expiration time of all resource records without their own TTL value
|
||||
example.com. IN SOA ns.example.com. username.example.com. ( 2007120710 1d 2h 4w 1h )
|
||||
example.com. IN NS ns ; ns.example.com is a nameserver for example.com
|
||||
example.com. IN NS ns.somewhere.example. ; ns.somewhere.example is a backup nameserver for example.com
|
||||
example.com. IN MX 10 mail.example.com. ; mail.example.com is the mailserver for example.com
|
||||
@ IN MX 20 mail2.example.com. ; equivalent to above line, "@" represents zone origin
|
||||
@ IN MX 50 mail3 ; equivalent to above line, but using a relative host name
|
||||
example.com. IN A 192.0.2.1 ; IPv4 address for example.com
|
||||
IN AAAA 2001:db8:10::1 ; IPv6 address for example.com
|
||||
ns IN A 192.0.2.2 ; IPv4 address for ns.example.com
|
||||
IN AAAA 2001:db8:10::2 ; IPv6 address for ns.example.com
|
||||
www IN CNAME example.com. ; www.example.com is an alias for example.com
|
||||
wwwtest IN CNAME www ; wwwtest.example.com is another alias for www.example.com
|
||||
mail IN A 192.0.2.3 ; IPv4 address for mail.example.com
|
||||
mail2 IN A 192.0.2.4 ; IPv4 address for mail2.example.com
|
||||
mail3 IN A 192.0.2.5 ; IPv4 address for mail3.example.com
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
<% FOREACH d IN alldomains %>
|
||||
<tr>
|
||||
<td><% d.domain %></td>
|
||||
<td> <a href="/domain/details/<% d.domain %>/"><% d.domain %></a> </td>
|
||||
<td><% d.login %></td>
|
||||
|
||||
<td>
|
||||
|
|
133
views/details.tt
133
views/details.tt
|
@ -17,94 +17,70 @@
|
|||
|
||||
<table class="table" >
|
||||
<caption>
|
||||
<td>Name</td>
|
||||
<td>Class</td>
|
||||
<tr>
|
||||
<td>Domaine</td>
|
||||
<td>Type</td>
|
||||
<td>Host</td>
|
||||
<td>Cible</td>
|
||||
<td>TTL</td>
|
||||
</tr>
|
||||
</caption>
|
||||
|
||||
<% FOREACH address in ns %>
|
||||
<% FOREACH rr in zone %>
|
||||
<tr>
|
||||
<form action='/domain/mod/<%domain%>/<%address.name%>/NS/<%address.host%>/<%address.ttl%>'>
|
||||
<td><input type='text' name='newname' class="form-control" value='<% address.name %>' /></td>
|
||||
<td><% address.class %></td>
|
||||
<td><input type='text' name='newtype' class="form-control" value='<% address.type %>'/></td>
|
||||
<td><input type='text' name='newhost' class="form-control" value='<% address.host %>'/></td>
|
||||
<td><input type='number' name='newttl' class="form-control" value='<% address.ttl %>'/></td>
|
||||
<td><input type='submit' id='submit' class="btn btn-success btn-xs" value='✔' />
|
||||
</form>
|
||||
<td><button type="button" class="btn btn-primary btn-danger btn-xs" onclick="location.href='http://'+location.host+'/domain/del/<% domain %>/<% address.name %>/NS/<% address.host %>/<% address.ttl %>';">✘</button></td>
|
||||
</tr>
|
||||
<% END %>
|
||||
<% SWITCH rr.type %>
|
||||
<% CASE [ "A", "AAAA", "TXT", "NS", "CNAME", "PTR" ] %>
|
||||
|
||||
<% FOREACH address in a %>
|
||||
<tr>
|
||||
<form action='/domain/mod/<%domain%>/<%address.name%>/A/<%address.host%>/<%address.ttl%>'>
|
||||
<td><input type='text' name='newname' class="form-control" value='<% address.name %>'/></td>
|
||||
<td><% address.class %></td>
|
||||
<td><input type='text' name='newtype' class="form-control" value='<% address.type %>'/></td>
|
||||
<td><input type='text' name='newhost' class="form-control" value='<% address.host %>'/></td>
|
||||
<td><input type='number' name='newttl' class="form-control" value='<% address.ttl %>'/></td>
|
||||
<td><input type='submit' id='submit' class="btn btn-success btn-xs" value='✔' />
|
||||
</form>
|
||||
<td><button type="button" class="btn btn-primary btn-danger btn-xs" onclick="location.href='http://'+location.host+'/domain/del/<% domain %>/<% address.name %>/A/<% address.host %>/<% address.ttl %>';">✘</button></td>
|
||||
</tr>
|
||||
<% END %>
|
||||
<form method="post" action='/domain/mod/<% domain %>'>
|
||||
<input type="hidden" name="oldname" value="<% rr.name %>"/>
|
||||
<input type="hidden" name="oldtype" value="<% rr.type %>"/>
|
||||
<input type="hidden" name="oldttl" value="<% rr.ttl %>"/>
|
||||
<input type="hidden" name="oldrdata" value="<% rr.rdata %>"/>
|
||||
|
||||
<% FOREACH address in aaaa %>
|
||||
<tr>
|
||||
<form action='/domain/mod/<%domain%>/<%address.name%>/AAAA/<%address.host%>/<%address.ttl%>'>
|
||||
<td><input type='text' name='newname' class="form-control" value='<% address.name %>'/></td>
|
||||
<td><% address.class %></td>
|
||||
<td><input type='text' name='newtype' class="form-control" value='<% address.type %>'/></td>
|
||||
<td><input type='text' name='newhost' class="form-control" value='<% address.host %>'/></td>
|
||||
<td><input type='number' name='newttl' class="form-control" value='<% address.ttl %>'/></td>
|
||||
<td><input type='submit' id='submit' class="btn btn-success btn-xs" value='✔' />
|
||||
</form>
|
||||
<td><button type="button" class="btn btn-primary btn-danger btn-xs" onclick="location.href='http://'+location.host+'/domain/del/<% domain %>/<% address.name %>/AAAA/<% address.host %>/<% address.ttl %>';">✘</button></td>
|
||||
</tr>
|
||||
<% END %>
|
||||
<td><input type='text' name='newname' class="form-control" value='<% rr.name %>'/></td>
|
||||
<td><% rr.class %></td>
|
||||
<td><input type='text' name='newtype' size='8' class="form-control" value='<% rr.type %>'/></td>
|
||||
<td><input type='number' name='newttl' size='4' class="form-control" value='<% rr.ttl %>'/></td>
|
||||
<td><input type='text' name='newrdata' class="form-control" value='<% rr.rdata %>'/></td>
|
||||
<td><input type='submit' id='submit' class="btn btn-success btn-xs" value='✔' /></td>
|
||||
|
||||
<% FOREACH address in cname %>
|
||||
<tr>
|
||||
<form action='/domain/mod/<%domain%>/<%address.name%>/CNAME/<%address.host%>/<%address.ttl%>'>
|
||||
<td><input type='text' name='newname' class="form-control" value='<% address.name %>'/></td>
|
||||
<td><% address.class %></td>
|
||||
<td><input type='text' name='newtype' class="form-control" value='<% address.type %>'/></td>
|
||||
<td><input type='text' name='newhost' class="form-control" value='<% address.host %>'/></td>
|
||||
<td><input type='number' name='newttl' class="form-control" value='<% address.ttl %>'/></td>
|
||||
<td><input type='submit' id='submit' class="btn btn-success btn-xs" value='✔' />
|
||||
<td>
|
||||
<a href='/domain/del/<% domain %>/<% rr.name %>/<% rr.ttl %>/<% rr.type %>/<% rr.rdata %>'>
|
||||
<button type="button" class="btn btn-primary btn-danger btn-xs">
|
||||
✘
|
||||
</button>
|
||||
</a>
|
||||
</td>
|
||||
</form>
|
||||
<td><button type="button" class="btn btn-primary btn-danger btn-xs" onclick="location.href='http://'+location.host+'/domain/del/<% domain %>/<% address.name %>/CNAME/<% address.host %>/<% address.ttl %>';">✘</button></td>
|
||||
</tr>
|
||||
<% END %>
|
||||
|
||||
<% FOREACH address in ptr %>
|
||||
<tr>
|
||||
<form action='/domain/mod/<%domain%>/<%address.name%>/PTR/<%address.host%>/<%address.ttl%>'>
|
||||
<td><input type='text' name='newname' class="form-control" value='<% address.name %>'/></td>
|
||||
<td><% address.class %></td>
|
||||
<td><input type='text' name='newtype' class="form-control" value='<% address.type %>'/></td>
|
||||
<td><input type='text' name='newhost' class="form-control" value='<% address.host %>'/></td>
|
||||
<td><input type='number' name='newttl' class="form-control" value='<% address.ttl %>'/></td>
|
||||
<td><input type='submit' id='submit' class="btn btn-success btn-xs" value='✔' />
|
||||
</form>
|
||||
<td><button type="button" class="btn btn-primary btn-danger btn-xs" onclick="location.href='http://'+location.host+'/domain/del/<% domain %>/<% address.name %>/PTR/<% address.host %>/<% address.ttl %>';">✘</button></td>
|
||||
</tr>
|
||||
<% END %>
|
||||
<% CASE "MX" %>
|
||||
|
||||
<% FOREACH address in mx %>
|
||||
<tr>
|
||||
<form action='/domain/mod/<%domain%>/<%address.name%>/MX/<%address.host%>/<%address.ttl%>'>
|
||||
<td><input type='text' name='newname' class="form-control" value='<% address.name %>'/></td>
|
||||
<td><% address.class %></td>
|
||||
<td><input type='text' name='newtype' class="form-control" value='<% address.type %>'/></td>
|
||||
<td><input type='text' name='newhost' class="form-control" value='<% address.host %>'/><input type='number' name='newpriority' class="form-control" value='<%address.priority%>'/></td>
|
||||
<td><input type='number' name='newttl' class="form-control" value='<% address.ttl %>'/></td>
|
||||
<td><input type='submit' id='submit' class="btn btn-success btn-xs" value='✔' />
|
||||
<form method="post" action='/domain/mod/<% domain %>'>
|
||||
<input type="hidden" name="oldname" value="<% rr.name %>"/>
|
||||
<input type="hidden" name="oldtype" value="<% rr.type %>"/>
|
||||
<input type="hidden" name="oldttl" value="<% rr.ttl %>"/>
|
||||
<input type="hidden" name="oldrdata" value="<% rr.rdata %>"/>
|
||||
<input type="hidden" name="oldpriority" value="<% rr.priority %>"/>
|
||||
|
||||
<td><input type='text' name='newname' class="form-control" value='<% rr.name %>'/></td>
|
||||
<td><% rr.class %></td>
|
||||
<td><input type='text' name='newtype' class="form-control" value='<% rr.type %>'/></td>
|
||||
<td><input type='number' name='newttl' size='4' class="form-control" value='<% rr.ttl %>'/></td>
|
||||
<td><input type='text' name='newrdata' class="form-control" value='<% rr.rdata %>'/>
|
||||
<input type='number' name='newpriority' size='4' class="form-control" value='<% rr.priority %>'/></td>
|
||||
<td><input type='submit' id='submit' class="btn btn-success btn-xs" value='✔' /></td>
|
||||
|
||||
<td>
|
||||
<a href='/domain/del/<% domain %>/<% rr.name %>/<% rr.ttl %>/<% rr.type %>/<% rr.rdata %>'>
|
||||
<button type="button" class="btn btn-primary btn-danger btn-xs">
|
||||
✘
|
||||
</button>
|
||||
</a>
|
||||
</td>
|
||||
</form>
|
||||
<td><button type="button" class="btn btn-primary btn-danger btn-xs" onclick="location.href='http://'+location.host+'/domain/del/<% domain %>/<% address.name %>/MX/<% address.host %>/<% address.ttl %>';">✘</button></td>
|
||||
<% CASE %>
|
||||
<td>Resource Record non pris en charge : <% rr.type %></td>
|
||||
<% END %>
|
||||
|
||||
</tr>
|
||||
<% END %>
|
||||
</table>
|
||||
|
@ -134,6 +110,7 @@
|
|||
<option value="MX">MX</option>
|
||||
<option value="NS">NS</option>
|
||||
<option value="PTR">PTR</option>
|
||||
<option value="TXT">TXT</option>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
|
@ -147,9 +124,9 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="value" class="col-sm-2 control-label">Valeur</label>
|
||||
<label for="rdata" class="col-sm-2 control-label">Valeur</label>
|
||||
<div class="col-sm-3">
|
||||
<input type="text" id="value" name="value" class="form-control" placeholder="IP ou ndd" >
|
||||
<input type="text" id="rdata" name="rdata" class="form-control" placeholder="IP ou ndd" >
|
||||
</div>
|
||||
Votre adresse IP : <% user_ip %>
|
||||
</div>
|
||||
|
|
Reference in New Issue