# Craig Barratt <cbarratt@users.sourceforge.net>
#
# 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
#
#========================================================================
#
-# Version 2.1.0beta0, released 20 Mar 2004.
+# Version 3.2.0, released 31 Jul 2010.
#
# See http://backuppc.sourceforge.net.
#
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);
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
if ( !defined($bpc) ) {
ErrorExit($Lang->{BackupPC__Lib__new_failed__check_apache_error_log})
- if ( !($bpc = BackupPC::Lib->new(undef, undef, 1)) );
+ 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->ServerMesg("log Re-read config file because mtime changed");
- $bpc->ServerMesg("server reload");
+ $bpc->ConfigRead();
+ $TopDir = $bpc->TopDir();
+ $LogDir = $bpc->LogDir();
+ $BinDir = $bpc->BinDir();
+ %Conf = $bpc->Conf();
+ $Lang = $bpc->Lang();
+ $ConfigMTime = $bpc->ConfigMTime();
+ umask($Conf{UmaskMode});
}
#
$MyURL = $ENV{SCRIPT_NAME};
$User = $ENV{REMOTE_USER};
+ #
+ # Handle LDAP uid=user when using mod_authz_ldap and otherwise untaint
+ #
+ $User = $1 if ( $User =~ /uid=([^,]+)/i || $User =~ /(.*)/ );
+
+ # strip Active directory domain in front of user
+ $User = $1 if ( $User =~ /\w+\\(\w+)/ );
+use Data::Dump qw(dump);
+warn "XX User: $User",dump( \%ENV );
+
#
# Clean up %ENV for taint checking
#
{map {$_, 1} split(",", $Hosts->{$host}{moreUsers}) }
}
}
+
+ #
+ # Untaint the host name
+ #
+ if ( $In{host} =~ /^([\w.\s-]+)$/ ) {
+ $In{host} = $1;
+ } else {
+ delete($In{host});
+ }
}
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);
$s =~ s/\"/"/g;
$s =~ s/>/>/g;
$s =~ s/</</g;
- $s =~ s{([^[:print:]])}{sprintf("&\#x%02X;", ord($1));}eg;
+ ### $s =~ s{([^[:print:]])}{sprintf("&\#x%02X;", ord($1));}eg;
return \$s;
}
Trailer();
exit(1);
} else {
- ErrorExit(eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server}}"));
+ ErrorExit(eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server}}"),
+ eval("qq{$Lang->{Unable_to_connect_to_BackupPC_server_error_message}}"));
}
}
}
{
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];
}
}
|| $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});
+ # XXX check against REMOTE_NTGROUP from mod_ntlm
+ $Privileged ||= $Conf{CgiAdminUserGroup} eq $ENV{REMOTE_NTGROUP};
+
return $Privileged;
}
#
sub GetUserHosts
{
- my($host, $getAll) = @_;
+ my($getAll) = @_;
my @hosts;
if ( $getAll && CheckPermission() ) {
{
my($title, $content, $noBrowse, $contentSub, $contentPost) = @_;
my @adminLinks = (
- { link => "", name => $Lang->{Status},
- priv => 1},
- { link => "?action=adminOpts", name => $Lang->{Admin_Options} },
- { link => "?action=summary", name => $Lang->{PC_Summary},
- priv => 1},
- { 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},
+ # XXX additional search extensions
+ { link => "?action=search", name => $Lang->{Search_archive},
+ priv => 0},
+ { link => "?action=burn", name => $Lang->{Burn_media},
+ priv => 1},
+ @{$Conf{CgiNavBarLinks} || []},
);
my $host = $In{host};
- print $Cgi->header();
+ binmode(STDOUT, ":utf8");
+ print $Cgi->header(-charset => "utf-8");
print <<EOF;
<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
<title>$title</title>
-$Conf{CSSstylesheet}
+<link rel=stylesheet type="text/css" href="$Conf{CgiImageDirURL}/$Conf{CgiCSSFile}" title="CSSFile">
+<link rel=icon href="$Conf{CgiImageDirURL}/favicon.ico" type="image/x-icon">
$Conf{CgiHeaders}
+<script src="$Conf{CgiImageDirURL}/sorttable.js"></script>
</head><body onLoad="document.getElementById('NavMenu').style.height=document.body.scrollHeight">
-<img src="$Conf{CgiImageDirURL}/logo.gif" hspace="5" vspace="7"><br>
+<a href="http://backuppc.sourceforge.net"><img src="$Conf{CgiImageDirURL}/logo.gif" hspace="5" vspace="7" border="0"></a><br>
EOF
if ( defined($Hosts) && defined($host) && defined($Hosts->{$host}) ) {
print "<div class=\"NavMenu\">";
- NavSectionTitle("${EscURI($host)}");
+ NavSectionTitle("${EscHTML($host)}");
print <<EOF;
</div>
<div class="NavMenu">
$Lang->{Last_bad_XferLOG_errors_only},
" class=\"navbar\"");
}
- if ( -f "$TopDir/pc/$host/config.pl" ) {
- NavLink("?action=view&type=config&host=${EscURI($host)}",
- $Lang->{Config_file}, " class=\"navbar\"");
- }
+ if ( $Conf{CgiUserConfigEditEnable} || $PrivAdmin ) {
+ NavLink("?action=editConfig&host=${EscURI($host)}",
+ $Lang->{CfgEdit_Edit_Config}, " class=\"navbar\"");
+ } elsif ( -f "$TopDir/pc/$host/config.pl"
+ || ($host ne "config" && -f "$TopDir/conf/$host.pl") ) {
+ NavLink("?action=view&type=config&host=${EscURI($host)}",
+ $Lang->{Config_file}, " class=\"navbar\"");
+ }
print "</div>\n";
}
print("<div id=\"Content\">\n$content\n");
<div class="NavMenu" id="NavMenu" style="height:100%">
EOF
my $hostSelectbox = "<option value=\"#\">$Lang->{Select_a_host}</option>";
- my @hosts = GetUserHosts($In{host}, $Conf{CgiNavBarAdminAllHosts});
+ my @hosts = GetUserHosts($Conf{CgiNavBarAdminAllHosts});
+ NavSectionTitle($Lang->{Hosts});
if ( defined($Hosts) && %$Hosts > 0 && @hosts ) {
- NavSectionTitle($Lang->{Hosts});
foreach my $host ( @hosts ) {
NavLink("?host=${EscURI($host)}", $host)
if ( @hosts < $Conf{CgiNavBarAdminAllHosts} );
<br><br>
EOF
}
- print <<EOF;
+ if ( $Conf{CgiSearchBoxEnable} ) {
+ print <<EOF;
<form action="$MyURL" method="get">
<input type="text" name="host" size="14" maxlength="64">
<input type="hidden" name="action" value="hostInfo"><input type="submit" value="$Lang->{Go}" name="ignore">
</form>
EOF
+ }
NavSectionTitle($Lang->{NavSectionTitle_});
foreach my $l ( @adminLinks ) {
- if ( $PrivAdmin || $l->{priv} ) {
- NavLink($l->{link}, $l->{name});
+ if ( $PrivAdmin || !$l->{priv} ) {
+ my $txt = $l->{lname} ne "" ? $Lang->{$l->{lname}} : $l->{name};
+ NavLink($l->{link}, $txt);
+ }
}
-}
-print <<EOF;
+ print <<EOF;
<br><br><br>
</div>
EOF