]> git.sur5r.net Git - bacula/bacula/blob - gui/bweb/cgi/bfileview.pl
ebl fix add some missing % in tooltips
[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');
53 my $where = $arg->{where};
54 my $jobid = $arg->{jobid};
55 my $jobid_url = "jobid=$jobid";
56 my $opt_level = 2 ;
57 my $max_file = 20;
58 my $batch = CGI::param("mode") || '';
59
60 my $md5_rep = md5_hex("$where:$jobid") ;
61 my $base_url = '/bweb/fv' ;
62 my $base_fich = $conf->{fv_write_path};
63
64 if ($where and $jobid and $batch eq 'batch') {
65     my $root = fv_get_root_pathid($where);
66     if ($root) {
67         fv_compute_size($jobid, $root);
68         exit 0;
69     }
70     exit 1;
71 }
72
73 print CGI::header('text/html');
74 $bweb->display_begin();
75 $bweb->display_job_zoom($jobid);
76
77 unless ($where and $jobid) {
78     $bweb->error("Can't get where or jobid");
79     exit 0;
80 }
81
82 unless (-w $base_fich) {
83     $bweb->error("$base_fich is not writable");
84     exit 0;
85 }
86
87 if (-f "$base_fich/$md5_rep.png" and -f "$base_fich/$md5_rep.tpl")
88 {
89     $bweb->display({}, "$base_fich/$md5_rep.tpl");
90     $bweb->display_end();
91     exit 0;
92 }
93  
94 my $attribs = fv_get_file_attribute($jobid, $where);
95 if ($attribs->{found}) {
96     $bweb->display($attribs, 'fv_file_attribs.tpl');
97     $bweb->display_end();
98     exit 0;
99 }
100
101 if ($where !~ m!/$!) {
102     $where = $where . "/" ;
103 }
104
105 my $root = fv_get_root_pathid($where);
106 if (!$root) {
107     $bweb->error("Can't find $where in catalog");
108     $bweb->display_end();
109     exit 0;
110 }
111
112 my $total = fv_compute_size($jobid, $root);
113
114 my $url_action = "bfileview.pl?opt_level=$opt_level" ;
115 my $top = new CCircle(
116                       display_other => 1,
117                       base_url => "$url_action;$jobid_url;where=$where",
118                       ) ;
119
120 fv_display_rep($top, $total, $root, $opt_level) ;
121
122 $top->draw_labels() ;
123 $top->set_title(Bweb::human_size($total)) ;
124
125 open(OUT, ">$base_fich/$md5_rep.png") or die "$base_fich/$md5_rep.png $!";
126 # make sure we are writing to a binary stream
127 binmode OUT;
128 # Convert the image to PNG and print it on standard output
129 print OUT $CCircle::gd->png;
130 close(OUT) ;
131
132 open(OUT, ">$base_fich/$md5_rep.tpl") or die "$base_fich/$md5_rep.tpl $!";
133 print OUT "
134  <form action='$url_action' method='get'>
135   <div align='right'>
136    <input title='jobids' type='hidden' name='jobid' value='$jobid'>
137    <input title='repertoire' type='text' name='where' value='$where'/>
138    <input type='submit' size='256' name='go' value='go'/>
139   </div>
140  </form>
141  <br/>
142 " ;
143
144 print OUT $top->get_imagemap($where, "$base_url/$md5_rep.png") ;
145 close(OUT) ;
146
147 $bweb->display({}, "$base_fich/$md5_rep.tpl");
148 $bweb->display_end();
149
150 sub fv_display_rep
151 {
152     my ($ccircle, $max, $rep, $level) = @_ ;
153     return if ($max < 1);
154
155     my $sum = 0;
156     my $dirs = fv_list_dirs($jobid, $rep);      # 0: pathid, 1: pathname
157
158     foreach my $dir (@{$dirs})
159     {
160         my $size = fv_compute_size($jobid, $dir->[0]);
161         $sum += $size;
162
163         my $per = $size * 100 / $max;
164         my $chld = $ccircle->add_part($per, 
165                                       basename($dir->[1]) . '/',
166                                       basename($dir->[1]) 
167                                        . sprintf(' %.0f%% ', $per)
168                                        . Bweb::human_size($size)
169                                       ) ;
170         
171         if ($chld and $level > 0) {
172             fv_display_rep($chld, $size, $dir->[0], $level - 1) ;
173         }
174     }
175
176     # 0: name, 1: size
177     my $files = fv_get_big_files($jobid, $rep, 3*100/$max, $max_file/($level+1));
178     foreach my $f (@{$files}) {
179         $ccircle->add_part($f->[1] * 100 / $max, 
180                            $f->[0],
181                            $f->[0] . "\n" . Bweb::human_size($f->[1]));
182         $sum += $f->[1];
183     }
184
185     if ($sum < $max) {
186         $ccircle->add_part(($max - $sum) * 100 / $max, 
187                            "other files < 3%",
188                            "other\n" . Bweb::human_size($max - $sum));
189     }
190
191     $ccircle->finalize() ;
192 }
193
194 sub fv_compute_size
195 {
196     my ($jobid, $rep) = @_;
197
198     my $size = fv_get_size($jobid, $rep);
199     if ($size) {
200         return $size;
201     }
202
203     $size = fv_get_files_size($jobid, $rep);
204
205     my $dirs = fv_list_dirs($jobid, $rep);
206     foreach my $dir (@{$dirs}) {
207         $size += fv_compute_size($jobid, $dir->[0]);
208     }
209     
210     fv_update_size($jobid, $rep, $size);
211     return $size;
212 }
213
214 sub fv_list_dirs
215 {
216     my ($jobid, $rep) = @_;
217
218     my $ret = $bweb->dbh_selectall_arrayref("
219       SELECT P.PathId,
220              (
221               SELECT Path FROM Path WHERE PathId = P.PathId
222               UNION 
223               SELECT Path FROM brestore_missing_path WHERE PathId = P.PathId
224              ) AS Path
225         FROM (
226           SELECT PathId
227             FROM brestore_pathvisibility 
228       INNER JOIN brestore_pathhierarchy USING (PathId)
229            WHERE PPathId  = $rep
230              AND JobId = $jobid
231              ) AS P
232 ");
233
234     return $ret;
235 }
236
237 sub fv_get_file_attribute
238 {
239     my ($jobid, $full_name) = @_;
240     
241     my $filename = $bweb->dbh_quote(basename($full_name));
242     my $path     = $bweb->dbh_quote(dirname($full_name) . "/");
243
244     my $attr = $bweb->dbh_selectrow_hashref("
245  SELECT 1    AS found,
246         MD5  AS md5,
247         base64_decode_lstat(8,  LStat) AS size,
248         base64_decode_lstat(11, LStat) AS atime,
249         base64_decode_lstat(12, LStat) AS mtime,
250         base64_decode_lstat(13, LStat) AS ctime
251
252    FROM File INNER JOIN Filename USING (FilenameId)
253              INNER JOIN Path     USING (PathId)
254   WHERE Name  = $filename
255    AND  Path  = $path
256    AND  JobId = $jobid
257 ");
258
259     $attr->{filename} = $full_name;
260     $attr->{size} = Bweb::human_size($attr->{size});
261     foreach my $d (qw/atime ctime mtime/) {
262         $attr->{$d} = strftime('%F %H:%M', localtime($attr->{$d}));
263     }
264     return $attr;
265 }
266
267 sub fv_get_size
268 {
269     my ($jobid, $rep) = @_;
270
271     my $ret = $bweb->dbh_selectrow_hashref("
272  SELECT Size AS size
273    FROM brestore_pathvisibility
274   WHERE PathId = $rep
275     AND JobId = $jobid
276 ");
277
278     return $ret->{size};
279 }
280
281 sub fv_get_files_size
282 {
283     my ($jobid, $rep) = @_;
284
285     my $ret = $bweb->dbh_selectrow_hashref("
286  SELECT sum(base64_decode_lstat(8,LStat)) AS size
287    FROM File
288   WHERE PathId  = $rep
289     AND JobId = $jobid
290 ");
291
292     return $ret->{size};
293 }
294
295 sub fv_get_big_files
296 {
297     my ($jobid, $rep, $min, $limit) = @_;
298
299     my $ret = $bweb->dbh_selectall_arrayref("
300    SELECT Name, size
301    FROM (
302          SELECT FilenameId,base64_decode_lstat(8,LStat) AS size
303            FROM File
304           WHERE PathId  = $rep
305             AND JobId = $jobid
306         ) AS S INNER JOIN Filename USING (FilenameId)
307    WHERE S.size > $min
308    ORDER BY S.size DESC
309    LIMIT $limit
310 ");
311
312     return $ret;
313 }
314
315 sub fv_update_size
316 {
317     my ($jobid, $rep, $size) = @_;
318
319     my $nb = $bweb->dbh_do("
320  UPDATE brestore_pathvisibility SET Size = $size 
321   WHERE JobId = $jobid 
322     AND PathId = $rep 
323 ");
324
325     return $nb;
326 }
327
328 sub fv_get_root_pathid
329 {
330     my ($path) = @_;
331     $path = $bweb->dbh_quote($path);
332     my $ret = $bweb->dbh_selectrow_hashref("
333 SELECT PathId FROM Path WHERE Path = $path
334    UNION 
335 SELECT PathId FROM brestore_missing_path WHERE PATH = $path
336 ");
337     return $ret->{pathid};
338 }
339
340 __END__
341
342 CREATE OR REPLACE FUNCTION base64_decode_lstat(int4, varchar) RETURNS int8 AS $$
343 DECLARE
344 val int8;
345 b64 varchar(64);
346 size varchar(64);
347 i int;
348 BEGIN
349 size := split_part($2, ' ', $1);
350 b64 := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
351 val := 0;
352 FOR i IN 1..length(size) LOOP
353 val := val + (strpos(b64, substr(size, i, 1))-1) * (64^(length(size)-i));
354 END LOOP;
355 RETURN val;
356 END;
357 $$ language 'plpgsql';
358
359 ALTER TABLE brestore_pathvisibility ADD Size  int8;
360
361
362
363 ALTER TABLE brestore_pathvisibility ADD Files int4;