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