chiark / gitweb /
Improvements.
authorijackson <ijackson>
Mon, 21 Jun 1999 17:23:41 +0000 (17:23 +0000)
committerijackson <ijackson>
Mon, 21 Jun 1999 17:23:41 +0000 (17:23 +0000)
.cvsignore
bcp5-registry.pl
config.pl
database.pl
template.html

index b8ed2a7e42428412bc10417319af5e28c7c3da49..9ddd1e0fd94702a5db4cc59811dc898143002e99 100644 (file)
@@ -1 +1,3 @@
 t.html
+list
+lockfile
index e9135825c025db167b2083e94bd96d8adf6637f0..309b9cbebded642daae33ea95bd8d70f538dd631 100755 (executable)
@@ -4,69 +4,309 @@ require "$ARGV[0]/config.pl";
 require 'database.pl';
 
 if ("$ARGV[1]" eq '--cgi') {
+    open DEBUG,"/dev/null" or die $!;
     require 'cgi-lib.pl';
     &ReadParse;
 } else {
-    foreach $x (@ARGV) {
-       $x =~ s/^(\w+)\=//;
-       $in{$1}= $x;
+    open DEBUG,">&STDERR" or die $!;
+    foreach $x (@ARGV[1..$#ARGV]) {
+       $x =~ m/^(\w+)\=/ or die "$x ?";
+       $in{$1}= $';
+       print DEBUG "$1 -> \"$'\"\n";
     }
 }
 
-@areas= split(/ /,'10.0.0.0/8 172.16.0.0/12 192.168.0.0/16');
-$rec_area= '172.16.0.0/12';
+@area_networks= qw(0a000000 ac100000 c0a80000);
+@area_prefixes= qw(8 12 16);
+$rec_areai= 1;
 
-$current_area= $rec_area;
-$view_area= '';
-$viewoverlap= '';
+$current_areai= $rec_areai;
+$list_areai= -1;
+$listoverlap= '';
 
 $intro= 0;
+$error= 0;
 $registernew= 0;
 $pick= 0;
 $details= 0;
 $fulldetails= 0;
-$created= 0;
-$updated= 0;
+$justcreated= 0;
+$justupdated= 0;
 $picked= 0;
-$viewingall= 0;
-$view= 1;
+$listingall= 0;
+$passwordsent= 0;
+$list= 0;
 $notfound= 0;
 $id= '';
 $name= '';
 $email= '';
-$emailhidechecked= 0;
+$emailhidechecked= '';
 $hiddenemail= 0;
-$viewingarea= length $view_area;
-$viewingoverlap= length $viewoverlap;
-
-if ($in{'dbid'}) {
-    database();
-    $id= $in{'dbid'};
-    if (!exists $db{$id}) {
-       $notfound= 1; 
-       $view= 0;
-   } else {
-       $details= 1;
-       getinfo();
-    }
+
+$listingarea= $list_areai>=0;
+$listingoverlap= length $listoverlap;
+
+open RAND,"/dev/urandom" or die $!;
+defined($now= time) or die $!;
+
+if (length $in{'register'}) {
+    
+    lock_database();
+    read_database();
+    
+    $id= randnybs(16);
+    $generation= 0;
+    $db{$id}= $ent= { };
+    $ent->{'created'}= $now;
+    $ent->{'changed'}= 0;
+    $email= $in{'email'};
+    set_entry();
+
+    $justcreated= 1;
+    show_entry();
+    finish();
+    
+} elsif (length $in{'mailpasswd'}) {
+
+    read_database();
+    get_entry();
+    send_password();
+
+    $passwordsent= 1;
+    finish();
+    
+} elsif (length $in{'view'}) {
+
+    read_database();
+    get_entry();
+    check_password();
+
+    $fulldetails= 1;
+    show_entry();
+    finish();
+    
+} elsif (length $in{'update'}) {
+    
+    lock_database();
+    get_entry();
+    check_password();
+    check_generation();
+
+    $ent->{'changed'}= $now;
+    $email= length($in{'email'}) ? $in{'email'} : $db{$id}->{'email'};
+    set_entry();
+
+    $justupdated= 1;
+    show_entry();
+    finish();
+    
+} elsif (length $in{'delete'}) {
+
+    lock_database();
+    get_entry();
+    check_password();
+    check_generation();
+    
+    delete $db{$id};
+    write_database();
+
+    $deleted= 1;
+    finish();
+
+} elsif (length $in{'pick'}) {
+
+    pick_net();
+    $picked= 1;
+    $pick= 1;
+    $list= 1;
+    finish();
+
+} elsif (length $in{'list'}) {
+
+    read_database();
+    list_database();
+    $list= 1;
+    finish();
+
+} elsif (length $in{'id'}) {
+
+    read_database();
+    get_entry();
+    $details= 1;
+    show_entry();
+    $list= 1;
+    $pick= 1;
+    finish();
+
 } else {
+
     $intro= 1;
-    $registernew= 1;
+    $list= 1;
     $pick= 1;
+    $registernew= 1;
+    finish();
+
+}
+
+sub set_entry () {
+    my $v, $b, @b, $val, $mask;
+    $name= $in{'name'};
+    foreach $v (qw(name email)) {
+       length $$v or finish_error("no$v");
+       finish_error("badchar") unless $$v =~ m/^[ -\176\240\376]+$/; $$v= $&;
+    }
+    $hiddenemail= !!length $in{'hiddenemail'};
+    $net= $in{'net'};
+print DEBUG "got $net\n";
+    $net =~ s,/(\d+)$,, or finish_error("badnet");
+print DEBUG "prefix $1\n";
+    $prefix= $1+0;  ($prefix >= 0 && $prefix <= 32) or finish_error("badnet");
+print DEBUG "prefix $1 $net\n";
+    $network= ''; @b= split(/\./,$net);
+    @b<=4 or finish_error("badnet");
+print DEBUG "big enough\n";
+    @b*8 >= $prefix or finish_error("badnet");
+    while (@b<4) { push @b,0; }
+print DEBUG "@b\n";
+    foreach $b (@b) {
+       $b>=0 && $b<=255 or finish_error("badnet");
+       $network .= sprintf("%02x",$b);
+    }
+print DEBUG "$network\n";
+    ($val,$mask) = net_valuemask($network,$prefix);
+printf DEBUG "%08x %08x %08x\n", $val,$mask,~$mask;
+    !($val & ~$mask) or finish_error("badnet");
+print DEBUG "ok\n";
+    $current_areai= find_areai($network,$prefix);
+print DEBUG "$current_areai\n";
+    $current_areai>=0 or finish_error("wrongnet");
+print DEBUG "ok\n";
+
+    foreach $k (qw(generation network prefix name email hiddenemail)) {
+       $ent->{$k}= $$k;
+    }
+
+    write_database();
 }
 
-open X, "template.html" or die $!;
-@x= <X>;
-close X or die $!;
+sub find_areai ($$) {
+    my ($network,$prefix) = @_;
+    my $i;
+    for ($i=0; $i<@area_networks; $i++) {
+       next unless net_subset($network,$prefix, $area_networks[$i],$area_prefixes[$i]);
+       return $i;
+    }
+    return -1;
+}
 
-$x[$#x] eq "\@\@\@eof:\@\@\@\n" or die $!;
-$#x--;
+sub net_subset ($$$$) {
+    my ($smln,$smlp, $bign,$bigp) = @_;
+    return 0 unless $smlp >= $bigp;
+    ($bigv,$bigm) = net_valuemask($bign,$bigp);
+    ($smlv,$smlm) = net_valuemask($bign,$bigp);
+    return 0 unless ($smlv & $bigm) == $bigv;
+    return 1;
+}
 
-$cl= 0;
-$level= -1;
-process(1);
+sub net_valuemask($$) {
+    my ($network,$prefix) = @_;
+    return (hex($network), (0xffffffff << (32-$prefix)));
+}
 
-close STDOUT or die $!;
+sub get_entry () {
+    length $in{'id'} or die;
+    $id= $in{'id'};
+    exists $db{$id} or finish_error('notfound');
+    $ent= $db{$id};
+}
+
+sub show_entry () {
+    my $k, $dk;
+    foreach $k (@db_fields) {
+       $$k= $ent->{$k};
+    }
+    foreach $k (qw(created changed)) {
+       $dk= "date$k";
+       $$dk= gmtime($$k)." GMT";
+    }
+    $net= display_net($network,$prefix);
+}
+
+sub list_database () {
+    my $t, $v, $k, $x;
+    $listing= '';
+    foreach $t (qw(all area overlap)) {
+       $listing= $t if length $in{"list$t"};
+    }
+    die unless $listing;
+    $v= "listing$listing"; $$v= 1;
+    &{"dblist_prep_$listing"}();
+    @kl= ();
+print DEBUG "ldb 1 @kl\n";
+    foreach $k (keys %db) {
+print DEBUG "ldb q $k\n";
+       next unless &{"dblist_cond_$listing"}($db{$k});
+       push @kl,$k;
+    }
+print DEBUG "ldb 2 @kl\n";
+    @kl= sort {
+       $x= $db{$a}->{'network'} cmp $db{$b}->{'network'}; return $x if $x;
+       $x= $db{$a}->{'prefix'} <=> $db{$b}->{'prefix'}; return $x if $x;
+       return -1 if $a eq 'picked' && $b ne 'picked';
+       return +1 if $b eq 'picked' && $a ne 'picked';;
+       $x= $db{$a}->{'name'} cmp $db{$b}->{'name'}; return $x if $x;
+       return $a cmp $b;
+    } @kl;
+print DEBUG "ldb 3 @kl\n";
+    $listingnonefound= @kl ? 0 : 1;
+print DEBUG "ldb end $listingnonefound\n";
+}
+
+sub check_generation () {
+    $ent->{'generation'} eq $ent->{'generation'} or finish_error('generation');
+}
+
+sub finish_error ($) {
+    my ($type) = @_;
+    my $t, $esel;
+    foreach $t (qw(noemail noname badnet wrongnet notfound generation badchar)) {
+       $esel= "error_$t";
+       $$esel= 0;
+    }
+    my $esel= "error_$type";
+    $$esel= 1;
+    $error= 1;
+    finish();
+}
+
+sub finish () {
+    open X, "template.html" or die $!;
+    @x= <X>;
+    close X or die $!;
+
+    $x[$#x] eq "\@\@\@eof:\@\@\@\n" or die $!;
+    $#x--;
+
+    $cl= 0;
+    $level= -1;
+    process(1);
+
+    close STDOUT or die $!;
+    exit 0;
+}
+
+sub display_net ($$) {
+    my ($network,$prefix) = @_;
+    return join('.', unpack("C4",pack("H8",$network)))."/".$prefix;
+}
+
+sub randnybs ($) {
+    my ($nybbles) = @_;
+    my $v;
+    my $bytes= $nybbles/2;
+    read(RAND,$v,$bytes) == $bytes or die $!;
+    return scalar unpack("H$nybbles",$v)
+}
 
 sub out ($) {
     print $_[0],"\n" or die $!;
@@ -123,18 +363,46 @@ sub getvar ($) {
     return $$vn;
 }
 
+sub dblist_prep_all { }
+sub dblist_cond_all { 1; }
+
 sub foreach_start_area { $area_i=0; }
-sub foreach_cond_area { return $area_i < @areas; }
+sub foreach_cond_area { return $area_i < @area_networks; }
 sub foreach_incr_area { $area_i++; }
 sub foreach_setvars_area {
-    $area= $areas[$area_i];
-    $area_recommended= $area eq $rec_area;
-    $area_pickchecked= $area eq $current_area ? 'checked' : '';
-    $area_viewing= $area eq $viewing_area;
-    out("<!-- setvars_area @areas $area_i $area -->");
+    $area_network= $area_networks[$area_i];
+    $area= display_net($area_network,$area_prefixes[$area_i]);
+    $area_recommended= $area_i==$rec_areai;
+    $area_pickchecked= $area_i==$current_areai ? 'checked' : '';
+    $area_listing= $area_i==$list_areai;
+#    out("<!-- setvars_area @area_networks $area_i $area -->");
+}
+
+%saniarray= ('<','lt', '>','gt', '&','amp', '"','quot');
+sub html_sani {
+    local ($in) = @_;
+    local ($out);
+    while ($in =~ m/[<>&"]/) {
+        $out.= $`. '&'. $saniarray{$&}. ';';
+        $in=$';
+    }
+    $out.= $in;
+    $out;
 }
 
-sub foreach_start_db { }
-sub foreach_cond_db { 0; }
-sub foreach_setvars_db { }
-sub foreach_incr_db { }
+sub foreach_start_db { $db_i=0; }
+sub foreach_cond_db { return $db_i < @kl; }
+sub foreach_incr_db { $db_i++; }
+sub foreach_setvars_db {
+    my $k, $ent;
+    $k= $kl[$db_i];
+    $ent= $db{$k};
+    if ($k eq 'picked') {
+       unset $db_id;
+    } else {
+       $db_id= $k;
+    }
+    $db_net= display_net($ent->{'network'}, $ent->{'prefix'});
+    $db_name= html_sani($ent->{'name'});
+    $db_email= $ent->{'hiddenemail'} ? "" : html_sani($ent->{'email'});
+}
index 2a16b3baf39da030d4e1de22d80fc9b1680ac9cf..1e723a238b128e593ac68bd8ab20ee96d12bbb72 100644 (file)
--- a/config.pl
+++ b/config.pl
@@ -3,3 +3,4 @@ $adminemail= 'ijackson+cam-bcp5@chiark.greenend.org.uk';
 $nameboxlen= 55;
 $emailboxlen= 55;
 $cgi= 'http://www.chiark.greenend.org.uk/ucgi/~ijackson/bcp5-registry';
+chdir("$ARGV[0]");
index a85cd6722641f536fac0334e36ff80d702d34e49..1d7b1f02ecf40fdc036a60aa734021c4e41ea31a 100644 (file)
@@ -1,5 +1,49 @@
 #
 
-sub database () { }
+@db_fields= qw(generation network prefix name email hiddenemail created changed);
+
+sub read_database () {
+print DEBUG "reading\n";
+    my @v,$id;
+    open DBF, "list" or die $!;
+    for (;;) {
+       $_= <DBF>;
+       length or die "$_ $!";
+       s/\n$//;
+       last if m/^\002/;
+       @v= split(/\001/,$_);
+       $id= shift @v;
+       length $id or die;
+       undef $v;
+       foreach $f (@db_fields) { $v->{$f}= shift(@v).''; }
+       $db{$id}= $v;
+    }
+    close DBF or die $!;
+    $db_read= 1;
+}
+
+sub write_database () {
+    my $k,$v;
+print DEBUG "writing\n";
+    die unless $ENV{'BCP5_REGISTRY_LOCKED'};
+    open DBF, ">list.new" or die $!;
+    while (($k,$v) = each %db) {
+       $str= "$k";
+       foreach $f (@db_fields) { $str.= "\1".$v->{$f}; }
+       print DBF $str,"\n" or die $!;
+    }
+    print DBF "\2\n" or die $!;
+    close DBF or die $!;
+    rename "list.new","list" or die $!;
+}
+
+sub lock_database () {
+print DEBUG "locking\n";
+    die if $db_read;
+    return if $ENV{'BCP5_REGISTRY_LOCKED'};
+    $ENV{'BCP5_REGISTRY_LOCKED'}= '1';
+    exec 'with-lock-ex','-w','lockfile',$0,@ARGV;
+    die $!;
+}
 
 1;
index 55f7048721e0c1f50afb5aa02b201a54378c4885..84e224dc33744bd7d5837c21d3f33ebd559f500c 100644 (file)
 @@@net@@@ picked
 @@@endif:@@@
 
+@@@if:passwordsent@@@
+password sent for @@@name@@@
+@@@endif:@@@
+
 @@@if:details@@@
 details of @@@name@@@
 @@@endif:@@@
 
-@@@if:created@@@
+@@@if:justcreated@@@
 registered @@@name@@@
 @@@endif:@@@
 
-@@@if:updated@@@
+@@@if:justupdated@@@
 updated @@@name@@@
 @@@endif:@@@
 
-@@@if:viewingall@@@
+@@@if:listingall@@@
 entire database
 @@@endif:@@@
 
-@@@if:viewingarea@@@
-subset for @@@viewarea@@@
+@@@if:listingarea@@@
+subset for @@@listarea@@@
 @@@endif:@@@
 
-@@@if:viewingoverlap@@@
-overlapping with @@@viewoverlap@@@
+@@@if:listingoverlap@@@
+overlapping with @@@listoverlap@@@
 @@@endif:@@@
 
-@@@if:notfound@@@
+@@@if:error@@@
+@@@if:error_notfound@@@
 entry not found
 @@@endif:@@@
+@@@ifnot:error_notfound@@@
+error
+@@@endif:@@@
+@@@endif:@@@
 
 </title>
 @@@endif:@@@
@@ -60,29 +69,34 @@ Random network picked: @@@net@@@
 Database entry details: @@@name@@@
 @@@endif:@@@
 
-@@@if:created@@@
+@@@if:justcreated@@@
 @@@name@@@ registered in database
 @@@endif:@@@
 
-@@@if:updated@@@
+@@@if:justupdated@@@
 Database entry updated: @@@name@@@
 @@@endif:@@@
 
-@@@if:viewingall@@@
+@@@if:listingall@@@
 Entire database listing
 @@@endif:@@@
 
-@@@if:viewingarea@@@
-Database subset listing for @@@viewarea@@@
+@@@if:listingarea@@@
+Database subset listing for @@@listarea@@@
 @@@endif:@@@
 
-@@@if:viewingoverlap@@@
-Database search, entries overlapping with @@@viewoverlap@@@
+@@@if:listingoverlap@@@
+Database search, entries overlapping with @@@listoverlap@@@
 @@@endif:@@@
 
-@@@if:notfound@@@
+@@@if:error@@@
+@@@if:error_notfound@@@
 Database entry not found
 @@@endif:@@@
+@@@ifnot:error_notfound@@@
+An error has occurred
+@@@endif:@@@
+@@@endif:@@@
 
 </h1>
 
@@ -113,6 +127,51 @@ by anyone else.
 @@@endif:@@@
 
 
+@@@if:error@@@
+
+@@@if:error_badnet@@@
+You entered a syntactically invalid CIDR-format network number.
+<p>
+IPv4 network numbers should be expressed as a dotted quad followed by
+a prefix length.  Each of the numbers in the dotted quad must be
+between 0 and 255.  The prefix length is separated from the dotted
+quad by a slash, and must be between 0 and 32.  None of the bits in
+the dotted quad beyond the prefix length must be set.
+@@@endif:@@@
+
+@@@if:error_wrongnet@@@
+The network number you specified does not lie wholly within the
+BCP5-allocated private-use address ranges.
+@@@endif:@@@
+
+@@@if:error_notfound@@@
+Sorry, the database entry cannot be found.  Perhaps the entry has been
+deleted or expired.
+<p>
+If you believe that this has happened to you in error, contact the
+registry administrator, @@@adminemail@@@, quoting identifier @@@id@@@.
+@@@endif:@@@
+
+@@@if:error_generation@@@
+Another modification has been made to the record.  Please use the
+`view' option to see the new values, before making any further
+changes.
+@@@endif:@@@
+
+@@@if:error_noemail@@@
+You must provide an email address.
+@@@endif:@@@
+
+@@@if:error_noname@@@
+You must provide a network name for the database.
+@@@endif:@@@
+
+@@@if:error_badchar@@@
+The name or email address you specified contains illegal character(s).
+@@@endif:@@@
+
+@@@endif:@@@
+
 @@@if:registernew@@@
 <h2>Register a network range you are using</h2>
 You may register an existing network range you are using in our
@@ -144,7 +203,7 @@ the entry.
 <h2>Entry details</h2>
 @@@endif:@@@
 
-@@@if:created@@@
+@@@if:justcreated@@@
 <h2>Entry created</h2>
 The database entry has been created, but will only persist for a short
 time unless you confirm it.  You have beeen sent an email requesting
@@ -153,13 +212,13 @@ confirmation, or return at a later date when you have received the
 email.
 @@@endif:@@@
 
-@@@if:updated@@@
+@@@if:justupdated@@@
 <h2>Entry updated/confirmed</h2>
 The database entry below has been updated/confirmed/renewed.
 @@@endif:@@@
 
 
-@@@if:registernew|details|fulldetails|created|updated|picked@@@
+@@@if:registernew|details|fulldetails|justcreated|justupdated|picked@@@
 
 <p>
 <form method="POST" action="@@@cgi@@@">
@@ -171,7 +230,7 @@ Network range:
 <input type=hidden name="net" value="@@@net@@@">@@@net@@@
 @@@endif:@@@
 @@@ifnot:picked@@@
-<input type=text name="net" size=20>
+<input type=text name="net" value="@@@net@@@" size=20>
 @@@endif:@@@
 <br>
 
@@ -188,50 +247,62 @@ New address:
 <input type=text name="email" size="@@@emailboxlen@@@" value="@@@email@@@">
 <br>
 
-<input type=checkbox name="hide" value="yes" @@@emailhidechecked@@@>
+<input type=checkbox name="hiddenemail" value="yes" @@@emailhidechecked@@@>
 Hide email address from public database.
 
 @@@if:registernew|picked@@@
 <input type=submit name="register" value="Register">
 @@@endif:@@@
 
-@@@if:details|fulldetails|created|updated@@@
+@@@if:details|fulldetails|justcreated|justupdated@@@
 <p>
 
 Entry created: @@@datecreated@@@<br>
-Last update: @@@datechanged@@@<br>
-Confirmed/renewed: @@@dateconfirmed@@@
+@@@if:changed@@@
+Last update/confirm: @@@datechanged@@@<br>
+@@@endif:@@@
+@@@ifnot:changed@@@
+Not yet confirmed.
+@@@endif:@@@
+<input type=hidden name="generation" value="@@@generation@@@">
 @@@endif:@@@
 
 @@@if:details@@@
-<p>
+<h3>Password request</h3>
 
 Use this to obtain your password.  Passwords expire after a while; if
 you do not have a recent notification of your password, you should
 request a current password: <br>
 <input type=submit name="mailpasswd" value="Mail password">
-<p>
 @@@endif:@@@
 
-@@@if:details|created@@@
+@@@if:details|fulldetails|justcreated|justupdated@@@
+<h3>Modify or manage existing entry</h3>
+@@@endif:@@@
+
+@@@if:details|justcreated@@@
 Using your password, you can update the details above (if you have
 changed them), confirm or renew your entry (to stop it expiring), and
 view the full details, including any hidden email address: <br>
-Password: <input type=text name="password" size="30">
-@@@endif:@@@
-
-@@@if:fulldetails|updated@@@
-<input type=hidden name="password" value="@@@password@@@">
-Password: supplied.
 @@@endif:@@@
 
-@@@if:details|created|updated@@@
-<input type=submit name="view" value="View full details."><br>
+@@@if:details|justcreated|justupdated@@@
+<input type=submit name="view" value="View full details.">
 @@@endif:@@@
 
-@@@if:details|fulldetails|created|updated@@@
+@@@if:details|fulldetails|justcreated|justupdated@@@
 <input type=submit name="update" value="Update/confirm/renew">
 <input type=submit name="delete" value="Delete">
+<br>
+@@@endif:@@@
+
+@@@if:details|justcreated@@@
+Password: <input type=text name="password" size="30">
+@@@endif:@@@
+
+@@@if:fulldetails|justupdated@@@
+<input type=hidden name="password" value="@@@password@@@">
+Password: supplied.
 @@@endif:@@@
 
 </form>
@@ -272,67 +343,59 @@ from
 @@@endif:@@@
 
 
-@@@if:notfound@@@
-Sorry, the database entry cannot be found.  Perhaps the entry has been
-deleted or expired.
-<p>
-
-If you believe that this has happened to you in error, contact the
-registry administrator, @@@adminemail@@@, quoting identifier @@@id@@@.
-
-@@@endif:@@@
-
-
-@@@if:view@@@
+@@@if:list@@@
 
 <h2>View database</h2>
 
 <form method="GET" action="@@@cgi@@@">
+<input type=hidden name="list" value="yes">
 
-@@@ifnot:viewingall@@@
+@@@ifnot:listingall@@@
 
-<input type=submit name="viewall" value="Entire database">
+<input type=submit name="listall" value="Entire database">
 
 @@@endif:@@@
 
 <h3>Entries allocated from</h3>
 
+<ul>
 @@@foreach:area@@@
 
-@@@ifnot:area_viewing@@@
-<input type=submit name="viewarea" value="@@@area@@@">
+<li>
+@@@ifnot:area_listing@@@
+<a href="@@@cgi@@@?listarea=@@@area@@@">@@@area@@@</A>
 @@@endif:@@@
-@@@if:area_viewing@@@
+@@@if:area_listing@@@
 @@@area@@@
 @@@endif:@@@
-<br>
 
 @@@endforeach:@@@
+</ul>
 
 @@@endif:@@@
 
-@@@if:view@@@
+@@@if:list@@@
 <h3>Entries overlapping with</h3>
 
-<input type=text name="with" value="@@@viewoverlap@@@" size="30">
-<input type=submit name="viewoverlap" value="Search">
+<input type=text name="with" value="@@@listoverlap@@@" size="30">
+<input type=submit name="listoverlap" value="Search">
 
 </form>
 @@@endif:@@@
 
-@@@if:viewingall|viewingoverlap|viewingarea@@@
+@@@if:listingall|listingarea|listingoverlap@@@
 
 <h2>Database</h2>
 
 <h3>
-@@@if:viewingall@@@
+@@@if:listingall@@@
 Entire database
 @@@endif:@@@
-@@@if:viewingoverlap@@@
-Entries which overlap with @@@viewoverlap@@@
+@@@if:listingoverlap@@@
+Entries which overlap with @@@listoverlap@@@
 @@@endif:@@@
-@@@if:viewingarea@@@
-Database for entries allocated from @@@viewarea@@@
+@@@if:listingarea@@@
+Database for entries allocated from @@@listarea@@@
 @@@endif:@@@
 </h3>
 
@@ -341,6 +404,8 @@ The range picked for you has been <em>emphasized</em> below.
 @@@endif:@@@
 <p>
 
+@@@ifnot:listingnonefound@@@
+
 You can get details about an existing entry by clicking on its address
 range; this can also be used to modify it.
 
@@ -348,7 +413,7 @@ range; this can also be used to modify it.
 <tr><td>Range <td>Name <td>Contact email
 </tr><br>
 @@@foreach:db@@@
-<tr><td><A href="@@@cgi@@@?dbid=@@@db_id@@@">@@@db_net@@@</A>
+<tr><td><A href="@@@cgi@@@?id=@@@db_id@@@">@@@db_net@@@</A>
 <td>@@@db_name@@@
 <td>@@@db_email@@@
 </tr><br>
@@ -357,6 +422,12 @@ range; this can also be used to modify it.
 
 @@@endif:@@@
 
+@@@if:listingnonefound@@@
+There are no matching entries in the database.
+@@@endif:@@@
+
+@@@endif:@@@
+
 </body>
 </html>
 @@@eof:@@@