1 |
dpavlin |
1 |
#============================================================= -*-perl-*- |
2 |
|
|
# |
3 |
|
|
# BackupPC::CGI::View package |
4 |
|
|
# |
5 |
|
|
# DESCRIPTION |
6 |
|
|
# |
7 |
|
|
# This module implements the View action for the CGI interface. |
8 |
|
|
# |
9 |
|
|
# AUTHOR |
10 |
|
|
# Craig Barratt <cbarratt@users.sourceforge.net> |
11 |
|
|
# |
12 |
|
|
# COPYRIGHT |
13 |
|
|
# Copyright (C) 2003 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 2.1.0, released 20 Jun 2004. |
32 |
|
|
# |
33 |
|
|
# See http://backuppc.sourceforge.net. |
34 |
|
|
# |
35 |
|
|
#======================================================================== |
36 |
|
|
|
37 |
|
|
package BackupPC::CGI::View; |
38 |
|
|
|
39 |
|
|
use strict; |
40 |
|
|
use BackupPC::CGI::Lib qw(:all); |
41 |
|
|
use BackupPC::FileZIO; |
42 |
|
|
|
43 |
|
|
sub action |
44 |
|
|
{ |
45 |
|
|
my $Privileged = CheckPermission($In{host}); |
46 |
|
|
my $compress = 0; |
47 |
|
|
my $fh; |
48 |
|
|
my $host = $In{host}; |
49 |
|
|
my $num = $In{num}; |
50 |
|
|
my $type = $In{type}; |
51 |
|
|
my $linkHosts = 0; |
52 |
|
|
my($file, $comment); |
53 |
|
|
my $ext = $num ne "" ? ".$num" : ""; |
54 |
|
|
|
55 |
|
|
ErrorExit(eval("qq{$Lang->{Invalid_number__num}}")) |
56 |
|
|
if ( $num ne "" && $num !~ /^\d+$/ ); |
57 |
|
|
if ( $type eq "XferLOG" ) { |
58 |
|
|
$file = "$TopDir/pc/$host/SmbLOG$ext"; |
59 |
|
|
$file = "$TopDir/pc/$host/XferLOG$ext" if ( !-f $file && !-f "$file.z"); |
60 |
|
|
} elsif ( $type eq "XferLOGbad" ) { |
61 |
|
|
$file = "$TopDir/pc/$host/SmbLOG.bad"; |
62 |
|
|
$file = "$TopDir/pc/$host/XferLOG.bad" if ( !-f $file && !-f "$file.z"); |
63 |
|
|
} elsif ( $type eq "XferErrbad" ) { |
64 |
|
|
$file = "$TopDir/pc/$host/SmbLOG.bad"; |
65 |
|
|
$file = "$TopDir/pc/$host/XferLOG.bad" if ( !-f $file && !-f "$file.z"); |
66 |
|
|
$comment = $Lang->{Extracting_only_Errors}; |
67 |
|
|
} elsif ( $type eq "XferErr" ) { |
68 |
|
|
$file = "$TopDir/pc/$host/SmbLOG$ext"; |
69 |
|
|
$file = "$TopDir/pc/$host/XferLOG$ext" if ( !-f $file && !-f "$file.z"); |
70 |
|
|
$comment = $Lang->{Extracting_only_Errors}; |
71 |
|
|
} elsif ( $type eq "RestoreLOG" ) { |
72 |
|
|
$file = "$TopDir/pc/$host/RestoreLOG$ext"; |
73 |
|
|
} elsif ( $type eq "RestoreErr" ) { |
74 |
|
|
$file = "$TopDir/pc/$host/RestoreLOG$ext"; |
75 |
|
|
$comment = $Lang->{Extracting_only_Errors}; |
76 |
|
|
} elsif ( $type eq "ArchiveLOG" ) { |
77 |
|
|
$file = "$TopDir/pc/$host/ArchiveLOG$ext"; |
78 |
|
|
} elsif ( $type eq "ArchiveErr" ) { |
79 |
|
|
$file = "$TopDir/pc/$host/ArchiveLOG$ext"; |
80 |
|
|
$comment = $Lang->{Extracting_only_Errors}; |
81 |
|
|
} elsif ( $host ne "" && $type eq "config" ) { |
82 |
|
|
$file = "$TopDir/pc/$host/config.pl"; |
83 |
|
|
$file = "$TopDir/conf/$host.pl" |
84 |
|
|
if ( $host ne "config" && -f "$TopDir/conf/$host.pl" |
85 |
|
|
&& !-f $file ); |
86 |
|
|
} elsif ( $type eq "docs" ) { |
87 |
|
|
$file = "$BinDir/../doc/BackupPC.html"; |
88 |
|
|
} elsif ( $type eq "config" ) { |
89 |
|
|
$file = "$TopDir/conf/config.pl"; |
90 |
|
|
} elsif ( $type eq "hosts" ) { |
91 |
|
|
$file = "$TopDir/conf/hosts"; |
92 |
|
|
$linkHosts = 1; |
93 |
|
|
} elsif ( $host ne "" ) { |
94 |
|
|
$file = "$TopDir/pc/$host/LOG$ext"; |
95 |
|
|
$linkHosts = 1; |
96 |
|
|
} else { |
97 |
|
|
$file = "$TopDir/log/LOG$ext"; |
98 |
|
|
$linkHosts = 1; |
99 |
|
|
} |
100 |
|
|
if ( $type ne "docs" && !$Privileged ) { |
101 |
|
|
ErrorExit($Lang->{Only_privileged_users_can_view_log_or_config_files}); |
102 |
|
|
} |
103 |
|
|
if ( !-f $file && -f "$file.z" ) { |
104 |
|
|
$file .= ".z"; |
105 |
|
|
$compress = 1; |
106 |
|
|
} |
107 |
|
|
my($contentPre, $contentSub, $contentPost); |
108 |
|
|
$contentPre .= eval("qq{$Lang->{Log_File__file__comment}}"); |
109 |
|
|
if ( defined($fh = BackupPC::FileZIO->open($file, 0, $compress)) ) { |
110 |
|
|
my $mtimeStr = $bpc->timeStamp((stat($file))[9], 1); |
111 |
|
|
|
112 |
|
|
$contentPre .= eval("qq{$Lang->{Contents_of_log_file}}"); |
113 |
|
|
|
114 |
|
|
$contentPre .= "<pre>"; |
115 |
|
|
if ( $type eq "XferErr" || $type eq "XferErrbad" |
116 |
|
|
|| $type eq "RestoreErr" |
117 |
|
|
|| $type eq "ArchiveErr" ) { |
118 |
|
|
$contentSub = sub { |
119 |
|
|
# |
120 |
|
|
# Because the content might be large, we use |
121 |
|
|
# a sub to return the data in 64K chunks. |
122 |
|
|
# |
123 |
|
|
my($skipped, $c, $s); |
124 |
|
|
while ( length($c) < 65536 ) { |
125 |
|
|
$s = $fh->readLine(); |
126 |
|
|
if ( $s eq "" ) { |
127 |
|
|
$c .= eval("qq{$Lang->{skipped__skipped_lines}}") |
128 |
|
|
if ( $skipped ); |
129 |
|
|
last; |
130 |
|
|
} |
131 |
|
|
$s =~ s/[\n\r]+//g; |
132 |
|
|
if ( $s =~ /smb: \\>/ |
133 |
|
|
|| $s =~ /^\s*(\d+) \(\s*\d+\.\d kb\/s\) (.*)$/ |
134 |
|
|
|| $s =~ /^tar: dumped \d+ files/ |
135 |
|
|
|| $s =~ /^\s*added interface/i |
136 |
|
|
|| $s =~ /^\s*restore tar file /i |
137 |
|
|
|| $s =~ /^\s*restore directory /i |
138 |
|
|
|| $s =~ /^\s*tarmode is now/i |
139 |
|
|
|| $s =~ /^\s*Total bytes written/i |
140 |
|
|
|| $s =~ /^\s*Domain=/i |
141 |
|
|
|| $s =~ /^\s*Getting files newer than/i |
142 |
|
|
|| $s =~ /^\s*Output is \/dev\/null/ |
143 |
|
|
|| $s =~ /^\s*\([\d.,]* kb\/s\) \(average [\d\.]* kb\/s\)$/ |
144 |
|
|
|| $s =~ /^\s+directory \\/ |
145 |
|
|
|| $s =~ /^\s*Timezone is/ |
146 |
|
|
|| $s =~ /^\s*creating lame (up|low)case table/i |
147 |
|
|
|| $s =~ /^\.\// |
148 |
|
|
|| $s =~ /^ / ) { |
149 |
|
|
$skipped++; |
150 |
|
|
next; |
151 |
|
|
} |
152 |
|
|
$c .= eval("qq{$Lang->{skipped__skipped_lines}}") |
153 |
|
|
if ( $skipped ); |
154 |
|
|
$skipped = 0; |
155 |
|
|
$c .= ${EscHTML($s)} . "\n"; |
156 |
|
|
} |
157 |
|
|
return $c; |
158 |
|
|
}; |
159 |
|
|
} elsif ( $linkHosts ) { |
160 |
|
|
# |
161 |
|
|
# Because the content might be large, we use |
162 |
|
|
# a sub to return the data in 64K chunks. |
163 |
|
|
# |
164 |
|
|
$contentSub = sub { |
165 |
|
|
my($c, $s); |
166 |
|
|
while ( length($c) < 65536 ) { |
167 |
|
|
$s = $fh->readLine(); |
168 |
|
|
last if ( $s eq "" ); |
169 |
|
|
$s =~ s/[\n\r]+//g; |
170 |
|
|
$s = ${EscHTML($s)}; |
171 |
|
|
$s =~ s/\b([\w-]+)\b/defined($Hosts->{$1}) |
172 |
|
|
? ${HostLink($1)} : $1/eg; |
173 |
|
|
$c .= $s . "\n"; |
174 |
|
|
} |
175 |
|
|
return $c; |
176 |
|
|
}; |
177 |
|
|
} elsif ( $type eq "config" ) { |
178 |
|
|
# |
179 |
|
|
# Because the content might be large, we use |
180 |
|
|
# a sub to return the data in 64K chunks. |
181 |
|
|
# |
182 |
|
|
$contentSub = sub { |
183 |
|
|
my($c, $s); |
184 |
|
|
while ( length($c) < 65536 ) { |
185 |
|
|
$s = $fh->readLine(); |
186 |
|
|
last if ( $s eq "" ); |
187 |
|
|
$s =~ s/[\n\r]+//g; |
188 |
|
|
# remove any passwords and user names |
189 |
|
|
$s =~ s/(SmbSharePasswd.*=.*['"]).*(['"])/$1****$2/ig; |
190 |
|
|
$s =~ s/(SmbShareUserName.*=.*['"]).*(['"])/$1****$2/ig; |
191 |
|
|
$s =~ s/(RsyncdPasswd.*=.*['"]).*(['"])/$1****$2/ig; |
192 |
|
|
$s =~ s/(ServerMesgSecret.*=.*['"]).*(['"])/$1****$2/ig; |
193 |
|
|
$s = ${EscHTML($s)}; |
194 |
|
|
$s =~ s[(\$Conf\{.*?\})][ |
195 |
|
|
my $c = $1; |
196 |
|
|
my $s = lc($c); |
197 |
|
|
$s =~ s{(\W)}{sprintf("%%%02x", ord($1) )}gxe; |
198 |
|
|
"<a href=\"?action=view&type=docs#item_$s\"><tt>$c</tt></a>" |
199 |
|
|
]eg; |
200 |
|
|
$c .= $s . "\n"; |
201 |
|
|
} |
202 |
|
|
return $c; |
203 |
|
|
}; |
204 |
|
|
} elsif ( $type eq "docs" ) { |
205 |
|
|
# |
206 |
|
|
# Because the content might be large, we use |
207 |
|
|
# a sub to return the data in 64K chunks. |
208 |
|
|
# |
209 |
|
|
$contentSub = sub { |
210 |
|
|
my($c, $s); |
211 |
|
|
while ( length($c) < 65536 ) { |
212 |
|
|
$s = $fh->readLine(); |
213 |
|
|
last if ( $s eq "" ); |
214 |
|
|
$c .= $s; |
215 |
|
|
} |
216 |
|
|
return $c; |
217 |
|
|
}; |
218 |
|
|
# |
219 |
|
|
# Documentation has a different header and no pre or post text, |
220 |
|
|
# so just handle it here |
221 |
|
|
# |
222 |
|
|
Header($Lang->{BackupPC__Documentation}, "", 0, $contentSub); |
223 |
|
|
Trailer(); |
224 |
|
|
return; |
225 |
|
|
} else { |
226 |
|
|
# |
227 |
|
|
# Because the content might be large, we use |
228 |
|
|
# a sub to return the data in 64K chunks. |
229 |
|
|
# |
230 |
|
|
$contentSub = sub { |
231 |
|
|
my($c, $s); |
232 |
|
|
while ( length($c) < 65536 ) { |
233 |
|
|
$s = $fh->readLine(); |
234 |
|
|
last if ( $s eq "" ); |
235 |
|
|
$s =~ s/[\n\r]+//g; |
236 |
|
|
$s = ${EscHTML($s)}; |
237 |
|
|
$c .= $s . "\n"; |
238 |
|
|
} |
239 |
|
|
return $c; |
240 |
|
|
}; |
241 |
|
|
} |
242 |
|
|
} else { |
243 |
|
|
if ( $type eq "docs" ) { |
244 |
|
|
ErrorExit(eval("qq{$Lang->{Unable_to_open__file__configuration_problem}}")); |
245 |
|
|
} |
246 |
|
|
$contentPre .= eval("qq{$Lang->{_pre___Can_t_open_log_file__file}}"); |
247 |
|
|
} |
248 |
|
|
$contentPost .= "</pre>\n" if ( $type ne "docs" ); |
249 |
|
|
Header(eval("qq{$Lang->{Backup_PC__Log_File__file}}"), |
250 |
|
|
$contentPre, !-f "$TopDir/pc/$host/backups", |
251 |
|
|
$contentSub, $contentPost); |
252 |
|
|
Trailer(); |
253 |
|
|
$fh->close() if ( defined($fh) ); |
254 |
|
|
} |
255 |
|
|
|
256 |
|
|
1; |