Ignore:
Timestamp:
12/11/13 16:01:18 (11 years ago)
Author:
Kris Deugau
Message:

/branches/stable

Merge reverse DNS work and object conversion from /trunk, part 5

Includes changes through r543 with a few more minor conflicts.

Location:
branches/stable
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/stable

  • branches/stable/dns.cgi

    r547 r548  
    33##
    44# $Id$
    5 # Copyright 2008-2012 Kris Deugau <kdeugau@deepnet.cx>
     5# Copyright 2008-2013 Kris Deugau <kdeugau@deepnet.cx>
    66#
    77#    This program is free software: you can redistribute it and/or modify
     
    3030use Net::DNS;
    3131use DBI;
     32
    3233use Data::Dumper;
    3334
     
    6566$webvar{revrec} = 'n' if !$webvar{revrec};      # non-reverse (domain) records
    6667
    67 # load some local system defaults (mainly DB connect info)
    68 # note this is not *absolutely* fatal, since there's a default dbname/user/pass in DNSDB.pm
    69 # we'll catch a bad DB connect string once we get to trying that
    70 ##fixme:  pass params to loadConfig, and use them there, to allow one codebase to support multiple sites
     68# create a DNSDB object.  this loads some local system defaults and connects to the DB
     69# with the credentials configured
     70##fixme:  pass params for loadConfig, and use them there, to allow one codebase to support multiple sites
    7171my $dnsdb = new DNSDB;
    7272
     
    7575$footer->param(version => $DNSDB::VERSION);
    7676
     77##fixme:  slim chance this could be triggered on errors other than DB failure?
    7778if (!$dnsdb) {
    7879  print "Content-type: text/html\n\n";
     
    8788$header->param(orgname => $dnsdb->{orgname}) if $dnsdb->{orgname} ne 'Example Corp';
    8889
    89 # persistent stuff needed on most/all pages
    90 my $sid = ($webvar{sid} ? $webvar{sid} : undef);
    91 my $session = new CGI::Session("driver:File", $sid, {Directory => $dnsdb->{sessiondir}})
     90my $logingroup;
     91my $curgroup;
     92my @viewablegroups;
     93
     94# retrieve the session ID from our cookie, if possible
     95my $sid = $q->cookie('dnsadmin_session');
     96
     97# see if the session loads
     98my $session = CGI::Session->load("driver:File", $sid, {Directory => $dnsdb->{sessiondir}})
    9299        or die CGI::Session->errstr();
    93 #$sid = $session->id() if !$sid;
     100
    94101if (!$sid) {
    95   # init stuff.  can probably axe this down to just above if'n'when user manipulation happens
    96   $sid = $session->id();
    97   $session->expire($dnsdb->{timeout});
    98 # need to know the "upper" group the user can deal with;  may as well
    99 # stick this in the session rather than calling out to the DB every time.
    100   $session->param('logingroup',1);
    101   $session->param('curgroup',1);        # yes, we *do* need to track this too.  er, probably.
    102   $session->param('domlistsortby','domain');
    103   $session->param('domlistorder','ASC');
    104   $session->param('revzonessortby','revnet');
    105   $session->param('revzonesorder','ASC');
    106   $session->param('useradminsortby','user');
    107   $session->param('useradminorder','ASC');
    108   $session->param('grpmansortby','group');
    109   $session->param('grpmanorder','ASC');
    110   $session->param('reclistsortby','host');
    111   $session->param('reclistorder','ASC');
    112   $session->param('loclistsortby','description');
    113   $session->param('loclistorder','ASC');
    114   $session->param('logsortby','stamp');
    115   $session->param('logorder','DESC');
     102  $webvar{page} = 'login';
     103} else {
     104  # we have a session to load from, maybe
     105  $logingroup = ($session->param('logingroup') ? $session->param('logingroup') : 1);
     106  $curgroup = ($session->param('curgroup') ? $session->param('curgroup') : $logingroup);
     107  # security check - does the user have permission to view this entity?
     108  # this is a prep step used "many" places
     109  $dnsdb->getChildren($logingroup, \@viewablegroups, 'all');
     110  push @viewablegroups, $logingroup;
     111##fixme: make sessions persist through closing the site?
     112# this even bridges browser close too.  hmm...
     113  $webvar{page} = 'domlist' if !$webvar{page};
    116114}
    117115
    118 # Just In Case.  Stale sessions should not be resurrectable.
    119 if ($sid ne $session->id()) {
    120   $sid = '';
    121   changepage(page=> "login", sessexpired => 1);
    122 }
    123 
    124 # normal expiry, more or less
    125 if ($session->is_expired) {
    126   $sid = '';
    127   changepage(page=> "login", sessexpired => 1);
    128 }
    129 
    130 my $logingroup = ($session->param('logingroup') ? $session->param('logingroup') : 1);
    131 my $curgroup = ($session->param('curgroup') ? $session->param('curgroup') : $logingroup);
    132 
    133 # decide which page to spit out...
    134 # also set $webvar{page} before we try to use it.
     116# set $webvar{page} before we try to use it.
    135117$webvar{page} = 'login' if !$webvar{page};
    136118
    137 # per-page startwith, filter, searchsubs
     119## per-page startwith, filter, searchsubs
    138120
    139121##fixme:  complain-munge-and-continue with non-"[a-z0-9-.]" filter and startwith
     
    150132$webvar{searchsubs} =~ s/[^yn]//g if $webvar{searchsubs};
    151133
    152 $session->param($webvar{page}.'startwith', $webvar{startwith}) if defined($webvar{startwith});
    153 $session->param($webvar{page}.'filter', $webvar{filter}) if defined($webvar{filter});
     134# pagination
     135my $perpage = 15;  # Just In Case
     136$perpage = $dnsdb->{perpage} if $dnsdb->{perpage};
     137my $offset = ($webvar{offset} ? $webvar{offset} : 0);
     138
     139## set up "URL to self" (whereami edition)
     140# @#$%@%@#% XHTML - & in a URL must be escaped.  >:(
     141my $uri_self = $ENV{REQUEST_URI};
     142$uri_self =~ s/\&([a-z])/\&amp\;$1/g;
     143
     144# le sigh.  and we need to strip any previous action
     145$uri_self =~ s/\&amp;action=[^&]+//g;
     146
     147# much magic happens.  if startwith or a search string change (to, from, or
     148# across, in the request vs whatever's in the session) then the offset should
     149# be reset to 0 so that the first/prev/next/last widget populates correctly,
     150# and so that the list of whatever we're looking at actually shows things
     151# (since we may have started on page 42 of 300 with a LOOOOONG list, but we
     152# now only need 3 pages for the filtered list).
     153# while we're at it, plonk these into the session for safekeeping.
     154if (defined($webvar{startwith})) {
     155  if ($webvar{startwith} ne $session->param($webvar{page}.'startwith')) {
     156    $uri_self =~ s/\&amp;offset=[^&]//;
     157    $offset = 0;
     158  }
     159  $session->param($webvar{page}.'startwith', $webvar{startwith});
     160}
     161if (defined($webvar{filter})) {
     162  if ($webvar{filter} ne $session->param($webvar{page}.'filter')) {
     163    $uri_self =~ s/\&amp;offset=[^&]//;
     164    $offset = 0;
     165  }
     166  $session->param($webvar{page}.'filter', $webvar{filter})
     167}
    154168$session->param($webvar{page}.'searchsubs', $webvar{searchsubs}) if defined($webvar{searchsubs});
    155169
     170# and now that the search/filter criteria for this page are set, put them in some globals for actual use.
    156171my $startwith = $session->param($webvar{page}.'startwith');
    157172my $filter = $session->param($webvar{page}.'filter');
     
    162177push @filterargs, "^[$startwith]" if $startwith;
    163178push @filterargs, $filter if $filter;
    164 
    165 ## set up "URL to self"
    166 # @#$%@%@#% XHTML - & in a URL must be escaped.  >:(
    167 my $uri_self = $ENV{REQUEST_URI};
    168 $uri_self =~ s/\&([a-z])/\&amp\;$1/g;
    169 
    170 # le sigh.  and we need to strip any previous action
    171 $uri_self =~ s/\&amp;action=[^&]+//g;
    172179
    173180# and search filter options.  these get stored in the session, but discarded
     
    181188
    182189# Fix up $uri_self so we don't lose the session/page
    183 $uri_self .= "?sid=$sid&amp;page=$webvar{page}" if $uri_self =~ m{/dns.cgi$};
    184 $uri_self = "$ENV{SCRIPT_NAME}?sid=$sid&amp;page=$webvar{page}$1" if $uri_self =~ m{/dns.cgi\&(.+)$};
    185 
    186 # pagination
    187 my $perpage = 15;
    188 $perpage = $dnsdb->{perpage} if $dnsdb->{perpage};
    189 my $offset = ($webvar{offset} ? $webvar{offset} : 0);
     190$uri_self .= "?page=$webvar{page}" if $uri_self =~ m{/dns.cgi$};
     191$uri_self = "$ENV{SCRIPT_NAME}?page=$webvar{page}$1" if $uri_self =~ m{/dns.cgi\&(.+)$};
     192
     193## end uri_self monkeying
    190194
    191195# NB:  these must match the field name and SQL ascend/descend syntax respectively
     196# sortby is reset to a suitable "default", then re-reset to whatever the user has
     197# clicked on last in the record=listing subs, but best to put a default here.
    192198my $sortby = "domain";
    193199my $sortorder = "ASC";
    194200
    195 # security check - does the user have permission to view this entity?
    196 # this is a prep step used "many" places
    197 my @viewablegroups;
    198 $dnsdb->getChildren($logingroup, \@viewablegroups, 'all');
    199 push @viewablegroups, $logingroup;
    200 
     201# Create the page template object.  Display a reasonable error page and whine if the template doesn't exist.
    201202my $page;
    202203eval {
     
    217218}
    218219
    219 # handle login redirect
     220my $sesscookie;
     221
     222# handle can-happen-on-(almost)-any-page actions
    220223if ($webvar{action}) {
     224
    221225  if ($webvar{action} eq 'login') {
    222226    # Snag ACL/permissions here too
     
    226230    if ($userdata) {
    227231
     232      # (re)create the session
     233      $session = new CGI::Session("driver:File", $sid, {Directory => $dnsdb->{sessiondir}})
     234        or die CGI::Session->errstr();
     235      $sid = $session->id();
     236
     237      $sesscookie = $q->cookie( -name => 'dnsadmin_session',
     238        -value => $sid,
     239        -expires => "+".$dnsdb->{timeout},
     240        -secure => 0,
     241## fixme:  need to extract root path for cookie, so as to limit cookie to dnsadmin instance
     242#        -path => $url
     243        );
     244
    228245      # set session bits
     246      $session->expire($dnsdb->{timeout});
    229247      $session->param('logingroup',$userdata->{group_id});
    230248      $session->param('curgroup',$userdata->{group_id});
     
    232250      $session->param('username',$webvar{username});
    233251
    234       changepage(page => "domlist");
     252# for reference.  seems we don't need to set these on login any more.
     253#  $session->param('domlistsortby','domain');
     254#  $session->param('domlistorder','ASC');
     255#  $session->param('revzonessortby','revnet');
     256#  $session->param('revzonesorder','ASC');
     257#  $session->param('useradminsortby','user');
     258#  $session->param('useradminorder','ASC');
     259#  $session->param('grpmansortby','group');
     260#  $session->param('grpmanorder','ASC');
     261#  $session->param('reclistsortby','host');
     262#  $session->param('reclistorder','ASC');
     263#  $session->param('loclistsortby','description');
     264#  $session->param('loclistorder','ASC');
     265#  $session->param('logsortby','stamp');
     266#  $session->param('logorder','DESC');
     267
     268      ## "recover my link" - tack on request bits and use requested page instead of hardcoding domlist
     269      # this could possibly be compacted by munging changepage a little so we don't have to deconstruct
     270      # and reconstruct the URI argument list.
     271      my %target = (page => "domlist");
     272      if ($webvar{target} && $webvar{target} =~ /\?/) {
     273        my $tmp = (split /\?/, $webvar{target})[1];
     274        $tmp =~ s/^\&//;
     275        my @targs = split /\&/, $tmp;
     276        foreach (@targs) {
     277          my ($k,$v) = split /=/;
     278          $target{$k} = $v if $k;
     279          # if we're going through a "session expired" login, we may have a different
     280          # "current group" than the login group.
     281          $session->param('curgroup', $v) if $k eq 'curgroup';
     282##fixme:  page=record goes "FOOM", sometimes - cause/fix?
     283        }
     284      }
     285      changepage(%target);
    235286
    236287    } else {
     
    243294    $session->flush();
    244295
     296    my $sesscookie = $q->cookie( -name => 'dnsadmin_session',
     297      -value => $sid,
     298      -expires => "-1",
     299      -secure => 0,
     300## fixme:  need to extract root path for cookie, so as to limit cookie to dnsadmin instance
     301#      -path => $url
     302      );
     303
    245304    my $newurl = "http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}";
    246305    $newurl =~ s|/[^/]+$|/|;
    247     print "Status: 302\nLocation: $newurl\n\n";
     306    print $q->redirect( -uri => $newurl, -cookie => $sesscookie);
    248307    exit;
    249308
    250   } elsif ($webvar{action} eq 'chgroup') {
     309  } elsif ($webvar{action} eq 'chgroup' && $webvar{page} ne 'login') {
    251310    # fiddle session-stored group data
    252311    # magic incantation to... uhhh...
     
    276335      changepage(%args);
    277336    }
    278 
    279   }
     337    # add offset back *into* $uri_self if we're also currently looking at a live record list.
     338    if ($webvar{page} eq 'reclist' && $webvar{defrec} eq 'n') {
     339      $uri_self .= "\&amp;offset=$offset";
     340    }
     341  } # done action=chgroup
    280342} # handle global webvar{action}s
     343
    281344
    282345# finally check if the user was disabled.  we could just leave this for logout/session expiry,
     
    295358$dnsdb->initActionLog($session->param('uid'));
    296359
    297 $page->param(sid => $sid) unless $webvar{page} eq 'login';      # no session ID on the login page
     360##
     361## Per-page processing
     362##
    298363
    299364if ($webvar{page} eq 'login') {
    300365
    301   $page->param(loginfailed => 1) if $webvar{loginfailed};
    302   $page->param(sessexpired => 1) if $webvar{sessexpired};
     366  my $target = $ENV{REQUEST_URI};
     367  $target =~ s/\&/\&amp;/g;
     368  $page->param(target => $target); # needs to be trimmed a little, maybe?
     369
     370  $page->param(sessexpired => 1) if (!$sid && $target !~ m|/$|);
     371
     372  if ($webvar{loginfailed}) {
     373    $page->param(loginfailed => 1);
     374    $webvar{target} =~ s/\&/\&amp;/g;   # XHTML we do (not) love you so
     375    $page->param(target => $webvar{target}) if $webvar{target};
     376  }
     377#  if $webvar{sessexpired};      # or this with below?
     378  if ($session->is_expired) {
     379    $page->param(sessexpired => 1);
     380    $session->delete();   # Just to make sure
     381    $session->flush();
     382  }
    303383  $page->param(version => $DNSDB::VERSION);
     384  $page->param(script_self => ($ENV{SCRIPT_NAME} =~ m|/([^/]+)$|)[0]);
    304385
    305386} elsif ($webvar{page} eq 'domlist' or $webvar{page} eq 'index') {
     
    337418  $webvar{group} = $curgroup if !$webvar{group};
    338419  fill_grouplist("grouplist", $webvar{group});
    339   fill_loclist();
     420  fill_loclist($curgroup, $webvar{defloc} ? $webvar{defloc} : '');
    340421
    341422  if ($session->param('add_failed')) {
     
    363444  $webvar{makeactive} = 0 if !defined($webvar{makeactive});
    364445
    365   my ($code,$msg) = $dnsdb->addDomain($webvar{domain}, $webvar{group}, ($webvar{makeactive} eq 'on' ? 1 : 0));
     446  my ($code,$msg) = $dnsdb->addDomain($webvar{domain}, $webvar{group}, ($webvar{makeactive} eq 'on' ? 1 : 0),
     447        $webvar{defloc});
    366448
    367449  if ($code eq 'OK') {
     
    373455    $session->param('add_failed', 1);
    374456##fixme:  domain a security risk for XSS?
    375     changepage(page => "newdomain", domain => $webvar{domain}, errmsg => $msg,
    376         makeactive => ($webvar{makeactive} ? 'y' : 'n'), group => $webvar{group});
     457    changepage(page => "newdomain", errmsg => $msg, domain => $webvar{domain},
     458        group => $webvar{group}, makeactive => ($webvar{makeactive} ? 'y' : 'n'), defloc => $webvar{defloc});
    377459  }
    378460
     
    640722
    641723    my @recargs = ($webvar{defrec}, $webvar{revrec}, $webvar{parentid},
    642         \$webvar{name}, \$webvar{type}, \$webvar{address}, $webvar{ttl}, $webvar{location});
     724        \$webvar{name}, \$webvar{type}, \$webvar{address}, $webvar{ttl}, $webvar{location},
     725        $webvar{expires}, $webvar{stamp});
    643726    if ($webvar{type} == $reverse_typemap{MX} or $webvar{type} == $reverse_typemap{SRV}) {
    644727      push @recargs, $webvar{distance};
     
    688771    $page->param(ttl            => $recdata->{ttl});
    689772    $page->param(typelist       => $dnsdb->getTypelist($webvar{revrec}, $recdata->{type}));
    690 
     773    if ($recdata->{stampactive}) {
     774      $page->param(stamp => $recdata->{stamp});
     775      $page->param(stamp_until => $recdata->{expires});
     776    }
    691777    if ($webvar{defrec} eq 'n') {
    692778      fill_loclist($curgroup, $recdata->{location});
     
    704790    my ($code,$msg) = $dnsdb->updateRec($webvar{defrec}, $webvar{revrec}, $webvar{id}, $webvar{parentid},
    705791        \$webvar{name}, \$webvar{type}, \$webvar{address}, $webvar{ttl}, $webvar{location},
     792        $webvar{expires}, $webvar{stamp},
    706793        $webvar{distance}, $webvar{weight}, $webvar{port});
    707794
     
    10011088  $page->param(perpage => $perpage);
    10021089
    1003   my $domlist = $dnsdb->getZoneList(revrec => 'n', curgroup => $curgroup);
     1090  my $domlist = $dnsdb->getZoneList(revrec => 'n', curgroup => $curgroup, offset => $offset);
    10041091  my $rownum = 0;
    10051092  foreach my $dom (@{$domlist}) {
     
    16931780
    16941781# start output here so we can redirect pages.
    1695 print "Content-type: text/html\n\n", $header->output;
     1782print $q->header( -cookie => $sesscookie);
     1783print $header->output;
    16961784
    16971785##common bits
     
    17221810  $page->param(inlogingrp => $curgroup == $logingroup);
    17231811
    1724 # fill in the URL-to-self
     1812# fill in the URL-to-self for the group tree and search-by-letter
    17251813  $page->param(whereami => $uri_self);
     1814# fill in general URL-to-self
     1815  $page->param(script_self => "$ENV{SCRIPT_NAME}?".($curgroup ? "curgroup=$curgroup" : ''));
    17261816}
    17271817
     
    17661856
    17671857  my @childlist;
     1858
     1859  # some magic to control bad offsets on group change
     1860  my $grp_uri_self = $uri_self;
     1861  $grp_uri_self =~ s/\&amp;offset=[^&]+// unless ($webvar{page} eq 'reclist' && $webvar{defrec} eq 'n');
    17681862
    17691863  my $grptree = HTML::Template->new(filename => 'templates/grptree.tmpl');
     
    17751869    $row{grpname} = $dnsdb->groupName($_);
    17761870    $row{grpnum} = $_;
    1777     $row{whereami} = $uri_self;
     1871    $row{whereami} = $grp_uri_self;
    17781872    $row{curgrp} = ($_ == $cur);
    17791873    $row{expanded} = $dnsdb->isParent($_, 'group', $cur, 'group');
     
    18051899
    18061900  # handle user check
    1807   my $newurl = "http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}?sid=$sid";
     1901  my $newurl = "http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}?";
    18081902  foreach (sort keys %params) {
    18091903## fixme:  something is undefined here on add location
     
    18141908  $session->flush();
    18151909
    1816   print "Status: 302\nLocation: $newurl\n\n";
     1910  print $q->redirect ( -url => $newurl, -cookie => $sesscookie);
    18171911  exit;
    18181912} # end changepage
     
    19011995  $page->param(ttl      => $soa->{ttl});
    19021996
    1903   my $foo2 = $dnsdb->getDomRecs(defrec => $def, revrec => $rev, id => $id, offset => $webvar{offset},
     1997  my $foo2 = $dnsdb->getRecList(defrec => $def, revrec => $rev, id => $id, offset => $webvar{offset},
    19041998        sortby => $sortby, sortorder => $sortorder, filter => $filter);
    19051999
    19062000  foreach my $rec (@$foo2) {
    19072001    $rec->{type} = $typemap{$rec->{type}};
    1908     $rec->{sid} = $webvar{sid};
    19092002    $rec->{fwdzone} = $rev eq 'n';
    19102003    $rec->{distance} = 'n/a' unless ($rec->{type} eq 'MX' || $rec->{type} eq 'SRV');
     
    19152008    $rec->{record_delete} = ($permissions{admin} || $permissions{record_delete});
    19162009    $rec->{locname} = '' unless ($permissions{admin} || $permissions{location_view});
     2010# Timestamps
     2011    if ($rec->{expires}) {
     2012      $rec->{stamptype} = $rec->{ispast} ? 'expired at' : 'expires at';
     2013    } else {
     2014      $rec->{stamptype} = 'valid after';
     2015    }
     2016    # strip seconds and timezone?  no, not yet.  could probably offer a config knob on this display at some point.
     2017#    $rec->{stamp} =~ s/:\d\d-\d+$//;
     2018    delete $rec->{expires};
     2019    delete $rec->{ispast};
    19172020  }
    19182021  $page->param(reclist => $foo2);
     
    19452048  my $soa = $dnsdb->getSOA($webvar{defrec}, $webvar{revrec}, $webvar{parentid});
    19462049  $page->param(ttl      => ($webvar{ttl} ? $webvar{ttl} : $soa->{minttl}));
     2050  $page->param(stamp_until => ($webvar{expires} eq 'until'));
     2051  $page->param(stamp => $webvar{stamp});
    19472052}
    19482053
     
    20062111  my $parent = shift;
    20072112
    2008   # Fix display/UI bug where if you are not on the first page of the list, and
    2009   # you add a search term or click one of the "starts with" links, you end up
    2010   # on a page showing nothing.
    2011   # For bonus points, this reverts to the original offset on clicking the "All" link (mostly)
    2012   if ($offset ne 'all') {
    2013     $offset-- while ($offset * $perpage) >= $pgcount;
    2014   }
    2015 
    20162113  $page->param(ntot => $pgcount);
    20172114  $page->param(nfirst => (($offset eq 'all' ? 0 : $offset)*$perpage+1));
     
    20442141  fill_fpnla($count);
    20452142
     2143  $sortby = ($webvar{revrec} eq 'n' ? 'domain' : 'revnet');
    20462144# sort/order
    20472145  $session->param($webvar{page}.'sortby', $webvar{sortby}) if $webvar{sortby};
     
    20712169  my $zonelist = $dnsdb->getZoneList(childlist => $childlist, curgroup => $curgroup, revrec => $webvar{revrec},
    20722170        filter => ($filter ? $filter : undef), startwith => ($startwith ? $startwith : undef),
    2073         offset => $webvar{offset}, sortby => $sortby, sortorder => $sortorder
     2171        offset => $offset, sortby => $sortby, sortorder => $sortorder
    20742172        );
    20752173# probably don't need this, keeping for reference for now
     
    22922390  foreach my $col (@$cols) {
    22932391    my %coldata;
    2294     $coldata{sid} = $sid;
    22952392    $coldata{page} = $webvar{page};
    22962393    $coldata{offset} = $webvar{offset} if $webvar{offset};
Note: See TracChangeset for help on using the changeset viewer.