X-Git-Url: http://git.rot13.org/?p=BackupPC.git;a=blobdiff_plain;f=lib%2FBackupPC%2FCGI%2FRestore.pm;h=c5cf73f388da5f3b2948156df84dbf51cf3e2a6c;hp=f236e1e1bb1ab8698a09d42879f4fa7e52920cc1;hb=f6fbcc3682d2bc9e7dfdc26e95bd5fcdb359496d;hpb=4ccad54a1f16abeffa0bf9a96df117d378eba9c1 diff --git a/lib/BackupPC/CGI/Restore.pm b/lib/BackupPC/CGI/Restore.pm index f236e1e..c5cf73f 100644 --- a/lib/BackupPC/CGI/Restore.pm +++ b/lib/BackupPC/CGI/Restore.pm @@ -10,7 +10,7 @@ # Craig Barratt # # COPYRIGHT -# Copyright (C) 2003 Craig Barratt +# Copyright (C) 2003-2007 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 @@ -28,7 +28,7 @@ # #======================================================================== # -# Version 2.1.0_CVS, released 3 Jul 2003. +# Version 3.2.0beta0, released 5 April 2009. # # See http://backuppc.sourceforge.net. # @@ -38,11 +38,14 @@ package BackupPC::CGI::Restore; use strict; use BackupPC::CGI::Lib qw(:all); +use BackupPC::Xfer; use Data::Dumper; +use File::Path; +use Encode qw/decode_utf8/; sub action { - my($str, $reply); + my($str, $reply, $content); my $Privileged = CheckPermission($In{host}); if ( !$Privileged ) { ErrorExit(eval("qq{$Lang->{Only_privileged_users_can_restore_backup_files}}")); @@ -62,7 +65,7 @@ sub action (my $name = $In{"fcb$i"}) =~ s/%([0-9A-F]{2})/chr(hex($1))/eg; $badFileCnt++ if ( $name =~ m{(^|/)\.\.(/|$)} ); if ( @fileList == 0 ) { - $pathHdr = $name; + $pathHdr = substr($name, 0, rindex($name, "/")); } else { while ( substr($name, 0, length($pathHdr)) ne $pathHdr ) { $pathHdr = substr($pathHdr, 0, rindex($pathHdr, "/")); @@ -72,12 +75,13 @@ sub action $hiddenStr .= < EOF + $name = decode_utf8($name); $fileListStr .= < ${EscHTML($name)} EOF } $hiddenStr .= "\n"; - $hiddenStr .= "\n"; + $hiddenStr .= "\n"; $badFileCnt++ if ( $In{pathHdr} =~ m{(^|/)\.\.(/|$)} ); $badFileCnt++ if ( $In{num} =~ m{(^|/)\.\.(/|$)} ); if ( @fileList == 0 ) { @@ -86,9 +90,6 @@ EOF if ( $badFileCnt ) { ErrorExit($Lang->{Nice_try__but_you_can_t_put}); } - if ( @fileList == 1 ) { - $pathHdr =~ s/(.*)\/.*/$1/; - } $pathHdr = "/" if ( $pathHdr eq "" ); if ( $In{type} != 0 && @fileList == $In{fcbMax} ) { # @@ -98,22 +99,69 @@ EOF @fileList = ( $pathHdr ); } if ( $In{type} == 0 ) { + # + # Build list of hosts + # + my($hostDestSel, @hosts, $gotThisHost, $directHost); + + # + # Check all the hosts this user has permissions for + # and make sure direct restore is enabled. + # Note: after this loop we have the config for the + # last host in @hosts, not the original $In{host}!! + # + $directHost = $host; + foreach my $h ( GetUserHosts(1) ) { + # + # Pick up the host's config file + # + $bpc->ConfigRead($h); + %Conf = $bpc->Conf(); + if ( BackupPC::Xfer::restoreEnabled( \%Conf ) ) { + # + # Direct restore is enabled + # + push(@hosts, $h); + $gotThisHost = 1 if ( $h eq $host ); + } + } + $directHost = $hosts[0] if ( !$gotThisHost && @hosts ); + foreach my $h ( @hosts ) { + my $sel = " selected" if ( $h eq $directHost ); + $hostDestSel .= ""; + } + # # Tell the user what options they have # - Header(eval("qq{$Lang->{Restore_Options_for__host}}")); - print(eval("qq{$Lang->{Restore_Options_for__host2}}")); + $pathHdr = decode_utf8($pathHdr); + $share = decode_utf8($share); + $content = eval("qq{$Lang->{Restore_Options_for__host2}}"); + + # + # Decide if option 1 (direct restore) is available based + # on whether the restore command is set. + # + if ( $hostDestSel ne "" ) { + $content .= eval( + "qq{$Lang->{Restore_Options_for__host_Option1}}"); + } else { + my $hostDest = $In{host}; + $content .= eval( + "qq{$Lang->{Restore_Options_for__host_Option1_disabled}}"); + } # # Verify that Archive::Zip is available before showing the # zip restore option # if ( eval { require Archive::Zip } ) { - print (eval("qq{$Lang->{Option_2__Download_Zip_archive}}")); + $content .= eval("qq{$Lang->{Option_2__Download_Zip_archive}}"); } else { - print (eval("qq{$Lang->{Option_2__Download_Zip_archive2}}")); + $content .= eval("qq{$Lang->{Option_2__Download_Zip_archive2}}"); } - print (eval("qq{$Lang->{Option_3__Download_Zip_archive}}")); + $content .= eval("qq{$Lang->{Option_3__Download_Zip_archive}}"); + Header(eval("qq{$Lang->{Restore_Options_for__host}}"), $content); Trailer(); } elsif ( $In{type} == 1 ) { # @@ -142,14 +190,15 @@ EOF # This is necessary to ensure the output gets to the correct place # under mod_perl. # - $bpc->cmdSystemOrEval(["$BinDir/BackupPC_tarCreate", + $bpc->cmdSystemOrEvalLong(["$BinDir/BackupPC_tarCreate", "-h", $host, "-n", $num, "-s", $share, @pathOpts, @fileList ], - sub { print(@_); } + sub { print(@_); }, + 1, # ignore stderr ); } elsif ( $In{type} == 2 ) { # @@ -179,7 +228,7 @@ EOF # This is necessary to ensure the output gets to the correct place # under mod_perl. # - $bpc->cmdSystemOrEval(["$BinDir/BackupPC_zipCreate", + $bpc->cmdSystemOrEvalLong(["$BinDir/BackupPC_zipCreate", "-h", $host, "-n", $num, "-c", $In{compressLevel}, @@ -187,7 +236,8 @@ EOF @pathOpts, @fileList ], - sub { print(@_); } + sub { print(@_); }, + 1, # ignore stderr ); } elsif ( $In{type} == 3 ) { # @@ -199,18 +249,40 @@ EOF if ( !CheckPermission($In{hostDest}) ) { ErrorExit(eval("qq{$Lang->{You_don_t_have_permission_to_restore_onto_host}}")); } + # + # Pick up the destination host's config file + # + my $hostDest = $1 if ( $In{hostDest} =~ /(.*)/ ); + $bpc->ConfigRead($hostDest); + %Conf = $bpc->Conf(); + + # + # Decide if option 1 (direct restore) is available based + # on whether the restore command is set. + # + unless ( BackupPC::Xfer::restoreEnabled( \%Conf ) ) { + ErrorExit(eval("qq{$Lang->{Restore_Options_for__host_Option1_disabled}}")); + } + $fileListStr = ""; foreach my $f ( @fileList ) { my $targetFile = $f; (my $strippedShare = $share) =~ s/^\///; (my $strippedShareDest = $In{shareDest}) =~ s/^\///; - substr($targetFile, 0, length($pathHdr)) = $In{pathHdr}; + substr($targetFile, 0, length($pathHdr)) = "/$In{pathHdr}/"; + $targetFile =~ s{//+}{/}g; + $strippedShareDest = decode_utf8($strippedShareDest); + $targetFile = decode_utf8($targetFile); + $strippedShare = decode_utf8($strippedShare); + $f = decode_utf8($f); $fileListStr .= <$host:/$strippedShare$f$In{hostDest}:/$strippedShareDest$targetFile EOF } - Header(eval("qq{$Lang->{Restore_Confirm_on__host}}")); - print(eval("qq{$Lang->{Are_you_sure}}")); + $In{shareDest} = decode_utf8($In{shareDest}); + $In{pathHdr} = decode_utf8($In{pathHdr}); + my $content = eval("qq{$Lang->{Are_you_sure}}"); + Header(eval("qq{$Lang->{Restore_Confirm_on__host}}"), $content); Trailer(); } elsif ( $In{type} == 4 ) { if ( !defined($Hosts->{$In{hostDest}}) ) { @@ -232,6 +304,9 @@ EOF $reqFileName = "restoreReq.$$.$i"; last if ( !-f "$TopDir/pc/$hostDest/$reqFileName" ); } + my $inPathHdr = $In{pathHdr}; + $inPathHdr = "/$inPathHdr" if ( $inPathHdr !~ m{^/} ); + $inPathHdr = "$inPathHdr/" if ( $inPathHdr !~ m{/$} ); my %restoreReq = ( # source of restore is hostSrc, #num, path shareSrc/pathHdrSrc num => $In{num}, @@ -242,7 +317,7 @@ EOF # destination of restore is hostDest:shareDest/pathHdrDest hostDest => $hostDest, shareDest => $In{shareDest}, - pathHdrDest => $In{pathHdr}, + pathHdrDest => $inPathHdr, # list of files to restore fileList => \@fileList, @@ -255,18 +330,21 @@ EOF [ \%restoreReq], [qw(*RestoreReq)]); $dump->Indent(1); - if ( open(REQ, ">$TopDir/pc/$hostDest/$reqFileName") ) { + eval { mkpath("$TopDir/pc/$hostDest", 0, 0777) } + if ( !-d "$TopDir/pc/$hostDest" ); + my $openPath = "$TopDir/pc/$hostDest/$reqFileName"; + if ( open(REQ, ">", $openPath) ) { binmode(REQ); print(REQ $dump->Dump); close(REQ); } else { - ErrorExit(eval("qq{$Lang->{Can_t_open_create}}")); + ErrorExit(eval("qq{$Lang->{Can_t_open_create__openPath}}")); } $reply = $bpc->ServerMesg("restore ${EscURI($ipAddr)}" . " ${EscURI($hostDest)} $User $reqFileName"); $str = eval("qq{$Lang->{Restore_requested_to_host__hostDest__backup___num}}"); - Header(eval("qq{$Lang->{Restore_Requested_on__hostDest}}")); - print (eval("qq{$Lang->{Reply_from_server_was___reply}}")); + my $content = eval("qq{$Lang->{Reply_from_server_was___reply}}"); + Header(eval("qq{$Lang->{Restore_Requested_on__hostDest}}"), $content); Trailer(); } }