Changeset 548 for branches/stable/dns.cgi
- Timestamp:
- 12/11/13 16:01:18 (11 years ago)
- Location:
- branches/stable
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable
- Property svn:mergeinfo changed
/trunk merged: 493-534,536-543
- Property svn:mergeinfo changed
-
branches/stable/dns.cgi
r547 r548 3 3 ## 4 4 # $Id$ 5 # Copyright 2008-201 2Kris Deugau <kdeugau@deepnet.cx>5 # Copyright 2008-2013 Kris Deugau <kdeugau@deepnet.cx> 6 6 # 7 7 # This program is free software: you can redistribute it and/or modify … … 30 30 use Net::DNS; 31 31 use DBI; 32 32 33 use Data::Dumper; 33 34 … … 65 66 $webvar{revrec} = 'n' if !$webvar{revrec}; # non-reverse (domain) records 66 67 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 71 71 my $dnsdb = new DNSDB; 72 72 … … 75 75 $footer->param(version => $DNSDB::VERSION); 76 76 77 ##fixme: slim chance this could be triggered on errors other than DB failure? 77 78 if (!$dnsdb) { 78 79 print "Content-type: text/html\n\n"; … … 87 88 $header->param(orgname => $dnsdb->{orgname}) if $dnsdb->{orgname} ne 'Example Corp'; 88 89 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}}) 90 my $logingroup; 91 my $curgroup; 92 my @viewablegroups; 93 94 # retrieve the session ID from our cookie, if possible 95 my $sid = $q->cookie('dnsadmin_session'); 96 97 # see if the session loads 98 my $session = CGI::Session->load("driver:File", $sid, {Directory => $dnsdb->{sessiondir}}) 92 99 or die CGI::Session->errstr(); 93 #$sid = $session->id() if !$sid; 100 94 101 if (!$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}; 116 114 } 117 115 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. 135 117 $webvar{page} = 'login' if !$webvar{page}; 136 118 137 # per-page startwith, filter, searchsubs119 ## per-page startwith, filter, searchsubs 138 120 139 121 ##fixme: complain-munge-and-continue with non-"[a-z0-9-.]" filter and startwith … … 150 132 $webvar{searchsubs} =~ s/[^yn]//g if $webvar{searchsubs}; 151 133 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 135 my $perpage = 15; # Just In Case 136 $perpage = $dnsdb->{perpage} if $dnsdb->{perpage}; 137 my $offset = ($webvar{offset} ? $webvar{offset} : 0); 138 139 ## set up "URL to self" (whereami edition) 140 # @#$%@%@#% XHTML - & in a URL must be escaped. >:( 141 my $uri_self = $ENV{REQUEST_URI}; 142 $uri_self =~ s/\&([a-z])/\&\;$1/g; 143 144 # le sigh. and we need to strip any previous action 145 $uri_self =~ s/\&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. 154 if (defined($webvar{startwith})) { 155 if ($webvar{startwith} ne $session->param($webvar{page}.'startwith')) { 156 $uri_self =~ s/\&offset=[^&]//; 157 $offset = 0; 158 } 159 $session->param($webvar{page}.'startwith', $webvar{startwith}); 160 } 161 if (defined($webvar{filter})) { 162 if ($webvar{filter} ne $session->param($webvar{page}.'filter')) { 163 $uri_self =~ s/\&offset=[^&]//; 164 $offset = 0; 165 } 166 $session->param($webvar{page}.'filter', $webvar{filter}) 167 } 154 168 $session->param($webvar{page}.'searchsubs', $webvar{searchsubs}) if defined($webvar{searchsubs}); 155 169 170 # and now that the search/filter criteria for this page are set, put them in some globals for actual use. 156 171 my $startwith = $session->param($webvar{page}.'startwith'); 157 172 my $filter = $session->param($webvar{page}.'filter'); … … 162 177 push @filterargs, "^[$startwith]" if $startwith; 163 178 push @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])/\&\;$1/g;169 170 # le sigh. and we need to strip any previous action171 $uri_self =~ s/\&action=[^&]+//g;172 179 173 180 # and search filter options. these get stored in the session, but discarded … … 181 188 182 189 # Fix up $uri_self so we don't lose the session/page 183 $uri_self .= "?sid=$sid&page=$webvar{page}" if $uri_self =~ m{/dns.cgi$}; 184 $uri_self = "$ENV{SCRIPT_NAME}?sid=$sid&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 190 194 191 195 # 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. 192 198 my $sortby = "domain"; 193 199 my $sortorder = "ASC"; 194 200 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. 201 202 my $page; 202 203 eval { … … 217 218 } 218 219 219 # handle login redirect 220 my $sesscookie; 221 222 # handle can-happen-on-(almost)-any-page actions 220 223 if ($webvar{action}) { 224 221 225 if ($webvar{action} eq 'login') { 222 226 # Snag ACL/permissions here too … … 226 230 if ($userdata) { 227 231 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 228 245 # set session bits 246 $session->expire($dnsdb->{timeout}); 229 247 $session->param('logingroup',$userdata->{group_id}); 230 248 $session->param('curgroup',$userdata->{group_id}); … … 232 250 $session->param('username',$webvar{username}); 233 251 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); 235 286 236 287 } else { … … 243 294 $session->flush(); 244 295 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 245 304 my $newurl = "http://$ENV{HTTP_HOST}$ENV{SCRIPT_NAME}"; 246 305 $newurl =~ s|/[^/]+$|/|; 247 print "Status: 302\nLocation: $newurl\n\n";306 print $q->redirect( -uri => $newurl, -cookie => $sesscookie); 248 307 exit; 249 308 250 } elsif ($webvar{action} eq 'chgroup' ) {309 } elsif ($webvar{action} eq 'chgroup' && $webvar{page} ne 'login') { 251 310 # fiddle session-stored group data 252 311 # magic incantation to... uhhh... … … 276 335 changepage(%args); 277 336 } 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 .= "\&offset=$offset"; 340 } 341 } # done action=chgroup 280 342 } # handle global webvar{action}s 343 281 344 282 345 # finally check if the user was disabled. we could just leave this for logout/session expiry, … … 295 358 $dnsdb->initActionLog($session->param('uid')); 296 359 297 $page->param(sid => $sid) unless $webvar{page} eq 'login'; # no session ID on the login page 360 ## 361 ## Per-page processing 362 ## 298 363 299 364 if ($webvar{page} eq 'login') { 300 365 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/\&/\&/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/\&/\&/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 } 303 383 $page->param(version => $DNSDB::VERSION); 384 $page->param(script_self => ($ENV{SCRIPT_NAME} =~ m|/([^/]+)$|)[0]); 304 385 305 386 } elsif ($webvar{page} eq 'domlist' or $webvar{page} eq 'index') { … … 337 418 $webvar{group} = $curgroup if !$webvar{group}; 338 419 fill_grouplist("grouplist", $webvar{group}); 339 fill_loclist( );420 fill_loclist($curgroup, $webvar{defloc} ? $webvar{defloc} : ''); 340 421 341 422 if ($session->param('add_failed')) { … … 363 444 $webvar{makeactive} = 0 if !defined($webvar{makeactive}); 364 445 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}); 366 448 367 449 if ($code eq 'OK') { … … 373 455 $session->param('add_failed', 1); 374 456 ##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}); 377 459 } 378 460 … … 640 722 641 723 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}); 643 726 if ($webvar{type} == $reverse_typemap{MX} or $webvar{type} == $reverse_typemap{SRV}) { 644 727 push @recargs, $webvar{distance}; … … 688 771 $page->param(ttl => $recdata->{ttl}); 689 772 $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 } 691 777 if ($webvar{defrec} eq 'n') { 692 778 fill_loclist($curgroup, $recdata->{location}); … … 704 790 my ($code,$msg) = $dnsdb->updateRec($webvar{defrec}, $webvar{revrec}, $webvar{id}, $webvar{parentid}, 705 791 \$webvar{name}, \$webvar{type}, \$webvar{address}, $webvar{ttl}, $webvar{location}, 792 $webvar{expires}, $webvar{stamp}, 706 793 $webvar{distance}, $webvar{weight}, $webvar{port}); 707 794 … … 1001 1088 $page->param(perpage => $perpage); 1002 1089 1003 my $domlist = $dnsdb->getZoneList(revrec => 'n', curgroup => $curgroup );1090 my $domlist = $dnsdb->getZoneList(revrec => 'n', curgroup => $curgroup, offset => $offset); 1004 1091 my $rownum = 0; 1005 1092 foreach my $dom (@{$domlist}) { … … 1693 1780 1694 1781 # start output here so we can redirect pages. 1695 print "Content-type: text/html\n\n", $header->output; 1782 print $q->header( -cookie => $sesscookie); 1783 print $header->output; 1696 1784 1697 1785 ##common bits … … 1722 1810 $page->param(inlogingrp => $curgroup == $logingroup); 1723 1811 1724 # fill in the URL-to-self 1812 # fill in the URL-to-self for the group tree and search-by-letter 1725 1813 $page->param(whereami => $uri_self); 1814 # fill in general URL-to-self 1815 $page->param(script_self => "$ENV{SCRIPT_NAME}?".($curgroup ? "curgroup=$curgroup" : '')); 1726 1816 } 1727 1817 … … 1766 1856 1767 1857 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/\&offset=[^&]+// unless ($webvar{page} eq 'reclist' && $webvar{defrec} eq 'n'); 1768 1862 1769 1863 my $grptree = HTML::Template->new(filename => 'templates/grptree.tmpl'); … … 1775 1869 $row{grpname} = $dnsdb->groupName($_); 1776 1870 $row{grpnum} = $_; 1777 $row{whereami} = $ uri_self;1871 $row{whereami} = $grp_uri_self; 1778 1872 $row{curgrp} = ($_ == $cur); 1779 1873 $row{expanded} = $dnsdb->isParent($_, 'group', $cur, 'group'); … … 1805 1899 1806 1900 # 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}?"; 1808 1902 foreach (sort keys %params) { 1809 1903 ## fixme: something is undefined here on add location … … 1814 1908 $session->flush(); 1815 1909 1816 print "Status: 302\nLocation: $newurl\n\n";1910 print $q->redirect ( -url => $newurl, -cookie => $sesscookie); 1817 1911 exit; 1818 1912 } # end changepage … … 1901 1995 $page->param(ttl => $soa->{ttl}); 1902 1996 1903 my $foo2 = $dnsdb->get DomRecs(defrec => $def, revrec => $rev, id => $id, offset => $webvar{offset},1997 my $foo2 = $dnsdb->getRecList(defrec => $def, revrec => $rev, id => $id, offset => $webvar{offset}, 1904 1998 sortby => $sortby, sortorder => $sortorder, filter => $filter); 1905 1999 1906 2000 foreach my $rec (@$foo2) { 1907 2001 $rec->{type} = $typemap{$rec->{type}}; 1908 $rec->{sid} = $webvar{sid};1909 2002 $rec->{fwdzone} = $rev eq 'n'; 1910 2003 $rec->{distance} = 'n/a' unless ($rec->{type} eq 'MX' || $rec->{type} eq 'SRV'); … … 1915 2008 $rec->{record_delete} = ($permissions{admin} || $permissions{record_delete}); 1916 2009 $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}; 1917 2020 } 1918 2021 $page->param(reclist => $foo2); … … 1945 2048 my $soa = $dnsdb->getSOA($webvar{defrec}, $webvar{revrec}, $webvar{parentid}); 1946 2049 $page->param(ttl => ($webvar{ttl} ? $webvar{ttl} : $soa->{minttl})); 2050 $page->param(stamp_until => ($webvar{expires} eq 'until')); 2051 $page->param(stamp => $webvar{stamp}); 1947 2052 } 1948 2053 … … 2006 2111 my $parent = shift; 2007 2112 2008 # Fix display/UI bug where if you are not on the first page of the list, and2009 # you add a search term or click one of the "starts with" links, you end up2010 # 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 2016 2113 $page->param(ntot => $pgcount); 2017 2114 $page->param(nfirst => (($offset eq 'all' ? 0 : $offset)*$perpage+1)); … … 2044 2141 fill_fpnla($count); 2045 2142 2143 $sortby = ($webvar{revrec} eq 'n' ? 'domain' : 'revnet'); 2046 2144 # sort/order 2047 2145 $session->param($webvar{page}.'sortby', $webvar{sortby}) if $webvar{sortby}; … … 2071 2169 my $zonelist = $dnsdb->getZoneList(childlist => $childlist, curgroup => $curgroup, revrec => $webvar{revrec}, 2072 2170 filter => ($filter ? $filter : undef), startwith => ($startwith ? $startwith : undef), 2073 offset => $ webvar{offset}, sortby => $sortby, sortorder => $sortorder2171 offset => $offset, sortby => $sortby, sortorder => $sortorder 2074 2172 ); 2075 2173 # probably don't need this, keeping for reference for now … … 2292 2390 foreach my $col (@$cols) { 2293 2391 my %coldata; 2294 $coldata{sid} = $sid;2295 2392 $coldata{page} = $webvar{page}; 2296 2393 $coldata{offset} = $webvar{offset} if $webvar{offset};
Note:
See TracChangeset
for help on using the changeset viewer.