From: Eric Bollengier Date: Tue, 21 Jul 2009 17:51:24 +0000 (+0000) Subject: Merge branch 'bwebII' X-Git-Tag: Release-5.0.0~483 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=99887158e27f5ab209ff0964114fa7bbce148017;p=bacula%2Fbacula Merge branch 'bwebII' git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@9079 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/gui/bweb/cgi/bresto.pl b/gui/bweb/cgi/bresto.pl index 3d3adab9cf..a22d0a82e1 100755 --- a/gui/bweb/cgi/bresto.pl +++ b/gui/bweb/cgi/bresto.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -w - +use strict; my $bresto_enable = 1; die "bresto is not enabled" if (not $bresto_enable); @@ -373,7 +373,7 @@ sub ls_files ) AS listfiles WHERE File.FileId = listfiles.id"; - print STDERR $query; +# print STDERR $query; $self->debug($query); my $result = $self->dbh_selectall_arrayref($query); $self->debug($result); @@ -381,6 +381,68 @@ WHERE File.FileId = listfiles.id"; return $result; } +sub ls_special_dirs +{ + my ($self) = @_; + return undef unless ($self->{curjobids}); + + my $pathid = $self->{cwdid}; + my $jobclause = $self->{curjobids}; + my $dir_filenameid = $self->get_dir_filenameid(); + + my $sq1 = +"((SELECT PPathId AS PathId, '..' AS Path + FROM brestore_pathhierarchy + WHERE PathId = $pathid) +UNION + (SELECT $pathid AS PathId, '.' AS Path))"; + + my $sq2 = " +SELECT tmp.PathId, tmp.Path, Lstat, JobId + FROM $sq1 AS tmp LEFT JOIN ( -- get attributes if any + SELECT File1.PathId, File1.JobId, File1.Lstat FROM File AS File1 + WHERE File1.FilenameId = $dir_filenameid + AND File1.JobId IN ($jobclause)) AS listfile1 + ON (tmp.PathId = listfile1.PathId) + ORDER BY tmp.Path, JobId DESC +"; + + my $result = $self->dbh_selectall_arrayref($sq2); + + my @return_list; + my $prev_dir=''; + foreach my $refrow (@{$result}) + { + my $dirid = $refrow->[0]; + my $dir = $refrow->[1]; + my $lstat = $refrow->[3]; + my $jobid = $refrow->[2] || 0; + next if ($dirid eq $prev_dir); + my @return_array = ($dirid,$dir,$lstat,$jobid); + push @return_list,(\@return_array); + $prev_dir = $dirid; + } + + return \@return_list; +} + +# Let's retrieve the list of the visible dirs in this dir ... +# First, I need the empty filenameid to locate efficiently +# the dirs in the file table +sub get_dir_filenameid +{ + my ($self) = @_; + if ($self->{dir_filenameid}) { + return $self->{dir_filenameid}; + } + my $query = "SELECT FilenameId FROM Filename WHERE Name = ''"; + my $sth = $self->dbh_prepare($query); + $sth->execute(); + my $result = $sth->fetchrow_arrayref(); + $sth->finish(); + return $self->{dir_filenameid} = $result->[0]; +} + # list all directories in a directory, accross curjobids # return ($dirid,$dir_basename,$lstat,$jobid) sub ls_dirs @@ -395,15 +457,10 @@ sub ls_dirs # Let's retrieve the list of the visible dirs in this dir ... # First, I need the empty filenameid to locate efficiently # the dirs in the file table - my $query = "SELECT FilenameId FROM Filename WHERE Name = ''"; - my $sth = $self->dbh_prepare($query); - $sth->execute(); - my $result = $sth->fetchrow_arrayref(); - $sth->finish(); - my $dir_filenameid = $result->[0]; + my $dir_filenameid = $self->get_dir_filenameid(); # Then we get all the dir entries from File ... - $query = " + my $query = " SELECT PathId, Path, JobId, Lstat FROM ( SELECT Path1.PathId, Path1.Path, lower(Path1.Path), @@ -418,18 +475,18 @@ SELECT PathId, Path, JobId, Lstat FROM ( WHERE brestore_pathhierarchy1.PPathId = $pathid AND brestore_pathvisibility1.jobid IN ($jobclause)) AS listpath1 JOIN Path AS Path1 ON (listpath1.PathId = Path1.PathId) - LEFT JOIN ( + + LEFT JOIN ( -- get attributes if any SELECT File1.PathId, File1.JobId, File1.Lstat FROM File AS File1 WHERE File1.FilenameId = $dir_filenameid AND File1.JobId IN ($jobclause)) AS listfile1 ON (listpath1.PathId = listfile1.PathId) ) AS A ORDER BY 2,3 DESC LIMIT $self->{limit} OFFSET $self->{offset} "; - $self->debug($query); - print STDERR $query; - $sth=$self->dbh_prepare($query); +# print STDERR $query; + my $sth=$self->dbh_prepare($query); $sth->execute(); - $result = $sth->fetchall_arrayref(); + my $result = $sth->fetchall_arrayref(); my @return_list; my $prev_dir=''; foreach my $refrow (@{$result}) @@ -836,7 +893,8 @@ sub fill_table_for_restore my $FileId = CGI::param('force')?",FileId":""; my $fileid = join(',', grep { /^\d+$/ } CGI::param('fileid')); - my @dirid = grep { /^\d+$/ } CGI::param('dirid'); + # can get dirid=("10,11", 10, 11) + my @dirid = grep { /^\d+$/ } map { split(/,/) } CGI::param('dirid') ; my $inclause = join(',', @jobid); my @union; @@ -952,7 +1010,7 @@ if (CGI::param('init')) { # used when choosing a job $bvfs->update_brestore_table(@jobid); } -my $pathid = CGI::param('node') || ''; +my $pathid = CGI::param('node') || CGI::param('pathid') || ''; my $path = CGI::param('path'); if ($pathid =~ /^(\d+)$/) { @@ -964,6 +1022,8 @@ if ($pathid =~ /^(\d+)$/) { } $bvfs->ch_dir($pathid); +#print STDERR "pathid=$pathid\n"; + # permit to use a regex filter if ($args->{qpattern}) { $bvfs->set_pattern($args->{qpattern}); @@ -1010,13 +1070,71 @@ if ($action eq 'restore') { sub escape_quote { my ($str) = @_; + if (!$str) { + return ''; + } $str =~ s/'/\\'/g; return $str; } print CGI::header('application/x-javascript'); -if ($action eq 'list_files') { + +if ($action eq 'list_files_dirs') { +# fileid, filenameid, pathid, jobid, name, size, mtime + my $jids = join(",", @jobid); + + my $files = $bvfs->ls_special_dirs(); + # return ($dirid,$dir_basename,$lstat,$jobid) + print "[\n"; + print join(',', + map { my @p=Bvfs::parse_lstat($_->[3]); + '[' . join(',', + 0, # fileid + 0, # filenameid + $_->[0], # pathid + "'$jids'", # jobid + "'" . escape_quote($_->[1]) . "'", # name + "'" . $p[7] . "'", # size + "'" . strftime('%Y-%m-%d %H:%m:%S', localtime($p[11])) . "'") . + ']'; + } @$files); + + print "," if (@$files); + + $files = $bvfs->ls_dirs(); + # return ($dirid,$dir_basename,$lstat,$jobid) + print join(',', + map { my @p=Bvfs::parse_lstat($_->[3]); + '[' . join(',', + 0, # fileid + 0, # filenameid + $_->[0], # pathid + "'$jids'", # jobid + "'" . escape_quote($_->[1]) . "'", # name + "'" . $p[7] . "'", # size + "'" . strftime('%Y-%m-%d %H:%m:%S', localtime($p[11])) . "'") . + ']'; + } @$files); + + print "," if (@$files); + + $files = $bvfs->ls_files(); + print join(',', + map { my @p=Bvfs::parse_lstat($_->[3]); + '[' . join(',', + $_->[1], + $_->[0], + $pathid, + $_->[4], + "'" . escape_quote($_->[2]) . "'", + "'" . $p[7] . "'", + "'" . strftime('%Y-%m-%d %H:%m:%S', localtime($p[11])) . "'") . + ']'; + } @$files); + print "]\n"; + +} elsif ($action eq 'list_files') { print "[[0,0,0,0,'.',4096,'1970-01-01 00:00:00'],"; my $files = $bvfs->ls_files(); # [ 1, 2, 3, "Bill", 10, '2007-01-01 00:00:00'], @@ -1072,6 +1190,7 @@ if ($action eq 'list_files') { my $lst; # in this mode, we compute the result to get all needed media +# print STDERR "force=", CGI::param('force'), "\n"; if (CGI::param('force')) { $table = fill_table_for_restore(@jobid); if (!$table) { @@ -1095,7 +1214,7 @@ if ($action eq 'list_files') { } if ($table) { - $bvfs->dbh_do("DROP TABLE $table"); + #$bvfs->dbh_do("DROP TABLE $table"); } } diff --git a/gui/bweb/html/bresto.js b/gui/bweb/html/bresto.js index eec51c438e..c7c0e47e55 100644 --- a/gui/bweb/html/bresto.js +++ b/gui/bweb/html/bresto.js @@ -1,7 +1,7 @@ // Bweb - A Bacula web interface // Bacula® - The Network Backup Solution // -// Copyright (C) 2000-2008 Free Software Foundation Europe e.V. +// Copyright (C) 2000-2009 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 @@ -36,13 +36,42 @@ function rd_vol_is_online(val) // TODO: fichier ou rep function rd_file_or_dir(val) { - if (val == 'F') { - return ''; + if (val > 0) { + return ''; } else { - return ''; + return ''; } } +function push_path() +{ + Ext.brestore.path_stack.push(Ext.brestore.path); + Ext.brestore.pathid_stack.push(Ext.brestore.pathid); + Ext.ComponentMgr.get('prevbp').enable(); +} +function pop_path() +{ + var pathid = Ext.brestore.pathid_stack.pop(); + var path = Ext.brestore.path_stack.pop(); + if (!pathid) { + Ext.ComponentMgr.get('prevbp').disable(); + return false; + } + Ext.ComponentMgr.get('wherefield').setValue(path); + + Ext.brestore.pathid = pathid; + Ext.brestore.path = path; + return true; +} + +function dirname(path) { + var a = path.match( /(^.*\/).+\// ); + if (a) { + return a[1]; + } + return path; +} + Ext.namespace('Ext.brestore'); Ext.brestore.jobid=0; // selected jobid Ext.brestore.jobdate=''; // selected date @@ -59,9 +88,11 @@ Ext.brestore.option_vcopies = false; Ext.brestore.dlglaunch; Ext.brestore.fpattern; Ext.brestore.use_filerelocation=false; -Ext.brestore.limit = 2000; +Ext.brestore.limit = 500; Ext.brestore.offset = 0; Ext.brestore.force_reload = 0; +Ext.brestore.path_stack = Array(); +Ext.brestore.pathid_stack = Array(); function get_node_path(node) { @@ -144,13 +175,15 @@ Ext.onReady(function(){ Ext.brestore.tree = root; // shortcut var click_cb = function(node, event) { + push_path(); + Ext.brestore.path = get_node_path(node); Ext.brestore.pathid = node.id; Ext.brestore.offset=0; Ext.brestore.fpattern = Ext.get('txt-file-pattern').getValue(); where_field.setValue(Ext.brestore.path); update_limits(); - file_store.load({params:init_params({action: 'list_files', + file_store.load({params:init_params({action: 'list_files_dirs', path:Ext.brestore.path, node:node.id}) }); @@ -188,11 +221,20 @@ Ext.onReady(function(){ {name: 'jobid' }, {name: 'name' }, {name: 'size', type: 'int' }, - {name: 'mtime', type: 'date', dateFormat: 'Y-m-d h:i:s'} + {name: 'mtime', type: 'date', dateFormat: 'Y-m-d h:i:s'}, + {name: 'type'} ])) }); + Ext.brestore.file_store=file_store; var cm = new Ext.grid.ColumnModel([{ + id: 'type', + header: 'Type', + dataIndex: 'filenameid', + width: 30, + css: 'white-space:normal;', + renderer: rd_file_or_dir + },{ id: 'cm-id', // id assigned so we can apply custom css // (e.g. .x-grid-col-topic b { color:#333 }) header: 'File', @@ -251,7 +293,7 @@ Ext.onReady(function(){ var file_paging_next = new Ext.Toolbar.Button({ id: 'bp-file-next', - icon: '/bweb/ext/resources/images/default/grid/page-next.gif', + icon: 'ext/resources/images/default/grid/page-next.gif', cls: '.x-btn-icon', tooltip: 'Next', handler: function(a,b,c) { @@ -260,7 +302,7 @@ Ext.onReady(function(){ Ext.brestore.offset += Ext.brestore.limit; file_store.removeAll(); file_versions_store.removeAll(); - file_store.load({params:init_params({action: 'list_files', + file_store.load({params:init_params({action: 'list_files_dirs', path:Ext.brestore.path, node:Ext.brestore.pathid}) }); @@ -269,7 +311,7 @@ Ext.onReady(function(){ }); var file_paging_prev = new Ext.Toolbar.Button({ id: 'bp-file-prev', - icon: '/bweb/ext/resources/images/default/grid/page-prev.gif', + icon: 'ext/resources/images/default/grid/page-prev.gif', cls: '.x-btn-icon', tooltip: 'Last', handler: function() { @@ -281,7 +323,7 @@ Ext.onReady(function(){ } file_store.removeAll(); file_versions_store.removeAll(); - file_store.load({params:init_params({action: 'list_files', + file_store.load({params:init_params({action: 'list_files_dirs', path:Ext.brestore.path, node:Ext.brestore.pathid}) }); @@ -323,14 +365,14 @@ Ext.onReady(function(){ value: Ext.brestore.limit }, file_paging_next, '->', file_paging_pattern, { id: 'bp-file-match', - icon: '/bweb/ext/resources/images/default/grid/refresh.gif', + icon: 'ext/resources/images/default/grid/refresh.gif', cls: '.x-btn-icon', tooltip: 'Refresh', handler: function(a,b,c) { update_user_limits(); file_store.removeAll(); file_versions_store.removeAll(); - file_store.load({params:init_params({action: 'list_files', + file_store.load({params:init_params({action: 'list_files_dirs', path:Ext.brestore.path, node:Ext.brestore.pathid}) }); @@ -390,11 +432,38 @@ Ext.onReady(function(){ * console.info('Store count = ', store.getCount()); * }); */ + file_grid.on('celldblclick', function(e) { + var r = e.selModel.getSelected(); + + if (r.json[1] == 0) { // select a directory + push_path(); + + if (r.json[4] == '..') { + Ext.brestore.path = dirname(Ext.brestore.path); + } else if (r.json[4] == '/') { + Ext.brestore.path = '/'; + } else if (r.json[4] != '.') { + Ext.brestore.path = Ext.brestore.path + r.json[4] + '/'; + } + Ext.brestore.pathid = r.json[2]; + Ext.brestore.filename = ''; + Ext.brestore.offset=0; + Ext.brestore.fpattern = Ext.get('txt-file-pattern').getValue(); + where_field.setValue(Ext.brestore.path); + update_limits(); + file_store.load({params:init_params({action: 'list_files_dirs', + path:Ext.brestore.path, + node:Ext.brestore.pathid}) + }); + } + return true; + }); // TODO: selection only when using dblclick file_grid.selModel.on('rowselect', function(e,i,r) { - if (r.json[4] == '.') { - return true; + if (r.json[1] == 0) { // select a directory + return true; } + Ext.brestore.filename = r.json[4]; file_versions_store.load({ params:init_params({action: 'list_versions', @@ -686,14 +755,19 @@ Ext.onReady(function(){ job_combo.on('select', function(e,c) { Ext.brestore.jobid = c.json[0]; Ext.brestore.jobdate = c.json[1]; - Ext.brestore.root_path=''; root.setText("Root"); tree_loader.baseParams = init_params({init:1, action: 'list_dirs'}); root.reload(); + + file_store.load({params:init_params({action: 'list_files_dirs', + path:Ext.brestore.path, + node:Ext.brestore.pathid}) + }); }); var where_field = new Ext.form.TextField({ fieldLabel: 'Location', + id: 'wherefield', name: 'where', width:275, allowBlank:false @@ -741,6 +815,24 @@ Ext.onReady(function(){ client_combo, job_combo, '-', + { + id: 'prevbp', + cls: 'x-btn-icon', + icon: 'prev.png', + disabled: true, + handler: function() { + if (!pop_path()) { + return; + } + Ext.brestore.offset=0; + update_limits(); + file_store.load({params:init_params({action: 'list_files_dirs', + node:Ext.brestore.pathid}) + }); + + } + + }, { text: 'Change location', cls:'x-btn-text-icon', @@ -771,7 +863,7 @@ Ext.onReady(function(){ }, '->', // Fill { // TODO: put this button on south panel - icon: '/bweb/mR.png', // icons can also be specified inline + icon: 'mR.png', // icons can also be specified inline cls: 'x-btn-text-icon', tooltip: 'Run restore', text: 'Run restore', @@ -851,12 +943,17 @@ Ext.onReady(function(){ if (data.selections) { if (data.grid.id == 'div-files') { for(var i=0;i