Index: /trunk/DNSDB.pm
===================================================================
--- /trunk/DNSDB.pm	(revision 264)
+++ /trunk/DNSDB.pm	(revision 265)
@@ -606,4 +606,87 @@
   return ('OK','OK');
 } # done AAAA+PTR template record
+
+
+##
+## Record data substitution subs
+##
+
+# Replace ZONE in hostname
+sub _ZONE {
+  my $zone = shift;
+  my $string = shift;
+  my $fr = shift || 'f';	# flag for forward/reverse order?  nb: ignored for IP
+
+  my $prefix = $zone->network->addr;	# Just In Case someone managed to slip in
+					# a funky subnet that had host bits set.
+
+  $string =~ s/,/./ if !$zone->{isv6};
+  $string =~ s/,/::/ if $zone->{isv6};
+
+#  if ($zone->{isv6} && ($zone->masklen % 4) != 0) {
+#    # grumpyfail, non-nibble zone.  shouldn't happen
+#    return;
+#  }
+
+    # Subbing ZONE in the host.  We need to properly ID the netblock range
+    # The subbed text should have "network IP with trailing zeros stripped" for
+    # blocks lined up on octet (for v4) or 16-bit (for v6) boundaries
+    # For blocks that do NOT line up on these boundaries, we tack on an extra "-0",
+    # then take the most significant octet or 16-bit chunk of the "broadcast" IP and
+    # append it after a double-dash
+    # ie:
+    # 8.0.0.0/6 -> 8.0.0.0 -> 11.255.255.255;  sub should be 8--11
+    # 10.0.0.0/12 -> 10.0.0.0 -> 10.0.0.0 -> 10.15.255.255;  sub should be 10-0--15
+    # 192.168.4.0/22 -> 192.168.4.0 -> 192.168.7.255;  sub should be 192-168-4--7
+    # 192.168.0.8/29 -> 192.168.0.8 -> 192.168.0.15;  sub should be 192-168-0-8--15
+    # Similar for v6
+    if (!$zone->{isv6}) {
+      my $bc = $zone->broadcast->addr;
+      if ($zone->masklen > 24) {
+      	$bc =~ s/^\d+\.\d+\.\d+\.//;
+      } elsif ($zone->masklen > 16) {
+	$prefix =~ s/\.0$//;
+      	$bc =~ s/^\d+\.\d+\.//;
+      } elsif ($zone->masklen > 8) {
+      	$bc =~ s/^\d+\.//;
+	$prefix =~ s/\.0\.0$//;
+      } else {
+	$prefix =~ s/\.0\.0\.0$//;
+      }
+      if ($zone->masklen % 8) {
+	$bc =~ s/(\.255)+$//;
+	$prefix .= "--$bc";	#"--".zone->masklen;	# use range or mask length?
+      }
+    } else {
+      if (($zone->masklen % 16) != 0) {
+	# Strip trailing :0 off $prefix, and :ffff off the broadcast IP
+	# Strip the leading 16-bit chunks off the front of the broadcast IP
+	# Append the remaining 16-bit chunk to the prefix after "--"
+	my $bc = $zone->broadcast->addr;
+	for (my $i=0; $i<(7-int($zone->masklen / 16)); $i++) {
+	  $prefix =~ s/:0$//;
+	  $bc =~ s/:ffff$//;
+	}
+	$bc =~ s/^([a-f0-9]+:)+//;
+	$prefix .= "--$bc";
+      } else {
+	# Strip off :0 from the end until we reach the netblock length.
+	for (my $i=0; $i<(8-$zone->masklen / 16); $i++) {
+	  $prefix =~ s/:0$//;
+	}
+      }
+    }
+
+  # Replace . and : with -
+  # If flagged for reverse-order, split on . or :, reverse, and join with -
+    if ($fr eq 'f') {
+      $prefix =~ s/[:.]+/-/g;
+    } else {
+      $prefix = join('-', reverse(split(/[:.]/, $prefix)));
+    }
+    $string =~ s/ZONE/$prefix/;
+#  }
+  return $string;
+} # done _ZONE
 
 
@@ -1288,57 +1371,25 @@
       $host =~ s/ADMINDOMAIN/$config{domain}/g;
 
-## tmp
-sub _ZONE {
-  my $zone = shift;
-  my $string = shift;
-  my $t1 = shift;	# flag for IP/network or hostname
-  my $t2 = shift || 'f';	# flag for forward/reverse order?  nb: ignored for IP
-
-  my $prefix = $zone->network->addr;	# Just In Case someone managed to slip in
-					# a funky subnet that had host bits set.
-  $prefix =~ s/(:0)+$/::/;
-  $prefix =~ s/0$//;
-
-  if ($t1 eq 'net') {
-    $string =~ s/ZONE[:.]+/$prefix/;
-  } else {
-    $prefix =~ s/[:.]+$//;
-    if ($t2 eq 'f') {
-      $prefix =~ s/[:.]+/-/g;
-    } else {
-      $prefix = join('-', reverse(split(/[:.]/, $prefix)));
-    }
-    $string =~ s/ZONE/$prefix/;
-  }
-  return $string;
-}
-## tmp
-
-# Check the zone;  if it's v4 and smaller than a /24 (sub-octet), we need
-# to check any template IPs to make sure they're in range.
-##fixme: need similar check on v6, except we'll just grump at non-nibble boundaries
-# first-pass:  masklen must be divisible by 4
-if (!$zone->{isv6} && $zone->masklen > 24) {
-      my $net = $zone->network->addr;
-      my $bc = $zone->broadcast;
-      $net =~ s/^\d+\.\d+\.\d+\.//;
-      $bc =~ s/^\d+\.\d+\.\d+\.//;
-      my $tmp = $host;
-      $tmp =~ s/^ZONE\.//;
-      if ($net <= $tmp && $tmp <= $bc) {
-      # replace ZONE with actual netblock in IP/value
-	unless (my $tmpval = _ZONE($zone, $val, 'net')) {
-	  $warnstr .= "$val does not fit in $zone;  skipping\n";
+      # Check to make sure the IP stubs will fit in the zone.  Under most usage failures here should be rare.
+      # On failure, tack a note on to a warning string and continue without adding this record.
+      # While we're at it, we substitute $zone for ZONE in the value.
+      if ($val eq 'ZONE') {
+	$val = $zone->network;
+      } elsif ($val =~ /ZONE/) {
+	my $tmpval = $val;
+	$tmpval =~ s/ZONE//;
+	my $addr;
+	if (_ipparent($dbh, 'n', 'y', \$tmpval, $rdns_id, \$addr)) {
+	  $val = $addr->addr;
+	} else {
+	  $warnstr .= "Default record '$val $typemap{$type} $host' doesn't fit in $zone, skipping\n";
 	  next;
 	}
-      } else {
-	$warnstr .= "Default record '$val $typemap{$type} $host' doesn't fit in $zone, skipping\n";
       }
-}
+
+      # Substitute $zone for ZONE in the hostname.
+      $host = _ZONE($zone, $host);
 
 ##work
-# - replace ZONE in $val
-#      $val =~ s/DOMAIN/$domain/g;
-
       $sth_in->execute($host,$type,$val,$ttl);
       if ($typemap{$type} eq 'SOA') {
@@ -1356,4 +1407,5 @@
 		username => $userinfo{name}, entry =>
 		$logentry." $val', TTL $ttl"));
+#print $logentry." $val', TTL $ttl\n";
       }
     }
@@ -1363,6 +1415,7 @@
 	username => $userinfo{name}, entry => $warnstr))
 	if $warnstr;
-
+#print $warnstr;
     # once we get here, we should have suceeded.
+#die "horribly\n";
     $dbh->commit;
   }; # end eval
