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