Index: /trunk/DNSDB.pm
===================================================================
--- /trunk/DNSDB.pm	(revision 371)
+++ /trunk/DNSDB.pm	(revision 372)
@@ -4293,11 +4293,20 @@
 # of remaining data, allows up to 255 raw bytes
 
+  # Locations/views - worth including in the caching setup?
+  my $lochash = $dbh->selectall_hashref("SELECT location,iplist FROM locations", 'location');
+  foreach my $location (keys %$lochash) {
+    foreach my $ipprefix (split /,/, $lochash->{$location}{iplist}) {
+      print $datafile "%$location:$ipprefix\n";
+    }
+    print $datafile "%$location\n" if !$lochash->{$location}{iplist};
+  }
+
   # tracking hash so we don't double-export A+PTR or AAAA+PTR records.
   my %recflags;
 
   my $domsth = $dbh->prepare("SELECT domain_id,domain,status,changed FROM domains WHERE status=1");
-  my $recsth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id ".
+  my $recsth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location ".
 	"FROM records WHERE domain_id=? AND type < 65280");	# Just exclude all types relating to rDNS
-  my $zonesth = $dbh->prepare("UPDATE domains SET changed=0 WHERE domain_id=?");
+  my $zonesth = $dbh->prepare("UPDATE domains SET changed='n' WHERE domain_id=?");
   $domsth->execute();
   while (my ($domid,$dom,$domstat,$changed) = $domsth->fetchrow_array) {
@@ -4312,9 +4321,12 @@
     if ($changed || -s "$config{exportcache}/$dom" == 0) {
       $recsth->execute($domid);
-      while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid) = $recsth->fetchrow_array) {
+      while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid,$loc) = $recsth->fetchrow_array) {
 	next if $recflags{$recid};
-##fixme:  need to store location in the db, and retrieve it here.
-# temporarily hardcoded to empty so we can include it further down.
-	my $loc = '';
+
+	$loc = '' if !$loc;	# de-nullify - just in case
+##fixme:  handle case of record-with-location-that-doesn't-exist better.
+# note this currently fails safe (tested) - records with a location that
+# doesn't exist will not be sent to any client
+#	$loc = '' if !$lochash->{$loc};
 
 ##fixme:  record validity timestamp. tinydns supports fiddling with timestamps.
@@ -4349,4 +4361,5 @@
   my $revsth = $dbh->prepare("SELECT rdns_id,revnet,status,changed FROM revzones WHERE status=1 ".
 	"ORDER BY masklen(revnet) DESC");
+
 # For reasons unknown, we can't sanely UNION these statements.  Feh.
 # Supposedly it should work though (note last 3 lines):
@@ -4361,11 +4374,10 @@
 #and LIMIT can be attached to a subexpression if it is enclosed in parentheses. Without parentheses, these
 #clauses will be taken to apply to the result of the UNION, not to its right-hand input expression.)
-
-  my $soasth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id ".
+  my $soasth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location ".
 	"FROM records WHERE rdns_id=? AND type=6");
-  $recsth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id ".
+  $recsth = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl,record_id,location ".
 	"FROM records WHERE rdns_id=? AND not type=6 ".
 	"ORDER BY masklen(CAST(val AS inet)) DESC, CAST(val AS inet)");
-  $zonesth = $dbh->prepare("UPDATE revzones SET changed=0 WHERE rdns_id=?");
+  $zonesth = $dbh->prepare("UPDATE revzones SET changed='n' WHERE rdns_id=?");
   $revsth->execute();
   while (my ($revid,$revzone,$revstat,$changed) = $revsth->fetchrow_array) {
@@ -4384,12 +4396,15 @@
       my (@zsoa) = $soasth->fetchrow_array();
       _printrec_tiny($datafile,'y',\%recflags,$revzone,
-	$zsoa[0],$zsoa[1],$zsoa[2],$zsoa[3],$zsoa[4],$zsoa[5],$zsoa[6],'','');
+	$zsoa[0],$zsoa[1],$zsoa[2],$zsoa[3],$zsoa[4],$zsoa[5],$zsoa[6],$zsoa[8],'');
 
       $recsth->execute($revid);
-      while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid) = $recsth->fetchrow_array) {
+      while (my ($host,$type,$val,$dist,$weight,$port,$ttl,$recid,$loc) = $recsth->fetchrow_array) {
 	next if $recflags{$recid};
-##fixme:  need to store location in the db, and retrieve it here.
-# temporarily hardcoded to empty so we can include it further down.
-	my $loc = '';
+
+	$loc = '' if !$loc;	# de-nullify - just in case
+##fixme:  handle case of record-with-location-that-doesn't-exist better.
+# note this currently fails safe (tested) - records with a location that
+# doesn't exist will not be sent to any client
+#	$loc = '' if !$lochash->{$loc};
 
 ##fixme:  record validity timestamp. tinydns supports fiddling with timestamps.
@@ -4587,5 +4602,11 @@
       } elsif ($typemap{$type} eq 'CNAME') {
 
-	print $datafile "C$host:$val:$ttl:$stamp:$loc\n";
+	if ($revrec eq 'n') {
+	  print $datafile "C$host:$val:$ttl:$stamp:$loc\n";
+	} else {
+	  my $val2 = NetAddr::IP->new($val);
+	  print $datafile "C"._ZONE($val2, 'ZONE', 'r', '.').($val2->{isv6} ? '.ip6.arpa' : '.in-addr.arpa').
+		":$host:$ttl:$stamp:$loc\n";
+	}
 
       } elsif ($typemap{$type} eq 'SRV') {
Index: /trunk/dns-1.0-1.2.sql
===================================================================
--- /trunk/dns-1.0-1.2.sql	(revision 371)
+++ /trunk/dns-1.0-1.2.sql	(revision 372)
@@ -3,5 +3,5 @@
 -- need this before we add any other bits
 CREATE TABLE locations (
-    loc character varying (4) PRIMARY KEY,
+    location character varying (4) PRIMARY KEY,
     group_id integer NOT NULL DEFAULT 1,
     iplist text NOT NULL DEFAULT '',
Index: /trunk/templates/loclist.tmpl
===================================================================
--- /trunk/templates/loclist.tmpl	(revision 371)
+++ /trunk/templates/loclist.tmpl	(revision 372)
@@ -22,5 +22,4 @@
 <td class="rightthird"><TMPL_INCLUDE NAME="sbox.tmpl"></td>
 </tr>
-<tr><td colspan="3" align="center"><TMPL_INCLUDE NAME="lettsearch.tmpl"></td></tr>
 <TMPL_IF addloc>
 <tr><td colspan="3" align="right"><a href="dns.cgi?sid=<TMPL_VAR NAME=sid>&amp;page=loc">New Location/View</a></td></tr>
@@ -37,5 +36,5 @@
 <TMPL_LOOP name=loctable>
 <tr class="row<TMPL_IF __odd__>0<TMPL_ELSE>1</TMPL_IF>">
-	<td align="left"><TMPL_IF edloc><a href="dns.cgi?sid=<TMPL_VAR NAME=sid>&amp;page=location&amp;loc_action=edit&amp;loc=<TMPL_VAR NAME=loc>"><TMPL_VAR NAME=description></a><TMPL_ELSE><TMPL_VAR NAME=description></TMPL_IF></td>
+	<td align="left"><TMPL_IF edloc><a href="dns.cgi?sid=<TMPL_VAR NAME=sid>&amp;page=location&amp;loc_action=edit&amp;loc=<TMPL_VAR NAME=location>"><TMPL_VAR NAME=description></a><TMPL_ELSE><TMPL_VAR NAME=description></TMPL_IF></td>
 	<td><TMPL_VAR name=iplist></td>
 	<td><TMPL_VAR name=group_name></td>
Index: /trunk/tiny-import.pl
===================================================================
--- /trunk/tiny-import.pl	(revision 371)
+++ /trunk/tiny-import.pl	(revision 372)
@@ -68,6 +68,6 @@
   open FLAT, "<$flatfile";
 
-  our $recsth = $dbh->prepare("INSERT INTO records (domain_id,rdns_id,host,type,val,distance,weight,port,ttl) ".
-	" VALUES (?,?,?,?,?,?,?,?,?)");
+  our $recsth = $dbh->prepare("INSERT INTO records (domain_id,rdns_id,host,type,val,distance,weight,port,ttl,location) ".
+	" VALUES (?,?,?,?,?,?,?,?,?,?)");
 
   my %deleg;
@@ -77,4 +77,5 @@
     next if /^\s*$/;
     chomp;
+    s/\s*$//;
     recslurp($_);
   }
@@ -187,5 +188,5 @@
       my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($ip));
       if ($fparent && $rparent) {
-	$recsth->execute($fparent, $rparent, $host, 65280, $ip, 0, 0, 0, $ttl);
+	$recsth->execute($fparent, $rparent, $host, 65280, $ip, 0, 0, 0, $ttl, $loc);
       } else {
 	push @deferred, $rec unless $nodefer;
@@ -207,5 +208,5 @@
 	($code,$msg) = DNSDB::_zone2cidr($host);
 	my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
-	$recsth->execute(0, $rparent, $targ, 5, $msg->addr, 0, 0, 0, $ttl);
+	$recsth->execute(0, $rparent, $targ, 5, $msg->addr, 0, 0, 0, $ttl, $loc);
 
 ##fixme:  automagically convert manually maintained sub-/24 delegations
@@ -218,5 +219,5 @@
 	my $fparent = DNSDB::_hostparent($dbh, $host);
 	if ($fparent) {
-	  $recsth->execute($fparent, 0, $host, 5, $targ, 0, 0, 0, $ttl);
+	  $recsth->execute($fparent, 0, $host, 5, $targ, 0, 0, 0, $ttl, $loc);
 	} else {
 	  push @deferred, $rec unless $nodefer;
@@ -245,5 +246,5 @@
 #	if !$rparent;
 	if ($rparent) {
-	  $recsth->execute(0, $rparent, $ns, 2, $msg, 0, 0, 0, $ttl);
+	  $recsth->execute(0, $rparent, $ns, 2, $msg, 0, 0, 0, $ttl, $loc);
 	} else {
 	  push @deferred, $rec unless $nodefer;
@@ -252,6 +253,6 @@
 	my $fparent = DNSDB::_hostparent($dbh, $zone);
 	if ($fparent) {
-	  $recsth->execute($fparent, 0, $zone, 2, $ns, 0, 0, 0, $ttl);
-	  $recsth->execute($fparent, 0, $ns, 2, $ip, 0, 0, 0, $ttl) if $ip;
+	  $recsth->execute($fparent, 0, $zone, 2, $ns, 0, 0, 0, $ttl, $loc);
+	  $recsth->execute($fparent, 0, $ns, 2, $ip, 0, 0, 0, $ttl, $loc) if $ip;
 	} else {
 	  push @deferred, $rec unless $nodefer;
@@ -283,5 +284,5 @@
       }
       if ($rparent) {
-	$recsth->execute(0, $rparent, $host, 12, $msg->addr, 0, 0, 0, $ttl);
+	$recsth->execute(0, $rparent, $host, 12, $msg->addr, 0, 0, 0, $ttl, $loc);
       } else {
 	push @deferred, $rec unless $nodefer;
@@ -302,5 +303,5 @@
       my $domid = DNSDB::_hostparent($dbh, $host);
       if ($domid) {
-	$recsth->execute($domid, 0, $host, 1, $ip, 0, 0, 0, $ttl);
+	$recsth->execute($domid, 0, $host, 1, $ip, 0, 0, 0, $ttl, $loc);
       } else {
 	push @deferred, $rec unless $nodefer;
@@ -323,9 +324,9 @@
 	$dbh->do("INSERT INTO revzones (revnet,group_id,status) VALUES (?,1,1)", undef, ($msg));
 	my ($rdns) = $dbh->selectrow_array("SELECT currval('revzones_rdns_id_seq')");
-        $recsth->execute(0, $rdns, "$contact:$master", 6, "$refresh:$retry:$expire:$minttl", 0, 0, 0, $ttl);
+        $recsth->execute(0, $rdns, "$contact:$master", 6, "$refresh:$retry:$expire:$minttl", 0, 0, 0, $ttl, $loc);
       } else {
 	$dbh->do("INSERT INTO domains (domain,group_id,status) VALUES (?,1,1)", undef, ($zone));
 	my ($domid) = $dbh->selectrow_array("SELECT currval('domains_domain_id_seq')");
-        $recsth->execute($domid, 0, "$contact:$master", 6, "$refresh:$retry:$expire:$minttl", 0, 0, 0, $ttl);
+        $recsth->execute($domid, 0, "$contact:$master", 6, "$refresh:$retry:$expire:$minttl", 0, 0, 0, $ttl, $loc);
       }
 
@@ -350,6 +351,6 @@
       my $domid = DNSDB::_hostparent($dbh, $zone);
       if ($domid) {
-        $recsth->execute($domid, 0, $zone, 15, $host, $dist, 0, 0, $ttl);
-	$recsth->execute($domid, 0, $host, 1, $ip, 0, 0, 0, $ttl) if $ip;
+	$recsth->execute($domid, 0, $zone, 15, $host, $dist, 0, 0, $ttl, $loc);
+	$recsth->execute($domid, 0, $host, 1, $ip, 0, 0, 0, $ttl, $loc) if $ip;
       } else {
 	push @deferred, $rec unless $nodefer;
@@ -371,9 +372,9 @@
 	($code,$msg) = DNSDB::_zone2cidr($fqdn);
 	my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
-	$recsth->execute(0, $rparent, $rdata, 16, "$msg", 0, 0, 0, $ttl);
+	$recsth->execute(0, $rparent, $rdata, 16, "$msg", 0, 0, 0, $ttl, $loc);
       } else {
 	my $domid = DNSDB::_hostparent($dbh, $fqdn);
 	if ($domid) {
-	  $recsth->execute($domid, 0, $fqdn, 16, $rdata, 0, 0, 0, $ttl);
+	  $recsth->execute($domid, 0, $fqdn, 16, $rdata, 0, 0, 0, $ttl, $loc);
 	} else {
 	  push @deferred, $rec unless $nodefer;
@@ -402,7 +403,7 @@
 	  ($rdns) = $dbh->selectrow_array("SELECT currval('revzones_rdns_id_seq')");
 # this would probably make a lot more sense to do hostmaster.$config{admindomain}
-          $recsth->execute(0, $rdns, "hostmaster.$fqdn:$ns", 6, "16384:2048:1048576:2560", 0, 0, 0, "2560");
-	}
-	$recsth->execute(0, $rdns, $ns, 2, "$msg", 0, 0, 0, $ttl);
+          $recsth->execute(0, $rdns, "hostmaster.$fqdn:$ns", 6, "16384:2048:1048576:2560", 0, 0, 0, "2560", $loc);
+	}
+	$recsth->execute(0, $rdns, $ns, 2, "$msg", 0, 0, 0, $ttl, $loc);
 ##fixme:  (?)  implement full conversion of tinydns . records?
 # -> problem:  A record for NS must be added to the appropriate *forward* zone, not the reverse
@@ -420,8 +421,8 @@
 	  $dbh->do("INSERT INTO domains (domain,group_id,status) VALUES (?,1,1)", undef, ($fqdn));
 	  ($domid) = $dbh->selectrow_array("SELECT currval('domains_domain_id_seq')");
-          $recsth->execute($domid, 0, "hostmaster.$fqdn:$ns", 6, "16384:2048:1048576:2560", 0, 0, 0, "2560");
-	}
-	$recsth->execute($domid, 0, $fqdn, 2, $ns, 0, 0, 0, $ttl);
-	$recsth->execute($domid, 0, $ns, 1, $ip, 0, 0, 0, $ttl) if $ip;
+          $recsth->execute($domid, 0, "hostmaster.$fqdn:$ns", 6, "16384:2048:1048576:2560", 0, 0, 0, "2560", $loc);
+	}
+	$recsth->execute($domid, 0, $fqdn, 2, $ns, 0, 0, 0, $ttl, $loc);
+	$recsth->execute($domid, 0, $ns, 1, $ip, 0, 0, 0, $ttl, $loc) if $ip;
       }
 
@@ -429,4 +430,20 @@
     } elsif ($rec =~ /^\%/) {
       $cnt{VIEWS}++;
+
+      # unfortunate that we don't have a guaranteed way to get a description on these.  :/
+      my ($loc,$cnet) = split /:/, $rec, 2;
+      $loc =~ s/^\%//;
+      if (my ($iplist) = $dbh->selectrow_array("SELECT iplist FROM locations WHERE location = ?", undef, ($loc))) {
+	if ($cnet) {
+	  $iplist .= ",$cnet";
+	  $dbh->do("UPDATE locations SET iplist = ? WHERE location = ?", undef, ($iplist, $loc));
+	} else {
+	  # hmm.  spit out a warning?  if we already have entries for $loc, adding a null
+	  # entry will almost certainly Do The Wrong Thing(TM)
+	}
+      } else {
+	$cnet = '' if !$cnet;	# de-nullify
+	$dbh->do("INSERT INTO locations (location,iplist,description) VALUES (?,?,?)", undef, ($loc, $cnet, $loc));
+      }
 
     } elsif ($rec =~ /^:/) {
@@ -471,5 +488,5 @@
 	my $domid = DNSDB::_hostparent($dbh, $fqdn);
 	if ($domid) {
-	  $recsth->execute($domid, 0, $fqdn, 33, $target, $prio, $weight, $port, $ttl) if $domid;
+	  $recsth->execute($domid, 0, $fqdn, 33, $target, $prio, $weight, $port, $ttl, $loc) if $domid;
 	} else {
 	  push @deferred, $rec unless $nodefer;
@@ -488,5 +505,5 @@
 	my $fparent = DNSDB::_hostparent($dbh, $fqdn);
 	if ($fparent) {
-	  $recsth->execute($fparent, 0, $fqdn, 28, $val->addr, 0, 0, 0, $ttl);
+	  $recsth->execute($fparent, 0, $fqdn, 28, $val->addr, 0, 0, 0, $ttl, $loc);
 	} else {
 	  push @deferred, $rec unless $nodefer;
@@ -501,5 +518,5 @@
 	  my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
 	  if ($rparent) {
-	    $recsth->execute(0, $rparent, $txtstring, 16, "$msg", 0, 0, 0, $ttl);
+	    $recsth->execute(0, $rparent, $txtstring, 16, "$msg", 0, 0, 0, $ttl, $loc);
 	  } else {
 	    push @deferred, $rec unless $nodefer;
@@ -508,5 +525,5 @@
 	  my $domid = DNSDB::_hostparent($dbh, $fqdn);
 	  if ($domid) {
-	    $recsth->execute($domid, 0, $fqdn, 16, $txtstring, 0, 0, 0, $ttl);
+	    $recsth->execute($domid, 0, $fqdn, 16, $txtstring, 0, 0, 0, $ttl, $loc);
 	  } else {
 	    push @deferred, $rec unless $nodefer;
@@ -527,5 +544,5 @@
 	  my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
 	  if ($rparent) {
-	    $recsth->execute(0, $rparent, "$email $txtrec", 17, "$msg", 0, 0, 0, $ttl);
+	    $recsth->execute(0, $rparent, "$email $txtrec", 17, "$msg", 0, 0, 0, $ttl, $loc);
 	  } else {
 	    push @deferred, $rec unless $nodefer;
@@ -534,5 +551,5 @@
 	  my $domid = DNSDB::_hostparent($dbh, $fqdn);
 	  if ($domid) {
-	    $recsth->execute($domid, 0, $fqdn, 17, "$email $txtrec", 0, 0, 0, $ttl);
+	    $recsth->execute($domid, 0, $fqdn, 17, "$email $txtrec", 0, 0, 0, $ttl, $loc);
 	  } else {
 	    push @deferred, $rec unless $nodefer;
@@ -549,5 +566,5 @@
 	my $domid = DNSDB::_hostparent($dbh, $fqdn);
 	if ($domid) {
-	  $recsth->execute($domid, 0, $fqdn, 44, $sshfp, 0, 0, 0, $ttl);
+	  $recsth->execute($domid, 0, $fqdn, 44, $sshfp, 0, 0, 0, $ttl, $loc);
 	} else {
 	  push @deferred, $rec unless $nodefer;
