From: Eric Bollengier Date: Mon, 11 Apr 2011 14:48:06 +0000 (+0200) Subject: bweb: Add sqlite support X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=802af002b28be54a6a8f49c239ea6337fecb3b5a;p=bacula%2Fbacula bweb: Add sqlite support --- diff --git a/gui/bweb/INSTALL b/gui/bweb/INSTALL index 7c1ae65f13..bd7124a4da 100644 --- a/gui/bweb/INSTALL +++ b/gui/bweb/INSTALL @@ -106,7 +106,9 @@ Click: Main -- you should see the charts ################ 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. @@ -145,8 +147,8 @@ Click: Main -- you should see the charts # 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 #################### @@ -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. -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" @@ -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) + 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 : @@ -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) -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 ################################################################ diff --git a/gui/bweb/cgi/bfileview.pl b/gui/bweb/cgi/bfileview.pl index 23bd23016c..08816c0932 100755 --- a/gui/bweb/cgi/bfileview.pl +++ b/gui/bweb/cgi/bfileview.pl @@ -67,7 +67,6 @@ if ($jobid and $batch eq 'batch') { exit 1; } -print CGI::header('text/html'); $bweb->display_begin(); $bweb->display_job_zoom($jobid); diff --git a/gui/bweb/cgi/bgraph.pl b/gui/bweb/cgi/bgraph.pl index 7407322dba..e75e794195 100755 --- a/gui/bweb/cgi/bgraph.pl +++ b/gui/bweb/cgi/bgraph.pl @@ -6,7 +6,7 @@ use strict; 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 @@ -31,10 +31,6 @@ use strict; (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. -=head1 VERSION - - $Id$ - =cut use Bweb; @@ -148,9 +144,8 @@ if ($gtype eq 'balloon') { $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 @@ -184,7 +179,7 @@ $limitq exit 0; } -print CGI::header('image/png'); +$bweb->send_content_type(-type => 'image/png'); sub get_graph { @@ -291,7 +286,7 @@ if ($graph eq 'job_size') { 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, @@ -330,7 +325,7 @@ if ($graph eq 'job_file') { 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, @@ -372,7 +367,7 @@ elsif ($graph eq 'file_histo' and $arg->{where}) { 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, @@ -423,7 +418,7 @@ elsif ($graph eq 'rep_histo' and $arg->{where}) { $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, @@ -467,14 +462,11 @@ elsif ($graph eq 'job_rate') { 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 / - ($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 @@ -513,12 +505,10 @@ elsif ($graph eq 'job_duration') { 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 @@ -574,12 +564,16 @@ $limitq 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 - " . ($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 @@ -593,7 +587,6 @@ WHERE Job.ClientId = Client.ClientId $groupq $limit "; - print STDERR $query if ($debug); my $obj = get_graph('title' => "Job $t : $arg->{jclients}/$arg->{jjobnames}", diff --git a/gui/bweb/cgi/btime.pl b/gui/bweb/cgi/btime.pl index f264828f79..479a8bf5b7 100755 --- a/gui/bweb/cgi/btime.pl +++ b/gui/bweb/cgi/btime.pl @@ -39,7 +39,6 @@ use strict; use GTime; use Getopt::Long ; use Bweb; -use Time::ParseDate qw/parsedate/; use POSIX qw/strftime/; use CGI; @@ -48,7 +47,6 @@ $conf->load(); my $bweb = new Bweb(info => $conf); -print CGI::header('text/html'); $bweb->display_begin(); $bweb->can_do('r_view_stat'); @@ -216,25 +214,25 @@ foreach my $elt (@$all) # l => $elt->[2], type => "waiting", begin => $begin, - end => parsedate($elt->[1]) - $t, + end => $elt->[1] - $t, }; 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", - begin => parsedate($elt->[1]) - $t, + begin => $elt->[1] - $t, end => $elt->[1], }; push @{$pool->{"$drive: $elt->[4]"}}, { type => "despool", - begin => parsedate($elt->[1]) - $t, + begin => $elt->[1] - $t, end => $elt->[1], }; } else { diff --git a/gui/bweb/cgi/bweb.pl b/gui/bweb/cgi/bweb.pl index 2510111516..08a652e7dc 100755 --- a/gui/bweb/cgi/bweb.pl +++ b/gui/bweb/cgi/bweb.pl @@ -41,27 +41,20 @@ my $client_re = qr/^([\w\d\.-]+)$/; 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); +my $arg = $bweb->get_form('jobid', 'limit', 'offset', 'age', 'new_dir'); # 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; } -my $arg = $bweb->get_form('jobid', 'limit', 'offset', 'age'); - $bweb->display_begin(); # if no configuration, we send edit_conf diff --git a/gui/bweb/html/bweb.js b/gui/bweb/html/bweb.js index de8f5b615c..0bcd098148 100644 --- a/gui/bweb/html/bweb.js +++ b/gui/bweb/html/bweb.js @@ -1,5 +1,5 @@ // 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. // @@ -22,7 +22,7 @@ // 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. @@ -77,6 +77,7 @@ var joblevelname = { 'F': 'Full', 'I': 'Incremental', 'D': 'Differential', + 'B': 'Base' }; @@ -131,24 +132,84 @@ function human_sec(val) 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) { - return val.toFixed(0) + ' hours'; + return val.toFixed(0) + ' hour' + add_s(val) ; } val /= 24; // hour -> day if ((val / 365) < 2) { - return val.toFixed(0) + ' days'; + return val.toFixed(0) + ' day' + add_s(val); } 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; } +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; diff --git a/gui/bweb/lib/Bweb.pm b/gui/bweb/lib/Bweb.pm index 7e51781636..174d3e434b 100644 --- a/gui/bweb/lib/Bweb.pm +++ b/gui/bweb/lib/Bweb.pm @@ -6,7 +6,7 @@ use strict; 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 @@ -68,6 +68,7 @@ sub new my ($class, %arg) = @_; my $self = bless { name => undef, + info => undef, }, $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) = @_; @@ -123,6 +131,22 @@ sub error 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 @@ -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) + It uses the following variables: template_dir lang director + =head2 EXAMPLE $ref = { name => 'me', age => 26 }; @@ -148,8 +174,10 @@ sub error 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", @@ -172,6 +200,7 @@ sub display $template->param('loginname', CGI::remote_user()); $template->param($hash); + $self->send_content_type(); print $template->output(); } 1; @@ -213,7 +242,7 @@ use CGI; =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\.-]*)$!, @@ -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!^(.+)?$!, - 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*$/, + 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 @@ -265,46 +299,15 @@ sub load 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) { - $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 = ) - { - 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; } @@ -972,10 +975,7 @@ SELECT Media.VolumeName AS volumename, 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) @@ -1089,6 +1089,7 @@ sub new 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 } @@ -1296,7 +1297,10 @@ our %sql_func = ( 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) ", @@ -1318,7 +1322,10 @@ our %sql_func = ( 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') ", @@ -1335,6 +1342,31 @@ our %sql_func = ( 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'; @@ -1349,6 +1381,18 @@ sub dbh_is_mysql 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) = @_; @@ -1392,6 +1436,16 @@ sub dbh_do 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) = @_; @@ -1558,14 +1612,14 @@ sub connect_db $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"); - } else { + } elsif ($self->dbh_is_pg()) { $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->{lang} = $self->{info}->{lang}; $self->{template_dir} = $self->{info}->{template_dir}; + my $args = $self->get_form('dir', 'lang'); + $self->set_lang($args->{lang}); + return $self; } @@ -1603,6 +1659,7 @@ sub display_begin if ($self->{info}->{enable_security}) { $self->get_roles(); # get lang } + $self->display($self->{info}, "begin.tpl"); } @@ -1695,17 +1752,16 @@ sub get_limit 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}' - 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}) { - 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}); } @@ -1735,6 +1791,22 @@ sub get_limit 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 @@ -1786,6 +1858,9 @@ sub get_form ); my %opt_ss =( # string with space + name => 1, + dir => 1, + new_dir => 1, job => 1, storage => 1, ); @@ -1830,7 +1905,7 @@ sub get_form 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 @@ -1839,12 +1914,12 @@ sub get_form $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) - my $value = CGI::param($i) || ''; + my $value = get_item($i, ''); 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}) { - my $value = CGI::param($i) || ''; + my $value = get_item($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}) { - 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 - 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; @@ -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}; @@ -1911,7 +1994,7 @@ sub get_form } if ($what{lang}) { - my $lang = CGI::param('lang') || 'en'; + my $lang = get_item('lang', 'en'); 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, - $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) @@ -2190,9 +2270,7 @@ sub help_intern_compute # 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') ) @@ -2207,10 +2285,7 @@ SELECT Media.VolumeName AS volumename, 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) @@ -2432,7 +2507,8 @@ JOIN client_group USING (client_group_id) "; } 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, @@ -2446,10 +2522,9 @@ SELECT Job.JobId AS jobid, 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, @@ -2474,6 +2549,24 @@ SELECT Job.JobId AS jobid, "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 { @@ -2484,7 +2577,8 @@ sub display_job_zoom # 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, @@ -2498,9 +2592,9 @@ SELECT DISTINCT Job.JobId AS jobid, 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) @@ -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.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, - 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) @@ -2608,9 +2699,7 @@ sub display_media 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=" @@ -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, - $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, @@ -2640,7 +2726,6 @@ WHERE Media.PoolId=Pool.PoolId $where $limit "; - 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, - $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 @@ -2878,7 +2960,6 @@ FROM Location "; my $location = $self->dbh_selectall_hashref($query, 'location'); - $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->{lang} = $1; + $self->set_lang($1); } return 1; } @@ -3827,7 +3908,7 @@ sub display_overview 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, @@ -3838,7 +3919,7 @@ FROM ( 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) @@ -4098,9 +4179,7 @@ SELECT Job.JobId AS jobid, 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 @@ -4250,7 +4329,6 @@ sub restore # TODO : make this internal to not eject tape ? use Bconsole; - 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."); } - $log->{logtxt} =~ s/\0//g; + $log->{logtxt} =~ s/(\0|\\,)//g; $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}, - duration => '00:00:00', + duration => 0, jobfiles => 0, jobbytes => 0, joberrors => 0, @@ -4720,8 +4798,10 @@ sub add_media $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}); @@ -4791,7 +4871,7 @@ sub purge 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({ @@ -4814,7 +4894,7 @@ sub prune 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({ @@ -4906,10 +4986,16 @@ sub enable_disable_job }, "command.tpl"); } +sub set_lang +{ + my ($self, $lang) = @_; + $self->{current_lang} = $lang; +} + sub get_bconsole { - my ($self) = @_; - return new Bconsole(pref => $self->{info}); + my ($self, @opts) = @_; + return new Bconsole(pref => $self->{info}, @opts); } sub cmd_storage @@ -4980,7 +5066,7 @@ sub run_job_mod $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"); @@ -5004,7 +5090,7 @@ SELECT Pool.Name AS name 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()]; @@ -5028,8 +5114,10 @@ sub run_job 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"); @@ -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 - fileset job storage/); + fileset job storage comment/); 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}, + comment => $arg->{comment} ); 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)); + $self->debug("checking $job, $job_pool, $client, $type, $schedname"); + my $sch = $sched->get_scheds($schedname); return undef if (!$sch); @@ -5152,7 +5243,7 @@ sub check_job 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, @@ -5182,7 +5273,7 @@ sub display_missing_job 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)) { diff --git a/gui/bweb/lib/GTime.pm b/gui/bweb/lib/GTime.pm index c06745c4cc..8fc818cbd4 100644 --- a/gui/bweb/lib/GTime.pm +++ b/gui/bweb/lib/GTime.pm @@ -84,10 +84,10 @@ sub new map { $self->{$_} = $arg{$_} } keys %arg ; if ($self->{begin}) { - $self->{begin} = parsedate($self->{begin}); + $self->{begin} = $self->{begin}; } if ($self->{end}) { - $self->{end} = parsedate($self->{end}); + $self->{end} = $self->{end}; } bless $self ; @@ -349,20 +349,20 @@ $top->add_job(label => "label", data => [ { type => "init", - begin => $begin1, - end => $end1, + begin => parsedate($begin1), + end => parsedate($end1), }, { type => "write", - begin => $end1, - end => $begin2, + begin => parsedate($end1), + end => parsedate($begin2), }, { type => "commit", - begin => $begin2, - end => $end2, + begin => parsedate($begin2), + end => parsedate($end2), }, ]); @@ -370,20 +370,20 @@ $top->add_job(label => "label2", data => [ { type => "init", - begin => $begin1, - end => $end1, + begin => parsedate($begin1), + end => parsedate($end1), }, { type => "write", - begin => $end1, - end => $begin2, + begin => parsedate($end1), + end => parsedate($begin2), }, { type => "commit", - begin => $begin2, - end => $end2, + begin => parsedate($begin2), + end => parsedate($end2), }, ]); diff --git a/gui/bweb/script/bweb-mysql.sql b/gui/bweb/script/bweb-mysql.sql index 90e8d1d4ba..afbabb8c7e 100644 --- a/gui/bweb/script/bweb-mysql.sql +++ b/gui/bweb/script/bweb-mysql.sql @@ -1,3 +1,9 @@ +-- -------------------------------------------------- +-- Upgrade from 5.0 +-- -------------------------------------------------- + +CREATE UNIQUE INDEX location_idx ON Location (Location(255)); + -- -------------------------------------------------- -- Upgrade from 2.4 -- -------------------------------------------------- diff --git a/gui/bweb/script/bweb-postgresql.sql b/gui/bweb/script/bweb-postgresql.sql index 50f57297c9..3c9aa63027 100644 --- a/gui/bweb/script/bweb-postgresql.sql +++ b/gui/bweb/script/bweb-postgresql.sql @@ -1,6 +1,22 @@ -- 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 -- -------------------------------------------------- diff --git a/gui/bweb/script/httpd.conf b/gui/bweb/script/httpd.conf index 81793bc126..d42ddd877f 100644 --- a/gui/bweb/script/httpd.conf +++ b/gui/bweb/script/httpd.conf @@ -11,9 +11,10 @@ server.port = 9180 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.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/", diff --git a/gui/bweb/script/regress.pl b/gui/bweb/script/regress.pl index a42c791c85..f0206185c1 100755 --- a/gui/bweb/script/regress.pl +++ b/gui/bweb/script/regress.pl @@ -6,7 +6,7 @@ use strict; 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 @@ -34,13 +34,14 @@ use strict; =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 - * 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 diff --git a/gui/bweb/script/tpl_generate.pl b/gui/bweb/script/tpl_generate.pl index bc3f221a00..1765c975a0 100755 --- a/gui/bweb/script/tpl_generate.pl +++ b/gui/bweb/script/tpl_generate.pl @@ -6,7 +6,7 @@ use strict; 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 @@ -37,10 +37,6 @@ use strict; rm -f lang/fr/tpl/*.tpl LANGUAGE=fr ./script/tpl_generate.pl tpl/*.pl -=head1 VERSION - - $Id$ - =cut my $debug=0; @@ -76,6 +72,9 @@ foreach my $f (@ARGV) print "Converting $f -> $out/$file "; while (my $l = ) { +# $l =~ s:bresto.html:bresto.html?dir=:; +# $l =~ s:(href=['"](\w+.pl)?\?):${1}dir=;:g; +# $l =~ s:(
]+>):$1:g; my (@str) = ($l =~ m/__(.+?)__/g); while (my $s = shift @str) { diff --git a/gui/bweb/tpl/ach_content.tpl b/gui/bweb/tpl/ach_content.tpl index 70ede3a689..59f8afe192 100644 --- a/gui/bweb/tpl/ach_content.tpl +++ b/gui/bweb/tpl/ach_content.tpl @@ -72,7 +72,7 @@ human_size(), "", "", "", -"", +timestamp_to_iso(""), chkbox ) ); diff --git a/gui/bweb/tpl/add_media.tpl b/gui/bweb/tpl/add_media.tpl index 15102e3537..99e8562a6c 100644 --- a/gui/bweb/tpl/add_media.tpl +++ b/gui/bweb/tpl/add_media.tpl @@ -34,7 +34,7 @@ diff --git a/gui/bweb/tpl/begin.tpl b/gui/bweb/tpl/begin.tpl index a7399eaf17..8b73fb23f7 100644 --- a/gui/bweb/tpl/begin.tpl +++ b/gui/bweb/tpl/begin.tpl @@ -76,9 +76,12 @@ if ('__Main__' == ('_' + '_Main_' + '_')) {
  • __About__
  • -
  •  __Logged as__
  • +
  •   +__Logged as__ +__on__ +
  • -
  • +
    diff --git a/gui/bweb/tpl/display_job.tpl b/gui/bweb/tpl/display_job.tpl index ef0c25fa0e..8530023dba 100644 --- a/gui/bweb/tpl/display_job.tpl +++ b/gui/bweb/tpl/display_job.tpl @@ -14,14 +14,15 @@ document.getElementById('status_').checked = true; var header = new Array("JobId", "__Client__", - "__Job Name__", + "__Job Name__", + "__Comment__", "__FileSet__", // "__Pool__", "__Level__", "__StartTime__", "__Duration__", "__JobFiles__", - "__JobBytes__", + "__JobBytes__", "__Errors__", "__Status__"); @@ -42,12 +43,13 @@ a.appendChild(img); data.push( new Array( "", "", -"", +"", +"", "", //"", "", "", -"", +human_duration(""), "", human_size(), "", diff --git a/gui/bweb/tpl/display_job_zoom.tpl b/gui/bweb/tpl/display_job_zoom.tpl index 69ec1f9b8a..f8eafd0b6e 100644 --- a/gui/bweb/tpl/display_job_zoom.tpl +++ b/gui/bweb/tpl/display_job_zoom.tpl @@ -1,5 +1,6 @@
    -

    __Information about job__

    +

    __Information about job__ + ()

    @@ -88,6 +89,7 @@ var header = new Array("JobId", "__Duration__", "__JobFiles__", "__JobBytes__", +// "__Comp__", "__Errors__", "__Pool__", "__Volume Name__", @@ -108,9 +110,10 @@ data.push( new Array( "", "", "", -"", +human_duration(""), "", human_size(), +//parseInt(100-100*/(+0.00001), 10) + "%", "", "", "\n", diff --git a/gui/bweb/tpl/display_media.tpl b/gui/bweb/tpl/display_media.tpl index 89adcec886..7487343516 100644 --- a/gui/bweb/tpl/display_media.tpl +++ b/gui/bweb/tpl/display_media.tpl @@ -62,7 +62,7 @@ d, "", "", "", -"", +timestamp_to_iso(""), chkbox ) ); diff --git a/gui/bweb/tpl/display_media_zoom.tpl b/gui/bweb/tpl/display_media_zoom.tpl index 655da33a55..1f676bfb5f 100644 --- a/gui/bweb/tpl/display_media_zoom.tpl +++ b/gui/bweb/tpl/display_media_zoom.tpl @@ -56,7 +56,7 @@ human_enabled(""), "", "", human_size(), -"", +timestamp_to_iso(""), human_sec(), human_sec(), "" diff --git a/gui/bweb/tpl/help_extern_compute.tpl b/gui/bweb/tpl/help_extern_compute.tpl index dc9be23886..f679201f5f 100644 --- a/gui/bweb/tpl/help_extern_compute.tpl +++ b/gui/bweb/tpl/help_extern_compute.tpl @@ -37,7 +37,7 @@ data.push( new Array( "", "", "", -"", +timestamp_to_iso(""), chkbox ) ); diff --git a/gui/bweb/tpl/help_intern_compute.tpl b/gui/bweb/tpl/help_intern_compute.tpl index 1ad308c530..41cc9f228d 100644 --- a/gui/bweb/tpl/help_intern_compute.tpl +++ b/gui/bweb/tpl/help_intern_compute.tpl @@ -39,7 +39,7 @@ data.push( new Array( "", "", "", -"", +timestamp_to_iso(""), chkbox ) ); diff --git a/gui/bweb/tpl/run_job_mod.tpl b/gui/bweb/tpl/run_job_mod.tpl index 8ba90c7a7c..8a42aa4053 100644 --- a/gui/bweb/tpl/run_job_mod.tpl +++ b/gui/bweb/tpl/run_job_mod.tpl @@ -57,7 +57,11 @@ + + __Comment:__ + __Start Time:__ ", joblevel[''], "", -"", +human_sec2(""), //"", //"", a, diff --git a/gui/bweb/tpl/scheduled_job.tpl b/gui/bweb/tpl/scheduled_job.tpl index c76ab7703d..ed8f5b7962 100644 --- a/gui/bweb/tpl/scheduled_job.tpl +++ b/gui/bweb/tpl/scheduled_job.tpl @@ -3,7 +3,7 @@

    __Next Jobs__

    - +