mirror of
https://github.com/unraid/webgui.git
synced 2026-01-19 16:10:17 -06:00
@@ -15,14 +15,22 @@ Link='nav-user'
|
||||
?>
|
||||
<style>
|
||||
/* Additional CSS for when user supplies element */
|
||||
.ca_element_notice{padding-right:20px;width:100%;height:40px;line-height:40px;color:#e68a00;background:#feefb3;border-bottom:#e68a00 1px solid;text-align:center;font-size:1.4rem;z-index:900;display:none;}
|
||||
.ca_PluginUpdateDismiss{float:right;margin-right:20px;cursor:pointer;}
|
||||
.ca_pluginUpdateInfo{cursor:pointer;}
|
||||
.ca_PluginUpdateInstall{cursor:pointer;}
|
||||
a.bannerInfo {cursor:pointer;text-decoration:none;}
|
||||
.bannerInfo::before {content:"\f05a";font-family:fontAwesome;color:#e68a00;}
|
||||
.ca_element_notice{padding-right:20px;width:100%;height:40px;line-height:40px;color:#e68a00;background:#feefb3;border-bottom:#e68a00 1px solid;text-align:center;font-size:1.4rem;z-index:900;}
|
||||
a.ca_PluginUpdateInstall{cursor:pointer;}
|
||||
span.ca_PluginUpdateDismiss{float:right;margin-right:20px;cursor:pointer;}
|
||||
span.bannerInfo {cursor:pointer;text-decoration:none;margin:0 12px 0 6px;}
|
||||
span.bannerInfo::before {content:"\f05a";font-family:fontAwesome;color:#e68a00;}
|
||||
</style>
|
||||
<script>
|
||||
const ca_args = {};
|
||||
|
||||
function ca_refresh() {
|
||||
<?if ($task == 'Plugins'):?>
|
||||
loadlist();
|
||||
<?else:?>
|
||||
refresh();
|
||||
<?endif;?>
|
||||
}
|
||||
|
||||
function ca_hidePluginUpdate(plugin,version,element) {
|
||||
$.cookie(plugin,version);
|
||||
@@ -30,14 +38,21 @@ function ca_hidePluginUpdate(plugin,version,element) {
|
||||
}
|
||||
|
||||
function ca_pluginUpdateInstall(plugin) {
|
||||
openBox("/plugins/dynamix.plugin.manager/scripts/plugin&arg1=update&arg2="+plugin,"_(Installing Update)_",600,900,true,"window.location.reload()");
|
||||
}
|
||||
|
||||
function ca_pluginUpdateShowInfo(cmd,title,height,width,load,func,id) {
|
||||
// open shadowbox window (run in foreground)
|
||||
var run = cmd.split('?')[0].substr(-4)=='.php' ? cmd : '/logging.htm?cmd='+cmd+'&csrf_token=<?=$var['csrf_token']?>';
|
||||
var options = load ? (func ? {modal:true,onClose:function(){setTimeout(func+'('+'"'+(id||'')+'")',0);}} : {modal:false,onClose:function(){location.reload();}}) : {modal:false};
|
||||
Shadowbox.open({content:run, player:'iframe', title:title, height:Math.min(height,screen.availHeight), width:Math.min(width,screen.availWidth), options:options});
|
||||
if (plugin == null) {
|
||||
openPlugin(ca_args.cmd,ca_args.title,'','ca_refresh');
|
||||
return;
|
||||
}
|
||||
ca_args.cmd = 'plugin update '+plugin;
|
||||
ca_args.title = "_(Installing Update)_";
|
||||
$.get('/plugins/dynamix.plugin.manager/include/ShowPlugins.php',{cmd:'alert'},function(data) {
|
||||
if (data==0) {
|
||||
// no alert message - proceed with update
|
||||
setTimeout(ca_pluginUpdateInstall);
|
||||
} else {
|
||||
// show alert message and ask for confirmation
|
||||
openAlert("showchanges <?=$alerts?>","_(Alert Message)_","ca_pluginUpdateInstall");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function caPluginUpdateCheck(plugin,options=[],callback) {
|
||||
@@ -54,21 +69,20 @@ function caPluginUpdateCheck(plugin,options=[],callback) {
|
||||
if ( options.debug == true ) result.updateAvailable = true;
|
||||
if ( ! options.element && ! options.dontShow ) {
|
||||
if ( result.updateAvailable ) {
|
||||
var HTML = result.updateMessage+" <a class='ca_PluginUpdateInstall' onclick='ca_pluginUpdateInstall(""+plugin+"");'>"+result.linkMessage+"</a> <a class='bannerInfo fa fa-info-circle' onclick='ca_pluginUpdateShowInfo("/plugins/dynamix.plugin.manager/include/ShowChanges.php?file=/tmp/plugins/"+pluginFilename+".txt","_(Release Notes)_",600,900); return false;'></a>";
|
||||
var HTML = result.updateMessage+"<span class='bannerInfo fa fa-info-circle big' title=\"_(View Release Notes)_\" onclick='openChanges(\"showchanges /tmp/plugins/"+pluginFilename+".txt\",\"_(Release Notes)_\")'></span><a class='ca_PluginUpdateInstall' onclick='ca_pluginUpdateInstall(\""+plugin+"\")'>"+result.linkMessage+"</a>";
|
||||
addBannerWarning(HTML,false,options.noDismiss);
|
||||
}
|
||||
} else {
|
||||
if ( $.cookie(plugin) != result.version ) {
|
||||
if ( result.updateAvailable ) {
|
||||
var HTML = result.updateMessage+" <a class='ca_PluginUpdateInstall' onclick='ca_pluginUpdateInstall(""+plugin+"");'>"+result.linkMessage+"</a> <a class='bannerInfo fa fa-info-circle' onclick='ca_pluginUpdateShowInfo("/plugins/dynamix.plugin.manager/include/ShowChanges.php?file=/tmp/plugins/"+pluginFilename+".txt","_(Release Notes)_",600,900); return false;'></a>";
|
||||
var HTML = result.updateMessage+"<span class='bannerInfo fa fa-info-circle big' title=\"_(View Release Notes)_\" onclick='openChanges(\"showchanges /tmp/plugins/"+pluginFilename+".txt\",\"_(Release Notes)_\")'></span><a class='ca_PluginUpdateInstall' onclick='ca_pluginUpdateInstall(\""+plugin+"\")'>"+result.linkMessage+"</a>";
|
||||
if ( ! options.noDismiss ) {
|
||||
HTML = HTML.concat("<span class='ca_PluginUpdateDismiss'><i class='fa fa-close' onclick='ca_hidePluginUpdate(""+plugin+"",""+result.version+"",""+options.element+"");'></i>");
|
||||
HTML = HTML.concat("<span class='ca_PluginUpdateDismiss'><i class='fa fa-close' onclick='ca_hidePluginUpdate(\""+plugin+"\",\""+result.version+"\",\""+options.element+"\")'></i></span>");
|
||||
}
|
||||
result.HTML = HTML;
|
||||
|
||||
if ( ! options.dontShow ) {
|
||||
$(options.element).html(HTML);
|
||||
$(options.element).addClass("ca_element_notice").show();
|
||||
$(options.element).addClass("ca_element_notice");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,5 +95,4 @@ function caPluginUpdateCheck(plugin,options=[],callback) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -15,17 +15,31 @@ Tag="download"
|
||||
*/
|
||||
?>
|
||||
<script>
|
||||
function installPlugin(name) {
|
||||
var file = name.trim();
|
||||
var plugin = file.replace(/^.*(\\|\/|\:)/,'').replace('.plg','')+':install';
|
||||
var func = plugin.includes('dynamix.unraid.net') ? 'reloadToList' : 'loadlist'; // conditionally reload on closure of shadboxbox for My Servers plugin
|
||||
if (file) openBox("/plugins/dynamix.plugin.manager/scripts/plugin&arg1=install&arg2="+file,"_(Install Plugin)_",600,900,true,func,plugin);
|
||||
const my = {};
|
||||
|
||||
function installPlugin(file) {
|
||||
if (file == null) {
|
||||
$('#plugin_file').val('');
|
||||
openPlugin(my.cmd,my.title,my.plg);
|
||||
return;
|
||||
}
|
||||
file = file.trim();
|
||||
if (!file) return;
|
||||
$.get('/plugins/dynamix.plugin.manager/include/ShowPlugins.php',{cmd:'alert'},function(data) {
|
||||
my.cmd = 'plugin install '+file;
|
||||
my.title = "_(Install Plugin)_";
|
||||
my.plg = file.replace(/^.*(\\|\/|\:)/,'').replace('.plg','')+':install';
|
||||
if (data==0) {
|
||||
// no alert message - proceed with install
|
||||
setTimeout(installPlugin);
|
||||
} else {
|
||||
// show alert message and ask for confirmation
|
||||
openAlert("showchanges <?=$alerts?>","<?=_('Alert Message')?>",'installPlugin');
|
||||
}
|
||||
});
|
||||
}
|
||||
function reloadToList() {
|
||||
$.removeCookie('tab');
|
||||
window.location.href = '/Plugins';
|
||||
};
|
||||
</script>
|
||||
|
||||
**_(Enter URL of remote plugin file or local plugin file)_**
|
||||
|
||||
<form name="plugin_install" method="POST" target="progressFrame">
|
||||
|
||||
@@ -18,8 +18,10 @@ Code="e944"
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
// Remove stale /tmp/plugin/*.plg entries
|
||||
foreach (glob("/tmp/plugins/*.{plg,txt}", GLOB_NOSORT+GLOB_BRACE) as $entry) if (!file_exists("/var/log/plugins/".basename($entry))) @unlink($entry);
|
||||
// Remove stale /tmp/plugin/*.plg entries (check that script 'plugin' is not running to avoid clashes)
|
||||
if (!exec("pgrep -f $docroot/plugins/dynamix.plugin.manager/scripts/plugin")) {
|
||||
foreach (glob("/tmp/plugins/*.{plg,txt}", GLOB_NOSORT+GLOB_BRACE) as $entry) if (!file_exists("/var/log/plugins/".basename($entry))) @unlink($entry);
|
||||
}
|
||||
$check = $notify['version'] ? 0 : 1;
|
||||
?>
|
||||
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.filetree.css')?>">
|
||||
@@ -27,8 +29,29 @@ $check = $notify['version'] ? 0 : 1;
|
||||
#plugin_tree{width:33%;height:200px;overflow-y:scroll}
|
||||
table tbody td{line-height:normal}
|
||||
</style>
|
||||
|
||||
<script src="<?autov('/webGui/javascript/jquery.filetree.js')?>" charset="utf-8"></script>
|
||||
<script>
|
||||
const args = {};
|
||||
|
||||
function openInstall(cmd,title,plg) {
|
||||
if (cmd == null) {
|
||||
openPlugin(args.cmd,args.title,args.plg);
|
||||
return;
|
||||
}
|
||||
args.cmd = cmd;
|
||||
args.title = title;
|
||||
args.plg = plg;
|
||||
$.get('/plugins/dynamix.plugin.manager/include/ShowPlugins.php',{cmd:'alert'},function(data) {
|
||||
if (data==0) {
|
||||
// no alert message - proceed with update
|
||||
setTimeout(openInstall);
|
||||
} else {
|
||||
// show alert message and ask for confirmation
|
||||
openAlert("showchanges <?=$alerts?>","_(Alert Message)_",'openInstall');
|
||||
}
|
||||
});
|
||||
}
|
||||
<?if ($display['resize']):?>
|
||||
function resize(bind) {
|
||||
var width = [];
|
||||
@@ -42,6 +65,19 @@ function resize(bind) {
|
||||
}
|
||||
}
|
||||
<?endif;?>
|
||||
function multiRemove() {
|
||||
if ($('input.remove:checked').length > 1) $('#removeall').show(); else $('#removeall').hide();
|
||||
}
|
||||
function updateList() {
|
||||
let list = [];
|
||||
$('input.update').each(function(){list.push($(this).attr('data'));});
|
||||
openPlugin("multiplugin update "+list.join('*'),"_(Update All Plugins)_",":return");
|
||||
}
|
||||
function removeList() {
|
||||
let list = [];
|
||||
$('input.remove:checked').each(function(){list.push($(this).attr('data'));});
|
||||
openPlugin("multiplugin remove "+list.join('*'),"_(Remove Selected Plugins)_","","refresh");
|
||||
}
|
||||
function updateInfo(data) {
|
||||
var updates = data.split('\n');
|
||||
for (var n=0,update; update=updates[n]; n++) {
|
||||
@@ -52,9 +88,6 @@ function updateInfo(data) {
|
||||
}
|
||||
}
|
||||
}
|
||||
function disableButton() {
|
||||
$('#plugin_list').find('input[type=button]').prop('disabled',true);
|
||||
}
|
||||
function initlist() {
|
||||
timers.plugins = setTimeout(function(){$('div.spinner.fixed').show('slow');},500);
|
||||
$.get('/plugins/dynamix.plugin.manager/include/ShowPlugins.php',{init:true,check:<?=$check?>},function(data) {
|
||||
@@ -94,14 +127,14 @@ function loadlist(id,check) {
|
||||
$('#plugin_table').trigger('update');
|
||||
$('#checkall').find('input').prop('disabled',false);
|
||||
if (data[1] > 1) $('#updateall').show(); else $('#updateall').hide();
|
||||
if (data[2] != null) openBox('/plugins/dynamix.plugin.manager/include/ShowChanges.php?file='+data[2],"_(Alert Message)_",600,900);
|
||||
});
|
||||
}
|
||||
$(function() {
|
||||
initlist();
|
||||
$('#plugin_tree').fileTree({root:'/boot/',top:'/boot/',filter:'plg'}, function(file) {$('#plugin_file').val(file);});
|
||||
$('.tabs').append("<span id='updateall' class='status vhshift' style='display:none;margin-left:12px'><input type='button' value='<?=_('Update All Plugins')?>' onclick='disableButton();openBox(\"/plugins/dynamix.plugin.manager/scripts/plugin&arg1=updateall\",\"<?=_('Update All Plugins')?>\",600,600,true,\"loadlist\",\":return\")'></span>");
|
||||
$('.tabs').append("<span id='checkall' class='status vhshift'><input type='button' value='<?=_('Check For Updates')?>' onclick='openBox(\"/plugins/dynamix.plugin.manager/scripts/checkall\",\"<?=_('Plugin Update Check')?>\",600,600,true,\"loadlist\",\":return\")' disabled></span>");
|
||||
$('.tabs').append("<span id='removeall' class='status vhshift' style='display:none;margin-left:12px'><input type='button' value=\"_(Remove Selected Plugins)_\" onclick='removeList()'></span>");
|
||||
$('.tabs').append("<span id='updateall' class='status vhshift' style='display:none;margin-left:12px'><input type='button' value=\"_(Update All Plugins)_\" onclick='updateList()'></span>");
|
||||
$('.tabs').append("<span id='checkall' class='status vhshift'><input type='button' value=\"_(Check For Updates)_\" onclick='openPlugin(\"checkall\",\"_(Plugin Update Check)_\",\":return\")' disabled></span>");
|
||||
});
|
||||
</script>
|
||||
<table class='tablesorter plugins shift' id='plugin_table'>
|
||||
|
||||
@@ -19,9 +19,10 @@ Tag="upload"
|
||||
$version = $branch = $date = _('unknown');
|
||||
$bzroot = file_exists('/boot/previous/bzroot');
|
||||
$check = $notify['unraidos'] ? 0 : 1;
|
||||
$changes = '/boot/previous/changes.txt';
|
||||
|
||||
if (file_exists('/boot/previous/changes.txt')) {
|
||||
exec("head -n4 /boot/previous/changes.txt",$rows);
|
||||
if (file_exists($changes)) {
|
||||
exec("head -n4 $changes",$rows);
|
||||
foreach ($rows as $row) {
|
||||
$i = stripos($row,'version');
|
||||
if ($i !== false) {
|
||||
@@ -39,9 +40,29 @@ input[value="_(Install)_"],input[value="_(Update)_"],input[value="_(Restore)_"]{
|
||||
span.vhshift{margin-top:13px!important}
|
||||
<?endif;?>
|
||||
</style>
|
||||
|
||||
<script>
|
||||
var original = null;
|
||||
const args = {};
|
||||
|
||||
function openInstall(cmd,title,plg) {
|
||||
if (cmd == null) {
|
||||
openPlugin(args.cmd,args.title,args.plg);
|
||||
return;
|
||||
}
|
||||
args.cmd = cmd;
|
||||
args.title = title;
|
||||
args.plg = plg;
|
||||
$.get('/plugins/dynamix.plugin.manager/include/ShowPlugins.php',{cmd:'alert'},function(data) {
|
||||
if (data==0) {
|
||||
// no alert message - proceed with update
|
||||
setTimeout(openInstall);
|
||||
} else {
|
||||
// show alert message and ask for confirmation
|
||||
openAlert("showchanges <?=$alerts?>","_(Alert Message)_",'openInstall');
|
||||
}
|
||||
});
|
||||
}
|
||||
function update_table(branch) {
|
||||
if (original) {
|
||||
if (branch != original) branch = '';
|
||||
@@ -82,21 +103,20 @@ function warning (data) {
|
||||
}
|
||||
function loadlist(id,check) {
|
||||
$.get('/plugins/dynamix.plugin.manager/include/ShowPlugins.php',{system:true,audit:id,check:check||<?=$check?>},function(data) {
|
||||
data = data.split('\0');
|
||||
var list = $('#os_list');
|
||||
if (id) {
|
||||
var cmd = id.split(':');
|
||||
var tr = 'tr#'+cmd[0].replace(/[\. _]/g,'');
|
||||
switch (cmd[1]) {
|
||||
case 'update' : data[0] = warning(data[0]);
|
||||
case 'return' : updateInfo(data[0]); break;
|
||||
case 'install': list.find(tr).remove(); list.append(warning(data[0])); break;
|
||||
case 'update' : data = warning(data);
|
||||
case 'return' : updateInfo(data); break;
|
||||
case 'install': list.find(tr).remove(); list.append(warning(data)); break;
|
||||
}
|
||||
} else {
|
||||
<?if (!$reboot):?>
|
||||
updateInfo(data[0]);
|
||||
updateInfo(data);
|
||||
<?else:?>
|
||||
updateInfo(warning(data[0]));
|
||||
updateInfo(warning(data));
|
||||
<?endif;?>
|
||||
}
|
||||
$('#os_table').trigger('update');
|
||||
@@ -104,12 +124,11 @@ function loadlist(id,check) {
|
||||
<?if ($reboot):?>
|
||||
$('#change_branch').prop('disabled',true);
|
||||
<?endif;?>
|
||||
if (data[1] != null) openBox('/plugins/dynamix.plugin.manager/include/ShowChanges.php?file='+data[1],"_(Alert Message)_",600,900);
|
||||
});
|
||||
}
|
||||
$(function() {
|
||||
initlist();
|
||||
$('.tabs').append("<span class='status vhshift'><input type='button' id='checkos' value='<?=_('Check for Updates')?>' onclick='openBox(\"/plugins/dynamix.plugin.manager/scripts/plugin&arg1=checkos\",\"<?=_('System Update Check')?>\",600,600,true,\"loadlist\",\":return\")' disabled></span>");
|
||||
$('.tabs').append("<span class='status vhshift'><input type='button' id='checkos' value=\"_(Check for Updates)_\" onclick='openPlugin(\"plugin checkos\",\"_(System Update Check)_\",\":return\")' disabled></span>");
|
||||
});
|
||||
</script>
|
||||
<table class='tablesorter plugins shift' id='os_table'>
|
||||
|
||||
@@ -34,16 +34,14 @@ function check_plugin($arg, &$ncsi) {
|
||||
function make_link($method, $arg, $extra='') {
|
||||
$plg = basename($arg,'.plg').':'.$method;
|
||||
$id = str_replace(['.',' ','_'],'',$plg);
|
||||
$check = $method=='remove' ? "<input type='checkbox' onClick='document.getElementById(\"$id\").disabled=!this.checked'>" : "";
|
||||
$check = $method=='remove' ? "<input type='checkbox' data='$arg' class='remove' onClick='document.getElementById(\"$id\").disabled=!this.checked;multiRemove()'>" : "";
|
||||
$disabled = $check ? ' disabled' : '';
|
||||
if ($method == 'delete') {
|
||||
$cmd = "/plugins/dynamix.plugin.manager/scripts/plugin_rm&arg1=$arg";
|
||||
$exec = $plg = "";
|
||||
$cmd = "plugin_rm $arg"; $plg = "";
|
||||
} else {
|
||||
$cmd = "/plugins/dynamix.plugin.manager/scripts/plugin&arg1=$method&arg2=$arg".($extra?"&arg3=$extra":"");
|
||||
$exec = "loadlist";
|
||||
$cmd = "plugin $method $arg".($extra?" $extra":"");
|
||||
}
|
||||
return "$check<input type='button' id='$id' value='"._(ucfirst($method))."' onclick='openBox(\"$cmd\",\""._(ucwords($method)." Plugin")."\",600,900,true,\"$exec\",\"$plg\");'$disabled>";
|
||||
return "$check<input type='button' id='$id' data='$arg' class='$method' value=\""._(ucfirst($method))."\" onclick='openInstall(\"$cmd\",\""._(ucwords($method)." Plugin")."\",\"$plg\");'$disabled>";
|
||||
}
|
||||
|
||||
// trying our best to find an icon
|
||||
|
||||
@@ -23,6 +23,7 @@ $system = unscript($_GET['system']??'');
|
||||
$branch = unscript($_GET['branch']??'');
|
||||
$audit = unscript($_GET['audit']??'');
|
||||
$check = unscript($_GET['check']??'');
|
||||
$cmd = unscript($_GET['cmd']??'');
|
||||
$init = unscript($_GET['init']??'');
|
||||
$empty = true;
|
||||
$install = false;
|
||||
@@ -32,6 +33,12 @@ $builtin = ['unRAIDServer'];
|
||||
$plugins = "/var/log/plugins/*.plg";
|
||||
$ncsi = null; // network connection status indicator
|
||||
|
||||
if ($cmd=='alert') {
|
||||
// signal alert message yer or no
|
||||
echo is_file($alerts) ? 1 : 0;
|
||||
die();
|
||||
}
|
||||
|
||||
if ($audit) {
|
||||
[$plg,$action] = my_explode(':',$audit);
|
||||
switch ($action) {
|
||||
@@ -166,7 +173,7 @@ foreach (glob($plugins,GLOB_NOSORT) as $plugin_link) {
|
||||
if (($changes = plugin('changes',$changes_file)) !== false) {
|
||||
$txtfile = "/tmp/plugins/".basename($plugin_file,'.plg').".txt";
|
||||
file_put_contents($txtfile,$changes);
|
||||
$version .= " <span class='fa fa-info-circle fa-fw big blue-text' title='"._('View Release Notes')."' onclick=\"openBox('/plugins/dynamix.plugin.manager/include/ShowChanges.php?file=$txtfile','"._('Release Notes')."',600,900)\"></span>";
|
||||
$version .= " <span class='fa fa-info-circle fa-fw big blue-text' title='"._('View Release Notes')."' onclick=\"openChanges('showchanges $txtfile','"._('Release Notes')."')\"></span>";
|
||||
}
|
||||
if ($rank < 2 && ($alert = plugin('alert',$changes_file)) !== false) {
|
||||
// generate alert message (if existing) when newer version is available
|
||||
@@ -182,5 +189,4 @@ foreach (glob($plugins,GLOB_NOSORT) as $plugin_link) {
|
||||
}
|
||||
if ($empty) echo "<tr><td colspan='6' style='text-align:center;padding-top:12px'><i class='fa fa-check-square-o icon'></i> "._('No plugins installed')."</td><tr>";
|
||||
if (!$init && !$os) echo "\0".$updates;
|
||||
if (!$init && file_exists($alerts)) echo "\0".$alerts;
|
||||
?>
|
||||
|
||||
54
plugins/dynamix.plugin.manager/post-hooks/post_plugin_checks
Executable file
54
plugins/dynamix.plugin.manager/post-hooks/post_plugin_checks
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2022, Lime Technology
|
||||
* Copyright 2012-2022, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: "/usr/local/emhttp";
|
||||
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
|
||||
|
||||
function readJson($file) {
|
||||
return is_file($file) ? json_decode(file_get_contents($file),true) : [];
|
||||
}
|
||||
function newurl($url) {
|
||||
$oldURL = 'https://raw.github.com/';
|
||||
$newURL = 'https://raw.githubusercontent.com/';
|
||||
return str_replace($oldURL,$newURL,$url);
|
||||
}
|
||||
function searchLink(&$db,$url) {
|
||||
if ($url) for ($i = 0; $i < count($db); $i++) if ($db[$i]['PluginURL']==$url) return $db[$i]['Support'];
|
||||
}
|
||||
|
||||
$method = $argv[1];
|
||||
$plugin = "/boot/config/plugins/{$argv[2]}";
|
||||
|
||||
if ($method == 'install' or $method == 'update') {
|
||||
// update support link in plugin file
|
||||
$info = readJson('/tmp/community.applications/tempFiles/templates.json');
|
||||
// find matching support link
|
||||
$url = plugin('pluginURL', $plugin);
|
||||
if ($support = searchLink($info, $url) ?: searchLink($info, newurl($url))) {
|
||||
// update incorrect or missing support links
|
||||
if (plugin('support', $plugin) != $support) {
|
||||
$xml = @simplexml_load_file($plugin);
|
||||
if ($xml->xpath('//PLUGIN/@support')[0]) {
|
||||
// support link exists, update it
|
||||
$xml->xpath('//PLUGIN/@support')[0] = $support;
|
||||
} else {
|
||||
// support link is missing, add it
|
||||
$xml->addAttribute('support', $support);
|
||||
}
|
||||
echo "Updating support link\n";
|
||||
file_put_contents($plugin, $xml->saveXML());
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
34
plugins/dynamix.plugin.manager/pre-hooks/pre_plugin_checks
Executable file
34
plugins/dynamix.plugin.manager/pre-hooks/pre_plugin_checks
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2022, Lime Technology
|
||||
* Copyright 2012-2022, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: "/usr/local/emhttp";
|
||||
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
|
||||
|
||||
$method = $argv[1];
|
||||
$plugin = $argv[2];
|
||||
|
||||
// validate plugin update (not applicable to OS updates)
|
||||
if ($method == 'check' and $plugin != 'unRAIDServer.plg') {
|
||||
$old_plugin = "/boot/config/plugins/$plugin";
|
||||
$new_plugin = "/tmp/plugins/$plugin";
|
||||
if (plugin('version', $new_plugin) > plugin('version', $old_plugin)) {
|
||||
echo "Validating $plugin update\n";
|
||||
if (($status = plugin('validate', $new_plugin)) != 'valid') {
|
||||
echo "$status\n";
|
||||
// restore original plugin and undo update
|
||||
copy($old_plugin, $new_plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?PHP
|
||||
/* Copyright 2019-2020, Lime Technology
|
||||
* Copyright 2019-2020, Andrew Zawadzki.
|
||||
/* Copyright 2005-2022, Lime Technology
|
||||
* Copyright 2019-2022, Andrew Zawadzki.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -14,81 +14,85 @@ $docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
//add translations
|
||||
$_SERVER['REQUEST_URI'] = "plugins";
|
||||
require_once "$docroot/plugins/dynamix/include/Translations.php";
|
||||
|
||||
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
|
||||
|
||||
function download_url($url, $path = "") {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch,CURLOPT_URL,$url);
|
||||
curl_setopt($ch,CURLOPT_FRESH_CONNECT,true);
|
||||
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
|
||||
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,15);
|
||||
curl_setopt($ch,CURLOPT_TIMEOUT,45);
|
||||
curl_setopt($ch,CURLOPT_ENCODING,"");
|
||||
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt_array($ch,[
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_FRESH_CONNECT => true,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_CONNECTTIMEOUT => 15,
|
||||
CURLOPT_TIMEOUT => 45,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_FOLLOWLOCATION => true
|
||||
]);
|
||||
$out = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
if ( $path )
|
||||
file_put_contents($path,$out);
|
||||
|
||||
if ( $path ) file_put_contents($path,$out);
|
||||
return $out ?: false;
|
||||
}
|
||||
|
||||
switch ($_POST['action']) {
|
||||
case 'checkPlugin':
|
||||
|
||||
$options = $_POST['options'];
|
||||
$plugin = $options['plugin'];
|
||||
|
||||
$name = $options['name'] ?? $plugin;
|
||||
|
||||
if ( ! $plugin || ! file_exists("/var/log/plugins/$plugin") ) {
|
||||
echo json_encode(array("updateAvailable"=>false));
|
||||
echo json_encode(["updateAvailable"=>false]);
|
||||
break;
|
||||
}
|
||||
|
||||
exec("mkdir -p /tmp/plugins");
|
||||
@unlink("/tmp/plugins/$plugin");
|
||||
$url = @plugin("pluginURL","/boot/config/plugins/$plugin");
|
||||
$url = plugin("pluginURL","/boot/config/plugins/$plugin");
|
||||
download_url($url,"/tmp/plugins/$plugin");
|
||||
|
||||
$changes = @plugin("changes","/tmp/plugins/$plugin");
|
||||
$version = @plugin("version","/tmp/plugins/$plugin");
|
||||
$installedVersion = @plugin("version","/boot/config/plugins/$plugin");
|
||||
$min = @plugin("min","/tmp/plugins/$plugin") ?: "6.4.0";
|
||||
$changes = plugin("changes","/tmp/plugins/$plugin");
|
||||
$alerts = plugin("alert","/tmp/plugins/$plugin");
|
||||
$version = plugin("version","/tmp/plugins/$plugin");
|
||||
$installedVersion = plugin("version","/boot/config/plugins/$plugin");
|
||||
$min = plugin("min","/tmp/plugins/$plugin") ?: "6.4.0";
|
||||
if ( $changes ) {
|
||||
file_put_contents("/tmp/plugins/".pathinfo($plugin, PATHINFO_FILENAME).".txt",$changes);
|
||||
} else {
|
||||
@unlink("/tmp/plugins/".pathinfo($plugin, PATHINFO_FILENAME).".txt");
|
||||
}
|
||||
if ( $alerts ) {
|
||||
file_put_contents('/tmp/plugins/my_alerts.txt',$alerts);
|
||||
} else {
|
||||
@unlink('/tmp/plugins/my_alerts.txt');
|
||||
}
|
||||
|
||||
$update = false;
|
||||
if ( strcmp($version,$installedVersion) > 0 ) {
|
||||
$unraid = parse_ini_file("/etc/unraid-version");
|
||||
$update = (version_compare($min,$unraid['version'],">")) ? false : true;
|
||||
$update = version_compare($min,$unraid['version'],'<=');
|
||||
}
|
||||
$updateMessage = sprintf(_("%s: An update is available."),$name);
|
||||
$linkMessage = sprintf(_("Click here to install version %s"),$version);
|
||||
|
||||
echo json_encode(array("updateAvailable" => $update,"version" => $version,"min"=>$min,"changes"=>$changes,"installedVersion"=>$installedVersion,"updateMessage"=>$updateMessage,"linkMessage"=>$linkMessage));
|
||||
echo json_encode(["updateAvailable"=>$update, "version"=>$version, "min"=>$min, "alert"=>$alerts, "changes"=>$changes, "installedVersion"=>$installedVersion, "updateMessage"=>$updateMessage, "linkMessage"=>$linkMessage]);
|
||||
break;
|
||||
|
||||
|
||||
case 'addRebootNotice':
|
||||
$message = htmlspecialchars(trim($_POST['message']));
|
||||
if (!$message) break;
|
||||
|
||||
$existing = @file("/tmp/reboot_notifications",FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: array();
|
||||
if ( ! $message ) break;
|
||||
|
||||
$existing = @file("/tmp/reboot_notifications",FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [];
|
||||
$existing[] = $message;
|
||||
|
||||
|
||||
file_put_contents("/tmp/reboot_notifications",implode("\n",array_unique($existing)));
|
||||
break;
|
||||
|
||||
|
||||
case 'removeRebootNotice':
|
||||
$message = htmlspecialchars(trim($_POST['message']));
|
||||
$existing = file_get_contents("/tmp/reboot_notifications");
|
||||
$newReboots = str_replace($message,"",$existing);
|
||||
file_put_contents("/tmp/reboot_notifications",$newReboots);
|
||||
break;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -24,13 +24,33 @@ $_SERVER['REQUEST_URI'] = 'plugins';
|
||||
$_SESSION['locale'] = $display['locale'];
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
|
||||
$console = !(isset($argv[1]) && $argv[1]=='nchan');
|
||||
|
||||
function write($message){
|
||||
global $console;
|
||||
if ($console) {
|
||||
echo $message;
|
||||
} else {
|
||||
$nchan = curl_init();
|
||||
curl_setopt_array($nchan,[
|
||||
CURLOPT_URL => 'http://localhost/pub/plugins?buffer_length=0',
|
||||
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
|
||||
CURLOPT_POST => 1,
|
||||
CURLOPT_POSTFIELDS => $message,
|
||||
CURLOPT_RETURNTRANSFER => true
|
||||
]);
|
||||
curl_exec($nchan);
|
||||
curl_close($nchan);
|
||||
}
|
||||
}
|
||||
|
||||
// check connectivity first
|
||||
echo _("Checking connectivity")."...\n";
|
||||
write(_("Checking connectivity")."...\n");
|
||||
if (exec("wget --spider --no-check-certificate -nv -T10 -t1 https://www.msftncsi.com/ncsi.txt 2>&1|grep -o 'OK'")) {
|
||||
$check = popen('plugin checkall','r');
|
||||
while (!feof($check)) echo fgets($check);
|
||||
while (!feof($check)) write(fgets($check));
|
||||
pclose($check);
|
||||
} else {
|
||||
echo _("No response, aborting")."!\n";
|
||||
write(_("No response, aborting")."!\n");
|
||||
}
|
||||
?>
|
||||
@@ -1,9 +1,11 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
// Copyright 2005-2020, Lime Technology
|
||||
// Copyright 2005-2022, Lime Technology
|
||||
// License: GPLv2 only
|
||||
//
|
||||
// Program updates made by Bergware International (April 2020)
|
||||
// Program updates made by Bergware International (June 2022)
|
||||
|
||||
$usage = <<<EOF
|
||||
Process language files.
|
||||
|
||||
@@ -30,6 +32,9 @@ Usage: language updateall
|
||||
|
||||
EOF;
|
||||
|
||||
// Error code to description (wget)
|
||||
// ref: https://www.gnu.org/software/wget/manual/html_node/Exit-Status.html
|
||||
//
|
||||
function error_desc($code) {
|
||||
switch($code) {
|
||||
case 0: return 'No errors';
|
||||
@@ -46,38 +51,79 @@ function error_desc($code) {
|
||||
}
|
||||
}
|
||||
|
||||
// Set output control
|
||||
// Check for optional parameter 'nchan'
|
||||
//
|
||||
function console($i) {
|
||||
global $console, $argv;
|
||||
$console = !(isset($argv[$i]) && $argv[$i]=='nchan');
|
||||
}
|
||||
|
||||
// Function to write either to console (echo) or nchan (curl)
|
||||
// Default output is console, use optional parameter "nchan" to write to nchan instead
|
||||
//
|
||||
function write($message) {
|
||||
global $console;
|
||||
if ($console) {
|
||||
echo $message;
|
||||
} else {
|
||||
$nchan = curl_init();
|
||||
curl_setopt_array($nchan,[
|
||||
CURLOPT_URL => 'http://localhost/pub/plugins?buffer_length=0',
|
||||
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
|
||||
CURLOPT_POST => 1,
|
||||
CURLOPT_POSTFIELDS => $message,
|
||||
CURLOPT_RETURNTRANSFER => true
|
||||
]);
|
||||
curl_exec($nchan);
|
||||
curl_close($nchan);
|
||||
}
|
||||
}
|
||||
|
||||
// Download a file from a URL.
|
||||
// Returns TRUE if success else FALSE and fills in error.
|
||||
//
|
||||
function download($url, $name, &$error) {
|
||||
$plg = basename($url);
|
||||
if ($file = popen("wget --compression=auto --no-cache --progress=dot -O $name $url 2>&1", 'r')) {
|
||||
echo "language: downloading: $url ...\r";
|
||||
write("language: downloading: $plg ...\r");
|
||||
$level = -1;
|
||||
while (!feof($file)) {
|
||||
if (preg_match('/\d+%/', fgets($file), $matches)) {
|
||||
$percentage = substr($matches[0],0,-1);
|
||||
if ($percentage > $level) {
|
||||
echo "language: downloading: $url ... $percentage%\r";
|
||||
write("language: downloading: $plg ... $percentage%\r");
|
||||
$level = $percentage;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (($perror = pclose($file)) == 0) {
|
||||
echo "language: downloading: $url ... done\n";
|
||||
write("language: downloading: $plg ... done\n");
|
||||
return true;
|
||||
} else {
|
||||
echo "language: downloading: $url ... failed (".error_desc($perror).")\n";
|
||||
$error = "$url download failure (".error_desc($perror).")";
|
||||
$error = "$plg download failure (".error_desc($perror).")";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$error = "$url failed to open";
|
||||
$error = "$plg failed to open";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with logging message.
|
||||
//
|
||||
function logger($message) {
|
||||
shell_exec("logger $message");
|
||||
}
|
||||
|
||||
// Interpret a language file
|
||||
// Returns TRUE if success, else FALSE and fills in error string.
|
||||
//
|
||||
function language($method, $xml_file, &$error) {
|
||||
global $docroot, $boot, $plugins, $tmp;
|
||||
|
||||
// parse language XML file
|
||||
$xml = file_exists($xml_file) ? simplexml_load_file($xml_file,NULL,LIBXML_NOCDATA) : false;
|
||||
$xml = file_exists($xml_file) ? @simplexml_load_file($xml_file,NULL,LIBXML_NOCDATA) : false;
|
||||
if ($xml === false) {
|
||||
$error = "XML file doesn't exist or xml parse error";
|
||||
return false;
|
||||
@@ -127,7 +173,7 @@ function language($method, $xml_file, &$error) {
|
||||
}
|
||||
case 'dump':
|
||||
// dump file: debugging
|
||||
echo print_r($xml);
|
||||
write(print_r($xml,true));
|
||||
return true;
|
||||
default:
|
||||
// return single attribute
|
||||
@@ -138,7 +184,7 @@ function language($method, $xml_file, &$error) {
|
||||
|
||||
// MAIN - single argument
|
||||
if ($argc < 2) {
|
||||
echo $usage;
|
||||
write($usage);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -147,23 +193,32 @@ $boot = '/boot/config/plugins';
|
||||
$plugins = '/var/log/plugins';
|
||||
$tmp = '/tmp/plugins';
|
||||
$method = $argv[1];
|
||||
$console = true; // default output is console, nchan otherwise
|
||||
|
||||
// language checkall
|
||||
// check all installed languages
|
||||
//
|
||||
if ($method == 'checkall') {
|
||||
echo "language: checking all language packs\n";
|
||||
console(2);
|
||||
write("language: checking all language packs\n");
|
||||
foreach (glob("$plugins/lang-*.xml", GLOB_NOSORT) as $link) {
|
||||
$lang_file = @readlink($link);
|
||||
if ($lang_file === false) continue;
|
||||
if (language('LanguageURL', $lang_file, $error) === false) continue;
|
||||
$name = str_replace('lang-', '', basename($lang_file, '.xml'));
|
||||
$lang = language('Language', $lang_file, $error) ?: $name;
|
||||
echo "language: checking $lang language pack ...\n";
|
||||
write("language: checking $lang language pack ...\n");
|
||||
exec(realpath($argv[0])." check $name >/dev/null");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// language updateall
|
||||
// update all installed languages
|
||||
//
|
||||
if ($method == 'updateall') {
|
||||
echo "language: updating all language packs\n";
|
||||
console(2);
|
||||
write("language: updating all language packs\n");
|
||||
foreach (glob("$plugins/lang-*.xml", GLOB_NOSORT) as $link) {
|
||||
$lang_file = @readlink($link);
|
||||
if ($lang_file === false) continue;
|
||||
@@ -174,7 +229,7 @@ if ($method == 'updateall') {
|
||||
$latest = language('Version', "$tmp/lang-$name.xml", $error);
|
||||
// update only when newer
|
||||
if (strcmp($latest, $version) > 0) {
|
||||
echo "language: updating $lang language pack ...\n";
|
||||
write("language: updating $lang language pack ...\n");
|
||||
exec(realpath($argv[0])." update $name >/dev/null");
|
||||
}
|
||||
}
|
||||
@@ -182,83 +237,94 @@ if ($method == 'updateall') {
|
||||
}
|
||||
|
||||
// MAIN - two arguments
|
||||
if ($argc != 3) {
|
||||
echo $usage;
|
||||
if ($argc < 3) {
|
||||
write($usage);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// language install [language_file]
|
||||
//
|
||||
if ($method == 'install') {
|
||||
echo "language: installing language pack\n";
|
||||
if (substr($argv[2],0,7)=='http://' || substr($argv[2],0,8)=='https://') {
|
||||
console(3);
|
||||
$argv[2] = preg_replace('#[\x00-\x1F\x80-\xFF]#', '', $argv[2]);
|
||||
$name = basename($argv[2]);
|
||||
write("language: installing language pack\n");
|
||||
// check for URL
|
||||
if (preg_match('#^https?://#',$argv[2])) {
|
||||
$langURL = $argv[2];
|
||||
echo "language: downloading $langURL\n";
|
||||
$name = basename($langURL);
|
||||
$xml_file = "$tmp/$name";
|
||||
write("language: downloading: $name\n");
|
||||
if (!download($langURL, $xml_file, $error)) {
|
||||
echo "language: $error\n";
|
||||
write("language: $error\n");
|
||||
@unlink($xml_file);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
$xml_file = realpath($argv[2]);
|
||||
$name = basename($xml_file);
|
||||
}
|
||||
$link_file = "$plugins/$name";
|
||||
$lang_file = "$boot/$name";
|
||||
@unlink($link_file);
|
||||
if (language('install', $xml_file, $error) === false) {
|
||||
echo "language: $error\n";
|
||||
write("language: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
$lang = language('Language', $xml_file, $error) ?: substr($name,0,-4);
|
||||
copy($xml_file, $lang_file);
|
||||
symlink($lang_file, $link_file);
|
||||
echo "language: $lang language pack installed\n";
|
||||
write("language: $lang language pack installed\n");
|
||||
logger("language: $lang language pack installed");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// language check [language]
|
||||
//
|
||||
if ($method == 'check') {
|
||||
console(3);
|
||||
$name = $argv[2];
|
||||
echo "language: checking language pack\n";
|
||||
write("language: checking language pack\n");
|
||||
$link_file = "$plugins/lang-$name.xml";
|
||||
$lang_file = @readlink($link_file);
|
||||
if ($lang_file === false) {
|
||||
echo "language: $name language pack not installed\n";
|
||||
write("language: $name language pack not installed\n");
|
||||
exit(1);
|
||||
}
|
||||
$templateURL = language('TemplateURL', $lang_file, $error);
|
||||
if ($templateURL === false) {
|
||||
echo "language: $error\n";
|
||||
write("language: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
$xml_file = "$tmp/lang-$name.xml";
|
||||
if (!download($templateURL, $xml_file, $error)) {
|
||||
echo "language: $error\n";
|
||||
write("language: $error\n");
|
||||
@unlink($xml_file);
|
||||
exit(1);
|
||||
}
|
||||
$version = language('Version', $xml_file, $error);
|
||||
if ($version === false) {
|
||||
echo "language: $error\n";
|
||||
write("language: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
echo "$version\n";
|
||||
write("$version\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// language update [language]
|
||||
//
|
||||
if ($method == 'update') {
|
||||
console(3);
|
||||
$name = $argv[2];
|
||||
echo "language: updating language pack\n";
|
||||
write("language: updating language pack\n");
|
||||
$link_file = "$plugins/lang-$name.xml";
|
||||
$lang_file = @readlink($link_file);
|
||||
if ($lang_file === false) {
|
||||
echo "language: $name language pack not installed\n";
|
||||
write("language: $name language pack not installed\n");
|
||||
exit(1);
|
||||
}
|
||||
// verify previous check has been done
|
||||
$xml_file = "$tmp/lang-$name.xml";
|
||||
if (!file_exists($xml_file)) {
|
||||
echo "language: update does not exist, perform a check first\n";
|
||||
write("language: update does not exist, perform a check first\n");
|
||||
exit (1);
|
||||
}
|
||||
$lang = language('Language', $xml_file, $error) ?: $name;
|
||||
@@ -266,47 +332,54 @@ if ($method == 'update') {
|
||||
$old_version = language('Version', $lang_file, $error);
|
||||
$new_version = language('Version', $xml_file, $error);
|
||||
if ($new_version == $old_version) {
|
||||
echo "language: $lang language pack not reinstalling same version\n";
|
||||
write("language: $lang language pack not reinstalling same version\n");
|
||||
exit(1);
|
||||
}
|
||||
// install the updated plugin
|
||||
@unlink("$boot/dynamix/lang-$name.zip");
|
||||
@unlink($link_file);
|
||||
if (language('install', $xml_file, $error) === false) {
|
||||
echo "language: $error\n";
|
||||
write("language: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
copy($xml_file, $lang_file);
|
||||
symlink($lang_file, $link_file);
|
||||
echo "language: $lang language pack updated\n";
|
||||
write("language: $lang language pack updated\n");
|
||||
logger("language: $lang language pack updated");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// language remove [language]
|
||||
//
|
||||
if ($method == 'remove') {
|
||||
console(3);
|
||||
$name = $argv[2];
|
||||
echo "language: removing language pack\n";
|
||||
write("language: removing language pack: $name\n");
|
||||
$link_file = "$plugins/lang-$name.xml";
|
||||
$lang_file = @readlink($link_file);
|
||||
if ($lang_file === false) {
|
||||
echo "language: $name language pack not installed\n";
|
||||
write("language: $name language pack not installed\n");
|
||||
exit(1);
|
||||
}
|
||||
$lang = language('Language', $lang_file, $error) ?: $name;
|
||||
if (language('remove', $lang_file, $error) === false) {
|
||||
echo "language: $error\n";
|
||||
write("language: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
echo "language: $lang language pack removed\n";
|
||||
write("language: $lang language pack removed\n");
|
||||
logger("language: $lang language pack removed");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// return attribute
|
||||
//
|
||||
console(3);
|
||||
$xml_file = $argv[2];
|
||||
$value = language($method, $xml_file, $error);
|
||||
if ($value === false) {
|
||||
echo "language: $error\n";
|
||||
write("language: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
echo "$value\n";
|
||||
write("$value\n");
|
||||
exit(0);
|
||||
?>
|
||||
|
||||
48
plugins/dynamix.plugin.manager/scripts/multiplugin
Executable file
48
plugins/dynamix.plugin.manager/scripts/multiplugin
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2022, Lime Technology
|
||||
* Copyright 2012-2022, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$method = $argv[1];
|
||||
$plugins = explode('*',$argv[2]);
|
||||
$console = !(isset($argv[3]) && $argv[3]=='nchan');
|
||||
|
||||
function write($message){
|
||||
global $console;
|
||||
if ($console) {
|
||||
echo $message;
|
||||
} else {
|
||||
$nchan = curl_init();
|
||||
curl_setopt_array($nchan,[
|
||||
CURLOPT_URL => 'http://localhost/pub/plugins?buffer_length=0',
|
||||
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
|
||||
CURLOPT_POST => 1,
|
||||
CURLOPT_POSTFIELDS => $message,
|
||||
CURLOPT_RETURNTRANSFER => true
|
||||
]);
|
||||
curl_exec($nchan);
|
||||
curl_close($nchan);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($plugins as $plugin) {
|
||||
if (!$plugin) continue;
|
||||
$line = '';
|
||||
$run = popen("plugin $method $plugin",'r');
|
||||
while (!feof($run)) {
|
||||
$line .= fgetc($run);
|
||||
if (in_array($line[-1],["\r","\n"])) {write($line); $line = '';}
|
||||
}
|
||||
pclose($run);
|
||||
write("\n");
|
||||
}
|
||||
?>
|
||||
@@ -4,6 +4,8 @@
|
||||
// License: GPLv2 only
|
||||
//
|
||||
// Program updates made by Bergware International (April 2020)
|
||||
// Program updates made by Bergware International (June 2022)
|
||||
|
||||
$usage = <<<EOF
|
||||
Process plugin files.
|
||||
|
||||
@@ -160,32 +162,95 @@ function error_desc($code) {
|
||||
}
|
||||
}
|
||||
|
||||
// Set output control
|
||||
// Check for optional parameter 'nchan'
|
||||
//
|
||||
function console($i) {
|
||||
global $console, $argv;
|
||||
$console = !(isset($argv[$i]) && $argv[$i]=='nchan');
|
||||
}
|
||||
|
||||
// Function to write either to console (echo) or nchan (curl)
|
||||
// Default output is console, use optional parameter "nchan" to write to nchan instead
|
||||
//
|
||||
function write($message) {
|
||||
global $console;
|
||||
if ($console) {
|
||||
echo $message;
|
||||
} else {
|
||||
$nchan = curl_init();
|
||||
curl_setopt_array($nchan,[
|
||||
CURLOPT_URL => 'http://localhost/pub/plugins?buffer_length=0',
|
||||
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
|
||||
CURLOPT_POST => 1,
|
||||
CURLOPT_POSTFIELDS => $message,
|
||||
CURLOPT_RETURNTRANSFER => true
|
||||
]);
|
||||
curl_exec($nchan);
|
||||
curl_close($nchan);
|
||||
}
|
||||
}
|
||||
|
||||
// Run command and obtain output
|
||||
//
|
||||
function run($command) {
|
||||
$run = popen($command,'r');
|
||||
while (!feof($run)) write(fgets($run));
|
||||
return pclose($run);
|
||||
}
|
||||
|
||||
// Run hooked scripts before correct execution of "method"
|
||||
// method = install, update, remove, check
|
||||
// hook programs receives two parameters: method and plugin-name
|
||||
//
|
||||
function pre_hooks() {
|
||||
global $method, $plugin;
|
||||
$hooks = "/usr/local/emhttp/plugins/dynamix.plugin.manager/pre-hooks";
|
||||
foreach (glob("$hooks/*") as $hook) if (is_executable($hook)) {
|
||||
write("Executing hook script: ".basename($hook)."\n");
|
||||
run("$hook $method $plugin");
|
||||
}
|
||||
}
|
||||
|
||||
// Run hooked scripts after successful completion of "method"
|
||||
// method = install, update, remove, check
|
||||
// hook programs receives two parameters: method and plugin-name
|
||||
//
|
||||
function post_hooks() {
|
||||
global $method, $plugin;
|
||||
$hooks = "/usr/local/emhttp/plugins/dynamix.plugin.manager/post-hooks";
|
||||
foreach (glob("$hooks/*") as $hook) if (is_executable($hook)) {
|
||||
write("Executing hook script: ".basename($hook)."\n");
|
||||
run("$hook $method $plugin");
|
||||
}
|
||||
}
|
||||
|
||||
// Download a file from a URL.
|
||||
// Returns TRUE if success else FALSE and fills in error.
|
||||
//
|
||||
function download($url, $name, &$error) {
|
||||
if ($file = popen("wget --compression=auto --no-cache --progress=dot -O $name $url 2>&1", 'r')) {
|
||||
echo "plugin: downloading: $url ...\r";
|
||||
function download($url, $name, &$error, $write=true) {
|
||||
$plg = basename($url);
|
||||
if ($file = popen("wget --compression=auto --no-cache --progress=dot --retry-connrefused --timeout=30 --tries=5 --waitretry=5 -O $name $url 2>&1", 'r')) {
|
||||
if ($write) write("plugin: downloading: $plg ...\r");
|
||||
$level = -1;
|
||||
while (!feof($file)) {
|
||||
if (preg_match('/\d+%/', fgets($file), $matches)) {
|
||||
$percentage = substr($matches[0],0,-1);
|
||||
if ($percentage > $level) {
|
||||
echo "plugin: downloading: $url ... $percentage%\r";
|
||||
if ($write) write("plugin: downloading: $plg ... $percentage%\r");
|
||||
$level = $percentage;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (($perror = pclose($file)) == 0) {
|
||||
echo "plugin: downloading: $url ... done\n";
|
||||
if ($write) write("plugin: downloading: $plg ... done\n");
|
||||
return true;
|
||||
} else {
|
||||
echo "plugin: downloading: $url ... failed (".error_desc($perror).")\n";
|
||||
$error = "$url download failure (".error_desc($perror).")";
|
||||
$error = "$plg download failure (".error_desc($perror).")";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$error = "$url failed to open";
|
||||
$error = "$plg failed to open";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -193,7 +258,6 @@ function download($url, $name, &$error) {
|
||||
// Deal with logging message.
|
||||
//
|
||||
function logger($message) {
|
||||
// echo "$message\n";
|
||||
shell_exec("logger $message");
|
||||
}
|
||||
|
||||
@@ -209,7 +273,7 @@ function plugin($method, $plugin_file, &$error) {
|
||||
$methods = ['install', 'remove'];
|
||||
|
||||
// parse plugin definition XML file
|
||||
$xml = file_exists($plugin_file) ? simplexml_load_file($plugin_file, NULL, LIBXML_NOCDATA) : false;
|
||||
$xml = file_exists($plugin_file) ? @simplexml_load_file($plugin_file, NULL, LIBXML_NOCDATA) : false;
|
||||
if ($xml === false) {
|
||||
$error = "XML file doesn't exist or xml parse error";
|
||||
return false;
|
||||
@@ -217,21 +281,52 @@ function plugin($method, $plugin_file, &$error) {
|
||||
|
||||
// dump
|
||||
if ($method == 'dump') {
|
||||
// echo $xml->asXML();
|
||||
echo print_r($xml);
|
||||
// dump file: debugging
|
||||
write(print_r($xml,true));
|
||||
return true;
|
||||
}
|
||||
|
||||
// release notes
|
||||
if ($method == 'changes') {
|
||||
if (!$xml->CHANGES) return false;
|
||||
return trim($xml->CHANGES);
|
||||
return $xml->CHANGES ? trim($xml->CHANGES) : false;
|
||||
}
|
||||
|
||||
// alert message
|
||||
if ($method == 'alert') {
|
||||
if (!$xml->ALERT) return false;
|
||||
return trim($xml->ALERT);
|
||||
return $xml->ALERT ? trim($xml->ALERT) : false;
|
||||
}
|
||||
|
||||
// validate plugin download without installation
|
||||
if ($method == 'validate') {
|
||||
$name = '/tmp/validate-plugin.tmp';
|
||||
foreach ($xml->FILE as $file) {
|
||||
if ($file->URL) {
|
||||
$url = $file->URL;
|
||||
@unlink($name);
|
||||
} elseif ($file->SHA256) {
|
||||
if (!is_file($name) && download($url, $name, $error, false) === false) {
|
||||
@unlink($name);
|
||||
return false;
|
||||
}
|
||||
if (hash_file('sha256', $name) != $file->SHA256) {
|
||||
$error = "bad file SHA256";
|
||||
@unlink($name);
|
||||
return false;
|
||||
}
|
||||
} elseif ($file->MD5) {
|
||||
if (!is_file($name) && download($url, $name, $error, false) === false) {
|
||||
@unlink($name);
|
||||
return false;
|
||||
}
|
||||
if (md5_file($name) != $file->MD5) {
|
||||
$error = "bad file MD5";
|
||||
@unlink($name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@unlink($name);
|
||||
return "valid";
|
||||
}
|
||||
|
||||
// check if $method is an attribute
|
||||
@@ -254,12 +349,12 @@ function plugin($method, $plugin_file, &$error) {
|
||||
// bergware - check Unraid version dependency (if present)
|
||||
$min = $file->attributes()->Min;
|
||||
if ($min && version_compare($unraid['version'],$min,'<')) {
|
||||
echo "plugin: skipping: ".basename($name)." - Unraid version too low, requires at least version $min\n";
|
||||
write("plugin: skipping: ".basename($name)." - Unraid version too low, requires at least version $min\n");
|
||||
continue;
|
||||
}
|
||||
$max = $file->attributes()->Max;
|
||||
if ($max && version_compare($unraid['version'],$max,'>')) {
|
||||
echo "plugin: skipping: ".basename($name)." - Unraid version too high, requires at most version $max\n";
|
||||
write("plugin: skipping: ".basename($name)." - Unraid version too high, requires at most version $max\n");
|
||||
continue;
|
||||
}
|
||||
// Name can be missing but only makes sense if Run attribute is present
|
||||
@@ -344,17 +439,19 @@ function plugin($method, $plugin_file, &$error) {
|
||||
$command = $file->attributes()->Run;
|
||||
if ($name) {
|
||||
logger("plugin: running: $name");
|
||||
system("$command $name", $retval);
|
||||
$retval = run("$command $name");
|
||||
} elseif ($file->LOCAL) {
|
||||
logger("plugin: running: $file->LOCAL");
|
||||
system("$command $file->LOCAL", $retval);
|
||||
$retval = run("$command $file->LOCAL");
|
||||
} elseif ($file->INLINE) {
|
||||
logger("plugin: running: 'anonymous'");
|
||||
$inline = escapeshellarg($file->INLINE);
|
||||
passthru("echo $inline | $command", $retval);
|
||||
$name = '/tmp/inline.sh';
|
||||
file_put_contents($name, $file->INLINE);
|
||||
$retval = run("$command $name");
|
||||
unlink($name);
|
||||
}
|
||||
if ($retval) {
|
||||
$error = "run failed: $command retval: $retval";
|
||||
if ($retval != 0) {
|
||||
$error = "run failed: $command";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -373,7 +470,7 @@ function move($src_file, $tar_dir) {
|
||||
//
|
||||
// MAIN - single argument
|
||||
if ($argc < 2) {
|
||||
echo $usage;
|
||||
write($usage);
|
||||
exit(1);
|
||||
}
|
||||
$notify = '/usr/local/emhttp/webGui/scripts/notify';
|
||||
@@ -382,11 +479,17 @@ $plugins = '/var/log/plugins';
|
||||
$tmp = '/tmp/plugins';
|
||||
$method = $argv[1];
|
||||
$builtin = ['unRAIDServer','unRAIDServer-'];
|
||||
$console = true; // default output is console, nchan otherwise
|
||||
|
||||
// plugin checkall
|
||||
// check all installed plugins, except built-in
|
||||
//
|
||||
if ($method == 'checkall') {
|
||||
console(2);
|
||||
if (!$cmd = realpath($argv[0])) {
|
||||
write("Unknown command: {$argv[0]}\n");
|
||||
exit(1);
|
||||
}
|
||||
foreach (glob("$plugins/*.plg", GLOB_NOSORT) as $link) {
|
||||
// skip OS related plugins
|
||||
if (in_array(basename($link,'.plg'),$builtin)) continue;
|
||||
@@ -395,8 +498,8 @@ if ($method == 'checkall') {
|
||||
if ($installed_plugin_file === false) continue;
|
||||
if (plugin('pluginURL', $installed_plugin_file, $error) === false) continue;
|
||||
$plugin = basename($installed_plugin_file);
|
||||
echo "plugin: checking $plugin ...\n";
|
||||
exec(realpath($argv[0])." check $plugin >/dev/null");
|
||||
write("plugin: checking $plugin ...\n");
|
||||
exec("$cmd check $plugin >/dev/null");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
@@ -405,6 +508,11 @@ if ($method == 'checkall') {
|
||||
// update all installed plugins, which have a update available
|
||||
//
|
||||
if ($method == 'updateall') {
|
||||
console(2);
|
||||
if (!$cmd = realpath($argv[0])) {
|
||||
write("Unknown command: {$argv[0]}\n");
|
||||
exit(1);
|
||||
}
|
||||
foreach (glob("$plugins/*.plg", GLOB_NOSORT) as $link) {
|
||||
// skip OS related plugins
|
||||
if (in_array(basename($link,'.plg'),$builtin)) continue;
|
||||
@@ -417,8 +525,8 @@ if ($method == 'updateall') {
|
||||
$latest = plugin('version', "$tmp/$plugin", $error);
|
||||
// update only when newer
|
||||
if (strcmp($latest,$version) > 0) {
|
||||
echo "plugin: updating $plugin ...\n";
|
||||
exec(realpath($argv[0])." update $plugin >/dev/null");
|
||||
write("plugin: updating $plugin ...\n");
|
||||
exec("$cmd update $plugin >/dev/null");
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
@@ -428,21 +536,26 @@ if ($method == 'updateall') {
|
||||
// check built-in only
|
||||
//
|
||||
if ($method == 'checkos') {
|
||||
console(2);
|
||||
if (!$cmd = realpath($argv[0])) {
|
||||
write("Unknown command: {$argv[0]}\n");
|
||||
exit(1);
|
||||
}
|
||||
foreach ($builtin as $link) {
|
||||
// only consider symlinks
|
||||
$installed_plugin_file = @readlink("$plugins/$link.plg");
|
||||
if ($installed_plugin_file === false) continue;
|
||||
if (plugin("pluginURL", $installed_plugin_file, $error) === false) continue;
|
||||
$plugin = basename($installed_plugin_file);
|
||||
echo "plugin: checking $plugin ...\n";
|
||||
exec(realpath($argv[0])." check $plugin >/dev/null");
|
||||
write("plugin: checking $plugin ...\n");
|
||||
exec("$cmd check $plugin >/dev/null");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// MAIN - two or three arguments
|
||||
if ($argc < 3) {
|
||||
echo $usage;
|
||||
write($usage);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -454,72 +567,76 @@ if ($argc < 3) {
|
||||
//
|
||||
$unraid = parse_ini_file('/etc/unraid-version');
|
||||
if ($method == 'install') {
|
||||
$argv[2] = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $argv[2]);
|
||||
echo "plugin: installing: {$argv[2]}\n";
|
||||
console(3);
|
||||
$argv[2] = preg_replace('#[\x00-\x1F\x80-\xFF]#', '', $argv[2]);
|
||||
$plugin = basename($argv[2]);
|
||||
write("plugin: installing: $plugin\n");
|
||||
// check for URL
|
||||
if ((strpos($argv[2], "http://") === 0) || (strpos($argv[2], "https://") === 0)) {
|
||||
if (preg_match('#^https?://#',$argv[2])) {
|
||||
$pluginURL = $argv[2];
|
||||
echo "plugin: downloading $pluginURL\n";
|
||||
$plugin_file = "$tmp/".basename($pluginURL);
|
||||
$plugin_file = "$tmp/$plugin";
|
||||
write("plugin: downloading: $plugin\n");
|
||||
if (!download($pluginURL, $plugin_file, $error)) {
|
||||
echo "plugin: $error\n";
|
||||
write("plugin: $error\n");
|
||||
@unlink($plugin_file);
|
||||
exit(1);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
$plugin_file = realpath($argv[2]);
|
||||
}
|
||||
// bergware - check Unraid version dependency (if present)
|
||||
$min = plugin('min', $plugin_file, $error);
|
||||
if ($min && version_compare($unraid['version'], $min, '<')) {
|
||||
echo "plugin: installed Unraid version is too low, require at least version $min\n";
|
||||
write("plugin: installed Unraid version is too low, require at least version $min\n");
|
||||
if (dirname($plugin_file) == "$boot") {
|
||||
move($plugin_file, "$boot-error");
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
$max = plugin('max', $plugin_file, $error);
|
||||
if (empty($max)) $max = plugin('Unraid', $plugin_file, $error);
|
||||
$max = plugin('max', $plugin_file, $error) ?: plugin('Unraid', $plugin_file, $error);
|
||||
if ($max && version_compare($unraid['version'], $max, '>')) {
|
||||
echo "plugin: installed Unraid version is too high, require at most version $max\n";
|
||||
write("plugin: installed Unraid version is too high, require at most version $max\n");
|
||||
if (dirname($plugin_file) == "$boot") {
|
||||
move($plugin_file, "$boot-error");
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
$plugin = basename($plugin_file);
|
||||
$symlink = "$plugins/$plugin";
|
||||
// check for re-install
|
||||
$installed_plugin_file = @readlink("$plugins/$plugin");
|
||||
$installed_plugin_file = @readlink($symlink);
|
||||
if ($installed_plugin_file !== false) {
|
||||
if ($plugin_file == $installed_plugin_file) {
|
||||
echo "plugin: not re-installing same plugin\n";
|
||||
write("plugin: not re-installing same plugin\n");
|
||||
exit(1);
|
||||
}
|
||||
// must have version attributes for re-install
|
||||
$version = plugin('version', $plugin_file, $error);
|
||||
if ($version === false) {
|
||||
echo "plugin: $error\n";
|
||||
write("plugin: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
$installed_version = plugin('version', $installed_plugin_file, $error);
|
||||
if ($installed_version === false) {
|
||||
echo "plugin: $error\n";
|
||||
write("plugin: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
// check version installation?
|
||||
$forced = $argc==4 ? $argv[3] : false;
|
||||
$forced = $console ? ($argc==4 ? $argv[3] : false) : ($argc==5 ? $argv[4] : false);
|
||||
if (!$forced) {
|
||||
// do not re-install if same plugin already installed or has higher version
|
||||
if (strcmp($version, $installed_version) < 0) {
|
||||
echo "plugin: not installing older version\n";
|
||||
write("plugin: not installing older version\n");
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp($version, $installed_version) == 0) {
|
||||
echo "plugin: not reinstalling same version\n";
|
||||
if (strcmp($version, $installed_version) === 0) {
|
||||
write("plugin: not reinstalling same version\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
// run hook scripts for pre processing
|
||||
pre_hooks();
|
||||
if (plugin('install', $plugin_file, $error) === false) {
|
||||
echo "plugin: $error\n";
|
||||
write("plugin: $error\n");
|
||||
if (dirname($plugin_file) == "$boot") {
|
||||
move($plugin_file, "$boot-error");
|
||||
}
|
||||
@@ -529,11 +646,14 @@ if ($method == 'install') {
|
||||
exec("$notify -e $event -s $subject -d $description) -i 2");
|
||||
exit(1);
|
||||
}
|
||||
unlink("$plugins/$plugin");
|
||||
// remove symlink for re-install
|
||||
unlink($symlink);
|
||||
} else {
|
||||
// run hook scripts for pre processing
|
||||
pre_hooks();
|
||||
// fresh install
|
||||
if (plugin('install', $plugin_file, $error) === false) {
|
||||
echo "plugin: $error\n";
|
||||
write("plugin: $error\n");
|
||||
if (dirname($plugin_file) == "$boot") {
|
||||
move($plugin_file, "$boot-error");
|
||||
}
|
||||
@@ -544,11 +664,15 @@ if ($method == 'install') {
|
||||
$target = "$boot/$plugin";
|
||||
if (!plugin('noInstall', $plugin_file, $error)) {
|
||||
if ($target != $plugin_file) copy($plugin_file, $target);
|
||||
symlink($target, "$plugins/$plugin");
|
||||
echo "plugin: $plugin installed\n";
|
||||
symlink($target, $symlink);
|
||||
write("plugin: $plugin installed\n");
|
||||
logger("plugin: $plugin installed");
|
||||
} else {
|
||||
echo "script: $plugin executed\n";
|
||||
write("script: $plugin executed\n");
|
||||
logger("script: $plugin executed");
|
||||
}
|
||||
// run hook scripts for post processing
|
||||
post_hooks();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -557,30 +681,36 @@ if ($method == 'install') {
|
||||
// directory.
|
||||
//
|
||||
if ($method == 'check') {
|
||||
console(3);
|
||||
$plugin = $argv[2];
|
||||
echo "plugin: checking: $plugin\n";
|
||||
$installed_plugin_file = @readlink("$plugins/$plugin");
|
||||
$symlink = "$plugins/$plugin";
|
||||
write("plugin: checking: $plugin ...\n");
|
||||
$installed_plugin_file = @readlink($symlink);
|
||||
if ($installed_plugin_file === false) {
|
||||
echo "plugin: not installed\n";
|
||||
write("plugin: not installed\n");
|
||||
exit(1);
|
||||
}
|
||||
$installed_pluginURL = plugin('pluginURL', $installed_plugin_file, $error);
|
||||
if ($installed_pluginURL === false) {
|
||||
echo "plugin: $error\n";
|
||||
write("plugin: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
$plugin_file = "$tmp/$plugin";
|
||||
if (!download($installed_pluginURL, $plugin_file, $error)) {
|
||||
echo "plugin: $error\n";
|
||||
write("plugin: $error\n");
|
||||
@unlink($plugin_file);
|
||||
exit(1);
|
||||
}
|
||||
// run hook scripts for pre processing
|
||||
pre_hooks();
|
||||
$version = plugin('version', $plugin_file, $error);
|
||||
if ($version === false) {
|
||||
echo "plugin: $error\n";
|
||||
write("plugin: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
echo "$version\n";
|
||||
write("$version\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -593,60 +723,53 @@ if ($method == 'check') {
|
||||
// Finally we mark the new.plg "installed".
|
||||
//
|
||||
if ($method == 'update') {
|
||||
console(3);
|
||||
$plugin = $argv[2];
|
||||
echo "plugin: updating: $plugin\n";
|
||||
$installed_plugin_file = @readlink("$plugins/$plugin");
|
||||
$symlink = "$plugins/$plugin";
|
||||
write("plugin: updating: $plugin\n");
|
||||
$installed_plugin_file = @readlink($symlink);
|
||||
if ($installed_plugin_file === false) {
|
||||
echo "plugin: $plugin not installed\n";
|
||||
write("plugin: $plugin not installed\n");
|
||||
exit(1);
|
||||
}
|
||||
// get old support link
|
||||
$previousSupportLink = plugin('support', "$plugins/$plugin", $error);
|
||||
// verify previous check has been done
|
||||
$plugin_file = "$tmp/$plugin";
|
||||
if (!file_exists($plugin_file)) {
|
||||
echo "plugin: $plugin_file does not exist, check for updates first\n";
|
||||
write("plugin: $plugin_file does not exist, check for updates first\n");
|
||||
exit (1);
|
||||
}
|
||||
// bergware - check Unraid version dependency (if present)
|
||||
$min = plugin('min', $plugin_file, $error);
|
||||
if ($min && version_compare($unraid['version'], $min, '<')) {
|
||||
echo "plugin: installed Unraid version is too low, require at least version $min\n";
|
||||
write("plugin: installed Unraid version is too low, require at least version $min\n");
|
||||
exit(1);
|
||||
}
|
||||
$max = plugin('max', $plugin_file, $error);
|
||||
if (empty($max))
|
||||
$max = plugin('Unraid', $plugin_file, $error);
|
||||
$max = plugin('max', $plugin_file, $error) ?: plugin('Unraid', $plugin_file, $error);
|
||||
if ($max && version_compare($unraid['version'], $max, '>')) {
|
||||
echo "plugin: installed Unraid version is too high, require at most version $max\n";
|
||||
write("plugin: installed Unraid version is too high, require at most version $max\n");
|
||||
exit(1);
|
||||
}
|
||||
// check for a reinstall of same version
|
||||
if (strcmp(plugin('version', $installed_plugin_file,$error), plugin('version', $plugin_file,$error1)) == 0) {
|
||||
echo "Not reinstalling same version\n";
|
||||
if (strcmp(plugin('version', $installed_plugin_file, $error), plugin('version', $plugin_file, $error)) === 0) {
|
||||
write("Not reinstalling same version\n");
|
||||
exit(1);
|
||||
}
|
||||
// run hook scripts for pre processing
|
||||
pre_hooks();
|
||||
// install the updated plugin
|
||||
if (plugin('install', $plugin_file, $error) === false) {
|
||||
echo "plugin: $error\n";
|
||||
write("plugin: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
// install was successful, save the updated plugin so it installs again next boot
|
||||
unlink("$plugins/$plugin");
|
||||
// re-inject the old support link if the updated plugin doesn't have one
|
||||
if (!plugin('support', $plugin_file,$error) && $previousSupportLink) {
|
||||
echo "\n\nUpdating Support Link\n";
|
||||
$pluginXML = simplexml_load_file($plugin_file);
|
||||
$pluginXML->addAttribute('support', $previousSupportLink);
|
||||
$dom = new DOMDocument('1.0');
|
||||
$dom->preserveWhiteSpace = false;
|
||||
$dom->formatOutput = true;
|
||||
$dom->loadXML($pluginXML->asXML());
|
||||
file_put_contents($plugin_file,$dom->saveXML());
|
||||
}
|
||||
copy($plugin_file,"$boot/$plugin");
|
||||
symlink("$boot/$plugin", "$plugins/$plugin");
|
||||
echo "plugin: $plugin updated\n";
|
||||
unlink($symlink);
|
||||
$target = "$boot/$plugin";
|
||||
copy($plugin_file, $target);
|
||||
symlink($target, $symlink);
|
||||
write("plugin: $plugin updated\n");
|
||||
logger("plugin: $plugin updated");
|
||||
// run hook scripts for post processing
|
||||
post_hooks();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -654,35 +777,43 @@ if ($method == 'update') {
|
||||
// only .plg files should have a remove method
|
||||
//
|
||||
if ($method == 'remove') {
|
||||
console(3);
|
||||
$plugin = $argv[2];
|
||||
echo "plugin: removing: $plugin\n";
|
||||
$installed_plugin_file = @readlink("$plugins/$plugin");
|
||||
$symlink = "$plugins/$plugin";
|
||||
write("plugin: removing: $plugin\n");
|
||||
$installed_plugin_file = @readlink($symlink);
|
||||
if ($installed_plugin_file !== false) {
|
||||
// remove the symlink
|
||||
unlink("$plugins/$plugin");
|
||||
unlink($symlink);
|
||||
@unlink("$tmp/$plugin");
|
||||
// run hook scripts for pre processing
|
||||
pre_hooks();
|
||||
if (plugin('remove', $installed_plugin_file, $error) === false) {
|
||||
// but if can't remove, restore the symlink
|
||||
symlink($installed_plugin_file, "$plugins/$plugin");
|
||||
echo "plugin: $error\n";
|
||||
if (is_file($installed_plugin_file)) symlink($installed_plugin_file, $symlink);
|
||||
write("plugin: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
// remove the plugin file
|
||||
move($installed_plugin_file, "$boot-removed");
|
||||
echo "plugin: $plugin removed\n";
|
||||
write("plugin: $plugin removed\n");
|
||||
logger("plugin: $plugin removed");
|
||||
exec("/usr/local/sbin/update_cron");
|
||||
// run hook scripts for post processing
|
||||
post_hooks();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// <attribute>
|
||||
// return attribute
|
||||
//
|
||||
console(3);
|
||||
$plugin_file = $argv[2];
|
||||
$value = plugin($method, $plugin_file, $error);
|
||||
if ($value === false) {
|
||||
echo "plugin: $error\n";
|
||||
write("plugin: $error\n");
|
||||
exit(1);
|
||||
}
|
||||
echo "$value\n";
|
||||
write("$value\n");
|
||||
exit(0);
|
||||
?>
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
text="Deleting $1 ..."
|
||||
if [[ -z $2 ]]; then
|
||||
echo $text
|
||||
else
|
||||
curl -sfd $text --unix-socket /var/run/nginx.socket http://localhost/pub/plugins?buffer_length=0 >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
# put some restrictions on 'rm'
|
||||
echo "Deleting $1 ..."
|
||||
[[ $1 == /boot/config/plugins-error/* ]] && rm $1
|
||||
[[ $1 == /boot/config/plugins-stale/* ]] && rm $1
|
||||
|
||||
50
plugins/dynamix.plugin.manager/scripts/showchanges
Executable file
50
plugins/dynamix.plugin.manager/scripts/showchanges
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2022, Lime Technology
|
||||
* Copyright 2012-2022, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
session_start();
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
// add translations
|
||||
$_SERVER['REQUEST_URI'] = 'plugins';
|
||||
$_SESSION['locale'] = $display['locale'];
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
|
||||
$file = realpath($argv[1] ?? '');
|
||||
$console = !(isset($argv[2]) && $argv[2]=='nchan');
|
||||
$valid = ['/var/tmp/','/tmp/plugins/'];
|
||||
$good = false;
|
||||
|
||||
function write($message){
|
||||
global $console;
|
||||
if ($console) {
|
||||
echo $message;
|
||||
} else {
|
||||
$nchan = curl_init();
|
||||
curl_setopt_array($nchan,[
|
||||
CURLOPT_URL => 'http://localhost/pub/changes?buffer_length=0',
|
||||
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
|
||||
CURLOPT_POST => 1,
|
||||
CURLOPT_POSTFIELDS => $message,
|
||||
CURLOPT_RETURNTRANSFER => true
|
||||
]);
|
||||
curl_exec($nchan);
|
||||
curl_close($nchan);
|
||||
}
|
||||
}
|
||||
if ($file) {
|
||||
foreach ($valid as $check) if (strncmp($file,$check,strlen($check))===0) $good = true;
|
||||
if ($good && pathinfo($file)['extension']=='txt') write(Markdown(file_get_contents($file)));
|
||||
} else {
|
||||
write(Markdown("*"._('No release notes available')."!*"));
|
||||
}
|
||||
?>
|
||||
@@ -3,8 +3,8 @@ Name="Apps"
|
||||
Code="e942"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2021, Lime Technology
|
||||
* Copyright 2012-2021, Bergware International.
|
||||
/* Copyright 2005-2022, Lime Technology
|
||||
* Copyright 2012-2022, 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,
|
||||
@@ -20,7 +20,7 @@ div.notice{margin:150px 0 20px 0}
|
||||
|
||||
<script>
|
||||
function installPlugin(file) {
|
||||
openBox("/plugins/dynamix.plugin.manager/scripts/plugin&arg1=install&arg2="+file,"_(Install Plugin)_",600,900,true);
|
||||
openPlugin("plugin install "+file,"_(Install Plugin)_","","refresh");
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -22,26 +22,22 @@ $zip = htmlspecialchars(str_replace(' ','_',strtolower($var['NAME'])));
|
||||
ul,li{margin:0;padding-top:0;padding-bottom:0}
|
||||
pre.pre{margin:30px 0}
|
||||
pre>p{margin:0;padding:0}
|
||||
tt{display:inline-block;text-align:left;position:absolute;left:30px;margin-bottom:30px}
|
||||
#command{white-space:normal;border:none}
|
||||
.sweet-alert{width:900px;height:600px}
|
||||
button.confirm{margin-top:70px}
|
||||
pre#text{height:250px!important}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
var diagnosticsFile = "";
|
||||
var diagnostic = new NchanSubscriber('/sub/diagnostic',{subscriber:'websocket'});
|
||||
var diagnostic = new NchanSubscriber('/sub/diagnostics',{subscriber:'websocket'});
|
||||
|
||||
diagnostic.on('message', function(data) {
|
||||
if (data) {
|
||||
if (data == diagnosticsFile.replace("/","")+"FINISHED") {
|
||||
diagnostic.stop();
|
||||
swal.close();
|
||||
location = diagnosticsFile;
|
||||
setTimeout(cleanUp,4000);
|
||||
} else {
|
||||
$("#command").html(data);
|
||||
}
|
||||
if (data == '_DONE_') {
|
||||
diagnostic.stop();
|
||||
swal.close();
|
||||
location = diagnosticsFile;
|
||||
setTimeout(cleanUp,4000);
|
||||
} else {
|
||||
let box = $('pre#text');
|
||||
box.html(box.html()+'<br>'+data).scrollTop(box[0].scrollHeight);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -56,7 +52,7 @@ function cleanUp() {
|
||||
|
||||
function zipfile(){
|
||||
var tzoffset = (new Date()).getTimezoneOffset() * 60000; //offset in milliseconds
|
||||
var localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, -1);
|
||||
var localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0,-1);
|
||||
return '<?=$zip?>-diagnostics-'+localISOTime.substr(0,16).replace(/[-:]/g,'').replace('T','-')+'.zip';
|
||||
}
|
||||
|
||||
@@ -65,10 +61,12 @@ function diagnostics(file) {
|
||||
$.post('/webGui/include/Download.php',{cmd:'diag',file:file,anonymize:anonymize},function(zip) {
|
||||
diagnosticsFile = zip;
|
||||
diagnostic.start();
|
||||
swal({title:"_(Downloading)_...",text:"/boot/logs"+zip+"<br><br><tt><pre id='command'></pre></tt>",html:true,type:"info",confirmButtonText:"_(Close)_"});
|
||||
swal({title:"_(Downloading)_...",text:"/boot/logs"+zip+"<hr><br><pre id='text'></pre><hr>",html:true,type:"info",confirmButtonText:"_(Close)_"});
|
||||
$('.sweet-alert').css({'height':'600','width':'900'});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
:diagnostics_1_plug:
|
||||
This utility is used for troubleshooting purposes. It will collect all of the system information and configuration files, and package these files in a single ZIP file which can be saved locally.
|
||||
Subsequently, this file can be included in your correspondence with Limetech or the Unraid forum.
|
||||
|
||||
@@ -21,7 +21,7 @@ $config = "/boot/config";
|
||||
$entity = $notify['entity'] & 1 == 1;
|
||||
$alerts = '/tmp/plugins/my_alerts.txt';
|
||||
|
||||
function annotate($text) {echo "\n<!--\n".str_repeat("#",strlen($text))."\n$text\n".str_repeat("#",strlen($text))."\n-->\n";}
|
||||
function annotate($text) {echo "\n<!--\n",str_repeat("#",strlen($text)),"\n$text\n",str_repeat("#",strlen($text)),"\n-->\n";}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html <?=$display['rtl']?>lang="<?=strtok($locale,'_')?:'en'?>">
|
||||
@@ -59,10 +59,13 @@ html{font-size:<?=$display['font']?>%}
|
||||
<?endif;?>
|
||||
<?endif;?>
|
||||
.inline_help{display:none}
|
||||
.upgrade_notice{position:fixed;top:1px;left:0;width:100%;height:40px;line-height:40px;color:#e68a00;background:#feefb3;border-bottom:#e68a00 1px solid;text-align:center;font-size:1.4rem;z-index:999}
|
||||
.upgrade_notice i{margin:14px;float:right;cursor:pointer}
|
||||
.upgrade_notice{position:fixed;top:24px;left:50%;margin-left:-480px;width:900px;height:40px;line-height:40px;color:#e68a00;background-color:#feefb3;border:#e68a00 1px solid;border-radius:40px;text-align:center;font-size:1.4rem;z-index:999}
|
||||
.upgrade_notice.done{color:#4f8a10;background-color:#dff2bf;border-color:#4f8a10}
|
||||
.upgrade_notice i{float:right;cursor:pointer}
|
||||
.back_to_top{display:none;position:fixed;bottom:30px;right:12px;color:#e22828;font-size:2.5rem;z-index:999}
|
||||
span.big.blue-text{cursor:pointer}
|
||||
pre#body{font-family:clear-sans;text-align:left;margin:-10px 0 0 30px;padding:0;height:400px;white-space:normal;border:none}
|
||||
pre#text{text-align:left;margin:-10px 0 0 30px;padding:0;height:400px;white-space:normal;border:none}
|
||||
<?
|
||||
$nchan = ['webGui/nchan/notify_poller','webGui/nchan/session_check'];
|
||||
$safemode = $var['safeMode']=='yes';
|
||||
@@ -78,7 +81,7 @@ if ($themes2) {
|
||||
}
|
||||
$notes = '/var/tmp/unRAIDServer.txt';
|
||||
if (!file_exists($notes)) file_put_contents($notes,shell_exec("$docroot/plugins/dynamix.plugin.manager/scripts/plugin changes $docroot/plugins/unRAIDServer/unRAIDServer.plg"));
|
||||
$notes = " <span class='fa fa-info-circle fa-fw big blue-text' title='"._('View Release Notes')."' onclick=\"openBox('/plugins/dynamix.plugin.manager/include/ShowChanges.php?file=$notes','"._('Release Notes')."',600,900)\"></span>";
|
||||
$notes = " <span class='fa fa-info-circle fa-fw big blue-text' title='"._('View Release Notes')."' onclick=\"openChanges('showchanges $notes','"._('Release Notes')."')\"></span>";
|
||||
?>
|
||||
</style>
|
||||
|
||||
@@ -100,9 +103,15 @@ var expiretime = <?=$var['regTy']=='Trial'||strstr($var['regTy'],'expired')?$var
|
||||
var before = new Date();
|
||||
|
||||
// page timer events
|
||||
var timers = {};
|
||||
const timers = {};
|
||||
timers.bannerWarning = null;
|
||||
|
||||
const addAlert = {};
|
||||
addAlert.text = $.cookie('addAlert-text');
|
||||
addAlert.cmd = $.cookie('addAlert-cmd');
|
||||
addAlert.plg = $.cookie('addAlert-plg');
|
||||
addAlert.func = $.cookie('addAlert-func');
|
||||
|
||||
// current csrf_token
|
||||
var csrf_token = "<?=$var['csrf_token']?>";
|
||||
|
||||
@@ -155,7 +164,7 @@ function updateTime() {
|
||||
}
|
||||
function refresh(top) {
|
||||
if (typeof top === 'undefined') {
|
||||
for (var i=0,element; element=document.querySelectorAll('input,button,select')[i]; i++) { element.disabled = true; }
|
||||
for (var i=0,element; element=document.querySelectorAll('input,button,select')[i]; i++) {element.disabled = true;}
|
||||
for (var i=0,link; link=document.getElementsByTagName('a')[i]; i++) { link.style.color = "gray"; } //fake disable
|
||||
location.reload();
|
||||
} else {
|
||||
@@ -205,7 +214,7 @@ function openBox(cmd,title,height,width,load,func,id) {
|
||||
// open shadowbox window (run in foreground)
|
||||
var uri = cmd.split('?');
|
||||
var run = uri[0].substr(-4)=='.php' ? cmd+(uri[1]?'&':'?')+'done=<?=urlencode(_("Done"))?>' : '/logging.htm?cmd='+cmd+'&csrf_token='+csrf_token+'&done=<?=urlencode(_("Done"))?>';
|
||||
var options = load ? (func ? {modal:true,onClose:function(){setTimeout(func+'('+'"'+(id||'')+'")',0);}} : {modal:true,onClose:function(){location.reload();}}) : {modal:false};
|
||||
var options = load ? (func ? {modal:true,onClose:function(){setTimeout(func+'('+'"'+(id||'')+'")');}} : {modal:true,onClose:function(){location.reload();}}) : {modal:false};
|
||||
Shadowbox.open({content:run, player:'iframe', title:title, height:Math.min(height,screen.availHeight), width:Math.min(width,screen.availWidth), options:options});
|
||||
}
|
||||
function openWindow(cmd,title,height,width) {
|
||||
@@ -235,6 +244,67 @@ function openTerminal(tag,name,more) {
|
||||
var socket = ['ttyd','syslog'].includes(tag) ? '/webterminal/'+tag+'/' : '/logterminal/'+name+(more=='.log'?more:'')+'/';
|
||||
$.get('/webGui/include/OpenTerminal.php',{tag:tag,name:name,more:more},function(){tty_window.location=socket; tty_window.focus();});
|
||||
}
|
||||
function bannerAlert(text,cmd,plg,func) {
|
||||
$.post('/webGui/include/StartCommand.php',{cmd:cmd,pid:1},function(pid) {
|
||||
if (pid == 0) {
|
||||
if ($(".upgrade_notice").hasClass('done') || timers.bannerAlert==null) {
|
||||
forcedBanner = false;
|
||||
if ($.cookie('addAlert') != null) {
|
||||
removeBannerWarning($.cookie('addAlert'));
|
||||
$.removeCookie('addAlert');
|
||||
}
|
||||
if (plg != null) setTimeout((func||'loadlist')+'("'+plg+'")',250);
|
||||
} else {
|
||||
$(".upgrade_notice").addClass('done');
|
||||
timers.bannerAlert = null;
|
||||
setTimeout(function(){bannerAlert(text,cmd,plg,func);},1000);
|
||||
}
|
||||
} else {
|
||||
$(".upgrade_notice").removeClass('done');
|
||||
$.cookie('addAlert',addBannerWarning(text,true,true,true));
|
||||
$.cookie('addAlert-text',text);
|
||||
$.cookie('addAlert-cmd',cmd);
|
||||
$.cookie('addAlert-plg',plg);
|
||||
$.cookie('addAlert-func',func);
|
||||
timers.bannerAlert = setTimeout(function(){bannerAlert(text,cmd,plg,func);},250);
|
||||
}
|
||||
});
|
||||
}
|
||||
function openPlugin(cmd,title,plg,func) {
|
||||
$.post('/webGui/include/StartCommand.php',{cmd:cmd+' nchan'},function(pid) {
|
||||
if (pid==0) return;
|
||||
plugins.start();
|
||||
swal({title:title+'<hr>',text:"<pre id='text'></pre><hr>",html:true,animation:'none',confirmButtonText:"<?=_('Close')?>"},function(){
|
||||
plugins.stop();
|
||||
$('.sweet-alert').hide('fast').removeClass('nchan');
|
||||
setTimeout(function(){bannerAlert("<?=_('Attention - operation continues in background')?>",cmd,plg,func);});
|
||||
});
|
||||
$('.sweet-alert').addClass('nchan');
|
||||
});
|
||||
}
|
||||
function openChanges(cmd,title) {
|
||||
$.post('/webGui/include/StartCommand.php',{cmd:cmd+' nchan'},function(pid) {
|
||||
if (pid==0) return;
|
||||
changes.start();
|
||||
swal({title:title+'<hr>',text:"<pre id='body'></pre><hr>",html:true,animation:'none',confirmButtonText:"<?=_('Close')?>"},function(){
|
||||
changes.stop();
|
||||
$('.sweet-alert').hide('fast').removeClass('nchan');
|
||||
});
|
||||
$('.sweet-alert').addClass('nchan');
|
||||
});
|
||||
}
|
||||
function openAlert(cmd,title,func) {
|
||||
$.post('/webGui/include/StartCommand.php',{cmd:cmd+' nchan'},function(pid) {
|
||||
if (pid==0) return;
|
||||
changes.start();
|
||||
swal({title:title+'<hr>',text:"<pre id='body'></pre><hr>",html:true,animation:'none',showCancelButton:true,confirmButtonText:"<?=_('Proceed')?>",cancelButtonText:"<?=_('Cancel')?>"},function(proceed){
|
||||
changes.stop();
|
||||
$('.sweet-alert').hide('fast').removeClass('nchan');
|
||||
if (proceed) setTimeout(func+'()',750);
|
||||
});
|
||||
$('.sweet-alert').addClass('nchan');
|
||||
});
|
||||
}
|
||||
function showStatus(name,plugin,job) {
|
||||
$.post('/webGui/include/ProcessStatus.php',{name:name,plugin:plugin,job:job},function(status){$(".tabs").append(status);});
|
||||
}
|
||||
@@ -254,29 +324,38 @@ function escapeQuotes(form) {
|
||||
var bannerWarnings = [];
|
||||
var currentBannerWarning = 0;
|
||||
var osUpgradeWarning = false;
|
||||
var forcedBanner = false;
|
||||
|
||||
function addBannerWarning(text,warning=true,noDismiss=false) {
|
||||
function addBannerWarning(text,warning=true, noDismiss=false, forced=false) {
|
||||
var cookieText = text.replace(/[^a-z0-9]/gi,'');
|
||||
if ($.cookie(cookieText) == "true") return false;
|
||||
if (warning) text = "<i class='fa fa-warning' style='float:initial;'></i> "+text;
|
||||
if (warning) text = "<i class='fa fa-warning fa-fw' style='float:initial'></i> "+text;
|
||||
if (bannerWarnings.indexOf(text) < 0) {
|
||||
var arrayEntry = bannerWarnings.push("placeholder") - 1;
|
||||
if (forced) {
|
||||
var arrayEntry = 0; bannerWarnings = []; clearTimeout(timers.bannerWarning); timers.bannerWarning = null; forcedBanner = true;
|
||||
} else {
|
||||
var arrayEntry = bannerWarnings.push("placeholder") - 1;
|
||||
}
|
||||
if (!noDismiss) text += "<a class='bannerDismiss' onclick='dismissBannerWarning("+arrayEntry+",""+cookieText+"")'></a>";
|
||||
bannerWarnings[arrayEntry] = text;
|
||||
} else return bannerWarnings.indexOf(text);
|
||||
} else {
|
||||
return bannerWarnings.indexOf(text);
|
||||
}
|
||||
if (timers.bannerWarning==null) showBannerWarnings();
|
||||
return arrayEntry;
|
||||
}
|
||||
|
||||
function dismissBannerWarning(entry,cookieText) {
|
||||
$.cookie(cookieText,"true",{expires:365});
|
||||
$.cookie(cookieText,"true");
|
||||
removeBannerWarning(entry);
|
||||
}
|
||||
|
||||
function removeBannerWarning(entry) {
|
||||
bannerWarnings[entry] = false;
|
||||
clearTimeout(timers.bannerWarning);
|
||||
showBannerWarnings();
|
||||
if (!forcedBanner) {
|
||||
bannerWarnings[entry] = false;
|
||||
clearTimeout(timers.bannerWarning);
|
||||
showBannerWarnings();
|
||||
}
|
||||
}
|
||||
|
||||
function bannerFilterArray(array) {
|
||||
@@ -313,7 +392,7 @@ function removeRebootNotice(message="<?=_('You must reboot for changes to take e
|
||||
}
|
||||
|
||||
function showUpgradeChanges() {
|
||||
openBox("/plugins/dynamix.plugin.manager/include/ShowChanges.php?file=/tmp/plugins/unRAIDServer.txt","<?=_('Release Notes')?>",600,900);
|
||||
openChanges("showchanges /tmp/plugins/unRAIDServer.txt","<?=_('Release Notes')?>");
|
||||
}
|
||||
function showUpgrade(text,noDismiss=false) {
|
||||
if ($.cookie('os_upgrade')==null) {
|
||||
@@ -321,11 +400,6 @@ function showUpgrade(text,noDismiss=false) {
|
||||
osUpgradeWarning = addBannerWarning(text.replace(/<a>(.+?)<\/a>/,"<a href='#' onclick='openUpgrade()'>$1</a>").replace(/<b>(.*)<\/b>/,"<a href='#' onclick='document.rebootNow.submit()'>$1</a>"),false,noDismiss);
|
||||
}
|
||||
}
|
||||
function confirmUpgrade() {
|
||||
swal({title:"<?=_('Update')?> Unraid OS",text:"<?=_('Do you want to update to the new version')?>?",type:'warning',html:true,showCancelButton:true,confirmButtonText:"<?=_('Proceed')?>",cancelButtonText:"<?=_('Cancel')?>"},function(){
|
||||
openBox("/plugins/dynamix.plugin.manager/scripts/plugin&arg1=update&arg2=unRAIDServer.plg","<?=_('Update')?> Unraid OS",600,900,true);
|
||||
});
|
||||
}
|
||||
function hideUpgrade(set) {
|
||||
removeBannerWarning(osUpgradeWarning);
|
||||
if (set)
|
||||
@@ -333,13 +407,26 @@ function hideUpgrade(set) {
|
||||
else
|
||||
$.removeCookie('os_upgrade');
|
||||
}
|
||||
function confirmUpgrade(confirm) {
|
||||
if (confirm) {
|
||||
swal({title:"<?=_('Update')?> Unraid OS",text:"<?=_('Do you want to update to the new version')?>?",type:'warning',html:true,showCancelButton:true,confirmButtonText:"<?=_('Proceed')?>",cancelButtonText:"<?=_('Cancel')?>"},function(){
|
||||
setTimeout(function(){openPlugin("plugin update unRAIDServer.plg","<?=_('Update')?> Unraid OS");},250);
|
||||
});
|
||||
} else {
|
||||
setTimeout(function(){openPlugin("plugin update unRAIDServer.plg","<?=_('Update')?> Unraid OS");},250);
|
||||
}
|
||||
}
|
||||
function openUpgrade() {
|
||||
hideUpgrade();
|
||||
<?if (file_exists($alerts)):?>
|
||||
openBox('/plugins/dynamix.plugin.manager/include/ShowChanges.php?file=<?=$alerts?>',"<?=_('Alert Message')?>",600,900,true,'confirmUpgrade');
|
||||
<?else:?>
|
||||
confirmUpgrade();
|
||||
<?endif;?>
|
||||
$.get('/plugins/dynamix.plugin.manager/include/ShowPlugins.php',{cmd:'alert'},function(data) {
|
||||
if (data==0) {
|
||||
// no alert message - proceed with upgrade
|
||||
confirmUpgrade(true);
|
||||
} else {
|
||||
// show alert message and ask for confirmation
|
||||
openAlert("showchanges <?=$alerts?>","<?=_('Alert Message')?>",'confirmUpgrade');
|
||||
}
|
||||
});
|
||||
}
|
||||
function digits(number) {
|
||||
if (number < 10) return 'one';
|
||||
@@ -626,7 +713,7 @@ defaultPage.on('message', function(msg,meta) {
|
||||
case 'Formatting': var status = "<span class='green strong'><i class='fa fa-play-circle'></i> <?=_('Array Started')?></span>•<span class='orange strong'><?=_('Formatting device(s)')?></span>"; break;
|
||||
default : var status = "<span class='orange strong'><i class='fa fa-pause-circle'></i> "+_('Array '+ini['fsState'])+"</span>";
|
||||
}
|
||||
if (ini['mdResyncPos']>0) {
|
||||
if (ini['mdResyncPos'] > 0) {
|
||||
var resync = ini['mdResyncAction'].split(/\s+/);
|
||||
switch (resync[0]) {
|
||||
case 'recon': var action = resync[1]=='P' ? "<?=_('Parity-Sync')?>" : "<?=_('Data-Rebuild')?>"; break;
|
||||
@@ -677,6 +764,23 @@ defaultPage.on('message', function(msg,meta) {
|
||||
}
|
||||
});
|
||||
|
||||
var plugins = new NchanSubscriber('/sub/plugins',{subscriber:'websocket'});
|
||||
plugins.on('message', function(data) {
|
||||
let box = $('pre#text');
|
||||
const text = box.html().split('<br>');
|
||||
if (data.slice(-1) == '\r') {
|
||||
text[text.length-1] = data.slice(0,-1);
|
||||
} else {
|
||||
text.push(data.slice(0,-1));
|
||||
}
|
||||
box.html(text.join('<br>')).scrollTop(box[0].scrollHeight);
|
||||
});
|
||||
|
||||
var changes = new NchanSubscriber('/sub/changes',{subscriber:'websocket'});
|
||||
changes.on('message', function(data) {
|
||||
$('pre#body').html(data);
|
||||
});
|
||||
|
||||
var backtotopoffset = 250;
|
||||
var backtotopduration = 500;
|
||||
$(window).scroll(function() {
|
||||
@@ -729,6 +833,7 @@ $(function() {
|
||||
var top = ($.cookie('top')||0) - $('.tabs').offset().top - 75;
|
||||
if (top>0) {$('html,body').scrollTop(top);}
|
||||
$.removeCookie('top');
|
||||
if ($.cookie('addAlert')!=null) bannerAlert(addAlert.text,addAlert.cmd,addAlert.plg,addAlert.func);
|
||||
<?if ($safemode):?>
|
||||
showNotice("<?=_('System running in')?> <b><?=('safe mode')?></b>");
|
||||
<?else:?>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2021, Lime Technology
|
||||
* Copyright 2012-2021, Bergware International.
|
||||
/* Copyright 2005-2022, Lime Technology
|
||||
* Copyright 2012-2022, 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,
|
||||
@@ -40,7 +40,7 @@ case 'delete':
|
||||
case 'diag':
|
||||
if (is_file("$docroot/$file") && !rootpath($file)) exit;
|
||||
$anon = empty($_POST['anonymize']) ? '' : escapeshellarg($_POST['anonymize']);
|
||||
exec("echo $docroot/webGui/scripts/diagnostics $anon ".escapeshellarg("$docroot/$file")." | at NOW > /dev/null 2>&1");
|
||||
exec("echo $docroot/webGui/scripts/diagnostics $anon ".escapeshellarg("$docroot/$file")." | at -M now > /dev/null 2>&1");
|
||||
echo "/$file";
|
||||
break;
|
||||
case 'unlink':
|
||||
|
||||
40
plugins/dynamix/include/StartCommand.php
Normal file
40
plugins/dynamix/include/StartCommand.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2022, Lime Technology
|
||||
* Copyright 2012-2022, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
require_once "$docroot/webGui/include/Secure.php";
|
||||
|
||||
function pgrep($proc) {
|
||||
return exec("pgrep -f $proc");
|
||||
}
|
||||
|
||||
[$command,$args] = explode(' ',unscript($_POST['cmd']??''),2);
|
||||
|
||||
// find absolute path of command
|
||||
foreach (glob("$docroot/plugins/*/scripts",GLOB_NOSORT) as $path) {
|
||||
if ($name = realpath("$path/$command")) break;
|
||||
}
|
||||
|
||||
$pid = 0; // preset to not started
|
||||
if ($command && strncmp($name,$path,strlen($path))===0) {
|
||||
if (isset($_POST['pid'])) {
|
||||
// return running pid
|
||||
$pid = pgrep($name);
|
||||
} elseif (!pgrep($name)) {
|
||||
// only execute when command and valid path is given and command not already running
|
||||
exec("echo \"$name $args\" | at -M now >/dev/null 2>&1");
|
||||
$pid = 1; // started
|
||||
}
|
||||
}
|
||||
echo $pid;
|
||||
?>
|
||||
@@ -22,29 +22,26 @@ $var = (array)@parse_ini_file("$get/var.ini");
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
$folders = ['/boot','/boot/config','/boot/config/plugins','/boot/syslinux','/var/log','/var/log/plugins','/boot/extra','/var/log/packages','/var/lib/pkgtools/packages','/tmp'];
|
||||
|
||||
function curl_socket($socket, $url, $postdata = NULL) {
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, $socket);
|
||||
if ($postdata !== NULL) {
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
function write($message) {
|
||||
$nchan = curl_init();
|
||||
curl_setopt_array($nchan,[
|
||||
CURLOPT_URL => "http://localhost/pub/diagnostics?buffer_length=0",
|
||||
CURLOPT_UNIX_SOCKET_PATH => "/var/run/nginx.socket",
|
||||
CURLOPT_POST => 1,
|
||||
CURLOPT_POSTFIELDS => $message,
|
||||
CURLOPT_RETURNTRANSFER => true
|
||||
]);
|
||||
curl_exec($nchan);
|
||||
curl_close($nchan);
|
||||
}
|
||||
function publish($endpoint, $message){
|
||||
curl_socket("/var/run/nginx.socket", "http://localhost/pub/$endpoint?buffer_length=1", $message);
|
||||
}
|
||||
|
||||
function exert($cmd, &$save=null) {
|
||||
function run($cmd, &$save=null) {
|
||||
global $cli,$diag;
|
||||
// execute command with timeout of 30s
|
||||
publish("diagnostic",$cmd);
|
||||
// output command for display
|
||||
write($cmd);
|
||||
// execute command with timeout of 30s
|
||||
exec("timeout -s9 30 $cmd", $save);
|
||||
return implode("\n",$save);
|
||||
}
|
||||
|
||||
function shareDisks($share) {
|
||||
return exec("shopt -s dotglob; getfattr --no-dereference --absolute-names --only-values -n system.LOCATIONS ".escapeshellarg("/usr/local/emhttp/mnt/user/$share")." 2>/dev/null") ?: "";
|
||||
}
|
||||
@@ -55,7 +52,7 @@ function anonymize($text,$select) {
|
||||
case 1:
|
||||
// remove any stray references to the GUID that may wind up in .ini files (notably Unassigned Devices)
|
||||
$text = str_replace(end(explode("-",$unraid_vars['regGUID'])),"...",$text);
|
||||
|
||||
|
||||
$rows = explode("\n", $text);
|
||||
$regex = "/\b((disk|cache|parity|cpu|eth|dev)[0-9]+)|(smart|flash|flashbackup|cache|parity|cpu$customShares)\b/";
|
||||
foreach ($rows as &$row) {
|
||||
@@ -91,39 +88,34 @@ function cache_filter($disks) {
|
||||
function pools_filter($disks) {
|
||||
return array_unique(array_map('prefix',array_keys(cache_filter($disks))));
|
||||
}
|
||||
function download_url($url, $path = "", $bg = false, $timeout = 15) {
|
||||
function download_url($url, $path="", $bg=false, $timeout=15) {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch,CURLOPT_URL,$url);
|
||||
curl_setopt($ch,CURLOPT_FRESH_CONNECT,true);
|
||||
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
|
||||
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10);
|
||||
curl_setopt($ch,CURLOPT_TIMEOUT,$timeout);
|
||||
curl_setopt($ch,CURLOPT_ENCODING,"");
|
||||
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
|
||||
curl_setopt_array($ch,[
|
||||
CURLOPT_URL => $url,
|
||||
CURLOPT_FRESH_CONNECT => true,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_CONNECTTIMEOUT => 10,
|
||||
CURLOPT_TIMEOUT => $timeout,
|
||||
CURLOPT_ENCODING => "",
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_FOLLOWLOCATION => true
|
||||
]);
|
||||
$out = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
if ( $path )
|
||||
file_put_contents($path,$out);
|
||||
|
||||
if ($path) file_put_contents($path,$out);
|
||||
return $out ?: false;
|
||||
}
|
||||
function geturls_certdetails($file, $hostname, $ip="") {
|
||||
// called by the geturls() function
|
||||
|
||||
// best to ensure the file exists before calling this function
|
||||
if (!file_exists($file)) return ['', '', ''];
|
||||
|
||||
// read the cert
|
||||
$data = null;
|
||||
exec("/usr/bin/openssl x509 -noout -subject -nameopt multiline -in ".escapeshellarg($file), $data);
|
||||
$data = implode("\n", $data);
|
||||
|
||||
// determine cn
|
||||
preg_match('/ *commonName *= (.*)/', $data, $matches);
|
||||
$cn = trim($matches[1]);
|
||||
|
||||
if (strpos($cn, ".myunraid.net") !== false) {
|
||||
$type = 'myunraid.net';
|
||||
$iphost = str_replace('.','-',$ip);
|
||||
@@ -147,28 +139,18 @@ function geturls_certdetails($file, $hostname, $ip="") {
|
||||
$type = 'user-provided';
|
||||
}
|
||||
}
|
||||
|
||||
return [$cn, $cn_priv, $type];
|
||||
}
|
||||
function geturls_checkhost($host, $hostpriv, $expectedip, $dnsserver) {
|
||||
// called by the geturls() function
|
||||
|
||||
// dns lookups will fail if there is no TLD or if it is ".local", so skip it
|
||||
if (strpos($host, '.') === false || strpos($host, '.local') !== false) {
|
||||
return '';
|
||||
}
|
||||
if (strpos($host, '.') === false || strpos($host, '.local') !== false) return '';
|
||||
$result = @dns_get_record($host, DNS_A);
|
||||
$ip = ($result) ? $result[0]['ip'] : '';
|
||||
if ($ip == '') {
|
||||
return " ERROR: When using DNS server {$dnsserver}, the host {$hostpriv} does not resolve.\n";
|
||||
}
|
||||
if ($ip == '') return " ERROR: When using DNS server {$dnsserver}, the host {$hostpriv} does not resolve.\n";
|
||||
if ($ip != $expectedip) {
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
|
||||
$ip = "[redacted]";
|
||||
}
|
||||
if (filter_var($expectedip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
|
||||
$expectedip = "[redacted]";
|
||||
}
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) $ip = "[redacted]";
|
||||
if (filter_var($expectedip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) $expectedip = "[redacted]";
|
||||
return " ERROR: When using DNS server {$dnsserver}, {$hostpriv} resolves to {$ip}. It should resolve to {$expectedip}\n";
|
||||
}
|
||||
return '';
|
||||
@@ -190,7 +172,6 @@ function geturls() {
|
||||
$rebindip = "192.168.42.42";
|
||||
$rebindtest_ip = exec("host -4 $rebindtesturl 2>/dev/null|sed -n 's/.*has address //p'");
|
||||
$rebind_msg = ($rebindtest_ip != $rebindip) ? "is enabled, $rebindtestdomain urls will not work" : "is disabled, $rebindtestdomain urls will work";
|
||||
|
||||
// show raw data from config files
|
||||
$urls = '';
|
||||
$urls .= "Server Name: {$var['NAME']}\n";
|
||||
@@ -202,7 +183,6 @@ function geturls() {
|
||||
$urls .= "USE SSL: {$var['USE_SSL']}\n";
|
||||
$urls .= "DNS Rebinding Protection {$rebind_msg} on this network\n\n";
|
||||
$urls .= "Available URLs:\n (the URL marked with an asterisk is the primary url for this server)\n";
|
||||
|
||||
// calculate variables
|
||||
$cert_path = "/boot/config/ssl/certs/";
|
||||
$host_name = $var['NAME'];
|
||||
@@ -214,29 +194,26 @@ function geturls() {
|
||||
$https_2_cert = 'certificate_bundle.pem';
|
||||
$http_primary = $https_1_primary = $https_2_primary = $http_msg = $https_1_msg = $https_2_msg = '';
|
||||
switch($var['USE_SSL']) {
|
||||
case "no":
|
||||
$http_primary = '*';
|
||||
break;
|
||||
case "yes":
|
||||
$https_1_primary = '*';
|
||||
$http_msg = "\n (this will redirect to the primary url)";
|
||||
break;
|
||||
case "auto":
|
||||
$http_msg = "\n (this will redirect to the primary url)";
|
||||
$https_1_msg = "\n (this will redirect to the primary url)";
|
||||
$https_2_primary = '*';
|
||||
break;
|
||||
case "no":
|
||||
$http_primary = '*';
|
||||
break;
|
||||
case "yes":
|
||||
$https_1_primary = '*';
|
||||
$http_msg = "\n (this will redirect to the primary url)";
|
||||
break;
|
||||
case "auto":
|
||||
$http_msg = "\n (this will redirect to the primary url)";
|
||||
$https_1_msg = "\n (this will redirect to the primary url)";
|
||||
$https_2_primary = '*';
|
||||
break;
|
||||
}
|
||||
|
||||
// calculate http ip url
|
||||
$http_ip_url = "http://{$internalip_priv}{$http_port}";
|
||||
$urls .= "HTTP IP url: {$http_ip_url}{$http_msg}\n";
|
||||
|
||||
// calculate http url
|
||||
$http_url = "http://{$expected_host}{$http_port}";
|
||||
$urls .= "{$http_primary}HTTP url: {$http_url}{$http_msg}\n";
|
||||
$urls .= geturls_checkhost($expected_host, $expected_host, $internalip, $dnsserver);
|
||||
|
||||
// calculate https url - self-signed or user-provided in tower_unraid_bundle.pem
|
||||
// this is available when USE_SSL != no, and the certificate file exists
|
||||
if ($var['USE_SSL'] != "no" && file_exists("{$cert_path}{$https_1_cert}")) {
|
||||
@@ -252,7 +229,6 @@ function geturls() {
|
||||
$urls .= "HTTPS url 1 (undefined): https://{$expected_host}{$https_port}\n (this url is not configured, it will not work)\n";
|
||||
$urls .= geturls_checkhost($expected_host, $expected_host, $internalip, $dnsserver);
|
||||
}
|
||||
|
||||
// calculate https url for certificate_bundle.pem
|
||||
// this is available if the certificate file exists, regardless of the USE_SSL setting
|
||||
// this is usually a (my)unraid.net LE cert, but it can also be a user-provided cert
|
||||
@@ -265,11 +241,9 @@ function geturls() {
|
||||
$urls .= " ERROR: the certificate Subject CN in {$https_2_cert} should be {$expected_host}\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($var['USE_SSL'] != "no") {
|
||||
$telnet_disabled = ($var['USE_TELNET'] == "no") ? " (disabled)" : "";
|
||||
$ssh_disabled = ($var['USE_SSH'] == "no") ? " (disabled)" : "";
|
||||
|
||||
$urls .= "\nTip: if DNS goes down and you lose access to the webgui, use telnet{$telnet_disabled}, ";
|
||||
$urls .= "ssh{$ssh_disabled}, or a local keyboard/monitor to run:\n";
|
||||
$urls .= " use_ssl no\n";
|
||||
@@ -277,11 +251,10 @@ function geturls() {
|
||||
if ($var['USE_SSL'] == "auto") {
|
||||
$urls .= "Or:\n";
|
||||
$urls .= " use_ssl yes\n";
|
||||
$urls .= "to make 'HTTPS url 1' the primary.";
|
||||
$urls .= "to make 'HTTPS url 1' the primary.";
|
||||
}
|
||||
$urls .= "\nOnce DNS has been restored, navigate to Settings -> Management Access and set 'Use SSL' back to '{$var['USE_SSL']}'\n";
|
||||
}
|
||||
|
||||
// get a list of the certificate files on the flash drive
|
||||
$dirlisting[0] = "{$cert_path}";
|
||||
if (file_exists($cert_path)) {
|
||||
@@ -292,28 +265,29 @@ function geturls() {
|
||||
$urls .= "\n\n".implode("\n", $dirlisting)."\n";
|
||||
$urls = str_replace("\n", "\r\n", $urls);
|
||||
return $urls;
|
||||
|
||||
}
|
||||
|
||||
exert("mkdir -p /boot/logs");
|
||||
// diagnostics start
|
||||
run("mkdir -p /boot/logs");
|
||||
|
||||
if ($cli) {
|
||||
// script is called from CLI
|
||||
// script is called from CLI
|
||||
echo "Starting diagnostics collection... ";
|
||||
$server = isset($var['NAME']) ? str_replace(' ','_',strtolower($var['NAME'])) : 'tower';
|
||||
$date = date('Ymd-Hi');
|
||||
$diag = "$server-diagnostics-$date";
|
||||
$zip = "/boot/logs/$diag.zip";
|
||||
} else {
|
||||
// script is called from GUI
|
||||
// script is called from GUI
|
||||
$diag = basename($zip, '.zip');
|
||||
$split = explode('-', $diag);
|
||||
$date = "{$split[2]}-{$split[3]}";
|
||||
}
|
||||
|
||||
// don't anonymize system share names
|
||||
$vardomain = (array)@parse_ini_file('/boot/config/domain.cfg');
|
||||
$vardocker = (array)@parse_ini_file('/boot/config/docker.cfg');
|
||||
$showshares = [];
|
||||
$vardomain = (array)@parse_ini_file('/boot/config/domain.cfg');
|
||||
$vardocker = (array)@parse_ini_file('/boot/config/docker.cfg');
|
||||
$showshares = [];
|
||||
$showshares[] = current(array_slice(explode('/',$vardomain['IMAGE_FILE']), 3, 1)).'.cfg';
|
||||
$showshares[] = current(array_slice(explode('/',$vardomain['DOMAINDIR']), 3, 1)).'.cfg';
|
||||
$showshares[] = current(array_slice(explode('/',$vardomain['MEDIADIR']), 3, 1)).'.cfg';
|
||||
@@ -323,27 +297,32 @@ $showshares[] = current(array_slice(explode('/',$vardocker['DOCKER_APP_CONFIG_PA
|
||||
$showshares[] = current(array_slice(explode('/',$vardocker['DOCKER_HOME']), 3, 1)).'.cfg';
|
||||
foreach ($showshares as $show) {
|
||||
$showme = str_replace(".cfg","",$show);
|
||||
if ($showme)
|
||||
$customShares .= "|$showme";
|
||||
if ($showme) $customShares .= "|$showme";
|
||||
}
|
||||
|
||||
// create folder structure
|
||||
exert("mkdir -p ".escapeshellarg("/$diag/system")." ".escapeshellarg("/$diag/config")." ".escapeshellarg("/$diag/logs")." ".escapeshellarg("/$diag/shares")." ".escapeshellarg("/$diag/smart")." ".escapeshellarg("/$diag/qemu")." ".escapeshellarg("/$diag/xml"));
|
||||
run("mkdir -p ".escapeshellarg("/$diag/system")." ".escapeshellarg("/$diag/config")." ".escapeshellarg("/$diag/logs")." ".escapeshellarg("/$diag/shares")." ".escapeshellarg("/$diag/smart")." ".escapeshellarg("/$diag/qemu")." ".escapeshellarg("/$diag/xml"));
|
||||
|
||||
// get utilization of running processes
|
||||
exert("top -bn1 -o%CPU 2>/dev/null|todos >".escapeshellarg("/$diag/system/top.txt"));
|
||||
run("top -bn1 -o%CPU 2>/dev/null|todos >".escapeshellarg("/$diag/system/top.txt"));
|
||||
|
||||
// make Unraid version reference
|
||||
$unraid = parse_ini_file('/etc/unraid-version');
|
||||
$unraid_vars = parse_ini_file('/var/local/emhttp/var.ini');
|
||||
file_put_contents("/$diag/unraid-".$unraid['version'].".txt",$unraid['version']."\r\n");
|
||||
|
||||
// add bz*.sha256 values
|
||||
exert("tail /boot/bz*.sha256 >> ".escapeshellarg("/$diag/unraid-".$unraid['version'].".txt"));
|
||||
run("tail /boot/bz*.sha256 >> ".escapeshellarg("/$diag/unraid-".$unraid['version'].".txt"));
|
||||
|
||||
// copy ini variables
|
||||
foreach (glob("$get/*.ini") as $file) {
|
||||
$ini = basename($file,".ini");
|
||||
// skip users file in anonymized mode
|
||||
if ($all || $ini != "users") file_put_contents("/$diag/system/vars.txt",preg_replace(["/\n/","/^Array/"],["\r\n",$ini],anonymize(print_r(parse_ini_file($file,true),true),1)),FILE_APPEND);
|
||||
}
|
||||
|
||||
// Create loads.txt
|
||||
$cpuload = exert("uptime")." Cores: ".exert("nproc")."\r\n".(string)@file_get_contents("$get/cpuload.ini")."\r\n";
|
||||
$cpuload = run("uptime")." Cores: ".run("nproc")."\r\n".(string)@file_get_contents("$get/cpuload.ini")."\r\n";
|
||||
$diskload = (array)@file("$get/diskload.ini");
|
||||
$disks = (array)@parse_ini_file("$get/disks.ini",true);
|
||||
$loadTxt = [];
|
||||
@@ -357,44 +336,51 @@ foreach ($diskload as $loadLine) {
|
||||
}
|
||||
}
|
||||
file_put_contents("/$diag/system/loads.txt",$cpuload.implode("\r\n",$loadTxt));
|
||||
|
||||
// individual commands execution (suppress errors)
|
||||
exert("lscpu 2>/dev/null|todos >".escapeshellarg("/$diag/system/lscpu.txt"));
|
||||
exert("lsscsi -vgl 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsscsi.txt"));
|
||||
exert("lspci -knn 2>/dev/null|todos >".escapeshellarg("/$diag/system/lspci.txt"));
|
||||
exert("lsusb 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsusb.txt"));
|
||||
exert("free -mth 2>/dev/null|todos >".escapeshellarg("/$diag/system/memory.txt"));
|
||||
exert("ps -auxf --sort=-pcpu 2>/dev/null|todos >".escapeshellarg("/$diag/system/ps.txt"));
|
||||
exert("lsof -Pni 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsof.txt"));
|
||||
exert("lsmod|sort 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsmod.txt"));
|
||||
exert("df -h 2>/dev/null|todos >".escapeshellarg("/$diag/system/df.txt"));
|
||||
exert("ifconfig -a -s 2>/dev/null|grep -Po '^(eth|bond)[0-9]+'", $ports);
|
||||
exert("dmidecode -qt2|awk -F: '/^\tManufacturer:/{m=\$2};/^\tProduct Name:/{p=\$2} END{print m\" -\"p}' 2>/dev/null|todos >".escapeshellarg("/$diag/system/motherboard.txt"));
|
||||
exert("dmidecode -qt0 2>/dev/null|todos >>".escapeshellarg("/$diag/system/motherboard.txt"));
|
||||
exert("cat /proc/meminfo 2>/dev/null|todos >".escapeshellarg("/$diag/system/meminfo.txt"));
|
||||
exert("dmidecode --type 17 2>/dev/null|todos >>".escapeshellarg("/$diag/system/meminfo.txt"));
|
||||
run("lscpu 2>/dev/null|todos >".escapeshellarg("/$diag/system/lscpu.txt"));
|
||||
run("lsscsi -vgl 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsscsi.txt"));
|
||||
run("lspci -knn 2>/dev/null|todos >".escapeshellarg("/$diag/system/lspci.txt"));
|
||||
run("lsusb 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsusb.txt"));
|
||||
run("free -mth 2>/dev/null|todos >".escapeshellarg("/$diag/system/memory.txt"));
|
||||
run("ps -auxf --sort=-pcpu 2>/dev/null|todos >".escapeshellarg("/$diag/system/ps.txt"));
|
||||
run("lsof -Pni 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsof.txt"));
|
||||
run("lsmod|sort 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsmod.txt"));
|
||||
run("df -h 2>/dev/null|todos >".escapeshellarg("/$diag/system/df.txt"));
|
||||
run("ifconfig -a -s 2>/dev/null|grep -Po '^(eth|bond)[0-9]+'", $ports);
|
||||
run("dmidecode -qt2|awk -F: '/^\tManufacturer:/{m=\$2};/^\tProduct Name:/{p=\$2} END{print m\" -\"p}' 2>/dev/null|todos >".escapeshellarg("/$diag/system/motherboard.txt"));
|
||||
run("dmidecode -qt0 2>/dev/null|todos >>".escapeshellarg("/$diag/system/motherboard.txt"));
|
||||
run("cat /proc/meminfo 2>/dev/null|todos >".escapeshellarg("/$diag/system/meminfo.txt"));
|
||||
run("dmidecode --type 17 2>/dev/null|todos >>".escapeshellarg("/$diag/system/meminfo.txt"));
|
||||
|
||||
// create ethernet information information (suppress errors)
|
||||
foreach ($ports as $port) {
|
||||
exert("ethtool ".escapeshellarg($port)." 2>/dev/null|todos >>".escapeshellarg("/$diag/system/ethtool.txt"));
|
||||
run("ethtool ".escapeshellarg($port)." 2>/dev/null|todos >>".escapeshellarg("/$diag/system/ethtool.txt"));
|
||||
file_put_contents("/$diag/system/ethtool.txt", "\r\n", FILE_APPEND);
|
||||
exert("ethtool -i ".escapeshellarg($port)." 2>/dev/null|todos >>".escapeshellarg("/$diag/system/ethtool.txt"));
|
||||
run("ethtool -i ".escapeshellarg($port)." 2>/dev/null|todos >>".escapeshellarg("/$diag/system/ethtool.txt"));
|
||||
file_put_contents("/$diag/system/ethtool.txt", "--------------------------------\r\n", FILE_APPEND);
|
||||
}
|
||||
exert("ifconfig -a 2>/dev/null|todos >".escapeshellarg("/$diag/system/ifconfig.txt"));
|
||||
run("ifconfig -a 2>/dev/null|todos >".escapeshellarg("/$diag/system/ifconfig.txt"));
|
||||
|
||||
// create system information (suppress errors)
|
||||
exert("find /sys/kernel/iommu_groups/ -type l 2>/dev/null|sort -V|todos >".escapeshellarg("/$diag/system/iommu_groups.txt"));
|
||||
exert("todos </proc/cmdline >".escapeshellarg("/$diag/system/cmdline.txt"));
|
||||
run("find /sys/kernel/iommu_groups/ -type l 2>/dev/null|sort -V|todos >".escapeshellarg("/$diag/system/iommu_groups.txt"));
|
||||
run("todos </proc/cmdline >".escapeshellarg("/$diag/system/cmdline.txt"));
|
||||
|
||||
// create folder structure listing
|
||||
$dest = "/$diag/system/folders.txt";
|
||||
foreach ($folders as $folder) {
|
||||
if (is_dir($folder)) exert("echo -ne ".escapeshellarg("\r\n$folder\r\n")." >>".escapeshellarg($dest).";ls -l ".escapeshellarg($folder)."|todos >>".escapeshellarg("$dest")); else exert("echo -ne ".escapeshellarg("\r\n$folder\r\nfolder does not exist\r\n")." >>".escapeshellarg("$dest"));
|
||||
if (is_dir($folder)) run("echo -ne ".escapeshellarg("\r\n$folder\r\n")." >>".escapeshellarg($dest).";ls -l ".escapeshellarg($folder)."|todos >>".escapeshellarg("$dest")); else run("echo -ne ".escapeshellarg("\r\n$folder\r\nfolder does not exist\r\n")." >>".escapeshellarg("$dest"));
|
||||
}
|
||||
|
||||
// copy configuration files (suppress errors)
|
||||
exert("cp /boot/config/*.{cfg,conf,dat} ".escapeshellarg("/$diag/config")." 2>/dev/null");
|
||||
exert("cp /boot/config/go ".escapeshellarg("/$diag/config/go.txt")." 2>/dev/null");
|
||||
run("cp /boot/config/*.{cfg,conf,dat} ".escapeshellarg("/$diag/config")." 2>/dev/null");
|
||||
run("cp /boot/config/go ".escapeshellarg("/$diag/config/go.txt")." 2>/dev/null");
|
||||
if (!$all)
|
||||
exert("sed -i -e '/password/c ***line removed***' -e '/user/c ***line removed***' -e '/pass/c ***line removed***' ".escapeshellarg("/$diag/config/go.txt"));
|
||||
run("sed -i -e '/password/c ***line removed***' -e '/user/c ***line removed***' -e '/pass/c ***line removed***' ".escapeshellarg("/$diag/config/go.txt"));
|
||||
|
||||
// anonymize configuration files
|
||||
if (!$all) exert("sed -ri 's/^((disk|flash)(Read|Write)List.*=\")[^\"]+/\\1.../' ".escapeshellarg("/$diag/config/*.cfg")." 2>/dev/null");
|
||||
if (!$all)
|
||||
run("sed -ri 's/^((disk|flash)(Read|Write)List.*=\")[^\"]+/\\1.../' ".escapeshellarg("/$diag/config/*.cfg")." 2>/dev/null");
|
||||
|
||||
// copy share information (anonymize if applicable)
|
||||
$files = glob("/boot/config/shares/*.cfg");
|
||||
@@ -404,12 +390,12 @@ foreach ($files as $file) {
|
||||
$dest = anonymize($dest,2);
|
||||
}
|
||||
@copy($file, $dest);
|
||||
if (!$all) exert("sed -ri 's/^(share(Comment|ReadList|WriteList)=\")[^\"]+/\\1.../' ".escapeshellarg($dest)." 2>/dev/null");
|
||||
if (!$all) run("sed -ri 's/^(share(Comment|ReadList|WriteList)=\")[^\"]+/\\1.../' ".escapeshellarg($dest)." 2>/dev/null");
|
||||
$share = pathinfo(basename($file),PATHINFO_FILENAME);
|
||||
$shareExists = explode(",",shareDisks($share));
|
||||
unset($exists);
|
||||
foreach ($shareExists as $anon) {
|
||||
if ( !$all )
|
||||
if (!$all) {
|
||||
if (!preg_match("/\b((disk)[0-9]+)|(cache)\b/", $anon)) {
|
||||
$len = strlen($anon);
|
||||
if ($len>2) {
|
||||
@@ -417,20 +403,23 @@ foreach ($files as $file) {
|
||||
$exists[] = substr($anon,0,1).$dash.substr($anon,-1);
|
||||
}
|
||||
}
|
||||
else
|
||||
} else {
|
||||
$exists[] = $anon;
|
||||
}
|
||||
}
|
||||
$shareDisk .= $exists ? str_pad(pathinfo($dest,PATHINFO_FILENAME),34).str_pad(exec("cat ".escapeshellarg($file)." | grep shareUseCache"),22)." Exists on ".implode(", ",$exists)."\r\n" : "";
|
||||
$exists = $exists ?: ["no drives"];
|
||||
file_put_contents($dest,"# Share exists on ".implode(", ",$exists)."\r\n",FILE_APPEND);
|
||||
}
|
||||
file_put_contents("/$diag/shares/shareDisks.txt",$shareDisk);
|
||||
|
||||
// create default user shares information
|
||||
$shares = (array)@parse_ini_file("$get/shares.ini", true);
|
||||
foreach ($shares as $share) {
|
||||
$name = $share['name'];
|
||||
if (!in_array("/boot/config/shares/$name.cfg",$files)) file_put_contents(anonymize("/$diag/shares/$name.cfg",2),"# This share has default settings.\r\n# Share exists on ".shareDisks($name)."\r\n");
|
||||
}
|
||||
|
||||
// copy pools information (anonymize)
|
||||
$files = glob("/boot/config/pools/*.cfg");
|
||||
@mkdir("/$diag/config/pools");
|
||||
@@ -438,6 +427,7 @@ foreach ($files as $file) {
|
||||
$dest = anonymize("/$diag/config/pools/".basename($file),2);
|
||||
@copy($file,$dest);
|
||||
}
|
||||
|
||||
// copy modprobe information
|
||||
$files = glob("/boot/config/modprobe.d/*.conf");
|
||||
if ($files) {
|
||||
@@ -447,22 +437,24 @@ if ($files) {
|
||||
@copy($file,$dest);
|
||||
}
|
||||
}
|
||||
|
||||
// copy docker information (if existing)
|
||||
$max = 1*1024*1024; //=1MB
|
||||
$docker = "/var/log/docker.log";
|
||||
if (file_exists($docker)) {
|
||||
$log = "/$diag/logs/docker";
|
||||
exert("todos <$docker >".escapeshellarg("$log.txt"));
|
||||
run("todos <$docker >".escapeshellarg("$log.txt"));
|
||||
if (filesize($docker)>=$max) {
|
||||
exert("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
||||
exert("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
||||
run("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
||||
run("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
||||
}
|
||||
}
|
||||
|
||||
// create SMART reports (suppress errors)
|
||||
$disks = (array)@parse_ini_file("$get/disks.ini", true);
|
||||
include_once "$docroot/webGui/include/CustomMerge.php";
|
||||
include_once "$docroot/webGui/include/Wrappers.php";
|
||||
exert("ls -l /dev/disk/by-id/[asun]* 2>/dev/null|sed '/-part/d;s|^.*/by-id/[^-]*-||;s|-> ../../||;s|:|-|'", $devices);
|
||||
run("ls -l /dev/disk/by-id/[asun]* 2>/dev/null|sed '/-part/d;s|^.*/by-id/[^-]*-||;s|-> ../../||;s|:|-|'", $devices);
|
||||
foreach ($devices as $device) {
|
||||
list($name,$port) = explode(' ',$device);
|
||||
$diskName = ''; $type = '';
|
||||
@@ -477,135 +469,145 @@ foreach ($devices as $device) {
|
||||
}
|
||||
$port = port_name($port);
|
||||
$status = $find['status'] == "DISK_OK" ? "" : " - {$find['status']}";
|
||||
exert("smartctl -x $type ".escapeshellarg("/dev/$port")." 2>/dev/null|todos >".escapeshellarg("/$diag/smart/$name-$date $diskName ($port)$status.txt"));
|
||||
run("smartctl -x $type ".escapeshellarg("/dev/$port")." 2>/dev/null|todos >".escapeshellarg("/$diag/smart/$name-$date $diskName ($port)$status.txt"));
|
||||
}
|
||||
|
||||
// create pool btrfs information
|
||||
foreach (pools_filter($disks) as $pool) {
|
||||
if (strpos($disks[$pool]['fsType'],'btrfs')!==false) {
|
||||
exert("echo 'Pool: $pool'|todos >>".escapeshellarg("/$diag/system/btrfs-usage.txt"));
|
||||
exert("/sbin/btrfs filesystem usage -T /mnt/$pool 2>/dev/null|todos >>".escapeshellarg("/$diag/system/btrfs-usage.txt"));
|
||||
run("echo 'Pool: $pool'|todos >>".escapeshellarg("/$diag/system/btrfs-usage.txt"));
|
||||
run("/sbin/btrfs filesystem usage -T /mnt/$pool 2>/dev/null|todos >>".escapeshellarg("/$diag/system/btrfs-usage.txt"));
|
||||
}
|
||||
}
|
||||
|
||||
// create installed plugin information
|
||||
$pluginList = json_decode(download_url("https://raw.githubusercontent.com/Squidly271/AppFeed/master/pluginList.json"),true);
|
||||
if ( ! $pluginList )
|
||||
$installedPlugins = "Could not download current plugin versions\r\n\r\n";
|
||||
|
||||
if (!$pluginList) $installedPlugins = "Could not download current plugin versions\r\n\r\n";
|
||||
$plugins = glob("/var/log/plugins/*.plg");
|
||||
foreach ($plugins as $plugin) {
|
||||
$plgVer = exert("plugin version ".escapeshellarg($plugin));
|
||||
$plgURL = exert("plugin pluginURL ".escapeshellarg($plugin));
|
||||
|
||||
$plgVer = run("plugin version ".escapeshellarg($plugin));
|
||||
$plgURL = run("plugin pluginURL ".escapeshellarg($plugin));
|
||||
$installedPlugins .= basename($plugin)." - $plgVer";
|
||||
if ( $pluginList && ! $pluginList[$plgURL] && basename($plugin) !== "unRAIDServer.plg")
|
||||
if ($pluginList && ! $pluginList[$plgURL] && basename($plugin) !== "unRAIDServer.plg")
|
||||
$installedPlugins .= " (Unknown to Community Applications)";
|
||||
if ( $pluginList[$plgURL]['blacklist'] )
|
||||
if ($pluginList[$plgURL]['blacklist'])
|
||||
$installedPlugins .= " (Blacklisted)";
|
||||
if ( $pluginList[$plgURL]['deprecated'] || ( $pluginList[$plgURL]['dmax'] && version_compare($pluginList[$plgURL]['dmax'],$unraid['version'],"<") ) )
|
||||
if ($pluginList[$plgURL]['deprecated'] || ($pluginList[$plgURL]['dmax'] && version_compare($pluginList[$plgURL]['dmax'],$unraid['version'],"<")))
|
||||
$installedPlugins .= " (Deprecated)";
|
||||
if ( $pluginList[$plgURL]['version'] > $plgVer )
|
||||
if ($pluginList[$plgURL]['version'] > $plgVer)
|
||||
$installedPlugins .= " (Update available: {$pluginList[$plgURL]['version']})";
|
||||
elseif ($pluginList[$plgURL])
|
||||
$installedPlugins .= " (Up to date)";
|
||||
if ( $pluginList[$plgURL]['max'] && version_compare($pluginList[$plgURL]['max'],$unraid['version'],"<") )
|
||||
if ($pluginList[$plgURL]['max'] && version_compare($pluginList[$plgURL]['max'],$unraid['version'],"<"))
|
||||
$installedPlugins .= " (Incompatible)";
|
||||
if ( $pluginList[$plgURL]['min'] && version_compare($pluginList[$plgURL]['min'],$unraid['version'],">") )
|
||||
if ($pluginList[$plgURL]['min'] && version_compare($pluginList[$plgURL]['min'],$unraid['version'],">"))
|
||||
$installedPlugins .= " (Incompatible)";
|
||||
|
||||
$installedPlugins .= "\r\n";
|
||||
}
|
||||
$installedPlugins = $installedPlugins ?: "No additional Plugins Installed";
|
||||
file_put_contents("/$diag/system/plugins.txt",$installedPlugins);
|
||||
|
||||
// determine urls
|
||||
file_put_contents("/$diag/system/urls.txt",geturls());
|
||||
|
||||
// copy libvirt information (if existing)
|
||||
$libvirtd = "/var/log/libvirt/libvirtd.log";
|
||||
if (file_exists($libvirtd)) {
|
||||
$log = "/$diag/logs/libvirt";
|
||||
exert("todos <$libvirtd >".escapeshellarg("$log.txt"));
|
||||
run("todos <$libvirtd >".escapeshellarg("$log.txt"));
|
||||
if (filesize($libvirtd)>=$max) {
|
||||
exert("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
||||
exert("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
||||
run("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
||||
run("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
||||
}
|
||||
}
|
||||
|
||||
// copy VMs information (if existing)
|
||||
$qemu = glob("/var/log/libvirt/qemu/*.log*");
|
||||
if ($qemu) {
|
||||
foreach ($qemu as $file) {
|
||||
$log = "/$diag/qemu/".basename($file,'.log');
|
||||
exert("todos <".escapeshellarg($file)." >".escapeshellarg("$log.txt"));
|
||||
run("todos <".escapeshellarg($file)." >".escapeshellarg("$log.txt"));
|
||||
if (filesize($file)>=$max) {
|
||||
exert("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
||||
exert("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
||||
run("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
||||
run("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
file_put_contents("/$diag/qemu/no qemu log files","");
|
||||
}
|
||||
|
||||
// copy VM XML config files
|
||||
exert("cp /etc/libvirt/qemu/*.xml ".escapeshellarg("/$diag/xml")." 2>/dev/null");
|
||||
run("cp /etc/libvirt/qemu/*.xml ".escapeshellarg("/$diag/xml")." 2>/dev/null");
|
||||
|
||||
// anonymize MAC OSK info
|
||||
$all_xml = glob("/$diag/xml/*.xml");
|
||||
foreach ($all_xml as $xml) {
|
||||
exert("sed -ri 's/(,osk=).+/\\1.../' ".escapeshellarg("$xml")." 2>/dev/null");
|
||||
exert("sed -ri 's/(passwd=).+/\\1.../' ".escapeshellarg("$xml")." 2>/dev/null");
|
||||
run("sed -ri 's/(,osk=).+/\\1.../' ".escapeshellarg("$xml")." 2>/dev/null");
|
||||
run("sed -ri 's/(passwd=).+/\\1.../' ".escapeshellarg("$xml")." 2>/dev/null");
|
||||
}
|
||||
|
||||
// copy syslog information (anonymize if applicable)
|
||||
$max = 2*1024*1024; //=2MB
|
||||
foreach (glob("/var/log/syslog*") as $file) {
|
||||
$log = "/$diag/logs/".basename($file);
|
||||
exert("todos <".escapeshellarg($file)." >".escapeshellarg("$log.txt"));
|
||||
run("todos <".escapeshellarg($file)." >".escapeshellarg("$log.txt"));
|
||||
if (!$all) {
|
||||
unset($titles,$rows);
|
||||
exert("grep -Po 'file: \K[^\"]+' ".escapeshellarg("$log.txt")." 2>/dev/null|sort|uniq", $titles);
|
||||
exert("sed -ri 's|\b\S+@\S+\.\S+\b|email@removed.com|;s|\b(username\|password)([=:])\S+\b|\\1\\2xxx|;s|(GUID: \S)\S+(\S) |\\1..\\2 |;s|(moving \"\S\|\"/mnt/user/\S).*(\S)\"|\\1..\\2\"|' ".escapeshellarg("$log.txt"));
|
||||
exert("sed -ri 's|(server: ).+(\.(my)?unraid\.net(:[0-9]+)?,)|\\1hash\\2|;s|(host: \").+(\.(my)?unraid\.net(:[0-9]+)?\")|\\1hash\\2|;s|(referrer: \"https?://).+(\.(my)?unraid\.net)|\\1hash\\2|' ".escapeshellarg("$log.txt"));
|
||||
run("grep -Po 'file: \K[^\"]+' ".escapeshellarg("$log.txt")." 2>/dev/null|sort|uniq", $titles);
|
||||
run("sed -ri 's|\b\S+@\S+\.\S+\b|email@removed.com|;s|\b(username\|password)([=:])\S+\b|\\1\\2xxx|;s|(GUID: \S)\S+(\S) |\\1..\\2 |;s|(moving \"\S\|\"/mnt/user/\S).*(\S)\"|\\1..\\2\"|' ".escapeshellarg("$log.txt"));
|
||||
run("sed -ri 's|(server: ).+(\.(my)?unraid\.net(:[0-9]+)?,)|\\1hash\\2|;s|(host: \").+(\.(my)?unraid\.net(:[0-9]+)?\")|\\1hash\\2|;s|(referrer: \"https?://).+(\.(my)?unraid\.net)|\\1hash\\2|' ".escapeshellarg("$log.txt"));
|
||||
foreach ($titles as $mover) {
|
||||
$title = "/{$mover[0]}..".substr($mover,-1)."/...";
|
||||
exert("sed -i 's/".str_replace("/","\/",$mover)."/".str_replace("/","\/",$title)."/g' ".escapeshellarg("$log.txt")." 2>/dev/null");
|
||||
//exert("sed -ri 's|(file: [.>cr].*)[ /]$mover/.*$|\\1 file: $title|' ".escapeshellarg("$log.txt")." 2>/dev/null");
|
||||
run("sed -i 's/".str_replace("/","\/",$mover)."/".str_replace("/","\/",$title)."/g' ".escapeshellarg("$log.txt")." 2>/dev/null");
|
||||
//run("sed -ri 's|(file: [.>cr].*)[ /]$mover/.*$|\\1 file: $title|' ".escapeshellarg("$log.txt")." 2>/dev/null");
|
||||
}
|
||||
exert("grep -n ' cache_dirs: -' ".escapeshellarg("$log.txt")." 2>/dev/null|cut -d: -f1", $rows);
|
||||
for ($i = 0; $i < count($rows); $i += 2) for ($row = $rows[$i]+1; $row < $rows[$i+1]; $row++) exert("sed -ri '$row s|(cache_dirs: \S).*(\S)|\\1..\\2|' ".escapeshellarg("$log.txt")." 2>/dev/null");
|
||||
run("grep -n ' cache_dirs: -' ".escapeshellarg("$log.txt")." 2>/dev/null|cut -d: -f1", $rows);
|
||||
for ($i = 0; $i < count($rows); $i += 2) for ($row = $rows[$i]+1; $row < $rows[$i+1]; $row++) run("sed -ri '$row s|(cache_dirs: \S).*(\S)|\\1..\\2|' ".escapeshellarg("$log.txt")." 2>/dev/null");
|
||||
}
|
||||
// replace consecutive repeated lines in syslog
|
||||
exert("awk -i inplace '{if(s!=substr(\$0,17)){if(x>0)print\"### [PREVIOUS LINE REPEATED \"x\" TIMES] ###\\r\";print;x=0}else{x++}s=substr(\$0,17)}END{if(x>0)print\"### [PREVIOUS LINE REPEATED \"x\" TIMES] ###\\r\"}' ".escapeshellarg("$log.txt"));
|
||||
run("awk -i inplace '{if(s!=substr(\$0,17)){if(x>0)print\"### [PREVIOUS LINE REPEATED \"x\" TIMES] ###\\r\";print;x=0}else{x++}s=substr(\$0,17)}END{if(x>0)print\"### [PREVIOUS LINE REPEATED \"x\" TIMES] ###\\r\"}' ".escapeshellarg("$log.txt"));
|
||||
// remove SHA256 hashes
|
||||
exert("sed -ri 's/(SHA256:).+[^\s\b]/SHA256:***REMOVED***/gm' $log.txt");
|
||||
run("sed -ri 's/(SHA256:).+[^\s\b]/SHA256:***REMOVED***/gm' $log.txt");
|
||||
// truncate syslog if too big
|
||||
if (basename($file)=='syslog' && filesize($file)>=$max) exert("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
||||
exert("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
||||
if (basename($file)=='syslog' && filesize($file)>=$max) run("tail -n 200 ".escapeshellarg("$log.txt")." >".escapeshellarg("$log.last200.txt"));
|
||||
run("truncate -s '<$max' ".escapeshellarg("$log.txt"));
|
||||
}
|
||||
|
||||
// copy dhcplog
|
||||
$dhcplog = "/var/log/dhcplog";
|
||||
if (file_exists($dhcplog)) {
|
||||
$log = "/$diag/logs/dhcplog.txt";
|
||||
exert("todos <$dhcplog >".escapeshellarg($log));
|
||||
run("todos <$dhcplog >".escapeshellarg($log));
|
||||
}
|
||||
|
||||
// copy graphql-api.log
|
||||
$graphql = "/var/log/graphql-api.log";
|
||||
if (file_exists($graphql)) {
|
||||
$log = "/$diag/logs/graphql-api.txt";
|
||||
exert("todos <$graphql >".escapeshellarg($log));
|
||||
run("todos <$graphql >".escapeshellarg($log));
|
||||
}
|
||||
|
||||
// copy vfio-pci log
|
||||
$vfiopci = "/var/log/vfio-pci";
|
||||
if (file_exists($vfiopci)) {
|
||||
$log = "/$diag/logs/vfio-pci.txt";
|
||||
exert("todos <$vfiopci >".escapeshellarg($log));
|
||||
run("todos <$vfiopci >".escapeshellarg($log));
|
||||
}
|
||||
|
||||
// generate unraid-api.txt
|
||||
if (file_exists("/usr/local/sbin/unraid-api")) {
|
||||
$log = "/$diag/system/unraid-api.txt";
|
||||
exert("unraid-api report | todos >".escapeshellarg($log));
|
||||
run("unraid-api report | todos >".escapeshellarg($log));
|
||||
}
|
||||
|
||||
// create resulting zip file and remove temp folder
|
||||
exert("zip -qmr ".escapeshellarg($zip)." ".escapeshellarg("/$diag"));
|
||||
run("zip -qmr ".escapeshellarg($zip)." ".escapeshellarg("/$diag"));
|
||||
if ($cli) {
|
||||
echo "done.\nZIP file '$zip' created.\n";
|
||||
} else {
|
||||
copy($zip,"/boot/logs/".basename($zip));
|
||||
}
|
||||
publish("diagnostic",basename($zip)."FINISHED");
|
||||
|
||||
// signal we are DONE
|
||||
write('_DONE_');
|
||||
?>
|
||||
|
||||
@@ -3,9 +3,12 @@ body.stop-scrolling{height:100%;overflow:hidden}
|
||||
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";/* IE8 */
|
||||
background-color:rgba(0, 0, 0, 0.4);position:fixed;left:0;right:0;top:0;bottom:0;display:none;z-index:10000}
|
||||
.sweet-alert{background-color:white;font-family:clear-sans;width:478px;padding:17px;border-radius:5px;text-align:center;position:fixed;left:50%;top:50%;margin-left:-256px;margin-top:-200px;overflow:hidden;display:none;z-index:99999}
|
||||
.sweet-alert.nchan{height:600px;width:900px;margin-left:-480px}
|
||||
@media all and (max-width:540px){.sweet-alert{width:auto;margin-left:0;margin-right:0;left:15px;right:15px}}
|
||||
.sweet-alert h2{color:#575757;font-size:3rem;text-align:center;font-weight:600;text-transform:none;position:relative;margin:25px 0;padding:0;line-height:40px;display:block}
|
||||
.sweet-alert pre h2{text-align:left;font-size:1.8rem;line-height:normal}
|
||||
.sweet-alert p{color:#797979;font-size:1.5rem;text-align:center;font-weight:300;position:relative;text-align:inherit;float:none;margin:0;padding:0;line-height:normal}
|
||||
.sweet-alert pre p{text-align:left;font-size:1.3rem}
|
||||
.sweet-alert fieldset{border:none;position:relative}
|
||||
.sweet-alert .sa-error-container{background-color:#f1f1f1;margin-left:-17px;margin-right:-17px;overflow:hidden;padding:0 10px;max-height:0;webkit-transition:padding 0.15s, max-height 0.15s;transition:padding 0.15s, max-height 0.15s}
|
||||
.sweet-alert .sa-error-container.show{padding:10px 0;max-height:100px;webkit-transition:padding 0.2s, max-height 0.2s;transition:padding 0.25s, max-height 0.25s}
|
||||
|
||||
Reference in New Issue
Block a user