]> git.sur5r.net Git - bacula/bacula/commitdiff
ebl add fileview tool
authorEric Bollengier <eric@eb.homelinux.org>
Fri, 29 Dec 2006 21:21:40 +0000 (21:21 +0000)
committerEric Bollengier <eric@eb.homelinux.org>
Fri, 29 Dec 2006 21:21:40 +0000 (21:21 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@3857 91ce42f0-d328-0410-95d8-f526ca767f89

18 files changed:
gui/bweb/INSTALL
gui/bweb/ReleaseNotes
gui/bweb/cgi/bfileview.pl [new file with mode: 0755]
gui/bweb/html/colorscm.png [new file with mode: 0644]
gui/bweb/lang/fr/tpl/begin.tpl
gui/bweb/lang/fr/tpl/config_edit.tpl
gui/bweb/lang/fr/tpl/config_view.tpl
gui/bweb/lang/fr/tpl/display_job_zoom.tpl
gui/bweb/lang/fr/tpl/fv_file_attribs.tpl [new file with mode: 0644]
gui/bweb/lang/fr/tpl/update_media.tpl
gui/bweb/lib/Bweb.pm
gui/bweb/lib/CCircle.pm [new file with mode: 0644]
gui/bweb/tpl/begin.tpl
gui/bweb/tpl/config_edit.tpl
gui/bweb/tpl/config_view.tpl
gui/bweb/tpl/display_job_zoom.tpl
gui/bweb/tpl/fv_file_attribs.tpl [new file with mode: 0644]
gui/bweb/tpl/update_media.tpl

index 11a97141e9526c3dce924f43279de704764da4f5..eec169a2857f470e1b46e3f470a696ac3e9ef44c 100644 (file)
@@ -12,6 +12,7 @@ Bweb works well with 1.39 release.
 6) get bacula log more useful
 7) bweb limitation
 8) using sudo with autochanger
+9) using bfileview.pl
 
 ################ FILE COPY #####################################
  # you must get bweb cvs files
@@ -54,6 +55,7 @@ Simply use lang/fr/tpl/*.tpl files instead of tpl/*.tpl
  - perl modules
     - DBI (with mysql or postgresql support DBD::Pg and DBD::mysql)
     - Gd::Graph
+    - Gd
     - HTML::Template
     - CGI
     - Expect
@@ -171,5 +173,30 @@ www-data ALL = (root) NOPASSWD: /usr/sbin/mtx -f /dev/changer status
 www-data ALL = (root) NOPASSWD: /usr/sbin/mtx -f /dev/changer load *
 www-data ALL = (root) NOPASSWD: /usr/sbin/mtx -f /dev/changer unload *
 
+################ BFILEVIEW SETUP ###############################
+
+At this time, bfileview works only with postgresql.
+
+Alias /bweb/fv /var/spool/bweb
+<Directory "/var/spool/bweb">
+    Options None
+    AllowOverride AuthConfig
+    Order allow,deny
+    Allow from all
+</Directory>
+
+mkdir /var/spool/bweb
+chmod 700 /var/spool/bweb
+chown www-data /var/spool/bweb
+
+You must use brestore.pl -b to initialise the database, and
+you can use bfileview.pl mode=batch jobid=xxx where=/ to compute tree size.
+
+At this time, it's a good idea to schedule brestore.pl -g after your BackupCatalog
+job.
+
+To upgrade from an old installation, you can use :
+ALTER TABLE brestore_pathvisibility ADD Size int8;
+
 
 Enjoy !
index 1b971eddcfebf95fd741770d6966e9b45d8d56d5..6095a109e0e9d6a588052177c40b39860edf3bb0 100644 (file)
@@ -1,4 +1,11 @@
-          Release Notes for bweb 1.39.28
+          Release Notes for bweb 1.39.32
+
+2006/12/29
+ - Add graphical backup view. See INSTALL to enable it. It's usefull
+   for tuning backup.
+   NOTES : 
+    - You must use brestore -b to initialise database after BackupCatalog job
+    - If you have an old installation, you must alter your schema (see INSTALL)
 
 2006/12/14
  - Add pool filter to job form
diff --git a/gui/bweb/cgi/bfileview.pl b/gui/bweb/cgi/bfileview.pl
new file mode 100755 (executable)
index 0000000..0d9c043
--- /dev/null
@@ -0,0 +1,346 @@
+#!/usr/bin/perl -w
+
+=head1 LICENSE
+
+   Bweb - A Bacula web interface
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+
+   The main author of Bweb is Eric Bollengier.
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation plus additions
+   that are listed in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zurich,
+   Switzerland, email:ftf@fsfeurope.org.
+
+=head1 VERSION
+
+    $Id$
+
+=cut
+
+# TODO:
+#  Si c'est un fichier selectionne, afficher ses attributs
+#  ajouter le base_fic et base_url dans les options bweb
+#
+
+use strict;
+use Bweb;
+use CCircle ;
+use Digest::MD5 qw(md5_hex);
+use File::Basename qw/basename dirname/;
+
+my $conf = new Bweb::Config(config_file => '/etc/bweb/config');
+$conf->load();
+my $bweb = new Bweb(info => $conf);
+$bweb->connect_db();
+
+my $arg = $bweb->get_form('where', 'jobid');
+my $where = $arg->{where};
+my $jobid = $arg->{jobid};
+my $jobid_url = "jobid=$jobid";
+my $opt_level = 2 ;
+my $max_file = 20;
+my $batch = CGI::param("mode") || '';
+
+my $md5_rep = md5_hex("$where:$jobid") ;
+my $base_url = '/bweb/fv' ;
+my $base_fich = $conf->{fv_write_path};
+
+die "Can't get where" unless ($where and $jobid);
+
+if ($batch eq 'batch') {
+    my $root = fv_get_root_pathid($where);
+    if ($root) {
+       fv_compute_size($jobid, $root);
+       exit 0;
+    }
+    exit 1;
+}
+
+my $url_action = "bfileview.pl?opt_level=$opt_level" ;
+my $top = new CCircle(
+                     display_other => 1,
+                     base_url => "$url_action;$jobid_url;where=$where",
+                     ) ;
+
+print CGI::header('text/html');
+$bweb->display_begin();
+$bweb->display_job_zoom($jobid);
+
+if (-f "$base_fich/$md5_rep.png" and -f "$base_fich/$md5_rep.tpl")
+{
+    $bweb->display({}, "$base_fich/$md5_rep.tpl");
+    $bweb->display_end();
+    exit 0;
+}
+my $attribs = fv_get_file_attribute($jobid, $where);
+if ($attribs->{found}) {
+    $bweb->display($attribs, 'fv_file_attribs.tpl');
+    $bweb->display_end();
+    exit 0;
+}
+
+if ($where !~ m!/$!) {
+    $where = $where . "/" ;
+}
+
+my $root = fv_get_root_pathid($where);
+if (!$root) {
+    $bweb->error("Can't find $where in catalog");
+    $bweb->display_end();
+    exit 0;
+}
+
+my $total = fv_compute_size($jobid, $root);
+
+fv_display_rep($top, $total, $root, $opt_level) ;
+
+$top->draw_labels() ;
+$top->set_title(Bweb::human_size($total)) ;
+
+open(OUT, ">$base_fich/$md5_rep.png") or die "$base_fich/$md5_rep.png $!";
+# make sure we are writing to a binary stream
+binmode OUT;
+# Convert the image to PNG and print it on standard output
+print OUT $CCircle::gd->png;
+close(OUT) ;
+
+open(OUT, ">$base_fich/$md5_rep.tpl") or die "$base_fich/$md5_rep.tpl $!";
+print OUT "
+ <form action='$url_action' method='get'>
+  <div align='right'>
+   <input title='jobids' type='hidden' name='jobid' value='$jobid'>
+   <input title='repertoire' type='text' name='where' value='$where'/>
+   <input type='submit' size='256' name='go' value='go'/>
+  </div>
+ </form>
+ <br/>
+" ;
+
+print OUT $top->get_imagemap($where, "$base_url/$md5_rep.png") ;
+close(OUT) ;
+
+$bweb->display({}, "$base_fich/$md5_rep.tpl");
+$bweb->display_end();
+
+sub fv_display_rep
+{
+    my ($ccircle, $max, $rep, $level) = @_ ;
+    return if ($max < 1);
+
+    my $sum = 0;
+    my $dirs = fv_list_dirs($jobid, $rep);     # 0: pathid, 1: pathname
+
+    foreach my $dir (@{$dirs})
+    {
+       my $size = fv_compute_size($jobid, $dir->[0]);
+       $sum += $size;
+
+       my $chld = $ccircle->add_part($size * 100 / $max, 
+                                     basename($dir->[1]) . '/',
+                                     basename($dir->[1]) 
+                                      . "\n" 
+                                      . Bweb::human_size($size)
+                                     ) ;
+       
+       if ($chld and $level > 0) {
+           fv_display_rep($chld, $size, $dir->[0], $level - 1) ;
+       }
+    }
+
+    # 0: name, 1: size
+    my $files = fv_get_big_files($jobid, $rep, 3*100/$max, $max_file/($level+1));
+    foreach my $f (@{$files}) {
+       $ccircle->add_part($f->[1] * 100 / $max, 
+                          $f->[0],
+                          $f->[0] . "\n" . Bweb::human_size($f->[1]));
+       $sum += $f->[1];
+    }
+
+    if ($sum < $max) {
+       $ccircle->add_part(($max - $sum) * 100 / $max, 
+                          "other files < 3",
+                          "other\n" . Bweb::human_size($max - $sum));
+    }
+
+    $ccircle->finalize() ;
+}
+
+sub fv_compute_size
+{
+    my ($jobid, $rep) = @_;
+
+    my $size = fv_get_size($jobid, $rep);
+    if ($size) {
+       return $size;
+    }
+
+    $size = fv_get_files_size($jobid, $rep);
+
+    my $dirs = fv_list_dirs($jobid, $rep);
+    foreach my $dir (@{$dirs}) {
+       $size += fv_compute_size($jobid, $dir->[0]);
+    }
+    
+    fv_update_size($jobid, $rep, $size);
+    return $size;
+}
+
+sub fv_list_dirs
+{
+    my ($jobid, $rep) = @_;
+
+    my $ret = $bweb->dbh_selectall_arrayref("
+      SELECT P.PathId,
+             (
+              SELECT Path FROM Path WHERE PathId = P.PathId
+              UNION 
+              SELECT Path FROM brestore_missing_path WHERE PathId = P.PathId
+             ) AS Path
+        FROM (
+          SELECT PathId
+            FROM brestore_pathvisibility 
+      INNER JOIN brestore_pathhierarchy USING (PathId)
+           WHERE PPathId  = $rep
+             AND JobId = $jobid
+             ) AS P
+");
+
+    return $ret;
+}
+
+sub fv_get_file_attribute
+{
+    my ($jobid, $full_name) = @_;
+    
+    my $filename = $bweb->dbh_quote(basename($full_name));
+    my $path     = $bweb->dbh_quote(dirname($full_name) . "/");
+
+    my $attr = $bweb->dbh_selectrow_hashref("
+ SELECT 1 AS found,
+        base64_decode_lstat(8, lstat) AS size
+   FROM File INNER JOIN Filename USING (FilenameId)
+             INNER JOIN Path     USING (PathId)
+  WHERE Name  = $filename
+   AND  Path  = $path
+   AND  JobId = $jobid
+");
+
+    $attr->{filename} = $full_name;
+    $attr->{size} = Bweb::human_size($attr->{size});
+    return $attr;
+}
+
+sub fv_get_size
+{
+    my ($jobid, $rep) = @_;
+
+    my $ret = $bweb->dbh_selectrow_hashref("
+ SELECT Size AS size
+   FROM brestore_pathvisibility
+  WHERE PathId = $rep
+    AND JobId = $jobid
+");
+
+    return $ret->{size};
+}
+
+sub fv_get_files_size
+{
+    my ($jobid, $rep) = @_;
+
+    my $ret = $bweb->dbh_selectrow_hashref("
+ SELECT sum(base64_decode_lstat(8,lstat)) AS size
+   FROM File
+  WHERE PathId  = $rep
+    AND JobId = $jobid
+");
+
+    return $ret->{size};
+}
+
+sub fv_get_big_files
+{
+    my ($jobid, $rep, $min, $limit) = @_;
+
+    my $ret = $bweb->dbh_selectall_arrayref("
+   SELECT Name, size
+   FROM (
+         SELECT FilenameId,base64_decode_lstat(8,lstat) AS size
+           FROM File
+          WHERE PathId  = $rep
+            AND JobId = $jobid
+        ) AS S INNER JOIN Filename USING (FilenameId)
+   WHERE S.size > $min
+   ORDER BY S.size DESC
+   LIMIT $limit
+");
+
+    return $ret;
+}
+
+sub fv_update_size
+{
+    my ($jobid, $rep, $size) = @_;
+
+    my $nb = $bweb->dbh_do("
+ UPDATE brestore_pathvisibility SET Size = $size 
+  WHERE JobId = $jobid 
+    AND PathId = $rep 
+");
+
+    return $nb;
+}
+
+sub fv_get_root_pathid
+{
+    my ($path) = @_;
+    $path = $bweb->dbh_quote($path);
+    my $ret = $bweb->dbh_selectrow_hashref("
+SELECT PathId FROM Path WHERE Path = $path
+   UNION 
+SELECT PathId FROM brestore_missing_path WHERE PATH = $path
+");
+    return $ret->{pathid};
+}
+
+__END__
+
+CREATE OR REPLACE FUNCTION base64_decode_lstat(int4, varchar) RETURNS int8 AS $$
+DECLARE
+val int8;
+b64 varchar(64);
+size varchar(64);
+i int;
+BEGIN
+size := split_part($2, ' ', $1);
+b64 := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+val := 0;
+FOR i IN 1..length(size) LOOP
+val := val + (strpos(b64, substr(size, i, 1))-1) * (64^(length(size)-i));
+END LOOP;
+RETURN val;
+END;
+$$ language 'plpgsql';
+
+ALTER TABLE brestore_pathvisibility ADD Size int8;
diff --git a/gui/bweb/html/colorscm.png b/gui/bweb/html/colorscm.png
new file mode 100644 (file)
index 0000000..cf2ccef
Binary files /dev/null and b/gui/bweb/html/colorscm.png differ
index 3d6408fff54d1b9338916b09ae2d2cc25cf797b4..b604b2827b8aa461b908f0dc552a8530159a8f8d 100644 (file)
@@ -19,44 +19,44 @@ if (navigator.appName == 'Konqueror') {
 </script>
 
 <ul id="menu">
- <li><a href="?">Accueil</a> </li>
- <li><a href="?action=client">Clients</a></li>
- <li><a href="?action=run_job">Jobs</a>
+ <li><a href="bweb.pl?">Accueil</a> </li>
+ <li><a href="bweb.pl?action=client">Clients</a></li>
+ <li><a href="bweb.pl?action=run_job">Jobs</a>
    <ul> 
-     <li><a href="?action=run_job">Jobs définis</a>
-     <li><a href="?action=job">Historique</a> </li>
-     <li><a href="?action=running">Jobs en cours</a>
-     <li><a href="?action=next_job">Prochains Jobs</a> </li>
-     <li><a href="?action=restore" title="Lancer brestore">Restauration</a> </li>
+     <li><a href="bweb.pl?action=run_job">Jobs définis</a>
+     <li><a href="bweb.pl?action=job">Historique</a> </li>
+     <li><a href="bweb.pl?action=running">Jobs en cours</a>
+     <li><a href="bweb.pl?action=next_job">Prochains Jobs</a> </li>
+     <li><a href="bweb.pl?action=restore" title="Lancer brestore">Restauration</a> </li>
    </ul>
  </li>
  <li style="padding: 0.25em 2em;">Medias
   <ul>
-     <li><a href="?action=pool">Pools</a> </li>
-     <li><a href="?action=location">Localisations</a> </li>
-     <li><a href="?action=media">Tous les Medias</a><hr></li>
-     <li><a href="?action=extern_media">Externaliser</a> </li>
-     <li><a href="?action=intern_media">Internaliser</a> </li>
+     <li><a href="bweb.pl?action=pool">Pools</a> </li>
+     <li><a href="bweb.pl?action=location">Localisations</a> </li>
+     <li><a href="bweb.pl?action=media">Tous les Medias</a><hr></li>
+     <li><a href="bweb.pl?action=extern_media">Externaliser</a> </li>
+     <li><a href="bweb.pl?action=intern_media">Internaliser</a> </li>
   </ul>
  </li>
 <TMPL_IF achs>
  <li style="padding: 0.25em 2em;">Robotiques
   <ul>
 <TMPL_LOOP achs>
-   <li><a href="?action=ach_view;ach=<TMPL_VAR name>"><TMPL_VAR name></a></li>
+   <li><a href="bweb.pl?action=ach_view;ach=<TMPL_VAR name>"><TMPL_VAR name></a></li>
 </TMPL_LOOP>
   </ul>
  </li>
 </TMPL_IF> 
- <li><a href="?action=graph"> Statistiques </a></li>
- <li> <a href="?action=view_conf"> Configuration </a> </li>
- <li> <a href="?action=about"> A propos </a> </li>
+ <li><a href="bweb.pl?action=graph"> Statistiques </a></li>
+ <li> <a href="bweb.pl?action=view_conf"> Configuration </a> </li>
+ <li> <a href="bweb.pl?action=about"> A propos </a> </li>
  <li style="padding: 0.25em 2em;float: right;">&nbsp;Logged as <TMPL_VAR NAME=loginname> </li>
  <li style="float: right;white-space: nowrap;">
 <input type="image" class="button" title="chercher un media" onclick="search_media();" src="/bweb/tape.png"><input type="image" title="chercher un client" onclick="search_client();" src="/bweb/client.png">&nbsp;<input class='formulaire' style="margin: 0 2px 0 2px; padding: 0 0 0 0;" id='searchbox' type='text' size='8' value="rechercher..." onclick="this.value='';" title="chercher un media ou un client"></li>
 </ul>
 
-<form name="search" action="?" method='GET'>
+<form name="search" action="bweb.pl?" method='GET'>
  <input type="hidden" name="action" value="">
  <input type="hidden" name="re_media" value="">
  <input type="hidden" name="re_client" value="">
index 23ee9d343885440015afe806b55c57e1e9a9712c..d5fdb7cf3c3001044c8dec61f56f177b8b10f66d 100644 (file)
@@ -35,6 +35,9 @@
      <tr><td>template_dir :</td> 
          <td> <input class="formulaire" title="/chemin/vers/votre/template_dir" type='text' value='<TMPL_VAR NAME=template_dir>' size='64' name='template_dir'> 
          </td></tr>
+     <tr><td>fv_write_path :</td> 
+         <td> <input class="formulaire" title="Ce répertoire doit être accessible en écriture pour apache et être sous /bweb/fv" type='text' value='<TMPL_VAR fv_write_path>' size='64' name='fv_write_path'> 
+         </td></tr>
      <tr><td>bconsole :</td> 
          <td> <input class="formulaire" title="/chemin/vers/bconsole -n -c /chemin/vers/bconsole.conf" type='text' value='<TMPL_VAR NAME=bconsole>' size='64' name='bconsole'> 
          </td></tr>
index 6dffabf0a36f5a65a7738ba61f3622d5e0c1e1cd..c36d5ba914b043e3fab684c1a4185c9d892ded81 100644 (file)
@@ -13,6 +13,7 @@
     <tr>  <td><b>Configuration Bweb</b></td>  <td/></tr>
     <tr><td title="/chemin/vers/votre/template_dir">template_dir :</td> <td> <TMPL_VAR template_dir> </td></tr>
     <tr><td title="/chemin/vers/une/font.ttf">graph_font :</td> <td> <TMPL_VAR graph_font> </td></tr>
+    <tr><td title="Ce répertoire doit être accessible en ecriture pour apache et être sous /bweb/fv">fv_write_path :</td> <td> <TMPL_VAR fv_write_path> </td></tr>
     <tr><td title="/chemin/vers/bconsole -n -c /chemin/vers/bconsole.conf">bconsole :</td> <td> <TMPL_VAR bconsole> </td></tr>
     <tr><td>debug :</td> <td> <TMPL_VAR debug> </td></tr>
     <TMPL_IF achs>
index 0f3d8958c6364c887b7d3116e71f26676853dc39..9a52d63ab91d720f1b47189567773bf7374b94d2 100644 (file)
@@ -4,7 +4,7 @@
  <div class="bodydiv">
  <table id='id0'></table>
  <table><td>
- <form action='?'>
+ <form action='bweb.pl?'>
   <input type='hidden' name='jobid' value='<TMPL_VAR jobid>'>
   <label>
   <input type="image" name='action' value='delete' title='Supprimer ce job'
@@ -13,7 +13,7 @@
   </label>
  </form>
  </td><td>
- <form action='?'>
+ <form action='bweb.pl?'>
   <TMPL_LOOP volumes>
    <input type='hidden' name='media' value='<TMPL_VAR VolumeName>'>
   </TMPL_LOOP>   
@@ -24,7 +24,7 @@
  </form>
  </td>
  <td>
- <form action='?'>
+ <form action='bweb.pl?'>
   <input type='hidden' name='client' value='<TMPL_VAR Client>'>
   <label>
   <input type="image" name='action' value='job' title='Voir les jobs de <TMPL_VAR Client>' src='/bweb/zoom.png'>Voir les jobs
@@ -32,7 +32,7 @@
  </form>
  </td>
  <td>
- <form action='?'>
+ <form action='bweb.pl?'>
   <input type='hidden' name='age' value='2678400'>
   <input type='hidden' name='client' value='<TMPL_VAR Client>'>
   <input type='hidden' name='jobname' value='<TMPL_VAR jobname>'>
  </form>
  </td>
  <td>
- <form action='?'>
+ <form action='bweb.pl?'>
   <input type='hidden' name='fileset' value='<TMPL_VAR FileSet>'>
   <label>
-  <input type="image" name='action' value='fileset_view' title='Voir le fileset associé'
+  <input type="image" name='action' value='fileset_view' title='Voir le fileset associé'
    src='/bweb/zoom.png'> Voir le FileSet
   </label>
  </form>
  </td>
+<!-- Enlever ce commentaire pour activer le bfileview
+ <td>
+ <form action='bfileview.pl?'>
+  <input type='hidden' name='jobid' value='<TMPL_VAR jobid>'>
+  <input type='hidden' name='where' value='/'>
+  <label>
+  <input type="image" name='action' value='bfileview' title="Voir la répartition des fichiers"
+   src='/bweb/colorscm.png'> Voir la répartition des fichiers
+  </label>
+ </form>
+ </td>
+-->
  </table>
 </div>
 
diff --git a/gui/bweb/lang/fr/tpl/fv_file_attribs.tpl b/gui/bweb/lang/fr/tpl/fv_file_attribs.tpl
new file mode 100644 (file)
index 0000000..bb4dd24
--- /dev/null
@@ -0,0 +1,2 @@
+Filename : <TMPL_VAR filename><br/>
+Size     : <TMPL_VAR size><br/>
index 16b57b3e2eba0a34798cf60212d754e7093e857f..d43eebff6da84759e63068e8c0a2bd53a223245d 100644 (file)
   </label>
   <label>
   <input type="image" name='action' title='Mettre à jour à partir du pool'
-    value='update_from_pool' src='/bweb/update.png'> Mettre à jour
+    value='update_from_pool' src='/bweb/update.png'> Reinitialiser
   </label>
  </form>
  </td>
index c3d7ee65f14d28db7a8349dbd25d136b70283565..74b3c69040671d9653d56409e4afb8d038ff0156 100644 (file)
@@ -208,6 +208,7 @@ use CGI;
 our %k_re = ( dbi      => qr/^(dbi:(Pg|mysql):(?:\w+=[\w\d\.-]+;?)+)$/i,
              user     => qr/^([\w\d\.-]+)$/i,
              password => qr/^(.*)$/i,
+             fv_write_path => qr!^([/\w\d\.-]+)$!,
              template_dir => qr!^([/\w\d\.-]+)$!,
              debug    => qr/^(on)?$/,
              email_media => qr/^([\w\d\.-]+@[\d\w\.-]+)$/,
diff --git a/gui/bweb/lib/CCircle.pm b/gui/bweb/lib/CCircle.pm
new file mode 100644 (file)
index 0000000..4b1ef12
--- /dev/null
@@ -0,0 +1,543 @@
+package CCircle ;
+
+=head1 LICENSE
+
+   Bweb - A Bacula web interface
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+
+   The main author of Bweb is Eric Bollengier.
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation plus additions
+   that are listed in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of John Walker.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zurich,
+   Switzerland, email:ftf@fsfeurope.org.
+
+=head1 VERSION
+
+    $Id$
+
+=cut
+
+use strict ;
+use GD ;
+
+my $pi =  3.14159265;
+
+our $gd ;
+our @color_tab ; 
+
+our $black ;
+our $white ;
+
+our $last_level = 1 ;
+our @draw_label ; 
+our $height ;
+our $width ;
+
+our $cur_color = 1 ;
+
+my $debug = 0 ;
+my $font_size = 6 ;
+
+our @image_map ;
+
+sub new
+{
+    my ($class, %arg) = @_ ;
+
+    my $self = {
+       start_degrees    => 0,
+       degrees_complete => 0,
+       parent_percent   => 100,
+       level            => 1,
+       center_x         => 600,
+       center_y         => 300,
+       diameter         => 75,
+       percent_total    => 0,
+       min_percent      => 2,
+       min_total        => 0,
+       width            => 1200,
+       height           => 600,
+       min_label        => 4,
+       min_degrees      => 2,
+       max_label_level  => 2,
+       display_other    => 0,
+       base_url         => '',
+    } ;
+
+    map { $self->{$_} = $arg{$_} } keys %arg ;
+
+    unless(defined $gd) {
+       $height = $self->{height} ;
+       $width  = $self->{width} ;
+
+       $gd    = new GD::Image($width,$height);
+       $white = $gd->colorAllocate(255,255,255);
+
+       push @color_tab, ($gd->colorAllocate(135,236,88),
+                         $gd->colorAllocate(255,95,95),
+                         $gd->colorAllocate(245,207,91),
+                         $gd->colorAllocate( 255, 236, 139),
+                         $gd->colorAllocate( 255, 174, 185),
+                         $gd->colorAllocate( 179, 255,  58),
+                         $gd->colorAllocate( 205, 133,   0),
+                         $gd->colorAllocate(205, 133,   0 ),
+                         $gd->colorAllocate(238, 238, 209),
+
+                         ) ;
+                     
+
+       $black = $gd->colorAllocate(0,0,0);
+       #$gd->>transparent($white);
+       $gd->interlaced('true');
+
+       $gd->arc($self->{center_x},$self->{center_y}, 
+                $self->{diameter},$self->{diameter},
+                $self->{start_degrees},360, $black) ;
+
+    }
+
+    $self->{rayon} = $self->{diameter} / 2 ;
+
+    bless $self ;
+
+    # pour afficher les labels tout propre
+    if ($self->{level} > $last_level) {
+       $last_level = $self->{level} ;
+    }
+
+    return $self ;
+}
+
+sub calc_xy
+{
+    my ($self, $level, $deg) = @_ ;
+
+    my $x1 =   $self->{center_x}+$self->{rayon} * $level * cos($deg*$pi/180) ;
+    my $y1 =   $self->{center_y}+$self->{rayon} * $level * sin($deg*$pi/180) ;
+
+    return ($x1, $y1) ;
+
+}
+
+sub add_part
+{
+    my ($self, $percent, $label, $tips) = @_ ;
+
+    $tips = $tips || $label ;
+
+    if (($percent + $self->{percent_total}) > 100.05) {
+       print STDERR "Attention $label ($percent\% + $self->{percent_total}\%) > 100\%\n" ;
+       return undef; 
+    }
+
+    if ($percent <= 0) {
+       print STDERR "Attention $label <= 0\%\n" ;
+       return undef; 
+    }
+
+    # angle de depart de l'arc
+    my $start_degrees = (($self->{degrees_complete})?
+                        $self->{degrees_complete}:$self->{start_degrees}) ;
+
+    # angle de fin de l'arc
+    my $end_degrees = $start_degrees +
+       ($percent * ( ( $self->{parent_percent} * 360 )/100 ) ) /100 ;
+
+#    print STDERR "-------- $debug --------
+#percent = $percent%
+#label = $label
+#level = $self->{level}
+#start = $start_degrees
+#end   = $end_degrees
+#parent= $self->{parent_percent}
+#" ;
+    if (($end_degrees - $start_degrees) < $self->{min_degrees}) {
+       $self->{min_total} += $percent ;
+       return undef ;
+    }
+
+    if ($percent <= $self->{min_percent}) {
+       $self->{min_total} += $percent ;
+       return undef ;
+    }
+
+    # on totalise les % en cours
+    $self->{percent_total} += $percent ;
+
+    #print STDERR "percent_total = $self->{percent_total}\n" ;
+
+    # position dans le cercle
+    my $n = $self->{level} ; # on ajoute/retire 0.005 pour depasser un peu
+    my $m = $n+1 ;
+
+    # si c'est la premiere tranche de la nouvelle serie, il faut dessiner
+    # la premiere limite 
+
+    if ($self->{degrees_complete} == 0) {
+       my ($x1, $y1) = $self->calc_xy($n-0.005, $self->{start_degrees}) ;
+       my ($x2, $y2) = $self->calc_xy($m+0.005, $self->{start_degrees}) ;
+
+       $gd->line($x1, $y1, $x2, $y2, $black) ;
+    }
+
+    # seconde ligne
+    my ($x3, $y3) = $self->calc_xy($n-0.005, $end_degrees) ;
+
+    my ($x4, $y4) = $self->calc_xy($m+0.005, $end_degrees) ;
+
+    # ligne de bord exterieur
+    $gd->line($x3, $y3, $x4, $y4, $black);
+
+    # on dessine le bord
+    $gd->arc($self->{center_x},$self->{center_y}, 
+            $self->{diameter}*($self->{level}+1),
+            $self->{diameter}*($self->{level}+1),
+
+            $start_degrees-0.5,
+            $end_degrees+0.5, $black) ;
+
+    # on calcule le point qui est au milieu de la tranche
+    # angle = (angle nouvelle tranche)/2
+
+    # rayon = n*rayon - 0.5*rayon
+    # n=1 -> 0.5
+    # n=2 -> 1.5
+    # n=3 -> 2.5
+
+    my $mid_rad = ($end_degrees - $start_degrees) /2 + $start_degrees;
+
+    my $moy_x = ($self->{center_x}+
+                  ($self->{rayon}*$m - 0.5*$self->{rayon})
+                      *cos($mid_rad*$pi/180)) ;
+
+    my $moy_y = ($self->{center_y}+
+                  ($self->{rayon}*$m - 0.5*$self->{rayon})
+                      *sin($mid_rad*$pi/180)) ;
+
+    $gd->fillToBorder($moy_x, 
+                     $moy_y,
+                     $black,
+                     $cur_color) ;
+    
+    # on prend une couleur au hasard
+    $cur_color = ($cur_color % $#color_tab) + 1 ;
+
+    # si le % est assez grand, on affiche le label
+    if ($percent > $self->{min_label}) {
+       push @draw_label, [$label, 
+                          $moy_x, $moy_y, 
+                          $self->{level}] ;
+
+       $self->push_image_map($label, $tips, $start_degrees, $end_degrees) ;
+    }
+
+    # pour pourvoir ajouter des sous donnees
+    my $ret = new CCircle(start_degrees  => $start_degrees, 
+                         parent_percent => $percent*$self->{parent_percent}/100,
+                         level          => $m,
+                         center_x       => $self->{center_x},
+                         center_y       => $self->{center_y},
+                         min_percent    => $self->{min_percent},
+                         min_degrees    => $self->{min_degrees},
+                         base_url       => $self->{base_url} . $label,
+                         ) ;
+                
+    $self->{degrees_complete} = $end_degrees ;
+    
+    #print STDERR "$debug : [$self->{level}] $label ($percent)\n" ;
+    #open(FP, sprintf(">/tmp/img.%.3i.png", $debug)) ;
+    #print FP $gd->png;
+    #close(FP) ;
+    
+    $debug++ ;
+
+    return $ret ;
+}
+
+# on dessine le restant < min_percent
+sub finalize
+{
+    my ($self) = @_ ;
+
+    $self->add_part($self->{min_total}, 
+                   "other < $self->{min_percent}",
+                   $black) ; 
+
+}
+
+sub set_title
+{
+    my ($self, $title) = @_ ;
+
+    $gd->string(GD::gdSmallFont, $self->{center_x} - $self->{rayon}*0.7, 
+               $self->{center_y}, $title, $black) ;
+}
+
+my $_image_map = '';
+
+sub get_imagemap
+{
+    my ($self, $title, $img) = @_ ;
+
+    return "
+<map name='testmap'>
+    $_image_map
+</map>
+<img src='$img' border=0 usemap='#testmap' alt=''>
+" ; 
+
+}
+
+sub push_image_map
+{
+    my ($self, $label, $tips, $start_degrees, $end_degrees) = @_ ;
+
+    if ($label =~ /^other </) {
+       if (!$self->{display_other}) {
+           return ;
+       }
+       $label = '';
+    }
+
+    # on prend des points tous les $delta sur l'arc interieur et exterieur
+
+    my $delta = 3 ;
+
+    if (($end_degrees - $start_degrees) < $delta) {
+       return ;
+    }
+
+    my @pts ;
+
+    for (my $i = $start_degrees ; 
+        $i <= $end_degrees ; 
+        $i = $i + $delta)
+    {
+       my ($x1, $y1) = $self->calc_xy($self->{level}, $i) ;
+       my ($x2, $y2) = $self->calc_xy($self->{level} + 1, $i) ;
+
+       push @pts, sprintf("%.2f,%.2f",$x1,$y1) ;
+       unshift @pts, sprintf("%.2f,%.2f",$x2, $y2) ;
+    }
+
+    my ($x1, $y1) = $self->calc_xy($self->{level}, $end_degrees) ;
+    my ($x2, $y2) = $self->calc_xy($self->{level} + 1, $end_degrees) ;
+
+    push @pts, sprintf("%.2f,%.2f",$x1,$y1) ;
+    unshift @pts, sprintf("%.2f,%.2f",$x2, $y2) ;
+
+    my $ret = join(",", @pts) ;
+
+    # on refait le traitement avec $i = $end_degrees
+    $_image_map .= "<area shape='polygon' coords='$ret' ". 
+                  "title='$tips' href='$self->{base_url}$label'>\n" ;
+
+}
+
+sub get_labels_imagemap
+{
+    my ($self) = @_ ;
+    my @ret ;
+
+    for my $l (@draw_label)
+    {
+       # translation 
+       my ($label, $x, $y, $level) = @{ $l } ;
+       
+       next if ($level > $self->{max_label_level}) ;
+
+       next if (!$self->{display_other} and $label =~ /^other .*</) ;
+
+       my $dy = ($y - $self->{center_y})*($last_level - $level) + $y ;
+
+       my $x2 ;
+       my $xp ;
+
+       if ($x < $self->{center_x}) {
+           $x2 =   $self->{center_x} 
+                 - $self->{rayon} * ($last_level + 3.7) ;
+           $xp = $x2 - (length($label) *6 + 2) ; # moins la taille de la police 
+       } else {
+           $x2 = $self->{center_x} + $self->{rayon} * ($last_level + 3.7) ;
+           $xp = $x2 + 10 ;
+       }
+
+       push @ret, $xp - 1 . ";" . $dy - 6 . ";" . $xp + length($label) * $font_size . ";" . $dy + 10 . "\n" ;
+
+       $gd->rectangle($xp - 1, $dy - 6,
+                      $xp + length($label) * $font_size, 
+                      $dy + 10, $black) ;
+    }
+}
+
+my $_label_hauteur ;
+my $_label_max ;
+my $_label_pos ;
+my $_label_init = 0 ;
+
+# on va stocker les positions dans un bitmap $_label_pos
+# 
+# si on match pas la position exacte, on essaye la case
+# au dessus ou en dessous
+# 
+# on a un bitmap pour les labels de gauche et un pour la droite
+# $_label_pos->[0] et $_label_pos->[1]
+sub get_label_pos
+{
+    my ($self, $x, $y) = @_ ;
+
+    unless ($_label_init) {
+       $_label_hauteur   = $self->{rayon} * 2 * $last_level ;
+       # nombre max de label = hauteur max / taille de la font
+       $_label_max =  $_label_hauteur / 12 ;
+       $_label_pos = [ [], [] ] ;
+       $_label_init = 1 ;
+    }
+
+    # on calcule la position du label dans le bitmap
+    use integer ;
+    my $num = $y * $_label_max / $_label_hauteur ;
+    no integer ;
+
+    my $n = 0 ;                        # nombre d'iteration
+    my $l ;
+
+    # on prend le bon bitmap
+    if ($x < $self->{center_x}) {
+       $l = $_label_pos->[0] ;
+    } else {
+       $l = $_label_pos->[1] ;
+    }      
+    
+    # on parcours le bitmap pour trouver la bonne position
+    while (($num - $n) > 0) {
+       if (not $l->[$num]) {
+           last ;
+       } elsif (not $l->[$num + $n]) {
+           $num = $num + $n ;
+           last ;
+       } elsif (not $l->[$num - $n]) {
+           $num = $num - $n ;
+           last ;
+       } 
+       $n++ ;
+    }
+    
+    $l->[$num] = 1 ;           # on prend la position
+    
+    if ($num <= 0) {
+       return 0 ;
+    }
+    
+    # calcul de la position
+    $y = $num * $_label_hauteur / $_label_max ;
+
+    return $y ;
+}
+
+sub draw_labels
+{
+    my ($self) = @_ ;
+
+    $gd->fillToBorder(1, 
+                     1,
+                     $black,
+                     $white) ;
+
+    for my $l (@draw_label)
+    {
+       # translation 
+       my ($label, $x, $y, $level) = @{ $l } ;
+
+       next if ($level > $self->{max_label_level}) ;
+
+       next if (!$self->{display_other} and $label =~ /^other </) ;
+
+       my $dx = ($x - $self->{center_x})*($last_level - $level) + $x ;
+       my $dy = ($y - $self->{center_y})*($last_level - $level) + $y ;
+
+       $dy = $self->get_label_pos($dx, $dy) ;
+
+       next unless ($dy) ; # pas d'affichage si pas de place
+       
+       $gd->line( $x, $y,
+                  $dx, $dy,
+                  $black) ;
+
+       my $x2 ;
+       my $xp ;
+
+       if ($x < $self->{center_x}) {
+           $x2 =   $self->{center_x} 
+                 - $self->{rayon} * ($last_level + 3.7) ;
+           $xp = $x2 - (length($label) * $font_size + 2) ; # moins la taille de la police 
+       } else {
+           $x2 = $self->{center_x} + $self->{rayon} * ($last_level + 3.7) ;
+           $xp = $x2 + 10 ;
+       }
+
+       $gd->line($dx, $dy,
+                 $x2, $dy,
+                 $black) ;
+
+       $gd->string(GD::gdSmallFont, $xp, $dy - 5, $label, $black) ;
+    }
+}
+
+1;
+__END__
+
+package main ;
+
+my $top = new CCircle() ;
+
+my $chld1 = $top->add_part(50, 'test') ;
+my $chld2 = $top->add_part(20, 'test') ;
+my $chld3 = $top->add_part(10, 'test') ;
+my $chld4 = $top->add_part(20, 'test') ;
+
+
+$chld1->add_part(20, 'test1') ;
+$chld1->add_part(20, 'test1') ;
+
+$chld2->add_part(20, 'test1') ;
+$chld2->add_part(20, 'test1') ;
+
+$chld3->add_part(20, 'test1') ;
+my $chld5 = $chld3->add_part(20, 'test1') ;
+
+$chld5->add_part(50, 'test3') ;
+
+$top->finalize() ;
+$chld1->finalize() ;
+$chld2->finalize() ;
+$chld3->finalize() ;
+$chld4->finalize() ;
+$chld5->finalize() ;
+
+$top->draw_labels() ;
+# make sure we are writing to a binary stream
+binmode STDOUT;
+
+# Convert the image to PNG and print it on standard output
+print $CCircle::gd->png;
index 47c8e38a8ad3b1781133391a714dc65b624d05fc..8ac9df276f6ef5546431c1ff3aa648e988f5da2d 100644 (file)
@@ -19,44 +19,44 @@ if (navigator.appName == 'Konqueror') {
 </script>
 
 <ul id="menu">
- <li><a href="?">Main</a> </li>
- <li><a href="?action=client">Clients</a></li>
- <li><a href="?action=run_job">Jobs</a>
+ <li><a href="bweb.pl?">Main</a> </li>
+ <li><a href="bweb.pl?action=client">Clients</a></li>
+ <li><a href="bweb.pl?action=run_job">Jobs</a>
    <ul> 
-     <li><a href="?action=run_job">Defined Jobs</a>
-     <li><a href="?action=job">Last Jobs</a> </li>
-     <li><a href="?action=running">Running Jobs</a>
-     <li><a href="?action=next_job">Next Jobs</a> </li>
-     <li><a href="?action=restore" title="Launch brestore">Restore</a> </li>
+     <li><a href="bweb.pl?action=run_job">Defined Jobs</a>
+     <li><a href="bweb.pl?action=job">Last Jobs</a> </li>
+     <li><a href="bweb.pl?action=running">Running Jobs</a>
+     <li><a href="bweb.pl?action=next_job">Next Jobs</a> </li>
+     <li><a href="bweb.pl?action=restore" title="Launch brestore">Restore</a> </li>
    </ul>
  </li>
  <li style="padding: 0.25em 2em;">Medias
   <ul>
-     <li><a href="?action=pool">Pools</a> </li>
-     <li><a href="?action=location">Locations</a> </li>
-     <li><a href="?action=media">All Medias</a><hr></li>
-     <li><a href="?action=extern_media">Eject Medias</a> </li>
-     <li><a href="?action=intern_media">Load Medias</a> </li>
+     <li><a href="bweb.pl?action=pool">Pools</a> </li>
+     <li><a href="bweb.pl?action=location">Locations</a> </li>
+     <li><a href="bweb.pl?action=media">All Medias</a><hr></li>
+     <li><a href="bweb.pl?action=extern_media">Eject Medias</a> </li>
+     <li><a href="bweb.pl?action=intern_media">Load Medias</a> </li>
   </ul>
  </li>
 <TMPL_IF achs>
  <li style="padding: 0.25em 2em;">Autochanger
   <ul>
 <TMPL_LOOP achs>
-   <li><a href="?action=ach_view;ach=<TMPL_VAR name>"><TMPL_VAR name></a></li>
+   <li><a href="bweb.pl?action=ach_view;ach=<TMPL_VAR name>"><TMPL_VAR name></a></li>
 </TMPL_LOOP>
   </ul>
  </li>
 </TMPL_IF> 
- <li><a href="?action=graph"> Statistics </a></li>
- <li> <a href="?action=view_conf"> Configuration </a> </li>
- <li> <a href="?action=about"> About </a> </li>
+ <li><a href="bweb.pl?action=graph"> Statistics </a></li>
+ <li> <a href="bweb.pl?action=view_conf"> Configuration </a> </li>
+ <li> <a href="bweb.pl?action=about"> About </a> </li>
  <li style="padding: 0.25em 2em;float: right;">&nbsp;Logged as <TMPL_VAR NAME=loginname> </li>
  <li style="float: right;white-space: nowrap;">
 <input type="image" class="button" title="search media" onclick="search_media();" src="/bweb/tape.png"><input type="image" title="search client" onclick="search_client();" src="/bweb/client.png">&nbsp;<input class='formulaire' style="margin: 0 2px 0 2px; padding: 0 0 0 0;" id='searchbox' type='text' size='8' value="search..." onclick="this.value='';" title="search media or client"></li>
 </ul>
 
-<form name="search" action="?" method='GET'>
+<form name="search" action="bweb.pl?" method='GET'>
  <input type="hidden" name="action" value="">
  <input type="hidden" name="re_media" value="">
  <input type="hidden" name="re_client" value="">
index b7c6f1774c24f95ea9c200acb8063299421ba729..3e7fe994fe87d26d389c65fac18214153f766095 100644 (file)
@@ -9,34 +9,37 @@
  
      <tr><td>DBI :</td>     
          <td> 
-          <input class="formulaire" type='text' value='<TMPL_VAR NAME=dbi>' size='64' name='dbi'> 
+          <input class="formulaire" type='text' value='<TMPL_VAR dbi>' size='64' name='dbi'> 
          </td>
      </tr>
      <tr><td>user :</td> 
-         <td> <input class="formulaire" type='text' value='<TMPL_VAR NAME=user>' name='user'>
+         <td> <input class="formulaire" type='text' value='<TMPL_VAR user>' name='user'>
          </td>
      </tr>
      <tr><td>password :</td> 
-         <td> <input class="formulaire" type='password' value='<TMPL_VAR NAME=password>' name='password'> 
+         <td> <input class="formulaire" type='password' value='<TMPL_VAR password>' name='password'> 
          </td></tr>
 
      <tr>  <td><b>General Options</b></td>  <td/></tr>
 
      <tr><td>email_media :</td> 
-         <td> <input class="formulaire" type='text' value='<TMPL_VAR NAME=email_media>' name='email_media'> 
+         <td> <input class="formulaire" type='text' value='<TMPL_VAR email_media>' name='email_media'> 
          </td></tr>
          </td></tr>
 
      <tr>  <td><b>Bweb Configuration</b></td>  <td/></tr>
 
      <tr><td>graph_font :</td> 
-         <td> <input class="formulaire" type='text' value='<TMPL_VAR NAME=graph_font>' size='64' name='graph_font'> 
+         <td> <input class="formulaire" type='text' value='<TMPL_VAR graph_font>' size='64' name='graph_font'> 
          </td></tr>
      <tr><td>template_dir :</td> 
-         <td> <input class="formulaire" type='text' value='<TMPL_VAR NAME=template_dir>' size='64' name='template_dir'> 
+         <td> <input class="formulaire" type='text' value='<TMPL_VAR template_dir>' size='64' name='template_dir'> 
+         </td></tr>
+     <tr><td>fv_write_path :</td> 
+         <td> <input class="formulaire" title="This folder must be writable by apache user and must be accessible on /bweb/fv" type='text' value='<TMPL_VAR fv_write_path>' size='64' name='fv_write_path'> 
          </td></tr>
      <tr><td>bconsole :</td> 
-         <td> <input class="formulaire" type='text' value='<TMPL_VAR NAME=bconsole>' size='64' name='bconsole'> 
+         <td> <input class="formulaire" type='text' value='<TMPL_VAR bconsole>' size='64' name='bconsole'> 
          </td></tr>
      <tr><td>debug :</td> 
          <td> <input class="formulaire" type='checkbox' name='debug'> 
index a55cbe1d4492ff0c0028f40f25374e855f529a74..3e778c4cb5d6041f66eb96cf589af73641183af8 100644 (file)
@@ -13,6 +13,7 @@
     <tr>  <td><b>Bweb Configuration</b></td>  <td/></tr>
     <tr><td title="/path/to/your/template_dir">template_dir :</td> <td> <TMPL_VAR template_dir> </td></tr>
     <tr><td title="/path/to/a/font.ttf">graph_font :</td> <td> <TMPL_VAR graph_font> </td></tr>
+    <tr><td title="This folder must be writable by apache user and must be accessible on /bweb/fv">fv_write_path :</td> <td> <TMPL_VAR fv_write_path> </td></tr>
     <tr><td title="/path/to/bconsole -n -c /path/to/bconsole.conf">bconsole :</td> <td> <TMPL_VAR bconsole> </td></tr>
     <tr><td>debug :</td> <td> <TMPL_VAR debug> </td></tr>
     <TMPL_IF achs>
index 0c2f29487ef00fa8c817e2c11646ef8459b5fac1..b0534e1083863e0c9269c71bd12ce17397768761 100644 (file)
@@ -4,7 +4,7 @@
  <div class="bodydiv">
  <table id='id0'></table>
  <table><td>
- <form action='?'>
+ <form action='bweb.pl?'>
   <input type='hidden' name='jobid' value='<TMPL_VAR jobid>'>
   <label>
   <input type="image" name='action' value='delete' title='delete this job'
@@ -13,7 +13,7 @@
   </label>
  </form>
  </td><td>
- <form action='?'>
+ <form action='bweb.pl?'>
   <TMPL_LOOP volumes>
    <input type='hidden' name='media' value='<TMPL_VAR VolumeName>'>
   </TMPL_LOOP>   
@@ -24,7 +24,7 @@
  </form>
  </td>
  <td>
- <form action='?'>
+ <form action='bweb.pl?'>
   <input type='hidden' name='client' value='<TMPL_VAR Client>'>
   <label>
   <input type="image" name='action' value='job' title='view <TMPL_VAR Client> jobs' src='/bweb/zoom.png'>View jobs
@@ -32,7 +32,7 @@
  </form>
  </td>
  <td>
- <form action='?'>
+ <form action='bweb.pl?'>
   <input type='hidden' name='age' value='2678400'>
   <input type='hidden' name='client' value='<TMPL_VAR Client>'>
   <input type='hidden' name='jobname' value='<TMPL_VAR jobname>'>
@@ -43,7 +43,7 @@
  </form>
  </td>
  <td>
- <form action='?'>
+ <form action='bweb.pl?'>
   <input type='hidden' name='fileset' value='<TMPL_VAR FileSet>'>
   <label>
   <input type="image" name='action' value='fileset_view' title='view fileset'
   </label>
  </form>
  </td>
+<!-- Remove this to enable fileview
+ <td>
+ <form action='bfileview.pl?'>
+  <input type='hidden' name='jobid' value='<TMPL_VAR jobid>'>
+  <input type='hidden' name='where' value='/'>
+  <label>
+  <input type="image" name='action' value='bfileview' title='view file usage'
+   src='/bweb/colorscm.png'> View file usage
+  </label>
+ </form>
+ </td>
+-->
  </table>
 </div>
 
@@ -114,4 +126,4 @@ nrsTable.setup(
 }
 );
 
-</script>
\ No newline at end of file
+</script>
diff --git a/gui/bweb/tpl/fv_file_attribs.tpl b/gui/bweb/tpl/fv_file_attribs.tpl
new file mode 100644 (file)
index 0000000..bb4dd24
--- /dev/null
@@ -0,0 +1,2 @@
+Filename : <TMPL_VAR filename><br/>
+Size     : <TMPL_VAR size><br/>
index dac62fdce27cdb84a7b152906a170934266adac3..2dc7416ca20cc30294e14638b6bd97627fdd95b4 100644 (file)
   </label>
   <label>
   <input type="image" name='action' title='Update from pool'
-    value='update_from_pool' src='/bweb/update.png'> Update
+    value='update_from_pool' src='/bweb/update.png'> Update from pool
   </label>
  </form>
  </td>