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