?? delete_zone.cgi
字號(hào):
#! /usr/bin/perl## B9DDNS - BIND 9 dynamic DNS webmin module.# Copyright (C) 2003 John Horne. <john.horne@plymouth.ac.uk># Copyright (C) 2004 John Horne. <john.horne@plymouth.ac.uk>## This program is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License as published by# the Free Software Foundation; either version 2 of the License, or# (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.### Delete a zone and all its records.#use strict;no strict 'vars';require './b9ddns-lib.pl';my $dynamic_zone = my $reverse = my $rev_zone_type = my $ipv4 = 0;my $count = my $no_named = 0;my $conf = my $zone_conf = my $view = my $type = my $server = '';my $file = my $real_file = my $record = my $oconf = my $ofile = my $orec = '';my $lref = my $user = my $zone = my $zone_hdr = my $origin = '';my $slave_parent = my $slave_conf = my $slave_zone_conf = '';my $slave_error = my $rev_zone_name = my $rev_file = '';my $dyn_rev_str = my $rev_zone_ref = my $rev_zone_rec_ref = my $err = '';my @servers = my @recs = my @orecs = ();my %wusers = my %uaccess = my %zone_type = my %rev_zone_recs = ();&ReadParse();$conf = &get_config();if ($in{'view'}) { $view = $conf->[$in{'view'}]; $conf = $view->{'members'};}$zone_conf = $conf->[$in{'index'}];%access = &get_module_acl();unless (&can_edit_zone(\%access, $zone_conf, $view)) { &terror('master_edelete');}if ($access{'ro'}) { &terror('master_ero');}unless ($access{'delete'}) { &terror('master_edeletecannot');}$origin = lc($zone_conf->{'value'});$origin .= '.' unless ($origin =~ /\.$/o);$dynamic_zone = &dynamic_zone($zone_conf, 1);$reverse++ if ($origin =~ /\.(in-addr|ip6)\.arpa\.$/o);$type = $in{'type'};$file = $in{'file'};$real_file = $config{'chroot'} . &absolute_path($file) if ($file);unless ($in{'confirm'}) { # # Ask the user if he/she is sure... # $zone_hdr = &zone_header($dynamic_zone, $origin, $text{ucfirst($type)}); &header($text{'delete_title'}, '', undef, 0, 0, 0, undef, undef, undef, $zone_hdr); print '<hr>'; if ($type eq 'hint') { print '<p>', $text{'hint_desc1'}, '<br><br>', $text{'hint_desc2'}, '<p>'; print '<center><p>', $text{'delete_mesg2'}, '<p>'; } else { if ($reverse) { $orec = &ip6arpa_to_net(&arpa_to_ip($origin)); } else { $orec = $origin; $orec =~ s/\.$//o unless ($origin eq '.'); } print '<center><p>', &text('delete_mesg', " <b>$orec</b>"); print ' ', $text{'delete_mesg_file'} if ($file && -e $real_file); print '<p>'; } print "<form action=delete_zone.cgi>\n"; print '<input type=hidden name=index value=', $in{'index'}, '>'; print '<input type=hidden name=view value=', $in{'view'}, '>'; print '<input type=hidden name=file value=', $file, '>'; print '<input type=hidden name=type value=', $type, '>'; print '<input type=submit name=confirm value="', $text{'master_del'}, '">'; if ($type eq 'hint') { print ' ' x 6, '<input type=checkbox name=del_hint value=1>', $text{'hint_del'}; } elsif ($type eq 'master') { print '<p>', $text{$reverse ? 'delete_fwd' : 'delete_rev'}, ' '; print '<input type=radio name=rev value=1 checked> ', $text{'yes'}; print '<input type=radio name=rev value=0> ', $text{'no'}, '<br>'; &foreign_require('servers', 'servers-lib.pl'); @servers = grep { $_->{'user'} } &servers::list_servers(); if (@servers && $access{'remote'}) { print $text{'delete_slave'}, ' <select name=slave>'; print '<option value=""> '; foreach $server (@servers) { printf "<option value=%s %s>%s\n", $server->{'host'}, ($server->{'host'} eq $config{'default_slave'}) ? 'selected' : '', $server->{'desc'} ? $server->{'desc'} : $server->{'host'}; } print '</select><br>'; } } print '</form></center>'; print '<hr>'; &footer("edit_zone.cgi?index=$in{'index'}&view=$in{'view'}&type=$type", $text{'master_return'}); exit;}if ($in{'rev'} && $type eq 'master') { # # When deleting the forward/reverse records we do not want to increment # the SOA serial number for each record deleted. The reason being that # if a date format serial number is used then it could easily exceed # the maximum of 100 changes per day. Since the reverse zone may be # static or dynamic, we must find out the zone type first of all. Then, # for static zones, we delete the record but increment the serial number # after all the records have been deleted. For dynamic zones we have to # store the record with the zone, and then at the end delete all the # records for each reverse zone in one go. This way the serial number # will only be incremented once. # # NOTE: There is no guarantee that a reverse record will be deleted - # for example, the user may not have rights to edit that particular # zone. As such it is the administrators responsibility to ensure that # the zone is completely deleted. # $no_named = (&named_running() <= 0); $ipv4 = ($origin =~ /\.in-addr\.arpa\.$/o); if ($file) { # This should always be true. &lock_file($real_file); @recs = &get_zone($zone_conf, $file, $origin, undef, 'master'); } # # We'll lock the named.conf file as well, just to be sure nobody else # starts to move the zones around whilst we are deleting things. # &lock_file($config{'chroot'} . $zone_conf->{'file'}); # # Find and delete the forward/reverse records. # foreach $record (@recs) { if ($reverse) { next if ($record->{'type'} ne 'PTR'); ($oconf, $ofile, $orec) = &find_forward($record->{'values'}->[0], $record->{'fqdn'}, $ipv4); next unless ($orec && &can_edit_zone(\%access, $oconf)); } else { next if ($record->{'type'} ne 'A' && $record->{'type'} ne 'AAAA'); ($oconf, $ofile, $orec) = &find_reverse($record->{'values'}->[0], $record->{'fqdn'}); next unless ($orec && &can_edit_reverse($oconf)); } $rev_zone_name = lc($oconf->{'value'}); $rev_zone_name .= '.' unless ($rev_zone_name =~ /\.$/o); $rev_zone_ref = &get_zone_data($oconf); if (defined($rev_zone_recs{$rev_zone_name})) { # # We must do this because non-updateable zones will # have reset their zone type. Using this (reset) value # will avoid us checking their SOA serial number every # time. # $rev_zone_type = $rev_zone_recs{$rev_zone_name}->[0]->[0]; } else { $rev_zone_type = $rev_zone_ref->[1]; } if ($rev_zone_type == 0) { # A static zone. # # For static zones we can still delete the records, # even if we cannot increment the serial number. The # changes will then take place the next time named is # restarted. # $rev_file = $config{'chroot'} . &absolute_path($ofile); &lock_file($rev_file); &delete_record($oconf, $ofile, $orec); &unlock_file($rev_file); } elsif ($rev_zone_type == 1) { # A dynamic zone. # # If named is not running then there is no way that we # can delete dynamic zone records. # $rev_zone_type = 2 if ($no_named); } else { # A dynamic zone which we cannot update or for next; # which we cannot update the serial number. } # # We must now check the zones SOA serial number. If it is not # updateable then we simply reset the zone type. # if ($config{'soa_date_style'} && $rev_zone_type != 2) { $count = &check_soa_serial($rev_zone_ref, $oconf, undef, undef); $rev_zone_type = 2 if ($count < 0); } push(@{ $rev_zone_recs{$rev_zone_name} }, [ $rev_zone_type, $oconf, $ofile, $orec ] ); } # # Get the first entry of the first record of each zone in order to # determine the zone type. If it is a static zone then we have already # deleted the record and just need to check the serial number and bump # it up. For dynamic zones we first need to build up a string of the # records to delete. # foreach $rev_zone_name (keys(%rev_zone_recs)) { $rev_zone_type = $rev_zone_recs{$rev_zone_name}->[0]->[0]; if ($rev_zone_type == 0) { # A static zone. $rev_zone_rec_ref = $rev_zone_recs{$rev_zone_name}->[0]; $oconf = $rev_zone_rec_ref->[1]; $ofile = $rev_zone_rec_ref->[2]; $orec = $rev_zone_rec_ref->[3]; } elsif ($rev_zone_type == 1) { # A dynamic zone. $count = 0; $dyn_rev_str = 'local ' . $config{'ns_if_update'} . "\n"; $dyn_rev_str .= 'zone ' . $rev_zone_name . "\n"; foreach $rev_zone_rec_ref (@{ $rev_zone_recs{$rev_zone_name} }) { $oconf = $rev_zone_rec_ref->[1]; $ofile = $rev_zone_rec_ref->[2]; $orec = $rev_zone_rec_ref->[3]; $count++; $dyn_rev_str .= "update delete $orec->{'fqdn'} $orec->{'class'} $orec->{'type'} $orec->{'values'}->[0]\n"; # # To ensure that the character string does not # get excessively large, we update the zone # after each 1000 records. This will, of course, # result in the SOA serial number being # increased for each thousand records. However, # this should not be a problem unless the zone # has a really large number of records. # if ($count >= 1000) { $count = 0; $dyn_rev_str .= "\n"; $err = `echo "$dyn_rev_str" | $config{'nsupdate_cmd'} >/dev/null 2>&1`; $dyn_rev_str = 'local ' . $config{'ns_if_update'} . "\n"; $dyn_rev_str .= 'zone ' . $rev_zone_name . "\n"; } } if ($count) { $dyn_rev_str .= "\n"; # # We do not bother with errors because it is # for the administrator to ensure that the zone # records have been deleted. # $err = `echo "$dyn_rev_str" | $config{'nsupdate_cmd'} >/dev/null 2>&1`; } } else { # A non-updateable zone - ignore it. next; } @recs = &get_zone($oconf, $ofile, $rev_zone_name, undef, 'master'); &bump_soa_record($oconf, \@recs, undef); }}## Now delete the records file.#if ($file && ($type ne 'hint' || ($type eq 'hint' && $in{'del_hint'}))) { &lock_file($real_file); unlink $real_file, $real_file . '.jnl'; &unlock_file($real_file);}## Remove the zone directive.#&lock_file($config{'chroot'} . $zone_conf->{'file'});$lref = &read_file_lines($config{'chroot'} . $zone_conf->{'file'});splice(@$lref, $zone_conf->{'line'}, $zone_conf->{'eline'} - $zone_conf->{'line'} + 1);&flush_file_lines();&unlock_all_files();## Remove from acl files.#&read_acl(undef, \%wusers);$lref = $origin;$lref =~ s/\.$//o unless ($lref eq '.');foreach $user (keys(%wusers)) { %uaccess = &get_module_acl($user); if ($uaccess{'zones'} ne '*') { $uaccess{'zones'} = join(' ', grep { $_ !~ /^$lref\.?$/i } split(/\s+/, $uaccess{'zones'})); &save_module_acl(\%uaccess, $user); }}## Also delete from slave servers.#if ($in{'slave'} && $access{'remote'}) { &error_setup($text{'delete_err2'}); &remote_error_setup(\&slave_error_handler); &remote_foreign_require($in{'slave'}, $module_name, 'b9ddns-lib.pl'); if ($slave_error) { &error($slave_error); } $slave_parent = &remote_foreign_call($in{'slave'}, $module_name, 'get_config_parent'); $slave_conf = $slave_parent->{'members'}; foreach $zone (&find('zone', $slave_conf)) { $slave_zone_conf = lc($zone->{'value'}); $slave_zone_conf .= '.' unless ($slave_zone_conf =~ /\.$/o); if ($slave_zone_conf eq $origin) { $slave_zone_conf = $zone; last; } } unless ($slave_zone_conf) { &terror('slave_ezone'); } &remote_foreign_call($in{'slave'}, $module_name, 'save_directive', $slave_parent, [ $slave_zone_conf ], [ ]); &remote_foreign_call($in{'slave'}, $module_name, 'flush_file_lines'); &remote_foreign_call($in{'slave'}, $module_name, 'webmin_log', 'delete', 'slave', $origin, \%in);}&webmin_log('delete', $type, $origin, \%in);&redirect('');exit;## can_edit_reverse(&zone)#sub can_edit_reverse { return $access{'reverse'} || &can_edit_zone(\%access, $_[0]);}sub slave_error_handler { $slave_error = $_[0]; return;}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -