IPv6 addresses can now be used for remote nameservers in slave and delegation zones.
---- Changes since 1.540 ----
Added the Test Zone Transfer button to the slave zone page, to check if zone transfers are possible or not.
+---- Changes since 1.550 ----
+Links for editing and deleting records now using the record name instead of an index, which makes editing more reliable if records are also being updated by dynamic DNS or some other tool.
if (defined($_[5])) {
print &ui_hidden("num", $_[5]);
%rec = %{$_[6]};
+ print &ui_hidden("id", &record_id(\%rec));
}
else {
print &ui_hidden("new", 1);
@recs = &read_zone_file($zone->{'file'}, $dom);
foreach $d (sort { $b <=> $a } @d) {
- $r = $recs[$d];
+ ($num, $id) = split(/\//, $d, 2);
+ $r = &find_record_by_id(\@recs, $id, $num);
+ next if (!$r);
if ($in{'rev'}) {
# Find the reverse
$fulloldvalue0 = &convert_to_absolute(
$type = $zone->{'type'};
$file = $zone->{'file'};
@recs = &read_zone_file($file, $dom);
-$rec = $recs[$in{'num'}];
+$rec = &find_record_by_id(\@recs, $in{'id'}, $in{'num'});
+$rec || &error($text{'edit_egone'});
&can_edit_type($rec->{'type'}, \%access) ||
&error($text{'recs_ecannottype'});
}
local @cols;
$name = &html_escape($name);
+ $id = &record_id($r);
if (!$access{'ro'} && $type eq 'master') {
push(@cols,
"<a href=\"edit_record.cgi?index=".
- "$in{'index'}&type=$in{'type'}&num=$r->{'num'}&".
+ "$in{'index'}&id=$id&num=$r->{'num'}&type=$in{'type'}&".
"sort=$in{'sort'}&view=$in{'view'}\">$name</a>");
}
else {
}
if (!$access{'ro'} && $type eq 'master') {
$rv .= &ui_checked_columns_row(\@cols, \@tds,
- "d", $r->{'num'});
+ "d", $r->{'num'}."/".$id);
}
else {
$rv .= &ui_columns_row(\@cols, \@tds);
edit_over=Yes (and replace existing)
edit_upfwd=Update forward?
edit_err=Failed to save record
+edit_egone=Selected record no longer exists!
edit_ettl='$1' is not a valid time-to-live
edit_eip='$1' is not a valid IP address
edit_eip6='$1' is not a valid IPv6 address
return undef;
}
+# record_id(&r)
+# Returns a unique ID string for a record, based on the name and value
+sub record_id
+{
+my ($r) = @_;
+return $r->{'name'}."/".$r->{'type'}.
+ (uc($r->{'type'}) eq 'SOA' ? '' : '/'.join('/', @{$r->{'values'}}));
+}
+
+# find_record_by_id(&recs, id, index)
+# Find a record by ID and possibly index
+sub find_record_by_id
+{
+my ($recs, $id, $num) = @_;
+my @rv = grep { &record_id($_) eq $id } @$recs;
+if (!@rv) {
+ return undef;
+ }
+elsif (@rv == 1) {
+ return $rv[0];
+ }
+else {
+ # Multiple matches .. find the one with the right index
+ @rv = grep { $_->{'num'} == $num } @rv;
+ return @rv ? $rv[0] : undef;
+ }
+}
+
1;
}
# get the old record if needed
-$r = $recs[$in{'num'}] if (defined($in{'num'}));
+if (defined($in{'num'})) {
+ $r = &find_record_by_id(\@recs, $in{'id'}, $in{'num'});
+ $r || &error($text{'edit_egone'});
+ }
# check for deletion
if ($in{'delete'}) {
&unlock_all_files();
$r->{'newvalues'} = $vals;
&webmin_log($in{'new'} ? 'create' : 'modify', 'record', $in{'origin'}, $r);
-&redirect("edit_recs.cgi?index=$in{'index'}&view=$in{'view'}&type=$in{'redirtype'}&sort=$in{'sort'}");
+&redirect("edit_recs.cgi?index=$in{'index'}&view=$in{'view'}&".
+ "type=$in{'redirtype'}&sort=$in{'sort'}");
# valname(name)
sub valname