From b5794e463f6e04a3941f4db54529328bcc3f2c34 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Sun, 24 Apr 2022 11:08:09 +0200 Subject: [PATCH] add icon to display detailed commands/file-contents from config-templates in admin_configfiles Signed-off-by: Michael Kaufmann --- admin_configfiles.php | 22 +- lib/Froxlor/Ajax/Ajax.php | 46 +++- lib/Froxlor/Config/ConfigDisplay.php | 224 ++++++++++++++++++ lib/Froxlor/Config/ConfigParser.php | 26 +- .../Froxlor/settings/conf/command.html.twig | 1 + .../Froxlor/settings/conf/file.html.twig | 2 + .../Froxlor/settings/conf/fileblock.html.twig | 6 + 7 files changed, 300 insertions(+), 27 deletions(-) create mode 100644 lib/Froxlor/Config/ConfigDisplay.php create mode 100644 templates/Froxlor/settings/conf/command.html.twig create mode 100644 templates/Froxlor/settings/conf/file.html.twig create mode 100644 templates/Froxlor/settings/conf/fileblock.html.twig diff --git a/admin_configfiles.php b/admin_configfiles.php index a72fa7c2..aea631b8 100644 --- a/admin_configfiles.php +++ b/admin_configfiles.php @@ -47,7 +47,7 @@ if ($userinfo['change_serversettings'] == '1') { $configfiles = new \Froxlor\Config\ConfigParser($config_dir . '/' . $distribution . ".xml"); // get distro-info - $dist_display = getCompleteDistroName($configfiles); + $dist_display = $configfiles->getCompleteDistroName(); // get all the services from the distro $services = $configfiles->getServices(); @@ -59,10 +59,8 @@ if ($userinfo['change_serversettings'] == '1') { foreach ($distros as $_distribution) { // get configparser object $dist = new \Froxlor\Config\ConfigParser($_distribution); - // get distro-info - $dist_display = getCompleteDistroName($dist); // store in tmp array - $distributions_select[str_replace(".xml", "", strtolower(basename($_distribution)))] = $dist_display; + $distributions_select[str_replace(".xml", "", strtolower(basename($_distribution)))] = $dist->getCompleteDistroName(); } // sort by distribution name @@ -149,19 +147,3 @@ if ($userinfo['change_serversettings'] == '1') { } else { \Froxlor\UI\Response::redirectTo('admin_index.php'); } - -function getCompleteDistroName($cparser) -{ - // get distro-info - $dist_display = $cparser->distributionName; - if ($cparser->distributionCodename != '') { - $dist_display .= " " . $cparser->distributionCodename; - } - if ($cparser->distributionVersion != '') { - $dist_display .= " (" . $cparser->distributionVersion . ")"; - } - if ($cparser->deprecated) { - $dist_display .= " [deprecated]"; - } - return $dist_display; -} diff --git a/lib/Froxlor/Ajax/Ajax.php b/lib/Froxlor/Ajax/Ajax.php index 4c8e0b19..e0d8cc3e 100644 --- a/lib/Froxlor/Ajax/Ajax.php +++ b/lib/Froxlor/Ajax/Ajax.php @@ -3,6 +3,8 @@ namespace Froxlor\Ajax; use Exception; +use Froxlor\Froxlor; +use Froxlor\FileDir; use Froxlor\Database\Database; use Froxlor\Http\HttpClient; use Froxlor\Validate\Validate; @@ -10,6 +12,8 @@ use Froxlor\Settings; use Froxlor\UI\Listing; use Froxlor\UI\Panel\UI; use Froxlor\UI\Request; +use Froxlor\Config\ConfigParser; +use Froxlor\Config\ConfigDisplay; /** * This file is part of the Froxlor project. @@ -320,14 +324,46 @@ class Ajax return $this->jsonResponse(['allowed_from' => $allowed_from, 'valid_until' => $valid_until]); } + /** + * return parsed commands/files of configuration templates + */ private function getConfigDetails() { - $distro = isset($_POST['distro,']) ? $_POST['distro,'] : ""; - $section = isset($_POST['section']) ? $_POST['section'] : ""; - $daemon = isset($_POST['daemon']) ? $_POST['daemon'] : ""; + if (isset($this->userinfo['adminsession']) && $this->userinfo['adminsession'] == 1 && $this->userinfo['change_serversettings'] == 1) { + $distribution = isset($_POST['distro']) ? $_POST['distro'] : ""; + $section = isset($_POST['section']) ? $_POST['section'] : ""; + $daemon = isset($_POST['daemon']) ? $_POST['daemon'] : ""; - // @todo + // validate distribution config-xml exists + $config_dir = FileDir::makeCorrectDir(Froxlor::getInstallDir() . '/lib/configfiles/'); + if (!file_exists($config_dir . "/" . $distribution . ".xml")) { + return $this->errorResponse("Unknown distribution. The configuration could not be found."); + } + // read in all configurations + $configfiles = new ConfigParser($config_dir . "/" . $distribution . ".xml"); + // get the services + $services = $configfiles->getServices(); + // validate selected service exists for this distribution + if (!isset($services[$section])) { + return $this->errorResponse("Unknown category for selected distribution"); + } + // get the daemons + $daemons = $services[$section]->getDaemons(); + // validate selected daemon exists for this section + if (!isset($daemons[$daemon])) { + return $this->errorResponse("Unknown service for selected category"); + } + // finally the config-steps + $confarr = $daemons[$daemon]->getConfig(); + // get parsed content + UI::initTwig(); + $content = ConfigDisplay::fromConfigArr($confarr, $configfiles->distributionEditor, $this->theme); - return $this->jsonResponse(['title' => 'TODO', 'content' => '']); + return $this->jsonResponse([ + 'title' => $configfiles->getCompleteDistroName() . ' » ' . $services[$section]->title . ' » ' . $daemons[$daemon]->title, + 'content' => $content + ]); + } + return $this->errorResponse('Not allowed', 403); } } diff --git a/lib/Froxlor/Config/ConfigDisplay.php b/lib/Froxlor/Config/ConfigDisplay.php new file mode 100644 index 00000000..cb6dd1eb --- /dev/null +++ b/lib/Froxlor/Config/ConfigDisplay.php @@ -0,0 +1,224 @@ + (2010-) + * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt + * @package Config + * + */ +class ConfigDisplay +{ + /** + * @var array + */ + private static $replace_arr; + + /** + * @var string + */ + private static $editor; + + /** + * @var string + */ + private static $theme; + + /** + * @param array $confarr + * @param string $editor + * @param string $theme + */ + public static function fromConfigArr(array $confarr, string $editor, string $theme) + { + self::$editor = $editor; + self::$theme = $theme; + + $customer_tmpdir = '/tmp/'; + if (Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_tmpdir') != '') { + $customer_tmpdir = Settings::Get('system.mod_fcgid_tmpdir'); + } elseif (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.tmpdir') != '') { + $customer_tmpdir = Settings::Get('phpfpm.tmpdir'); + } + + // try to convert namserver hosts to ip's + $ns_ips = ""; + $known_ns_ips = []; + if (Settings::Get('system.nameservers') != '') { + $nameservers = explode(',', Settings::Get('system.nameservers')); + foreach ($nameservers as $nameserver) { + $nameserver = trim($nameserver); + // DNS servers might be multi homed; allow transfer from all ip + // addresses of the DNS server + $nameserver_ips = PhpHelper::gethostbynamel6($nameserver); + // append dot to hostname + if (substr($nameserver, -1, 1) != '.') { + $nameserver .= '.'; + } + // ignore invalid responses + if (!is_array($nameserver_ips)) { + // act like \Froxlor\PhpHelper::gethostbynamel6() and return unmodified hostname on error + $nameserver_ips = array( + $nameserver + ); + } else { + $known_ns_ips = array_merge($known_ns_ips, $nameserver_ips); + } + if (!empty($ns_ips)) { + $ns_ips .= ','; + } + $ns_ips .= implode(",", $nameserver_ips); + } + } + + // AXFR server + if (Settings::Get('system.axfrservers') != '') { + $axfrservers = explode(',', Settings::Get('system.axfrservers')); + foreach ($axfrservers as $axfrserver) { + if (!in_array(trim($axfrserver), $known_ns_ips)) { + if (!empty($ns_ips)) { + $ns_ips .= ','; + } + $ns_ips .= trim($axfrserver); + } + } + } + + Database::needSqlData(true); + $sql = Database::getSqlData(); + + self::$replace_arr = array( + '' => $sql['user'], + '' => 'FROXLOR_MYSQL_PASSWORD', + '' => $sql['db'], + '' => $sql['host'], + '' => isset($sql['socket']) ? $sql['socket'] : null, + '' => Settings::Get('system.hostname'), + '' => Settings::Get('system.ipaddress'), + '' => Settings::Get('system.nameservers'), + '' => $ns_ips, + '' => Settings::Get('system.vmail_homedir'), + '' => Settings::Get('system.vmail_uid'), + '' => Settings::Get('system.vmail_gid'), + '' => (Settings::Get('system.use_ssl') == '1') ? 'imaps pop3s' : '', + '' => FileDir::makeCorrectDir($customer_tmpdir), + '' => FileDir::makeCorrectDir(Froxlor::getInstallDir()), + '' => FileDir::makeCorrectDir(Settings::Get('system.bindconf_directory')), + '' => Settings::Get('system.apachereload_command'), + '' => FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')), + '' => FileDir::makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir')), + '' => Settings::Get('system.httpgroup') + ); + + $commands_pre = ""; + $commands_file = ""; + $commands_post = ""; + + $lasttype = ''; + $commands = ''; + + $configpage = ""; + + foreach ($confarr as $_action) { + if ($lasttype != '' && $lasttype != $_action['type']) { + $commands = trim($commands); + $numbrows = count(explode("\n", $commands)); + $configpage .= UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', ['commands' => $commands, 'numbrows' => $numbrows]); + $lasttype = ''; + $commands = ''; + } + switch ($_action['type']) { + case "install": + $commands .= strtr($_action['content'], self::$replace_arr) . "\n"; + $lasttype = "install"; + break; + case "command": + $commands .= strtr($_action['content'], self::$replace_arr) . "\n"; + $lasttype = "command"; + break; + case "file": + if (array_key_exists('content', $_action)) { + $commands_file = self::getFileContentContainer($_action['content'], $_action['name']); + } elseif (array_key_exists('subcommands', $_action)) { + foreach ($_action['subcommands'] as $fileaction) { + if (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "pre") { + $commands_pre .= $fileaction['content'] . "\n"; + } elseif (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "post") { + $commands_post .= $fileaction['content'] . "\n"; + } elseif ($fileaction['type'] == 'file') { + $commands_file = self::getFileContentContainer($fileaction['content'], $_action['name']); + } + } + } + $realname = $_action['name']; + $commands = trim($commands_pre); + if ($commands != "") { + $numbrows = count(explode("\n", $commands)); + $commands_pre = UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', ['commands' => $commands, 'numbrows' => $numbrows]); + } + $commands = trim($commands_post); + if ($commands != "") { + $numbrows = count(explode("\n", $commands)); + $commands_post = UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', ['commands' => $commands, 'numbrows' => $numbrows]); + } + $configpage .= UI::twig()->render(self::$theme . '/settings/conf/fileblock.html.twig', [ + 'realname' => $realname, + 'commands_pre' => $commands_pre, + 'commands_file' => $commands_file, + 'commands_post' => $commands_post + ]); + $commands = ''; + $commands_pre = ''; + $commands_post = ''; + break; + } + } + $commands = trim($commands); + if ($commands != '') { + $numbrows = count(explode("\n", $commands)); + $configpage .= UI::twig()->render(self::$theme . '/settings/conf/command.html.twig', ['commands' => $commands, 'numbrows' => $numbrows]); + } + return $configpage; + } + + /** + * @param string $file_content + * @param string $realname + * + * @return string + */ + private static function getFileContentContainer(string $file_content, string $realname): string + { + $files = ""; + $file_content = trim($file_content); + if ($file_content != '') { + $file_content = strtr($file_content, self::$replace_arr); + $file_content = htmlspecialchars($file_content); + $numbrows = count(explode("\n", $file_content)); + //eval("\$files=\"" . \Froxlor\UI\Template::getTemplate("configfiles/configfiles_file") . "\";"); + $files = UI::twig()->render(self::$theme . '/settings/conf/file.html.twig', [ + 'distro_editor' => self::$editor, + 'realname' => $realname, + 'numbrows' => $numbrows, + 'file_content' => $file_content + ]); + } + return $files; + } +} diff --git a/lib/Froxlor/Config/ConfigParser.php b/lib/Froxlor/Config/ConfigParser.php index d78b0bc8..20f624cc 100644 --- a/lib/Froxlor/Config/ConfigParser.php +++ b/lib/Froxlor/Config/ConfigParser.php @@ -1,4 +1,5 @@ xml->xpath('//distribution'); // No distribution found - can't use this file - if (! is_array($distribution)) { + if (!is_array($distribution)) { throw new \Exception('Invalid XML, no distribution found'); } @@ -235,4 +236,25 @@ class ConfigParser // Return our carefully searched for defaults return $this->defaults; } + + /** + * return complete distribution string "Name [codename] [ (version)] [deprecated] + * + * @return string + */ + public function getCompleteDistroName(): string + { + // get distro-info + $dist_display = $this->distributionName; + if ($this->distributionCodename != '') { + $dist_display .= " " . $this->distributionCodename; + } + if ($this->distributionVersion != '') { + $dist_display .= " (" . $this->distributionVersion . ")"; + } + if ($this->deprecated) { + $dist_display .= " [deprecated]"; + } + return $dist_display; + } } diff --git a/templates/Froxlor/settings/conf/command.html.twig b/templates/Froxlor/settings/conf/command.html.twig new file mode 100644 index 00000000..97514312 --- /dev/null +++ b/templates/Froxlor/settings/conf/command.html.twig @@ -0,0 +1 @@ + diff --git a/templates/Froxlor/settings/conf/file.html.twig b/templates/Froxlor/settings/conf/file.html.twig new file mode 100644 index 00000000..ce850874 --- /dev/null +++ b/templates/Froxlor/settings/conf/file.html.twig @@ -0,0 +1,2 @@ + + diff --git a/templates/Froxlor/settings/conf/fileblock.html.twig b/templates/Froxlor/settings/conf/fileblock.html.twig new file mode 100644 index 00000000..6efa0bb7 --- /dev/null +++ b/templates/Froxlor/settings/conf/fileblock.html.twig @@ -0,0 +1,6 @@ +
+ {{ realname }} + {{ commands_pre|raw }} + {{ commands_file|raw }} + {{ commands_post|raw }} +