Merge pull request #1308 from bergware/master

DeviceInfo and ShareEdit: fix size calculation
This commit is contained in:
tom mortensen
2023-04-25 11:05:24 -07:00
committed by GitHub
6 changed files with 248 additions and 194 deletions
+3 -2
View File
@@ -40,9 +40,11 @@ $(function(){
$.get('/webGui/include/Browse.php',{dir:encodeURIComponent("<?=$dir?>"),path:"<?=$path?>"},function(data){
clearTimeout(timers.browse);
var table = $('table.indexer');
var thead = table.find('thead');
var col = $.cookie('col')||1;
var dir = $.cookie('dir')||0;
table.html(data);
table.find('tbody,tfoot').remove();
thead.after(data);
table.bind('sortEnd',function(e,t){
var sort = e.target.config.sortList.toString().split(',');
$.cookie('col',sort[0]);
@@ -55,6 +57,5 @@ $(function(){
</script>
<table class="indexer tablesorter shift">
<thead><tr><th>_(Type)_</th><th class='sorter-text'>_(Name)_</th><th>_(Size)_</th><th>_(Last Modified)_</th><th style="width:200px">_(Location)_</th></tr></thead>
<tbody><tr><td colspan="5">&nbsp;</td></tr></tbody>
</table>
<input type="button" value="_(Done)_" onclick="done('Browse')">
+100 -81
View File
@@ -27,12 +27,26 @@ $bgcolor = in_array($display['theme'],['white','azure']) ? '#f2f2f2' : '#1c1c
$mode = ['Disabled','Hourly','Daily','Weekly','Monthly'];
$days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
function sanitize(&$val) {
$data = explode('.',str_replace([' ',','],['','.'],$val));
$last = array_pop($data);
$val = count($data) ? implode($data).".$last" : $last;
}
function presetSpace($val) {
if (!$val) return;
$units = ['KB','MB','GB','TB','PB','EB','ZB','YB'];
$val = filter_var($val,FILTER_SANITIZE_NUMBER_INT);
$base = $val>0 ? floor(log($val,1000)) : 0;
return ($val/pow(1000,$base)).' '._var($units,$base);
global $disk,$display;
if (!$val or strcasecmp($val,'NaN')==0) return;
sanitize($val);
$size = _var($disk,'fsSize',0);
$size = $size>0 ? round(100*$val/$size,1) : 0;
$unit = '%';
if ($size < 1) {
$units = ['KB','MB','GB','TB','PB','EB','ZB','YB'];
$base = $val>0 ? floor(log($val,1000)) : 0;
$size = round($val/pow(1000,$base),1);
$unit = _var($units,$base);
}
[$dot,$comma] = str_split(_var($display,'number','.,'));
return $size>0 ? number_format($size,$size-floor($size)?1:0,$dot,$comma).' '.$unit : '';
}
function fsSize() {
global $disks,$pools;
@@ -99,23 +113,30 @@ if ($.cookie('deletepool')) {
done();
}
function setFloor() {
if ($('#shareFloor').length==0) return;
const fsSize = {<?=fsSize()?>};
const units = ['K','M','G','T','P','E','Z','Y'];
if ($('#shareFloor').length) {
var val = $('#shareFloor').val();
var size = fsSize['<?=$tag?>'] * 0.1; // 10% of available size
var base = Math.pow(1000,Math.floor(Math.log(size)/Math.log(1000)));
if (val.replace(/[A-Z.,\s]/gi,'')==0) {
size = (Math.floor(size/base) * base).toString();
$.cookie('autosize-<?=$tag?>','1',{expires:365});
} else {
size = val;
$.removeCookie('autosize-<?=$tag?>');
}
var unit = size.replace(/[0-9.,\s]/g,'');
base = unit.length==2 ? 1000 : (unit.length==1 ? 1024 : 0);
$('#shareFloor').val(base>0 ? size.replace(unit,'') * Math.pow(base,(units.indexOf(unit.toUpperCase().replace('B',''))||0)) : size);
var val = $('#shareFloor').val();
var full = fsSize["<?=$tag?>"];
var size = parseInt(full * 0.1); // 10% of available size
var number = val.replace(/[A-Z%\s]/gi,'').replace(',','.').split('.');
var last = number.pop();
number = number.length ? number.join('')+'.'+last : last;
if (number==0 && size>0) {
size = size.toString();
$.cookie('autosize-<?=$tag?>','1',{expires:365});
} else {
size = val;
$.removeCookie('autosize-<?=$tag?>');
}
var unit = size.replace(/[0-9.,\s]/g,'');
if (unit=='%') {
number = (number > 0 && number <= 100) ? parseInt(full * number / 100) : '';
} else {
var base = unit.length==2 ? 1000 : (unit.length==1 ? 1024 : 0);
number = base>0 ? number * Math.pow(base,(units.indexOf(unit.toUpperCase().replace('B',''))||0)) : size;
}
$('#shareFloor').val(isNaN(number) ? '' : number);
}
<?if (fsType('btrfs')):?>
function presetBTRFS(form,hour) {
@@ -513,67 +534,6 @@ function eraseDisk(name) {
}
});
}
$(function() {
<?if (count($sheets)>1):?>
var ctrl = "<span class='status <?=$tabbed?'vhshift':'vshift'?>'><span class='waitmsg fa fa-circle-o-notch fa-span fa-fw' style='display:none;margin-right:8px'></span><a href='/<?=$path?>?name=<?=$prev?>' title='_(previous device)_'>";
ctrl += "<button type='button' style='margin-right:4px' onclick='this.disabled=true;$(\".waitmsg\").show();'><i class='fa fa-chevron-left fa-fw'></i></button></a>";
ctrl += "<a href='/<?=$path?>?name=<?=$next?>' title='_(next device)_'><button type='button' onclick='this.disabled=true;$(\".waitmsg\").show();'><i class='fa fa-chevron-right fa-fw'></i></button></a></span>";
<?if ($tabbed):?>
$('.tabs').append(ctrl);
<?else:?>
$('div[class=title]:first').append(ctrl);
<?endif;?>
<?endif;?>
<?if (!diskStatus('_NP')):?>
var form = document.smart_settings;
<?if (!isset($disk['smType'])):?>
form.smType.selectedIndex = 0;
<?endif;?>
setGlue(form,false);
<?endif;?>
var status = true;
if ($.cookie('autosize-<?=$tag?>')) $('#autosize').show();
if ($.cookie('btrfs-balance-<?=$tag?>')) status = btrfsBalance($.cookie('btrfs-balance-<?=$tag?>'));
if ($.cookie('btrfs-scrub-<?=$tag?>')) status = btrfsScrub($.cookie('btrfs-scrub-<?=$tag?>'));
if ($.cookie('btrfs-check-<?=$tag?>')) status = btrfsCheck($.cookie('btrfs-check-<?=$tag?>'));
if ($.cookie('zfs-scrub-<?=$tag?>')) status = zfsScrub($.cookie('zfs-scrub-<?=$tag?>'));
if ($.cookie('zfs-resilver-<?=$tag?>')) status = zfsResilver($.cookie('zfs-resilver-<?=$tag?>'));
if ($.cookie('rfs-check-<?=$tag?>')) status = rfsCheck($.cookie('rfs-check-<?=$tag?>'));
if ($.cookie('xfs-check-<?=$tag?>')) status = xfsCheck($.cookie('xfs-check-<?=$tag?>'));
if (status) {
$.post('/webGui/include/FileSystemStatus.php',{cmd:'status',path:'<?=$tag?>'},function(a){
var action = a.split(',');
for (var i=0,busy; busy=action[i]; i++) {
switch (busy) {
case 'btrfs-balance':
$.cookie('btrfs-balance-<?=$tag?>','/mnt/<?=$tag?>');
btrfsBalance($.cookie('btrfs-balance-<?=$tag?>'));
break;
case 'btrfs-scrub':
$.cookie('btrfs-scrub-<?=$tag?>','/mnt/<?=$tag?>');
btrfsScrub($.cookie('btrfs-scrub-<?=$tag?>'));
break;
case 'btrfs-check':
$.cookie('btrfs-check-<?=$tag?>','/mnt/<?=$tag?>');
btrfsCheck($.cookie('btrfs-check-<?=$tag?>'));
break;
case 'zfs-scrub':
$.cookie('zfs-scrub-<?=$tag?>','<?=$tag?>');
zfsScrub($.cookie('zfs-scrub-<?=$tag?>'));
break;
case 'zfs-resilver':
$.cookie('zfs-resilver-<?=$tag?>','<?=$tag?>');
zfsResilver($.cookie('zfs-resilver-<?=$tag?>'));
break;
}
}
});
}
var groups = <?=_var($disk,'fsGroups',0)?:0?>;
var width = <?=_var($disk,'fsWidth',0)?:0?>;
var devices = (groups==0 || width==0) ? <?=_var($disk,'devices',0)?:0?> : groups * width;
selectDiskFsProfile(devices,width,true);
});
</script>
<form markdown="1" method="POST" action="/update.htm" target="progressFrame" onsubmit="setFloor()">
@@ -1287,7 +1247,66 @@ _(Name)_:
</form>
<script>
$(function(){
$(function() {
<?if (count($sheets)>1):?>
var ctrl = "<span class='status <?=$tabbed?'vhshift':'vshift'?>'><span class='waitmsg fa fa-circle-o-notch fa-span fa-fw' style='display:none;margin-right:8px'></span><a href='/<?=$path?>?name=<?=$prev?>' title='_(previous device)_'>";
ctrl += "<button type='button' style='margin-right:4px' onclick='this.disabled=true;$(\".waitmsg\").show();'><i class='fa fa-chevron-left fa-fw'></i></button></a>";
ctrl += "<a href='/<?=$path?>?name=<?=$next?>' title='_(next device)_'><button type='button' onclick='this.disabled=true;$(\".waitmsg\").show();'><i class='fa fa-chevron-right fa-fw'></i></button></a></span>";
<?if ($tabbed):?>
$('.tabs').append(ctrl);
<?else:?>
$('div[class=title]:first').append(ctrl);
<?endif;?>
<?endif;?>
<?if (!diskStatus('_NP')):?>
var form = document.smart_settings;
<?if (!isset($disk['smType'])):?>
form.smType.selectedIndex = 0;
<?endif;?>
setGlue(form,false);
<?endif;?>
var status = true;
if ($.cookie('autosize-<?=$tag?>')) $('#autosize').show();
if ($.cookie('btrfs-balance-<?=$tag?>')) status = btrfsBalance($.cookie('btrfs-balance-<?=$tag?>'));
if ($.cookie('btrfs-scrub-<?=$tag?>')) status = btrfsScrub($.cookie('btrfs-scrub-<?=$tag?>'));
if ($.cookie('btrfs-check-<?=$tag?>')) status = btrfsCheck($.cookie('btrfs-check-<?=$tag?>'));
if ($.cookie('zfs-scrub-<?=$tag?>')) status = zfsScrub($.cookie('zfs-scrub-<?=$tag?>'));
if ($.cookie('zfs-resilver-<?=$tag?>')) status = zfsResilver($.cookie('zfs-resilver-<?=$tag?>'));
if ($.cookie('rfs-check-<?=$tag?>')) status = rfsCheck($.cookie('rfs-check-<?=$tag?>'));
if ($.cookie('xfs-check-<?=$tag?>')) status = xfsCheck($.cookie('xfs-check-<?=$tag?>'));
if (status) {
$.post('/webGui/include/FileSystemStatus.php',{cmd:'status',path:'<?=$tag?>'},function(a){
var action = a.split(',');
for (var i=0,busy; busy=action[i]; i++) {
switch (busy) {
case 'btrfs-balance':
$.cookie('btrfs-balance-<?=$tag?>','/mnt/<?=$tag?>');
btrfsBalance($.cookie('btrfs-balance-<?=$tag?>'));
break;
case 'btrfs-scrub':
$.cookie('btrfs-scrub-<?=$tag?>','/mnt/<?=$tag?>');
btrfsScrub($.cookie('btrfs-scrub-<?=$tag?>'));
break;
case 'btrfs-check':
$.cookie('btrfs-check-<?=$tag?>','/mnt/<?=$tag?>');
btrfsCheck($.cookie('btrfs-check-<?=$tag?>'));
break;
case 'zfs-scrub':
$.cookie('zfs-scrub-<?=$tag?>','<?=$tag?>');
zfsScrub($.cookie('zfs-scrub-<?=$tag?>'));
break;
case 'zfs-resilver':
$.cookie('zfs-resilver-<?=$tag?>','<?=$tag?>');
zfsResilver($.cookie('zfs-resilver-<?=$tag?>'));
break;
}
}
});
}
var groups = <?=_var($disk,'fsGroups',0)?:0?>;
var width = <?=_var($disk,'fsWidth',0)?:0?>;
var devices = (groups==0 || width==0) ? <?=_var($disk,'devices',0)?:0?> : groups * width;
selectDiskFsProfile(devices,width,true);
<?if (fsType('btrfs')):?>
presetBTRFS(document.balance_schedule,'#balance-hour');
presetBTRFS(document.scrub_schedule,'#scrub-hour');
+2 -2
View File
@@ -39,8 +39,8 @@ if ($name) {
}
?>
<style>
div.clone1{position:absolute;right:0;margin-top:0}
div.clone2{position:absolute;right:0;margin-top:48px}
div.clone1{position:absolute;right:10px;margin-top:0}
div.clone2{position:absolute;right:10px;margin-top:48px}
span.input{display:inline-block;width:330px}
<?if ($themes1):?>
span.wrap{display:inline-block;width:128px}
+69 -32
View File
@@ -31,13 +31,9 @@ if ($name == "") {
"cachePool" => "",
"cow" => "auto"
];
$loc = 0;
} elseif (array_key_exists($name, $shares)) {
// edit existing share
$share = $shares[$name];
// find current location(s) of share
$tag = implode('|',array_merge(['disk'],pools_filter($disks)));
$loc = count(array_filter(explode(',',preg_replace("/($tag)/",',$1',exec("getfattr --no-dereference --absolute-names --only-values -n system.LOCATIONS ".escapeshellarg("/mnt/user/$name")." 2>/dev/null")))));
} else {
// handle share deleted case
echo "<p class='notice'>"._('Share')." '".htmlspecialchars($name)."' "._('has been deleted').".</p><input type='button' value=\""._('Done')."\" onclick='done()'>";
@@ -46,20 +42,35 @@ if ($name == "") {
// Check for non existent pool device
if ($share['cachePool'] && !in_array($share['cachePool'],$pools)) $share['useCache'] = "no";
// check for empty share
function shareEmpty($name) {
return is_dir("/mnt/user/$name") ? count(scandir("/mnt/user/$name",SCANDIR_SORT_NONE))<=2 : true;
}
function globalInclude($name) {
global $var;
return substr($name,0,4)=='disk' && (!$var['shareUserInclude'] || in_array($name,explode(',',$var['shareUserInclude'])));
}
function sanitize(&$val) {
$data = explode('.',str_replace([' ',','],['','.'],$val));
$last = array_pop($data);
$val = count($data) ? implode($data).".$last" : $last;
}
function presetSpace($val) {
if (!$val) return;
$units = ['KB','MB','GB','TB','PB','EB','ZB','YB'];
$val = filter_var($val,FILTER_SANITIZE_NUMBER_INT);
$base = $val>0 ? floor(log($val,1000)) : 0;
return ($val/pow(1000,$base)).' '._var($units,$base);
global $disks,$shares,$name,$pools,$display;
if (!$val or strcasecmp($val,'NaN')==0) return;
sanitize($val);
$small = [];
foreach (data_filter($disks) as $disk) $small[] = _var($disk,'fsSize');
$fsSize[""] = min(array_filter($small));
foreach ($pools as $pool) $fsSize[$pool] = _var($disks[$pool],'fsSize',0);
$pool = _var($shares[$name],'cachePool');
$size = _var($fsSize,$pool,0);
$size = $size>0 ? round(100*$val/$size,1) : 0;
$unit = '%';
if ($size < 1) {
$units = ['KB','MB','GB','TB','PB','EB','ZB','YB'];
$base = $val>0 ? floor(log($val,1000)) : 0;
$size = round($val/pow(1000,$base),1);
$unit = _var($units,$base);
}
[$dot,$comma] = str_split(_var($display,'number','.,'));
return $size>0 ? number_format($size,$size-floor($size)?1:0,$dot,$comma).' '.$unit : '';
}
function fsSize() {
global $disks,$pools;
@@ -90,20 +101,23 @@ function direction() {
// global shares include/exclude
$myDisks = array_filter(array_diff(array_keys(array_filter($disks,'my_disks')), explode(',',$var['shareUserExclude'])), 'globalInclude');
?>
:share_edit_global1_help:
<?if ($name):?>
:share_edit_global2_help:
<?endif;?>
<style>
div.shade-white{background-color:#ededed;margin-top:10px;padding:8px 0 3px 0}
div.shade-black{background-color:#212121;margin-top:10px;padding:8px 0 3px 0}
div.shade-azure{background-color:#edeaef;margin-top:10px;padding:8px 0 3px 0}
div.shade-gray{background-color:#121510;margin-top:10px;padding:8px 0 3px 0}
#s1,#s2,#s3,#s4,#s5,#autosize{display:none}
#s1,#s2,#s3,#s4,#s5,#autosize,.empty,.full2{display:none}
i.fa-info.i{margin-right:10px}
<?if ($themes1):?>
form[name=share_edit]{margin-top:-20px}
<?endif;?>
</style>
:share_edit_global1_help:
<?if ($name):?>
:share_edit_global2_help:
<?endif;?>
<div id="" class="clone1">
<span class="clone">_(Read settings from)_</span><i class="fa fa-arrow-left fa-fw"></i>
<span class="wrap"><select name="readshare" class="clone" onchange="toggleButton('readshare',false)">
@@ -146,26 +160,31 @@ _(Comments)_:
:share_edit_comments_help:
<?if (_var($share,'exclusive')=="no"):?>
<div markdown="1">
_(Minimum free space)_:
: <span class="input"><input type="text" name="shareFloor" maxlength="16" autocomplete="off" spellcheck="false" class="narrow" value="<?=presetSpace($share['floor'])?>" placeholder="0"></span><span id="autosize"><i class="fa fa-info i"></i>_(Calculated free space value)_</span>
:share_edit_free_space_help:
</div>
<?endif;?>
<?if ($name):?>
<?if (shareEmpty($name)):?>
<div markdown="1" class="empty">
_(Share status)_:
: _(Share is empty)_
:share_edit_status_help:
<?else:?>
</div>
<div markdown="1" class="full">
_(Share status)_:
: _(Share contains data)_
: <span class="full1">&nbsp;</span><span class="full2">_(Share contains data)_</span>
:share_edit_delete_help:
<?endif;?>
<?if ($share['exclusive']=="yes"):?>
</div>
<?if (_var($share,'exclusive')=="yes"):?>
_(Exclusive access)_:
: _(Yes)_
@@ -321,18 +340,26 @@ _(Mover action)_:
<?if (!$name):?>
&nbsp;
: <input type="submit" name="cmdEditShare" value="_(Add Share)_" onclick="this.value='Add Share'"><input type="button" value="_(Done)_" onclick="done()">
<?elseif (shareEmpty($name)):?>
<?else:?>
<div markdown="1" class="empty">
_(Delete)_<input type="checkbox" name="confirmDelete" onchange="chkDelete(this.form, this.form.cmdEditShare);">
: <input type="submit" name="cmdEditShare" value="_(Apply)_" onclick="if (this.value=='_(Delete)_') this.value='Delete'; else this.value='Apply'" disabled><input type="button" value="_(Done)_" onclick="done()">
<?else:?>
</div>
<div markdown="1" class="full">
&nbsp;
: <input type="submit" name="cmdEditShare" value="_(Apply)_" onclick="this.value='Apply'" disabled><input type="button" value="_(Done)_" onclick="done()">
</div>
<?endif;?>
</form>
<script>
var form = document.share_edit;
$(function() {
<?if ($name):?>
$.post('/webGui/include/ShareList.php',{scan:"<?=$name?>"},function(e){
if (e==1) {$('.empty').show(); $('.full').hide();} else {$('.full1').hide(); $('.full2').show();}
});
<?endif;?>
initDropdown(false,true);
<?if ($tabbed):?>
$('#tab1').bind({click:function(){initDropdown(true,true);}});
@@ -449,18 +476,26 @@ function unite(field) {
function setFloor(val) {
const fsSize = {<?=fsSize()?>};
const units = ['K','M','G','T','P','E','Z','Y'];
var size = fsSize[$('#primary').val()] * 0.1; // 10% of available size
var base = Math.pow(1000,Math.floor(Math.log(size)/Math.log(1000)));
if (val.replace(/[A-Z.,\s]/gi,'')==0) {
size = (Math.floor(size/base) * base).toString();
var full = fsSize[$('#primary').val()];
var size = parseInt(full * 0.1); // 10% of available size
var number = val.replace(/[A-Z%\s]/gi,'').replace(',','.').split('.');
var last = number.pop();
number = number.length ? number.join('')+'.'+last : last;
if (number==0 && size>0) {
size = size.toString()
$.cookie('autosize-'+$('#shareName').val(),'1',{expires:365});
} else {
size = val;
$.removeCookie('autosize-'+$('#shareName').val());
}
var unit = size.replace(/[0-9.,\s]/g,'');
base = unit.length==2 ? 1000 : (unit.length==1 ? 1024 : 0);
return base>0 ? size.replace(unit,'') * Math.pow(base,(units.indexOf(unit.toUpperCase().replace('B',''))||0)) : size;
if (unit=='%') {
number = (number > 0 && number <= 100) ? parseInt(full * number / 100) : '';
} else {
var base = unit.length==2 ? 1000 : (unit.length==1 ? 1024 : 0);
number = base>0 ? number * Math.pow(base,(units.indexOf(unit.toUpperCase().replace('B',''))||0)) : size;
}
return isNaN(number) ? '' : number;
}
// Compose input fields
function prepareEdit() {
@@ -487,7 +522,9 @@ function prepareEdit() {
// Update settings
form.shareName.value = share;
form.shareUseCache.value = z(4);
<?if (_var($share,'exclusive')=="no"):?>
form.shareFloor.value = setFloor(form.shareFloor.value);
<?endif;?>
switch (form.shareUseCache.value) {
case 'no':
form.shareAllocator.value = form.shareAllocator1.value;
+67 -76
View File
@@ -1,6 +1,6 @@
<?PHP
/* Copyright 2005-2021, Lime Technology
* Copyright 2012-2021, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, 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,
@@ -18,95 +18,86 @@ require_once "$docroot/webGui/include/Translations.php";
require_once "$docroot/webGui/include/Helpers.php";
function write(&$rows) {
if ($size = count($rows)) echo '<tbody>',implode(array_map(function($row){echo gzinflate($row);},$rows)),'</tbody>';
$rows = $size;
}
function add($number, $name, $single='', $plural='s') {
return $number.' '._($name.($number==1 ? $single : $plural));
}
function parent_link() {
global $dir,$path;
return ($dir && dirname($dir)!='/' && dirname($dir)!='/mnt' && dirname($dir)!='/mnt/user') ? "<a href=\"/$path?dir=".rawurlencode(dirname($dir))."\">Parent Directory</a>" : "";
}
function trim_slash($url){
return preg_replace('://+:','/',$url);
$parent = dirname($dir);
return $parent=='/' ? false : '<a href="/'.$path.'?dir='.rawurlencode(htmlspecialchars($parent)).'">'._('Parent Directory').'</a>';
}
function my_devs(&$devs) {
global $disks;
global $disks,$lock;
$text = []; $i = 0;
foreach ($devs as $dev) {
switch ($disks[$dev]['luksState']) {
case 0: $text[$i] = "<a class='info' onclick='return false'><i class='lock fa fa-fw fa-unlock-alt grey-text'></i><span>"._('Not encrypted')."</span></a>"; break;
case 1: $text[$i] = "<a class='info' onclick='return false'><i class='lock fa fa-fw fa-unlock-alt green-text'></i><span>"._('Encrypted and unlocked')."</span></a>"; break;
case 2: $text[$i] = "<a class='info' onclick='return false'><i class='lock fa fa-fw fa-lock red-text'></i><span>"._('Locked: missing encryption key')."</span></a>"; break;
case 3: $text[$i] = "<a class='info' onclick='return false'><i class='lock fa fa-fw fa-lock red-text'></i><span>"._('Locked: wrong encryption key')."</span></a>"; break;
default: $text[$i] = "<a class='info' onclick='return false'><i class='lock fa fa-fw fa-lock red-text'></i><span>"._('Locked: unknown error')."</span></a>"; break;
if ($lock=='---') {
$text[$i] = '<a class="info" onclick="return false"><i class="lock fa fa-fw fa-hdd-o grey-text"></i></a>&nbsp;---';
} else {
switch ($disks[$dev]['luksState']??0) {
case 0: $text[$i] = "<a class='info' onclick='return false'><i class='lock fa fa-fw fa-unlock-alt grey-text'></i><span>"._('Not encrypted')."</span></a>"; break;
case 1: $text[$i] = "<a class='info' onclick='return false'><i class='lock fa fa-fw fa-unlock-alt green-text'></i><span>"._('Encrypted and unlocked')."</span></a>"; break;
case 2: $text[$i] = "<a class='info' onclick='return false'><i class='lock fa fa-fw fa-lock red-text'></i><span>"._('Locked: missing encryption key')."</span></a>"; break;
case 3: $text[$i] = "<a class='info' onclick='return false'><i class='lock fa fa-fw fa-lock red-text'></i><span>"._('Locked: wrong encryption key')."</span></a>"; break;
default: $text[$i] = "<a class='info' onclick='return false'><i class='lock fa fa-fw fa-lock red-text'></i><span>"._('Locked: unknown error')."</span></a>"; break;
}
$text[$i] .= compress($dev,12,0);
}
$text[$i++] .= compress($dev,8,0);
$i++;
}
return implode(', ',$text);
return implode($text);
}
extract(parse_plugin_cfg('dynamix',true));
$disks = parse_ini_file('state/disks.ini',true);
$dir = realpath(htmlspecialchars_decode(rawurldecode($_GET['dir'])));
$path = unscript($_GET['path']);
[$root,$main,$rest] = my_explode('/',mb_substr($dir,1),3);
$fix = $root=='mnt' ? ($main ?: '---') : ($root=='boot' ? _('flash') : '---');
$user = $root=='mnt' && in_array($main,['user','user0']);
$fmt = "%F {$display['time']}";
$dirs = $files = [];
$total = $i = 0;
$disks = parse_ini_file('state/disks.ini',true);
$shares = parse_ini_file('state/shares.ini',true);
$dir = realpath(htmlspecialchars_decode(rawurldecode($_GET['dir'])));
$path = unscript($_GET['path']);
$fmt = "%F {$display['time']}";
$dirs = $files = [];
$total = $objs = 0;
[$null,$root,$main,$rest] = my_explode('/',$dir,4);
$user = $root=='mnt' && in_array($main,['user','user0']);
$lock = $root=='mnt' ? ($main ?: '---') : ($root=='boot' ? _('flash') : '---');
if ($user) {
$tag = implode('|',array_merge(['disk'],pools_filter($disks)));
$set = explode(';',str_replace(',;',',',preg_replace("/($tag)/",';$1',exec("shopt -s dotglob; getfattr --no-dereference --absolute-names --only-values -n system.LOCATIONS ".escapeshellarg($dir)."/* 2>/dev/null"))));
exec("shopt -s dotglob; getfattr --no-dereference --absolute-names -n system.LOCATIONS ".escapeshellarg($dir)."/* 2>/dev/null",$tmp);
for ($i = 0; $i < count($tmp); $i+=3) $set[basename($tmp[$i])] = explode('"',$tmp[$i+1])[1];
unset($tmp);
}
$stat = popen("shopt -s dotglob; stat -L -c'%F|%n|%s|%Y' ".escapeshellarg($dir)."/* 2>/dev/null",'r');
$stat = popen("shopt -s dotglob; stat -L -c'%F|%s|%Y|%n' ".escapeshellarg($dir)."/* 2>/dev/null",'r');
while (($row = fgets($stat))!==false) {
$row .= $user ? "|{$set[++$i]}" : "|$fix";
if ($row[0]=='d') $dirs[] = $row; else $files[] = $row;
[$type,$size,$time,$name] = explode('|',rtrim($row,"\n"),4);
$dev = explode('/',$name,5);
$devs = explode(',',$user ? $set[basename($name)]??$shares[$dev[3]]['cachePool']??'' : $lock);
$objs++;
$text = [];
if ($type[0]=='d') {
$text[] = "<tr>";
$text[] = "<td data=''><div class='icon-dir'></div></td>";
$text[] = "<td><a href=\"/$path?dir=".rawurlencode(htmlspecialchars($name))."\">".htmlspecialchars(basename($name))."</a></td>";
$text[] = "<td data='0'>&lt;"._('FOLDER')."&gt;</td>";
$text[] = "<td data='$time'>".my_time($time,$fmt)."</td>";
$text[] = "<td class='loc'>".my_devs($devs)."</td>";
$text[] = "</tr>";
$dirs[] = gzdeflate(implode($text));
} else {
$ext = strtolower(pathinfo($name,PATHINFO_EXTENSION));
$tag = count($devs)>1 ? 'warning' : '';
$text[] = "<tr>";
$text[] = "<td data='$ext'><div class='icon-file icon-$ext'></div></td>";
$text[] = "<td><a href=\"".htmlspecialchars($name)."\" download target=\"_blank\" class=\"".($tag?:'none')."\">".htmlspecialchars(basename($name))."</a></td>";
$text[] = "<td data='$size' class='$tag'>".my_scale($size,$unit)." $unit</td>";
$text[] = "<td data='$time' class='$tag'>".my_time($time,$fmt)."</td>";
$text[] = "<td class='loc $tag'>".my_devs($devs)."</td>";
$text[] = "</tr>";
$files[] = gzdeflate(implode($text));
$total += $size;
}
}
pclose($stat);
echo "<thead><tr><th>"._('Type')."</th><th class='sorter-text'>"._('Name')."</th><th>"._('Size')."</th><th>"._('Last Modified')."</th><th style='width:200px'>"._('Location')."</th></tr></thead>";
if ($link = parent_link()) echo "<tbody class='tablesorter-infoOnly'><tr><td><div><img src='/webGui/icons/folderup.png'></div></td><td>$link</td><td colspan='3'></td></tr></tbody>";
echo "<tbody>";
foreach ($dirs as $row) {
[$type,$full,$size,$time,$set] = my_explode('|',$row,5);
$file = pathinfo($full);
$full = str_replace($docroot,'',$full);
$name = $file['basename'];
$devs = explode(',',$set);
echo "<tr>";
echo "<td data=''><div class='icon-dir'></div></td>";
echo "<td><a href=\"/$path?dir=".rawurlencode(htmlspecialchars($full))."\">".htmlspecialchars($name)."</a></td>";
echo "<td data='0'>&lt;"._('FOLDER')."&gt;</td>";
echo "<td data='$time'>".my_time($time,$fmt)."</td>";
echo "<td class='loc'>".my_devs($devs)."</td>";
echo "</tr>";
}
if (count($dirs)) echo "</tbody><tbody>";
foreach ($files as $row) {
[$type,$full,$size,$time,$set] = my_explode('|',$row,5);
$file = pathinfo($full);
$full = str_replace($docroot,'',$full);
$name = $file['basename'];
$ext = strtolower($file['extension']);
$devs = explode(',',$set);
$tag = strpos($set,',')===false ? '' : 'warning';
echo "<tr>";
echo "<td data='$ext'><div class='icon-file icon-$ext'></div></td>";
echo "<td><a href=\"".htmlspecialchars($full)."\" download target=\"_blank\" class=\"".($tag?:'none')."\">".htmlspecialchars($name)."</a></td>";
echo "<td data='$size' class='$tag'>".my_scale($size,$unit)." $unit</td>";
echo "<td data='$time' class='$tag'>".my_time($time,$fmt)."</td>";
echo "<td class='loc $tag'>".my_devs($devs)."</td>";
echo "</tr>";
$total += $size;
}
echo "</tbody>";
$dirs = count($dirs);
$files = count($files);
$objs = $dirs + $files;
if ($objs==0 && !exec("find ".escapeshellarg($dir)." -maxdepth 0 -empty -exec echo 1 \;")) {
echo "<tfoot><tr><td></td><td colspan='4'>"._('No listing: Too many files')."</td></tr></tfoot>";
} else {
$total = ' ('.my_scale($total,$unit).' '.$unit.' '._('total').')';
echo "<tfoot><tr><td></td><td colspan='4'>$objs "._('object'.($objs==1?'':'s')).": $dirs "._('director'.($dirs==1?'y':'ies')).", $files "._('file'.($files==1?'':'s'))."$total</td></tr></tfoot>";
}
echo write($dirs),write($files),'<tfoot><tr><td></td><td colspan="4">',add($objs,'object'),': ',add($dirs,'director','y','ies'),', ',add($files,'file'),' (',my_scale($total,$unit),' ',$unit,' ',_('total'),')</td></tr></tfoot>';
?>
+7 -1
View File
@@ -13,6 +13,11 @@
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
if (isset($_POST['scan'])) {
$scan = $_POST['scan'];
die(is_dir("/mnt/user/$scan") ? (count(scandir("/mnt/user/$scan",SCANDIR_SORT_NONE))<=2 ? '1' : '0') : '1');
}
// add translations
$_SERVER['REQUEST_URI'] = 'shares';
require_once "$docroot/webGui/include/Translations.php";
@@ -115,7 +120,8 @@ foreach ($shares as $name => $share) {
$cache = "<a class='hand info none' onclick='return false'><i class='fa fa-bullseye fa-fw'></i>".compress(my_disk($share['cachePool'],$display['raw']))." <i class='fa fa-long-arrow-left fa-fw'></i><i class='fa fa-database fa-fw'></i>"._('Array')."<span>"._('Secondary stoage to Primary storage')."</span></a>";
break;
case 'only':
$cache = "<a class='hand info none' onclick='return false'><i class='fa fa-bullseye fa-fw'></i>".compress(my_disk($share['cachePool'],$display['raw']))."<span>".sprintf(_('Primary storage %s'),$share['cachePool'])."</span></a>";
$exclusive = isset($share['exclusive']) && $share['exclusive']=='yes' ? "<i class='fa fa-caret-right '></i> " : "";
$cache = "<a class='hand info none' onclick='return false'><i class='fa fa-bullseye fa-fw'></i>$exclusive".compress(my_disk($share['cachePool'],$display['raw']))."<span>".sprintf(_('Primary storage %s'),$share['cachePool']).($exclusive ? ", "._('Exclusive access') : "")."</span></a>";
break;
}
if (array_key_exists($name, $ssz1)) {