Plugin system update

This commit is contained in:
bergware
2022-07-15 21:23:21 +02:00
parent a230d199d5
commit 5b641d107b
9 changed files with 181 additions and 62 deletions
+18 -8
View File
@@ -36,7 +36,7 @@ const args = {};
function openInstall(cmd,title,plg) {
if (cmd == null) {
openPlugin(args.cmd,args.title,args.plg);
openPlugin(args.cmd,args.title,args.plg,null,1);
return;
}
args.cmd = cmd;
@@ -69,14 +69,22 @@ 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");
var plugin = [];
$('input.update').each(function(){plugin.push($(this).attr('data'));});
var plugins = plugin.join('*');
$('#updateall').hide();
$.get('/plugins/dynamix.plugin.manager/include/ShowPlugins.php',{cmd:'pending',plugin:plugins},function() {
openPlugin("multiplugin update "+plugins,"_(Update All Plugins)_",":return","loadlist",1);
});
}
function removeList() {
let list = [];
$('input.remove:checked').each(function(){list.push($(this).attr('data'));});
openPlugin("multiplugin remove "+list.join('*'),"_(Remove Selected Plugins)_","","refresh");
var plugin = [];
$('input.remove:checked').each(function(){plugin.push($(this).attr('data'));});
var plugins = plugin.join('*');
$('#removeall').hide();
$.get('/plugins/dynamix.plugin.manager/include/ShowPlugins.php',{cmd:'pending',plugin:plugins},function() {
openPlugin("multiplugin remove "+plugins,"_(Remove Selected Plugins)_","","refresh",1);
});
}
function updateInfo(data) {
var updates = data.split('\n');
@@ -85,6 +93,8 @@ function updateInfo(data) {
for (var i=0,field; field=fields[i]; i++) {
var row = field.split('::');
$('#'+row[0]).attr('data',row[1]).html(row[2]);
var removeButton = $('input[data="'+row[0].substr(4).replace(/-/g,'.')+'.plg'+'"]');
if (row[2].indexOf('hourglass') >= 0) removeButton.hide(); else removeButton.show();
}
}
}
@@ -123,10 +133,10 @@ function loadlist(id,check) {
}
} else {
updateInfo(data[0]);
if (data[1] > 1) $('#updateall').show(); else $('#updateall').hide();
}
$('#plugin_table').trigger('update');
$('#checkall').find('input').prop('disabled',false);
if (data[1] > 1) $('#updateall').show(); else $('#updateall').hide();
});
}
$(function() {
@@ -41,7 +41,11 @@ function make_link($method, $arg, $extra='') {
} else {
$cmd = "plugin $method $arg".($extra?" $extra":"");
}
return "$check<input type='button' id='$id' data='$arg' class='$method' value=\""._(ucfirst($method))."\" onclick='openInstall(\"$cmd\",\""._(ucwords($method)." Plugin")."\",\"$plg\");'$disabled>";
if (is_file("/tmp/plugins/pluginPending/$arg") && !$check) {
return "<span class='orange-text'><i class='fa fa-hourglass-o fa-fw'></i>&nbsp;"._('pending')."</span>";
} else {
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
@@ -39,6 +39,12 @@ if ($cmd=='alert') {
die();
}
if ($cmd=='pending') {
// prepare pending status for multi operations
foreach (explode('*',$_GET['plugin']) as $plugin) file_put_contents("/tmp/plugins/pluginPending/$plugin",'multi');
die();
}
if ($audit) {
[$plg,$action] = my_explode(':',$audit);
switch ($action) {
@@ -27,32 +27,47 @@ 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];
$name = $argv[2];
$error = $argv[3];
$plugin = "/boot/config/plugins/$name";
$type = $argv[1]; // plugin or language
$method = $argv[2]; // install, update, remove, check
$name = $argv[3]; // plugin name (*.plg) or language name (*.xml)
$error = $argv[4]; // error code (empty if none)
if ($method == 'install' or $method == 'update') {
// check if method successfully completed
if ($error) die;
// 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);
$plugin = "/boot/config/plugins/$name";
$pending = "/tmp/plugins/pluginPending";
switch ($type) {
case 'plugin':
switch ($method) {
case 'install':
case 'update':
// abort if method was unsuccessful
if ($error) break;
// 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());
}
echo "Updating support link\n";
file_put_contents($plugin, $xml->saveXML());
}
}
break;
case 'language':
// nothing defined
break;
}
// unset pending status
if ($method != 'check') @unlink("$pending/$name");
?>
@@ -15,20 +15,41 @@
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: "/usr/local/emhttp";
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
$method = $argv[1];
$plugin = $argv[2];
$type = $argv[1]; // plugin or language
$method = $argv[2]; // install, update, remove, check
$name = $argv[3]; // plugin name (*.plg) or language name (*.xml)
// 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);
$plugin = "/boot/config/plugins/$name";
$pending = "/tmp/plugins/pluginPending";
// set pending status
if (!is_dir($pending)) mkdir($pending);
if ($method != 'check') file_put_contents("$pending/$name",$method);
switch ($type) {
case 'plugin':
switch ($method) {
case 'update':
// implicit validation on plugin update
if (@readlink("/var/log/plugins/$name")) plugin('check', $name);
break;
case 'check':
// validate plugin update (not applicable to OS updates)
if ($name == 'unRAIDServer.plg') break;
$new_plugin = "/tmp/plugins/$name";
if (plugin('version', $new_plugin) > plugin('version', $plugin)) {
echo "Validating $name update\n";
if (($status = plugin('validate', $new_plugin)) != 'valid') {
echo "$status\n";
// restore original plugin and undo update
copy($plugin, $new_plugin);
}
}
break;
}
break;
case 'language':
// nothing defined
break;
}
?>
@@ -79,6 +79,34 @@ function write($message) {
}
}
// Run hooked scripts before correct execution of "method"
// method = install, update, remove, check
// hook programs receives three parameters: type=language and method and language-name
//
function pre_hooks() {
global $method, $name;
$language = pathinfo($name)['extension'] == 'xml' ? $name : "lang-$name.xml";
$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 language $method $language");
}
}
// Run hooked scripts after successful or failed completion of "method"
// method = install, update, remove, check
// hook programs receives four parameters: type=language and method and language-name and error (empty if none)
//
function post_hooks($error='') {
global $method, $name;
$language = pathinfo($name)['extension'] == 'xml' ? $name : "lang-$name.xml";
$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 language $method $language $error");
}
}
// Download a file from a URL.
// Returns TRUE if success else FALSE and fills in error.
//
@@ -262,8 +290,12 @@ if ($method == 'install') {
$link_file = "$plugins/$name";
$lang_file = "$boot/$name";
@unlink($link_file);
// run hook scripts for pre processing
pre_hooks();
if (language('install', $xml_file, $error) === false) {
write("language: $error\n");
// run hook scripts for post processing
post_hooks($error);
exit(1);
}
$lang = language('Language', $xml_file, $error) ?: substr($name,0,-4);
@@ -271,6 +303,8 @@ if ($method == 'install') {
symlink($lang_file, $link_file);
write("language: $lang language pack installed\n");
logger("language: $lang language pack installed");
// run hook scripts for post processing
post_hooks();
done();
}
@@ -296,12 +330,18 @@ if ($method == 'check') {
@unlink($xml_file);
exit(1);
}
// run hook scripts for pre processing
pre_hooks();
$version = language('Version', $xml_file, $error);
if ($version === false) {
write("language: $error\n");
// run hook scripts for post processing
post_hooks($error);
exit(1);
}
write("$version\n");
// run hook scripts for post processing
post_hooks();
exit(0);
}
@@ -333,14 +373,20 @@ if ($method == 'update') {
// install the updated plugin
@unlink("$boot/dynamix/lang-$name.zip");
@unlink($link_file);
// run hook scripts for pre processing
pre_hooks();
if (language('install', $xml_file, $error) === false) {
write("language: $error\n");
// run hook scripts for post processing
post_hooks($error);
exit(1);
}
copy($xml_file, $lang_file);
symlink($lang_file, $link_file);
write("language: $lang language pack updated\n");
logger("language: $lang language pack updated");
// run hook scripts for post processing
post_hooks();
done();
}
@@ -356,12 +402,18 @@ if ($method == 'remove') {
exit(1);
}
$lang = language('Language', $lang_file, $error) ?: $name;
// run hook scripts for pre processing
pre_hooks();
if (language('remove', $lang_file, $error) === false) {
write("language: $error\n");
// run hook scripts for post processing
post_hooks($error);
exit(1);
}
write("language: $lang language pack removed\n");
logger("language: $lang language pack removed");
// run hook scripts for post processing
post_hooks();
done();
}
@@ -200,27 +200,27 @@ function run($command) {
// Run hooked scripts before correct execution of "method"
// method = install, update, remove, check
// hook programs receives two parameters: method and plugin-name
// hook programs receives three parameters: type=plugin and 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("$hook plugin $method $plugin");
}
}
// Run hooked scripts after successful or failed completion of "method"
// method = install, update, remove, check
// hook programs receives three parameters: method and plugin-name and error (empty if none)
// hook programs receives four parameters: type=plugin and method and plugin-name and error (empty if none)
//
function post_hooks($error='') {
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 $error");
run("$hook plugin $method $plugin $error");
}
}