mirror of
https://github.com/unraid/webgui.git
synced 2026-04-25 20:01:38 -05:00
File Manager: add UD shares to user shares
This commit is contained in:
@@ -488,7 +488,7 @@ function doAction(action, title, id) {
|
||||
case 4: // move folder
|
||||
case 9: // move file
|
||||
// disallow mixing of disk and user shares
|
||||
var valid = ud ? /^\/mnt\/.+/ : (user ? /^\/mnt\/(user0?|rootshare)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)).+$|^\/boot\/.+/);
|
||||
var valid = user ? /^\/mnt\/(user0?|disks|remotes)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)\/).*$|^\/boot\/.+/;
|
||||
// check if 'mv' can be used
|
||||
if (path.length > 2) {
|
||||
if (user) {
|
||||
@@ -520,7 +520,7 @@ function doAction(action, title, id) {
|
||||
break;
|
||||
default:
|
||||
// disallow mixing of disk and user shares
|
||||
var valid = ud ? /^\/mnt\/.+/ : (user ? /^\/mnt\/(user0?|rootshare)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)).+$|^\/boot\/.+/);
|
||||
var valid = user ? /^\/mnt\/(user0?|disks|remotes)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)\/).*$|^\/boot\/.+/;
|
||||
break;
|
||||
}
|
||||
if (!target || !valid.test(target)) {errorTarget(); return;}
|
||||
@@ -558,7 +558,7 @@ function doAction(action, title, id) {
|
||||
case 4: // move folder
|
||||
case 9: // move file
|
||||
// disallow mixing of disk and user shares
|
||||
var valid = ud ? /^\/mnt\/.+/ : (user ? /^\/mnt\/(user0?|rootshare)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)).+$|^\/boot\/.+/);
|
||||
var valid = user ? /^\/mnt\/(user0?|disks|remotes)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)\/).*$|^\/boot\/.+/;
|
||||
// check if 'mv' can be used
|
||||
if (path.length > 2) {
|
||||
if (user) {
|
||||
@@ -583,7 +583,7 @@ function doAction(action, title, id) {
|
||||
break;
|
||||
default:
|
||||
// disallow mixing of disk and user shares
|
||||
var valid = ud ? /^\/mnt\/.+/ : (user ? /^\/mnt\/(user0?|rootshare)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)).+$|^\/boot\/.+/);
|
||||
var valid = user ? /^\/mnt\/(user0?|disks|remotes)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)\/).*$|^\/boot\/.+/;
|
||||
break;
|
||||
}
|
||||
if (!target || !valid.test(target)) {errorTarget(); return;}
|
||||
@@ -767,7 +767,7 @@ function doActions(action, title) {
|
||||
break;
|
||||
case 4: // move object
|
||||
// disallow mixing of disk and user shares
|
||||
var valid = ud ? /\/mnt\/.+/ : (user ? /^\/mnt\/(user0?|rootshare)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)).+$|^\/boot\/.+/);
|
||||
var valid = user ? /^\/mnt\/(user0?|disks|remotes)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)\/).*$|^\/boot\/.+/;
|
||||
// check if 'mv' can be used
|
||||
if (path.length > 2) {
|
||||
if (user) {
|
||||
@@ -801,7 +801,7 @@ function doActions(action, title) {
|
||||
break;
|
||||
default:
|
||||
// disallow mixing of disk and user shares
|
||||
var valid = ud ? /\/mnt\/.+/ : (user ? /^\/mnt\/(user0?|rootshare)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)).+$|^\/boot\/.+/);
|
||||
var valid = user ? /^\/mnt\/(user0?|disks|remotes)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)\/).*$|^\/boot\/.+/;
|
||||
break;
|
||||
}
|
||||
if (!target || !valid.test(target)) {errorTarget(); return;}
|
||||
@@ -839,7 +839,7 @@ function doActions(action, title) {
|
||||
break;
|
||||
case 4: // move object
|
||||
// disallow mixing of disk and user shares
|
||||
var valid = ud ? /\/mnt\/.+/ : (user ? /^\/mnt\/(user0?|rootshare)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)).+$|^\/boot\/.+/);
|
||||
var valid = user ? /^\/mnt\/(user0?|disks|remotes)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)\/).*$|^\/boot\/.+/;
|
||||
// check if 'mv' can be used
|
||||
if (path.length > 2) {
|
||||
if (user) {
|
||||
@@ -866,7 +866,7 @@ function doActions(action, title) {
|
||||
break;
|
||||
default:
|
||||
// disallow mixing of disk and user shares
|
||||
var valid = ud ? /\/mnt\/.+/ : (user ? /^\/mnt\/(user0?|rootshare)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)).+$|^\/boot\/.+/);
|
||||
var valid = user ? /^\/mnt\/(user0?|disks|remotes)\/.+/ : /^\/mnt\/(?!.*(user0?|rootshare)\/).*$|^\/boot\/.+/;
|
||||
break;
|
||||
}
|
||||
if (!target || !valid.test(target)) {errorTarget(); return;}
|
||||
|
||||
@@ -25,18 +25,18 @@ function write(&$rows) {
|
||||
|
||||
function validdir($dir) {
|
||||
$path = realpath($dir);
|
||||
return in_array(explode('/',$path)[1]??'',['mnt','boot']) ? $path : '';
|
||||
return in_array(explode('/', $path)[1] ?? '', ['mnt','boot']) ? $path : '';
|
||||
}
|
||||
|
||||
function escapeQuote($data) {
|
||||
return str_replace('"','"',$data);
|
||||
return str_replace('"','"', $data);
|
||||
}
|
||||
|
||||
function add($number, $name, $single='', $plural='s') {
|
||||
return $number.' '._($name.($number==1 ? $single : $plural));
|
||||
}
|
||||
|
||||
function age($number,$time) {
|
||||
function age($number, $time) {
|
||||
return sprintf(_('%s '.($number==1 ? $time : $time.'s').' ago'),$number);
|
||||
}
|
||||
|
||||
@@ -44,25 +44,25 @@ function my_age($time) {
|
||||
if (!is_numeric($time)) $time = time();
|
||||
$age = new DateTime('@'.$time);
|
||||
$age = date_create('now')->diff($age);
|
||||
if ($age->y > 0) return age($age->y,'year');
|
||||
if ($age->m > 0) return age($age->m,'month');
|
||||
if ($age->d > 0) return age($age->d,'day');
|
||||
if ($age->h > 0) return age($age->h,'hour');
|
||||
if ($age->i > 0) return age($age->i,'minute');
|
||||
return age($age->s,'second');
|
||||
if ($age->y > 0) return age($age->y, 'year');
|
||||
if ($age->m > 0) return age($age->m, 'month');
|
||||
if ($age->d > 0) return age($age->d, 'day');
|
||||
if ($age->h > 0) return age($age->h, 'hour');
|
||||
if ($age->i > 0) return age($age->i, 'minute');
|
||||
return age($age->s, 'second');
|
||||
}
|
||||
|
||||
function parent_link() {
|
||||
global $dir,$path;
|
||||
global $dir, $path;
|
||||
$parent = dirname($dir);
|
||||
return $parent=='/' ? false : '<a href="/'.$path.'?dir='.rawurlencode(htmlspecialchars($parent)).'">'._('Parent Directory').'</a>';
|
||||
return $parent == '/' ? false : '<a href="/'.$path.'?dir='.rawurlencode(htmlspecialchars($parent)).'">'._('Parent Directory').'</a>';
|
||||
}
|
||||
|
||||
function my_devs(&$devs,$name,$menu) {
|
||||
global $disks,$lock;
|
||||
global $disks, $lock;
|
||||
$text = []; $i = 0;
|
||||
foreach ($devs as $dev) {
|
||||
if ($lock=='---') {
|
||||
if ($lock == '---') {
|
||||
$text[$i] = '<a class="info" onclick="return false"><i class="lock fa fa-fw fa-hdd-o grey-text"></i></a> ---';
|
||||
} else {
|
||||
switch ($disks[$dev]['luksState']??0) {
|
||||
@@ -72,7 +72,7 @@ function my_devs(&$devs,$name,$menu) {
|
||||
case 3: $text[$i] = '<span class="dfm_device"><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] = '<span class="dfm_device"><a class="info" onclick="return false"><i class="lock fa fa-fw fa-lock red-text"></i><span>'._('Locked: unknown error').'</span></a>'; break;
|
||||
}
|
||||
$root = $dev=='flash' ? "/boot/$name" : "/mnt/$dev/$name";
|
||||
$root = ($dev == 'flash' ? "/boot/$name" : "/mnt/$dev/$name");
|
||||
$text[$i] .= '<span id="device_'.$i.'" class="hand" onclick="'.$menu.'(\''.$root.'\','.$i.')" oncontextmenu="'.$menu.'(\''.$root.'\','.$i.');return false">'.compress($dev,11,0).'</span></span>';
|
||||
}
|
||||
$i++;
|
||||
@@ -141,8 +141,8 @@ $path = unscript($_GET['path']);
|
||||
$fmt = "%F {$display['time']}";
|
||||
$dirs = $files = [];
|
||||
$total = $objs = 0;
|
||||
[$null,$root,$main,$next,$rest] = my_explode('/',$dir,5);
|
||||
$user = $root=='mnt' && in_array($main,['user','user0']);
|
||||
[$null,$root,$main,$next,$rest] = my_explode('/', $dir, 5);
|
||||
$user = $root=='mnt' && in_array($main, ['user','user0']);
|
||||
$lock = $root=='mnt' ? ($main ?: '---') : ($root=='boot' ? _('flash') : '---');
|
||||
$ishare = $root=='mnt' && (!$main || !$next || ($main=='rootshare' && !$rest));
|
||||
$folder = $lock=='---' ? _('DEVICE') : ($ishare ? _('SHARE') : _('FOLDER'));
|
||||
@@ -154,13 +154,14 @@ if ($user ) {
|
||||
}
|
||||
|
||||
$stat = popen("shopt -s dotglob;stat -L -c'%F|%U|%A|%s|%Y|%n' ".escapeshellarg($dir)."/* 2>/dev/null",'r');
|
||||
while (($row = fgets($stat))!==false) {
|
||||
|
||||
while (($row = fgets($stat)) !== false) {
|
||||
[$type,$owner,$perm,$size,$time,$name] = explode('|',rtrim($row,"\n"),6);
|
||||
$dev = explode('/',$name,5);
|
||||
$devs = explode(',',$user ? $set[basename($name)]??$shares[$dev[3]]['cachePool']??'' : $lock);
|
||||
$dev = explode('/', $name, 5);
|
||||
$devs = explode(',', $user ? $set[basename($name)] ?? $shares[$dev[3]]['cachePool'] ?? '' : $lock);
|
||||
$objs++;
|
||||
$text = [];
|
||||
if ($type[0]=='d') {
|
||||
if ($type[0] == 'd') {
|
||||
$text[] = '<tr><td><i id="check_'.$objs.'" class="fa fa-fw fa-square-o" onclick="selectOne(this.id)"></i></td>';
|
||||
$text[] = '<td data=""><i class="fa fa-folder-o"></i></td>';
|
||||
$text[] = '<td><a id="name_'.$objs.'" oncontextmenu="folderContextMenu(this.id,\'right\');return false" href="/'.$path.'?dir='.rawurlencode(htmlspecialchars($name)).'">'.htmlspecialchars(basename($name)).'</a></td>';
|
||||
@@ -172,8 +173,8 @@ while (($row = fgets($stat))!==false) {
|
||||
$text[] = '<td><i id="row_'.$objs.'" data="'.escapeQuote($name).'" type="d" class="fa fa-plus-square-o" onclick="folderContextMenu(this.id,\'both\')" oncontextmenu="folderContextMenu(this.id,\'both\');return false">...</i></td></tr>';
|
||||
$dirs[] = gzdeflate(implode($text));
|
||||
} else {
|
||||
$ext = strtolower(pathinfo($name,PATHINFO_EXTENSION));
|
||||
$tag = count($devs)>1 ? 'warning' : '';
|
||||
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
|
||||
$tag = count($devs) > 1 ? 'warning' : '';
|
||||
$text[] = '<tr><td><i id="check_'.$objs.'" class="fa fa-fw fa-square-o" onclick="selectOne(this.id)"></i></td>';
|
||||
$text[] = '<td class="ext" data="'.$ext.'"><i class="'.icon_class($ext).'"></i></td>';
|
||||
$text[] = '<td id="name_'.$objs.'" class="'.$tag.'" onclick="fileEdit(this.id)" oncontextmenu="fileContextMenu(this.id,\'right\');return false">'.htmlspecialchars(basename($name)).'</td>';
|
||||
@@ -189,6 +190,7 @@ while (($row = fgets($stat))!==false) {
|
||||
}
|
||||
|
||||
pclose($stat);
|
||||
|
||||
if ($link = parent_link()) echo '<tbody class="tablesorter-infoOnly"><tr><td></td><td><i class="fa fa-folder-open-o"></i></td><td>',$link,'</td><td colspan="6"></td></tr></tbody>';
|
||||
echo write($dirs),write($files),'<tfoot><tr><td></td><td></td><td colspan="7">',add($objs,'object'),': ',add($dirs,'director','y','ies'),', ',add($files,'file'),' (',my_scale($total,$unit),' ',$unit,' ',_('total'),')</td></tr></tfoot>';
|
||||
?>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*
|
||||
* History:
|
||||
*
|
||||
* 1.2.2 - allow user shares to UD shares
|
||||
* 1.2.1 - exclude folders from the /mnt/ root folder
|
||||
* 1.2.0 - adapted by Bergware for use in Unraid - support UTF-8 encoding & hardening
|
||||
* 1.1.1 - SECURITY: forcing root to prevent users from determining system's file structure (per DaveBrad)
|
||||
@@ -29,13 +30,19 @@
|
||||
function path($dir) {
|
||||
return mb_substr($dir,-1) == '/' ? $dir : $dir.'/';
|
||||
}
|
||||
|
||||
function is_top($dir) {
|
||||
global $root;
|
||||
return mb_strlen($dir) > mb_strlen($root);
|
||||
}
|
||||
function is_low($dir) {
|
||||
global $root;
|
||||
return mb_substr($dir,0,mb_strlen($root)) == $root;
|
||||
|
||||
function no_dots($name) {
|
||||
return !in_array($name, ['.','..']);
|
||||
}
|
||||
|
||||
function my_dir($name) {
|
||||
global $rootdir, $userdir, $topdir, $UDincluded;
|
||||
return ($rootdir === $userdir && in_array($name, $UDincluded)) ? $topdir : $rootdir;
|
||||
}
|
||||
|
||||
$root = path(realpath($_POST['root']));
|
||||
@@ -44,62 +51,60 @@ if (!$root) exit("ERROR: Root filesystem directory not set in jqueryFileTree.php
|
||||
$docroot = '/usr/local/emhttp';
|
||||
require_once "$docroot/webGui/include/Secure.php";
|
||||
|
||||
$rootdir = path(realpath($_POST['dir']));
|
||||
$topdir = '/mnt/';
|
||||
$mntdir = '/mnt/';
|
||||
$userdir = '/mnt/user/';
|
||||
$rootdir = path(realpath($_POST['dir']));
|
||||
$topdir = str_replace($userdir, $mntdir, $rootdir);
|
||||
$filters = (array)$_POST['filter'];
|
||||
$match = $_POST['match'];
|
||||
$checkbox = $_POST['multiSelect'] == 'true' ? "<input type='checkbox'>" : "";
|
||||
|
||||
/* Excluded folders to not show in the dropdown in the '/mnt/' directory only. */
|
||||
$excludedFolders = ['RecycleBin', 'addons', 'rootshare'];
|
||||
$udShares = ['disks','remotes'];
|
||||
// Excluded UD shares to hide under '/mnt'
|
||||
$UDexcluded = ['RecycleBin', 'addons', 'rootshare'];
|
||||
// Included UD shares to show under '/mnt/user'
|
||||
$UDincluded = ['disks','remotes'];
|
||||
|
||||
echo "<ul class='jqueryFileTree'>";
|
||||
if ($_POST['show_parent'] == 'true' && is_top($rootdir)) {
|
||||
echo "<li class='directory collapsed'>$checkbox<a href='#' rel=\"".htmlspecialchars(dirname($rootdir))."\">..</a></li>";
|
||||
}
|
||||
|
||||
if (is_low($rootdir) && is_dir($rootdir)) {
|
||||
$dirs = $files = [];
|
||||
$names = array_filter(scandir($rootdir, SCANDIR_SORT_NONE), function($n){return $n != '.' && $n != '..';});
|
||||
if (is_dir($rootdir)) {
|
||||
$dirs = $files = [];
|
||||
$names = array_filter(scandir($rootdir, SCANDIR_SORT_NONE), 'no_dots');
|
||||
// add UD shares under /mnt/user
|
||||
foreach ($UDincluded as $name) {
|
||||
if (!is_dir($topdir.$name)) continue;
|
||||
if ($rootdir === $userdir) {
|
||||
if (!in_array($name, $names)) $names[] = $name;
|
||||
} else {
|
||||
if (explode('/', $topdir)[2] === $name) $names = array_merge($names, array_filter(scandir($topdir, SCANDIR_SORT_NONE), 'no_dots'));
|
||||
}
|
||||
}
|
||||
natcasesort($names);
|
||||
foreach ($names as $name) {
|
||||
if (is_dir($rootdir.$name)) {
|
||||
if (is_dir(my_dir($name).$name)) {
|
||||
$dirs[] = $name;
|
||||
} else {
|
||||
$files[] = $name;
|
||||
}
|
||||
}
|
||||
foreach ($dirs as $name) {
|
||||
$htmlRel = htmlspecialchars($rootdir.$name);
|
||||
// Exclude '.Recycle.Bin' from all shares and UD folders from '/mnt'
|
||||
if ($name === '.Recycle.Bin' || ($rootdir === $mntdir && in_array($name, $UDexcluded))) continue;
|
||||
$htmlRel = htmlspecialchars(my_dir($name).$name);
|
||||
$htmlName = htmlspecialchars(mb_strlen($name) <= 33 ? $name : mb_substr($name, 0, 30).'...');
|
||||
|
||||
/* Exclude '.Recycle.Bin' from all directories */
|
||||
if ($name === '.Recycle.Bin') continue;
|
||||
|
||||
/* Exclude folders only when directory is '/mnt/' */
|
||||
if (in_array($name, $excludedFolders) && $rootdir === $topdir) continue;
|
||||
|
||||
if (empty($match) || preg_match("/$match/", $rootdir.$name.'/')) {
|
||||
echo "<li class='directory collapsed'>$checkbox<a href='#' rel=\"$htmlRel/\">$htmlName</a></li>";
|
||||
}
|
||||
}
|
||||
if ($rootdir === $userdir) {
|
||||
// add unassigned devices top level shares
|
||||
foreach ($udShares as $name) if (is_dir($topdir.$name)) {
|
||||
echo "<li class='directory collapsed'>$checkbox<a href='#' rel=\"{$topdir}{$name}/\">$name</a></li>";
|
||||
}
|
||||
}
|
||||
foreach ($files as $name) {
|
||||
$htmlRel = htmlspecialchars($rootdir . $name);
|
||||
$htmlRel = htmlspecialchars(my_dir($name).$name);
|
||||
$htmlName = htmlspecialchars($name);
|
||||
$ext = mb_strtolower(pathinfo($name, PATHINFO_EXTENSION));
|
||||
foreach ($filters as $filter) {
|
||||
if (empty($filter) || $ext == $filter) {
|
||||
if (empty($match) || preg_match("/$match/", $name)) {
|
||||
echo "<li class='file ext_$ext'>$checkbox<a href='#' rel=\"$htmlRel\">$htmlName</a></li>";
|
||||
}
|
||||
foreach ($filters as $filter) if (empty($filter) || $ext === $filter) {
|
||||
if (empty($match) || preg_match("/$match/", $name)) {
|
||||
echo "<li class='file ext_$ext'>$checkbox<a href='#' rel=\"$htmlRel\">$htmlName</a></li>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user