#!/usr/bin/perl -w
-
+use strict;
my $bresto_enable = 1;
die "bresto is not enabled" if (not $bresto_enable);
) 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);
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
# 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),
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})
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;
$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+)$/) {
}
$bvfs->ch_dir($pathid);
+#print STDERR "pathid=$pathid\n";
+
# permit to use a regex filter
if ($args->{qpattern}) {
$bvfs->set_pattern($args->{qpattern});
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'],
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) {
}
if ($table) {
- $bvfs->dbh_do("DROP TABLE $table");
+ #$bvfs->dbh_do("DROP TABLE $table");
}
}
// 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
// TODO: fichier ou rep
function rd_file_or_dir(val)
{
- if (val == 'F') {
- return '<img src="A.png">';
+ if (val > 0) {
+ return '<img src="file_f.png">';
} else {
- return '<img src="R.png">';
+ return '<img src="file_d.png">';
}
}
+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
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)
{
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})
});
{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',
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) {
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})
});
});
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() {
}
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})
});
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})
});
* 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',
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
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',
},
'->', // 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',
if (data.selections) {
if (data.grid.id == 'div-files') {
for(var i=0;i<data.selections.length;i++) {
+ var name = data.selections[i].json[4];
+ var fnid = data.selections[i].json[1];
+ if (fnid == 0 && name != '..') {
+ name = name + '/';
+ }
r = new file_selection_record({
jobid: data.selections[0].json[3],
fileid: data.selections[i].json[0],
filenameid:data.selections[i].json[1],
pathid: data.selections[i].json[2],
- name: Ext.brestore.path + data.selections[i].json[4],
+ name: Ext.brestore.path + ((name=='..')?'':name),
size: data.selections[i].json[5],
mtime: data.selections[i].json[6]
});
}
function reload_media_store() {
+ Ext.brestore.media_store.removeAll();
var items = file_selection_store.data.items;
var tab_fileid=new Array();
var tab_dirid=new Array();