mirror of
https://github.com/unraid/webgui.git
synced 2025-12-31 14:40:36 -06:00
433 lines
12 KiB
PHP
Executable File
433 lines
12 KiB
PHP
Executable File
#!/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)
|
|
|
|
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
|
require_once "$docroot/webGui/include/Wrappers.php";
|
|
require_once "$docroot/webGui/include/publish.php";
|
|
$logger = 'language-manager';
|
|
|
|
$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) {
|
|
foreach ($messages as $message) {
|
|
publish('plugins', $message,1,false);
|
|
}
|
|
} 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;
|
|
}
|
|
}
|
|
|
|
// 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");
|
|
my_logger("$lang language pack installed", $logger);
|
|
// 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");
|
|
my_logger("$lang language pack updated", $logger);
|
|
// 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");
|
|
my_logger("$lang language pack removed", $logger);
|
|
// 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);
|
|
?>
|