]> git.sur5r.net Git - bacula/bacula/blob - gui/bweb/cgi/bfileview.pl
ebl cleanup
[bacula/bacula] / gui / bweb / cgi / bfileview.pl
1 #!/usr/bin/perl -w
2
3 =head1 LICENSE
4
5    Bweb - A Bacula web interface
6    Bacula® - The Network Backup Solution
7
8    Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
9
10    The main author of Bweb is Eric Bollengier.
11    The main author of Bacula is Kern Sibbald, with contributions from
12    many others, a complete list can be found in the file AUTHORS.
13
14    This program is Free Software; you can redistribute it and/or
15    modify it under the terms of version two of the GNU General Public
16    License as published by the Free Software Foundation plus additions
17    that are listed in the file LICENSE.
18
19    This program is distributed in the hope that it will be useful, but
20    WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22    General Public License for more details.
23
24    You should have received a copy of the GNU General Public License
25    along with this program; if not, write to the Free Software
26    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27    02110-1301, USA.
28
29    Bacula® is a registered trademark of John Walker.
30    The licensor of Bacula is the Free Software Foundation Europe
31    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zurich,
32    Switzerland, email:ftf@fsfeurope.org.
33
34 =head1 VERSION
35
36     $Id$
37
38 =cut
39
40 use strict;
41 use POSIX qw/strftime/;
42 use Bweb;
43 use CCircle ;
44 use Digest::MD5 qw(md5_hex);
45 use File::Basename qw/basename dirname/;
46
47 my $conf = new Bweb::Config(config_file => $Bweb::config_file);
48 $conf->load();
49 my $bweb = new Bweb(info => $conf);
50 $bweb->connect_db();
51
52 my $arg = $bweb->get_form('where', 'jobid', 'pathid', 'filenameid');
53 my $where = $arg->{where} || '/';
54 my $jobid = $arg->{jobid};
55 my $pathid = $arg->{pathid};
56 my $fnid = $arg->{filenameid};
57 my $jobid_url = "jobid=$jobid";
58 my $opt_level = 2 ;
59 my $max_file = 20;
60 my $batch = CGI::param("mode") || '';
61
62 my $md5_rep = md5_hex("$where:$jobid") ;
63 my $base_url = '/bweb/fv' ;
64 my $base_fich = $conf->{fv_write_path};
65
66 if ($jobid and $batch eq 'batch') {
67     my $root = fv_get_root_pathid($where);
68     if ($root) {
69         fv_compute_size($jobid, $root);
70         exit 0;
71     }
72     exit 1;
73 }
74
75 print CGI::header('text/html');
76 $bweb->display_begin();
77 $bweb->display_job_zoom($jobid);
78
79 unless ($jobid) {
80     $bweb->error("Can't get where or jobid");
81     exit 0;
82 }
83
84 unless ($base_fich and -w $base_fich) {
85     $bweb->error("fv_write_path ($base_fich) is not writable." . 
86                  " See Bweb configuration.");
87     exit 0;
88 }
89
90 if (-f "$base_fich/$md5_rep.png" and -f "$base_fich/$md5_rep.tpl")
91 {
92     $bweb->display({}, "$base_fich/$md5_rep.tpl");
93     $bweb->display_end();
94     exit 0;
95 }
96
97
98 # if it's a file, display it
99 if ($fnid and $pathid)
100 {
101     my $attribs = fv_get_file_attribute_from_id($jobid, $pathid, $fnid);
102     if ($attribs->{found}) {
103         $bweb->display($attribs, 'fv_file_attribs.tpl');
104         $bweb->display_end();
105         exit 0;
106     }
107
108 } else {
109
110     my $attribs = fv_get_file_attribute($jobid, $where);
111     if ($attribs->{found}) {
112         $bweb->display($attribs, 'fv_file_attribs.tpl');
113         $bweb->display_end();
114         exit 0;
115     }
116 }
117
118 my $root;
119
120 if ($pathid) {
121     $root = $pathid;
122     $where = fv_get_root_path($pathid);
123
124 } else {
125     if ($where !~ m!/$!) {
126         $where = $where . "/" ;
127     }
128     
129     $root = fv_get_root_pathid($where);
130 }
131
132 if (!$root) {
133     $bweb->error("Can't find $where in catalog");
134     $bweb->display_end();
135     exit 0;
136 }
137
138 my $total = fv_compute_size($jobid, $root);
139
140 my $url_action = "bfileview.pl?opt_level=$opt_level" ;
141 my $top = new CCircle(
142                       display_other => 1,
143                       base_url => "$url_action;pathid=$root;$jobid_url;where=$where",
144                       ) ;
145
146 fv_display_rep($top, $total, $root, $opt_level) ;
147
148 $top->draw_labels() ;
149 $top->set_title(Bweb::human_size($total)) ;
150
151 open(OUT, ">$base_fich/$md5_rep.png") or die "$base_fich/$md5_rep.png $!";
152 # make sure we are writing to a binary stream
153 binmode OUT;
154 # Convert the image to PNG and print it on standard output
155 print OUT $CCircle::gd->png;
156 close(OUT) ;
157
158 open(OUT, ">$base_fich/$md5_rep.tpl") or die "$base_fich/$md5_rep.tpl $!";
159 print OUT "
160  <form action='$url_action' method='get'>
161   <div align='right'>
162    <input title='jobids' type='hidden' name='jobid' value='$jobid'>
163    <input title='repertoire' type='text' name='where' value='$where'/>
164    <input type='submit' size='256' name='go' value='go'/>
165   </div>
166  </form>
167  <br/>
168 " ;
169
170 print OUT $top->get_imagemap($where, "$base_url/$md5_rep.png") ;
171 close(OUT) ;
172
173 $bweb->display({}, "$base_fich/$md5_rep.tpl");
174 $bweb->display_end();
175
176 sub fv_display_rep
177 {
178     my ($ccircle, $max, $rep, $level) = @_ ;
179     return if ($max < 1);
180
181     my $sum = 0;
182     my $dirs = fv_list_dirs($jobid, $rep);      # 0: pathid, 1: pathname
183
184     foreach my $dir (@{$dirs})
185     {
186         my $size = fv_compute_size($jobid, $dir->[0]);
187         $sum += $size;
188
189         my $per = $size * 100 / $max;
190         # can't use pathname when using utf or accent
191         # a bit ugly
192         $ccircle->{base_url} =~ s/pathid=\d+;/pathid=$dir->[0];/;
193
194         my $chld = $ccircle->add_part($per, 
195                                       basename($dir->[1]) . '/',
196                                       basename($dir->[1]) 
197                                        . sprintf(' %.0f%% ', $per)
198                                        . Bweb::human_size($size)
199                                       ) ;
200
201         if ($chld && $level > 0) {
202             fv_display_rep($chld, $size, $dir->[0], $level - 1) ;
203         }
204     }
205
206     # 0: filenameid, 1: filename, 2: size
207     my $files = fv_get_big_files($jobid, $rep, 3*100/$max, $max_file/($level+1));
208     foreach my $f (@{$files}) {
209         $ccircle->{base_url} =~ s/pathid=\d+;(filenameid=\d+;)?/pathid=$rep;filenameid=$f->[0];/;
210         $ccircle->add_part($f->[2] * 100 / $max, 
211                            $f->[1],
212                            $f->[1] . "\n" . Bweb::human_size($f->[2]));
213         $sum += $f->[2];
214     }
215
216     if ($sum < $max) {
217         $ccircle->add_part(($max - $sum) * 100 / $max, 
218                            "other files < 3%",
219                            "other\n" . Bweb::human_size($max - $sum));
220     }
221
222     $ccircle->finalize() ;
223 }
224
225 sub fv_compute_size
226 {
227     my ($jobid, $rep) = @_;
228
229     my $size = fv_get_size($jobid, $rep);
230     if ($size) {
231         return $size;
232     }
233
234     $size = fv_get_files_size($jobid, $rep);
235
236     my $dirs = fv_list_dirs($jobid, $rep);
237     foreach my $dir (@{$dirs}) {
238         $size += fv_compute_size($jobid, $dir->[0]);
239     }
240     
241     fv_update_size($jobid, $rep, $size);
242     return $size;
243 }
244
245 sub fv_list_dirs
246 {
247     my ($jobid, $rep) = @_;
248
249     my $ret = $bweb->dbh_selectall_arrayref("
250       SELECT P.PathId,
251              ( SELECT Path FROM Path WHERE PathId = P.PathId) AS Path
252         FROM (
253           SELECT PathId
254             FROM brestore_pathvisibility 
255       INNER JOIN brestore_pathhierarchy USING (PathId)
256            WHERE PPathId  = $rep
257              AND JobId = $jobid
258              ) AS P
259 ");
260
261     return $ret;
262 }
263
264 sub fv_get_file_attribute
265 {
266     my ($jobid, $full_name) = @_;
267     
268     my $filename = $bweb->dbh_quote(basename($full_name));
269     my $path     = $bweb->dbh_quote(dirname($full_name) . "/");
270
271     my $attr = $bweb->dbh_selectrow_hashref("
272  SELECT 1    AS found,
273         MD5  AS md5,
274         base64_decode_lstat(8,  LStat) AS size,
275         base64_decode_lstat(11, LStat) AS atime,
276         base64_decode_lstat(12, LStat) AS mtime,
277         base64_decode_lstat(13, LStat) AS ctime
278
279    FROM File INNER JOIN Filename USING (FilenameId)
280              INNER JOIN Path     USING (PathId)
281   WHERE Name  = $filename
282    AND  Path  = $path
283    AND  JobId = $jobid
284 ");
285
286     $attr->{filename} = $full_name;
287     $attr->{size} = Bweb::human_size($attr->{size});
288     foreach my $d (qw/atime ctime mtime/) {
289         $attr->{$d} = strftime('%F %H:%M', localtime($attr->{$d}));
290     }
291     return $attr;
292 }
293
294
295 sub fv_get_file_attribute_from_id
296 {
297     my ($jobid, $pathid, $filenameid) = @_;
298     
299     my $attr = $bweb->dbh_selectrow_hashref("
300  SELECT 1    AS found,
301         MD5  AS md5,
302         base64_decode_lstat(8,  LStat) AS size,
303         base64_decode_lstat(11, LStat) AS atime,
304         base64_decode_lstat(12, LStat) AS mtime,
305         base64_decode_lstat(13, LStat) AS ctime,
306         Path.Path ||  Filename.Name AS filename
307
308    FROM File INNER JOIN Filename USING (FilenameId)
309              INNER JOIN Path     USING (PathId)
310   WHERE FilenameId  = $filenameid
311    AND  PathId  = $pathid
312    AND  JobId = $jobid
313 ");
314
315     $attr->{size} = Bweb::human_size($attr->{size});
316     foreach my $d (qw/atime ctime mtime/) {
317         $attr->{$d} = strftime('%F %H:%M', localtime($attr->{$d}));
318     }
319     return $attr;
320 }
321
322 sub fv_get_size
323 {
324     my ($jobid, $rep) = @_;
325
326     my $ret = $bweb->dbh_selectrow_hashref("
327  SELECT Size AS size
328    FROM brestore_pathvisibility
329   WHERE PathId = $rep
330     AND JobId = $jobid
331 ");
332
333     return $ret->{size};
334 }
335
336 sub fv_get_files_size
337 {
338     my ($jobid, $rep) = @_;
339
340     my $ret = $bweb->dbh_selectrow_hashref("
341  SELECT sum(base64_decode_lstat(8,LStat)) AS size
342    FROM File
343   WHERE PathId  = $rep
344     AND JobId = $jobid
345 ");
346
347     return $ret->{size};
348 }
349
350 sub fv_get_big_files
351 {
352     my ($jobid, $rep, $min, $limit) = @_;
353
354     my $ret = $bweb->dbh_selectall_arrayref("
355    SELECT Name AS name, size, FilenameId AS filenameid
356    FROM (
357          SELECT FilenameId,base64_decode_lstat(8,LStat) AS size
358            FROM File
359           WHERE PathId  = $rep
360             AND JobId = $jobid
361         ) AS S INNER JOIN Filename USING (FilenameId)
362    WHERE S.size > $min
363    ORDER BY S.size DESC
364    LIMIT $limit
365 ");
366
367     return $ret;
368 }
369
370 sub fv_update_size
371 {
372     my ($jobid, $rep, $size) = @_;
373
374     my $nb = $bweb->dbh_do("
375  UPDATE brestore_pathvisibility SET Size = $size 
376   WHERE JobId = $jobid 
377     AND PathId = $rep 
378 ");
379
380     return $nb;
381 }
382
383 sub fv_get_root_pathid
384 {
385     my ($path) = @_;
386     $path = $bweb->dbh_quote($path);
387     my $ret = $bweb->dbh_selectrow_hashref("SELECT PathId FROM Path WHERE Path = $path");
388     return $ret->{pathid};
389 }
390
391 sub fv_get_root_path
392 {
393     my ($pathid) = @_;
394     my $ret = $bweb->dbh_selectrow_hashref("SELECT Path FROM Path WHERE PathId = $pathid");
395     return $ret->{path};
396 }
397
398
399 __END__
400
401 CREATE OR REPLACE FUNCTION base64_decode_lstat(int4, varchar) RETURNS int8 AS $$
402 DECLARE
403 val int8;
404 b64 varchar(64);
405 size varchar(64);
406 i int;
407 BEGIN
408 size := split_part($2, ' ', $1);
409 b64 := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
410 val := 0;
411 FOR i IN 1..length(size) LOOP
412 val := val + (strpos(b64, substr(size, i, 1))-1) * (64^(length(size)-i));
413 END LOOP;
414 RETURN val;
415 END;
416 $$ language 'plpgsql';
417
418 ALTER TABLE brestore_pathvisibility ADD Size  int8;
419
420
421
422 ALTER TABLE brestore_pathvisibility ADD Files int4;