18f7ba48abeec9a7b1e3857aa786feb98ff3f976
[BackupPC.git] / lib / BackupPC / CGI / Archive.pm
1 #============================================================= -*-perl-*-
2 #
3 # BackupPC::CGI::Archive package
4 #
5 # DESCRIPTION
6 #
7 #   This module implements the Archive action for the CGI interface.
8 #
9 # AUTHOR
10 #   Craig Barratt  <cbarratt@users.sourceforge.net>
11 #
12 # COPYRIGHT
13 #   Copyright (C) 2003-2009  Craig Barratt
14 #
15 #   This program is free software; you can redistribute it and/or modify
16 #   it under the terms of the GNU General Public License as published by
17 #   the Free Software Foundation; either version 2 of the License, or
18 #   (at your option) any later version.
19 #
20 #   This program is distributed in the hope that it will be useful,
21 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
22 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 #   GNU General Public License for more details.
24 #
25 #   You should have received a copy of the GNU General Public License
26 #   along with this program; if not, write to the Free Software
27 #   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 #
29 #========================================================================
30 #
31 # Version 3.2.0, released 31 Jul 2010.
32 #
33 # See http://backuppc.sourceforge.net.
34 #
35 #========================================================================
36
37 package BackupPC::CGI::Archive;
38
39 use strict;
40 use BackupPC::CGI::Lib qw(:all);
41 use Data::Dumper;
42 use BackupPC::Search;
43
44 sub action
45 {
46     my $archHost = $In{host};
47     my $Privileged = CheckPermission();
48
49     if ( !$Privileged ) {
50         ErrorExit($Lang->{Only_privileged_users_can_archive} );
51     }
52     if ( $In{type} == 0 ) {
53         my($fullTot, $fullSizeTot, $incrTot, $incrSizeTot, $str,
54            $strNone, $strGood, $hostCntGood, $hostCntNone, $checkBoxCnt,
55            $backupnumber);
56
57         $hostCntGood = $hostCntNone = $checkBoxCnt = $fullSizeTot = 0;
58         GetStatusInfo("hosts");
59
60         foreach my $host ( sort(keys(%Status)) ) {
61             my($fullDur, $incrCnt, $fullSize, $fullRate);
62             my @Backups = $bpc->BackupInfoRead($host);
63             my $fullCnt = $incrCnt = 0;
64
65             for ( my $i = 0 ; $i < @Backups ; $i++ ) {
66                 if ( $Backups[$i]{type} eq "full" ) {
67                     $fullSize = $Backups[$i]{size} / (1024 * 1024);
68                     $incrSizeTot = 0;
69                 } else {
70                     $incrSizeTot = $Backups[$i]{size} / (1024 * 1024);
71                 }
72                 $backupnumber = $Backups[$i]{num};
73             }
74             $fullSizeTot += $fullSize + $incrSizeTot;
75             $fullSize = sprintf("%.2f", ($fullSize + $incrSizeTot) / 1000);
76
77                 $bpc->ConfigRead($archHost);
78                 %Conf = $bpc->Conf();
79
80                 my $checkboxes;
81                 foreach my $backupnumber ( BackupPC::Search::host_backup_nums($host) ) {
82                         $checkboxes .= qq|
83 <input type="hidden" name="fcb$checkBoxCnt" value="$host">
84 <input type="checkbox" name="backup$checkBoxCnt" value="$backupnumber">$backupnumber
85                         |;
86                         $checkBoxCnt++;
87                 }
88
89 =for ASA extension removed this
90             $str = <<EOF;
91 <tr>
92 <td class="border"><input type="hidden" name="backup$checkBoxCnt" value="$backupnumber"><input type="checkbox" name="fcb$checkBoxCnt" value="$host">&nbsp;${HostLink($host)} </td>
93 <td align="center" class="border"> ${UserLink($Hosts->{$host}{user})} </td>
94 <td align="center" class="border"> $fullSize </td>
95 EOF
96             $checkBoxCnt++;
97 =cut
98
99             $str = <<EOF;
100 <tr>
101 <td class="border">
102 ${HostLink($host)}
103 $checkboxes
104 </td>
105 <td align="center" class="border">
106 ${UserLink($Hosts->{$host}{user})}
107 </td>
108 <td align="center" class="border"> $fullSize </td>
109 EOF
110
111             if ( @Backups == 0 ) {
112                 $hostCntNone++;
113                 $strNone .= $str;
114             } else {
115                 $hostCntGood++;
116                 $strGood .= $str;
117             }
118         }
119         $fullSizeTot = sprintf("%.2f", $fullSizeTot / 1000);
120         my $now      = timeStamp2(time);
121         my $checkAllHosts = $Lang->{checkAllHosts};
122         $strGood .= <<EOF;
123 <input type="hidden" name="archivehost" value="$In{'archivehost'}">
124 EOF
125         my $content = eval("qq{$Lang->{BackupPC_Archive}}");
126         Header(eval("qq{$Lang->{BackupPC__Archive}}"), $content, 1);
127         Trailer();
128     } else {
129         my(@HostList, @BackupList, $HostListStr, $hiddenStr, $pathHdr,
130            $badFileCnt, $reply, $str);
131
132         #
133         # Pick up the archive host's config file
134         #
135         $bpc->ConfigRead($archHost);
136         %Conf = $bpc->Conf();
137
138         my $args = {
139             SplitPath    => $Conf{SplitPath},
140             ParPath      => $Conf{ParPath},
141             CatPath      => $Conf{CatPath},
142             GzipPath     => $Conf{GzipPath},
143             Bzip2Path    => $Conf{Bzip2Path},
144             ArchiveDest  => $Conf{ArchiveDest},
145             ArchiveComp  => $Conf{ArchiveComp},
146             ArchivePar   => $Conf{ArchivePar},
147             ArchiveSplit => $Conf{ArchiveSplit},
148             topDir       => $bpc->{TopDir},
149         };
150
151         ServerConnect();
152
153         for ( my $i = 0 ; $i < $In{fcbMax} ; $i++ ) {
154             next if ( !defined($In{"fcb$i"}) );
155             my $name = $In{"fcb$i"};
156             my $backupno = $In{"backup$i"};
157             next unless defined $backupno; # ASA - skip hosts without backups checked
158             push(@HostList, $name);
159             push(@BackupList, $backupno);
160             $hiddenStr .= <<EOF;
161 <input type="hidden" name="fcb$i" value="$In{'fcb' . $i}">
162 <input type="hidden" name="backup$i" value="$In{'backup' . $i}">
163 EOF
164             $HostListStr .= <<EOF;
165 <li> ${EscHTML($name)} $i
166 EOF
167         }
168         $hiddenStr .= <<EOF;
169 <input type="hidden" name="archivehost" value="$In{'archivehost'}">
170 EOF
171         $hiddenStr .= "<input type=\"hidden\" name=\"fcbMax\" value=\"$In{fcbMax}\">\n";
172         if ( @HostList == 0 ) {
173             ErrorExit($Lang->{You_haven_t_selected_any_hosts});
174         }
175         my ($ArchiveDest, $ArchiveCompNone, $ArchiveCompGzip,
176             $ArchiveCompBzip2, $ArchivePar, $ArchiveSplit);
177         $ArchiveDest = $Conf{ArchiveDest};
178         if ( $Conf{ArchiveComp} eq "none" ) {
179             $ArchiveCompNone   = "checked";
180         } else {
181             $ArchiveCompNone   = "";
182         }
183         if ( $Conf{ArchiveComp} eq "gzip" ) {
184             $ArchiveCompGzip   = "checked";
185         } else {
186             $ArchiveCompGzip   = "";
187         }
188         if ( $Conf{ArchiveComp} eq "bzip2" ) {
189             $ArchiveCompBzip2  = "checked";
190         } else {
191             $ArchiveCompBzip2  = "";
192         }
193         $ArchivePar   = $Conf{ArchivePar};
194         $ArchiveSplit = $Conf{ArchiveSplit};
195
196         if ( $In{type} == 1 ) {
197             #
198             # Tell the user what options they have
199             #
200             my $paramStr = "";
201             if ( $Conf{ArchiveClientCmd} =~ /\$archiveloc\b/ ) {
202                 $paramStr .= eval("qq{$Lang->{BackupPC_Archive2_location}}");
203             }
204             if ( $Conf{ArchiveClientCmd} =~ /\$compression\b/ ) {
205                 $paramStr .= eval("qq{$Lang->{BackupPC_Archive2_compression}}");
206             }
207             if ( $Conf{ArchiveClientCmd} =~ /\$parfile\b/
208                     && -x $Conf{ParPath} ) {
209                 $paramStr .= eval("qq{$Lang->{BackupPC_Archive2_parity}}");
210             }
211             if ( $Conf{ArchiveClientCmd} =~ /\$splitsize\b/
212                     && -x $Conf{SplitPath} ) {
213                 $paramStr .= eval("qq{$Lang->{BackupPC_Archive2_split}}");
214             }
215             my $content = eval("qq{$Lang->{BackupPC_Archive2}}");
216             Header(eval("qq{$Lang->{BackupPC__Archive}}"), $content, 1);
217             Trailer();
218         } elsif ( $In{type} == 2 ) {
219             my $reqFileName;
220             my $archivehost = $1 if ( $In{archivehost} =~ /(.+)/ );
221             for ( my $i = 0 ; ; $i++ ) {
222                 $reqFileName = "archiveReq.$$.$i";
223                 last if ( !-f "$TopDir/pc/$archivehost/$reqFileName" );
224             }
225             my($compname, $compext);
226             if ( $In{compression} == 2 ) {          # bzip2 compression
227                 $compname = $Conf{Bzip2Path};
228                 $compext = '.bz2';
229             } elsif ( $In{compression} == 1 ) {     # gzip compression
230                 $compname = $Conf{GzipPath};
231                 $compext = '.gz';
232             } else { # No Compression
233                 $compname = $Conf{CatPath};
234                 $compext = '.raw';
235             }
236             my $fullsplitsize = $In{splitsize} . '000000'; # mb -> bytes
237             my %ArchiveReq = (
238                 # parameters for the archive
239                 archiveloc  => $In{archive_device},
240                 archtype    => $In{archive_type},
241                 compression => $compname,
242                 compext     => $compext,
243                 parfile     => $In{par},
244                 splitsize   => $fullsplitsize,
245                 host        => $archivehost,
246
247                 # list of hosts to restore
248                 HostList    => \@HostList,
249                 BackupList  => \@BackupList,
250
251                 # other info
252                 user        => $User,
253                 reqTime     => time,
254             );
255             my($archive) = Data::Dumper->new(
256                             [  \%ArchiveReq],
257                             [qw(*ArchiveReq)]);
258             $archive->Indent(1);
259             my $openPath = "$TopDir/pc/$archivehost/$reqFileName";
260             if ( open(REQ, ">", $openPath) ) {
261                 binmode(REQ);
262                 print(REQ $archive->Dump);
263                 close(REQ);
264             } else {
265                 ErrorExit(eval("qq{$Lang->{Can_t_open_create__openPath}}"));
266             }
267             $reply = $bpc->ServerMesg("archive $User $archivehost $reqFileName");
268             $str = eval("qq{$Lang->{Archive_requested}}");
269
270             my $content = eval("qq{$Lang->{BackupPC_Archive_Reply_from_server}}");
271             Header(eval("qq{$Lang->{BackupPC__Archive}}"), $content, 1);
272             Trailer();
273         }
274     }
275 }
276
277 1;