From fd3e5de80fa6f0c0c435031e31474d3d509adbff Mon Sep 17 00:00:00 2001 From: bergware Date: Fri, 21 Mar 2025 15:20:27 +0100 Subject: [PATCH 1/4] File manager: style fixes --- emhttp/plugins/dynamix/Browse.page | 165 +++++++++++-------- emhttp/plugins/dynamix/BrowseButton.page | 49 ++++-- emhttp/plugins/dynamix/include/Browse.php | 14 +- emhttp/plugins/dynamix/include/Control.php | 7 +- emhttp/plugins/dynamix/include/Templates.php | 4 +- emhttp/plugins/dynamix/nchan/file_manager | 117 +++++++------ emhttp/plugins/dynamix/sheets/Browse.css | 2 - 7 files changed, 211 insertions(+), 147 deletions(-) diff --git a/emhttp/plugins/dynamix/Browse.page b/emhttp/plugins/dynamix/Browse.page index c2b6fdb5e..8b7cd83cb 100644 --- a/emhttp/plugins/dynamix/Browse.page +++ b/emhttp/plugins/dynamix/Browse.page @@ -3,8 +3,8 @@ Tag="home" Nchan="file_manager" --- "> "> @@ -41,19 +44,20 @@ if (!file_exists($editor)) file_put_contents($editor,implode("\n",['','txt','js' +
_(Type)__(Name)__(Owner)__(Permission)__(Size)__(Last Modified)__(Location)__(Action)_
diff --git a/emhttp/plugins/dynamix/BrowseButton.page b/emhttp/plugins/dynamix/BrowseButton.page index d193921b6..118ee6f19 100644 --- a/emhttp/plugins/dynamix/BrowseButton.page +++ b/emhttp/plugins/dynamix/BrowseButton.page @@ -4,8 +4,8 @@ Icon="icon-u-duplicate" Code="e963" --- $myPage['name']=='Browse', + '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') @@ -28,6 +28,7 @@ if ($dfm['running'] || $dfm['browser']) eval('?>'.parse_file("$docroot/webGui/in function BrowseButton() { location.replace('//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');} @@ -43,7 +44,7 @@ String.prototype.dfm_wedge = function(len){len=len||70;return this.length<=len ? 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) { +function dfm_footer(action, text) { switch (action) { case 'show': $('#countdown').show(); @@ -54,7 +55,7 @@ function dfm_footer(action,text) { $('#user-notice').hide(); break; case 'write': - if ($('#countdown').html()=='') $('#countdown').html(''); + if ($('#countdown').html() == '') $('#countdown').html(''); $('#user-notice').html(text); break; case 'clear': @@ -63,26 +64,32 @@ function dfm_footer(action,text) { break; } } + function dfm_done() { - dfm_footer('write',"_(Searching)_... _(Done)_"); + dfm_footer('write', "_(Searching)_... _(Done)_"); } + function dfm_minimize() { dfm.window.dialog('close'); dfm_footer('show'); } + function dfm_close_button() { $('.ui-dfm .ui-dialog-titlebar-close').html('').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];}); + 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)) { @@ -98,6 +105,7 @@ function dfm_createSource(source) { select.html(''); } } + function dfm_showProgress(data) { if (!data) return 0; let file = null; @@ -105,7 +113,7 @@ function dfm_showProgress(data) { let line = text[0].split('... '); let strict = /^mnt|^boot/; let footer = false; - if (text[0]=='#cat#') { + if (text[0] == '#cat#') { let loc = [], cat = []; for (let i=1,row; row=text[i]; i++) { if (!row) continue; @@ -119,7 +127,7 @@ function dfm_showProgress(data) { dfm.window.find('#dfm_files').html(loc.length+" "+"_(files)_"); } return cat.length; - } else if (text.length==1) { + } else if (text.length == 1) { text = text[0].dfm_wedge(80); footer = text.indexOf("_(Searching)_") != -1; } else { @@ -134,10 +142,11 @@ function dfm_showProgress(data) { footer = true; } } - if (file==null || strict.test(file)) dfm.window.find('.dfm_text').html((file?line[0]+'... /'+dfm_escapeHTML(file.dfm_wedge())+'
':'')+text); + if (file == null || strict.test(file)) dfm.window.find('.dfm_text').html((file?line[0]+'... /'+dfm_escapeHTML(file.dfm_wedge())+'
':'')+text); if (footer) dfm_footer('write',text); return 0; } + function dfm_fileManager(action) { switch (action) { case 'start': @@ -161,14 +170,15 @@ function dfm_fileManager(action) { break; } } + function dfm_makeDialog(open) { - if (open && dfm_read.action==15) { + 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'); + 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 @@ -245,8 +255,8 @@ function dfm_makeDialog(open) { dfm.window.find('.dfm_sparse').css({'opacity':'0.5'}); dfm.window.find('.dfm_exist').css({'opacity':'0.5'}); dfm.window.dialog({ - dialogClass: 'ui-dfm', - autoOpen: open||dfm.dialog, + classes: {'ui-dialog': 'ui-dfm'}, + autoOpen: open || dfm.dialog, title: dfm_read.title, height: dfm.height, width: 900, @@ -254,7 +264,7 @@ function dfm_makeDialog(open) { modal: true, buttons: { "_(Start)_": function(){ - if (dfm_read.action==15) { + 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)_..."); @@ -280,6 +290,7 @@ function dfm_makeDialog(open) { 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) { @@ -289,6 +300,7 @@ function dfm_openDialog(open) { dfm_makeDialog(open); }); } + var nchan_filemanager = new NchanSubscriber('/sub/filemanager',{subscriber:'websocket'}); nchan_filemanager.on('message', function(msg) { let data = $.parseJSON(msg); @@ -304,7 +316,7 @@ nchan_filemanager.on('message', function(msg) { $('.ui-dfm .ui-dialog-buttonset button:lt(2)').prop('disabled',false); } else { let cat = dfm_showProgress(data.status); - if (data.done==1) { + if (data.done == 1) { setTimeout(function(){$.post('/webGui/include/Control.php',{mode:'start'},function(queue){ switch (parseInt(queue)) { case 0: @@ -324,16 +336,17 @@ nchan_filemanager.on('message', function(msg) { break; } })}); - } else if (data.done==2) { + } 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 (cat == 0) dfm.window.find('.dfm_text').html("_(No results found)_"); if ($('#user-notice:visible')) dfm_done(); } } }); + $(function(){ dfm_openDialog(); diff --git a/emhttp/plugins/dynamix/include/Browse.php b/emhttp/plugins/dynamix/include/Browse.php index f0895c079..1e58d5811 100644 --- a/emhttp/plugins/dynamix/include/Browse.php +++ b/emhttp/plugins/dynamix/include/Browse.php @@ -1,6 +1,6 @@ ',implode(array_map(function($row){echo gzinflate($row);},$rows)),''; $rows = $size; } + function validdir($dir) { $path = realpath($dir); return in_array(explode('/',$path)[1]??'',['mnt','boot']) ? $path : ''; } + function escapeQuote($data) { return str_replace('"','"',$data); } + function add($number, $name, $single='', $plural='s') { return $number.' '._($name.($number==1 ? $single : $plural)); } + function age($number,$time) { return sprintf(_('%s '.($number==1 ? $time : $time.'s').' ago'),$number); } + function my_age($time) { if (!is_numeric($time)) $time = time(); $age = new DateTime('@'.$time); @@ -46,11 +51,13 @@ function my_age($time) { if ($age->i > 0) return age($age->i,'minute'); return age($age->s,'second'); } + function parent_link() { global $dir,$path; $parent = dirname($dir); return $parent=='/' ? false : ''._('Parent Directory').''; } + function my_devs(&$devs,$name,$menu) { global $disks,$lock; $text = []; $i = 0; @@ -72,6 +79,7 @@ function my_devs(&$devs,$name,$menu) { } return implode($text); } + function icon_class($ext) { switch ($ext) { case '3gp': case 'asf': case 'avi': case 'f4v': case 'flv': case 'm4v': case 'mkv': case 'mov': case 'mp4': case 'mpeg': case 'mpg': case 'm2ts': case 'ogm': case 'ogv': case 'vob': case 'webm': case 'wmv': @@ -144,6 +152,7 @@ if ($user ) { 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|%U|%A|%s|%Y|%n' ".escapeshellarg($dir)."/* 2>/dev/null",'r'); while (($row = fgets($stat))!==false) { [$type,$owner,$perm,$size,$time,$name] = explode('|',rtrim($row,"\n"),6); @@ -178,6 +187,7 @@ while (($row = fgets($stat))!==false) { $total += $size; } } + pclose($stat); if ($link = parent_link()) echo '',$link,''; echo write($dirs),write($files),'',add($objs,'object'),': ',add($dirs,'director','y','ies'),', ',add($files,'file'),' (',my_scale($total,$unit),' ',$unit,' ',_('total'),')'; diff --git a/emhttp/plugins/dynamix/include/Control.php b/emhttp/plugins/dynamix/include/Control.php index 66aa20ab3..045da6886 100644 --- a/emhttp/plugins/dynamix/include/Control.php +++ b/emhttp/plugins/dynamix/include/Control.php @@ -1,6 +1,6 @@ i > 0) return age($age->i,'minute'); return age($age->s,'second'); } + function validname($name) { $path = realpath(dirname($name)); return in_array(explode('/',$path)[1]??'',['mnt','boot']) ? $path.'/'.basename($name) : ''; } + function escape($name) {return escapeshellarg(validname($name));} function quoted($name) {return is_array($name) ? implode(' ',array_map('escape',$name)) : escape($name);} diff --git a/emhttp/plugins/dynamix/include/Templates.php b/emhttp/plugins/dynamix/include/Templates.php index 2d827c0c8..f1f23fe73 100644 --- a/emhttp/plugins/dynamix/include/Templates.php +++ b/emhttp/plugins/dynamix/include/Templates.php @@ -1,6 +1,6 @@ 0) { + $rows = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + if (count($rows) > 0) { natcasesort($rows); - $user = array_filter($rows,function($path){return preg_match('/^\/mnt\/user0?\//',$path);}); - if (count($user)>0) { + $user = array_filter($rows, function($path){return preg_match('/^\/mnt\/user0?\//', $path);}); + if (count($user) > 0) { for ($n=0; $n < count($user); $n+=100) { - $name = array_slice($user,$n,100); + $name = array_slice($user, $n, 100); $set[] = exec("getfattr --no-dereference --absolute-names --only-values -n system.LOCATIONS ".quoted($name)." 2>$null"); } - $disks = parse_ini_file('state/disks.ini',true); + $disks = parse_ini_file('state/disks.ini', true); $tag = implode('|',array_merge(['disk'],pools_filter($disks))); - $set = explode(';',str_replace(',;',',',preg_replace("/($tag)/",';$1',implode($set)))); + $set = explode(';',str_replace(',;',',',preg_replace("/($tag)/", ';$1', implode($set)))); } - foreach (array_diff($rows,$user) as $row) { - [$none,$root,$main] = explode('/',$row,4); - $cat[] = ($root=='mnt' ? $main : ($root=='boot' ? 'flash' : '---'))."\0".$row; + foreach (array_diff($rows, $user) as $row) { + [$none, $root, $main] = explode('/',$row,4); + $cat[] = ($root == 'mnt' ? $main : ($root == 'boot' ? 'flash' : '---'))."\0".$row; } $i = 0; foreach ($user as $row) $cat[] = $set[++$i]."\0".$row; } return "#cat#\n".implode("\n",$cat)."\n"; } + function escape($name) {return escapeshellarg(validname($name));} -function quoted($name) {return is_array($name) ? implode(' ',array_map('escape',$name)) : escape($name);} -function source($name) {return is_array($name) ? implode(' ',array_map('escapeshellarg',$name)) : escapeshellarg($name);} +function quoted($name) {return is_array($name) ? implode(' ',array_map('escape', $name)) : escape($name);} +function source($name) {return is_array($name) ? implode(' ',array_map('escapeshellarg', $name)) : escapeshellarg($name);} while (true) { - unset($action,$source,$target,$H,$sparse,$exist,$zfs); + unset($action, $source, $target, $H, $sparse, $exist, $zfs); if (file_exists($active)) extract(parse_ini_file($active)); $reply = []; if (isset($action)) { // check for language changes - extract(parse_plugin_cfg('dynamix',true)); + extract(parse_plugin_cfg('dynamix', true)); if ($display['locale'] != $locale_init) { $locale_init = $display['locale']; update_translation($locale_init); } - $source = explode("\r",$source); + $source = explode("\r", $source); switch ($action) { case 0: // create folder if (!empty($pid)) { $reply['status'] = ''._('Creating').'...'; } else { $dir = $source[0].'/'.$target; - exec("mkdir -pm0777 ".quoted($dir)." 1>$null 2>$error & echo $!",$pid); + exec("mkdir -pm0777 ".quoted($dir)." 1>$null 2>$error & echo $!", $pid); exec("chown -Rfv nobody:users ".quoted($dir)); } break; @@ -129,7 +138,7 @@ while (true) { if (!empty($pid)) { $reply['status'] = ''._('Removing').'... '.exec("tail -1 $status"); } else { - exec("find ".quoted($source)." -name \"*\" -print -delete 1>$status 2>$null & echo \$!",$pid); + exec("find ".quoted($source)." -name \"*\" -print -delete 1>$status 2>$null & echo \$!", $pid); } break; case 2: // rename folder @@ -138,18 +147,18 @@ while (true) { $reply['status'] = ''._('Renaming').'...'; } else { $path = dirname($source[0]); - exec("mv -f ".quoted($source)." ".quoted("$path/$target")." 1>$null 2>$error & echo \$!",$pid); + exec("mv -f ".quoted($source)." ".quoted("$path/$target")." 1>$null 2>$error & echo \$!", $pid); } break; case 3: // copy folder case 8: // copy file if (!empty($pid)) { - $reply['status'] = ''._('Copying').'... '.shell_exec("tail -2 $status|awk -F\"\\r\" '{gsub(/^ +/,\"\",\$NF);print \$NF}'"); + $reply['status'] = ''._('Copying').'... '.shell_exec("tail -2 $status | awk -F\"\\r\" '{gsub(/^ +/,\"\",\$NF);print \$NF}'"); } else { - $target = validname($target,false); + $target = validname($target, false); if ($target) { $mkpath = isdir($target) ? '--mkpath' : ''; - exec("rsync -ahPIX$H $sparse $exist $mkpath --out-format=%f --info=flist0,misc0,stats0,name1,progress2 ".quoted($source)." ".escapeshellarg($target)." 1>$status 2>$error & echo \$!",$pid); + exec("rsync -ahPIX$H $sparse $exist $mkpath --out-format=%f --info=flist0,misc0,stats0,name1,progress2 ".quoted($source)." ".escapeshellarg($target)." 1>$status 2>$error & echo \$!", $pid); } else { $reply['error'] = 'Invalid target name'; } @@ -158,13 +167,13 @@ while (true) { case 4: // move folder (rsync) case 9: // move file (rsync) if (!empty($pid)) { - $reply['status'] = ''._('Moving').'... '.($move===false ? exec("tail -1 $status") : shell_exec("tail -2 $status|awk -F\"\\r\" '{gsub(/^ +/,\"\",\$NF);print \$NF}'")); + $reply['status'] = ''._('Moving').'... '.($move===false ? exec("tail -1 $status") : shell_exec("tail -2 $status | awk -F\"\\r\" '{gsub(/^ +/,\"\",\$NF);print \$NF}'")); } else { - $target = validname($target,false); + $target = validname($target, false); if ($target) { $move = true; $mkpath = isdir($target) ? '--mkpath' : ''; - exec("rsync -ahPIX$H $sparse $exist $mkpath --out-format=%f --info=flist0,misc0,stats0,name1,progress2 --remove-source-files ".quoted($source)." ".escapeshellarg($target)." 1>$status 2>$error & echo \$!",$pid); + exec("rsync -ahPIX$H $sparse $exist $mkpath --out-format=%f --info=flist0,misc0,stats0,name1,progress2 --remove-source-files ".quoted($source)." ".escapeshellarg($target)." 1>$status 2>$error & echo \$!", $pid); } else { $reply['error'] = 'Invalid target name'; } @@ -175,10 +184,10 @@ while (true) { if (!empty($pid)) { $reply['status'] = ''._('Moving').'...'; } else { - $target = validname($target,false); + $target = validname($target, false); if ($target) { $f = $exist ? 'f' : 'n'; - exec("mv -{$f}t ".escapeshellarg($target)." ".quoted($source)." 1>$status 2>$error & echo \$!",$pid); + exec("mv -{$f}t ".escapeshellarg($target)." ".quoted($source)." 1>$status 2>$error & echo \$!", $pid); } else { $reply['error'] = 'Invalid target name'; } @@ -186,37 +195,37 @@ while (true) { break; case 11: // change owner if (!empty($pid)) { - $reply['status'] = ''._('Updating').'... '.exec("tail -2 $status|grep -Pom1 \"^.+ of '\\K[^']+\""); + $reply['status'] = ''._('Updating').'... '.exec("tail -2 $status | grep -Pom1 \"^.+ of '\\K[^']+\""); } else { - exec("chown -Rfv $target ".quoted($source)." 1>$status 2>$error & echo \$!",$pid); + exec("chown -Rfv $target ".quoted($source)." 1>$status 2>$error & echo \$!", $pid); } break; case 12: // change permission if (!empty($pid)) { - $reply['status'] = ''._('Updating').'... '.exec("tail -2 $status|grep -Pom1 \"^.+ of '\\K[^']+\""); + $reply['status'] = ''._('Updating').'... '.exec("tail -2 $status | grep -Pom1 \"^.+ of '\\K[^']+\""); } else { - exec("chmod -Rfv $target ".quoted($source)." 1>$status 2>$error & echo \$!",$pid); + exec("chmod -Rfv $target ".quoted($source)." 1>$status 2>$error & echo \$!", $pid); } break; case 15: // search if (!empty($pid)) { - $reply['status'] = ''._('Searching').'... '.exec("wc -l $status|grep -Pom1 '^[0-9]+'"); + $reply['status'] = ''._('Searching').'... '.exec("wc -l $status | grep -Pom1 '^[0-9]+'"); } else { - exec("find ".source($source)." -iname ".escapeshellarg($target)." 1>$status 2>$null & echo \$!",$pid); + exec("find ".source($source)." -iname ".escapeshellarg($target)." 1>$status 2>$null & echo \$!", $pid); } break; case 99: // kill running background process if (!empty($pid)) exec("kill $pid"); - delete_file($active,$status,$error); - unset($pid,$move); + delete_file($active, $status, $error); + unset($pid, $move); break; default: continue 2; } $pid = pgrep($pid??0); - if ($pid===false) { + if ($pid === false) { if (!empty($move)) { - exec("find ".quoted($source)." -type d -empty -print -delete 1>$status 2>$null & echo \$!",$pid); + exec("find ".quoted($source)." -type d -empty -print -delete 1>$status 2>$null & echo \$!", $pid); $move = false; $pid = pgrep($pid); } else { @@ -235,18 +244,18 @@ while (true) { foreach ($datasets as $dataset) if (exec("ls --indicator-style=none /mnt/$dataset|wc -l")==0) exec("zfs destroy $dataset 2>/dev/null"); } } - if (file_exists($error)) $reply['error'] = str_replace("\n","
",trim(file_get_contents($error))); - delete_file($active,$status,$error); - unset($pid,$move); + if (file_exists($error)) $reply['error'] = str_replace("\n","
", trim(file_get_contents($error))); + delete_file($active, $status, $error); + unset($pid, $move); } } } - if (time()-$timer) { + if (time() - $timer) { // update every second - publish('filemonitor',file_exists($active) ? 1 : 0); + publish('filemonitor', file_exists($active) ? 1 : 0); $timer = time(); } - publish('filemanager',json_encode($reply)); + publish('filemanager', json_encode($reply)); usleep(250000); } ?> diff --git a/emhttp/plugins/dynamix/sheets/Browse.css b/emhttp/plugins/dynamix/sheets/Browse.css index 6143a0b62..2e209d726 100644 --- a/emhttp/plugins/dynamix/sheets/Browse.css +++ b/emhttp/plugins/dynamix/sheets/Browse.css @@ -12,7 +12,6 @@ table.tablesorter.indexer thead th:nth-child(2){width:3%!important} table.tablesorter.indexer thead th:nth-child(3){width:auto!important} table.tablesorter.indexer thead th:nth-child(n+4){width:10%!important} table.tablesorter.indexer thead th:nth-child(9){width:3%!important} -table.tablesorter.indexer tbody tr:hover td{background-color:} table.tablesorter.indexer thead th{text-align:left} table.tablesorter.indexer tbody td{text-align:left} table.tablesorter.indexer thead th:last-child{text-align:right} @@ -21,6 +20,5 @@ i[id^="row_"],i[id^="check_"]{cursor:pointer;font-size:1.8rem;color:gray} td[id^="name_"]{cursor:pointer} i.fa-home{font-size:2rem} i.fa-chevron-right{font-size:1.2rem;margin:0 8px} -div.autoheight{width:100%;overflow-y:auto;margin-top:} div#buttons{display:none} .dropdown-menu{z-index:10001} From 0ffe15774a325833856d6ae0eb9b6aa78238a387 Mon Sep 17 00:00:00 2001 From: bergware Date: Fri, 21 Mar 2025 22:34:10 +0100 Subject: [PATCH 2/4] Wrappers: fix PHP error --- emhttp/plugins/dynamix/include/Wrappers.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emhttp/plugins/dynamix/include/Wrappers.php b/emhttp/plugins/dynamix/include/Wrappers.php index 1878f7793..77c9a9ee6 100644 --- a/emhttp/plugins/dynamix/include/Wrappers.php +++ b/emhttp/plugins/dynamix/include/Wrappers.php @@ -181,7 +181,7 @@ function get_nvme_info($device, $info) { switch ($info) { case 'temp': exec("nvme id-ctrl /dev/$device 2>/dev/null | grep -Pom2 '^[wc]ctemp +: \K\d+'",$temp); - return [$temp[0]-273, $temp[1]-273]; + return count($temp) >= 2 ? [$temp[0]-273, $temp[1]-273] : [0, 0]; case 'cctemp': return exec("nvme id-ctrl /dev/$device 2>/dev/null | grep -Pom1 '^cctemp +: \K\d+'")-273; case 'wctemp': From b299a4fe3c4d3c686d315312eb875e7785fd6ca1 Mon Sep 17 00:00:00 2001 From: bergware Date: Fri, 21 Mar 2025 23:03:47 +0100 Subject: [PATCH 3/4] update_2: fix PHP error --- emhttp/plugins/dynamix/nchan/update_2 | 29 +++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/emhttp/plugins/dynamix/nchan/update_2 b/emhttp/plugins/dynamix/nchan/update_2 index 87556f092..aa3d31015 100755 --- a/emhttp/plugins/dynamix/nchan/update_2 +++ b/emhttp/plugins/dynamix/nchan/update_2 @@ -1,7 +1,7 @@ #!/usr/bin/php -q 'green', 'operational' => 'orange']); - return " / ".number_format($power,$power<10?2:1,$number[0]).' '._('W').""; + return " / ".number_format($power, $power < 10 ? 2 : 1, $number[0]).' '._('W').""; } + function my_clock($time) { if (!$time) return _('less than a minute'); $days = floor($time/1440); @@ -45,12 +46,14 @@ function my_clock($time) { $mins = $time%60; return plus($days,'day',($hour|$mins)==0).plus($hour,'hour',$mins==0).plus($mins,'minute',true); } + function find_day($D) { global $days; if ($days[0] == '*') return $D; foreach ($days as $d) if ($d >= $D) return $d; return $days[0]; } + function find_month($M) { global $months, $Y; if ($M > 12) {$M = 1; $Y++;} @@ -58,6 +61,7 @@ function find_month($M) { foreach ($months as $m) if ($m >= $M) return $m; return $months[0]; } + function today($D) { global $days, $M, $Y; if ($days[0]=='*') return date('w',mktime(0,0,0,$M,$D,$Y)); @@ -66,18 +70,22 @@ function today($D) { if (in_array($day,$days)) return $day; } } + function next_day($D) { return find_day(($D+1)%7); } + function last_day() { global $M, $Y; return date('t',mktime(0,0,0,$M,1,$Y)); } + function mkdate($D, $s) { global $M, $Y; if ($s > last_day()) {$s = 1; $M = find_month($M+1);} for ($d = $s; $d < $s+7; $d++) if ($D == date('w',mktime(0,0,0,$M,$d,$Y))) return $d; } + function stage($i) { global $h, $m, $D, $M, $Y, $time, $now; if ($i < 0) { @@ -123,14 +131,17 @@ function stage($i) { } return $t; } + function normalize($type,$count) { $words = explode('_',$type); foreach ($words as &$word) $word = $word==strtoupper($word) ? $word : preg_replace(['/^(ct|cnt)$/','/^blk$/'],['count','block'],strtolower($word)); return ucfirst(implode(' ',$words)).": ".str_replace('_',' ',strtolower($count))."\n"; } + function active_disks($disk) { return substr(_var($disk,'status'),0,7)!='DISK_NP' && in_array(_var($disk,'type'),['Parity','Data']); } + function device_name(&$disk) { switch (_var($disk,'type')) { case 'Extra' : @@ -142,6 +153,7 @@ function device_name(&$disk) { $fancy = _(my_disk(native($name,1)),3); return " $fancy"; } + function yellow_text($disk) { global $var; if (_var($disk, 'type')=='Parity') { @@ -153,6 +165,7 @@ function yellow_text($disk) { } return $text; } + function device_status(&$disk, &$error, &$warning) { global $var; if (_var($disk,'type')!='Extra' && _var($var,'fsState')=='Stopped') { @@ -171,6 +184,7 @@ function device_status(&$disk, &$error, &$warning) { } return ""._($text); } + function device_temp(&$disk, &$red, &$orange) { global $display; $spin = strpos(_var($disk,'color'),'blink')===false; @@ -189,6 +203,7 @@ function device_temp(&$disk, &$red, &$orange) { } return ($spin ? "".my_temp($temp)."" : "*").($nvme ? my_power($dev) : ""); } + function device_smart(&$disk, &$fail, &$smart) { global $numbers,$saved; if (!_var($disk,'device') || strpos(_var($disk,'color'),'blink')!==false) return "-"; @@ -222,6 +237,7 @@ function device_smart(&$disk, &$fail, &$smart) { $title .= _('Click for context menu'); return "$text"; } + function device_usage(&$disk, &$full, &$high) { global $display; $text = $display['text']; @@ -242,6 +258,7 @@ function device_usage(&$disk, &$full, &$high) { return $text%10==0 ? "-" : "-
"; } } + function array_group($type, $pool=false) { global $disks,$error,$warning,$red,$orange,$fail,$smart,$full,$high; if ($type != 'Data') {$error = $warning = $red = $orange = $fail = $smart = $full = $high = 0;} @@ -257,6 +274,7 @@ function array_group($type, $pool=false) { } return implode($echo); } + function extra_group() { global $devs,$error,$warning,$red,$orange,$fail,$smart,$full,$high; $error = $warning = $red = $orange = $fail = $smart = $full = $high = 0; @@ -275,6 +293,7 @@ function extra_group() { } return implode($echo); } + function update_translation($locale) { global $docroot,$language; $language = []; @@ -293,9 +312,11 @@ function update_translation($locale) { } } } + function create_sync($file) { return file_exists($file) ? explode(',',file_get_contents($file)) : []; } + function print_error($error) { return sprintf(_('Finding **%s** error'.($error==1?'':'s')),$error?:'0'); } From cef680037502261dcd30ea1666bb2d665c423726 Mon Sep 17 00:00:00 2001 From: bergware Date: Fri, 21 Mar 2025 23:39:43 +0100 Subject: [PATCH 4/4] update_2: fix PHP error --- emhttp/plugins/dynamix/nchan/update_2 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/emhttp/plugins/dynamix/nchan/update_2 b/emhttp/plugins/dynamix/nchan/update_2 index aa3d31015..d8f682750 100755 --- a/emhttp/plugins/dynamix/nchan/update_2 +++ b/emhttp/plugins/dynamix/nchan/update_2 @@ -35,7 +35,8 @@ function my_power($device) { if (!_var($display,'power')) return ''; $number = _var($display,'number','.,'); [$power,$state] = my_explode('W ', get_nvme_info($device,'state')); - $state = strtr($state, ['non-operational' => 'green', 'operational' => 'orange']); + $power = $power ?: 0; + $state = $state ? strtr($state, ['non-operational' => 'green', 'operational' => 'orange']) : ''; return " / ".number_format($power, $power < 10 ? 2 : 1, $number[0]).' '._('W').""; }