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