- Timestamp:
- 06/13/17 13:58:57 (8 years ago)
- Location:
- branches/stable
- Files:
-
- 22 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/stable
- Property svn:mergeinfo changed
/trunk merged: 722-724,727-749
- Property svn:mergeinfo changed
-
branches/stable/DNSDB.pm
r725 r756 3 3 ## 4 4 # $Id$ 5 # Copyright 2008-201 3Kris Deugau <kdeugau@deepnet.cx>5 # Copyright 2008-2016 Kris Deugau <kdeugau@deepnet.cx> 6 6 # 7 7 # This program is free software: you can redistribute it and/or modify … … 36 36 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); 37 37 38 $VERSION = "1. 2.5p2"; ##VERSION##38 $VERSION = "1.4.0"; ##VERSION## 39 39 @ISA = qw(Exporter); 40 40 @EXPORT_OK = qw( … … 146 146 domain => 'domain_id', 147 147 revzone => 'rdns_id', 148 record => 'record_id' 148 record => 'record_id', 149 149 ); 150 150 my %par_col = ( … … 456 456 # group_id, log entry 457 457 # and optionally one or more of: 458 # domain_id, rdns_id 458 # domain_id, rdns_id, logparent 459 459 # The %userdata hash provides the user ID, username, and fullname 460 # Returns the log entry ID, mainly for use in bulk operations to allow a "parent" log entry 461 # and a set of child entries (eg, domain add and the individual default-record-copy entries) 460 462 sub _log { 461 463 my $self = shift; … … 466 468 $args{rdns_id} = 0 if !$args{rdns_id}; 467 469 $args{domain_id} = 0 if !$args{domain_id}; 470 $args{logparent} = 0 if !$args{logparent}; 468 471 469 472 ##fixme: farm out the actual logging to different subs for file, syslog, internal, etc based on config 470 473 # if ($self->{log_channel} eq 'sql') { 471 $dbh->do("INSERT INTO log (domain_id,rdns_id,group_id,entry,user_id,email,name) VALUES (?,?,?,?,?,?,?)", 474 $dbh->do("INSERT INTO log (domain_id,rdns_id,group_id,logparent,entry,user_id,email,name) ". 475 "VALUES (?,?,?,?,?,?,?,?)", 472 476 undef, 473 ($args{domain_id}, $args{rdns_id}, $args{group_id}, $args{ entry},477 ($args{domain_id}, $args{rdns_id}, $args{group_id}, $args{logparent}, $args{entry}, 474 478 $self->{loguserid}, $self->{logusername}, $self->{logfullname}) ); 479 480 my ($log_id) = $dbh->selectrow_array("SELECT currval('log_log_id_seq')"); 481 return $log_id; 482 475 483 # } elsif ($self->{log_channel} eq 'file') { 476 484 # } elsif ($self->{log_channel} eq 'syslog') { … … 1655 1663 my ($c) = ($$tmpl =~ /(\%-?c)/); my $nld = ''; my $cld = ''; 1656 1664 $c = '' if !$c; 1665 my ($cn) = ($$tmpl =~ /(\%x)/); 1657 1666 my $skipgw = ($c =~ /\%-c/ ? 0 : 1); 1658 1667 my $ipkill = 0; 1668 1669 if ($cn) { 1670 # "natural n'th IP in the block" pattern 1671 $$tmpl =~ s/$cn/$ipindex+1/e; 1672 } 1659 1673 1660 1674 ##fixme: still have one edge case not handled well: … … 2368 2382 undef, ($domain, $defloc)); 2369 2383 2370 $self->_log(domain_id => $dom_id, group_id => $group,2384 my $logparent = $self->_log(domain_id => $dom_id, group_id => $group, 2371 2385 entry => "Added ".($state ? 'active' : 'inactive')." domain $domain"); 2372 2386 … … 2384 2398 my @tmp1 = split /:/, $host; 2385 2399 my @tmp2 = split /:/, $val; 2386 $self->_log(domain_id => $dom_id, group_id => $group, 2400 $self->_log(domain_id => $dom_id, group_id => $group, logparent => $logparent, 2387 2401 entry => "[new $domain] Added SOA record [contact $tmp1[0]] [master $tmp1[1]] ". 2388 2402 "[refresh $tmp2[0]] [retry $tmp2[1]] [expire $tmp2[2]] [minttl $tmp2[3]], TTL $ttl"); … … 2391 2405 $logentry .= " [distance $dist]" if $typemap{$type} eq 'MX'; 2392 2406 $logentry .= " [priority $dist] [weight $weight] [port $port]" if $typemap{$type} eq 'SRV'; 2393 $self->_log(domain_id => $dom_id, group_id => $group, 2407 $self->_log(domain_id => $dom_id, group_id => $group, logparent => $logparent, 2394 2408 entry => $logentry." $val', TTL $ttl"); 2395 2409 } … … 3439 3453 "WHERE group_id IN ($args{curgroup}".($args{childlist} ? ",$args{childlist}" : '').")". 3440 3454 ($args{startwith} ? " AND username ~* ?" : ''). 3441 ($args{filter} ? " AND username ~* ?" : ''); 3455 ($args{filter} ? " AND username ~* ?" : ''). 3456 " AND NOT type = 'R' "; 3442 3457 my ($count) = $dbh->selectrow_array($sql, undef, (@filterargs) ); 3443 3458 $errstr = $dbh->errstr if !$count; … … 3645 3660 $errstr = $DBI::errstr if !$uname; 3646 3661 3662 no warnings qw (uninitialized); 3647 3663 $fullformat =~ s/\%u/$uname/g; 3648 3664 $fullformat =~ s/\%f/$fname/g; … … 4810 4826 # Get a count of log entries 4811 4827 # Takes a database handle and a hash containing at least: 4812 # - Entity IDand entity type as the primary log "slice"4828 # - Entity identifier and entity type as the primary log "slice" 4813 4829 sub getLogCount { 4814 4830 my $self = shift; 4815 my $dbh = $self->{dbh}; 4816 4817 my %args = @_; 4818 4819 my @filterargs; 4820 ##fixme: which fields do we want to filter on? 4821 # push @filterargs, 4822 4823 $errstr = 'Missing primary parent ID and/or type'; 4824 # fail early if we don't have a "prime" ID to look for log entries for 4825 return if !$args{id}; 4826 4827 # or if the prime id type is missing or invalid 4828 return if !$args{logtype}; 4829 $args{logtype} = 'revzone' if $args{logtype} eq 'rdns'; # hack pthui 4830 $args{logtype} = 'domain' if $args{logtype} eq 'dom'; # hack pthui 4831 return if !grep /^$args{logtype}$/, ('group', 'domain', 'revzone', 'user'); 4832 4833 my $sql = "SELECT count(*) FROM log ". 4834 "WHERE $id_col{$args{logtype}}=?". 4835 ($args{filter} ? " AND entry ~* ?" : ''); 4836 my ($count) = $dbh->selectrow_array($sql, undef, ($args{id}, @filterargs) ); 4837 $errstr = $dbh->errstr if !$count; 4838 return $count; 4831 return $self->getLogEntries(@_, count => 1); 4839 4832 } # end getLogCount() 4840 4833 … … 4843 4836 # Get a list of log entries 4844 4837 # Takes arguments as with getLogCount() above, plus optional: 4838 # - "count" flag 4839 # OR 4845 4840 # - sort field 4846 4841 # - sort order … … 4854 4849 my @filterargs; 4855 4850 4856 # fail early if we don't have a "prime" ID to look for log entries for 4857 return if !$args{id}; 4858 4859 # or if the prime id type is missing or invalid 4851 # fail if the prime id type is missing or invalid 4852 $errstr = "Missing primary log slice type"; 4860 4853 return if !$args{logtype}; 4861 4854 $args{logtype} = 'revzone' if $args{logtype} eq 'rdns'; # hack pthui 4862 4855 $args{logtype} = 'domain' if $args{logtype} eq 'dom'; # hack pthui 4856 $errstr = "Invalid primary log slice type"; 4863 4857 return if !grep /^$args{logtype}$/, ('group', 'domain', 'revzone', 'user'); 4858 4859 # fail if we don't have a prime ID to look for log entries for 4860 $errstr = "Missing ID for primary log slice"; 4861 return if !($args{id} || $args{fname}); 4864 4862 4865 4863 # Sorting defaults … … 4868 4866 $args{offset} = 0 if !$args{offset} || $args{offset} !~ /^(?:all|\d+)$/; 4869 4867 4870 my %sortmap = (fname => 'name', username => 'email', entry => 'entry', stamp => 'stamp'); 4868 my %sortmap = (fname => 'name', username => 'email', entry => 'entry', stamp => 'stamp', 4869 revzone => 'revnet', domain => 'domain'); 4871 4870 $args{sortby} = $sortmap{$args{sortby}}; 4872 4871 4873 my $sql = "SELECT user_id AS userid, email AS useremail, name AS userfname, entry AS logentry, ". 4874 "date_trunc('second',stamp) AS logtime ". 4875 "FROM log ". 4876 "WHERE $id_col{$args{logtype}}=?". 4877 ($args{filter} ? " AND entry ~* ?" : ''). 4878 " ORDER BY $args{sortby} $args{sortorder}, log_id $args{sortorder}". 4872 push @filterargs, $args{filter} if $args{filter}; 4873 my $sql; 4874 if ($args{count}) { 4875 $sql = "SELECT count(*) FROM log l "; 4876 } else { 4877 $sql = "SELECT l.log_id AS logparent, l.user_id AS userid, l.name AS userfname, d.domain, l.domain_id, ". 4878 "r.revnet AS revzone, ". 4879 "l.rdns_id, l.entry AS logentry, date_trunc('second',l.stamp) AS logtime ". 4880 "FROM log l ". 4881 "LEFT JOIN domains d ON l.domain_id = d.domain_id ". 4882 "LEFT JOIN revzones r ON l.rdns_id = r.rdns_id "; 4883 } 4884 4885 # decide which ID argument to use. Only use the "full name" if no normal ID is present 4886 my $idarg; 4887 if ($args{id}) { 4888 $sql .= "WHERE l.$id_col{$args{logtype}} = ? "; 4889 $idarg = $args{id}; 4890 } else { 4891 $sql .= "WHERE l.name = ? "; 4892 $idarg = $args{fname}; 4893 } 4894 4895 # trim log "subentries" - we'll figure out where to stash these later 4896 $sql .= " AND logparent = 0"; 4897 4898 # add the entry filter, if any 4899 $sql .= ($args{filter} ? " AND entry ~* ?" : ''); 4900 4901 # Limit scope based on group. Mainly useful for ltype==user, so subgroup 4902 # users can see what the deities in parent groups have done to their domains. 4903 if ($args{group} != 1) { 4904 my @grouplist; 4905 $self->getChildren($args{group}, \@grouplist); 4906 my $groupset = join(',', $args{group}, @grouplist); 4907 $sql .= " AND l.group_id IN ($groupset)"; 4908 } 4909 4910 if ($args{count}) { 4911 my ($count) = $dbh->selectrow_array($sql, undef, ($idarg, @filterargs) ); 4912 $errstr = $dbh->errstr if !$count; 4913 return $count; 4914 } else { 4915 $sql .= " ORDER BY $args{sortby} $args{sortorder}, log_id $args{sortorder}". 4879 4916 ($args{offset} eq 'all' ? '' : " LIMIT $self->{perpage} OFFSET ".$args{offset}*$self->{perpage}); 4880 my $loglist = $dbh->selectall_arrayref($sql, { Slice => {} }, ($args{id}, @filterargs) ); 4881 $errstr = $dbh->errstr if !$loglist; 4882 return $loglist; 4917 my @loglist; 4918 my $sth = $dbh->prepare($sql); 4919 my $logchild = $dbh->prepare("SELECT entry FROM log WHERE logparent = ? ORDER BY log_id"); 4920 $sth->execute($idarg, @filterargs); 4921 while (my $row = $sth->fetchrow_hashref) { 4922 $logchild->execute($row->{logparent}); 4923 my $childlist = $logchild->fetchall_arrayref({}); 4924 $row->{childentries} = $childlist; 4925 push @loglist, $row; 4926 } 4927 return \@loglist; 4928 } 4929 4930 # Your llama is on fire 4931 4883 4932 } # end getLogEntries() 4933 4934 4935 # a collection of joins for the record search 4936 our $recsearchsqlbase = q( 4937 FROM records r 4938 LEFT JOIN domains d ON r.domain_id = d.domain_id 4939 LEFT JOIN groups g1 ON d.group_id = g1.group_id 4940 LEFT JOIN revzones z ON r.rdns_id = z.rdns_id 4941 LEFT JOIN groups g2 on z.group_id = g2.group_id 4942 JOIN rectypes t ON r.type = t.val 4943 LEFT JOIN locations l ON r.location = l.location 4944 WHERE r.type <> 6 AND (r.host ~* ? OR r.val ~* ?) 4945 ); 4946 4947 4948 ## DNSDB::recSearchCount() 4949 # Get a total count for a global record search 4950 # Takes a hash with the search string and the login group of the user 4951 sub recSearchCount { 4952 my $self = shift; 4953 my $dbh = $self->{dbh}; 4954 my %args = @_; 4955 4956 my $sql = "SELECT count(*)".$recsearchsqlbase; 4957 4958 # Limit scope based on group 4959 if ($args{group} != 1) { 4960 my @grouplist; 4961 $self->getChildren($args{group}, \@grouplist); 4962 my $groupset = join(',', $args{group}, @grouplist); 4963 # oh my aching HEAD. there has to be a better way to do conditions on joined tables... 4964 $sql .= "AND ( 4965 (g1.group_id IN ($groupset) AND g2.group_id IN ($groupset)) OR 4966 (g1.group_id IN ($groupset) AND g2.group_id IS NULL) OR 4967 (g1.group_id IS NULL AND g2.group_id IN ($groupset)) 4968 ) 4969 "; 4970 } 4971 4972 my $count = $dbh->selectrow_array($sql, undef, $args{searchfor}, $args{searchfor}); 4973 $errstr = $dbh->errstr if !$count; 4974 return $count; 4975 4976 } # end recSearchCount() 4977 4978 4979 ## DNSDB::recSearch() 4980 # Find records matching the search string 4981 # Takes a hash with the search string, login group of the user, pagination offset, sort field, 4982 # and sort direction 4983 # Returns a reference to a list of hashrefs 4984 sub recSearch { 4985 my $self = shift; 4986 my $dbh = $self->{dbh}; 4987 my %args = @_; 4988 4989 my $sql = q(SELECT 4990 r.domain_id, d.domain, g1.group_name AS domgroup, 4991 r.rdns_id, z.revnet AS revzone, g2.group_name AS revgroup, 4992 r.host, t.name AS rectype, r.val, l.description AS location, r.record_id). 4993 $recsearchsqlbase; 4994 4995 # Limit scope based on group 4996 if ($args{group} != 1) { 4997 my @grouplist; 4998 $self->getChildren($args{group}, \@grouplist); 4999 my $groupset = join(',', $args{group}, @grouplist); 5000 # oh my aching HEAD. there has to be a better way to do conditions on joined tables... 5001 $sql .= "AND ( 5002 (g1.group_id IN ($groupset) AND g2.group_id IN ($groupset)) OR 5003 (g1.group_id IN ($groupset) AND g2.group_id IS NULL) OR 5004 (g1.group_id IS NULL AND g2.group_id IN ($groupset)) 5005 ) 5006 "; 5007 } 5008 5009 # mixed tables means this isn't a simple prefix like the regular record list filter. :/ 5010 my %sortmap = ( 5011 domain => 'd.domain', 5012 revzone => 'z.revnet', 5013 host => 'r.host', 5014 type => 't.name', 5015 val => 'inetlazy(r.val)', 5016 location => 'r.location', 5017 ); 5018 5019 # Sorting defaults 5020 $args{sortorder} = 'ASC' if !$args{sortorder} || !grep /^$args{sortorder}$/, ('ASC','DESC'); 5021 $args{sortby} = 'r.host' if !$args{sortby} || $args{sortby} !~ /^[\w_.]+$/; 5022 $args{offset} = 0 if !$args{offset} || $args{offset} !~ /^(?:all|\d+)$/; 5023 5024 $args{sortby} = $sortmap{$args{sortby}} if $args{sortby} !~ /\./; 5025 5026 # Add sort and offset to SQL 5027 $sql .= "ORDER BY $args{sortby} $args{sortorder},record_id ASC\n"; 5028 $sql .= ($args{offset} eq 'all' ? '' : "LIMIT $self->{perpage} OFFSET ".$args{offset}*$self->{perpage}); 5029 5030 ##fixme: should probably sent the warning somewhere else 5031 my $ret = $dbh->selectall_arrayref($sql, { Slice => {} }, $args{searchfor}, $args{searchfor}) 5032 or warn $dbh->errstr; 5033 return $ret; 5034 5035 } # end recSearch() 4884 5036 4885 5037 … … 5379 5531 eval { 5380 5532 5533 my $logparent; 5534 5381 5535 if ($rev eq 'n') { 5382 5536 ##fixme: serial … … 5386 5540 ($zone_id) = $dbh->selectrow_array("SELECT currval('domains_domain_id_seq')"); 5387 5541 $domain_id = $zone_id; 5388 $ self->_log(group_id => $group, domain_id => $domain_id,5542 $logparent = $self->_log(group_id => $group, domain_id => $domain_id, 5389 5543 entry => "[Added ".($args{status} ? 'active' : 'inactive')." domain $zone via AXFR]"); 5390 5544 } else { … … 5395 5549 ($zone_id) = $dbh->selectrow_array("SELECT currval('revzones_rdns_id_seq')"); 5396 5550 $rdns_id = $zone_id; 5397 $ self->_log(group_id => $group, rdns_id => $rdns_id,5551 $logparent = $self->_log(group_id => $group, rdns_id => $rdns_id, 5398 5552 entry => "[Added ".($args{status} ? 'active' : 'inactive')." reverse zone $cidr via AXFR]"); 5399 5553 } … … 5647 5801 $logentry .= " ".($rev eq 'y' ? $host : $val)."', TTL $ttl"; 5648 5802 } 5649 $self->_log(group_id => $group, domain_id => $domain_id, rdns_id => $rdns_id, entry => $logentry); 5803 $self->_log(group_id => $group, domain_id => $domain_id, rdns_id => $rdns_id, 5804 logparent => $logparent, entry => $logentry); 5650 5805 5651 5806 } # while axfr_next -
branches/stable/Makefile
r725 r756 3 3 4 4 PKGNAME=dnsadmin 5 VERSION=1. 2.65 VERSION=1.4.0 6 6 RELEASE=1 7 7 … … 46 46 INSTALL COPYING TODO Makefile dnsadmin.spec \ 47 47 \ 48 dns.sql dns-1.0-1.2.sql dns-1.2.3-1.2.4.sql dns-upd-1.2.6.sql \48 dns.sql dns-1.0-1.2.sql dns-1.2.3-1.2.4.sql dns-upd-1.2.6.sql dns-upd-1.4.0.sql \ 49 49 \ 50 50 $(SCRIPTS) $(MODULES) \ … … 85 85 templates/msgblock.tmpl templates/newdomain.tmpl templates/newgrp.tmpl templates/newrevzone.tmpl \ 86 86 templates/permlist.tmpl templates/pgcount.tmpl templates/reclist.tmpl templates/record.tmpl \ 87 templates/recsearch.tmpl \ 87 88 templates/revzones.tmpl templates/sbox.tmpl templates/soadata.tmpl templates/template.tmpl \ 88 89 templates/textrecs.tmpl templates/updatesoa.tmpl templates/useradmin.tmpl templates/user.tmpl \ -
branches/stable/compact-recs.pl
r649 r756 4 4 ## 5 5 # $Id$ 6 # Copyright 2013 Kris Deugau <kdeugau@deepnet.cx>6 # Copyright 2013,2014 Kris Deugau <kdeugau@deepnet.cx> 7 7 # 8 8 # This program is free software: you can redistribute it and/or modify -
branches/stable/dns-rpc.cgi
r725 r756 3 3 ## 4 4 # $Id$ 5 # Copyright 2012 ,2013Kris Deugau <kdeugau@deepnet.cx>5 # Copyright 2012-2016 Kris Deugau <kdeugau@deepnet.cx> 6 6 # 7 7 # This program is free software: you can redistribute it and/or modify … … 115 115 116 116 my $reqcnt = 0; 117 118 while (FCGI::accept >= 0) { 117 my $req = FCGI::Request(); 118 119 while ($req->Accept() >= 0) { 119 120 my $res = Frontier::Responder->new( 120 121 methods => $methods … … 200 201 my $modflag = 0; 201 202 # order by most common change. host should be first, due to rDNS RPC calls 202 for my $field qw(host type val) {203 for my $field (qw(host type val)) { 203 204 return 1 if ( 204 205 defined($newrec->{$field}) && -
branches/stable/dns.cgi
r725 r756 3 3 ## 4 4 # $Id$ 5 # Copyright 2008-201 3Kris Deugau <kdeugau@deepnet.cx>5 # Copyright 2008-2016 Kris Deugau <kdeugau@deepnet.cx> 6 6 # 7 7 # This program is free software: you can redistribute it and/or modify … … 120 120 $webvar{startwith} =~ s/^(0-9|[a-z]).*/$1/ if $webvar{startwith}; 121 121 # not much call for chars not allowed in domain names 122 $webvar{filter} =~ s/[^a-zA-Z0-9_.:\@ -]//g if $webvar{filter};122 $webvar{filter} =~ s/[^a-zA-Z0-9_.:\@%-]//g if $webvar{filter}; 123 123 ## only set 'y' if box is checked, no other values legal 124 124 ## however, see https://secure.deepnet.cx/trac/dnsadmin/ticket/31 … … 138 138 # @#$%@%@#% XHTML - & in a URL must be escaped. >:( 139 139 my $uri_self = $ENV{REQUEST_URI}; 140 $uri_self = "/dns.cgi" if !$uri_self || $uri_self eq '/'; 140 141 $uri_self =~ s/\&([a-z])/\&\;$1/g; 141 142 … … 455 456 456 457 if ($code eq 'OK') { 458 $webvar{domain} = lc($webvar{domain}) if $dnsdb->{lowercase}; 457 459 $dnsdb->mailNotify("New ".($webvar{makeactive} eq 'on' ? 'Active' : 'Inactive')." Domain Created", 458 460 ($webvar{makeactive} eq 'on' ? 'Active' : 'Inactive').qq( domain "$webvar{domain}" added by ). … … 1795 1797 ##fixme: where should we call this from? 1796 1798 $id = $webvar{id}; 1797 if (!check_scope(id => $id, type => 'user')) { 1798 $page->param(errmsg => "You are not permitted to view log entries for the requested user"); 1799 goto DONELOG; 1800 } 1801 $page->param(logfor => 'user '.$dnsdb->userFullName($id)); 1799 ##fixme: don't include username on out-of-scope users 1800 $page->param(logfor => 'user '.($id ? $dnsdb->userFullName($id) : $webvar{fname})); 1802 1801 } elsif ($webvar{ltype} && $webvar{ltype} eq 'dom') { 1803 1802 $id = $webvar{id}; … … 1821 1820 } 1822 1821 $webvar{ltype} = 'group' if !$webvar{ltype}; 1823 my $lcount = $dnsdb->getLogCount(id => $id, logtype => $webvar{ltype}) or push @debugbits, $dnsdb->errstr; 1822 1823 # Done here since we want to allow more arbitrary blobs in the log filter 1824 if (defined($webvar{logfilter})) { 1825 $session->param('logfilter', '') if !$session->param('logfilter'); 1826 if ($webvar{logfilter} ne $session->param('logfilter')) { 1827 $uri_self =~ s/\&offset=[^&]//; 1828 $offset = 0; 1829 } 1830 $session->param('logfilter', $webvar{logfilter}) 1831 } 1832 my $logfilter = $session->param('logfilter'); 1833 $filter = $logfilter; 1834 $page->param(logfilter => $logfilter); 1835 1836 my $lcount = $dnsdb->getLogCount(id => $id, group => $logingroup, fname => $webvar{fname}, 1837 logtype => $webvar{ltype}, filter => $logfilter); 1838 if (!$lcount) { 1839 $page->param(errmsg => $dnsdb->errstr); 1840 $lcount = 0; 1841 } 1824 1842 1825 1843 $page->param(id => $id); … … 1840 1858 1841 1859 # Set up the column headings with the sort info 1842 my @cols = ('fname','username','entry','stamp'); 1843 my %colnames = (fname => 'Name', username => 'Username', entry => 'Log Entry', stamp => 'Date/Time'); 1860 my @cols = ('fname','domain','revzone','entry','stamp'); 1861 my %colnames = (fname => 'Name', domain => 'Forward zone', revzone => 'Reverse zone', 1862 entry => 'Log Entry', stamp => 'Date/Time'); 1844 1863 fill_colheads($sortby, $sortorder, \@cols, \%colnames); 1845 1864 1846 1865 ##fixme: increase per-page limit or use separate limit for log? some ops give *lots* of entries... 1847 my $logentries = $dnsdb->getLogEntries(id => $id, logtype => $webvar{ltype}, 1848 offset => $webvar{offset}, sortby => $sortby, sortorder => $sortorder); 1849 $page->param(logentries => $logentries); 1866 my $logentries = $dnsdb->getLogEntries(id => $id, group => $logingroup, fname => $webvar{fname}, 1867 logtype => $webvar{ltype}, 1868 offset => $webvar{offset}, sortby => $sortby, sortorder => $sortorder, filter => $logfilter); 1869 if (!$logentries) { 1870 $page->param(errmsg => $dnsdb->errstr); 1871 } else { 1872 # undef $logentries is inexplicably puking instead of showing "no entries found", 1873 # like all the rest of the methods that return a list the same way. idunno... 1874 $page->param(logentries => $logentries); 1875 } 1850 1876 1851 1877 ##fixme: 1852 # - filtering1853 # - show reverse zone column?1854 1878 # - on log record creation, bundle "parented" log actions (eg, "AXFR record blah for domain foo", 1855 1879 # or "Add record bar for new domain baz") into one entry (eg, "AXFR domain foo", "Add domain baz")? … … 1858 1882 # scope check fail target 1859 1883 DONELOG: ; 1884 1885 } elsif ($webvar{page} eq 'recsearch') { 1886 1887 # we do this for the domain and record list filter/search - it should be extremely rare to 1888 # need to search on characters outside this set until we get into IDNs 1889 # note this is a little larger due to template records 1890 $webvar{searchfor} =~ s/[^a-zA-Z0-9_.:\@%-]//g if $webvar{searchfor}; 1891 1892 # save the search in the session, same as the "filter" in various other lists... 1893 if (defined($webvar{searchfor})) { 1894 if ($session->param('recsearch') && $webvar{searchfor} ne $session->param('recsearch')) { 1895 $uri_self =~ s/\&offset=[^&]//; 1896 $offset = 0; 1897 } 1898 $session->param(recsearch => $webvar{searchfor}); 1899 } 1900 my $searchfor = $session->param('recsearch'); 1901 1902 $sortby = 'host'; 1903 $session->param($webvar{page}.'sortby', $webvar{sortby}) if $webvar{sortby}; 1904 $session->param($webvar{page}.'order', $webvar{order}) if $webvar{order}; 1905 $sortby = $session->param($webvar{page}.'sortby') if $session->param($webvar{page}.'sortby'); 1906 $sortorder = $session->param($webvar{page}.'order') if $session->param($webvar{page}.'order'); 1907 1908 # some magic to label and linkify the column headers for sorting 1909 my @cols = ('domain','revzone','host','type','val'); 1910 my %colheads = (domain => "Domain (Group)", revzone => "Reverse zone (Group)", host => "Host", 1911 type => "Type", val => "IP/value"); 1912 # only users allowed to see location/view data get this column 1913 if ($permissions{admin} || $permissions{location_view}) { 1914 $colheads{location} = "Location"; 1915 push @cols, 'location'; 1916 } 1917 fill_colheads($sortby, $sortorder, \@cols, \%colheads); 1918 1919 # pgcount.tmpl 1920 my $count = $dnsdb->recSearchCount(searchfor => $searchfor, group => $logingroup); 1921 fill_pgcount($count, "records"); 1922 fill_fpnla($count); 1923 1924 # and a bit for fpnla.tmpl 1925 $page->param(curpage => $webvar{page}); 1926 1927 $page->param(searchfor => $searchfor); 1928 my $recset = $dnsdb->recSearch(searchfor => $searchfor, group => $logingroup, offset => $webvar{offset}, 1929 sortby => $sortby, sortorder => $sortorder); 1930 $page->param(searchresults => $recset); 1860 1931 1861 1932 } # end $webvar{page} dance -
branches/stable/dns.sql
r725 r756 31 31 32 32 COPY misc (misc_id, key, value) FROM stdin; 33 1 dbversion 1. 2.633 1 dbversion 1.4.0 34 34 \. 35 35 … … 136 136 entry text, 137 137 stamp timestamp with time zone DEFAULT now(), 138 rdns_id integer 139 ); 138 rdns_id integer, 139 logparent integer NOT NULL DEFAULT 0 140 ); 141 CREATE INDEX log_domain_id_index ON log(domain_id); 142 CREATE INDEX log_user_id_index ON log(user_id); 143 CREATE INDEX log_group_id_index ON log(group_id); 144 CREATE INDEX log_rdns_id_index ON log(rdns_id); 140 145 141 146 CREATE TABLE permissions ( -
branches/stable/mergerecs
r690 r756 3 3 ## 4 4 # $Id$ 5 # Copyright 2014 Kris Deugau <kdeugau@deepnet.cx>5 # Copyright 2014,2016 Kris Deugau <kdeugau@deepnet.cx> 6 6 # 7 7 # This program is free software: you can redistribute it and/or modify … … 36 36 sub usage { 37 37 die qq(usage: mergerecs zone [domain] [--detail] 38 zone The zone to walk for PTR records to try to merge. 39 domain Optionally restrict record merges to a specified domain as well. 38 zone The primary zone to walk for records to try to merge. May be either 39 a reverse zone or a domain. 40 domain Optionally restrict record merges in a reverse zone to a specific 41 domain. 40 42 --detail Optional argument to add one log entry for each A+PTR pair merged 41 43 instead of a single generic entry. … … 82 84 } 83 85 die "$pzone is not a valid reverse zone specification\n" if !$npzone; 84 $zid = $dnsdb->revID($npzone );86 $zid = $dnsdb->revID($npzone, ''); 85 87 } else { 86 88 $rev = 'n'; 87 $zid = $dnsdb->domainID($pzone );88 } 89 die "$pzone is not a zone in the database \n" if !$zid;89 $zid = $dnsdb->domainID($pzone, ''); 90 } 91 die "$pzone is not a zone in the database (".$dnsdb->errstr.")\n" if !$zid; 90 92 91 93 # check the second arg. 92 my $fzid = $dnsdb->domainID($matchdom );94 my $fzid = $dnsdb->domainID($matchdom, ''); 93 95 die "$matchdom is not a domain in the database\n" if $matchdom && !$fzid; 94 96 … … 116 118 $reclist->execute($zid); 117 119 my $nrecs = 0; 120 my @cloglist; 118 121 while (my ($host,$val,$type,$id,$ttl,$loc) = $reclist->fetchrow_array) { 119 122 my $etype = 12; … … 134 137 $delsth->execute($erid); 135 138 if ($logdetail) { 136 $dnsdb->_log(group_id => $group, domain_id => $zid, rdns_id => $erdns, entry => $logentry); 139 my $lid = $dnsdb->_log(group_id => $group, domain_id => $zid, rdns_id => $erdns, entry => $logentry); 140 push @cloglist, $lid; 137 141 print "$logentry\n"; 138 142 } … … 140 144 } 141 145 } # while 142 if (!$logdetail) { 143 $dnsdb->_log(group_id => $group, domain_id => $zid, 146 my $lpid = $dnsdb->_log(group_id => $group, domain_id => $zid, 144 147 entry => "Merged $nrecs A and AAAA records in $pzone with matching PTRs"); 148 # since unlike in most other operations, we only "know" the parent log entry *after* 149 # we're done entering all the child entries, we have to update the children with the parent ID 150 my $assoc = $dbh->prepare("UPDATE log SET logparent = ? WHERE log_id = ?"); 151 for my $lcid (@cloglist) { 152 $assoc->execute($lpid, $lcid); 145 153 } 146 154 print "Merged $nrecs A and AAAA records in $pzone with matching PTRs\n"; … … 157 165 $reclist->execute($zid); 158 166 my $nrecs = 0; 167 my @cloglist; 159 168 while (my ($host,$val,$type,$id,$ttl,$loc) = $reclist->fetchrow_array) { 160 169 if ($matchdom) { … … 178 187 $delsth->execute($erid); 179 188 if ($logdetail) { 180 $dnsdb->_log(group_id => $group, domain_id => $edid, rdns_id => $zid, entry => $logentry); 181 print "$logentry\n"; 189 my $lid = $dnsdb->_log(group_id => $group, domain_id => $edid, rdns_id => $zid, entry => $logentry); 190 push @cloglist, $lid; 191 print "$lid: $logentry\n"; 182 192 } 183 193 $nrecs++; … … 185 195 } # while 186 196 my $entry = "Merged $nrecs PTR records in $pzone with matching A or AAAA records".($fzid ? " in $matchdom" : ''); 187 if (!$logdetail) { 188 if ($fzid) { 189 $dnsdb->_log(group_id => $group, domain_id => $fzid, rdns_id => $zid, entry => $entry); 190 } else { 191 $dnsdb->_log(group_id => $group, rdns_id => $zid, entry => $entry); 192 } 197 my $lpid; 198 if ($fzid) { 199 $lpid = $dnsdb->_log(group_id => $group, domain_id => $fzid, rdns_id => $zid, entry => $entry); 200 } else { 201 $lpid = $dnsdb->_log(group_id => $group, rdns_id => $zid, entry => $entry); 202 } 203 # since unlike in most other operations, we only "know" the parent log entry *after* 204 # we're done entering all the child entries, we have to update the children with the parent ID 205 my $assoc = $dbh->prepare("UPDATE log SET logparent = ? WHERE log_id = ?"); 206 for my $lcid (@cloglist) { 207 $assoc->execute($lpid, $lcid); 193 208 } 194 209 print "$entry\n"; 195 } # else 210 } 211 196 212 $dbh->commit; 197 213 }; -
branches/stable/notes
r725 r756 330 330 BIND reference for views/locations/split-horizon 331 331 https://kb.isc.org/article/AA-00851/0/Understanding-views-in-BIND-9-by-example.html 332 333 HTML calendar widget? 334 http://www.cssflow.com/snippets/tag/date-picker (paid) -
branches/stable/reverse-patterns.html
r690 r756 138 138 </td> 139 139 </tr> 140 <tr class="row0"> 141 <td>n'th natural IP</td> 142 <td>%x</td> 143 <td> 144 customer-23-%x.example.com<br /> 145 192.168.23.40 -> customer-23-1.example.com<br /> 146 192.168.23.41 -> customer-23-2.example.com<br /> 147 192.168.23.42 -> customer-23-3.example.com<br /> 148 192.168.23.43 -> customer-23-4.example.com<br /> 149 192.168.23.44 -> customer-23-5.example.com<br /> 150 192.168.23.45 -> customer-23-6.example.com<br /> 151 192.168.23.46 -> customer-23-7.example.com<br /> 152 192.168.23.47 -> customer-23-8.example.com 153 </td> 154 </tr> 140 155 </tbody> 141 156 </table> -
branches/stable/templates/bulkdomain.tmpl
r649 r756 43 43 <table> 44 44 <tr> 45 <TMPL_LOOP NAME=domtable><td><input type="checkbox" name="<TMPL_IF fwdzone>dom<TMPL_ELSE>rev</TMPL_IF>_<TMPL_VAR NAME=zoneid>" value="<TMPL_VAR NAME=zoneid>" /> <TMPL_VAR NAME=zone>< /td>45 <TMPL_LOOP NAME=domtable><td><input type="checkbox" name="<TMPL_IF fwdzone>dom<TMPL_ELSE>rev</TMPL_IF>_<TMPL_VAR NAME=zoneid>" value="<TMPL_VAR NAME=zoneid>" /> <TMPL_VAR NAME=zone><TMPL_IF location> (<TMPL_VAR NAME=location>)</TMPL_IF></td> 46 46 <TMPL_IF newrow><TMPL_UNLESS __last__></tr> 47 47 <tr> -
branches/stable/templates/dns.css
r649 r756 36 36 background-color: #F0F0F0; 37 37 } 38 39 /* Alternating row colours, now in CSS */ 40 .altrows > tbody > tr { 41 background-color: #D0E0E0; 42 } 43 .altrows > tbody > tr:nth-child(even) { 44 background-color: #FFFFFF; 45 } 46 .altrows > tbody > tr:nth-child(odd) { 47 background-color: #DDDDDD; 48 } 49 38 50 .container { 39 51 background-color: #FFFFFF; … … 188 200 .center { 189 201 text-align: center; 202 } 203 .vpad { 204 padding-top: 5px; 205 padding-bottom: 5px; 190 206 } 191 207 /* not sure this really does what I think it does. is it really not … … 277 293 font-size: 1.2em; 278 294 } 295 296 /* Pure CSS "click to show" widget, adapted from the group tree CSS */ 297 .collapsible li > input + * { 298 display: none; 299 } 300 /* when the input is checked, show the content div */ 301 .collapsible li > input:checked + * { 302 display: block; 303 } 304 /* hide the checkbox */ 305 .nocheckbox li > input { 306 display: none; 307 margin: 0em; 308 padding: 0px; 309 } 310 /* mostly just making the input label clickable */ 311 .collapsible label { 312 cursor: pointer; 313 display: inline; 314 margin: 0em; 315 padding: 0px; 316 padding-left: 10px; 317 } 318 /* be nice if we could make this work without the HTML list structure... */ 319 .notalist { 320 list-style: none; 321 margin: 0; 322 padding: 1px; 323 } 324 -
branches/stable/templates/domlist.tmpl
r725 r756 28 28 </table> 29 29 30 <table width="98%" border="0" cellspacing="4" cellpadding="3" >30 <table width="98%" border="0" cellspacing="4" cellpadding="3" class="altrows"> 31 31 <tr> 32 32 <TMPL_LOOP NAME=colheads> <td class="datahead_<TMPL_IF __first__>l<TMPL_ELSE>s</TMPL_IF>"><a href="<TMPL_VAR … … 41 41 <TMPL_IF name=domtable> 42 42 <TMPL_LOOP name=domtable> 43 <tr class="row<TMPL_IF __odd__>0<TMPL_ELSE>1</TMPL_IF>">43 <tr> 44 44 <td align="left"><a href="<TMPL_VAR NAME=script_self>&page=reclist&id=<TMPL_VAR NAME=zoneid>&defrec=n<TMPL_UNLESS domlist>&revrec=y</TMPL_UNLESS>"><TMPL_VAR NAME=zone></a><TMPL_IF location> (<TMPL_VAR NAME=location>)</TMPL_IF></td> 45 45 <td><TMPL_IF status>Active<TMPL_ELSE>Inactive</TMPL_IF></td> … … 49 49 </tr> 50 50 </TMPL_LOOP> 51 <tr><td colspan="5" align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td></tr>52 51 <TMPL_ELSE> 53 52 <tr><td colspan="5" align="center">No <TMPL_IF domlist>domains<TMPL_ELSE>reverse zones</TMPL_IF> found</td></tr> … … 55 54 </table> 56 55 56 <TMPL_IF domtable><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF> 57 57 58 </td> 58 59 </tr> -
branches/stable/templates/footer.tmpl
r548 r756 5 5 <div id="contact"> 6 6 <a href="https://secure.deepnet.cx/trac/dnsadmin">dnsadmin</a> <TMPL_VAR NAME=version> 7 © 2008-201 3<a href="mailto:kdeugau@deepnet.cx">Kris Deugau</a>/<a href="http://www.deepnet.cx">deepnet</a><br />7 © 2008-2016 <a href="mailto:kdeugau@deepnet.cx">Kris Deugau</a>/<a href="http://www.deepnet.cx">deepnet</a><br /> 8 8 Written for standards-based browsers (eg <a href="http://www.firefox.com">FireFox</a>/<a href="http://www.mozilla.org">Mozilla</a>) 9 9 </div> -
branches/stable/templates/grpman.tmpl
r649 r756 24 24 </table> 25 25 26 <table width="98%" border="0" cellspacing="4" cellpadding="3" >26 <table width="98%" border="0" cellspacing="4" cellpadding="3" class="altrows"> 27 27 <tr> 28 28 <TMPL_LOOP NAME=colheads> <td class="datahead_<TMPL_IF __first__>l<TMPL_ELSE>s</TMPL_IF>"><a href="<TMPL_VAR … … 38 38 <TMPL_IF name=grouptable> 39 39 <TMPL_LOOP name=grouptable> 40 <tr class="row<TMPL_IF __odd__>0<TMPL_ELSE>1</TMPL_IF>">40 <tr> 41 41 <td align="left"><TMPL_IF edgrp><a href="<TMPL_VAR NAME=script_self>&page=edgroup&gid=<TMPL_VAR NAME=groupid>"><TMPL_VAR NAME=groupname></a><TMPL_ELSE><TMPL_VAR NAME=groupname></TMPL_IF></td> 42 42 <td><TMPL_VAR name=pgroup></td> … … 49 49 </tr> 50 50 </TMPL_LOOP> 51 <tr><td colspan="6" align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td></tr>52 51 <TMPL_ELSE> 53 52 <tr><td colspan="6" align="center">No groups found</td></tr> … … 55 54 </table> 56 55 56 <TMPL_IF grouptable><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF> 57 57 58 </td> 58 59 </tr> -
branches/stable/templates/loclist.tmpl
r649 r756 21 21 </table> 22 22 23 <table width="98%" border="0" cellspacing="4" cellpadding="3" class="csubtable ">23 <table width="98%" border="0" cellspacing="4" cellpadding="3" class="csubtable altrows"> 24 24 <tr> 25 25 <TMPL_LOOP NAME=colheads> <td class="datahead_s"><a href="<TMPL_VAR … … 33 33 <TMPL_IF name=loctable> 34 34 <TMPL_LOOP name=loctable> 35 <tr class="row<TMPL_IF __odd__>0<TMPL_ELSE>1</TMPL_IF>">35 <tr> 36 36 <td align="left"><TMPL_IF edloc><a href="<TMPL_VAR NAME=script_self>&page=location&locact=edit&loc=<TMPL_VAR NAME=location>"><TMPL_VAR NAME=description></a><TMPL_ELSE><TMPL_VAR NAME=description></TMPL_IF></td> 37 37 <td><TMPL_VAR name=iplist></td> … … 48 48 </table> 49 49 50 <TMPL_IF loctable><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF> 51 50 52 </td> 51 53 </tr> -
branches/stable/templates/log.tmpl
r649 r756 8 8 9 9 <TMPL_IF errmsg> 10 <div class= 'errmsg'><TMPL_VAR NAME=errmsg></div>10 <div class="errmsg"><TMPL_VAR NAME=errmsg></div> 11 11 </TMPL_IF> 12 12 13 <table border="0" width="9 0%">13 <table border="0" width="98%"> 14 14 <tr><th colspan="3"><div class="center maintitle">Log entries for <TMPL_VAR NAME=logfor></div></th></tr> 15 15 <tr> 16 16 <td class="leftthird"><TMPL_INCLUDE NAME="pgcount.tmpl"></td> 17 17 <td align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td> 18 <td class="rightthird"> </td> 18 <td class="rightthird"> 19 <form action="<TMPL_VAR NAME=script_self>"> 20 <input type="hidden" name="page" value="log" /> 21 <input type="hidden" name="offset" value="0" /> 22 <input type="hidden" name="id" value="<TMPL_VAR NAME=id>" /> 23 <input type="hidden" name="ltype" value="<TMPL_VAR NAME=ltype>" /> 24 <input name="logfilter"<TMPL_IF logfilter> value="<TMPL_VAR NAME=logfilter ESCAPE=HTML>"</TMPL_IF> /> 25 <input type="submit" value="Filter" /> 26 </form> 27 </td> 19 28 </tr> 20 29 </table> 21 <table border="0" width="90%"> 22 <!-- Not sure "Customer ID" (filled with uid) is of any use... --> 23 <!-- td>Customer ID</td --> 30 <table border="0" width="98%"> 24 31 <tr class="darkrowheader"> 25 <TMPL_LOOP NAME=colheads> <td><a href="<TMPL_VAR NAME=script_self>&page=<TMPL_VAR NAME=page><TMPL_IF 32 <TMPL_LOOP NAME=colheads> 33 <td class="data_nowrap"><a href="<TMPL_VAR NAME=script_self>&page=<TMPL_VAR NAME=page><TMPL_IF 26 34 NAME=offset>&offset=<TMPL_VAR NAME=offset></TMPL_IF>&sortby=<TMPL_VAR 27 35 NAME=sortby>&order=<TMPL_VAR NAME=order>&id=<TMPL_VAR NAME=id>&ltype=<TMPL_VAR … … 35 43 <TMPL_LOOP NAME=logentries> 36 44 <tr class="datalinelight"> 37 <td><TMPL_VAR NAME=userfname></td> 38 <!-- td><TMPL_VAR NAME=userid></td --> 39 <td><TMPL_VAR NAME=useremail></td> 40 <td><TMPL_VAR NAME=logentry></td> 45 <td><a href="<TMPL_VAR NAME=script_self>&page=log&sortby=<TMPL_VAR 46 NAME=sortby>&order=<TMPL_VAR NAME=order>&<TMPL_IF userid>id=<TMPL_VAR 47 NAME=userid><TMPL_ELSE>fname=<TMPL_VAR NAME=userfname ESCAPE=URL></TMPL_IF>&ltype=user"><TMPL_VAR 48 NAME=userfname></a></td> 49 <td><a href="<TMPL_VAR NAME=script_self>&page=log&sortby=<TMPL_VAR 50 NAME=sortby>&order=<TMPL_VAR NAME=order>&id=<TMPL_VAR 51 NAME=domain_id>&ltype=dom"><TMPL_VAR NAME=domain></a></td> 52 <td><a href="<TMPL_VAR NAME=script_self>&page=log&sortby=<TMPL_VAR 53 NAME=sortby>&order=<TMPL_VAR NAME=order>&id=<TMPL_VAR 54 NAME=rdns_id>&ltype=rdns"><TMPL_VAR NAME=revzone></a></td> 55 <TMPL_IF childentries> 56 <td> 57 <ul class="collapsible nocheckbox notalist"> 58 <li class="notalist"> 59 <label for="childlist<TMPL_VAR NAME=logparent>"><TMPL_VAR NAME=logentry> (<img src="<TMPL_VAR 60 NAME=webpath>/images/tree_open.png" />Click for details)</label> 61 <input type="checkbox" id="childlist<TMPL_VAR NAME=logparent>" /> 62 <ul class="notalist"> 63 <li class="notalist"><TMPL_LOOP NAME=childentries> 64 <TMPL_VAR NAME=entry><TMPL_UNLESS __last__><br /></TMPL_UNLESS></TMPL_LOOP> 65 </li> 66 </ul> 67 </li> 68 </ul> 69 <TMPL_ELSE> 70 <td><TMPL_VAR NAME=logentry> 71 </TMPL_IF> 72 </td> 41 73 <td><TMPL_VAR NAME=logtime></td> 42 74 </tr> 43 75 </TMPL_LOOP> 44 <tr><td colspan="5" align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td></tr>45 76 <TMPL_ELSE> 46 77 <tr class="datalinelight"> … … 50 81 </table> 51 82 83 <TMPL_IF logentries><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF> 84 52 85 </td> 53 86 </tr> -
branches/stable/templates/menu.tmpl
r649 r756 31 31 <!-- hmm: <TMPL_VAR NAME=groupname> --> 32 32 <hr /> 33 Find records(s): 34 <form action="<TMPL_VAR NAME=script_self>&page=recsearch" method="post"> 35 <input name="searchfor" /> 36 <input type="submit" value=" Search " /> 37 </form> 38 <hr /> 33 39 <a href="<TMPL_VAR NAME=script_self>&page=dnsq">DNS Query</a><br /> 34 40 <a href="<TMPL_VAR NAME=script_self>&page=whoisq">WHOIS Query</a><br /> -
branches/stable/templates/reclist.tmpl
r649 r756 49 49 </table> 50 50 51 <table width="100%" >51 <table width="100%" class="altrows"> 52 52 <TMPL_IF reclist> 53 53 <tr class="darkrowheader"> … … 62 62 </tr> 63 63 <TMPL_LOOP NAME=reclist> 64 <tr class="row<TMPL_IF __odd__>0<TMPL_ELSE>1</TMPL_IF>">64 <tr> 65 65 <TMPL_IF fwdzone> 66 66 <td><TMPL_IF record_edit><a href="<TMPL_VAR NAME=script_self>&page=record&parentid=<TMPL_VAR … … 89 89 </tr> 90 90 </TMPL_LOOP> 91 <tr class="darkrowheader"><td colspan="8" align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td></tr>92 91 <TMPL_ELSE> 93 92 <tr><td colspan="8" align="center">No records found</td></tr> 94 93 </TMPL_IF> 95 94 </table> 95 96 <TMPL_IF reclist><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF> 96 97 97 98 </td></tr></table> -
branches/stable/templates/useradmin.tmpl
r649 r756 22 22 </table> 23 23 24 <table width="98%" border="0" cellspacing="4" cellpadding="3" class="csubtable ">24 <table width="98%" border="0" cellspacing="4" cellpadding="3" class="csubtable altrows"> 25 25 <tr> 26 26 <TMPL_LOOP NAME=colheads> <td class="datahead_<TMPL_IF __first__>l<TMPL_ELSE>s</TMPL_IF>"><a href="<TMPL_VAR … … 34 34 <TMPL_IF name=usertable> 35 35 <TMPL_LOOP name=usertable> 36 <tr class="row<TMPL_IF __odd__>0<TMPL_ELSE>1</TMPL_IF>">36 <tr> 37 37 <td align="left"><TMPL_IF eduser><a href="<TMPL_VAR NAME=script_self>&page=user&useraction=edit&user=<TMPL_VAR NAME=user_id>"><TMPL_VAR NAME=username></a><TMPL_ELSE><TMPL_VAR NAME=username></TMPL_IF></td> 38 38 <td class="data_nowrap"><TMPL_VAR name=fname></td> … … 51 51 </tr> 52 52 </TMPL_LOOP> 53 <tr><td colspan="6" align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td></tr>54 53 <TMPL_ELSE> 55 54 <tr><td colspan="6" align="center">No users found</td></tr> … … 57 56 </table> 58 57 58 <TMPL_IF usertable><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF> 59 59 60 </td> 60 61 </tr> -
branches/stable/textrecs.cgi
r587 r756 3 3 ## 4 4 # $Id$ 5 # Copyright 2012 ,2013Kris Deugau <kdeugau@deepnet.cx>5 # Copyright 2012-2014 Kris Deugau <kdeugau@deepnet.cx> 6 6 # 7 7 # This program is free software: you can redistribute it and/or modify -
branches/stable/tiny-import.pl
r649 r756 3 3 ## 4 4 # $Id$ 5 # Copyright 2012 ,2013Kris Deugau <kdeugau@deepnet.cx>5 # Copyright 2012-2014 Kris Deugau <kdeugau@deepnet.cx> 6 6 # 7 7 # This program is free software: you can redistribute it and/or modify
Note:
See TracChangeset
for help on using the changeset viewer.