📄 save_record.cgi
字号:
# occur because the revrec reference will have been reset to orec # above. The revconf and revfile variables will automatically be the # same for both records. # if ($revconf && &can_edit_reverse($revconf)) { $name = &convert_fqdn(1, $name, $origin, 1); $rname = ($ipv4_rec) ? &ip_to_arpa($value) : &net_to_ip6arpa($value); $oldname = &convert_fqdn(1, $in{'oldname'}, $origin, 1); $rev_origin = lc($revconf->{'value'}); $rev_origin .= '.' unless ($rev_origin =~ /\.$/o); unless ($new_rev_dynamic) { &lock_file($config{'chroot'}. &absolute_path($revfile)); } if ($revrec && ($new || (lc($revrec->{'values'}->[0]) eq $oldname)) && ($in{'rev'} == 2 || $only_ttl_changed)) { # # Update an existing reverse record. # &modify_record($revconf, $revfile, $revrec, $rname, $ttl, 'IN', 'PTR', $name, $in{'comment'}); } else { # # Create a reverse record regardless of whether one # already exists or not. # &create_record($revconf, $revfile, $rname, $ttl, 'IN', 'PTR', $name, $in{'comment'}); } @orecs = &get_zone($revconf, $revfile, $rev_origin); &bump_soa_record($revconf, \@orecs, $new_rev_serial); }}elsif ($in{'fwd'} && $name !~ /\*/o) { # # The user may create a new record which already has a reverse record. # if ($new) { $oconf = $revconf; $ofile = $revfile; $orec = $revrec; } # # If the old forward record is not within the zone of the new one then # delete the old forward record (if requested). # if ($oconf && $fwdconf && $oconf->{'value'} eq $fwdconf->{'value'}) { $only_ttl_changed++ if ($orec && $fwdrec && $orec->{'fqdn'} eq $fwdrec->{'fqdn'} && $orec->{'values'}->[0] eq $fwdrec->{'values'}->[0]); if ($only_ttl_changed && ($ttl == $fwdrec->{'ttl'} || ($ttl == 0 && ! defined($fwdrec->{'ttl'})))) { $fwdconf = 0; } else { $fwdrec = $orec; # We don't need orec itself anymore. } } else { &delete_rev_rec() if ($oconf && $in{'fwd'} == 2); } if ($fwdconf && &can_edit_forward($fwdconf)) { $name = &convert_fqdn(1, $name, $origin, 1); $oldname = &convert_fqdn(1, $oldname, $origin, 1); $oldvalue = $fwdrec->{'values'}->[0] if ($fwdrec); if ($ipv4_zone) { $rtype = 'A'; $name = &compress_ip(&arpa_to_ip($name)); $oldname = &compress_ip(&arpa_to_ip($oldname)); $oldvalue = &compress_ip($oldvalue) if ($fwdrec); } else { $rtype = 'AAAA'; $name = &compress_ip6(&ip6arpa_to_net($name)); $oldname = &compress_ip6(&ip6arpa_to_net($oldname)); $oldvalue = &compress_ip6($oldvalue) if ($fwdrec); } $rev_origin = lc($fwdconf->{'value'}); $rev_origin .= '.' unless ($rev_origin =~ /\.$/o); $rname = &convert_fqdn(1, $value, $rev_origin, 0); unless ($new_rev_dynamic) { &lock_file($config{'chroot'} . &absolute_path($fwdfile)); } if ($fwdrec && ($new || ($oldname eq $oldvalue)) && ($in{'fwd'} == 2 || $only_ttl_changed)) { # # Update an existing forward record. # &modify_record($fwdconf, $fwdfile, $fwdrec, $rname, $ttl, 'IN', $rtype, $name, $in{'comment'}); } else { # # Create a forward record regardless of whether one # already exists or not. # &create_record($fwdconf, $fwdfile, $rname, $ttl, 'IN', $rtype, $name, $in{'comment'}); } @orecs = &get_zone($fwdconf, $fwdfile, $rev_origin); &bump_soa_record($fwdconf, \@orecs, $new_rev_serial); }}&bump_soa_record($zone, \@recs, $new_serial);&unlock_all_files();&webmin_log($new ? 'create' : 'modify', 'record', $origin, $rec);&redirect("edit_recs.cgi?index=$in{'index'}&view=$in{'view'}&type=$in{'redirtype'}&sort=$in{'sort'}&file=${file}&ztype=$in{'ztype'}");exit;## can_edit_reverse(&zone)#sub can_edit_reverse { return ($access{'reverse'} || &can_edit_zone(\%access, $_[0]));}## can_edit_forward(&zone)#sub can_edit_forward { return (&can_edit_zone(\%access, $_[0]));}## Delete a reverse or forward record associated with a new or existing record.# Wildcarded records are not updated. Once all this has been done, we reset the# relevant values so that subsquent code will think that the reverse record# never existed. We must do this to ensure that the reverse record is not# looked at again.#sub delete_rev_rec { return if ($new || $oldname =~ /\*/o); return unless ($in{'rev'} || $in{'fwd'}); if ($in{'rev'}) { # # Deleting a reverse record. # if ($orec && &can_edit_reverse($oconf)) { $rname = lc($orec->{'values'}->[0]); } else { return; } } else { # # Deleting a forward record. # if ($orec && &can_edit_forward($oconf)) { if ($ipv4_zone) { $rname = &ip_to_arpa($orec->{'values'}->[0]); } else { $rname = &net_to_ip6arpa($orec->{'values'}->[0]); $rname = lc($rname); } } else { return; } } $oldname = &convert_fqdn(1, $in{'oldname'}, $origin, 1); if ($rname eq $oldname) { # # Found the old reverse/forward record, so delete it. # unless ($old_rev_dynamic) { &lock_file($config{'chroot'} . &absolute_path($ofile)); } &delete_record($oconf, $ofile, $orec); $rev_origin = lc($oconf->{'value'}); $rev_origin .= '.' unless ($rev_origin =~ /\.$/o); @orecs = &get_zone($oconf, $ofile, $rev_origin); &bump_soa_record($oconf, \@orecs, $old_rev_serial); unless ($old_rev_dynamic) { &unlock_file($config{'chroot'} . &absolute_path($ofile)); } } return;}## Check the old reverse/forward serial number. This will return a 2 element# array consisting of the new serial number, and whether the zone is dynamic.## check_rev_serial(zone)#sub check_rev_serial { my $dynamic = my $serial = 0; my $zone = my $rec = my $zone_ref = ''; my @return_array = (); $zone = $_[0]; return @return_array unless ($zone); $zone_ref = &get_zone_data($zone); $dynamic = $return_array[1] = $zone_ref->[1]; if ($dynamic == 2 || ($return_array[0] = &check_soa_serial($zone_ref, $zone, undef, undef)) < 0) { &terror('soa_serial_noupdt', ($in{'rev'}) ? $text{'reverse'} : $text{'forward'}); } return @return_array;}## Unfortunately TXT records are a little awkward! Generally the text message# is saved with double quotes around it. We must, therefore, escape any# internal quotes or semicolon's. We must also double up all the escape# characters for quotes if this is a dynamic zone. The reason being that the# string will be passed through the 'echo' command, and would normally strip a# level of quotes off. So we must prevent that.## This subroutine actually escapes and quotes as necessary the old TXT record# value so that it may be deleted or changed. If we didn't do this then the DNS# would just keep creating new records rather than changing the old one.#sub fix_oldtxt_rec { my $i = 0; my $v = ''; for ($i = 0; defined($rec->{'values'}->[$i]); $i++) { $v .= $rec->{'values'}->[$i] . ' '; undef $rec->{'values'}->[$i]; } $v =~ s/\s+$//o; $v =~ s/(?<!\\)([;"])/\\$1/g; if ($dynamic) { $v =~ s/(\\")/\\\\$1/g; $rec->{'values'}->[0] = $rec->{'value'} = '\"' . $v . '\"'; } else { $rec->{'values'}->[0] = $rec->{'value'} = '"' . $v . '"'; } return;}## This subroutine will check that any new record, or a record that is being# changed, is checked against all the other records to ensure that there are# no CNAME or DNAME record collisions.#sub check_name_collision { my $name_is_cname = my $name_is_dname = 0; my $rec_is_cname = my $rec_is_dname = my $n_wild = 0; my $oldname = my $wild = my $nw = my $vw = ''; if ($name =~ /\*/o) { $n_wild++; $nw = $name; $nw =~ s/\./\\./go; # Escape any existing dots. $nw =~ s/^\*/.*/o; # Change the asterisk to '.*'. } $oldname = lc($in{'oldname'}) unless ($new); if ($type eq 'CNAME') { $name_is_cname++; if ($n_wild && $value =~ /^$nw$/) { &terror('edit_cname_self1'); } elsif ($name eq $value) { &terror('edit_cname_self2'); } } elsif ($type eq 'DNAME') { $name_is_dname++; $nw = $name; $nw =~ s/\./\\./go; # Escape any existing dots. if ($value =~ /(^|\.)$nw$/) { &terror('edit_cname_self2'); } } if ($name ne $rec_name) { foreach $z (@recs) { $v = $z->{'fqdn'}; # # If we are modifying a record, then we can ignore the # old one. We are only interested in testing against # all the other records. # next if (! $new && ($oldname eq $v)); $rec_is_cname = ($z->{'type'} eq 'CNAME'); $rec_is_dname = ($z->{'type'} eq 'DNAME'); # # If we are adding a DNAME record then we can only # allow in the zone other DNAME records, and those # records whose label is the same as that of the # DNAME. That is, NS, MX records, etc. # if ($name_is_dname) { $vw = $v; $vw =~ s/\./\\./go; if ($v =~ /\.$nw$/) { &terror('edit_dname_noallow_below', "<i>$name</i>", $v); } elsif ($name =~ /\.$vw$/ && $rec_is_dname) { &terror('edit_dname_noallow_above', "<i>$v</i>"); } elsif (($rec_is_dname || $rec_is_cname) && ($name eq $v)) { &terror('edit_dname_exists', ($rec_is_dname ? 'DNAME' : 'CNAME')); } next; } elsif ($rec_is_dname) { $vw = $v; $vw =~ s/\./\\./go; if ($name =~ /\.$vw$/) { &terror('edit_dname_seen', "<i>$v</i>"); } elsif ($name_is_cname && ($name eq $v)) { &terror('edit_dname_exists', 'DNAME'); } next; } # # We have finished with DNAMEs, so now test CNAME # records. # next unless ($name_is_cname || $rec_is_cname); # # Non-wildcard records are allowed to clash with # wildcarded ones - they take precedence. So, we only # really need to test when both records are equal, when # they are not wildcarded, or when one record is within # the other one, and they are both wildcarded. # if ($n_wild && $v =~ /\*/o) { $vw = $v; $vw =~ s/\./\\./go; $vw =~ s/^\*/.*/o; next unless ($v =~ /^$nw$/ || $name =~ /^$vw$/); $wild = $text{'edit_cname_wild'}; } elsif ($v eq $name) { # # CNAME records can have KEY/NXT/SIG records of # the same name. # next if ($name_is_cname && ($z->{'type'} eq 'KEY' || $z->{'type'} eq 'NXT' || $z->{'type'} eq 'SIG')); next if ($rec_is_cname && ($type eq 'KEY' || $type eq 'NXT' || $type eq 'SIG')); $wild = ''; } else { next; } if ($name_is_cname) { $zn = ($config{'display_fqdn'}) ? 1 : ($reverse) ? -1 : 0; $v = &convert_fqdn($zn, $name, $origin, 0); &terror('edit_ecname1', $v, $wild); } elsif ($rec_is_cname) { &terror('edit_ecname2', $wild); } } } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -