mirror of
https://github.com/unraid/webgui.git
synced 2026-01-01 23:20:35 -06:00
354 lines
13 KiB
Plaintext
354 lines
13 KiB
Plaintext
Menu="Buttons:3a"
|
|
Title="File Manager"
|
|
Icon="icon-u-duplicate"
|
|
Code="e963"
|
|
---
|
|
<?PHP
|
|
/* Copyright 2005-2025, Lime Technology
|
|
* Copyright 2012-2025, Bergware International.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License version 2,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*/
|
|
?>
|
|
<?
|
|
$dfm = [
|
|
'browser' => $myPage['name'] == 'Browse',
|
|
'running' => file_exists('/var/tmp/file.manager.active'),
|
|
'jobs' => file_exists('/var/tmp/file.manager.jobs'),
|
|
'zfs' => is_executable('/usr/sbin/zfs')
|
|
];
|
|
if ($dfm['running'] || $dfm['browser']) eval('?>'.parse_file("$docroot/webGui/include/Templates.php"));
|
|
?>
|
|
<script>
|
|
function BrowseButton() {
|
|
location.replace('/<?=$task?>/Browse?dir=/mnt');
|
|
}
|
|
|
|
// Prototypes
|
|
String.prototype.dfm_patch = function(){return this.replace('rw','x+rw').replace('r-','wx+r').replace('--','rwx');}
|
|
String.prototype.dfm_proxy = function(){return this.replace('name','row');}
|
|
String.prototype.dfm_fetch = function(tag){return this.replace('check',tag);}
|
|
String.prototype.dfm_bring = function(tag){return this.replace('row',tag);}
|
|
String.prototype.dfm_strip = function(){return this.replace(/\/$/,'');}
|
|
String.prototype.dfm_quote = function(){return this.replace(/"/g,'"');}
|
|
String.prototype.dfm_alter = function(...a){var t=this;for(var i=0;i<a.length;i+=2){t=t.replace(a[i],a[i+1]);} return t;}
|
|
String.prototype.dfm_build = function(){return this.replace(/\n(<!--!|!-->)\n/g,'');}
|
|
String.prototype.dfm_wedge = function(len){len=len||70;return this.length<=len ? this : this.slice(0,Math.round(len/2)-2)+'...'+this.slice(-1-Math.round(len/2));}
|
|
|
|
// General variables
|
|
const dfm = {window:null, dialog:false, running:false, previous:'', height:0, tsize:{0:0,1:6,2:3,3:3,4:3,11:2,12:2,14:0,15:3}};
|
|
var dfm_read = {};
|
|
|
|
function dfm_footer(action, text) {
|
|
switch (action) {
|
|
case 'show':
|
|
$('#user-notice').show();
|
|
break;
|
|
case 'hide':
|
|
$('#user-notice').hide();
|
|
break;
|
|
case 'write':
|
|
let icon = '<a class="hand" onclick="dfm_openDialog(true)" title="_(File Manager)_"><i class="icon-u-duplicate dfm"></i></a>';
|
|
$('#user-notice').html(icon + text);
|
|
break;
|
|
case 'clear':
|
|
$('#user-notice').html('');
|
|
break;
|
|
}
|
|
}
|
|
|
|
function dfm_done() {
|
|
dfm_footer('write', "<i class='fa fa-circle-thin dfm'></i>_(Searching)_... _(Done)_");
|
|
}
|
|
|
|
function dfm_minimize() {
|
|
dfm.window.dialog('close');
|
|
dfm_footer('show');
|
|
}
|
|
|
|
function dfm_close_button() {
|
|
$('.ui-dfm .ui-dialog-titlebar-close').html('<i class="fa fa-window-minimize"></i>').prop({'title':"_(Minimize)_"}).prop('onclick',null).off('click').click(function(){dfm_minimize();}).show();
|
|
}
|
|
|
|
function dfm_htmlspecialchars(text) {
|
|
var map = {'&':'&','<':'<','>':'>','"':'"',"'":'''};
|
|
return text.replace(/[&<>"']/g, function(m){return map[m];});
|
|
}
|
|
|
|
function dfm_escapeHTML(name) {
|
|
const data = document.createElement('div');
|
|
const text = document.createTextNode(name);
|
|
data.appendChild(text);
|
|
return data.innerHTML;
|
|
}
|
|
|
|
function dfm_createSource(source) {
|
|
var select = dfm.window.find('#dfm_source');
|
|
if (Array.isArray(source)) {
|
|
for (var i=0,object; object=source[i]; i++) {
|
|
if (i < 10) {
|
|
select.html(select.html()+'<option'+(i==0?' selected':'')+'>'+object+'</option>');
|
|
} else {
|
|
select.html(select.html()+'<option><_(more)_> ...</option>');
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
select.html('<option selected>'+source+'</option>');
|
|
}
|
|
}
|
|
|
|
function dfm_showProgress(data) {
|
|
if (!data) return 0;
|
|
let file = null;
|
|
let text = data.split('\n');
|
|
let line = text[0].split('... ');
|
|
let strict = /^mnt|^boot/;
|
|
let footer = false;
|
|
if (text[0] == '#cat#') {
|
|
let loc = [], cat = [];
|
|
for (let i=1,row; row=text[i]; i++) {
|
|
if (!row) continue;
|
|
row = row.split('\0');
|
|
loc.push(row[0]);
|
|
cat.push(row[1].dfm_wedge(80));
|
|
}
|
|
if (cat.length > 0) {
|
|
dfm.window.find('.dfm_loc').html(loc.join('<br>'));
|
|
dfm.window.find('.dfm_text').html(cat.join('<br>'));
|
|
dfm.window.find('#dfm_files').html(loc.length+" "+"_(files)_");
|
|
}
|
|
return cat.length;
|
|
} else if (text.length == 1) {
|
|
text = text[0].dfm_wedge(80);
|
|
footer = text.indexOf("_(Searching)_") != -1;
|
|
} else {
|
|
if (strict.test(text[1])) {
|
|
file = text[1];
|
|
text = dfm.previous;
|
|
} else {
|
|
file = line[1];
|
|
text = text[1].split(/\s+/);
|
|
text = "<i class='fa fa-circle-o-notch fa-spin dfm'></i>_(Completed)_: "+text[1]+", _(Speed)_: "+text[2]+", _(ETA)_: "+text[3];
|
|
dfm.previous = text;
|
|
footer = true;
|
|
}
|
|
}
|
|
if (file == null || strict.test(file)) dfm.window.find('.dfm_text').html((file?line[0]+'... /'+dfm_escapeHTML(file.dfm_wedge())+'<br>':'')+text);
|
|
if (footer) dfm_footer('write',text);
|
|
return 0;
|
|
}
|
|
|
|
function dfm_fileManager(action) {
|
|
switch (action) {
|
|
case 'start':
|
|
$('.ui-dfm .ui-dialog-buttonset button:lt(2)').prop('disabled',true);
|
|
<?if ($dfm['browser']):?>
|
|
$('.dfm_control').prop('disabled',true);
|
|
$('.dfm_control.jobs').prop('disabled',$.cookie('dfm_control.jobs')?false:true);
|
|
<?endif;?>
|
|
if (!dfm.running) nchan_filemanager.start();
|
|
dfm.running = true;
|
|
break;
|
|
case 'stop':
|
|
if (dfm.running) nchan_filemanager.stop();
|
|
<?if ($dfm['browser']):?>
|
|
dfm.window.find('.dfm_text').removeClass('orange-text').html('');
|
|
$('.dfm_control.basic').prop('disabled',false);
|
|
$('.dfm_control.common').prop('disabled',$.cookie('dfm_control.common')?true:false);
|
|
<?endif;?>
|
|
dfm_footer('clear');
|
|
dfm.running = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
function dfm_makeDialog(open) {
|
|
if (open && dfm_read.action == 15) {
|
|
dfm.window.dialog('open');
|
|
dfm_footer('hide');
|
|
return;
|
|
}
|
|
dfm.window = $('#dfm_dialogWindow');
|
|
if (dfm.window.dialog('instance') !== undefined) dfm.dialog = dfm.window.dialog('isOpen');
|
|
var dfm_source = dfm_read.source.split('\r').slice(0,9);
|
|
switch (dfm_read.action) {
|
|
case 0: // create folder/object
|
|
dfm.window.html($('#dfm_templateCreateFolder').html());
|
|
dfm.height = 330;
|
|
break;
|
|
case 1: // delete folder/object
|
|
dfm.window.html($('#dfm_templateDeleteFolder').html());
|
|
dfm.height = 330;
|
|
break;
|
|
case 2: // rename folder/object
|
|
dfm.window.html($('#dfm_templateRenameFolder').html());
|
|
dfm.window.find('#dfm_target').val(dfm_read.target.strip().split('/').pop());
|
|
dfm.height = 330;
|
|
break;
|
|
case 3: // copy folder/object
|
|
dfm.window.html($('#dfm_templateCopyFolder').html());
|
|
dfm.window.find('#dfm_target').val(dfm_read.target).prop('disabled',true);
|
|
dfm.window.find('#dfm_sparse').prop('checked',dfm_read.sparse ? true : false);
|
|
dfm.window.find('#dfm_exist').prop('checked',dfm_read.exist ? false : true);
|
|
dfm.height = 630;
|
|
break;
|
|
case 4: // move folder/object (rsync)
|
|
case 5: // move folder/object (mv)
|
|
dfm.window.html($('#dfm_templateMoveFolder').html());
|
|
dfm.window.find('#dfm_target').val(dfm_read.target).prop('disabled',true);
|
|
dfm.window.find('#dfm_sparse').prop('checked',dfm_read.sparse ? true : false);
|
|
dfm.window.find('#dfm_exist').prop('checked',dfm_read.exist ? false : true);
|
|
dfm.height = 630;
|
|
break;
|
|
case 6: // delete file
|
|
dfm.window.html($('#dfm_templateDeleteFile').html());
|
|
dfm.height = 330;
|
|
break;
|
|
case 8: // copy file
|
|
dfm.window.html($('#dfm_templateCopyFile').html());
|
|
dfm.window.find('#dfm_target').val(dfm_read.target).prop('disabled',true);
|
|
dfm.window.find('#dfm_sparse').prop('checked',dfm_read.sparse ? true : false);
|
|
dfm.window.find('#dfm_exist').prop('checked',dfm_read.exist ? false : true);
|
|
dfm.height = 630;
|
|
break;
|
|
case 9: // move file (rsync)
|
|
case 10: // move file (mv)
|
|
dfm.window.html($('#dfm_templateMoveFile').html());
|
|
dfm.window.find('#dfm_target').val(dfm_read.target).prop('disabled',true);
|
|
dfm.window.find('#dfm_sparse').prop('checked',dfm_read.sparse ? true :false);
|
|
dfm.window.find('#dfm_exist').prop('checked',dfm_read.exist ? false : true);
|
|
dfm.height = 630;
|
|
break;
|
|
case 11: // change owner
|
|
dfm.window.html($('#dfm_templateChangeOwner').html());
|
|
dfm.window.find('#dfm_target').prop('disabled',true);
|
|
dfm.height = 330;
|
|
break;
|
|
case 12: // change permission
|
|
dfm.window.html($('#dfm_templateChangePermission').html());
|
|
dfm.window.find('#dfm_owner').prop('disabled',true);
|
|
dfm.window.find('#dfm_group').prop('disabled',true);
|
|
dfm.window.find('#dfm_other').prop('disabled',true);
|
|
dfm.height = 330;
|
|
break;
|
|
case 15: // search
|
|
dfm.window.html($('#dfm_templateSearch').html());
|
|
dfm.window.find('#dfm_target').val(dfm_read.target).prop('disabled',true);
|
|
dfm.window.find('.dfm_loc').html(' ').css({'line-height':'normal'});
|
|
dfm.window.find('.dfm_text').html('').css({'line-height':'normal'});
|
|
dfm.height = 630;
|
|
break;
|
|
}
|
|
dfm.window.find('#dfm_source').attr('size',Math.min(dfm.tsize[dfm_read.action],dfm_source.length));
|
|
dfm_createSource(dfm_source);
|
|
dfm.window.find('#dfm_sparse').prop('disabled',true);
|
|
dfm.window.find('#dfm_exist').prop('disabled',true);
|
|
dfm.window.find('.dfm_sparse').css({'opacity':'0.5'});
|
|
dfm.window.find('.dfm_exist').css({'opacity':'0.5'});
|
|
dfm.window.dialog({
|
|
classes: {'ui-dialog': 'ui-dfm'},
|
|
autoOpen: open || dfm.dialog,
|
|
title: dfm_read.title,
|
|
height: dfm.height,
|
|
width: 900,
|
|
resizable: false,
|
|
modal: true,
|
|
buttons: {
|
|
"_(Start)_": function(){
|
|
if (dfm_read.action == 15) {
|
|
var dfm_target = dfm.window.find('#dfm_target').val();
|
|
dfm.window.find('.dfm_loc').html(' ');
|
|
dfm.window.find('.dfm_text').html("_(Running)_...");
|
|
dfm_footer('hide');
|
|
dfm_fileManager('start');
|
|
$.post('/webGui/include/Control.php',{mode:'file',action:15,title:encodeURIComponent(dfm_read.title),source:encodeURIComponent(dfm_read.source),target:encodeURIComponent(dfm_target),hdlink:'',sparse:'',exist:'',zfs:''});
|
|
} else {
|
|
return;
|
|
}
|
|
},
|
|
"_(Queue)_": function(){
|
|
return;
|
|
},
|
|
"_(Cancel)_": function(){
|
|
dfm_fileManager('stop');
|
|
dfm.window.dialog('destroy');
|
|
$.post('/webGui/include/Control.php',{mode:'file',action:99},function(){<?if ($dfm['browser']):?>setTimeout(loadList,500);<?endif;?>});
|
|
}
|
|
}
|
|
});
|
|
dfm_close_button();
|
|
$('.ui-dfm .ui-dialog-buttonset button:lt(2)').prop('disabled',true);
|
|
setTimeout(function(){$('.ui-dfm .ui-dialog-buttonset button:eq(2)').focus();});
|
|
if (open||dfm.dialog) dfm_footer('hide'); else dfm_footer('show');
|
|
}
|
|
|
|
function dfm_openDialog(open) {
|
|
$.post('/webGui/include/Control.php',{mode:'read'},function(data){
|
|
if (data) {
|
|
dfm_read = JSON.parse(data);
|
|
dfm_read.action = parseInt(dfm_read.action);
|
|
}
|
|
dfm_makeDialog(open);
|
|
});
|
|
}
|
|
|
|
var nchan_filemanager = new NchanSubscriber('/sub/filemanager',{subscriber:'websocket'});
|
|
nchan_filemanager.on('message', function(msg) {
|
|
let data = $.parseJSON(msg);
|
|
if (data.error) {
|
|
dfm_fileManager('stop');
|
|
dfm.window.find('.dfm_text').addClass('orange-text').html(data.error);
|
|
dfm.window.find('#dfm_target').prop('disabled',false);
|
|
dfm.window.find('#dfm_sparse').prop('disabled',false);
|
|
dfm.window.find('#dfm_exist').prop('disabled',false);
|
|
dfm.window.find('#dfm_owner').prop('disabled',false);
|
|
dfm.window.find('#dfm_group').prop('disabled',false);
|
|
dfm.window.find('#dfm_other').prop('disabled',false);
|
|
$('.ui-dfm .ui-dialog-buttonset button:lt(2)').prop('disabled',false);
|
|
} else {
|
|
let cat = dfm_showProgress(data.status);
|
|
if (data.done == 1) {
|
|
setTimeout(function(){$.post('/webGui/include/Control.php',{mode:'start'},function(queue){
|
|
switch (parseInt(queue)) {
|
|
case 0:
|
|
dfm_fileManager('stop');
|
|
dfm.window.dialog('destroy');
|
|
<?if ($dfm['browser']):?>
|
|
setTimeout(loadList);
|
|
<?endif;?>
|
|
break;
|
|
case 1:
|
|
<?if ($dfm['browser']):?>
|
|
$('.dfm_control.jobs').prop('disabled',true);
|
|
<?endif;?>
|
|
$.removeCookie('dfm_control.jobs');
|
|
case 2:
|
|
dfm_openDialog();
|
|
break;
|
|
}
|
|
})});
|
|
} else if (data.done == 2) {
|
|
nchan_filemanager.stop();
|
|
dfm.running = false;
|
|
dfm.window.find('#dfm_target').prop('disabled',false).focus();
|
|
$('.ui-dfm .ui-dialog-buttonset button:eq(0)').prop('disabled',false);
|
|
if (cat == 0) dfm.window.find('.dfm_text').html("_(No results found)_");
|
|
if ($('#user-notice:visible')) dfm_done();
|
|
}
|
|
}
|
|
});
|
|
|
|
<?if ($dfm['running']):?>
|
|
$(function(){
|
|
dfm_openDialog();
|
|
dfm_fileManager('start');
|
|
});
|
|
<?endif;?>
|
|
</script>
|