mirror of
https://github.com/unraid/webgui.git
synced 2026-04-21 17:29:28 -05:00
repo reorg
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2019-2023, 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,
|
||||
* 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';
|
||||
//add translations
|
||||
$_SERVER['REQUEST_URI'] = "plugins";
|
||||
require_once "$docroot/plugins/dynamix/include/Translations.php";
|
||||
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
|
||||
require_once "$docroot/plugins/dynamix/include/Secure.php";
|
||||
|
||||
function download_url($url, $path = "") {
|
||||
$ch = curl_init();
|
||||
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);
|
||||
return $out ?: false;
|
||||
}
|
||||
|
||||
switch ($_POST['action']) {
|
||||
case 'checkPlugin':
|
||||
$options = $_POST['options'] ?? '';
|
||||
$plugin = $options['plugin'] ?? '';
|
||||
|
||||
$name = unbundle($options['name'] ?? $plugin);
|
||||
$file = "/boot/config/plugins/$plugin";
|
||||
$file = realpath($file)==$file ? $file : "";
|
||||
|
||||
if ( ! $plugin || ! file_exists($file) ) {
|
||||
echo json_encode(["updateAvailable"=>false]);
|
||||
break;
|
||||
}
|
||||
|
||||
exec("mkdir -p /tmp/plugins");
|
||||
@unlink("/tmp/plugins/$plugin");
|
||||
$url = plugin("pluginURL","/boot/config/plugins/$plugin");
|
||||
download_url($url,"/tmp/plugins/$plugin");
|
||||
|
||||
$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'],'<=');
|
||||
}
|
||||
$updateMessage = sprintf(_("%s: An update is available."),$name);
|
||||
$linkMessage = sprintf(_("Click here to install version %s"),$version);
|
||||
|
||||
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) ?: [];
|
||||
$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;
|
||||
}
|
||||
?>
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* 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/Wrappers.php";
|
||||
extract(parse_plugin_cfg('dynamix',true));
|
||||
|
||||
// add translations
|
||||
$_SERVER['REQUEST_URI'] = 'plugins';
|
||||
$login_locale = _var($display,'locale');
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
|
||||
$nchan = $argv[$argc-1] == 'nchan'; // console or nchan output
|
||||
|
||||
function write(...$messages){
|
||||
global $nchan;
|
||||
if ($nchan) {
|
||||
$com = curl_init();
|
||||
curl_setopt_array($com,[
|
||||
CURLOPT_URL => 'http://localhost/pub/plugins?buffer_length=1',
|
||||
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
|
||||
CURLOPT_POST => 1,
|
||||
CURLOPT_RETURNTRANSFER => true
|
||||
]);
|
||||
foreach ($messages as $message) {
|
||||
curl_setopt($com, CURLOPT_POSTFIELDS, $message);
|
||||
curl_exec($com);
|
||||
}
|
||||
curl_close($com);
|
||||
} else {
|
||||
foreach ($messages as $message) echo $message;
|
||||
}
|
||||
}
|
||||
|
||||
write(_("Checking connectivity")." ...\n");
|
||||
if (exec("wget --spider --no-check-certificate -nv -T10 -t1 https://www.msftncsi.com/ncsi.txt 2>&1|grep -om1 'OK'")) {
|
||||
$check = popen('plugin checkall','r');
|
||||
while (!feof($check)) write(fgets($check));
|
||||
pclose($check);
|
||||
} else {
|
||||
write(_("No response, aborting")."!\n");
|
||||
}
|
||||
if ($nchan) write('_DONE_','');
|
||||
?>
|
||||
+442
@@ -0,0 +1,442 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
// Copyright 2005-2023, 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.
|
||||
|
||||
Usage: language install LANGUAGE-FILE
|
||||
install a language
|
||||
|
||||
Usage: language [attribute name] LANGUAGE-FILE
|
||||
obtain an attribute value
|
||||
|
||||
Usage: language check LANGUAGE
|
||||
check and output the latest version of the language
|
||||
|
||||
Usage: language update LANGUAGE
|
||||
update the language
|
||||
|
||||
Usage: language remove LANGUAGE
|
||||
remove the language
|
||||
|
||||
Usage: language checkall
|
||||
check the latest version of all installed languages
|
||||
|
||||
Usage: language updateall
|
||||
update all installed languages
|
||||
|
||||
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';
|
||||
case -1: return 'Generic error';
|
||||
case 1: return 'Generic error';
|
||||
case 2: return 'Parse error';
|
||||
case 3: return 'File I/O error';
|
||||
case 4: return 'Network failure';
|
||||
case 5: return 'SSL verification failure';
|
||||
case 6: return 'Username/password authentication failure';
|
||||
case 7: return 'Protocol errors';
|
||||
case 8: return 'Invalid URL / Server error response';
|
||||
default: return 'Error code '.$code;
|
||||
}
|
||||
}
|
||||
|
||||
// Signal DONE to caller
|
||||
//
|
||||
function done($code) {
|
||||
global $nchan;
|
||||
if ($nchan) write('_DONE_','');
|
||||
exit($code);
|
||||
}
|
||||
|
||||
// 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(...$messages){
|
||||
global $nchan;
|
||||
if ($nchan) {
|
||||
$com = curl_init();
|
||||
curl_setopt_array($com,[
|
||||
CURLOPT_URL => 'http://localhost/pub/plugins?buffer_length=1',
|
||||
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
|
||||
CURLOPT_POST => 1,
|
||||
CURLOPT_RETURNTRANSFER => true
|
||||
]);
|
||||
foreach ($messages as $message) {
|
||||
curl_setopt($com, CURLOPT_POSTFIELDS, $message);
|
||||
curl_exec($com);
|
||||
}
|
||||
curl_close($com);
|
||||
} else {
|
||||
foreach ($messages as $message) echo $message;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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.
|
||||
//
|
||||
function download($url, $name, &$error) {
|
||||
$plg = basename($url);
|
||||
if ($file = popen("wget --compression=auto --no-cache --progress=dot -O $name $url 2>&1", '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) {
|
||||
write("language: downloading: $plg ... $percentage%\r");
|
||||
$level = $percentage;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (($perror = pclose($file)) == 0) {
|
||||
write("language: downloading: $plg ... done\n");
|
||||
return true;
|
||||
} else {
|
||||
$error = "$plg download failure (".error_desc($perror).")";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$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;
|
||||
if ($xml === false) {
|
||||
$error = "XML file doesn't exist or xml parse error";
|
||||
return false;
|
||||
}
|
||||
switch ($method) {
|
||||
case 'install':
|
||||
$url = $xml->LanguageURL;
|
||||
$name = $xml->LanguagePack;
|
||||
$save = "$boot/dynamix/lang-$name.zip";
|
||||
if (!file_exists($save)) {
|
||||
if ($url) {
|
||||
if (!download($url, $save, $error)) {
|
||||
@unlink($save);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$error = "missing URL";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$path = "$docroot/languages/$name";
|
||||
exec("mkdir -p $path");
|
||||
@unlink("$docroot/webGui/javascript/translate.$name.js");
|
||||
foreach (glob("$path/*.dot",GLOB_NOSORT) as $dot_file) unlink($dot_file);
|
||||
exec("unzip -qqLjo -d $path $save", $dummy, $err);
|
||||
if ($err > 1) {
|
||||
@unlink($save);
|
||||
exec("rm -rf $path");
|
||||
$error = "unzip failed. Error code $err";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case 'remove':
|
||||
$name = $xml->LanguagePack;
|
||||
if ($name) {
|
||||
$path = "$docroot/languages/$name";
|
||||
exec("rm -rf $path");
|
||||
@unlink("$docroot/webGui/javascript/translate.$name.js");
|
||||
@unlink("$boot/lang-$name.xml");
|
||||
@unlink("$plugins/lang-$name.xml");
|
||||
@unlink("$tmp/lang-$name.xml");
|
||||
@unlink("$boot/dynamix/lang-$name.zip");
|
||||
return true;
|
||||
} else {
|
||||
$error = "missing language pack";
|
||||
return false;
|
||||
}
|
||||
case 'dump':
|
||||
// dump file: debugging
|
||||
write(print_r($xml,true));
|
||||
return true;
|
||||
default:
|
||||
// return single attribute
|
||||
$error = "$method attribute not present";
|
||||
return $xml->$method ?: false;
|
||||
}
|
||||
}
|
||||
|
||||
$docroot = '/usr/local/emhttp';
|
||||
$boot = '/boot/config/plugins';
|
||||
$plugins = '/var/log/plugins';
|
||||
$tmp = '/tmp/plugins';
|
||||
$method = $argv[1];
|
||||
$nchan = $argv[$argc-1] == 'nchan'; // console or nchan output
|
||||
|
||||
// MAIN - single argument
|
||||
if ($argc < 2) {
|
||||
write($usage);
|
||||
done(1);
|
||||
}
|
||||
|
||||
// language checkall
|
||||
// check all installed languages
|
||||
//
|
||||
if ($method == 'checkall') {
|
||||
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;
|
||||
write("language: checking $lang language pack ...\n");
|
||||
exec(realpath($argv[0])." check $name >/dev/null");
|
||||
}
|
||||
write("language: checking finished.\n");
|
||||
done(0);
|
||||
}
|
||||
|
||||
// language updateall
|
||||
// update all installed languages
|
||||
//
|
||||
if ($method == 'updateall') {
|
||||
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;
|
||||
if (language('LanguageURL', $lang_file, $error) === false) continue;
|
||||
$version = language('Version', $lang_file, $error);
|
||||
$name = str_replace('lang-', '', basename($lang_file, '.xml'));
|
||||
$lang = language('Language', $lang_file, $error) ?: $name;
|
||||
$latest = language('Version', "$tmp/lang-$name.xml", $error);
|
||||
// update only when newer
|
||||
if (strcmp($latest, $version) > 0) {
|
||||
write("language: updating $lang language pack ...\n");
|
||||
exec(realpath($argv[0])." update $name >/dev/null");
|
||||
}
|
||||
}
|
||||
write("language: updating finished.\n");
|
||||
done(0);
|
||||
}
|
||||
|
||||
// MAIN - two arguments
|
||||
if ($argc < 3) {
|
||||
write($usage);
|
||||
done(1);
|
||||
}
|
||||
|
||||
// language install [language_file]
|
||||
//
|
||||
if ($method == 'install') {
|
||||
$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];
|
||||
$xml_file = "$tmp/$name";
|
||||
write("language: downloading: $name\n");
|
||||
if (!download($langURL, $xml_file, $error)) {
|
||||
write("language: $error\n");
|
||||
@unlink($xml_file);
|
||||
done(1);
|
||||
}
|
||||
} else {
|
||||
$xml_file = realpath($argv[2]);
|
||||
}
|
||||
$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);
|
||||
done(1);
|
||||
}
|
||||
$lang = language('Language', $xml_file, $error) ?: substr($name,0,-4);
|
||||
copy($xml_file, $lang_file);
|
||||
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(0);
|
||||
}
|
||||
|
||||
// language check [language]
|
||||
//
|
||||
if ($method == 'check') {
|
||||
$name = $argv[2];
|
||||
write("language: checking language pack\n");
|
||||
$link_file = "$plugins/lang-$name.xml";
|
||||
$lang_file = @readlink($link_file);
|
||||
if ($lang_file === false) {
|
||||
write("language: $name language pack not installed\n");
|
||||
done(1);
|
||||
}
|
||||
$templateURL = language('TemplateURL', $lang_file, $error);
|
||||
if ($templateURL === false) {
|
||||
write("language: $error\n");
|
||||
done(1);
|
||||
}
|
||||
$xml_file = "$tmp/lang-$name.xml";
|
||||
if (!download($templateURL, $xml_file, $error)) {
|
||||
write("language: $error\n");
|
||||
@unlink($xml_file);
|
||||
done(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);
|
||||
done(1);
|
||||
}
|
||||
write("$version\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks();
|
||||
done(0);
|
||||
}
|
||||
|
||||
// language update [language]
|
||||
//
|
||||
if ($method == 'update') {
|
||||
$name = $argv[2];
|
||||
write("language: updating language pack\n");
|
||||
$link_file = "$plugins/lang-$name.xml";
|
||||
$lang_file = @readlink($link_file);
|
||||
if ($lang_file === false) {
|
||||
write("language: $name language pack not installed\n");
|
||||
done(1);
|
||||
}
|
||||
// verify previous check has been done
|
||||
$xml_file = "$tmp/lang-$name.xml";
|
||||
if (!file_exists($xml_file)) {
|
||||
write("language: update does not exist, perform a check first\n");
|
||||
exit (1);
|
||||
}
|
||||
$lang = language('Language', $xml_file, $error) ?: $name;
|
||||
// check for a reinstall of same version
|
||||
$old_version = language('Version', $lang_file, $error);
|
||||
$new_version = language('Version', $xml_file, $error);
|
||||
if ($new_version == $old_version) {
|
||||
write("language: $lang language pack not reinstalling same version\n");
|
||||
done(1);
|
||||
}
|
||||
// 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);
|
||||
done(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(0);
|
||||
}
|
||||
|
||||
// language remove [language]
|
||||
//
|
||||
if ($method == 'remove') {
|
||||
$name = $argv[2];
|
||||
write("language: removing language pack: $name\n");
|
||||
$link_file = "$plugins/lang-$name.xml";
|
||||
$lang_file = @readlink($link_file);
|
||||
if ($lang_file === false) {
|
||||
write("language: $name language pack not installed\n");
|
||||
done(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);
|
||||
done(1);
|
||||
}
|
||||
write("language: $lang language pack removed\n");
|
||||
logger("language: $lang language pack removed");
|
||||
// run hook scripts for post processing
|
||||
post_hooks();
|
||||
done(0);
|
||||
}
|
||||
|
||||
// return attribute
|
||||
//
|
||||
$xml_file = $argv[2];
|
||||
$value = language($method, $xml_file, $error);
|
||||
if ($value === false) {
|
||||
write("language: $error\n");
|
||||
done(1);
|
||||
}
|
||||
write("$value\n");
|
||||
done(0);
|
||||
?>
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* 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/Wrappers.php";
|
||||
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
|
||||
extract(parse_plugin_cfg('dynamix', true));
|
||||
|
||||
// Multi-language support
|
||||
$_SERVER['REQUEST_URI'] = "scripts";
|
||||
$login_locale = _var($display,'locale');
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
|
||||
$var = @parse_ini_file('/var/local/emhttp/var.ini') ?: [];
|
||||
|
||||
function apos($text) {
|
||||
// So that "'" doesn't show up in email
|
||||
return str_replace("'","'",$text);
|
||||
}
|
||||
|
||||
$server = strtoupper($var['NAME']);
|
||||
$output = _var($notify,'language_notify');
|
||||
$script = "$docroot/webGui/scripts/notify";
|
||||
$tmp = '/tmp/plugins';
|
||||
$plugins = '/var/log/plugins';
|
||||
|
||||
language('checkall');
|
||||
foreach (glob("/$tmp/lang-*.xml", GLOB_NOSORT) as $file) {
|
||||
$name = basename($file);
|
||||
$lang = language('LanguageLocal', $file);
|
||||
$new = language('Version', $file);
|
||||
$old = language('Version', "$plugins/$name");
|
||||
|
||||
// silently suppress bad download of XML file
|
||||
if (strcmp($new, $old) > 0) {
|
||||
$event = apos(_("Language")." - $lang [$new]");
|
||||
$subject = apos(sprintf(_("Notice [%s] - Version update %s"),$server,$new));
|
||||
$description = apos(sprintf(_("A new version of %s is available"),$lang));
|
||||
exec("$script -e ".escapeshellarg($event)." -s ".escapeshellarg($subject)." -d ".escapeshellarg($description)." -i ".escapeshellarg("normal $output")." -l '/Apps' -x");
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
?>
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* 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]??'');
|
||||
$nchan = $argv[$argc-1] == 'nchan'; // console or nchan output
|
||||
$call = ['plg' => 'plugin', 'xml' => 'language', '' => 'language'];
|
||||
|
||||
function write(...$messages){
|
||||
global $nchan;
|
||||
if ($nchan) {
|
||||
$com = curl_init();
|
||||
curl_setopt_array($com,[
|
||||
CURLOPT_URL => 'http://localhost/pub/plugins?buffer_length=1',
|
||||
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
|
||||
CURLOPT_POST => 1,
|
||||
CURLOPT_RETURNTRANSFER => true
|
||||
]);
|
||||
foreach ($messages as $message) {
|
||||
curl_setopt($com, CURLOPT_POSTFIELDS, $message);
|
||||
curl_exec($com);
|
||||
}
|
||||
curl_close($com);
|
||||
} else {
|
||||
foreach ($messages as $message) echo $message;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($plugins as $plugin) {
|
||||
if (!$plugin || (!$cmd = $call[pathinfo($plugin,PATHINFO_EXTENSION)])) continue;
|
||||
$line = '';
|
||||
$pluginArg = $method == "update" ? basename($plugin) : $plugin;
|
||||
$run = popen("$cmd $method $pluginArg",'r');
|
||||
while (!feof($run)) {
|
||||
$line .= fgetc($run);
|
||||
if (in_array($line[-1],["\r","\n"])) {write($line); $line = '';}
|
||||
}
|
||||
pclose($run);
|
||||
write("\n");
|
||||
}
|
||||
if ($nchan) write('_DONE_','');
|
||||
?>
|
||||
+887
@@ -0,0 +1,887 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
// 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 plugin files.
|
||||
|
||||
Usage: plugin install PLUGIN-FILE [forced]
|
||||
install a plugin
|
||||
|
||||
PLUGIN-FILE is a plugin definition XML file with ".plg" extension.
|
||||
|
||||
PLUGIN-FILE can be a local file, or a URL. If a URL, the plugin file is first downloaded to /tmp/plugins.
|
||||
|
||||
forced is optional and can be used to install a lower version than currently running.
|
||||
|
||||
This command will process all FILE elements in PLUGIN-FILE which are tagged with the "install" method (or
|
||||
that have no method tag).
|
||||
|
||||
This command has two major use cases:
|
||||
|
||||
1) Invoked at system startup by /etc/rc.d/rc.local on each .plg file found int /boot/config/plugins.
|
||||
|
||||
Upon success we register the plugin as "installed" by creating a symlink to it in /var/log/plugins.
|
||||
|
||||
If any kind of error, we move the file to /boot/config/plugins-error.
|
||||
|
||||
If a symlink already exists for the plugin file, this indicates a plugin replacing a "built-in" plugin. In
|
||||
this case, if the version of PLUGIN-FILE is newer than the built-in plugin, we go ahead and install normally;
|
||||
otherwise, we move to /boot/config/plugins-stale.
|
||||
|
||||
2) Invoked manually or via Plugin Manager for a .plg file not in /boot/config/plugins.
|
||||
|
||||
If a symlink already exists for the plugin file, this indicates a plugin update. In this case, if the version of
|
||||
PLUGIN-FILE is newer than the built-in plugin, we go ahead and install normally and then move the old plugin
|
||||
to /boot/config/plugins-stale.
|
||||
|
||||
Upon success we copy PLUGIN-FILE to /boot/config/plugins and register it as "installed" by creating a
|
||||
symlink to it in /var/log/plugins.
|
||||
|
||||
Usage: plugin remove PLUGIN
|
||||
remove a plugin
|
||||
|
||||
PLUGIN is the file basename of a plugin, e.g., "myplugin.plg".
|
||||
|
||||
If PLUGIN is found in /var/log/plugins then this command will process all FILE elements in PLUGIN which are
|
||||
tagged with the "remove" method. Upon success we delete /var/log/plugins/PLUGIN and move the plugin
|
||||
file to /boot/config/plugins-removed
|
||||
|
||||
Usage: plugin check PLUGIN
|
||||
check and output the latest version of PLUGIN
|
||||
|
||||
We extract the pluginURL attribute from PLUGIN and use it to download (presumably the latest
|
||||
version of) the plugin file to /tmp/plugins/ directory, and then output the version string.
|
||||
|
||||
Usage: plugin checkall
|
||||
check all installed plugins
|
||||
|
||||
Runs 'plugin check PLUGIN' for each plugin file linked-to in /var/log/plugins.
|
||||
|
||||
Usage: plugin update PLUGIN
|
||||
update the plugin
|
||||
|
||||
We look for the new plugin in /tmp/plugins/ directory. If found then we first execute the "install"
|
||||
method of each FILE in the new plugin. (If necessary, a plugin can detect that this is an
|
||||
"update" by checking for the existence of /var/log/plugins/PLUGIN.) If successful, we
|
||||
delete the "old" plugin file from /boot/config/plugins/, copy the "new" plugin file from
|
||||
/tmp/plugins/ to /boot/config/plugins/, and finally create the new symlink.
|
||||
|
||||
Note: to support `plugin check` and `plugin update` the plugin file must contain both "pluginURL" and
|
||||
"version" attributes.
|
||||
|
||||
Usage: plugin [attribute name] PLUGIN-FILE
|
||||
|
||||
Any method which is not one of the actions listed above is assumed to be the name of an attribute of
|
||||
the <PLUGIN> tag within PLUGIN-FILE. If the attribute exists, its value (a string) is output and the command
|
||||
exit status is 0. If the attribute does not exist, command exit status is 1.
|
||||
|
||||
The plugin manager recognizes this set of attributes for the <PLUGIN> tag:
|
||||
|
||||
name - MANDATORY plugin name, e.g., "myplugin" or "my-plugin" etc.
|
||||
This tag defines the name of the plugin. The name should omit embedded information such as architecture,
|
||||
version, author, etc.
|
||||
|
||||
The plugin should create a directory under `/usr/local/emhttp/plugins` named after
|
||||
the plugin, e.g., `/usr/local/emhttp/plugins/myplugin`. Any webGui pages, icons, README files, etc, should
|
||||
be created inside this directory.
|
||||
|
||||
The plugin should also create a directory under `/boot/config/plugins` named after the plugin, e.g.,
|
||||
`/boot/config/plugins/myplugin`. Here is where you store plugin-specific files such as a configuration
|
||||
file and icon file. Note that this directory exists on the users USB Flash device and writes should be
|
||||
minimized.
|
||||
|
||||
Upon successful installation, the plugin manager will copy the input plugin file to `/boot/config/plugins`
|
||||
on the users USB Flash device, and create a symlink in `/var/log/plugins` also named after the plugin,
|
||||
e.g., `/var/log/plugins/myplugin`. Each time the unRaid server is re-booted, all plugins stored
|
||||
in `/boot/config/plugins` are automatically installed; plugin authors should be aware of this behavior.
|
||||
|
||||
author - OPTIONAL
|
||||
Whatever you put here will show up under the **Author** column in the Plugin List. If this attribute
|
||||
is omitted we display "anonymous".
|
||||
|
||||
version - MANDATORY
|
||||
Use a string suitable for comparison to determine if one version is older/same/newer than another version.
|
||||
Any format is acceptable but LimeTech uses "YYYY.MM.DD", e.g., "2014.02.18" (if multiple versions happen
|
||||
to get posted on the same day we add a letter suffix, e.g., "2014.02.18a").
|
||||
|
||||
pluginURL - OPTIONAL but MANDATORY if you want "check for updates" to work with your plugin
|
||||
This is the URL of the plugin file to download and extract the **version** attribute from to determine if
|
||||
this is a new version.
|
||||
|
||||
More attributes may be defined in the future.
|
||||
|
||||
Here is the set of directories and files used by the plugin system:
|
||||
|
||||
/boot/config/plugins/
|
||||
This directory contains the plugin files for plugins to be (re)installed at boot-time. Upon
|
||||
successful `plugin install`, the plugin file is copied here (if not here already). Upon successful
|
||||
`plugin remove`, the plugin file is deleted from here.
|
||||
|
||||
/boot/config/plugins-error/
|
||||
This directory contains plugin files that failed to install.
|
||||
|
||||
/boot/config/plugins-removed/
|
||||
This directory contains plugin files that have been removed.
|
||||
|
||||
/boot/config/plugins-stale/
|
||||
This directory contains plugin files that failed to install because a newer version of the same plugin is
|
||||
already installed.
|
||||
|
||||
/tmp/plugins/
|
||||
This directory is used as a target for downloaded plugin files. The `plugin check` operation
|
||||
downloads the plugin file here and the `plugin update` operation looks for the plugin to update here.
|
||||
|
||||
/var/log/plugins/
|
||||
This directory contains a symlink named after the plugin name (not the plugin file name) which points to
|
||||
the actual plugin file used to install the plugin. The existence of this file indicates successful
|
||||
install of the plugin.
|
||||
|
||||
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';
|
||||
case -1: return 'Generic error';
|
||||
case 1: return 'Generic error';
|
||||
case 2: return 'Parse error';
|
||||
case 3: return 'File I/O error';
|
||||
case 4: return 'Network failure';
|
||||
case 5: return 'SSL verification failure';
|
||||
case 6: return 'Username/password authentication failure';
|
||||
case 7: return 'Protocol errors';
|
||||
case 8: return 'Invalid URL / Server error response';
|
||||
default: return 'Error code '.$code;
|
||||
}
|
||||
}
|
||||
|
||||
// Signal DONE to caller
|
||||
//
|
||||
function done($code) {
|
||||
global $nchan;
|
||||
if ($nchan) write('_DONE_','');
|
||||
exit($code);
|
||||
}
|
||||
|
||||
// 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(...$messages){
|
||||
global $nchan;
|
||||
if ($nchan) {
|
||||
$com = curl_init();
|
||||
curl_setopt_array($com,[
|
||||
CURLOPT_URL => 'http://localhost/pub/plugins?buffer_length=1',
|
||||
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
|
||||
CURLOPT_POST => 1,
|
||||
CURLOPT_RETURNTRANSFER => true
|
||||
]);
|
||||
foreach ($messages as $message) {
|
||||
curl_setopt($com, CURLOPT_POSTFIELDS, $message);
|
||||
curl_exec($com);
|
||||
}
|
||||
curl_close($com);
|
||||
} else {
|
||||
foreach ($messages as $message) echo $message;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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 plugin $method $plugin");
|
||||
}
|
||||
}
|
||||
|
||||
// Run hooked scripts after successful or failed completion of "method"
|
||||
// method = install, update, remove, check
|
||||
// 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 plugin $method $plugin $error");
|
||||
}
|
||||
}
|
||||
|
||||
// Download a file from a URL.
|
||||
// Returns TRUE if success else FALSE and fills in error.
|
||||
//
|
||||
function download($url, $name, &$error, $write=true) {
|
||||
if ($url) {
|
||||
$plg = basename($url);
|
||||
$plg = str_replace('"', '', $plg);
|
||||
$tries = (strpos($url, '.cdn') !== false) ? "1" : "3";
|
||||
if ($file = popen("wget --compression=auto --no-cache --progress=dot --retry-connrefused --prefer-family=IPv4 --timeout=10 --tries=$tries --waitretry=$tries -O $name $url 2>&1", 'r')) {
|
||||
if ($write) write("plugin: downloading: $plg ...\r");
|
||||
$level = -1;
|
||||
while (($line = fgets($file)) !== false) {
|
||||
if (preg_match('/ \d+% /', $line, $matches)) {
|
||||
$percentage = substr(trim($matches[0]),0,-1);
|
||||
if ($percentage > $level) {
|
||||
if ($write) write("plugin: downloading: $plg ... $percentage%\r");
|
||||
$level = $percentage;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (($perror = pclose($file)) != 0) {
|
||||
$error = "$plg download failure: ".error_desc($perror);
|
||||
return false;
|
||||
} elseif (filesize($name) == 0) {
|
||||
if ($write) write("plugin: download failure: zero-length file\r","\n");
|
||||
return false;
|
||||
} else {
|
||||
if ($write) write("plugin: downloading: $plg ... done\r","\n");
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
$error = "$plg failed to open";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// The url is empty
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filter URL.
|
||||
// If URL contains '.cdn' remove the '.cdn' from the URL.
|
||||
// Returns URL without '.cdn' if found.
|
||||
//
|
||||
function filter_url($url) {
|
||||
if (strpos($url, '.cdn') !== false) {
|
||||
$new_url = str_replace('"', '', $url);
|
||||
$new_url = str_replace('.cdn', '', $new_url);
|
||||
} else {
|
||||
$new_url = "";
|
||||
}
|
||||
return($new_url);
|
||||
}
|
||||
|
||||
// Deal with logging message.
|
||||
//
|
||||
function logger($message) {
|
||||
shell_exec("logger $message");
|
||||
}
|
||||
|
||||
// Interpret a plugin file
|
||||
// Returns TRUE if success, else FALSE and fills in error string.
|
||||
//
|
||||
// If a FILE element does not have a Method attribute, we treat as though Method is "install".
|
||||
// A FILE Method attribute can list multiple methods separated by spaces in which case that file
|
||||
// is processed for any of those methods.
|
||||
//
|
||||
function plugin($method, $plugin_file, &$error) {
|
||||
global $unraid;
|
||||
$methods = ['install', 'remove'];
|
||||
|
||||
// parse plugin definition XML file
|
||||
$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;
|
||||
}
|
||||
|
||||
// dump
|
||||
if ($method == 'dump') {
|
||||
// dump file: debugging
|
||||
write(print_r($xml,true));
|
||||
return true;
|
||||
}
|
||||
|
||||
// release notes
|
||||
if ($method == 'changes') {
|
||||
return $xml->CHANGES ? trim($xml->CHANGES) : false;
|
||||
}
|
||||
|
||||
// alert message
|
||||
if ($method == '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) {
|
||||
if (!$file->SHA256 and !$file->MD5) continue;
|
||||
if ( (download($file->URL, $name, $error, false) === false) && (download(filter_url($file->URL), $name, $error, false) === false) ) {
|
||||
@unlink($name);
|
||||
return false;
|
||||
}
|
||||
if (($file->SHA256 && hash_file('sha256',$name) != $file->SHA256) or ($file->MD5 && md5_file($name) != $file->MD5)) {
|
||||
$error = "bad hash value";
|
||||
@unlink($name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@unlink($name);
|
||||
return "valid";
|
||||
}
|
||||
|
||||
// check if $method is an attribute
|
||||
if (!in_array($method, $methods)) {
|
||||
foreach ($xml->attributes() as $key => $value) {
|
||||
if ($method == $key) return $value;
|
||||
}
|
||||
$error = "$method attribute not present";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process FILE elements in order
|
||||
//
|
||||
foreach ($xml->FILE as $file) {
|
||||
// skip if not our $method
|
||||
if (isset($file->attributes()->Method)) {
|
||||
if (!in_array($method, explode(" ", $file->attributes()->Method))) continue;
|
||||
} elseif ($method != 'install') continue;
|
||||
$name = $file->attributes()->Name;
|
||||
// bergware - check Unraid version dependency (if present)
|
||||
$min = $file->attributes()->Min;
|
||||
if ($min && version_compare($unraid['version'],$min,'<')) {
|
||||
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,'>')) {
|
||||
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
|
||||
if ($name) {
|
||||
// Ensure parent directory exists
|
||||
//
|
||||
if (!file_exists(dirname($name))) {
|
||||
if (!mkdir(dirname($name), 0770, true)) {
|
||||
$error = "unable to create parent directory for $name";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// If file already exists, check the SHA256/MD5 (if supplied)
|
||||
if (file_exists($name)) {
|
||||
if ($file->SHA256) {
|
||||
logger("plugin: checking: $name - SHA256");
|
||||
if (hash_file('sha256', $name) != $file->SHA256) {
|
||||
unlink($name);
|
||||
}
|
||||
} elseif ($file->MD5) {
|
||||
logger("plugin: checking: $name - MD5");
|
||||
if (md5_file($name) != $file->MD5) {
|
||||
unlink($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If file already exists, do not overwrite
|
||||
//
|
||||
if (file_exists($name)) {
|
||||
logger("plugin: skipping: $name already exists");
|
||||
} elseif ($file->LOCAL) {
|
||||
// Create the file
|
||||
//
|
||||
// for local file, just copy it
|
||||
logger("plugin: creating: $name - copying LOCAL file $file->LOCAL");
|
||||
if (!copy($file->LOCAL, $name)) {
|
||||
$error = "unable to copy LOCAL file: $name";
|
||||
@unlink($name);
|
||||
return false;
|
||||
}
|
||||
} elseif ($file->INLINE) {
|
||||
// for inline file, create with inline contents
|
||||
logger("plugin: creating: $name - from INLINE content");
|
||||
$contents = trim($file->INLINE).PHP_EOL;
|
||||
if ($file->attributes()->Type == 'base64') {
|
||||
logger("plugin: decoding: $name as base64");
|
||||
$contents = base64_decode($contents);
|
||||
if ($contents === false) {
|
||||
$error = "unable to decode inline base64: $name";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!file_put_contents($name, $contents)) {
|
||||
$error = "unable to create file: $name";
|
||||
@unlink($name);
|
||||
return false;
|
||||
}
|
||||
} elseif ($file->URL) {
|
||||
// for download file, download and maybe verify the file MD5
|
||||
logger("plugin: creating: $name - downloading from URL $file->URL");
|
||||
if ( (download($file->URL, $name, $error) === false) && (download(filter_url($file->URL), $name, $error) === false) ) {
|
||||
@unlink($name);
|
||||
return false;
|
||||
}
|
||||
if ($file->SHA256) {
|
||||
logger("plugin: checking: $name - SHA256");
|
||||
if (hash_file('sha256', $name) != $file->SHA256) {
|
||||
$error = "bad file SHA256: $name";
|
||||
unlink($name);
|
||||
return false;
|
||||
}
|
||||
} elseif ($file->MD5) {
|
||||
logger("plugin: checking: $name - MD5");
|
||||
if (md5_file($name) != $file->MD5) {
|
||||
$error = "bad file MD5: $name";
|
||||
unlink($name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Maybe change the file mode
|
||||
//
|
||||
if ($file->attributes()->Mode) {
|
||||
// if file has 'Mode' attribute, apply it
|
||||
$mode = $file->attributes()->Mode;
|
||||
logger("plugin: setting: $name - mode to $mode");
|
||||
if (!chmod($name, octdec($mode))) {
|
||||
$error = "chmod failure: $name";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Maybe "run" the file now
|
||||
//
|
||||
if ($file->attributes()->Run) {
|
||||
$command = $file->attributes()->Run;
|
||||
if ($name) {
|
||||
logger(escapeshellarg("plugin: running: $command $name"));
|
||||
$retval = run("$command $name");
|
||||
} elseif ($file->LOCAL) {
|
||||
logger(escapeshellarg("plugin: running: $command $file->LOCAL"));
|
||||
$retval = run("$command $file->LOCAL");
|
||||
} elseif ($file->INLINE) {
|
||||
logger("plugin: running: 'anonymous'");
|
||||
$name = '/tmp/inline.sh';
|
||||
file_put_contents($name, $file->INLINE);
|
||||
$retval = run("$command $name");
|
||||
unlink($name);
|
||||
}
|
||||
if ($retval != 0) {
|
||||
$error = "run failed: '$command' returned $retval";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function move($src_file, $tar_dir) {
|
||||
@mkdir($tar_dir);
|
||||
return rename($src_file, $tar_dir."/".basename($src_file));
|
||||
}
|
||||
|
||||
$notify = '/usr/local/emhttp/webGui/scripts/notify';
|
||||
$boot = '/boot/config/plugins';
|
||||
$plugins = '/var/log/plugins';
|
||||
$tmp = '/tmp/plugins';
|
||||
$method = $argv[1];
|
||||
$builtin = ['unRAIDServer','unRAIDServer-'];
|
||||
$nchan = $argv[$argc-1] == 'nchan'; // console or nchan output
|
||||
|
||||
// In following code,
|
||||
// $plugin - is a basename of a plugin, eg, "myplugin.plg"
|
||||
// $plugin_file - is an absolute path, eg, "/boot/config/plugins/myplugin.plg"
|
||||
//
|
||||
// MAIN - single argument
|
||||
if ($argc < 2) {
|
||||
write($usage);
|
||||
done(1);
|
||||
}
|
||||
|
||||
// plugin checkall
|
||||
// check all installed plugins, except built-in
|
||||
//
|
||||
if ($method == 'checkall') {
|
||||
if (!$cmd = realpath($argv[0])) {
|
||||
write("Unknown command: {$argv[0]}\n");
|
||||
done(1);
|
||||
}
|
||||
foreach (glob("$plugins/*.plg", GLOB_NOSORT) as $link) {
|
||||
// skip OS related plugins
|
||||
if (in_array(basename($link,'.plg'),$builtin)) continue;
|
||||
// only consider symlinks
|
||||
$installed_plugin_file = @readlink($link);
|
||||
if ($installed_plugin_file === false) continue;
|
||||
if (plugin('pluginURL', $installed_plugin_file, $error) === false) continue;
|
||||
$plugin = basename($installed_plugin_file);
|
||||
write("plugin: checking $plugin ...\n");
|
||||
exec("$cmd check $plugin >/dev/null");
|
||||
}
|
||||
write("plugin: checking finished.\n");
|
||||
done(0);
|
||||
}
|
||||
|
||||
// plugin updateall
|
||||
// update all installed plugins, which have a update available
|
||||
//
|
||||
if ($method == 'updateall') {
|
||||
if (!$cmd = realpath($argv[0])) {
|
||||
write("Unknown command: {$argv[0]}\n");
|
||||
done(1);
|
||||
}
|
||||
foreach (glob("$plugins/*.plg", GLOB_NOSORT) as $link) {
|
||||
// skip OS related plugins
|
||||
if (in_array(basename($link,'.plg'),$builtin)) continue;
|
||||
// only consider symlinks
|
||||
$installed_plugin_file = @readlink($link);
|
||||
if ($installed_plugin_file === false) continue;
|
||||
if (plugin('pluginURL', $installed_plugin_file, $error) === false) continue;
|
||||
$version = plugin('version', $installed_plugin_file, $error);
|
||||
$plugin = basename($installed_plugin_file);
|
||||
$latest = plugin('version', "$tmp/$plugin", $error);
|
||||
// update only when newer
|
||||
if (strcmp($latest,$version) > 0) {
|
||||
write("plugin: updating $plugin ...\n");
|
||||
exec("$cmd update $plugin >/dev/null");
|
||||
}
|
||||
}
|
||||
write("plugin: updating finished.\n");
|
||||
done(0);
|
||||
}
|
||||
|
||||
// plugin checkos
|
||||
// check built-in only
|
||||
//
|
||||
if ($method == 'checkos') {
|
||||
if (!$cmd = realpath($argv[0])) {
|
||||
write("Unknown command: {$argv[0]}\n");
|
||||
done(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);
|
||||
write("plugin: checking $plugin ...\n");
|
||||
exec("$cmd check $plugin >/dev/null");
|
||||
}
|
||||
write("plugin: checking finished.\n");
|
||||
done(0);
|
||||
}
|
||||
|
||||
// MAIN - two or three arguments
|
||||
if ($argc < 3) {
|
||||
write($usage);
|
||||
done(1);
|
||||
}
|
||||
|
||||
// plugin install [plugin_file]
|
||||
// cases:
|
||||
// a) dirname of [plugin_file] is /boot/config/plugins (system startup)
|
||||
// b) [plugin_file] is a URL
|
||||
// c) dirname of [plugin_file] is not /boot/config/plugins
|
||||
//
|
||||
$unraid = parse_ini_file('/etc/unraid-version');
|
||||
if ($method == 'install') {
|
||||
$argv[2] = preg_replace('#[\x00-\x1F\x80-\xFF]#', '', $argv[2]);
|
||||
$plugin = basename($argv[2]);
|
||||
if (pathinfo($plugin, PATHINFO_EXTENSION) != "plg") {
|
||||
write("plugin: $plugin is not a plg file\n");
|
||||
done(1);
|
||||
}
|
||||
write("plugin: installing: $plugin\n");
|
||||
// check for URL
|
||||
if (preg_match('#^https?://#',$argv[2])) {
|
||||
$pluginURL = $argv[2];
|
||||
// run hook scripts for pre processing
|
||||
pre_hooks();
|
||||
$plugin_file = "$tmp/$plugin";
|
||||
write("plugin: downloading: $plugin\n");
|
||||
if ( (download($pluginURL, $plugin_file, $error) === false) && (download(filter_url($pluginURL), $plugin_file, $error) === false) ) {
|
||||
write("plugin: $error\n");
|
||||
@unlink($plugin_file);
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
} 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, '<')) {
|
||||
write("plugin: installed Unraid version is too low, require at least version $min\n");
|
||||
if (dirname($plugin_file) == "$boot") {
|
||||
move($plugin_file, "$boot-error");
|
||||
}
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
$max = plugin('max', $plugin_file, $error) ?: plugin('Unraid', $plugin_file, $error);
|
||||
if ($max && version_compare($unraid['version'], $max, '>')) {
|
||||
write("plugin: installed Unraid version is too high, require at most version $max\n");
|
||||
if (dirname($plugin_file) == "$boot") {
|
||||
move($plugin_file, "$boot-error");
|
||||
}
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
$symlink = "$plugins/$plugin";
|
||||
// check for re-install
|
||||
$installed_plugin_file = @readlink($symlink);
|
||||
if ($installed_plugin_file !== false) {
|
||||
if ($plugin_file == $installed_plugin_file) {
|
||||
write("plugin: not re-installing same plugin\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
// must have version attributes for re-install
|
||||
$version = plugin('version', $plugin_file, $error);
|
||||
if ($version === false) {
|
||||
write("plugin: $error\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
$installed_version = plugin('version', $installed_plugin_file, $error);
|
||||
if ($installed_version === false) {
|
||||
write("plugin: $error\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
// check version installation?
|
||||
$forced = $nchan ? ($argc==5 ? $argv[4] : false) : ($argc==4 ? $argv[3] : false);
|
||||
if (!$forced) {
|
||||
// do not re-install if same plugin already installed or has higher version
|
||||
if (strcmp($version, $installed_version) < 0) {
|
||||
write("plugin: not installing older version\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
if (strcmp($version, $installed_version) === 0) {
|
||||
write("plugin: not reinstalling same version\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
}
|
||||
// run hook scripts for pre processing
|
||||
pre_hooks();
|
||||
if (plugin('install', $plugin_file, $error) === false) {
|
||||
write("plugin: $error\n");
|
||||
if (dirname($plugin_file) == "$boot") {
|
||||
move($plugin_file, "$boot-error");
|
||||
}
|
||||
$event = "Install error";
|
||||
$subject = "plugin: ".basename($plugin_file);
|
||||
$description = "Plugin failed to install";
|
||||
exec("$notify -e $event -s $subject -d $description) -i 2");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
// 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) {
|
||||
write("plugin: $error\n");
|
||||
if (dirname($plugin_file) == "$boot") {
|
||||
move($plugin_file, "$boot-error");
|
||||
}
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
}
|
||||
// register successful install
|
||||
$target = "$boot/$plugin";
|
||||
if (!plugin('noInstall', $plugin_file, $error)) {
|
||||
if ($target != $plugin_file) copy($plugin_file, $target);
|
||||
symlink($target, $symlink);
|
||||
write("plugin: $plugin installed\n");
|
||||
logger("plugin: $plugin installed");
|
||||
} else {
|
||||
write("script: $plugin executed\n");
|
||||
logger("script: $plugin executed");
|
||||
}
|
||||
// run hook scripts for post processing
|
||||
post_hooks();
|
||||
done(0);
|
||||
}
|
||||
|
||||
// plugin check [plugin]
|
||||
// We use the pluginURL attribute to download the latest plg file into the "/tmp/plugins/"
|
||||
// directory.
|
||||
//
|
||||
if ($method == 'check') {
|
||||
$plugin = $argv[2];
|
||||
$symlink = "$plugins/$plugin";
|
||||
write("plugin: checking: $plugin ...\n");
|
||||
$installed_plugin_file = @readlink($symlink);
|
||||
if ($installed_plugin_file === false) {
|
||||
write("plugin: not installed\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
$installed_pluginURL = plugin('pluginURL', $installed_plugin_file, $error);
|
||||
if ($installed_pluginURL === false) {
|
||||
write("plugin: $error\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
$plugin_file = "$tmp/$plugin";
|
||||
if ( (download($installed_pluginURL, $plugin_file, $error) === false) && (download(filter_url($installed_pluginURL), $plugin_file, $error) === false) ) {
|
||||
write("plugin: $error\n");
|
||||
@unlink($plugin_file);
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
// run hook scripts for pre processing
|
||||
pre_hooks();
|
||||
$version = plugin('version', $plugin_file, $error);
|
||||
if ($version === false) {
|
||||
write("plugin: $error\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
write("$version\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks();
|
||||
done(0);
|
||||
}
|
||||
|
||||
// plugin update [plugin]
|
||||
// [plugin] is the plg file we are going to be replacing, eg, "old.plg".
|
||||
// We assume a "check" has already been done, ie, "/tmp/plugins/new.plg" already exists.
|
||||
// We execute the "install" method of new.plg. If this fails, then we mark old.plg "not installed";
|
||||
// the plugin manager will recognize this as an install error.
|
||||
// If install new.plg succeeds, then we remove old.plg and copy new.plg in place.
|
||||
// Finally we mark the new.plg "installed".
|
||||
//
|
||||
if ($method == 'update') {
|
||||
$plugin = $argv[2];
|
||||
$symlink = "$plugins/$plugin";
|
||||
write("plugin: updating: $plugin\n");
|
||||
$installed_plugin_file = @readlink($symlink);
|
||||
if ($installed_plugin_file === false) {
|
||||
write("plugin: $plugin not installed\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
// verify previous check has been done
|
||||
$plugin_file = "$tmp/$plugin";
|
||||
if (!file_exists($plugin_file)) {
|
||||
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, '<')) {
|
||||
write("plugin: installed Unraid version is too low, require at least version $min\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
$max = plugin('max', $plugin_file, $error) ?: plugin('Unraid', $plugin_file, $error);
|
||||
if ($max && version_compare($unraid['version'], $max, '>')) {
|
||||
write("plugin: installed Unraid version is too high, require at most version $max\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
// check for a reinstall of same version
|
||||
if (strcmp(plugin('version', $installed_plugin_file, $error), plugin('version', $plugin_file, $error)) === 0) {
|
||||
write("Not reinstalling same version\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
// run hook scripts for pre processing
|
||||
pre_hooks();
|
||||
// install the updated plugin
|
||||
if (plugin('install', $plugin_file, $error) === false) {
|
||||
write("plugin: $error\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
// install was successful, save the updated plugin so it installs again next boot
|
||||
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();
|
||||
done(0);
|
||||
}
|
||||
|
||||
// plugin remove [plugin]
|
||||
// only .plg files should have a remove method
|
||||
//
|
||||
if ($method == 'remove') {
|
||||
$plugin = $argv[2];
|
||||
$symlink = "$plugins/$plugin";
|
||||
write("plugin: removing: $plugin\n");
|
||||
$installed_plugin_file = @readlink($symlink);
|
||||
if ($installed_plugin_file !== false) {
|
||||
// remove the symlink
|
||||
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
|
||||
if (is_file($installed_plugin_file)) symlink($installed_plugin_file, $symlink);
|
||||
write("plugin: $error\n");
|
||||
// run hook scripts for post processing
|
||||
post_hooks($error);
|
||||
done(1);
|
||||
}
|
||||
}
|
||||
// remove the plugin file
|
||||
move($installed_plugin_file, "$boot-removed");
|
||||
write("plugin: $plugin removed\n");
|
||||
logger("plugin: $plugin removed");
|
||||
exec("/usr/local/sbin/update_cron");
|
||||
// run hook scripts for post processing
|
||||
post_hooks();
|
||||
done(0);
|
||||
}
|
||||
|
||||
// return attribute
|
||||
//
|
||||
$plugin_file = $argv[2];
|
||||
$value = plugin($method, $plugin_file, $error);
|
||||
if ($value === false) {
|
||||
write("plugin: $error\n");
|
||||
done(1);
|
||||
}
|
||||
write("$value\n");
|
||||
done(0);
|
||||
?>
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
write(){
|
||||
for message in "$@"; do
|
||||
curl -sfd "$message" --unix-socket /var/run/nginx.socket http://localhost/pub/plugins?buffer_length=1 >/dev/null 2>&1
|
||||
done
|
||||
}
|
||||
|
||||
# put some restrictions on 'delete'
|
||||
if [[ $1 == /boot/config/plugins-error/* || $1 == /boot/config/plugins-stale/* ]]; then
|
||||
text="Deleting $1 ..."
|
||||
if [[ -z $2 ]]; then
|
||||
echo "$text"
|
||||
else
|
||||
write "$text " "_DONE_" ""
|
||||
fi
|
||||
rm $1
|
||||
fi
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* 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/Wrappers.php";
|
||||
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
|
||||
|
||||
extract(parse_plugin_cfg('dynamix',true));
|
||||
|
||||
// Multi-language support
|
||||
$_SERVER['REQUEST_URI'] = "scripts";
|
||||
$login_locale = _var($display,'locale');
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
|
||||
$var = @parse_ini_file('/var/local/emhttp/var.ini') ?: [];
|
||||
|
||||
function apos($text) {
|
||||
// So that "'" doesn't show up in email
|
||||
return str_replace("'","'",$text);
|
||||
}
|
||||
|
||||
$current = parse_ini_file('/etc/unraid-version');
|
||||
$server = strtoupper(_var($var,'NAME','tower'));
|
||||
$output = _var($notify,'plugin');
|
||||
$builtin = ['unRAIDServer','unRAIDServer-'];
|
||||
$script = "$docroot/webGui/scripts/notify";
|
||||
$tmp = '/tmp/plugins';
|
||||
$plugins = '/var/log/plugins';
|
||||
|
||||
plugin('checkall');
|
||||
foreach (glob("/$tmp/*.plg", GLOB_NOSORT) as $file) {
|
||||
$name = basename($file,'.plg');
|
||||
// skip OS related updates
|
||||
if (in_array($name,$builtin)) continue;
|
||||
$new = plugin('version', $file);
|
||||
$old = plugin('version', "$plugins/$name.plg");
|
||||
$min = plugin('min', $file) ?: $current['version'];
|
||||
// silently suppress bad download of PLG file
|
||||
if (strcmp($new, $old)>0 && !version_compare($min,$current['version'],">")) {
|
||||
$event = apos(_("Plugin")." - $name [$new]");
|
||||
$subject = apos(sprintf(_("Notice [%s] - Version update %s"),$server,$new));
|
||||
$description = apos(sprintf(_("A new version of %s is available"),$name));
|
||||
exec("$script -e ".escapeshellarg($event)." -s ".escapeshellarg($subject)." -d ".escapeshellarg($description)." -i ".escapeshellarg("normal $output")." -l '/Plugins' -x");
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
?>
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* 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/Wrappers.php";
|
||||
extract(parse_plugin_cfg('dynamix',true));
|
||||
|
||||
// add translations
|
||||
$_SERVER['REQUEST_URI'] = 'plugins';
|
||||
$login_locale = _var($display,'locale');
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
|
||||
$file = realpath($argv[1]??'');
|
||||
$valid = ['/var/tmp/','/tmp/plugins/'];
|
||||
$good = false;
|
||||
|
||||
foreach ($valid as $check) if (strncmp($file,$check,strlen($check))===0) $good = true;
|
||||
if ($file && $good && pathinfo($file)['extension']=='txt') {
|
||||
echo Markdown(file_get_contents($file));
|
||||
} else {
|
||||
echo Markdown("*"._('No release notes available')."!*");
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* 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/Wrappers.php";
|
||||
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
|
||||
|
||||
// Multi-language support
|
||||
if (!function_exists('_')) {
|
||||
function _($text) {return $text;}
|
||||
}
|
||||
|
||||
extract(parse_plugin_cfg('dynamix', true));
|
||||
|
||||
$var = @parse_ini_file('/var/local/emhttp/var.ini') ?: [];
|
||||
$script = "$docroot/webGui/scripts/notify";
|
||||
$server = strtoupper(_var($var,'NAME','server'));
|
||||
$output = _var($notify,'plugin');
|
||||
$builtin = ['unRAIDServer'];
|
||||
|
||||
foreach ($builtin as $name) {
|
||||
$plg = "$name.plg";
|
||||
plugin('check',$plg);
|
||||
$file = "/tmp/plugins/$plg";
|
||||
$old = plugin('version', "/var/log/plugins/$plg");
|
||||
$new = plugin('version', $file);
|
||||
|
||||
// silently suppress bad download of PLG file
|
||||
if (version_compare($new,$old,'>')) {
|
||||
exec("$script -e ".escapeshellarg("System - $name [$new]")." -s ".escapeshellarg("Notice [$server] - Version update $new")." -d ".escapeshellarg("A new version of $name is available")." -i ".escapeshellarg("normal $output")." -l '/Tools/Update' -x");
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
?>
|
||||
Reference in New Issue
Block a user