X-Git-Url: http://git.rot13.org/?p=BackupPC.git;a=blobdiff_plain;f=lib%2FBackupPC%2FCGI%2FLib.pm;h=44afe9d9f7bbf0356360fb3d6cadbd5980ef2a4f;hp=078f3fd18ca098ca003372ccd6f237556737b8a9;hb=ca593f66fd6c35764bd8997c6338b781330f019c;hpb=359a795122e5fd5888ad92731147dcd7c1d6db12 diff --git a/lib/BackupPC/CGI/Lib.pm b/lib/BackupPC/CGI/Lib.pm index 078f3fd..44afe9d 100644 --- a/lib/BackupPC/CGI/Lib.pm +++ b/lib/BackupPC/CGI/Lib.pm @@ -11,7 +11,7 @@ # Craig Barratt # # COPYRIGHT -# Copyright (C) 2003 Craig Barratt +# Copyright (C) 2003-2009 Craig Barratt # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -29,7 +29,7 @@ # #======================================================================== # -# Version 2.1.0_CVS, released 3 Jul 2003. +# Version 3.2.0beta0, released 5 April 2009. # # See http://backuppc.sourceforge.net. # @@ -44,11 +44,11 @@ require Exporter; use vars qw( @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS ); -use vars qw($Cgi %In $MyURL $User %Conf $TopDir $BinDir $bpc); +use vars qw($Cgi %In $MyURL $User %Conf $TopDir $LogDir $BinDir $bpc); use vars qw(%Status %Info %Jobs @BgQueue @UserQueue @CmdQueue %QueueLen %StatusHost); use vars qw($Hosts $HostsMTime $ConfigMTime $PrivAdmin); -use vars qw(%UserEmailInfo $UserEmailInfoMTime %RestoreReq); +use vars qw(%UserEmailInfo $UserEmailInfoMTime %RestoreReq %ArchiveReq); use vars qw($Lang); @ISA = qw(Exporter); @@ -76,11 +76,11 @@ use vars qw($Lang); NavLink h1 h2 - $Cgi %In $MyURL $User %Conf $TopDir $BinDir $bpc + $Cgi %In $MyURL $User %Conf $TopDir $LogDir $BinDir $bpc %Status %Info %Jobs @BgQueue @UserQueue @CmdQueue %QueueLen %StatusHost $Hosts $HostsMTime $ConfigMTime $PrivAdmin - %UserEmailInfo $UserEmailInfoMTime %RestoreReq + %UserEmailInfo $UserEmailInfoMTime %RestoreReq %ArchiveReq $Lang ); @@ -93,11 +93,32 @@ sub NewRequest $Cgi = new CGI; %In = $Cgi->Vars; + if ( !defined($bpc) ) { + ErrorExit($Lang->{BackupPC__Lib__new_failed__check_apache_error_log}) + if ( !($bpc = BackupPC::Lib->new(undef, undef, undef, 1)) ); + $TopDir = $bpc->TopDir(); + $LogDir = $bpc->LogDir(); + $BinDir = $bpc->BinDir(); + %Conf = $bpc->Conf(); + $Lang = $bpc->Lang(); + $ConfigMTime = $bpc->ConfigMTime(); + umask($Conf{UmaskMode}); + } elsif ( $bpc->ConfigMTime() != $ConfigMTime ) { + $bpc->ConfigRead(); + $TopDir = $bpc->TopDir(); + $LogDir = $bpc->LogDir(); + $BinDir = $bpc->BinDir(); + %Conf = $bpc->Conf(); + $Lang = $bpc->Lang(); + $ConfigMTime = $bpc->ConfigMTime(); + umask($Conf{UmaskMode}); + } + # # Default REMOTE_USER so in a miminal installation the user # has a sensible default. # - $ENV{REMOTE_USER} = $Conf{BackupPCUser} if ( !defined($ENV{REMOTE_USER}) ); + $ENV{REMOTE_USER} = $Conf{BackupPCUser} if ( $ENV{REMOTE_USER} eq "" ); # # We require that Apache pass in $ENV{SCRIPT_NAME} and $ENV{REMOTE_USER}. @@ -108,20 +129,10 @@ sub NewRequest $MyURL = $ENV{SCRIPT_NAME}; $User = $ENV{REMOTE_USER}; - if ( !defined($bpc) ) { - ErrorExit($Lang->{BackupPC__Lib__new_failed__check_apache_error_log}) - if ( !($bpc = BackupPC::Lib->new(undef, undef, 1)) ); - $TopDir = $bpc->TopDir(); - $BinDir = $bpc->BinDir(); - %Conf = $bpc->Conf(); - $Lang = $bpc->Lang(); - $ConfigMTime = $bpc->ConfigMTime(); - } elsif ( $bpc->ConfigMTime() != $ConfigMTime ) { - $bpc->ConfigRead(); - %Conf = $bpc->Conf(); - $ConfigMTime = $bpc->ConfigMTime(); - $Lang = $bpc->Lang(); - } + # + # Handle LDAP uid=user when using mod_authz_ldap and otherwise untaint + # + $User = $1 if ( $User =~ /uid=([^,]+)/i || $User =~ /(.*)/ ); # # Clean up %ENV for taint checking @@ -156,6 +167,15 @@ EOF {map {$_, 1} split(",", $Hosts->{$host}{moreUsers}) } } } + + # + # Untaint the host name + # + if ( $In{host} =~ /^([\w.\s-]+)$/ ) { + $In{host} = $1; + } else { + delete($In{host}); + } } sub timeStamp2 @@ -163,7 +183,10 @@ sub timeStamp2 my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($_[0] == 0 ? time : $_[0] ); $mon++; - if ( $Conf{CgiDateFormatMMDD} ) { + if ( $Conf{CgiDateFormatMMDD} == 2 ) { + $year += 1900; + return sprintf("%04d-%02d-%02d %02d:%02d", $year, $mon, $mday, $hour, $min); + } elsif ( $Conf{CgiDateFormatMMDD} ) { return sprintf("$mon/$mday %02d:%02d", $hour, $min); } else { return sprintf("$mday/$mon %02d:%02d", $hour, $min); @@ -207,7 +230,7 @@ sub EscHTML $s =~ s/\"/"/g; $s =~ s/>/>/g; $s =~ s/\n

", @mesg); - $Conf{CgiHeaderFontType} ||= "arial"; - $Conf{CgiHeaderFontSize} ||= "3"; - $Conf{CgiNavBarBgColor} ||= "#ddeeee"; - $Conf{CgiHeaderBgColor} ||= "#99cc33"; if ( !defined($ENV{REMOTE_USER}) ) { $mesg .= <ServerMesg("log User $User (host=$In{host}) got CGI error: $head") if ( defined($bpc) ); if ( !defined($Lang->{Error}) ) { - Header("BackupPC: Error"); $mesg = <$mesg

EOF + Header("BackupPC: Error", $content); Trailer(); } else { - Header(eval("qq{$Lang->{Error}}")); - print (eval("qq{$Lang->{Error____head}}")); + my $content = eval("qq{$Lang->{Error____head}}"); + Header(eval("qq{$Lang->{Error}}"), $content); Trailer(); } exit(1); @@ -267,7 +286,17 @@ sub ServerConnect return if ( $bpc->ServerOK() ); $bpc->ServerDisconnect(); if ( my $err = $bpc->ServerConnect($Conf{ServerHost}, $Conf{ServerPort}) ) { - ErrorExit(eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server}}")); + if ( CheckPermission() + && -f $Conf{ServerInitdPath} + && $Conf{ServerInitdStartCmd} ne "" ) { + my $content = eval("qq{$Lang->{Admin_Start_Server}}"); + Header(eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server}}"), $content); + Trailer(); + exit(1); + } else { + ErrorExit(eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server}}"), + eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server_error_message}}")); + } } } @@ -275,21 +304,25 @@ sub GetStatusInfo { my($status) = @_; ServerConnect(); + %Status = () if ( $status =~ /\bhosts\b/ ); + %StatusHost = () if ( $status =~ /\bhost\(/ ); my $reply = $bpc->ServerMesg("status $status"); $reply = $1 if ( $reply =~ /(.*)/s ); eval($reply); # ignore status related to admin and trashClean jobs if ( $status =~ /\bhosts\b/ ) { - delete($Status{$bpc->adminJob}); + foreach my $host ( grep(/admin/, keys(%Status)) ) { + delete($Status{$host}) if ( $bpc->isAdminJob($host) ); + } delete($Status{$bpc->trashJob}); } } sub ReadUserEmailInfo { - if ( (stat("$TopDir/log/UserEmailInfo.pl"))[9] != $UserEmailInfoMTime ) { - do "$TopDir/log/UserEmailInfo.pl"; - $UserEmailInfoMTime = (stat("$TopDir/log/UserEmailInfo.pl"))[9]; + if ( (stat("$LogDir/UserEmailInfo.pl"))[9] != $UserEmailInfoMTime ) { + do "$LogDir/UserEmailInfo.pl"; + $UserEmailInfoMTime = (stat("$LogDir/UserEmailInfo.pl"))[9]; } } @@ -310,34 +343,38 @@ sub CheckPermission || $host ne "" && !defined($Hosts->{$host}) ); if ( $Conf{CgiAdminUserGroup} ne "" ) { my($n,$p,$gid,$mem) = getgrnam($Conf{CgiAdminUserGroup}); - $Privileged ||= ($mem =~ /\b$User\b/); + $Privileged ||= ($mem =~ /\b\Q$User\E\b/); } if ( $Conf{CgiAdminUsers} ne "" ) { - $Privileged ||= ($Conf{CgiAdminUsers} =~ /\b$User\b/); + $Privileged ||= ($Conf{CgiAdminUsers} =~ /\b\Q$User\E\b/); $Privileged ||= $Conf{CgiAdminUsers} eq "*"; } $PrivAdmin = $Privileged; + return $Privileged if ( !defined($host) ); + $Privileged ||= $User eq $Hosts->{$host}{user}; $Privileged ||= defined($Hosts->{$host}{moreUsers}{$User}); - return $Privileged; } # # Returns the list of hosts that should appear in the navigation bar -# for this user. If $Conf{CgiNavBarAdminAllHosts} is set, the admin -# gets all the hosts. Otherwise, regular users get hosts for which -# they are the user or are listed in the moreUsers column in the -# hosts file. +# for this user. If $getAll is set, the admin gets all the hosts. +# Otherwise, regular users get hosts for which they are the user or +# are listed in the moreUsers column in the hosts file. # sub GetUserHosts { - if ( $Conf{CgiNavBarAdminAllHosts} && CheckPermission() ) { - return sort keys %$Hosts; - } + my($getAll) = @_; + my @hosts; - return sort grep { $Hosts->{$_}{user} eq $User || + if ( $getAll && CheckPermission() ) { + @hosts = sort keys %$Hosts; + } else { + @hosts = sort grep { $Hosts->{$_}{user} eq $User || defined($Hosts->{$_}{moreUsers}{$User}) } keys(%$Hosts); + } + return @hosts; } # @@ -381,94 +418,136 @@ sub ConfirmIPAddress sub Header { - my($title) = @_; + my($title, $content, $noBrowse, $contentSub, $contentPost) = @_; my @adminLinks = ( - { link => "", name => $Lang->{Status}, - priv => 1}, - { link => "?action=summary", name => $Lang->{PC_Summary} }, - { link => "?action=view&type=LOG", name => $Lang->{LOG_file} }, - { link => "?action=LOGlist", name => $Lang->{Old_LOGs} }, - { link => "?action=emailSummary", name => $Lang->{Email_summary} }, - { link => "?action=view&type=config", name => $Lang->{Config_file} }, - { link => "?action=view&type=hosts", name => $Lang->{Hosts_file} }, - { link => "?action=queue", name => $Lang->{Current_queues} }, - { link => "?action=view&type=docs", name => $Lang->{Documentation}, - priv => 1}, - { link => "http://backuppc.sourceforge.net/faq", name => "FAQ", - priv => 1}, - { link => "http://backuppc.sourceforge.net", name => "SourceForge", - priv => 1}, + { link => "", name => $Lang->{Status}}, + { link => "?action=summary", name => $Lang->{PC_Summary}}, + { link => "?action=editConfig", name => $Lang->{CfgEdit_Edit_Config}, + priv => 1}, + { link => "?action=editConfig&newMenu=hosts", + name => $Lang->{CfgEdit_Edit_Hosts}, + priv => 1}, + { link => "?action=adminOpts", name => $Lang->{Admin_Options}, + priv => 1}, + { link => "?action=view&type=LOG", name => $Lang->{LOG_file}, + priv => 1}, + { link => "?action=LOGlist", name => $Lang->{Old_LOGs}, + priv => 1}, + { link => "?action=emailSummary", name => $Lang->{Email_summary}, + priv => 1}, + { link => "?action=queue", name => $Lang->{Current_queues}, + priv => 1}, + @{$Conf{CgiNavBarLinks} || []}, ); - print $Cgi->header(); + my $host = $In{host}; + + binmode(STDOUT, ":utf8"); + print $Cgi->header(-charset => "utf-8"); print < $title + + $Conf{CgiHeaders} - - - - -
+ + +
EOF - NavSectionTitle("BackupPC"); - print " \n"; - if ( defined($In{host}) && defined($Hosts->{$In{host}}) ) { - my $host = $In{host}; - NavSectionTitle( eval("qq{$Lang->{Host_Inhost}}") ); - NavSectionStart(); - NavLink("?host=${EscURI($host)}", $Lang->{Home}); - NavLink("?action=view&type=LOG&host=${EscURI($host)}", $Lang->{LOG_file}); - NavLink("?action=LOGlist&host=${EscURI($host)}", $Lang->{Old_LOGs}); - if ( -f "$TopDir/pc/$host/SmbLOG.bad" - || -f "$TopDir/pc/$host/SmbLOG.bad.z" - || -f "$TopDir/pc/$host/XferLOG.bad" - || -f "$TopDir/pc/$host/XferLOG.bad.z" ) { - NavLink("?action=view&type=XferLOGbad&host=${EscURI($host)}", - $Lang->{Last_bad_XferLOG}); - NavLink("?action=view&type=XferErrbad&host=${EscURI($host)}", - $Lang->{Last_bad_XferLOG_errors_only}); - } - if ( -f "$TopDir/pc/$host/config.pl" ) { - NavLink("?action=view&type=config&host=${EscURI($host)}", $Lang->{Config_file}); + + if ( defined($Hosts) && defined($host) && defined($Hosts->{$host}) ) { + print "
"; + NavSectionTitle("${EscHTML($host)}"); + print < +\n"; } - NavSectionTitle($Lang->{NavSectionTitle_}); - NavSectionStart(); - foreach my $l ( @adminLinks ) { - if ( $PrivAdmin || $l->{priv} ) { - NavLink($l->{link}, $l->{name}); - } else { - NavLink(undef, $l->{name}); - } + print("
\n$content\n"); + if ( defined($contentSub) && ref($contentSub) eq "CODE" ) { + while ( (my $s = &$contentSub()) ne "" ) { + print($s); + } } - NavSectionEnd(); - NavSectionTitle($Lang->{Hosts}); + print($contentPost) if ( defined($contentPost) ); print < -
$Lang->{Host_or_User_name}
- +


+ +
+ EOF - if ( defined($Hosts) && %$Hosts > 0 ) { - NavSectionStart(1); - foreach my $host ( GetUserHosts() ) { - NavLink("?host=${EscURI($host)}", $host); + } + NavSectionTitle($Lang->{NavSectionTitle_}); + foreach my $l ( @adminLinks ) { + if ( $PrivAdmin || !$l->{priv} ) { + my $txt = $l->{lname} ne "" ? $Lang->{$l->{lname}} : $l->{name}; + NavLink($l->{link}, $txt); } - NavSectionEnd(); } + print <   - +


+ EOF } sub Trailer { print < EOF } @@ -478,41 +557,33 @@ sub NavSectionTitle { my($head) = @_; print < -$head - - + EOF } sub NavSectionStart { - my($padding) = @_; - - $padding = 1 if ( !defined($padding) ); - print < -EOF } sub NavSectionEnd { - print "\n"; } sub NavLink { my($link, $text) = @_; - print "·"; if ( defined($link) ) { + my($class); + $class = " class=\"NavCurrent\"" + if ( length($link) && $ENV{REQUEST_URI} =~ /\Q$link\E$/ + || $link eq "" && $ENV{REQUEST_URI} !~ /\?/ ); $link = "$MyURL$link" if ( $link eq "" || $link =~ /^\?/ ); print <$text +$text EOF } else { print <$text +$text
EOF } } @@ -521,12 +592,7 @@ sub h1 { my($str) = @_; return \< - - $str - - +
$str
EOF } @@ -534,11 +600,6 @@ sub h2 { my($str) = @_; return \< - - $str - - +
$str
EOF }