Changeset 756


Ignore:
Timestamp:
06/13/17 13:58:57 (7 years ago)
Author:
Kris Deugau
Message:

/branches/stable

Merge /trunk through r749 for 1.4.0

Location:
branches/stable
Files:
22 edited
2 copied

Legend:

Unmodified
Added
Removed
  • branches/stable

  • branches/stable/DNSDB.pm

    r725 r756  
    33##
    44# $Id$
    5 # Copyright 2008-2013 Kris Deugau <kdeugau@deepnet.cx>
     5# Copyright 2008-2016 Kris Deugau <kdeugau@deepnet.cx>
    66#
    77#    This program is free software: you can redistribute it and/or modify
     
    3636use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
    3737
    38 $VERSION        = "1.2.5p2";    ##VERSION##
     38$VERSION        = "1.4.0";      ##VERSION##
    3939@ISA            = qw(Exporter);
    4040@EXPORT_OK      = qw(
     
    146146                domain  => 'domain_id',
    147147                revzone => 'rdns_id',
    148                 record  => 'record_id'
     148                record  => 'record_id',
    149149        );
    150150my %par_col = (
     
    456456#  group_id, log entry
    457457# and optionally one or more of:
    458 #  domain_id, rdns_id
     458#  domain_id, rdns_id, logparent
    459459# 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)
    460462sub _log {
    461463  my $self = shift;
     
    466468  $args{rdns_id} = 0 if !$args{rdns_id};
    467469  $args{domain_id} = 0 if !$args{domain_id};
     470  $args{logparent} = 0 if !$args{logparent};
    468471
    469472##fixme:  farm out the actual logging to different subs for file, syslog, internal, etc based on config
    470473#  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 (?,?,?,?,?,?,?,?)",
    472476        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},
    474478                $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
    475483#  } elsif ($self->{log_channel} eq 'file') {
    476484#  } elsif ($self->{log_channel} eq 'syslog') {
     
    16551663    my ($c) = ($$tmpl =~ /(\%-?c)/);  my $nld = '';  my $cld = '';
    16561664    $c = '' if !$c;
     1665    my ($cn) = ($$tmpl =~ /(\%x)/);
    16571666    my $skipgw = ($c =~ /\%-c/ ? 0 : 1);
    16581667    my $ipkill = 0;
     1668
     1669    if ($cn) {
     1670      # "natural n'th IP in the block" pattern
     1671      $$tmpl =~ s/$cn/$ipindex+1/e;
     1672    }
    16591673
    16601674##fixme: still have one edge case not handled well:
     
    23682382        undef, ($domain, $defloc));
    23692383
    2370     $self->_log(domain_id => $dom_id, group_id => $group,
     2384    my $logparent = $self->_log(domain_id => $dom_id, group_id => $group,
    23712385        entry => "Added ".($state ? 'active' : 'inactive')." domain $domain");
    23722386
     
    23842398        my @tmp1 = split /:/, $host;
    23852399        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,
    23872401                entry => "[new $domain] Added SOA record [contact $tmp1[0]] [master $tmp1[1]] ".
    23882402                "[refresh $tmp2[0]] [retry $tmp2[1]] [expire $tmp2[2]] [minttl $tmp2[3]], TTL $ttl");
     
    23912405        $logentry .= " [distance $dist]" if $typemap{$type} eq 'MX';
    23922406        $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,
    23942408                entry => $logentry." $val', TTL $ttl");
    23952409      }
     
    34393453        "WHERE group_id IN ($args{curgroup}".($args{childlist} ? ",$args{childlist}" : '').")".
    34403454        ($args{startwith} ? " AND username ~* ?" : '').
    3441         ($args{filter} ? " AND username ~* ?" : '');
     3455        ($args{filter} ? " AND username ~* ?" : '').
     3456        " AND NOT type = 'R' ";
    34423457  my ($count) = $dbh->selectrow_array($sql, undef, (@filterargs) );
    34433458  $errstr = $dbh->errstr if !$count;
     
    36453660  $errstr = $DBI::errstr if !$uname;
    36463661
     3662  no warnings qw (uninitialized);
    36473663  $fullformat =~ s/\%u/$uname/g;
    36483664  $fullformat =~ s/\%f/$fname/g;
     
    48104826# Get a count of log entries
    48114827# Takes a database handle and a hash containing at least:
    4812 # - Entity ID and entity type as the primary log "slice"
     4828# - Entity identifier and entity type as the primary log "slice"
    48134829sub getLogCount {
    48144830  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);
    48394832} # end getLogCount()
    48404833
     
    48434836# Get a list of log entries
    48444837# Takes arguments as with getLogCount() above, plus optional:
     4838# - "count" flag
     4839#  OR
    48454840# - sort field
    48464841# - sort order
     
    48544849  my @filterargs;
    48554850
    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";
    48604853  return if !$args{logtype};
    48614854  $args{logtype} = 'revzone' if $args{logtype} eq 'rdns';       # hack pthui
    48624855  $args{logtype} = 'domain' if $args{logtype} eq 'dom';         # hack pthui
     4856  $errstr = "Invalid primary log slice type";
    48634857  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});
    48644862
    48654863  # Sorting defaults
     
    48684866  $args{offset} = 0 if !$args{offset} || $args{offset} !~ /^(?:all|\d+)$/;
    48694867
    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');
    48714870  $args{sortby} = $sortmap{$args{sortby}};
    48724871
    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}".
    48794916        ($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
    48834932} # end getLogEntries()
     4933
     4934
     4935# a collection of joins for the record search
     4936our $recsearchsqlbase = q(
     4937FROM records r
     4938LEFT JOIN domains d ON r.domain_id = d.domain_id
     4939  LEFT JOIN groups g1 ON d.group_id = g1.group_id
     4940LEFT JOIN revzones z ON r.rdns_id = z.rdns_id
     4941  LEFT JOIN groups g2 on z.group_id = g2.group_id
     4942JOIN rectypes t ON r.type = t.val
     4943LEFT JOIN locations l ON r.location = l.location
     4944WHERE 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
     4951sub 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
     4984sub 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()
    48845036
    48855037
     
    53795531  eval {
    53805532
     5533    my $logparent;
     5534
    53815535    if ($rev eq 'n') {
    53825536##fixme:  serial
     
    53865540      ($zone_id) = $dbh->selectrow_array("SELECT currval('domains_domain_id_seq')");
    53875541      $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,
    53895543                entry => "[Added ".($args{status} ? 'active' : 'inactive')." domain $zone via AXFR]");
    53905544    } else {
     
    53955549      ($zone_id) = $dbh->selectrow_array("SELECT currval('revzones_rdns_id_seq')");
    53965550      $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,
    53985552                entry => "[Added ".($args{status} ? 'active' : 'inactive')." reverse zone $cidr via AXFR]");
    53995553    }
     
    56475801        $logentry .= " ".($rev eq 'y' ? $host : $val)."', TTL $ttl";
    56485802      }
    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);
    56505805
    56515806    } # while axfr_next
  • branches/stable/Makefile

    r725 r756  
    33
    44PKGNAME=dnsadmin
    5 VERSION=1.2.6
     5VERSION=1.4.0
    66RELEASE=1
    77
     
    4646        INSTALL COPYING TODO Makefile dnsadmin.spec \
    4747        \
    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 \
    4949        \
    5050        $(SCRIPTS) $(MODULES) \
     
    8585        templates/msgblock.tmpl templates/newdomain.tmpl templates/newgrp.tmpl templates/newrevzone.tmpl \
    8686        templates/permlist.tmpl templates/pgcount.tmpl templates/reclist.tmpl templates/record.tmpl \
     87        templates/recsearch.tmpl \
    8788        templates/revzones.tmpl templates/sbox.tmpl templates/soadata.tmpl templates/template.tmpl \
    8889        templates/textrecs.tmpl templates/updatesoa.tmpl templates/useradmin.tmpl templates/user.tmpl \
  • branches/stable/compact-recs.pl

    r649 r756  
    44##
    55# $Id$
    6 # Copyright 2013 Kris Deugau <kdeugau@deepnet.cx>
     6# Copyright 2013,2014 Kris Deugau <kdeugau@deepnet.cx>
    77#
    88#    This program is free software: you can redistribute it and/or modify
  • branches/stable/dns-rpc.cgi

    r725 r756  
    33##
    44# $Id$
    5 # Copyright 2012,2013 Kris Deugau <kdeugau@deepnet.cx>
     5# Copyright 2012-2016 Kris Deugau <kdeugau@deepnet.cx>
    66#
    77#    This program is free software: you can redistribute it and/or modify
     
    115115
    116116my $reqcnt = 0;
    117 
    118 while (FCGI::accept >= 0) {
     117my $req = FCGI::Request();
     118
     119while ($req->Accept() >= 0) {
    119120  my $res = Frontier::Responder->new(
    120121        methods => $methods
     
    200201  my $modflag = 0;
    201202  # 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)) {
    203204    return 1 if (
    204205        defined($newrec->{$field}) &&
  • branches/stable/dns.cgi

    r725 r756  
    33##
    44# $Id$
    5 # Copyright 2008-2013 Kris Deugau <kdeugau@deepnet.cx>
     5# Copyright 2008-2016 Kris Deugau <kdeugau@deepnet.cx>
    66#
    77#    This program is free software: you can redistribute it and/or modify
     
    120120$webvar{startwith} =~ s/^(0-9|[a-z]).*/$1/ if $webvar{startwith};
    121121# 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};
    123123## only set 'y' if box is checked, no other values legal
    124124## however, see https://secure.deepnet.cx/trac/dnsadmin/ticket/31
     
    138138# @#$%@%@#% XHTML - & in a URL must be escaped.  >:(
    139139my $uri_self = $ENV{REQUEST_URI};
     140$uri_self = "/dns.cgi" if !$uri_self || $uri_self eq '/';
    140141$uri_self =~ s/\&([a-z])/\&amp\;$1/g;
    141142
     
    455456
    456457  if ($code eq 'OK') {
     458    $webvar{domain} = lc($webvar{domain}) if $dnsdb->{lowercase};
    457459    $dnsdb->mailNotify("New ".($webvar{makeactive} eq 'on' ? 'Active' : 'Inactive')." Domain Created",
    458460        ($webvar{makeactive} eq 'on' ? 'Active' : 'Inactive').qq( domain "$webvar{domain}" added by ).
     
    17951797##fixme:  where should we call this from?
    17961798    $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}));
    18021801  } elsif ($webvar{ltype} && $webvar{ltype} eq 'dom') {
    18031802    $id = $webvar{id};
     
    18211820  }
    18221821  $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/\&amp;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  }
    18241842
    18251843  $page->param(id => $id);
     
    18401858
    18411859  # 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');
    18441863  fill_colheads($sortby, $sortorder, \@cols, \%colnames);
    18451864
    18461865##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  }
    18501876
    18511877##fixme:
    1852 # - filtering
    1853 # - show reverse zone column?
    18541878# - on log record creation, bundle "parented" log actions (eg, "AXFR record blah for domain foo",
    18551879#   or "Add record bar for new domain baz") into one entry (eg, "AXFR domain foo", "Add domain baz")?
     
    18581882  # scope check fail target
    18591883  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/\&amp;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);
    18601931
    18611932} # end $webvar{page} dance
  • branches/stable/dns.sql

    r725 r756  
    3131
    3232COPY misc (misc_id, key, value) FROM stdin;
    33 1       dbversion       1.2.6
     331       dbversion       1.4.0
    3434\.
    3535
     
    136136    entry text,
    137137    stamp timestamp with time zone DEFAULT now(),
    138     rdns_id integer
    139 );
     138    rdns_id integer,
     139    logparent integer NOT NULL DEFAULT 0
     140);
     141CREATE INDEX log_domain_id_index ON log(domain_id);
     142CREATE INDEX log_user_id_index ON log(user_id);
     143CREATE INDEX log_group_id_index ON log(group_id);
     144CREATE INDEX log_rdns_id_index ON log(rdns_id);
    140145
    141146CREATE TABLE permissions (
  • branches/stable/mergerecs

    r690 r756  
    33##
    44# $Id$
    5 # Copyright 2014 Kris Deugau <kdeugau@deepnet.cx>
     5# Copyright 2014,2016 Kris Deugau <kdeugau@deepnet.cx>
    66#
    77#    This program is free software: you can redistribute it and/or modify
     
    3636sub usage {
    3737  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.
    4042 --detail Optional argument to add one log entry for each A+PTR pair merged
    4143          instead of a single generic entry.
     
    8284  }
    8385  die "$pzone is not a valid reverse zone specification\n" if !$npzone;
    84   $zid = $dnsdb->revID($npzone);
     86  $zid = $dnsdb->revID($npzone, '');
    8587} else {
    8688  $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}
     91die "$pzone is not a zone in the database (".$dnsdb->errstr.")\n" if !$zid;
    9092
    9193# check the second arg.
    92 my $fzid = $dnsdb->domainID($matchdom);
     94my $fzid = $dnsdb->domainID($matchdom, '');
    9395die "$matchdom is not a domain in the database\n" if $matchdom && !$fzid;
    9496
     
    116118    $reclist->execute($zid);
    117119    my $nrecs = 0;
     120    my @cloglist;
    118121    while (my ($host,$val,$type,$id,$ttl,$loc) = $reclist->fetchrow_array) {
    119122      my $etype = 12;
     
    134137        $delsth->execute($erid);
    135138        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;
    137141          print "$logentry\n";
    138142        }
     
    140144      }
    141145    } # while
    142     if (!$logdetail) {
    143       $dnsdb->_log(group_id => $group, domain_id => $zid,
     146    my $lpid = $dnsdb->_log(group_id => $group, domain_id => $zid,
    144147        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);
    145153    }
    146154    print "Merged $nrecs A and AAAA records in $pzone with matching PTRs\n";
     
    157165    $reclist->execute($zid);
    158166    my $nrecs = 0;
     167    my @cloglist;
    159168    while (my ($host,$val,$type,$id,$ttl,$loc) = $reclist->fetchrow_array) {
    160169      if ($matchdom) {
     
    178187        $delsth->execute($erid);
    179188        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";
    182192        }
    183193        $nrecs++;
     
    185195    } # while
    186196    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);
    193208    }
    194209    print "$entry\n";
    195   } # else
     210  }
     211
    196212  $dbh->commit;
    197213};
  • branches/stable/notes

    r725 r756  
    330330BIND reference for views/locations/split-horizon
    331331https://kb.isc.org/article/AA-00851/0/Understanding-views-in-BIND-9-by-example.html
     332
     333HTML calendar widget?
     334http://www.cssflow.com/snippets/tag/date-picker  (paid)
  • branches/stable/reverse-patterns.html

    r690 r756  
    138138            </td>
    139139          </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>
    140155        </tbody>
    141156      </table>
  • branches/stable/templates/bulkdomain.tmpl

    r649 r756  
    4343<table>
    4444<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>
    4646<TMPL_IF newrow><TMPL_UNLESS __last__></tr>
    4747<tr>
  • branches/stable/templates/dns.css

    r649 r756  
    3636        background-color: #F0F0F0;
    3737}
     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
    3850.container {
    3951        background-color: #FFFFFF;
     
    188200.center {
    189201        text-align: center;
     202}
     203.vpad {
     204        padding-top: 5px;
     205        padding-bottom: 5px;
    190206}
    191207/* not sure this really does what I think it does.  is it really not
     
    277293        font-size: 1.2em;
    278294}
     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  
    2828</table>
    2929
    30 <table width="98%" border="0" cellspacing="4" cellpadding="3">
     30<table width="98%" border="0" cellspacing="4" cellpadding="3" class="altrows">
    3131<tr>
    3232<TMPL_LOOP NAME=colheads>       <td class="datahead_<TMPL_IF __first__>l<TMPL_ELSE>s</TMPL_IF>"><a href="<TMPL_VAR
     
    4141<TMPL_IF name=domtable>
    4242<TMPL_LOOP name=domtable>
    43 <tr class="row<TMPL_IF __odd__>0<TMPL_ELSE>1</TMPL_IF>">
     43<tr>
    4444        <td align="left"><a href="<TMPL_VAR NAME=script_self>&amp;page=reclist&amp;id=<TMPL_VAR NAME=zoneid>&amp;defrec=n<TMPL_UNLESS domlist>&amp;revrec=y</TMPL_UNLESS>"><TMPL_VAR NAME=zone></a><TMPL_IF location> (<TMPL_VAR NAME=location>)</TMPL_IF></td>
    4545        <td><TMPL_IF status>Active<TMPL_ELSE>Inactive</TMPL_IF></td>
     
    4949</tr>
    5050</TMPL_LOOP>
    51 <tr><td colspan="5" align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td></tr>
    5251<TMPL_ELSE>
    5352<tr><td colspan="5" align="center">No <TMPL_IF domlist>domains<TMPL_ELSE>reverse zones</TMPL_IF> found</td></tr>
     
    5554</table>
    5655
     56<TMPL_IF domtable><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF>
     57
    5758</td>
    5859</tr>
  • branches/stable/templates/footer.tmpl

    r548 r756  
    55<div id="contact">
    66<a href="https://secure.deepnet.cx/trac/dnsadmin">dnsadmin</a> <TMPL_VAR NAME=version>
    7 &copy; 2008-2013 <a href="mailto:kdeugau@deepnet.cx">Kris Deugau</a>/<a href="http://www.deepnet.cx">deepnet</a><br />
     7&copy; 2008-2016 <a href="mailto:kdeugau@deepnet.cx">Kris Deugau</a>/<a href="http://www.deepnet.cx">deepnet</a><br />
    88Written for standards-based browsers (eg <a href="http://www.firefox.com">FireFox</a>/<a href="http://www.mozilla.org">Mozilla</a>)
    99</div>
  • branches/stable/templates/grpman.tmpl

    r649 r756  
    2424</table>
    2525
    26 <table width="98%" border="0" cellspacing="4" cellpadding="3">
     26<table width="98%" border="0" cellspacing="4" cellpadding="3" class="altrows">
    2727<tr>
    2828<TMPL_LOOP NAME=colheads>       <td class="datahead_<TMPL_IF __first__>l<TMPL_ELSE>s</TMPL_IF>"><a href="<TMPL_VAR
     
    3838<TMPL_IF name=grouptable>
    3939<TMPL_LOOP name=grouptable>
    40 <tr class="row<TMPL_IF __odd__>0<TMPL_ELSE>1</TMPL_IF>">
     40<tr>
    4141        <td align="left"><TMPL_IF edgrp><a href="<TMPL_VAR NAME=script_self>&amp;page=edgroup&amp;gid=<TMPL_VAR NAME=groupid>"><TMPL_VAR NAME=groupname></a><TMPL_ELSE><TMPL_VAR NAME=groupname></TMPL_IF></td>
    4242        <td><TMPL_VAR name=pgroup></td>
     
    4949</tr>
    5050</TMPL_LOOP>
    51 <tr><td colspan="6" align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td></tr>
    5251<TMPL_ELSE>
    5352<tr><td colspan="6" align="center">No groups found</td></tr>
     
    5554</table>
    5655
     56<TMPL_IF grouptable><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF>
     57
    5758</td>
    5859</tr>
  • branches/stable/templates/loclist.tmpl

    r649 r756  
    2121</table>
    2222
    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">
    2424<tr>
    2525<TMPL_LOOP NAME=colheads>       <td class="datahead_s"><a href="<TMPL_VAR
     
    3333<TMPL_IF name=loctable>
    3434<TMPL_LOOP name=loctable>
    35 <tr class="row<TMPL_IF __odd__>0<TMPL_ELSE>1</TMPL_IF>">
     35<tr>
    3636        <td align="left"><TMPL_IF edloc><a href="<TMPL_VAR NAME=script_self>&amp;page=location&amp;locact=edit&amp;loc=<TMPL_VAR NAME=location>"><TMPL_VAR NAME=description></a><TMPL_ELSE><TMPL_VAR NAME=description></TMPL_IF></td>
    3737        <td><TMPL_VAR name=iplist></td>
     
    4848</table>
    4949
     50<TMPL_IF loctable><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF>
     51
    5052</td>
    5153</tr>
  • branches/stable/templates/log.tmpl

    r649 r756  
    88
    99<TMPL_IF errmsg>
    10 <div class='errmsg'><TMPL_VAR NAME=errmsg></div>
     10<div class="errmsg"><TMPL_VAR NAME=errmsg></div>
    1111</TMPL_IF>
    1212
    13 <table border="0" width="90%">
     13<table border="0" width="98%">
    1414<tr><th colspan="3"><div class="center maintitle">Log entries for <TMPL_VAR NAME=logfor></div></th></tr>
    1515<tr>
    1616<td class="leftthird"><TMPL_INCLUDE NAME="pgcount.tmpl"></td>
    1717<td align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td>
    18 <td class="rightthird">&nbsp;</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>
    1928</tr>
    2029</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%">
    2431<tr class="darkrowheader">
    25 <TMPL_LOOP NAME=colheads>       <td><a href="<TMPL_VAR NAME=script_self>&amp;page=<TMPL_VAR NAME=page><TMPL_IF
     32<TMPL_LOOP NAME=colheads>
     33        <td class="data_nowrap"><a href="<TMPL_VAR NAME=script_self>&amp;page=<TMPL_VAR NAME=page><TMPL_IF
    2634 NAME=offset>&amp;offset=<TMPL_VAR NAME=offset></TMPL_IF>&amp;sortby=<TMPL_VAR
    2735 NAME=sortby>&amp;order=<TMPL_VAR NAME=order>&amp;id=<TMPL_VAR NAME=id>&amp;ltype=<TMPL_VAR
     
    3543<TMPL_LOOP NAME=logentries>
    3644    <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>&amp;page=log&amp;sortby=<TMPL_VAR
     46 NAME=sortby>&amp;order=<TMPL_VAR NAME=order>&amp;<TMPL_IF userid>id=<TMPL_VAR
     47 NAME=userid><TMPL_ELSE>fname=<TMPL_VAR NAME=userfname ESCAPE=URL></TMPL_IF>&amp;ltype=user"><TMPL_VAR
     48 NAME=userfname></a></td>
     49        <td><a href="<TMPL_VAR NAME=script_self>&amp;page=log&amp;sortby=<TMPL_VAR
     50 NAME=sortby>&amp;order=<TMPL_VAR NAME=order>&amp;id=<TMPL_VAR
     51 NAME=domain_id>&amp;ltype=dom"><TMPL_VAR NAME=domain></a></td>
     52        <td><a href="<TMPL_VAR NAME=script_self>&amp;page=log&amp;sortby=<TMPL_VAR
     53 NAME=sortby>&amp;order=<TMPL_VAR NAME=order>&amp;id=<TMPL_VAR
     54 NAME=rdns_id>&amp;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>&nbsp;(<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>
    4173        <td><TMPL_VAR NAME=logtime></td>
    4274    </tr>
    4375</TMPL_LOOP>
    44     <tr><td colspan="5" align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td></tr>
    4576<TMPL_ELSE>
    4677    <tr class="datalinelight">
     
    5081</table>
    5182
     83<TMPL_IF logentries><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF>
     84
    5285</td>
    5386</tr>
  • branches/stable/templates/menu.tmpl

    r649 r756  
    3131<!-- hmm:  <TMPL_VAR NAME=groupname> -->
    3232<hr />
     33Find records(s):
     34<form action="<TMPL_VAR NAME=script_self>&amp;page=recsearch" method="post">
     35<input name="searchfor" />
     36<input type="submit" value=" Search " />
     37</form>
     38<hr />
    3339<a href="<TMPL_VAR NAME=script_self>&amp;page=dnsq">DNS Query</a><br />
    3440<a href="<TMPL_VAR NAME=script_self>&amp;page=whoisq">WHOIS Query</a><br />
  • branches/stable/templates/reclist.tmpl

    r649 r756  
    4949</table>
    5050
    51 <table width="100%">
     51<table width="100%" class="altrows">
    5252<TMPL_IF reclist>
    5353<tr class="darkrowheader">
     
    6262</tr>
    6363<TMPL_LOOP NAME=reclist>
    64 <tr class="row<TMPL_IF __odd__>0<TMPL_ELSE>1</TMPL_IF>">
     64<tr>
    6565<TMPL_IF fwdzone>
    6666        <td><TMPL_IF record_edit><a href="<TMPL_VAR NAME=script_self>&amp;page=record&amp;parentid=<TMPL_VAR
     
    8989</tr>
    9090</TMPL_LOOP>
    91 <tr class="darkrowheader"><td colspan="8" align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td></tr>
    9291<TMPL_ELSE>
    9392<tr><td colspan="8" align="center">No records found</td></tr>
    9493</TMPL_IF>
    9594</table>
     95
     96<TMPL_IF reclist><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF>
    9697
    9798</td></tr></table>
  • branches/stable/templates/useradmin.tmpl

    r649 r756  
    2222</table>
    2323
    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">
    2525<tr>
    2626<TMPL_LOOP NAME=colheads>       <td class="datahead_<TMPL_IF __first__>l<TMPL_ELSE>s</TMPL_IF>"><a href="<TMPL_VAR
     
    3434<TMPL_IF name=usertable>
    3535<TMPL_LOOP name=usertable>
    36 <tr class="row<TMPL_IF __odd__>0<TMPL_ELSE>1</TMPL_IF>">
     36<tr>
    3737        <td align="left"><TMPL_IF eduser><a href="<TMPL_VAR NAME=script_self>&amp;page=user&amp;useraction=edit&amp;user=<TMPL_VAR NAME=user_id>"><TMPL_VAR NAME=username></a><TMPL_ELSE><TMPL_VAR NAME=username></TMPL_IF></td>
    3838        <td class="data_nowrap"><TMPL_VAR name=fname></td>
     
    5151</tr>
    5252</TMPL_LOOP>
    53 <tr><td colspan="6" align="center"><TMPL_INCLUDE NAME="fpnla.tmpl"></td></tr>
    5453<TMPL_ELSE>
    5554<tr><td colspan="6" align="center">No users found</td></tr>
     
    5756</table>
    5857
     58<TMPL_IF usertable><div class="center vpad"><TMPL_INCLUDE NAME="fpnla.tmpl"></div></TMPL_IF>
     59
    5960</td>
    6061</tr>
  • branches/stable/textrecs.cgi

    r587 r756  
    33##
    44# $Id$
    5 # Copyright 2012,2013 Kris Deugau <kdeugau@deepnet.cx>
     5# Copyright 2012-2014 Kris Deugau <kdeugau@deepnet.cx>
    66#
    77#    This program is free software: you can redistribute it and/or modify
  • branches/stable/tiny-import.pl

    r649 r756  
    33##
    44# $Id$
    5 # Copyright 2012,2013 Kris Deugau <kdeugau@deepnet.cx>
     5# Copyright 2012-2014 Kris Deugau <kdeugau@deepnet.cx>
    66#
    77#    This program is free software: you can redistribute it and/or modify
Note: See TracChangeset for help on using the changeset viewer.