]> git.sur5r.net Git - bacula/bacula/commitdiff
bweb: Add sqlite support
authorEric Bollengier <eric@eb.homelinux.org>
Mon, 11 Apr 2011 14:48:06 +0000 (16:48 +0200)
committerEric Bollengier <eric@eb.homelinux.org>
Mon, 11 Apr 2011 14:48:06 +0000 (16:48 +0200)
25 files changed:
gui/bweb/INSTALL
gui/bweb/cgi/bfileview.pl
gui/bweb/cgi/bgraph.pl
gui/bweb/cgi/btime.pl
gui/bweb/cgi/bweb.pl
gui/bweb/html/bweb.js
gui/bweb/lib/Bweb.pm
gui/bweb/lib/GTime.pm
gui/bweb/script/bweb-mysql.sql
gui/bweb/script/bweb-postgresql.sql
gui/bweb/script/httpd.conf
gui/bweb/script/regress.pl
gui/bweb/script/tpl_generate.pl
gui/bweb/tpl/ach_content.tpl
gui/bweb/tpl/add_media.tpl
gui/bweb/tpl/begin.tpl
gui/bweb/tpl/display_job.tpl
gui/bweb/tpl/display_job_zoom.tpl
gui/bweb/tpl/display_media.tpl
gui/bweb/tpl/display_media_zoom.tpl
gui/bweb/tpl/help_extern_compute.tpl
gui/bweb/tpl/help_intern_compute.tpl
gui/bweb/tpl/run_job_mod.tpl
gui/bweb/tpl/running_job.tpl
gui/bweb/tpl/scheduled_job.tpl

index 7c1ae65f13a98172c865ce3ff6f6af5b815e195b..bd7124a4dafadf7e3753bf28e4388017738fdcaa 100644 (file)
@@ -106,7 +106,9 @@ Click: Main -- you should see the charts
 
 ################ FILE COPY (Full Apache methode) ###############
  # you must get bweb svn files
 
 ################ FILE COPY (Full Apache methode) ###############
  # you must get bweb svn files
- svn checkout https://bacula.svn.sourceforge.net/svnroot/bacula/trunk/gui/bweb bweb
+ git clone git://bacula.git.sourceforge.net/gitroot/bacula/bacula
+ git checkout origin/master
+ cd bacula/gui/
 
  # or get them from the released tar files or from the apt or rpms.
 
 
  # or get them from the released tar files or from the apt or rpms.
 
@@ -145,8 +147,8 @@ Click: Main -- you should see the charts
 
  # done !
 
 
  # done !
 
- WARNING : Your www-data (or wwwrun on SuSE) user must be able to execute bconsole and able 
-           to read the bconsole.conf file!
+ WARNING : Your www-data (or wwwrun on SuSE) user must be able to execute
+           bconsole and able to read the bconsole.conf file!
            You can create an bconsole group for that.
 
 ################ USE FRENCH/SPANISH VERSION ####################
            You can create an bconsole group for that.
 
 ################ USE FRENCH/SPANISH VERSION ####################
@@ -324,8 +326,8 @@ You MUST use brestore.pl -b or bresto.pl action=batch to initialize the
 database, and you CAN use bfileview.pl mode=batch jobid=xxx where=/ to compute
 tree size.
 
 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 -b after your 
-BackupCatalog job.
+At this time, it's a good idea to schedule brestore.pl -b or bresto.pl after
+your BackupCatalog job.
 
 Job {
   Name = "BackupCatalog"
 
 Job {
   Name = "BackupCatalog"
@@ -383,6 +385,7 @@ For postgresql, it will be done with bweb/script/bweb-postgresql.sql (already do
 It will do some basics things on a working bweb/brestore setup.
 
 1) Go to http://extjs.com and download their toolkit (use the 2.2 release)
 It will do some basics things on a working bweb/brestore setup.
 
 1) Go to http://extjs.com and download their toolkit (use the 2.2 release)
+   You can also get it from http://www.bacula.org/downloads/extjs-2.2.zip
 
 2) Install files in /bweb/ext web root 
  example on debian : 
 
 2) Install files in /bweb/ext web root 
  example on debian : 
@@ -390,15 +393,7 @@ It will do some basics things on a working bweb/brestore setup.
 
 3) Make sure that brestore cache tables are in your catalog (bweb-xxx.sql files)
 
 
 3) Make sure that brestore cache tables are in your catalog (bweb-xxx.sql files)
 
-4) Enable bresto.pl cgi. 
-  edit the bweb/cgi/bresto.pl script and change $bresto_enable=0; to $bresto_enable=1;
-  on the top of the file.
-
-5) Use the last Bweb.pm
-  If you are trying bresto in a working bweb/brestore setup, you must make sure that you use 
-  the last Bweb.pm git version.
-
-6) Go on http://you-director/bweb/bresto.html
+4) Go on http://you-director/bweb/bresto.html
 
 ################################################################
 
 
 ################################################################
 
index 23bd23016c77bdd40dcbcbe4fc8fb5364b858a53..08816c0932cb194f35a05fc130e8d2ab23c48505 100755 (executable)
@@ -67,7 +67,6 @@ if ($jobid and $batch eq 'batch') {
     exit 1;
 }
 
     exit 1;
 }
 
-print CGI::header('text/html');
 $bweb->display_begin();
 $bweb->display_job_zoom($jobid);
 
 $bweb->display_begin();
 $bweb->display_job_zoom($jobid);
 
index 7407322dba4a5c3925973299c55d9a6b020ac373..e75e7941952f94221f2a565e716a0bd1562fcb4f 100755 (executable)
@@ -6,7 +6,7 @@ use strict;
    Bweb - A Bacula web interface
    Bacula® - The Network Backup Solution
 
    Bweb - A Bacula web interface
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2010 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
 
    The main author of Bweb is Eric Bollengier.
    The main author of Bacula is Kern Sibbald, with contributions from
@@ -31,10 +31,6 @@ use strict;
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 
-=head1 VERSION
-
-    $Id$
-
 =cut
 
 use Bweb;
 =cut
 
 use Bweb;
@@ -148,9 +144,8 @@ if ($gtype eq 'balloon') {
     $b->set_legend_axis(%legend);
 
     my $all = $dbh->selectall_arrayref("
     $b->set_legend_axis(%legend);
 
     my $all = $dbh->selectall_arrayref("
-SELECT $bweb->{sql}->{SEC_TO_INT}(  $bweb->{sql}->{UNIX_TIMESTAMP}(EndTime)
-                                  - $bweb->{sql}->{UNIX_TIMESTAMP}(StartTime))
-         AS duration, $order, JobId, Job.Name
+SELECT $bweb->{sql}->{JOB_DURATION} AS duration,
+       $order, JobId, Job.Name
        
  FROM $jobt AS Job, Client $filter $groupf
 WHERE Job.ClientId = Client.ClientId
        
  FROM $jobt AS Job, Client $filter $groupf
 WHERE Job.ClientId = Client.ClientId
@@ -184,7 +179,7 @@ $limitq
     exit 0;
 }
 
     exit 0;
 }
 
-print CGI::header('image/png');
+$bweb->send_content_type(-type => 'image/png');
 
 sub get_graph
 {
 
 sub get_graph
 {
@@ -291,7 +286,7 @@ if ($graph eq 'job_size') {
 
     my $query = "
 SELECT 
 
     my $query = "
 SELECT 
-       UNIX_TIMESTAMP(Job.StartTime)  AS starttime,
+       $bweb->{sql}->{STARTTIME_SEC}  AS starttime,
        Client.Name                    AS clientname,
        Job.Name                       AS jobname,
        Job.JobBytes                   AS jobbytes,
        Client.Name                    AS clientname,
        Job.Name                       AS jobname,
        Job.JobBytes                   AS jobbytes,
@@ -330,7 +325,7 @@ if ($graph eq 'job_file') {
 
     my $query = "
 SELECT 
 
     my $query = "
 SELECT 
-       UNIX_TIMESTAMP(Job.StartTime)  AS starttime,
+       $bweb->{sql}->{STARTTIME_SEC}  AS starttime,
        Client.Name                    AS clientname,
        Job.Name                       AS jobname,
        Job.JobFiles                   AS jobfiles,
        Client.Name                    AS clientname,
        Job.Name                       AS jobname,
        Job.JobFiles                   AS jobfiles,
@@ -372,7 +367,7 @@ elsif ($graph eq 'file_histo' and $arg->{where}) {
     my $file = $dbh->quote(basename($arg->{where}));
 
     my $query = "
     my $file = $dbh->quote(basename($arg->{where}));
 
     my $query = "
-SELECT UNIX_TIMESTAMP(Job.StartTime)    AS starttime,
+SELECT $bweb->{sql}->{STARTTIME_SEC}  AS starttime,
        Client.Name                      AS client,
        Job.Name                         AS jobname,
        base64_decode_lstat(8,LStat)     AS lstat,
        Client.Name                      AS client,
        Job.Name                         AS jobname,
        base64_decode_lstat(8,LStat)     AS lstat,
@@ -423,7 +418,7 @@ elsif ($graph eq 'rep_histo' and $arg->{where}) {
     $dir = $dbh->quote($dir);
 
     my $query = "
     $dir = $dbh->quote($dir);
 
     my $query = "
-SELECT UNIX_TIMESTAMP(Job.StartTime) AS starttime,
+SELECT $bweb->{sql}->{STARTTIME_SEC}  AS starttime,
        Client.Name                   AS client,
        Job.Name                      AS jobname,
        brestore_pathvisibility.size  AS size,
        Client.Name                   AS client,
        Job.Name                      AS jobname,
        brestore_pathvisibility.size  AS size,
@@ -467,14 +462,11 @@ elsif ($graph eq 'job_rate') {
 
     my $query = "
 SELECT 
 
     my $query = "
 SELECT 
-       UNIX_TIMESTAMP(Job.StartTime)  AS starttime,
+       $bweb->{sql}->{STARTTIME_SEC}  AS starttime,
        Client.Name                    AS clientname,
        Job.Name                       AS jobname,
        Job.JobBytes /
        Client.Name                    AS clientname,
        Job.Name                       AS jobname,
        Job.JobBytes /
-       ($bweb->{sql}->{SEC_TO_INT}(
-                          $bweb->{sql}->{UNIX_TIMESTAMP}(EndTime)  
-                        - $bweb->{sql}->{UNIX_TIMESTAMP}(StartTime)) + 0.01) 
-         AS rate,
+               ($bweb->{sql}->{JOB_DURATION} + 0.01) AS rate,
        Job.Level                      AS joblevel
 
 FROM $jobt AS Job, FileSet, Client $filter $groupf
        Job.Level                      AS joblevel
 
 FROM $jobt AS Job, FileSet, Client $filter $groupf
@@ -513,12 +505,10 @@ elsif ($graph eq 'job_duration') {
 
     my $query = "
 SELECT 
 
     my $query = "
 SELECT 
-       UNIX_TIMESTAMP(Job.StartTime)       AS starttime,
-       Client.Name                         AS clientname,
-       Job.Name                            AS jobname,
-  $bweb->{sql}->{SEC_TO_INT}(  $bweb->{sql}->{UNIX_TIMESTAMP}(EndTime)  
-                             - $bweb->{sql}->{UNIX_TIMESTAMP}(StartTime)) 
-         AS duration,
+       $bweb->{sql}->{STARTTIME_SEC}  AS starttime,
+       Client.Name                    AS clientname,
+       Job.Name                       AS jobname,
+       $bweb->{sql}->{JOB_DURATION}   AS duration,
        Job.Level                      AS joblevel
 
 FROM $jobt AS Job, FileSet, Client $filter $groupf
        Job.Level                      AS joblevel
 
 FROM $jobt AS Job, FileSet, Client $filter $groupf
@@ -574,12 +564,16 @@ $limitq
     if ($t eq 'sum' or $t eq 'avg') {
        push @arg, ('y_number_format' => \&Bweb::human_size);
     }
     if ($t eq 'sum' or $t eq 'avg') {
        push @arg, ('y_number_format' => \&Bweb::human_size);
     }
-    
-    my $stime = $bweb->{sql}->{"STARTTIME_$d"};
+    my $stime;
+    if ($per_t) {
+        $stime = $bweb->{sql}->{"STARTTIME_$d"};
+    } else {
+        $stime = $bweb->{sql}->{STARTTIME_SEC};
+    }
 
     my $query = "
 SELECT
 
     my $query = "
 SELECT
-     " . ($per_t?"":"UNIX_TIMESTAMP") . "($stime) AS A,
+     $stime AS A,
      $t(JobBytes)                  AS nb
 FROM $jobt AS Job, FileSet, Client $filter $groupf
 WHERE Job.ClientId = Client.ClientId
      $t(JobBytes)                  AS nb
 FROM $jobt AS Job, FileSet, Client $filter $groupf
 WHERE Job.ClientId = Client.ClientId
@@ -593,7 +587,6 @@ WHERE Job.ClientId = Client.ClientId
   $groupq
 $limit
 ";
   $groupq
 $limit
 ";
-
     print STDERR $query  if ($debug);
 
     my $obj = get_graph('title' => "Job $t : $arg->{jclients}/$arg->{jjobnames}",
     print STDERR $query  if ($debug);
 
     my $obj = get_graph('title' => "Job $t : $arg->{jclients}/$arg->{jjobnames}",
index f264828f79834b8f22e929b6f18d010bbb311101..479a8bf5b797bb08a82c75d999694a5506759f1a 100755 (executable)
@@ -39,7 +39,6 @@ use strict;
 use GTime;
 use Getopt::Long ;
 use Bweb;
 use GTime;
 use Getopt::Long ;
 use Bweb;
-use Time::ParseDate qw/parsedate/;
 use POSIX qw/strftime/;
 use CGI;
 
 use POSIX qw/strftime/;
 use CGI;
 
@@ -48,7 +47,6 @@ $conf->load();
 
 my $bweb = new Bweb(info => $conf);
 
 
 my $bweb = new Bweb(info => $conf);
 
-print CGI::header('text/html');
 $bweb->display_begin();
 $bweb->can_do('r_view_stat');
 
 $bweb->display_begin();
 $bweb->can_do('r_view_stat');
 
@@ -216,25 +214,25 @@ foreach my $elt (@$all)
 #              l => $elt->[2],
                type  => "waiting",
                begin => $begin,
 #              l => $elt->[2],
                type  => "waiting",
                begin => $begin,
-               end   => parsedate($elt->[1]) - $t,
+               end   => $elt->[1] - $t,
            };
 
            push @$data, {
 #              l => $elt->[2],
                type  => "despool",
            };
 
            push @$data, {
 #              l => $elt->[2],
                type  => "despool",
-               begin => parsedate($elt->[1]) - $t,
+               begin => $elt->[1] - $t,
                end   => $elt->[1],
            };
 
            push @{$write->{$drive}}, { # display only write time
                type  => "despool",
                end   => $elt->[1],
            };
 
            push @{$write->{$drive}}, { # display only write time
                type  => "despool",
-               begin => parsedate($elt->[1]) - $t,
+               begin => $elt->[1] - $t,
                end   => $elt->[1],
            };
 
            push @{$pool->{"$drive: $elt->[4]"}}, {
                type  => "despool",
                end   => $elt->[1],
            };
 
            push @{$pool->{"$drive: $elt->[4]"}}, {
                type  => "despool",
-               begin => parsedate($elt->[1]) - $t,
+               begin => $elt->[1] - $t,
                end   => $elt->[1],
            };
        } else {
                end   => $elt->[1],
            };
        } else {
index 251011151697af6d93fa9be256c7ea15ec82db49..08a652e7dc04b5603abaf5306fd2b5f40fc3d8f2 100755 (executable)
@@ -41,27 +41,20 @@ my $client_re = qr/^([\w\d\.-]+)$/;
 
 my $action = CGI::param('action') || 'begin';
 
 
 my $action = CGI::param('action') || 'begin';
 
-if ($action eq 'restore') {
-    print CGI::header('text/brestore');        # specialy to run brestore.pl
-
-} else {
-    print CGI::header('text/html');
-}
-
 # loading config file
 my $conf = new Bweb::Config(config_file => $Bweb::config_file);
 $conf->load();
 
 my $bweb = new Bweb(info => $conf);
 # loading config file
 my $conf = new Bweb::Config(config_file => $Bweb::config_file);
 $conf->load();
 
 my $bweb = new Bweb(info => $conf);
+my $arg = $bweb->get_form('jobid', 'limit', 'offset', 'age', 'new_dir');
 
 # just send data with text/brestore content
 if ($action eq 'restore') {
 
 # just send data with text/brestore content
 if ($action eq 'restore') {
+    print CGI::header('text/brestore');        # specialy to run brestore.pl
     $bweb->restore();
     exit 0;
 }
 
     $bweb->restore();
     exit 0;
 }
 
-my $arg = $bweb->get_form('jobid', 'limit', 'offset', 'age');
-
 $bweb->display_begin();
 
 # if no configuration, we send edit_conf
 $bweb->display_begin();
 
 # if no configuration, we send edit_conf
index de8f5b615c8cbdd899d84e78777ba56663e94e2d..0bcd098148d23967f773f74a51f575e66a5d8f5f 100644 (file)
@@ -1,5 +1,5 @@
 // Bweb - A Bacula web interface
 // Bweb - A Bacula web interface
-// Bacula® - The Network Backup Solution
+// Bacula® - The Network Backup Solution
 //
 // Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
 //
 //
 // Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
 //
@@ -22,7 +22,7 @@
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 // 02110-1301, USA.
 //
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 // 02110-1301, USA.
 //
-// Bacula® is a registered trademark of Kern Sibbald.
+// Bacula® is a registered trademark of Kern Sibbald.
 // The licensor of Bacula is the Free Software Foundation Europe
 // (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zurich,
 // Switzerland, email:ftf@fsfeurope.org.
 // The licensor of Bacula is the Free Software Foundation Europe
 // (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zurich,
 // Switzerland, email:ftf@fsfeurope.org.
@@ -77,6 +77,7 @@ var joblevelname = {
  'F': 'Full',
  'I': 'Incremental',
  'D': 'Differential',
  'F': 'Full',
  'I': 'Incremental',
  'D': 'Differential',
+ 'B': 'Base'
 };
 
 
 };
 
 
@@ -131,24 +132,84 @@ function human_sec(val)
    val /= 60;                  // sec -> min
    
    if ((val / 60) <= 1) {
    val /= 60;                  // sec -> min
    
    if ((val / 60) <= 1) {
-      return val.toFixed(0) + ' mins';
+      return val.toFixed(0) + ' min' + add_s(val) ;
    }
 
    val /= 60;                  // min -> hour
 
    if ((val / 24) <= 1) { 
    }
 
    val /= 60;                  // min -> hour
 
    if ((val / 24) <= 1) { 
-      return val.toFixed(0) + ' hours';
+      return val.toFixed(0) + ' hour' + add_s(val) ;
    }
 
    val /= 24;                   // hour -> day
 
    if ((val / 365) < 2) { 
    }
 
    val /= 24;                   // hour -> day
 
    if ((val / 365) < 2) { 
-      return val.toFixed(0) + ' days';
+      return val.toFixed(0) + ' day' + add_s(val);
    }
 
    val /= 365;
 
    }
 
    val /= 365;
 
-   return val.toFixed(0) + ' years';
+   return val.toFixed(0) + ' year' + add_s(val);
+}
+
+function add_s(val)
+{
+    if (val >= 2) {
+        return "s ";
+    } else {
+        return " ";
+    }
+}
+
+function human_sec2(val)
+{
+   if (!val) {
+      val = 0;
+   }
+   val = parseInt(val);
+   if (val < 60) {
+       return val.toFixed(0) + ' sec' + add_s(val);
+   }
+
+   val /= 60;                  // sec -> min
+   if ((val / 60) <= 1) {
+       return val.toFixed(0) + ' min' + add_s(val);
+   }
+
+   var prev = val % 60;
+   val /= 60;                  // min -> hour
+
+   if ((val / 24) <= 1) { 
+       return val.toFixed(0) + ' hour' + add_s(val) 
+           + prev.toFixed(0) + ' min' + add_s(prev);
+   }
+   prev = val % 24;
+   val /= 24;                   // hour -> day
+
+   if ((val / 365) < 2) { 
+       return val.toFixed(0) + ' day' + add_s(val) 
+           + prev.toFixed(0) + ' hour' + add_s(prev);
+   }
+
+   prev = val % 365;
+   val /= 365;
+
+    return val.toFixed(0) + ' year' + add_s(val) 
+        + prev.toFixed(0) + ' day' + add_s(prev);
+}
+
+function human_duration(val)
+{
+    if (!val) {
+        val = 0;
+    }
+    val = parseInt(val);
+    var sec = val % 60;
+    val = val / 60;
+    var min = val % 60;
+    val = val / 60;
+    return pad(val.toFixed(0)) + ':' + pad(min.toFixed(0)) + ':' + pad(sec.toFixed(0));
 }
 
 
 }
 
 
@@ -308,6 +369,18 @@ function percent_usage(value, parent)
    return parent;
 }
 
    return parent;
 }
 
+function pad(n){return n<10 ? '0'+n : n}
+
+function timestamp_to_iso(ts)
+{
+    if(ts < 1000000000000){
+        ts=(ts*1000);
+    }
+    var datum = new Date(ts);
+    
+    return datum.getFullYear() + '-' + pad(datum.getMonth()+1) + '-' + pad(datum.getDay()+1) + ' ' + pad(datum.getHours()) + ':' + pad(datum.getMinutes()) + ':' + pad(datum.getSeconds());
+}
+
 function bweb_get_job_img(status, errors, type)
 {
   var ret;
 function bweb_get_job_img(status, errors, type)
 {
   var ret;
index 7e5178163673b3b815f9698df37fcfb3503b5211..174d3e434b7c71b6f576fc8a4c0b71488328645d 100644 (file)
@@ -6,7 +6,7 @@ use strict;
    Bweb - A Bacula web interface
    Bacula® - The Network Backup Solution
 
    Bweb - A Bacula web interface
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2006-2010 Free Software Foundation Europe e.V.
+   Copyright (C) 2006-2011 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
 
    The main author of Bweb is Eric Bollengier.
    The main author of Bacula is Kern Sibbald, with contributions from
@@ -68,6 +68,7 @@ sub new
     my ($class, %arg) = @_;
     my $self = bless {
         name => undef,
     my ($class, %arg) = @_;
     my $self = bless {
         name => undef,
+        info => undef,
     }, $class;
 
     map { $self->{lc($_)} = $arg{$_} } keys %arg ;
     }, $class;
 
     map { $self->{lc($_)} = $arg{$_} } keys %arg ;
@@ -88,6 +89,13 @@ sub debug
     }
 }
 
     }
 }
 
+sub ldebug
+{
+    open(FP, ">>/tmp/log");
+    print FP Data::Dumper::Dumper(\@_);
+    close(FP);
+}
+
 sub fdebug
 {
     my ($self, $what) = @_;
 sub fdebug
 {
     my ($self, $what) = @_;
@@ -123,6 +131,22 @@ sub error
     return 0;
 }
 
     return 0;
 }
 
+# send content type the first time, see man CGI to overwrite
+# values
+my $send_content_type_done=0;
+sub send_content_type
+{
+    my ($self, %arg) = @_;
+    my $info = $self->{info} || $self;
+
+    if (!$send_content_type_done) { # display it once
+        $send_content_type_done = 1;
+
+        %arg = (-type => 'text/html', %arg);
+        print CGI::header(%arg);
+    }
+}
+
 =head1 FUNCTION
 
     display - display an html page with HTML::Template
 =head1 FUNCTION
 
     display - display an html page with HTML::Template
@@ -138,6 +162,8 @@ sub error
     hash keys are not sensitive. See HTML::Template for more
     explanations about the hash ref. (it's can be quiet hard to understand) 
 
     hash keys are not sensitive. See HTML::Template for more
     explanations about the hash ref. (it's can be quiet hard to understand) 
 
+    It uses the following variables: template_dir lang director
+
 =head2 EXAMPLE
 
     $ref = { name => 'me', age => 26 };
 =head2 EXAMPLE
 
     $ref = { name => 'me', age => 26 };
@@ -148,8 +174,10 @@ sub error
 sub display
 {
     my ($self, $hash, $tpl) = @_ ;
 sub display
 {
     my ($self, $hash, $tpl) = @_ ;
-    my $dir = $self->{template_dir} || $template_dir;
-    my $lang = $self->{lang} || 'en';
+    my $info = $self->{info} || $self;
+
+    my $dir = $info->{template_dir} || $template_dir;
+    my $lang = $self->{current_lang} || $info->{lang} || 'en';
     my $template = HTML::Template->new(filename => $tpl,
                                        path =>["$dir/$lang",
                                                "$dir/$lang/tpl",
     my $template = HTML::Template->new(filename => $tpl,
                                        path =>["$dir/$lang",
                                                "$dir/$lang/tpl",
@@ -172,6 +200,7 @@ sub display
     $template->param('loginname', CGI::remote_user());
 
     $template->param($hash);
     $template->param('loginname', CGI::remote_user());
 
     $template->param($hash);
+    $self->send_content_type();
     print $template->output();
 }
 1;
     print $template->output();
 }
 1;
@@ -213,7 +242,7 @@ use CGI;
 
 =cut
 
 
 =cut
 
-our %k_re = ( dbi      => qr/^(dbi:(Pg|mysql):(?:\w+=[\w\d\.-]+;?)+)$/i,
+our %k_re = ( dbi      => qr/^(dbi:(Pg|mysql|SQLite):(?:\w+=[\w\d\.\/\-]+;?)+)$/i,
               user     => qr/^([\w\d\.-]+)$/i,
               password => qr/^(.*)$/,
               fv_write_path => qr!^([/\w\d\.-]*)$!,
               user     => qr/^([\w\d\.-]+)$/i,
               password => qr/^(.*)$/,
               fv_write_path => qr!^([/\w\d\.-]*)$!,
@@ -223,14 +252,19 @@ our %k_re = ( dbi      => qr/^(dbi:(Pg|mysql):(?:\w+=[\w\d\.-]+;?)+)$/i,
               email_media => qr/^([\w\d\.-]+@[\d\w\.-]+)$/,
               graph_font  => qr!^([/\w\d\.-]+.ttf)?$!,
               bconsole    => qr!^(.+)?$!,
               email_media => qr/^([\w\d\.-]+@[\d\w\.-]+)$/,
               graph_font  => qr!^([/\w\d\.-]+.ttf)?$!,
               bconsole    => qr!^(.+)?$!,
-              syslog_file => qr!^(.+)?$!,
-              log_dir     => qr!^(.+)?$!,
               wiki_url    => qr!(.*)$!,
               stat_job_table => qr!^(\w*)$!,
               display_log_time => qr!^(on)?$!,
               enable_security => qr/^(on)?$/,
               enable_security_acl => qr/^(on)?$/,
               default_age => qr/^((?:\d+(?:[ywdhms]\s*?)?)+)\s*$/,
               wiki_url    => qr!(.*)$!,
               stat_job_table => qr!^(\w*)$!,
               display_log_time => qr!^(on)?$!,
               enable_security => qr/^(on)?$/,
               enable_security_acl => qr/^(on)?$/,
               default_age => qr/^((?:\d+(?:[ywdhms]\s*?)?)+)\s*$/,
+              name => qr/^([\w\s\d\.\-]+)$/,
+              dir_ver => qr/^(\d+(\.\d+)?)$/,
+              # can be subitem
+              subconf => qr/^$/,
+              achs => qr/^$/,
+              ach_list => qr/^$/,
+              url => qr!^(https?://[\w\.\d/@?;]+)$!,
               );
 
 =head1 FUNCTION
               );
 
 =head1 FUNCTION
@@ -265,46 +299,15 @@ sub load
     use strict;
 
     if ($f and $@) {
     use strict;
 
     if ($f and $@) {
-        $self->load_old();
-        $self->save();
-        return $self->error("If you update from an old bweb install, your must reload this page and if it's fail again, you have to configure bweb again...") ;
+        return $self->error("Something is wrong with your configuration file...") ;
     }
 
     }
 
-    # set default values
-    $self->{default_age} = '7d';
-
+    # keep a backup of the original config
     foreach my $k (keys %$VAR1) {
     foreach my $k (keys %$VAR1) {
-        $self->{$k} = $VAR1->{$k};
-    }
-
-    return 1;
-}
-
-=head1 FUNCTION
-
-    load_old - load old configuration format
-
-=cut
-
-sub load_old
-{
-    my ($self) = @_ ;
-
-    unless (open(FP, $self->{config_file}))
-    {
-        return $self->error("$self->{config_file} : $!");
-    }
-
-    while (my $line = <FP>)
-    {
-        chomp($line);
-        my ($k, $v) = split(/\s*=\s*/, $line, 2);
-        if ($k_re{$k}) {
-            $self->{$k} = $v;
+        if (exists $k_re{$k} and defined $VAR1->{$k}) {
+            $self->{main_conf}->{$k} = $VAR1->{$k};
         }
     }
         }
     }
-
-    close(FP);
     return 1;
 }
 
     return 1;
 }
 
@@ -972,10 +975,7 @@ SELECT Media.VolumeName  AS volumename,
        Media.Slot        AS slot,
        Media.InChanger   AS inchanger,
        Pool.Name         AS name,
        Media.Slot        AS slot,
        Media.InChanger   AS inchanger,
        Pool.Name         AS name,
-       $bweb->{sql}->{FROM_UNIXTIME}(
-          $bweb->{sql}->{UNIX_TIMESTAMP}(Media.LastWritten) 
-        + $bweb->{sql}->{TO_SEC}(Media.VolRetention)
-       ) AS expire
+       $self->{sql}->{MEDIA_EXPIRE} AS expire
 FROM Media 
  INNER JOIN Pool USING (PoolId) 
 
 FROM Media 
  INNER JOIN Pool USING (PoolId) 
 
@@ -1089,6 +1089,7 @@ sub new
         my $sel = $self->{name}?"=\"$self->{name}\"":'';
         my $b = $self->{bconsole};
         my $out = $b->send_cmd("show schedule$sel");
         my $sel = $self->{name}?"=\"$self->{name}\"":'';
         my $b = $self->{bconsole};
         my $out = $b->send_cmd("show schedule$sel");
+        $self->{show_output}=$out;
         $self->parse_scheds(split(/\r?\n/, $out));
         undef $self->{bconsole}; # useless now
     }
         $self->parse_scheds(split(/\r?\n/, $out));
         undef $self->{bconsole}; # useless now
     }
@@ -1296,7 +1297,10 @@ our %sql_func = (
               SEC_TO_INT => "SEC_TO_INT",
               SEC_TO_TIME => '',
               MATCH => " ~* ",
               SEC_TO_INT => "SEC_TO_INT",
               SEC_TO_TIME => '',
               MATCH => " ~* ",
-              STARTTIME_SEC  => " date_trunc('sec', Job.StartTime) ",
+              MEDIA_EXPIRE => "date_part('epoch', Media.LastWritten) + Media.VolRetention",
+              ENDTIME_SEC => " date_part('epoch', EndTime) ",
+              JOB_DURATION => " date_part('epoch', EndTime) -  date_part('epoch', StartTime) ",
+              STARTTIME_SEC  => " date_part('epoch', Job.StartTime) ",
               STARTTIME_DAY  => " date_trunc('day', Job.StartTime) ",
               STARTTIME_HOUR => " date_trunc('hour', Job.StartTime) ",
               STARTTIME_MONTH  => " date_trunc('month', Job.StartTime) ",
               STARTTIME_DAY  => " date_trunc('day', Job.StartTime) ",
               STARTTIME_HOUR => " date_trunc('hour', Job.StartTime) ",
               STARTTIME_MONTH  => " date_trunc('month', Job.StartTime) ",
@@ -1318,7 +1322,10 @@ our %sql_func = (
               TO_SEC => '',
               SEC_TO_TIME => 'SEC_TO_TIME',
               MATCH => " REGEXP ",
               TO_SEC => '',
               SEC_TO_TIME => 'SEC_TO_TIME',
               MATCH => " REGEXP ",
-              STARTTIME_SEC => " DATE_FORMAT(Job.StartTime, '%Y-%m-%d %T') ",
+              MEDIA_EXPIRE => 'UNIX_TIMESTAMP(Media.LastWritten)+Media.VolRetention',
+              ENDTIME_SEC => " UNIX_TIMESTAMP(EndTime) ",
+              JOB_DURATION => " UNIX_TIMESTAMP(EndTime) - UNIX_TIMESTAMP(StartTime) ",
+              STARTTIME_SEC => " UNIX_TIMESTAMP(Job.StartTime) ",
               STARTTIME_DAY  => " DATE_FORMAT(Job.StartTime, '%Y-%m-%d') ",
               STARTTIME_HOUR => " DATE_FORMAT(Job.StartTime, '%Y-%m-%d %H') ",
               STARTTIME_MONTH => " DATE_FORMAT(Job.StartTime, '%Y-%m') ",
               STARTTIME_DAY  => " DATE_FORMAT(Job.StartTime, '%Y-%m-%d') ",
               STARTTIME_HOUR => " DATE_FORMAT(Job.StartTime, '%Y-%m-%d %H') ",
               STARTTIME_MONTH => " DATE_FORMAT(Job.StartTime, '%Y-%m') ",
@@ -1335,6 +1342,31 @@ our %sql_func = (
               CONCAT_SEP => " SEPARATOR '' ",
               NOW => "NOW()",
           },
               CONCAT_SEP => " SEPARATOR '' ",
               NOW => "NOW()",
           },
+          SQLite => {
+              UNIX_TIMESTAMP => '',
+              FROM_UNIXTIME => '',
+              SEC_TO_INT => '',
+              TO_SEC => '',
+              SEC_TO_TIME => '',
+              MATCH => " REGEXP ",
+              MEDIA_EXPIRE => "strftime('%s', Media.LastWritten) + Media.VolRetention",
+              ENDTIME_SEC => " strftime('%s', EndTime) ",
+              STARTTIME_SEC =>  " strftime('%s', Job.StartTime) ",
+              JOB_DURATION => " strftime('%s', EndTime) -  strftime('%s', StartTime)",
+
+              STARTTIME_DAY  => " strftime('%Y-%m-%d', Job.StartTime) ",
+              STARTTIME_HOUR => " strftime('%Y-%m-%d %H', Job.StartTime) ",
+              STARTTIME_MONTH => " strftime('%Y-%m', Job.StartTime) ",
+              STARTTIME_WEEK => " strftime('%Y-%W', Job.StartTime) ",
+              STARTTIME_PHOUR=> " strftime('%H', Job.StartTime) ",
+              STARTTIME_PDAY => " strftime('%d', Job.StartTime) ",
+              STARTTIME_PMONTH => " strftime('%m', Job.StartTime) ",
+              STARTTIME_PWEEK => " strftime('%W', Job.StartTime) ",
+              DB_SIZE => " SELECT 0 ",
+              CAT_POOL_TYPE => " MediaType || Pool.Name ",
+              CONCAT_SEP => "",
+              NOW => "strftime('%Y-%m-%d %H:%M:%S', 'now')",
+          },
          );
 
 use Exporter 'import';
          );
 
 use Exporter 'import';
@@ -1349,6 +1381,18 @@ sub dbh_is_mysql
     return $self->{info}->{dbi} =~ /dbi:mysql/i;
 }
 
     return $self->{info}->{dbi} =~ /dbi:mysql/i;
 }
 
+sub dbh_is_sqlite
+{
+    my ($self) = @_;
+    return $self->{info}->{dbi} =~ /dbi:sqlite/i;
+}
+
+sub dbh_is_pg
+{
+    my ($self) = @_;
+    return $self->{info}->{dbi} =~ /dbi:pg/i;
+}
+
 sub dbh_disconnect
 {
     my ($self) = @_;
 sub dbh_disconnect
 {
     my ($self) = @_;
@@ -1392,6 +1436,16 @@ sub dbh_do
     return $self->{dbh}->do($query);
 }
 
     return $self->{dbh}->do($query);
 }
 
+# For sqlite, convert UNIX_TIMESTAMP(a) to strftime('%s', a)
+sub dbh_convert
+{
+    my ($self, $query) = @_ ; 
+    if ($self->dbh_is_sqlite()) {
+        $query =~ s/UNIX_TIMESTAMP\(([^)]+)\)/strftime('%s', $1)/gs;
+    }
+    return $query;
+}
+
 sub dbh_selectall_hashref
 {
     my ($self, $query, $join) = @_;
 sub dbh_selectall_hashref
 {
     my ($self, $query, $join) = @_;
@@ -1558,14 +1612,14 @@ sub connect_db
                                     $self->{info}->{user},
                                     $self->{info}->{password});
 
                                     $self->{info}->{user},
                                     $self->{info}->{password});
 
-        $self->error("Can't connect to your database:\n$DBI::errstr\n")
+        return $self->error("Can't connect to your database:\n$DBI::errstr\n")
             unless ($self->{dbh});
 
         $self->{dbh}->{FetchHashKeyName} = 'NAME_lc';
 
         if ($self->dbh_is_mysql()) {
             $self->{dbh}->do("SET group_concat_max_len=1000000");
             unless ($self->{dbh});
 
         $self->{dbh}->{FetchHashKeyName} = 'NAME_lc';
 
         if ($self->dbh_is_mysql()) {
             $self->{dbh}->do("SET group_concat_max_len=1000000");
-        } else {
+        } elsif ($self->dbh_is_pg()) {
             $self->{dbh}->do("SET datestyle TO 'ISO, YMD'");
         }
     }
             $self->{dbh}->do("SET datestyle TO 'ISO, YMD'");
         }
     }
@@ -1591,9 +1645,11 @@ sub new
 
     $self->{loginname} = CGI::remote_user();
     $self->{debug} = $self->{info}->{debug};
 
     $self->{loginname} = CGI::remote_user();
     $self->{debug} = $self->{info}->{debug};
-    $self->{lang} = $self->{info}->{lang};
     $self->{template_dir} = $self->{info}->{template_dir};
 
     $self->{template_dir} = $self->{info}->{template_dir};
 
+    my $args = $self->get_form('dir', 'lang');
+    $self->set_lang($args->{lang});
+
     return $self;
 }
 
     return $self;
 }
 
@@ -1603,6 +1659,7 @@ sub display_begin
     if ($self->{info}->{enable_security}) {
         $self->get_roles();     # get lang
     }
     if ($self->{info}->{enable_security}) {
         $self->get_roles();     # get lang
     }
+
     $self->display($self->{info}, "begin.tpl");
 }
 
     $self->display($self->{info}, "begin.tpl");
 }
 
@@ -1695,17 +1752,16 @@ sub get_limit
     my $sql = $self->{sql};
 
     if ($arg{since} and $arg{age}) {
     my $sql = $self->{sql};
 
     if ($arg{since} and $arg{age}) {
-        my $now = "$self->{sql}->{UNIX_TIMESTAMP}(TIMESTAMP '$arg{since}')";
         my $d = strftime('%Y-%m-%d %H:%M:%S', localtime($btime + $arg{age}));
         $limit .= "
  AND StartTime > '$arg{since}'  
         my $d = strftime('%Y-%m-%d %H:%M:%S', localtime($btime + $arg{age}));
         $limit .= "
  AND StartTime > '$arg{since}'  
- AND $self->{sql}->{UNIX_TIMESTAMP}(EndTime) < ($now + $self->{sql}->{TO_SEC}($arg{age}))";
+ AND EndTime < '$d' ";
 
         $label .= "since $arg{since} and during " . human_sec($arg{age});
 
     } elsif ($arg{age}) {
 
         $label .= "since $arg{since} and during " . human_sec($arg{age});
 
     } elsif ($arg{age}) {
-        my $d = strftime('%Y-%m-%d %H:%M:%S', localtime($btime - $arg{age}));
-        $limit .=  "AND EndTime > '$d' " ;
+        my $when = $btime - $arg{age};
+        $limit .= "AND JobTDate > $when";
 
         $label = "last " . human_sec($arg{age});
     }
 
         $label = "last " . human_sec($arg{age});
     }
@@ -1735,6 +1791,22 @@ sub get_limit
     return ($limit, $label);
 }
 
     return ($limit, $label);
 }
 
+sub get_item
+{
+    my ($what, $default) = @_;
+    my %opt_cookies = ( dir => 1 );
+
+    my $ret = CGI::param($what);
+
+    if ($opt_cookies{$what} && !$ret) {
+        $ret = CGI::cookie($what);
+    }
+    
+    $ret = $ret || $default;
+    return $ret;
+    
+}
+
 =head1 FUNCTION
 
     $bweb->get_form(...) - Get useful stuff
 =head1 FUNCTION
 
     $bweb->get_form(...) - Get useful stuff
@@ -1786,6 +1858,9 @@ sub get_form
                  );
 
     my %opt_ss =(               # string with space
                  );
 
     my %opt_ss =(               # string with space
+                 name    => 1,
+                 dir     => 1,
+                 new_dir => 1,
                  job     => 1,
                  storage => 1,
                  );
                  job     => 1,
                  storage => 1,
                  );
@@ -1830,7 +1905,7 @@ sub get_form
 
     foreach my $i (@what) {
         if (exists $opt_i{$i}) {# integer param
 
     foreach my $i (@what) {
         if (exists $opt_i{$i}) {# integer param
-            my $value = CGI::param($i) || $opt_i{$i} ;
+            my $value = get_item($i, $opt_i{$i}) ;
             if ($value =~ /^(\d+)$/) {
                 $ret{$i} = $1;
             } elsif ($i eq 'age' &&  # can have unit
             if ($value =~ /^(\d+)$/) {
                 $ret{$i} = $1;
             } elsif ($i eq 'age' &&  # can have unit
@@ -1839,12 +1914,12 @@ sub get_form
                 $ret{$i} = human_sec_unit($value);
             }
         } elsif ($opt_s{$i}) {  # simple string param
                 $ret{$i} = human_sec_unit($value);
             }
         } elsif ($opt_s{$i}) {  # simple string param
-            my $value = CGI::param($i) || '';
+            my $value = get_item($i, '');
             if ($value =~ /^([\w\d\.-]+)$/) {
                 $ret{$i} = $1;
             }
         } elsif ($opt_ss{$i}) { # simple string param (with space)
             if ($value =~ /^([\w\d\.-]+)$/) {
                 $ret{$i} = $1;
             }
         } elsif ($opt_ss{$i}) { # simple string param (with space)
-            my $value = CGI::param($i) || '';
+            my $value = get_item($i, '');
             if ($value =~ /^([\w\d\.\-\s]+)$/) {
                 $ret{$i} = $1;
             }
             if ($value =~ /^([\w\d\.\-\s]+)$/) {
                 $ret{$i} = $1;
             }
@@ -1864,22 +1939,22 @@ sub get_form
             $ret{$i} = [ map { { name => $self->dbh_quote($_) } } 
                                            grep { ! /^\s*$/ } CGI::param($1) ];
         } elsif (exists $opt_p{$i}) {
             $ret{$i} = [ map { { name => $self->dbh_quote($_) } } 
                                            grep { ! /^\s*$/ } CGI::param($1) ];
         } elsif (exists $opt_p{$i}) {
-            my $value = CGI::param($i) || '';
+            my $value = get_item($i, '');
             if ($value =~ /^([\w\d\.\/\s:\@\-]+)$/) {
                 $ret{$i} = $1;
             }
         } elsif (exists $opt_r{$i}) {
             if ($value =~ /^([\w\d\.\/\s:\@\-]+)$/) {
                 $ret{$i} = $1;
             }
         } elsif (exists $opt_r{$i}) {
-            my $value = CGI::param($i) || '';
+            my $value = get_item($i, '');
             if ($value =~ /^([^'"']+)$/) {
                 $ret{$i} = $1;
             }
         } elsif (exists $opt_d{$i}) {
             if ($value =~ /^([^'"']+)$/) {
                 $ret{$i} = $1;
             }
         } elsif (exists $opt_d{$i}) {
-            my $value = CGI::param($i) || '';
+            my $value = get_item($i, '');
             if ($value =~ /^\s*(\d+\s+\w+)$/) {
                 $ret{$i} = $1;
             }
         } elsif (exists $opt_t{$i}) { # 1: hh:min optionnal, 2: hh:min required
             if ($value =~ /^\s*(\d+\s+\w+)$/) {
                 $ret{$i} = $1;
             }
         } elsif (exists $opt_t{$i}) { # 1: hh:min optionnal, 2: hh:min required
-            my $when = CGI::param($i) || '';
+            my $when = get_item($i, '');
             if ($when =~ /(\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?)/) {
                 if ($opt_t{$i} == 1 or defined $2) {
                     $ret{$i} = $1;
             if ($when =~ /(\d{4}-\d{2}-\d{2}( \d{2}:\d{2}(:\d{2})?)?)/) {
                 if ($opt_t{$i} == 1 or defined $2) {
                     $ret{$i} = $1;
@@ -1888,6 +1963,14 @@ sub get_form
         }
     }
 
         }
     }
 
+    if ($what{comment}) {
+        my $s = CGI::param('comment');
+        if ($s) {
+            $s =~ s/["\\'<>]/ /g; # strip some characters
+            $ret{comment}=$s;
+        }
+    }
+
     if ($what{storage_cmd}) {
         if (!grep {/^\Q$ret{storage_cmd}\E$/} ('mount', 'umount', 'release','status')) {
             delete $ret{storage_cmd};
     if ($what{storage_cmd}) {
         if (!grep {/^\Q$ret{storage_cmd}\E$/} ('mount', 'umount', 'release','status')) {
             delete $ret{storage_cmd};
@@ -1911,7 +1994,7 @@ sub get_form
     }
 
     if ($what{lang}) {
     }
 
     if ($what{lang}) {
-        my $lang = CGI::param('lang') || 'en';
+        my $lang = get_item('lang', 'en');
         if ($lang =~ /^(\w\w)$/) {
             $ret{lang} = $1;
         }
         if ($lang =~ /^(\w\w)$/) {
             $ret{lang} = $1;
         }
@@ -2144,10 +2227,7 @@ SELECT Media.VolumeName  AS volumename,
        Media.VolMounts   AS volmounts,
        Pool.Name         AS name,
        Media.Recycle     AS recycle,
        Media.VolMounts   AS volmounts,
        Pool.Name         AS name,
        Media.Recycle     AS recycle,
-       $self->{sql}->{FROM_UNIXTIME}(
-          $self->{sql}->{UNIX_TIMESTAMP}(Media.LastWritten) 
-        + $self->{sql}->{TO_SEC}(Media.VolRetention)
-       ) AS expire
+       $self->{sql}->{MEDIA_EXPIRE} AS expire
 FROM Media 
  INNER JOIN Pool     ON (Pool.PoolId = Media.PoolId)
  LEFT  JOIN Location ON (Media.LocationId = Location.LocationId)
 FROM Media 
  INNER JOIN Pool     ON (Pool.PoolId = Media.PoolId)
  LEFT  JOIN Location ON (Media.LocationId = Location.LocationId)
@@ -2190,9 +2270,7 @@ sub help_intern_compute
         # we take only expired volumes or purged/recycle ones
         $sql = "
 AND (
         # we take only expired volumes or purged/recycle ones
         $sql = "
 AND (
- (  ($self->{sql}->{UNIX_TIMESTAMP}(Media.LastWritten) 
-      + $self->{sql}->{TO_SEC}(Media.VolRetention)
-    ) < $self->{sql}->{NOW}
+ ( ($self->{sql}->{MEDIA_EXPIRE}) < $btime
  ) OR ( 
   Media.VolStatus IN ('Purged', 'Recycle')
  )
  ) OR ( 
   Media.VolStatus IN ('Purged', 'Recycle')
  )
@@ -2207,10 +2285,7 @@ SELECT Media.VolumeName  AS volumename,
        Media.MediaType   AS mediatype,
        Media.VolMounts   AS volmounts,
        Pool.Name         AS name,
        Media.MediaType   AS mediatype,
        Media.VolMounts   AS volmounts,
        Pool.Name         AS name,
-       $self->{sql}->{FROM_UNIXTIME}(
-          $self->{sql}->{UNIX_TIMESTAMP}(Media.LastWritten) 
-        + $self->{sql}->{TO_SEC}(Media.VolRetention)
-       ) AS expire
+       $self->{sql}->{MEDIA_EXPIRE} AS expire
 FROM Media 
  INNER JOIN Pool ON (Pool.PoolId = Media.PoolId) 
  LEFT  JOIN Location ON (Location.LocationId = Media.LocationId)
 FROM Media 
  INNER JOIN Pool ON (Pool.PoolId = Media.PoolId) 
  LEFT  JOIN Location ON (Location.LocationId = Media.LocationId)
@@ -2432,7 +2507,8 @@ JOIN client_group USING (client_group_id)
 ";
     }
     my $filter = $self->get_client_filter();
 ";
     }
     my $filter = $self->get_client_filter();
-
+    my $comment = $self->get_db_field('Comment');
+    my $rb = $self->get_db_field('ReadBytes');
     my $query="
 SELECT  Job.JobId       AS jobid,
         Client.Name     AS client,
     my $query="
 SELECT  Job.JobId       AS jobid,
         Client.Name     AS client,
@@ -2446,10 +2522,9 @@ SELECT  Job.JobId       AS jobid,
         JobBytes        AS jobbytes,
         JobStatus       AS jobstatus,
         Type            AS jobtype,
         JobBytes        AS jobbytes,
         JobStatus       AS jobstatus,
         Type            AS jobtype,
-     $self->{sql}->{SEC_TO_TIME}(  $self->{sql}->{UNIX_TIMESTAMP}(EndTime)  
-                                 - $self->{sql}->{UNIX_TIMESTAMP}(StartTime)) 
-                        AS duration,
-
+        $rb             AS readbytes,
+        $comment        AS comment,
+        $self->{sql}->{JOB_DURATION} AS duration,
         JobErrors       AS joberrors
 
  FROM Client $filter $cgq, 
         JobErrors       AS joberrors
 
  FROM Client $filter $cgq, 
@@ -2474,6 +2549,24 @@ SELECT  Job.JobId       AS jobid,
                    "display_job.tpl");
 }
 
                    "display_job.tpl");
 }
 
+# Adapt the code to the Schema version
+# TODO: can use the Version field
+sub get_db_field
+{
+    my ($self, $what) = @_ ;
+
+    my %feature = ('Comment' => 4, 'ReadBytes' => 4);
+    my %replacement = ('Comment' => "''", 'ReadBytes' => 'JobBytes');
+
+    if (!$self->{info}->{dir_ver} or 
+        $self->{info}->{dir_ver} >= $feature{$what})
+    {
+        return $what;
+    } else {
+        return $replacement{$what};
+    }
+}
+
 # display job informations
 sub display_job_zoom
 {
 # display job informations
 sub display_job_zoom
 {
@@ -2484,7 +2577,8 @@ sub display_job_zoom
 
     # get security filter
     my $filter = $self->get_client_filter();
 
     # get security filter
     my $filter = $self->get_client_filter();
-
+    my $comment = $self->get_db_field('Comment');
+    my $rb = $self->get_db_field('ReadBytes');
     my $query="
 SELECT DISTINCT Job.JobId       AS jobid,
                 Client.Name     AS client,
     my $query="
 SELECT DISTINCT Job.JobId       AS jobid,
                 Client.Name     AS client,
@@ -2498,9 +2592,9 @@ SELECT DISTINCT Job.JobId       AS jobid,
                 JobStatus       AS jobstatus,
                 JobErrors       AS joberrors,
                 Type            AS jobtype,
                 JobStatus       AS jobstatus,
                 JobErrors       AS joberrors,
                 Type            AS jobtype,
-                $self->{sql}->{SEC_TO_TIME}(  $self->{sql}->{UNIX_TIMESTAMP}(EndTime)  
-                                            - $self->{sql}->{UNIX_TIMESTAMP}(StartTime)) AS duration
-
+                $rb             AS readbytes,
+                $comment        AS comment,
+                $self->{sql}->{JOB_DURATION} AS duration
  FROM Client $filter,
       Job LEFT JOIN FileSet ON (Job.FileSetId = FileSet.FileSetId)
           LEFT JOIN Pool    ON (Job.PoolId    = Pool.PoolId)
  FROM Client $filter,
       Job LEFT JOIN FileSet ON (Job.FileSetId = FileSet.FileSetId)
           LEFT JOIN Pool    ON (Job.PoolId    = Pool.PoolId)
@@ -2546,16 +2640,13 @@ SELECT client_group_name AS client_group_name,
        COALESCE(jobok.joberrors,0) + COALESCE(joberr.joberrors,0) AS joberrors,
        COALESCE(jobok.nbjobs,0)  AS nbjobok,
        COALESCE(joberr.nbjobs,0) AS nbjoberr,
        COALESCE(jobok.joberrors,0) + COALESCE(joberr.joberrors,0) AS joberrors,
        COALESCE(jobok.nbjobs,0)  AS nbjobok,
        COALESCE(joberr.nbjobs,0) AS nbjoberr,
-       COALESCE(jobok.duration, '0:0:0') AS duration
+       COALESCE(jobok.duration, '0') AS duration
 
 FROM client_group $filter LEFT JOIN (
     SELECT client_group_name AS client_group_name, COUNT(1) AS nbjobs, 
            SUM(JobFiles) AS jobfiles, SUM(JobBytes) AS jobbytes, 
            SUM(JobErrors) AS joberrors,
 
 FROM client_group $filter LEFT JOIN (
     SELECT client_group_name AS client_group_name, COUNT(1) AS nbjobs, 
            SUM(JobFiles) AS jobfiles, SUM(JobBytes) AS jobbytes, 
            SUM(JobErrors) AS joberrors,
-           SUM($self->{sql}->{SEC_TO_TIME}(  $self->{sql}->{UNIX_TIMESTAMP}(EndTime)  
-                              - $self->{sql}->{UNIX_TIMESTAMP}(StartTime)))
-                        AS duration
-
+           $self->{sql}->{JOB_DURATION} AS duration
     FROM Job JOIN client_group_member ON (Job.ClientId = client_group_member.ClientId)
              JOIN client_group USING (client_group_id)
     
     FROM Job JOIN client_group_member ON (Job.ClientId = client_group_member.ClientId)
              JOIN client_group USING (client_group_id)
     
@@ -2608,9 +2699,7 @@ sub display_media
     if ($arg->{expired}) {
         $where = " 
         AND VolStatus IN ('Full', 'Used')
     if ($arg->{expired}) {
         $where = " 
         AND VolStatus IN ('Full', 'Used')
-        AND (    $self->{sql}->{UNIX_TIMESTAMP}(Media.LastWritten) 
-               + $self->{sql}->{TO_SEC}(Media.VolRetention)
-            ) < $self->{sql}->{NOW}  " . $where ;
+        AND ( $self->{sql}->{MEDIA_EXPIRE} ) < $btime  " . $where ;
     }
 
     my $query="
     }
 
     my $query="
@@ -2623,10 +2712,7 @@ SELECT Media.VolumeName  AS volumename,
        Location.Location AS location,
        (volbytes*100/COALESCE(media_avg_size.size,-1))  AS volusage,
        Pool.Name         AS poolname,
        Location.Location AS location,
        (volbytes*100/COALESCE(media_avg_size.size,-1))  AS volusage,
        Pool.Name         AS poolname,
-       $self->{sql}->{FROM_UNIXTIME}(
-          $self->{sql}->{UNIX_TIMESTAMP}(Media.LastWritten) 
-        + $self->{sql}->{TO_SEC}(Media.VolRetention)
-       ) AS expire
+       $self->{sql}->{MEDIA_EXPIRE} AS expire
 FROM      Pool, Media 
 LEFT JOIN Location ON (Media.LocationId = Location.LocationId)
 LEFT JOIN (SELECT avg(Media.VolBytes) AS size,
 FROM      Pool, Media 
 LEFT JOIN Location ON (Media.LocationId = Location.LocationId)
 LEFT JOIN (SELECT avg(Media.VolBytes) AS size,
@@ -2640,7 +2726,6 @@ WHERE Media.PoolId=Pool.PoolId
 $where
 $limit
 ";
 $where
 $limit
 ";
-
     my $all = $self->dbh_selectall_hashref($query, 'volumename') ;
 
     $self->display({ ID => $cur_id++,
     my $all = $self->dbh_selectall_hashref($query, 'volumename') ;
 
     $self->display({ ID => $cur_id++,
@@ -2694,10 +2779,7 @@ SELECT InChanger     AS online,
        Media.VolWriteTime/1000000 AS volwritetime,
        Media.RecycleCount AS recyclecount,
        Media.Comment      AS comment,
        Media.VolWriteTime/1000000 AS volwritetime,
        Media.RecycleCount AS recyclecount,
        Media.Comment      AS comment,
-       $self->{sql}->{FROM_UNIXTIME}(
-          $self->{sql}->{UNIX_TIMESTAMP}(Media.LastWritten) 
-        + $self->{sql}->{TO_SEC}(Media.VolRetention)
-       ) AS expire
+       $self->{sql}->{MEDIA_EXPIRE} AS expire
  FROM Pool,
       Media LEFT JOIN Location ON (Media.LocationId = Location.LocationId)
  WHERE Pool.PoolId = Media.PoolId
  FROM Pool,
       Media LEFT JOIN Location ON (Media.LocationId = Location.LocationId)
  WHERE Pool.PoolId = Media.PoolId
@@ -2878,7 +2960,6 @@ FROM Location
 ";
 
     my $location = $self->dbh_selectall_hashref($query, 'location');
 ";
 
     my $location = $self->dbh_selectall_hashref($query, 'location');
-
     $self->display({ ID => $cur_id++,
                      Locations => [ values %$location ] },
                    "display_location.tpl");
     $self->display({ ID => $cur_id++,
                      Locations => [ values %$location ] },
                    "display_location.tpl");
@@ -3141,7 +3222,7 @@ sub get_roles
     }
     $self->{security}->{use_acl} = $rows->[0]->[0];
     if ($rows->[0]->[2] =~ /^(\w\w)$/) {
     }
     $self->{security}->{use_acl} = $rows->[0]->[0];
     if ($rows->[0]->[2] =~ /^(\w\w)$/) {
-        $self->{lang} = $1;
+        $self->set_lang($1);
     }
     return 1;
 }
     }
     return 1;
 }
@@ -3827,7 +3908,7 @@ sub display_overview
 
     my $q = "
 SELECT name, $stime1 AS num, 
 
     my $q = "
 SELECT name, $stime1 AS num, 
-       JobStatus AS value, joberrors, nb_job, date
+       Status.JobStatus AS value, joberrors, nb_job, date
 FROM (
   SELECT $stime2        AS date, 
          client_group_name AS name,
 FROM (
   SELECT $stime2        AS date, 
          client_group_name AS name,
@@ -3838,7 +3919,7 @@ FROM (
     JOIN client_group_member USING (ClientId)
     JOIN client_group        USING (client_group_id) $filter3
     JOIN Status              USING (JobStatus)
     JOIN client_group_member USING (ClientId)
     JOIN client_group        USING (client_group_id) $filter3
     JOIN Status              USING (JobStatus)
-   WHERE JobStatus IN ('T', 'W', 'f', 'A', 'e', 'E')
+   WHERE Job.JobStatus IN ('T', 'W', 'f', 'A', 'e', 'E')
        $filter1 $filter2
    GROUP BY client_group_name, date
 ) AS sub JOIN Status USING (severity)
        $filter1 $filter2
    GROUP BY client_group_name, date
 ) AS sub JOIN Status USING (severity)
@@ -4098,9 +4179,7 @@ SELECT Job.JobId AS jobid,
        Job.JobFiles  AS jobfiles,
        Job.JobBytes  AS jobbytes,
        Job.JobStatus AS jobstatus,
        Job.JobFiles  AS jobfiles,
        Job.JobBytes  AS jobbytes,
        Job.JobStatus AS jobstatus,
-$self->{sql}->{SEC_TO_TIME}($self->{sql}->{UNIX_TIMESTAMP}($self->{sql}->{NOW})
-                          - $self->{sql}->{UNIX_TIMESTAMP}(StartTime)) 
-         AS duration,
+       $btime - Job.JobTDate AS duration,
        Client.Name AS clientname
 FROM Job INNER JOIN Client USING (ClientId) $filter
 WHERE 
        Client.Name AS clientname
 FROM Job INNER JOIN Client USING (ClientId) $filter
 WHERE 
@@ -4250,7 +4329,6 @@ sub restore
 # TODO : make this internal to not eject tape ?
 use Bconsole;
 
 # TODO : make this internal to not eject tape ?
 use Bconsole;
 
-
 sub display_files
 {
     my ($self) = @_ ;
 sub display_files
 {
     my ($self) = @_ ;
@@ -4620,7 +4698,7 @@ SELECT count(1) AS nbline,
 your 'Messages' resources include 'catalog = all' and you loaded Bweb SQL
 functions in your Catalog.");
     }
 your 'Messages' resources include 'catalog = all' and you loaded Bweb SQL
 functions in your Catalog.");
     }
-    $log->{logtxt} =~ s/\0//g;
+    $log->{logtxt} =~ s/(\0|\\,)//g;
     $self->display({ lines=> $log->{logtxt},
                      nbline => $log->{nbline},
                      jobid => $arg->{jobid},
     $self->display({ lines=> $log->{logtxt},
                      nbline => $log->{nbline},
                      jobid => $arg->{jobid},
@@ -4684,7 +4762,7 @@ INSERT INTO $jobtable
                             pool => $arg->{pool},
                             level => $arg->{level},
                             starttime => $arg->{when},
                             pool => $arg->{pool},
                             level => $arg->{level},
                             starttime => $arg->{when},
-                            duration => '00:00:00',
+                            duration => 0,
                             jobfiles => 0,
                             jobbytes => 0,
                             joberrors => 0,
                             jobfiles => 0,
                             jobbytes => 0,
                             joberrors => 0,
@@ -4720,8 +4798,10 @@ sub add_media
         $b->send("0\n");
         $b->send("$arg->{media}\n");
     }
         $b->send("0\n");
         $b->send("$arg->{media}\n");
     }
+    $b->close();
 
 
-    $b->expect_it('-re','^[*]');
+    sleep(2);
+    #$b->expect_it('-re','^[*]');
 
     CGI::param('media', '');
     CGI::param('re_media', $arg->{media});
 
     CGI::param('media', '');
     CGI::param('re_media', $arg->{media});
@@ -4791,7 +4871,7 @@ sub purge
         return $self->error("Can't get media selection");
     }
 
         return $self->error("Can't get media selection");
     }
 
-    my $b = new Bconsole(pref => $self->{info}, timeout => 60);
+    my $b = $self->get_bconsole(timeout => 60);
 
     foreach my $v (@volume) {
         $self->display({
 
     foreach my $v (@volume) {
         $self->display({
@@ -4814,7 +4894,7 @@ sub prune
         return $self->error("Can't get media selection");
     }
 
         return $self->error("Can't get media selection");
     }
 
-    my $b = new Bconsole(pref => $self->{info}, timeout => 60);
+    my $b = $self->get_bconsole(timeout => 60);
 
     foreach my $v (@volume) {
         $self->display({
 
     foreach my $v (@volume) {
         $self->display({
@@ -4906,10 +4986,16 @@ sub enable_disable_job
     }, "command.tpl");  
 }
 
     }, "command.tpl");  
 }
 
+sub set_lang
+{
+    my ($self, $lang) = @_;
+    $self->{current_lang} = $lang;
+}
+
 sub get_bconsole
 {
 sub get_bconsole
 {
-    my ($self) = @_;
-    return new Bconsole(pref => $self->{info});
+    my ($self, @opts) = @_;
+    return new Bconsole(pref => $self->{info}, @opts);
 }
 
 sub cmd_storage
 }
 
 sub cmd_storage
@@ -4980,7 +5066,7 @@ sub run_job_mod
     $self->can_do('r_run_job');
 
     my $b = $self->get_bconsole();
     $self->can_do('r_run_job');
 
     my $b = $self->get_bconsole();
-    my $arg = $self->get_form(qw/pool level client fileset storage media job/);
+    my $arg = $self->get_form(qw/pool level client fileset storage media job comment/);
 
     if (!$arg->{job}) {
         return $self->error("Can't get job name");
 
     if (!$arg->{job}) {
         return $self->error("Can't get job name");
@@ -5004,7 +5090,7 @@ SELECT Pool.Name AS name
 
     my %job_opt = (%$attr, %$arg);
     
 
     my %job_opt = (%$attr, %$arg);
     
-    my $jobs   = [ map {{ name => $_ }} $b->list_job() ];
+    my $jobs   = [ map {{ name => $_ }} $b->list_backup() ];
 
     my $pools  = [ map { { name => $_ } } $b->list_pool() ];
     my $clients = [ map { { name => $_ } }$b->list_client()];
 
     my $pools  = [ map { { name => $_ } } $b->list_pool() ];
     my $clients = [ map { { name => $_ } }$b->list_client()];
@@ -5028,8 +5114,10 @@ sub run_job
 
     my $b = $self->get_bconsole();
     
 
     my $b = $self->get_bconsole();
     
-    my $jobs   = [ map {{ name => $_ }} $b->list_job() ];
-
+    my $jobs   = [ map {{ name => $_ }} $b->list_backup() ];
+    if ($b->{error}) {
+        return $self->error("Bconsole returns an error, check your setup. ERR=$b->{error}");
+    }
     $self->display({
         jobs     => $jobs,
     }, "run_job.tpl");
     $self->display({
         jobs     => $jobs,
     }, "run_job.tpl");
@@ -5045,7 +5133,7 @@ sub run_job_now
     # TODO: check input (don't use pool, level)
 
     my $arg = $self->get_form(qw/pool level client priority when 
     # TODO: check input (don't use pool, level)
 
     my $arg = $self->get_form(qw/pool level client priority when 
-                                 fileset job storage/);
+                                 fileset job storage comment/);
     if (!$arg->{job}) {
         return $self->error("Can't get your job name");
     }
     if (!$arg->{job}) {
         return $self->error("Can't get your job name");
     }
@@ -5058,6 +5146,7 @@ sub run_job_now
                         pool => $arg->{pool},
                         fileset => $arg->{fileset},
                         when => $arg->{when},
                         pool => $arg->{pool},
                         fileset => $arg->{fileset},
                         when => $arg->{when},
+                        comment => $arg->{comment}
                         );
 
     print $b->{error};    
                         );
 
     print $b->{error};    
@@ -5122,6 +5211,8 @@ sub check_job
     my ($self, $sched, $schedname, $job, $job_pool, $client, $type) = @_;
     return undef if (!$self->can_view_client($client));
 
     my ($self, $sched, $schedname, $job, $job_pool, $client, $type) = @_;
     return undef if (!$self->can_view_client($client));
 
+    $self->debug("checking $job, $job_pool, $client, $type, $schedname");
+
     my $sch = $sched->get_scheds($schedname);    
     return undef if (!$sch);
 
     my $sch = $sched->get_scheds($schedname);    
     return undef if (!$sch);
 
@@ -5152,7 +5243,7 @@ sub check_job
  LIMIT 1
 ");             
             if ($all) {
  LIMIT 1
 ");             
             if ($all) {
-#               print "ok $job ";
+                $self->debug("found job record for $job on $client");
             } else {
                 push @{$self->{tmp}}, {date => $evt, level => $level,
                                        type => 'Backup', name => $job,
             } else {
                 push @{$self->{tmp}}, {date => $evt, level => $level,
                                        type => 'Backup', name => $job,
@@ -5182,7 +5273,7 @@ sub display_missing_job
     my $sched = new Bweb::Sched(bconsole => $bconsole,
                                 begin => $arg->{begin},
                                 end => $arg->{end});
     my $sched = new Bweb::Sched(bconsole => $bconsole,
                                 begin => $arg->{begin},
                                 end => $arg->{end});
-
+    $self->debug($sched);
     my $job = $bconsole->send_cmd("show job");
     my ($jname, $jsched, $jclient, $jpool, $jtype);
     foreach my $j (split(/\r?\n/, $job)) {
     my $job = $bconsole->send_cmd("show job");
     my ($jname, $jsched, $jclient, $jpool, $jtype);
     foreach my $j (split(/\r?\n/, $job)) {
index c06745c4ccc533ed8ea700c20b7b4ff819c897af..8fc818cbd42cae215cfbf1cab97cd03cddb74dfa 100644 (file)
@@ -84,10 +84,10 @@ sub new
     map { $self->{$_} = $arg{$_} } keys %arg ;
 
     if ($self->{begin}) {
     map { $self->{$_} = $arg{$_} } keys %arg ;
 
     if ($self->{begin}) {
-        $self->{begin} = parsedate($self->{begin});
+        $self->{begin} = $self->{begin};
     }
     if ($self->{end}) {
     }
     if ($self->{end}) {
-        $self->{end} = parsedate($self->{end});
+        $self->{end} = $self->{end};
     }
 
     bless $self ;
     }
 
     bless $self ;
@@ -349,20 +349,20 @@ $top->add_job(label => "label",
               data => [
                        {
                            type  => "init",
               data => [
                        {
                            type  => "init",
-                           begin => $begin1,
-                           end   => $end1,
+                           begin => parsedate($begin1),
+                           end   => parsedate($end1),
                        },
 
                        {
                            type  => "write",
                        },
 
                        {
                            type  => "write",
-                           begin => $end1,
-                           end   => $begin2,
+                           begin => parsedate($end1),
+                           end   => parsedate($begin2),
                        },
 
                        {
                            type  => "commit",
                        },
 
                        {
                            type  => "commit",
-                           begin => $begin2,
-                           end   => $end2,
+                           begin => parsedate($begin2),
+                           end   => parsedate($end2),
                        },
                        ]);
 
                        },
                        ]);
 
@@ -370,20 +370,20 @@ $top->add_job(label => "label2",
               data => [
                        {
                            type  => "init",
               data => [
                        {
                            type  => "init",
-                           begin => $begin1,
-                           end   => $end1,
+                           begin => parsedate($begin1),
+                           end   => parsedate($end1),
                        },
 
                        {
                            type  => "write",
                        },
 
                        {
                            type  => "write",
-                           begin => $end1,
-                           end   => $begin2,
+                           begin => parsedate($end1),
+                           end   => parsedate($begin2),
                        },
 
                        {
                            type  => "commit",
                        },
 
                        {
                            type  => "commit",
-                           begin => $begin2,
-                           end   => $end2,
+                           begin => parsedate($begin2),
+                           end   => parsedate($end2),
                        },
                        ]);
 
                        },
                        ]);
 
index 90e8d1d4bab0dba7e329b3ae20dd732a9ad87df3..afbabb8c7ec3d32a4b336f8a86d5db4234cc4855 100644 (file)
@@ -1,3 +1,9 @@
+-- --------------------------------------------------
+-- Upgrade from 5.0
+-- --------------------------------------------------
+
+CREATE UNIQUE INDEX location_idx ON Location (Location(255));
+
 -- --------------------------------------------------
 -- Upgrade from 2.4
 -- --------------------------------------------------
 -- --------------------------------------------------
 -- Upgrade from 2.4
 -- --------------------------------------------------
index 50f57297c96c31bce5692999b978df0ec2c0934d..3c9aa630274f8c7300fc3d0327933e417466b066 100644 (file)
@@ -1,6 +1,22 @@
 -- Require > 7.4, else use createlang command
 CREATE PROCEDURAL LANGUAGE plpgsql;
 
 -- Require > 7.4, else use createlang command
 CREATE PROCEDURAL LANGUAGE plpgsql;
 
+-- --------------------------------------------------
+-- Upgrade from 5.0
+-- --------------------------------------------------
+
+BEGIN;
+
+-- PG 8.4 drops implicit cast from double to bigint
+CREATE FUNCTION SEC_TO_TIME(double precision)
+RETURNS interval AS $$
+    select date_trunc('second', $1 * interval '1 second');
+$$ LANGUAGE SQL;
+
+COMMIT;
+
+CREATE UNIQUE INDEX location_idx ON Location (Location);
+
 -- --------------------------------------------------
 -- Upgrade from 2.2
 -- --------------------------------------------------
 -- --------------------------------------------------
 -- Upgrade from 2.2
 -- --------------------------------------------------
index 81793bc1269edb857c94dae90072deadc8f78977..d42ddd877f705f701a7383dcfff93537f2106331 100644 (file)
@@ -11,9 +11,10 @@ server.port = 9180
 
 var.basedir = env.BWEBBASE
 
 
 var.basedir = env.BWEBBASE
 
-server.modules = ("mod_cgi", "mod_alias", "mod_setenv")
+server.modules = ("mod_cgi", "mod_alias", "mod_setenv", "mod_accesslog")
 server.document-root = basedir + "/html/" 
 server.document-root = basedir + "/html/" 
-
+server.errorlog = basedir + "/error.log"
+accesslog.filename = basedir + "/access.log"
 cgi.assign = ( ".pl" => "/usr/bin/perl" )
 alias.url = ( "/cgi-bin/bweb/" => basedir + "/cgi/", 
               "/bweb/fv/" => "/tmp/",
 cgi.assign = ( ".pl" => "/usr/bin/perl" )
 alias.url = ( "/cgi-bin/bweb/" => basedir + "/cgi/", 
               "/bweb/fv/" => "/tmp/",
index a42c791c85c8e1a19b28230a01976b04244bd77f..f0206185c17e6e68627762e79f72e41e3048b0da 100755 (executable)
@@ -6,7 +6,7 @@ use strict;
    Bweb - A Bacula web interface
    Bacula® - The Network Backup Solution
 
    Bweb - A Bacula web interface
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2010 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
 
    The main author of Bweb is Eric Bollengier.
    The main author of Bacula is Kern Sibbald, with contributions from
@@ -34,13 +34,14 @@ use strict;
 =head1 USAGE
 
     Get it working with a regress environment:
 =head1 USAGE
 
     Get it working with a regress environment:
-     * get regress module from SVN
+     * get regress module from git
      * use postgresql or mysql in config
      * make setup
      * add catalog = all, !skipped, !saved into Messages Standard (scripts/bacula-dir.conf)
      * add exit 0 to scripts/cleanup
      * run bacula-backup-test
      * use postgresql or mysql in config
      * make setup
      * add catalog = all, !skipped, !saved into Messages Standard (scripts/bacula-dir.conf)
      * add exit 0 to scripts/cleanup
      * run bacula-backup-test
-     * uncomment job schedule in bacula-dir.conf
+     * uncomment job schedule in bacula-dir.conf 
+       $ sed -i 's/# Sc/  Sc/' bacula-dir.conf
      * load bweb-(mysql|postgresql).sql
      * ./bin/bacula start
      * configure bweb to point to bconsole and the catalog
      * load bweb-(mysql|postgresql).sql
      * ./bin/bacula start
      * configure bweb to point to bconsole and the catalog
index bc3f221a002a568b1cc29fed24a697a4cbd10b30..1765c975a0f25a781af433a5cf89d34986d321ce 100755 (executable)
@@ -6,7 +6,7 @@ use strict;
    Bweb - A Bacula web interface
    Bacula® - The Network Backup Solution
 
    Bweb - A Bacula web interface
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2010 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
 
    The main author of Bweb is Eric Bollengier.
    The main author of Bacula is Kern Sibbald, with contributions from
@@ -37,10 +37,6 @@ use strict;
     rm -f lang/fr/tpl/*.tpl
     LANGUAGE=fr ./script/tpl_generate.pl tpl/*.pl
 
     rm -f lang/fr/tpl/*.tpl
     LANGUAGE=fr ./script/tpl_generate.pl tpl/*.pl
 
-=head1 VERSION
-
-    $Id$
-
 =cut
 
 my $debug=0;
 =cut
 
 my $debug=0;
@@ -76,6 +72,9 @@ foreach my $f (@ARGV)
     print "Converting $f -> $out/$file ";
     while (my $l = <FP>)
     {
     print "Converting $f -> $out/$file ";
     while (my $l = <FP>)
     {
+#        $l =~ s:bresto.html:bresto.html<TMPL_IF cur_name>?dir=<TMPL_VAR cur_name></TMPL_IF>:;
+#        $l =~ s:(href=['"](\w+.pl)?\?):${1}<TMPL_IF cur_name>dir=<TMPL_VAR cur_name>;</TMPL_IF>:g;
+#        $l =~ s:(<form [^>]+>):$1<TMPL_IF cur_name><input type='hidden' name='dir' value='<TMPL_VAR cur_name>'></TMPL_IF>:g;
        my (@str) = ($l =~ m/__(.+?)__/g);
         
         while (my $s = shift @str) {
        my (@str) = ($l =~ m/__(.+?)__/g);
         
         while (my $s = shift @str) {
index 70ede3a6895ade1bf6c71b516fedc0e9d6f28fb6..59f8afe19243e3c8377f4aecfbf01f68fc36ddb6 100644 (file)
@@ -72,7 +72,7 @@ human_size(<TMPL_VAR volbytes>),
 "<TMPL_VAR mediatype>",
 "<TMPL_VAR name>",
 "<TMPL_VAR lastwritten>",
 "<TMPL_VAR mediatype>",
 "<TMPL_VAR name>",
 "<TMPL_VAR lastwritten>",
-"<TMPL_VAR expire>",
+timestamp_to_iso("<TMPL_VAR expire>"),
 chkbox
  )
 );
 chkbox
  )
 );
index 15102e3537e50c2f93b424bf3d6fbea451ceeddb..99e8562a6c0569f38e99a724c7da66ba7ed18d9e 100644 (file)
@@ -34,7 +34,7 @@
      </tr>
     </table>
     <button type="submit" class="bp" name='action' value='add_media'>
      </tr>
     </table>
     <button type="submit" class="bp" name='action' value='add_media'>
-     <img src='/bweb/add.png' alt=''>__Add__<button>
+     <img src='/bweb/add.png' alt=''>__Add__</button>
    </form>
 </div>
 
    </form>
 </div>
 
index a7399eaf17028b13d22d1b21bd1ce3d69392c44f..8b73fb23f79125b310fefd2654b069f2ca547dd5 100644 (file)
@@ -76,9 +76,12 @@ if ('__Main__' == ('_' + '_Main_' + '_')) {
 </TMPL_IF>
 </li>
  <li> <a href="bweb.pl?action=about"> __About__ </a> </li>
 </TMPL_IF>
 </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="padding: 0.25em 2em;float: right;">&nbsp;
+<TMPL_IF loginname>__Logged as__ <TMPL_VAR loginname></TMPL_IF>
+<TMPL_IF cur_name>__on__ <TMPL_VAR cur_name></TMPL_IF>
+</li>
  <li style="float: right;white-space: nowrap;">
  <li style="float: right;white-space: nowrap;">
-<button type="submit" class="bp" class="button" title="__Search media__" onclick="search_media();"><img src="/bweb/tape.png" alt=''></button><button type="submit" title="__Search client__" onclick="search_client();" class='bp'><img src="/bweb/client.png" alt=''></button><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__"></button></li>
+<button type="submit" class="bp" class="button" title="__Search media__" onclick="search_media();"><img src="/bweb/tape.png" alt=''></button><button type="submit" title="__Search client__" onclick="search_client();" class='bp'><img src="/bweb/client.png" alt=''></button><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="bweb.pl?" method='GET'>
 </ul>
 
 <form name="search" action="bweb.pl?" method='GET'>
index ef0c25fa0e25c7e8a0f36501f4c2a56bbcc58b25..8530023dbacb0f374893bf3bdf5a6bd40dd5dc0f 100644 (file)
@@ -14,14 +14,15 @@ document.getElementById('status_<TMPL_VAR status>').checked = true;
 
 var header = new Array("JobId",
                       "__Client__",
 
 var header = new Array("JobId",
                       "__Client__",
-                      "__Job Name__", 
+                      "__Job Name__",
+                       "__Comment__",
                       "__FileSet__",
 //                     "__Pool__",
                        "__Level__",
                        "__StartTime__",
                       "__Duration__",
                        "__JobFiles__",
                       "__FileSet__",
 //                     "__Pool__",
                        "__Level__",
                        "__StartTime__",
                       "__Duration__",
                        "__JobFiles__",
-                       "__JobBytes__", 
+                       "__JobBytes__",
                        "__Errors__",
                       "__Status__");
 
                        "__Errors__",
                       "__Status__");
 
@@ -42,12 +43,13 @@ a.appendChild(img);
 data.push( new Array(
 "<TMPL_VAR JobId>",
 "<TMPL_VAR Client>",     
 data.push( new Array(
 "<TMPL_VAR JobId>",
 "<TMPL_VAR Client>",     
-"<TMPL_VAR JobName>",    
+"<TMPL_VAR JobName>",
+"<TMPL_VAR Comment>",
 "<TMPL_VAR FileSet>",    
 //"<TMPL_VAR Pool>",
 "<TMPL_VAR Level>",      
 "<TMPL_VAR StartTime>",
 "<TMPL_VAR FileSet>",    
 //"<TMPL_VAR Pool>",
 "<TMPL_VAR Level>",      
 "<TMPL_VAR StartTime>",
-"<TMPL_VAR Duration>",
+human_duration("<TMPL_VAR Duration>"),
 "<TMPL_VAR JobFiles>",   
 human_size(<TMPL_VAR JobBytes>),
 "<TMPL_VAR joberrors>",   
 "<TMPL_VAR JobFiles>",   
 human_size(<TMPL_VAR JobBytes>),
 "<TMPL_VAR joberrors>",   
index 69ec1f9b8a2d6b618edac7fb8fc29952fb0246fb..f8eafd0b6eb54bb6a555cfb4da0bc9b832dbbf50 100644 (file)
@@ -1,5 +1,6 @@
  <div class='titlediv'>
  <div class='titlediv'>
-  <h1 class='newstitle'>__Information about job__</h1>
+  <h1 class='newstitle'>__Information about job__ <i><TMPL_VAR JobName></i>
+       <TMPL_IF comment>(<TMPL_VAR comment>)</TMPL_IF></h1>
  </div>
  <div class="bodydiv">
  <table id='id0'></table>
  </div>
  <div class="bodydiv">
  <table id='id0'></table>
@@ -88,6 +89,7 @@ var header = new Array("JobId",
                       "__Duration__",
                        "__JobFiles__",
                        "__JobBytes__",
                       "__Duration__",
                        "__JobFiles__",
                        "__JobBytes__",
+//                       "__Comp__",
                        "__Errors__",
                       "__Pool__",
                        "__Volume Name__",
                        "__Errors__",
                       "__Pool__",
                        "__Volume Name__",
@@ -108,9 +110,10 @@ data.push( new Array(
 "<TMPL_VAR FileSet>",    
 "<TMPL_VAR Level>",      
 "<TMPL_VAR StartTime>",
 "<TMPL_VAR FileSet>",    
 "<TMPL_VAR Level>",      
 "<TMPL_VAR StartTime>",
-"<TMPL_VAR duration>",
+human_duration("<TMPL_VAR duration>"),
 "<TMPL_VAR JobFiles>",   
 human_size(<TMPL_VAR JobBytes>),
 "<TMPL_VAR JobFiles>",   
 human_size(<TMPL_VAR JobBytes>),
+//parseInt(100-100*<TMPL_VAR JobBytes>/(<TMPL_VAR ReadBytes>+0.00001), 10) + "%",
 "<TMPL_VAR joberrors>",
 "<TMPL_VAR poolname>",
 "<TMPL_LOOP volumes><TMPL_VAR VolumeName>\n</TMPL_LOOP>",   
 "<TMPL_VAR joberrors>",
 "<TMPL_VAR poolname>",
 "<TMPL_LOOP volumes><TMPL_VAR VolumeName>\n</TMPL_LOOP>",   
index 89adcec886c42f518cf0b0c68ac489fa83d940ee..7487343516dfcc7fc922bcccd9a2cb8a8f59c9fd 100644 (file)
@@ -62,7 +62,7 @@ d,
 "<TMPL_VAR poolname>",
 "<TMPL_VAR mediatype>",
 "<TMPL_VAR lastwritten>",
 "<TMPL_VAR poolname>",
 "<TMPL_VAR mediatype>",
 "<TMPL_VAR lastwritten>",
-"<TMPL_VAR expire>",
+timestamp_to_iso("<TMPL_VAR expire>"),
 chkbox
  )
 );
 chkbox
  )
 );
index 655da33a55e1631ffc7954dc7b535bedbaa37482..1f676bfb5fceb6be81990de15fca43d6232708c5 100644 (file)
@@ -56,7 +56,7 @@ human_enabled("<TMPL_VAR enabled>"),
 "<TMPL_VAR location>",
 "<TMPL_VAR volstatus>",
 human_size(<TMPL_VAR nb_bytes>),
 "<TMPL_VAR location>",
 "<TMPL_VAR volstatus>",
 human_size(<TMPL_VAR nb_bytes>),
-"<TMPL_VAR expire>",
+timestamp_to_iso("<TMPL_VAR expire>"),
 human_sec(<TMPL_VAR volretention>),
 human_sec(<TMPL_VAR voluseduration>),
 "<TMPL_VAR maxvoljobs>"
 human_sec(<TMPL_VAR volretention>),
 human_sec(<TMPL_VAR voluseduration>),
 "<TMPL_VAR maxvoljobs>"
index dc9be23886d68f5d0b56cd902f9a7ad7c8705d34..f679201f5f79e3017fb363d6562cd483bf25e22b 100644 (file)
@@ -37,7 +37,7 @@ data.push( new Array(
 "<TMPL_VAR mediatype>",
 "<TMPL_VAR name>",
 "<TMPL_VAR lastwritten>",
 "<TMPL_VAR mediatype>",
 "<TMPL_VAR name>",
 "<TMPL_VAR lastwritten>",
-"<TMPL_VAR expire>",
+timestamp_to_iso("<TMPL_VAR expire>"),
 chkbox
  )
 );
 chkbox
  )
 );
index 1ad308c53017efb5ba65b4f0c790e332f4645e49..41cc9f228d007988ad854aee71afd65138621682 100644 (file)
@@ -39,7 +39,7 @@ data.push( new Array(
 "<TMPL_VAR mediatype>",
 "<TMPL_VAR name>",
 "<TMPL_VAR lastwritten>",
 "<TMPL_VAR mediatype>",
 "<TMPL_VAR name>",
 "<TMPL_VAR lastwritten>",
-"<TMPL_VAR expire>",
+timestamp_to_iso("<TMPL_VAR expire>"),
 chkbox
  )
 );
 chkbox
  )
 );
index 8ba90c7a7c1df8f54731f48f0ee374342c7c3ed7..8a42aa40535e338bcac85428bd990da98bf4309e 100644 (file)
      <option id='level_Incremental' value='Incremental'>__Incremental__</option>
      <option id='level_Full' value='Full'>__Full__</option>
      <option id='level_Differential' value='Differential'>__Differential__</option>
      <option id='level_Incremental' value='Incremental'>__Incremental__</option>
      <option id='level_Full' value='Full'>__Full__</option>
      <option id='level_Differential' value='Differential'>__Differential__</option>
+     <option id='level_Base' value='Base'>__Base__</option>
    </select>
    </select>
+   </td></tr><tr><td>__Comment:__ </td><td>
+   <input type='text' title='Comment about this job'
+          size='17' name='comment' value='<TMPL_VAR comment>'>
 
    </td></tr><tr id='more1' style="visibility:hidden"><td>__Start Time:__ </td><td>
    <input type='text' title='YYYY-MM-DD HH:MM:SS'
 
    </td></tr><tr id='more1' style="visibility:hidden"><td>__Start Time:__ </td><td>
    <input type='text' title='YYYY-MM-DD HH:MM:SS'
index 60967e59b5671dc9f4d8e0e6f35d3584fae4b89e..34c0f935324fcd8e81b2e37d4027cfc7005b1cd4 100644 (file)
@@ -54,7 +54,7 @@ data.push( new Array(
 "<TMPL_VAR JobName>",    
 joblevel['<TMPL_VAR Level>'],      
 "<TMPL_VAR StartTime>",
 "<TMPL_VAR JobName>",    
 joblevel['<TMPL_VAR Level>'],      
 "<TMPL_VAR StartTime>",
-"<TMPL_VAR duration>",
+human_sec2("<TMPL_VAR duration>"),
 //"<TMPL_VAR JobFiles>",   
 //"<TMPL_VAR JobBytes>",
 a,
 //"<TMPL_VAR JobFiles>",   
 //"<TMPL_VAR JobBytes>",
 a,
index c76ab7703d717c1d292ed59b97691bf0266bad75..ed8f5b79628974127fcf3f6b10131517f022db0e 100644 (file)
@@ -3,7 +3,7 @@
   <h1 class='newstitle'> <TMPL_IF title><TMPL_VAR title><TMPL_ELSE>__Next Jobs__ </TMPL_IF></h1>
  </div>
  <div class='bodydiv'>
   <h1 class='newstitle'> <TMPL_IF title><TMPL_VAR title><TMPL_ELSE>__Next Jobs__ </TMPL_IF></h1>
  </div>
  <div class='bodydiv'>
-    <form name='form1' action='<TMPL_VAR cginame>?' method='GET'>
+    <form name='form1' action='?' method='GET'>
      <table id='id<TMPL_VAR ID>'></table>
      <button type="submit" class="bp" name='action' title='__Run now__' value='run_job_mod'>
        <img src='/bweb/R.png' alt=''>  __Run now__ </button>
      <table id='id<TMPL_VAR ID>'></table>
      <button type="submit" class="bp" name='action' title='__Run now__' value='run_job_mod'>
        <img src='/bweb/R.png' alt=''>  __Run now__ </button>