From 56a9a71248b24cf68eddedde48bb0524ad09d5d9 Mon Sep 17 00:00:00 2001 From: Michael Kaufmann Date: Tue, 15 Feb 2022 11:18:19 +0100 Subject: [PATCH] preparing for re-design using new template-engine for future 0.11.x releases Signed-off-by: Michael Kaufmann --- .gitignore | 1 + composer.json | 6 +- composer.lock | 382 ++++++-- install/install.php | 27 +- install/lib/class.FroxlorInstall.php | 872 +++++++++--------- install/lng/english.lng.php | 4 +- install/lng/german.lng.php | 4 +- install/templates/assets/css/install.css | 637 ------------- install/templates/assets/img/favicon.ico | Bin 1386 -> 0 bytes install/templates/assets/img/logo.png | Bin 2606 -> 0 bytes install/templates/assets/img/password.png | Bin 3395 -> 0 bytes .../templates/assets/img/text_align_left.png | Bin 198 -> 0 bytes install/templates/dataform.tpl | 10 - install/templates/dataform2.tpl | 13 - install/templates/dataitem.tpl | 4 - install/templates/dataitemchk.tpl | 4 - install/templates/dataitemselect.tpl | 6 - install/templates/dataitemyesno.tpl | 4 - install/templates/datasection.tpl | 2 - install/templates/footer.tpl | 7 - install/templates/header.tpl | 13 - install/templates/lngform.tpl | 20 - install/templates/page.tpl | 11 - install/templates/pagebottom.tpl | 4 - install/templates/textarea.tpl | 5 - lib/Froxlor/PhpHelper.php | 62 +- lib/Froxlor/UI/Panel/CustomReflection.php | 54 ++ lib/Froxlor/UI/Panel/FroxlorTwig.php | 102 ++ lib/Froxlor/UI/Panel/UI.php | 274 ++++++ lib/init.php | 165 ++-- templates/Froxlor/assets/css/main.css | 12 + templates/Froxlor/base.html.twig | 77 ++ templates/Froxlor/install/form.html.twig | 88 ++ templates/Froxlor/install/index.html.twig | 53 ++ .../Froxlor/misc/alert_nosession.html.twig | 23 + .../Froxlor/misc/configurehint.html.twig | 17 + .../Froxlor/misc/ownershiphint.html.twig | 20 + .../misc/phprequirementfailed.html.twig | 49 + .../Froxlor/misc/vendormissinghint.html.twig | 50 + 39 files changed, 1685 insertions(+), 1397 deletions(-) delete mode 100644 install/templates/assets/css/install.css delete mode 100644 install/templates/assets/img/favicon.ico delete mode 100644 install/templates/assets/img/logo.png delete mode 100644 install/templates/assets/img/password.png delete mode 100644 install/templates/assets/img/text_align_left.png delete mode 100644 install/templates/dataform.tpl delete mode 100644 install/templates/dataform2.tpl delete mode 100644 install/templates/dataitem.tpl delete mode 100644 install/templates/dataitemchk.tpl delete mode 100644 install/templates/dataitemselect.tpl delete mode 100644 install/templates/dataitemyesno.tpl delete mode 100644 install/templates/datasection.tpl delete mode 100644 install/templates/footer.tpl delete mode 100644 install/templates/header.tpl delete mode 100644 install/templates/lngform.tpl delete mode 100644 install/templates/page.tpl delete mode 100644 install/templates/pagebottom.tpl delete mode 100644 install/templates/textarea.tpl create mode 100644 lib/Froxlor/UI/Panel/CustomReflection.php create mode 100644 lib/Froxlor/UI/Panel/FroxlorTwig.php create mode 100644 lib/Froxlor/UI/Panel/UI.php create mode 100644 templates/Froxlor/assets/css/main.css create mode 100644 templates/Froxlor/base.html.twig create mode 100644 templates/Froxlor/install/form.html.twig create mode 100644 templates/Froxlor/install/index.html.twig create mode 100644 templates/Froxlor/misc/alert_nosession.html.twig create mode 100644 templates/Froxlor/misc/configurehint.html.twig create mode 100644 templates/Froxlor/misc/ownershiphint.html.twig create mode 100644 templates/Froxlor/misc/phprequirementfailed.html.twig create mode 100644 templates/Froxlor/misc/vendormissinghint.html.twig diff --git a/.gitignore b/.gitignore index 272a8cdf..8fae7b37 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ img/ !templates/Froxlor/ !templates/Sparkle/ +!templates/Sparkl2/ !templates/misc/ templates/Sparkle/assets/css/custom.css vendor/ diff --git a/composer.json b/composer.json index b1e6f0b1..4447fac6 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,11 @@ "monolog/monolog": "^1.24", "robthree/twofactorauth": "^1.6", "froxlor/idna-convert-legacy": "^2.1", - "voku/anti-xss": "^4.1" + "voku/anti-xss": "^4.1", + "twig/twig": "^3.3", + "twbs/bootstrap": "^5.1", + "components/jquery": "^3.6", + "components/font-awesome": "^5.15" }, "require-dev": { "phpunit/phpunit": "^9", diff --git a/composer.lock b/composer.lock index e026863c..053ef538 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,96 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "85144894a3d797cd463442147120549f", + "content-hash": "723dd2a8563bc4727619df8792ab2cb5", "packages": [ + { + "name": "components/font-awesome", + "version": "5.15.4", + "source": { + "type": "git", + "url": "https://github.com/components/font-awesome.git", + "reference": "e6fd09f30f578915cc0cf186b0dd0da54385b6be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/components/font-awesome/zipball/e6fd09f30f578915cc0cf186b0dd0da54385b6be", + "reference": "e6fd09f30f578915cc0cf186b0dd0da54385b6be", + "shasum": "" + }, + "type": "component", + "extra": { + "component": { + "styles": [ + "css/all.css" + ], + "files": [ + "css/all.min.css", + "webfonts/*" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "CC-BY-4.0", + "MIT", + "OFL-1.1" + ], + "description": "Font Awesome, the iconic SVG, font, and CSS framework.", + "support": { + "issues": "https://github.com/components/font-awesome/issues", + "source": "https://github.com/components/font-awesome/tree/5.15.4" + }, + "time": "2021-08-15T10:31:24+00:00" + }, + { + "name": "components/jquery", + "version": "3.6.0", + "source": { + "type": "git", + "url": "https://github.com/components/jquery.git", + "reference": "6cf38ee1fd04b6adf8e7dda161283aa35be818c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/components/jquery/zipball/6cf38ee1fd04b6adf8e7dda161283aa35be818c3", + "reference": "6cf38ee1fd04b6adf8e7dda161283aa35be818c3", + "shasum": "" + }, + "type": "component", + "extra": { + "component": { + "scripts": [ + "jquery.js" + ], + "files": [ + "jquery.min.js", + "jquery.min.map", + "jquery.slim.js", + "jquery.slim.min.js", + "jquery.slim.min.map" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "JS Foundation and other contributors" + } + ], + "description": "jQuery JavaScript Library", + "homepage": "http://jquery.com", + "support": { + "forum": "http://forum.jquery.com", + "irc": "irc://irc.freenode.org/jquery", + "issues": "https://github.com/jquery/jquery/issues", + "source": "https://github.com/jquery/jquery", + "wiki": "http://docs.jquery.com/" + }, + "time": "2021-03-20T19:13:42+00:00" + }, { "name": "froxlor/idna-convert-legacy", "version": "v2.1.2", @@ -346,6 +434,88 @@ ], "time": "2021-10-20T12:19:55+00:00" }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.24.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "30885182c981ab175d4d034db0f6f469898070ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", + "reference": "30885182c981ab175d4d034db0f6f469898070ab", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-10-20T20:35:02+00:00" + }, { "name": "symfony/polyfill-iconv", "version": "v1.24.0", @@ -753,6 +923,132 @@ ], "time": "2021-05-27T09:17:38+00:00" }, + { + "name": "twbs/bootstrap", + "version": "v5.1.3", + "source": { + "type": "git", + "url": "https://github.com/twbs/bootstrap.git", + "reference": "1a6fdfae6be09b09eaced8f0e442ca6f7680a61e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twbs/bootstrap/zipball/1a6fdfae6be09b09eaced8f0e442ca6f7680a61e", + "reference": "1a6fdfae6be09b09eaced8f0e442ca6f7680a61e", + "shasum": "" + }, + "replace": { + "twitter/bootstrap": "self.version" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Otto", + "email": "markdotto@gmail.com" + }, + { + "name": "Jacob Thornton", + "email": "jacobthornton@gmail.com" + } + ], + "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", + "homepage": "https://getbootstrap.com/", + "keywords": [ + "JS", + "css", + "framework", + "front-end", + "mobile-first", + "responsive", + "sass", + "web" + ], + "support": { + "issues": "https://github.com/twbs/bootstrap/issues", + "source": "https://github.com/twbs/bootstrap/tree/v5.1.3" + }, + "time": "2021-10-09T06:43:19+00:00" + }, + { + "name": "twig/twig", + "version": "v3.3.8", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "972d8604a92b7054828b539f2febb0211dd5945c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/972d8604a92b7054828b539f2febb0211dd5945c", + "reference": "972d8604a92b7054828b539f2febb0211dd5945c", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v3.3.8" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2022-02-04T06:59:48+00:00" + }, { "name": "voku/anti-xss", "version": "4.1.35", @@ -3778,88 +4074,6 @@ ], "time": "2021-10-28T13:39:27+00:00" }, - { - "name": "symfony/polyfill-ctype", - "version": "v1.24.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "30885182c981ab175d4d034db0f6f469898070ab" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/30885182c981ab175d4d034db0f6f469898070ab", - "reference": "30885182c981ab175d4d034db0f6f469898070ab", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.23-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for ctype functions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "ctype", - "polyfill", - "portable" - ], - "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.24.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2021-10-20T20:35:02+00:00" - }, { "name": "symfony/polyfill-php80", "version": "v1.24.0", @@ -4238,5 +4452,5 @@ "platform-dev": { "ext-pcntl": "*" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.0.0" } diff --git a/install/install.php b/install/install.php index 7a258149..f6353a8c 100644 --- a/install/install.php +++ b/install/install.php @@ -15,16 +15,39 @@ * @package Install * */ -if (! file_exists(dirname(__DIR__) . '/vendor/autoload.php')) { +// define default theme for configurehint, etc. +$_deftheme = 'Froxlor'; + +// validate correct php version +if (version_compare("7.1.0", PHP_VERSION, ">=")) { // get hint-template - $vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/Sparkle/misc/vendormissinghint.tpl'); + $wrongphp_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/phprequirementfailed.html.twig'); + // replace values + $wrongphp_hint = str_replace("", "7.1.0", $wrongphp_hint); + $wrongphp_hint = str_replace("", PHP_VERSION, $wrongphp_hint); + $wrongphp_hint = str_replace("", date('Y', time()), $wrongphp_hint); + die($wrongphp_hint); +} + +if (!file_exists(dirname(__DIR__) . '/vendor/autoload.php')) { + // get hint-template + $vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/vendormissinghint.html.twig'); // replace values $vendor_hint = str_replace("", dirname(__DIR__), $vendor_hint); $vendor_hint = str_replace("", date('Y', time()), $vendor_hint); die($vendor_hint); } + require dirname(__DIR__) . '/vendor/autoload.php'; require __DIR__ . '/lib/class.FroxlorInstall.php'; +use Froxlor\UI\Panel\UI; + +UI::initTwig(true); +UI::Twig()->addGlobal('install_mode', '1'); +UI::Twig()->addGlobal('basehref', '../'); + $frxinstall = new FroxlorInstall(); $frxinstall->run(); + +UI::TwigOutputBuffer(); diff --git a/install/lib/class.FroxlorInstall.php b/install/lib/class.FroxlorInstall.php index 30855bfa..53bbde7a 100644 --- a/install/lib/class.FroxlorInstall.php +++ b/install/lib/class.FroxlorInstall.php @@ -9,7 +9,6 @@ * COPYING file online at http://files.froxlor.org/misc/COPYING.txt * * @copyright (c) the authors - * @author Michael Kaufmann * @author Froxlor team (2010-) * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt * @package Classes @@ -18,17 +17,18 @@ * */ +use Froxlor\UI\Panel\UI; + /** * Class FroxlorInstall * - * Does the dirty work + * Setup froxlor's database and populate with data from install process * * @copyright (c) the authors - * @author Michael Kaufmann * @author Froxlor team (2010-) * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt * @package Install - * + * */ class FroxlorInstall { @@ -41,13 +41,6 @@ class FroxlorInstall */ private $_basepath = null; - /** - * theme to use for the installation process - * - * @var string - */ - private $_theme = 'Sparkle'; - /** * language array * @@ -99,8 +92,6 @@ class FroxlorInstall */ public function run() { - // send headers - $this->_sendHeaders(); // check if we have a valid installation already $this->_checkUserdataFile(); // include the MySQL-Table-Definitions @@ -116,18 +107,16 @@ class FroxlorInstall */ private function _showPage() { - // set theme for templates - $theme = $this->_theme; - eval("echo \"" . $this->_getTemplate("header") . "\";"); // check install-state if ((isset($_POST['installstep']) && $_POST['installstep'] == '1') || (isset($_GET['check']) && $_GET['check'] == '1')) { $pagetitle = $this->_lng['install']['title']; - if ($this->_checkPostData()) { + $check_result = null; + if (!empty($_POST) && $this->_checkPostData($check_result)) { // check data and create userdata etc.etc.etc. $result = $this->_doInstall(); } elseif (isset($_GET['check']) && $_GET['check'] == '1') { // gather data - $result = $this->_showDataForm(); + $result = $this->_showDataForm($check_result); } else { // this should not happen $result = array( @@ -143,9 +132,12 @@ class FroxlorInstall // output everything $pagecontent = $result['pagecontent']; $pagenavigation = $result['pagenavigation']; - eval("echo \"" . $this->_getTemplate("page") . "\";"); - $current_year = date('Y', time()); - eval("echo \"" . $this->_getTemplate("footer") . "\";"); + + UI::TwigBuffer('/install/index.html.twig', [ + 'pagetitle' => $pagetitle, + 'pagecontent' => $pagecontent, + 'pagenavigation' => $pagenavigation + ]); } /** @@ -154,7 +146,7 @@ class FroxlorInstall * * @return boolean */ - private function _checkPostData() + private function _checkPostData(&$check_result) { $this->_guessServerName(); $this->_guessServerIP(); @@ -187,11 +179,35 @@ class FroxlorInstall // check system-hostname to be a FQDN if ($this->_validate_ip($this->_data['servername']) !== false) { + $check_result[] = "Invalid hostname"; $this->_data['servername'] = ''; } if (empty($this->_data['serverip']) || $this->_validate_ip($this->_data['serverip']) == false) { - return false; + $check_result[] = "Invalid IP address"; + } + + $nonempty = [ + 'admin_pass1' => 'admin-user password', + 'mysql_unpriv_pass' => 'unprivileged mysql-user password', + 'mysql_root_pass' => 'mysql root-user password', + 'servername' => 'servername', + 'serverip' => 'server IP address', + 'httpuser' => 'webserver user', + 'httpgroup' => 'webserver group' + ]; + foreach ($nonempty as $necheck => $msg) { + if ($this->_data[$necheck] == '') { + $check_result[] = $msg . " cannot be empty"; + } + } + + if ($this->_data['admin_pass1'] != $this->_data['admin_pass2']) { + $check_result[] = "admin-user passwords do not match"; + } + + if ($this->_data['mysql_unpriv_user'] == $this->_data['mysql_root_user']) { + $check_result[] = "unprivileged mysql-user and mysql root-user must not be the same"; } if (isset($_POST['installstep']) && $_POST['installstep'] == '1' && $this->_data['admin_pass1'] == $this->_data['admin_pass2'] && $this->_data['admin_pass1'] != '' && $this->_data['admin_pass2'] != '' && $this->_data['mysql_unpriv_pass'] != '' && $this->_data['mysql_root_pass'] != '' && $this->_data['servername'] != '' && $this->_data['serverip'] != '' && $this->_data['httpuser'] != '' && $this->_data['httpgroup'] != '' && $this->_data['mysql_unpriv_user'] != $this->_data['mysql_root_user']) { @@ -207,10 +223,14 @@ class FroxlorInstall */ private function _doInstall() { - $content = ""; + // check results + $content = []; // check for mysql-root-connection - $content .= $this->_status_message('begin', $this->_lng['install']['testing_mysql']); + $check = [ + 'title' => $this->_lng['install']['testing_mysql'], + 'result' => 0 + ]; $options = array( 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' @@ -231,19 +251,22 @@ class FroxlorInstall $db_root = new PDO($dsn, $this->_data['mysql_root_user'], '', $options); // set the given password $passwd_stmt = $db_root->prepare(" - SET PASSWORD = PASSWORD(:passwd) - "); + SET PASSWORD = PASSWORD(:passwd) + "); $passwd_stmt->execute(array( 'passwd' => $this->_data['mysql_root_pass'] )); } catch (PDOException $e) { // nope - $content .= $this->_status_message('red', $e->getMessage()); + $check['result'] = 1; + $check['result_txt'] = $this->_lng['install']['failed']; + $check['result_desc'] = $e->getMessage(); $fatal_fail = true; + $content[] = $check; } } - if (! $fatal_fail) { + if (!$fatal_fail) { $version_server = $db_root->getAttribute(PDO::ATTR_SERVER_VERSION); $sql_mode = 'NO_ENGINE_SUBSTITUTION'; if (version_compare($version_server, '8.0.11', '<')) { @@ -252,16 +275,18 @@ class FroxlorInstall $db_root->exec('SET sql_mode = "' . $sql_mode . '"'); // ok, if we are here, the database connection is up and running - $content .= $this->_status_message('green', "OK"); + $check['result_txt'] = "OK"; + $content[] = $check; + // check for existing db and create backup if so - $content .= $this->_backupExistingDatabase($db_root); + $this->_backupExistingDatabase($db_root, $content); if (!$this->_abort) { // create unprivileged user and the database itself - $content .= $this->_createDatabaseAndUser($db_root); + $this->_createDatabaseAndUser($db_root, $content); // importing data to new database - $content .= $this->_importDatabaseData(); + $this->_importDatabaseData($content); } - if (! $this->_abort) { + if (!$this->_abort) { // create DB object for new database $options = array( 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' @@ -283,58 +308,71 @@ class FroxlorInstall } $db->exec('SET sql_mode = "' . $sql_mode . '"'); } catch (PDOException $e) { - // dafuq? this should have happened in _importDatabaseData() - $content .= $this->_status_message('red', $e->getMessage()); + // this should have happened in _importDatabaseData() + $check = [ + 'title' => 'Unexpected exception occured', + 'result' => 1, + 'result_txt' => '!!!', + 'result_desc' => $e->getMessage() + ]; + $content[] = $check; $another_fail = true; } - if (! $another_fail) { + if (!$another_fail) { // change settings accordingly - $content .= $this->_doSettings($db); + $this->_doSettings($db, $content); // create entries - $content .= $this->_doDataEntries($db); + $this->_doDataEntries($db, $content); $db = null; // create config-file - $content .= $this->_createUserdataConf(); + $this->_createUserdataConf($content); } } } - $content .= "
"; - // check if we have unrecoverable errors if ($fatal_fail || $another_fail || $this->_abort) { // D'oh - $navigation = ''; - $msgcolor = 'red'; + $_die = true; $message = $this->_lng['install']['testing_mysql_fail']; $link = 'install.php?check=1'; $linktext = $this->_lng['click_here_to_goback']; } else { // all good - $navigation = ''; - $msgcolor = 'green'; + $_die = false; $message = $this->_lng['install']['froxlor_succ_installed']; $link = '../index.php'; $linktext = $this->_lng['click_here_to_login']; } - eval("\$navigation .= \"" . $this->_getTemplate("pagebottom") . "\";"); - return array( - 'pagecontent' => $content, - 'pagenavigation' => $navigation + 'pagecontent' => [ + 'installprocess' => $content + ], + 'pagenavigation' => [ + 'bad' => $_die, + 'message' => $message, + 'link' => $link, + 'linktext' => $linktext + ] ); } /** * Create userdata.inc.php file + * + * @param array $content + * + * @return void */ - private function _createUserdataConf() + private function _createUserdataConf(&$content) { - $content = ""; + $check = [ + 'title' => $this->_lng['install']['creating_configfile'], + 'result' => 0 + ]; - $content .= $this->_status_message('begin', $this->_lng['install']['creating_configfile']); $userdata = "_data['mysql_host'], "'\\") . "';\n"; @@ -360,7 +398,6 @@ class FroxlorInstall $fp = @fopen($userdata_file, 'w'); @fputs($fp, $userdata, strlen($userdata)); @fclose($fp); - $content .= $this->_status_message('green', 'OK'); } else { @unlink($userdata_file); // try creating it in a temporary file @@ -369,16 +406,17 @@ class FroxlorInstall $fp = @fopen($temp_file, 'w'); @fputs($fp, $userdata, strlen($userdata)); @fclose($fp); - $content .= $this->_status_message('orange', sprintf($this->_lng['install']['creating_configfile_temp'], $temp_file)); + $check['result'] = 2; + $check['result_txt'] = sprintf($this->_lng['install']['creating_configfile_temp'], $temp_file); } else { - $content .= $this->_status_message('red', $this->_lng['install']['creating_configfile_failed']); - $escpduserdata = nl2br(htmlspecialchars($userdata)); - eval("\$content .= \"" . $this->_getTemplate("textarea") . "\";"); + $check['result'] = 1; + $check['result_txt'] = $this->_lng['install']['creating_configfile_failed']; + $check['result_desc'] = nl2br(htmlspecialchars($userdata)); } } @umask($umask); - return $content; + $content[] = $check; } /** @@ -389,7 +427,7 @@ class FroxlorInstall */ private function genUniqueToken(int $length = 16) { - if(!isset($length) || intval($length) <= 8 ){ + if (!isset($length) || intval($length) <= 8) { $length = 16; } if (function_exists('random_bytes')) { @@ -409,43 +447,67 @@ class FroxlorInstall * create corresponding entries in froxlor database * * @param object $db + * @param array $content * - * @return string status messages + * @return void */ - private function _doDataEntries(&$db) + private function _doDataEntries(&$db, &$content) { - $content = ""; - - $content .= $this->_status_message('begin', $this->_lng['install']['creating_entries']); + $check = [ + 'title' => $this->_lng['install']['creating_entries'], + 'result' => 0 + ]; // and lets insert the default ip and port $stmt = $db->prepare(" - INSERT INTO `" . TABLE_PANEL_IPSANDPORTS . "` SET - `ip`= :serverip, - `port` = '80', - `namevirtualhost_statement` = '1', - `vhostcontainer` = '1', - `vhostcontainer_servername_statement` = '1' - "); + INSERT INTO `" . TABLE_PANEL_IPSANDPORTS . "` SET + `ip`= :serverip, + `port` = :serverport, + `namevirtualhost_statement` = :nvh, + `vhostcontainer` = '1', + `vhostcontainer_servername_statement` = '1' + "); $stmt->execute(array( - 'serverip' => $this->_data['serverip'] + 'nvh' => $this->_data['webserver'] == 'apache2' ? '1' : '0', + 'serverip' => $this->_data['serverip'], + 'serverport' => 80 )); $defaultip = $db->lastInsertId(); + $defaultsslip = false; + if ($this->_data['use_ssl']) { + $stmt->execute(array( + 'serverip' => $this->_data['serverip'], + 'serverport' => 443 + )); + $defaultsslip = $db->lastInsertId(); + } + // insert the defaultip $upd_stmt = $db->prepare(" - UPDATE `" . TABLE_PANEL_SETTINGS . "` SET - `value` = :defaultip - WHERE `settinggroup` = 'system' AND `varname` = 'defaultip' - "); + UPDATE `" . TABLE_PANEL_SETTINGS . "` SET + `value` = :defaultip + WHERE `settinggroup` = 'system' AND `varname` = :defipfld + "); $upd_stmt->execute(array( - 'defaultip' => $defaultip + 'defaultip' => $defaultip, + 'defipfld' => 'defaultip' )); - $content .= $this->_status_message('green', 'OK'); + if ($defaultsslip) { + $upd_stmt->execute(array( + 'defaultip' => $defaultsslip, + 'defipfld' => 'defaultsslip' + )); + } + + $content[] = $check; // last but not least create the main admin - $content .= $this->_status_message('begin', $this->_lng['install']['adding_admin_user']); + $check = [ + 'title' => $this->_lng['install']['adding_admin_user'], + 'result' => 0 + ]; $ins_data = array( 'loginname' => $this->_data['admin_user'], /* use SHA256 default crypt */ @@ -454,35 +516,33 @@ class FroxlorInstall 'deflang' => $this->_languages[$this->_activelng] ); $ins_stmt = $db->prepare(" - INSERT INTO `" . TABLE_PANEL_ADMINS . "` SET - `loginname` = :loginname, - `password` = :password, - `name` = 'Froxlor-Administrator', - `email` = :email, - `def_language` = :deflang, - `api_allowed` = 1, - `customers` = -1, - `customers_see_all` = 1, - `caneditphpsettings` = 1, - `domains` = -1, - `domains_see_all` = 1, - `change_serversettings` = 1, - `diskspace` = -1024, - `mysqls` = -1, - `emails` = -1, - `email_accounts` = -1, - `email_forwarders` = -1, - `email_quota` = -1, - `ftps` = -1, - `subdomains` = -1, - `traffic` = -1048576 - "); + INSERT INTO `" . TABLE_PANEL_ADMINS . "` SET + `loginname` = :loginname, + `password` = :password, + `name` = 'Froxlor-Administrator', + `email` = :email, + `def_language` = :deflang, + `api_allowed` = 1, + `customers` = -1, + `customers_see_all` = 1, + `caneditphpsettings` = 1, + `domains` = -1, + `domains_see_all` = 1, + `change_serversettings` = 1, + `diskspace` = -1024, + `mysqls` = -1, + `emails` = -1, + `email_accounts` = -1, + `email_forwarders` = -1, + `email_quota` = -1, + `ftps` = -1, + `subdomains` = -1, + `traffic` = -1048576 + "); $ins_stmt->execute($ins_data); - $content .= $this->_status_message('green', 'OK'); - - return $content; + $content[] = $check; } /** @@ -506,19 +566,22 @@ class FroxlorInstall * change settings according to users input * * @param object $db + * @param array $content * - * @return string status messages + * @return void */ - private function _doSettings(&$db) + private function _doSettings(&$db, &$content) { - $content = ""; + $check = [ + 'title' => $this->_lng['install']['changing_data'], + 'result' => 0 + ]; - $content .= $this->_status_message('begin', $this->_lng['install']['changing_data']); $upd_stmt = $db->prepare(" - UPDATE `" . TABLE_PANEL_SETTINGS . "` SET - `value` = :value - WHERE `settinggroup` = :group AND `varname` = :varname - "); + UPDATE `" . TABLE_PANEL_SETTINGS . "` SET + `value` = :value + WHERE `settinggroup` = :group AND `varname` = :varname + "); $this->_updateSetting($upd_stmt, 'admin@' . $this->_data['servername'], 'panel', 'adminmail'); $this->_updateSetting($upd_stmt, $this->_data['serverip'], 'system', 'ipaddress'); @@ -581,22 +644,22 @@ class FroxlorInstall // insert task 99 to generate a correct cron.d-file automatically $db->query("INSERT INTO `" . TABLE_PANEL_TASKS . "` SET `type` = '99';"); - $content .= $this->_status_message('green', 'OK'); - - return $content; + $content[] = $check; } /** * Import froxlor.sql into database * - * @param object $db_root + * @param array $content * - * @return string status messages + * @return void */ - private function _importDatabaseData() + private function _importDatabaseData(&$content) { - $content = ""; - $content .= $this->_status_message('begin', $this->_lng['install']['testing_new_db']); + $check = [ + 'title' => $this->_lng['install']['testing_new_db'], + 'result' => 0 + ]; $options = array( 'PDO::MYSQL_ATTR_INIT_COMMAND' => 'SET names utf8' ); @@ -624,55 +687,61 @@ class FroxlorInstall } $db->exec('SET sql_mode = "' . $sql_mode . '"'); } catch (PDOException $e) { - $content .= $this->_status_message('red', $e->getMessage()); + $check['result'] = 1; + $check['result_txt'] = $this->_lng['install']['failed']; + $check['result_desc'] = $e->getMessage(); $fatal_fail = true; + $this->_abort = true; + $content[] = $check; } - if (! $fatal_fail) { + if (!$fatal_fail) { - $content .= $this->_status_message('green', 'OK'); + $content[] = $check; - $content .= $this->_status_message('begin', $this->_lng['install']['importing_data']); + $check = [ + 'title' => $this->_lng['install']['importing_data'], + 'result' => 0 + ]; $db_schema = dirname(dirname(__FILE__)) . '/froxlor.sql'; $sql_query = @file_get_contents($db_schema); $sql_query = $this->_remove_remarks($sql_query); $sql_query = $this->_split_sql_file($sql_query, ';'); - for ($i = 0; $i < sizeof($sql_query); $i ++) { + for ($i = 0; $i < sizeof($sql_query); $i++) { if (trim($sql_query[$i]) != '') { try { $db->query($sql_query[$i]); } catch (\PDOException $e) { - $content .= $this->_status_message('red', $e->getMessage()); + $check['result'] = 1; + $check['result_txt'] = $this->_lng['install']['failed']; + $check['result_desc'] = $e->getMessage(); $fatal_fail = true; $this->_abort = true; break; } } } - - if (! $fatal_fail) { - $content .= $this->_status_message('green', 'OK'); - } $db = null; } - - return $content; + $content[] = $check; } /** * Create database and database-user * * @param object $db_root + * @param array $content * - * @return string status messages + * @return void */ - private function _createDatabaseAndUser(&$db_root) + private function _createDatabaseAndUser(&$db_root, &$content) { - $content = ""; - // so first we have to delete the database and // the user given for the unpriv-user if they exit - $content .= $this->_status_message('begin', $this->_lng['install']['prepare_db']); + $check = [ + 'title' => $this->_lng['install']['prepare_db'], + 'result' => 0 + ]; $del_stmt = $db_root->prepare("DELETE FROM `mysql`.`user` WHERE `User` = :user AND `Host` = :accesshost"); $del_stmt->execute(array( @@ -702,20 +771,23 @@ class FroxlorInstall $del_stmt->execute(); $db_root->query("FLUSH PRIVILEGES;"); - $content .= $this->_status_message('green', 'OK'); + $content[] = $check; // we have to create a new user and database for the froxlor unprivileged mysql access - $content .= $this->_status_message('begin', $this->_lng['install']['create_mysqluser_and_db']); + $check = [ + 'title' => $this->_lng['install']['create_mysqluser_and_db'], + 'result' => 0 + ]; $ins_stmt = $db_root->prepare("CREATE DATABASE `" . str_replace('`', '', $this->_data['mysql_database']) . "` CHARACTER SET=utf8 COLLATE=utf8_general_ci"); $ins_stmt->execute(); $mysql_access_host_array = array_map('trim', explode(',', $this->_data['mysql_access_host'])); - if (in_array('127.0.0.1', $mysql_access_host_array) && ! in_array('localhost', $mysql_access_host_array)) { + if (in_array('127.0.0.1', $mysql_access_host_array) && !in_array('localhost', $mysql_access_host_array)) { $mysql_access_host_array[] = 'localhost'; } - if (! in_array('127.0.0.1', $mysql_access_host_array) && in_array('localhost', $mysql_access_host_array)) { + if (!in_array('127.0.0.1', $mysql_access_host_array) && in_array('localhost', $mysql_access_host_array)) { $mysql_access_host_array[] = '127.0.0.1'; } @@ -727,9 +799,7 @@ class FroxlorInstall $db_root->query("FLUSH PRIVILEGES;"); $this->_data['mysql_access_host'] = implode(',', $mysql_access_host_array); - $content .= $this->_status_message('green', 'OK'); - - return $content; + $content[] = $check; } private function _grantDbPrivilegesTo(&$db_root, $database, $username, $password, $access_host) @@ -768,13 +838,12 @@ class FroxlorInstall * Check if an old database exists and back it up if necessary * * @param object $db_root + * @param array $content * - * @return string status messages + * @return void */ - private function _backupExistingDatabase(&$db_root) + private function _backupExistingDatabase(&$db_root, &$content) { - $content = ""; - // check for existing of former database $tables_exist = false; $sql = "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = :database"; @@ -784,7 +853,10 @@ class FroxlorInstall )); $rows = $db_root->query("SELECT FOUND_ROWS()")->fetchColumn(); - $content .= $this->_status_message('begin', $this->_lng['install']['check_db_exists']); + $check = [ + 'title' => $this->_lng['install']['check_db_exists'], + 'result' => 0 + ]; // check result if ($result_stmt !== false && $rows > 0) { @@ -792,11 +864,17 @@ class FroxlorInstall } if ($tables_exist) { - if ((int)$this->_data['mysql_forcecreate'] > 0) { + if ((int) $this->_data['mysql_forcecreate'] > 0) { // set status - $content .= $this->_status_message('orange', 'exists (' . $this->_data['mysql_database'] . ')'); + $check['result'] = 2; + $check['result_txt'] = 'exists (' . $this->_data['mysql_database'] . ')'; + $content[] = $check; + // tell what's going on - $content .= $this->_status_message('begin', $this->_lng['install']['backup_old_db']); + $check = [ + 'title' => $this->_lng['install']['backup_old_db'], + 'result' => 0 + ]; // create temporary backup-filename $filename = "/tmp/froxlor_backup_" . date('YmdHi') . ".sql"; @@ -821,126 +899,77 @@ class FroxlorInstall $output = []; exec($command, $output); @unlink($cnffilename); - if (stristr(implode(" ", $output), "error") || ! file_exists($filename)) { - $content .= $this->_status_message('red', $this->_lng['install']['backup_failed']); + if (stristr(implode(" ", $output), "error") || !file_exists($filename)) { + $check['result'] = 1; + $check['result_txt'] = $this->_lng['install']['backup_failed']; $this->_abort = true; - } else { - $content .= $this->_status_message('green', 'OK (' . $filename . ')'); } } else { - $content .= $this->_status_message('red', $this->_lng['install']['backup_binary_missing']); + $check['result'] = 1; + $check['result_txt'] = $this->_lng['install']['backup_binary_missing']; $this->_abort = true; } + $content[] = $check; } else { - $content .= $this->_status_message('red', $this->_lng['install']['db_exists']); + $check['result'] = 1; + $check['result_txt'] = $this->_lng['install']['db_exists']; $this->_abort = true; } - } else { - $content .= $content .= $this->_status_message('green', 'OK'); } - - return $content; + $content[] = $check; } /** * show form to collect all needed data for the install */ - private function _showDataForm() + private function _showDataForm($check_result = null) { - $content = ""; // form action $formaction = htmlspecialchars($_SERVER['PHP_SELF']); if (isset($_GET['check'])) { $formaction .= '?check=' . (int) $_GET['check']; } - // language selection - $language_options = ''; - foreach ($this->_languages as $language_file => $language_name) { - $language_options .= \Froxlor\UI\HTML::makeoption($language_name, $language_file, $this->_activelng, true, true); - } - // get language-form-template - eval("\$content .= \"" . $this->_getTemplate("lngform") . "\";"); + + // prefill whatever we can + $cpdr = []; + $this->_checkPostData($cpdr); // form-data - $formdata = ""; + $formdata = []; /** * Database */ - $section = $this->_lng['install']['database']; - eval("\$formdata .= \"" . $this->_getTemplate("datasection") . "\";"); - // host - $formdata .= $this->_getSectionItemString('mysql_host', true); - // database - $formdata .= $this->_getSectionItemString('mysql_database', true); - // database overwrite if exists? - $formdata .= $this->_getSectionItemYesNo('mysql_forcecreate', false); - // unpriv-user has to be different from root - if ($this->_data['mysql_unpriv_user'] == $this->_data['mysql_root_user']) { - $style = 'blue'; - } else { - $style = ''; - } - $formdata .= $this->_getSectionItemString('mysql_unpriv_user', true, $style); - // is we posted and no password was given -> red - if (! empty($_POST['installstep']) && $this->_data['mysql_unpriv_pass'] == '') { - $style = 'red'; - } else { - $style = ''; - } - $formdata .= $this->_getSectionItemString('mysql_unpriv_pass', true, $style, 'password'); - // unpriv-user has to be different from root - if ($this->_data['mysql_unpriv_user'] == $this->_data['mysql_root_user']) { - $style = 'blue'; - } else { - $style = ''; - } - $formdata .= $this->_getSectionItemString('mysql_root_user', true, $style); - // is we posted and no password was given -> red - if (! empty($_POST['installstep']) && $this->_data['mysql_root_pass'] == '') { - $style = 'red'; - } else { - $style = ''; - } - $formdata .= $this->_getSectionItemString('mysql_root_pass', true, $style, 'password'); - - $formdata .= $this->_getSectionItemString('mysql_ssl_ca_file', false, $style); - $formdata .= $this->_getSectionItemYesNo('mysql_ssl_verify_server_certificate', false, $style); + $formdata['db'] = [ + 'title' => $this->_lng['install']['database'], + 'fields' => [ + $this->_getSectionItemString('mysql_host', true), + $this->_getSectionItemString('mysql_database', true), + $this->_getSectionItemYesNo('mysql_forcecreate', false), + $this->_getSectionItemString('mysql_unpriv_user', true, (!empty($this->_data['mysql_unpriv_user'] ?? "") && $this->_data['mysql_unpriv_user'] == $this->_data['mysql_root_user']) ? 'red' : ''), + $this->_getSectionItemString('mysql_unpriv_pass', true, (!empty($_POST['installstep']) && $this->_data['mysql_unpriv_pass'] == '') ? 'red' : '', 'password'), + $this->_getSectionItemString('mysql_root_user', true, (!empty($this->_data['mysql_unpriv_user'] ?? "") && $this->_data['mysql_unpriv_user'] == $this->_data['mysql_root_user']) ? 'red' : ''), + $this->_getSectionItemString('mysql_root_pass', true, (!empty($_POST['installstep']) && $this->_data['mysql_root_pass'] == '') ? 'red' : '', 'password'), + $this->_getSectionItemString('mysql_ssl_ca_file', false), + $this->_getSectionItemYesNo('mysql_ssl_verify_server_certificate', false) + ] + ]; /** * admin data */ - $section = $this->_lng['install']['admin_account']; - eval("\$formdata .= \"" . $this->_getTemplate("datasection") . "\";"); - // user - $formdata .= $this->_getSectionItemString('admin_user', true); - // check for admin passwords to be equal - if (! empty($_POST['installstep']) && ($this->_data['admin_pass1'] == '' || $this->_data['admin_pass1'] != $this->_data['admin_pass2'])) { - $style = 'color:red;'; - } else { - $style = ''; - } - $formdata .= $this->_getSectionItemString('admin_pass1', true, $style, 'password'); - // check for admin passwords to be equal - if (! empty($_POST['installstep']) && ($this->_data['admin_pass2'] == '' || $this->_data['admin_pass1'] != $this->_data['admin_pass2'])) { - $style = 'color:red;'; - } else { - $style = ''; - } - $formdata .= $this->_getSectionItemString('admin_pass2', true, $style, 'password'); - // activate newsfeed? - $formdata .= $this->_getSectionItemYesNo('activate_newsfeed', true); + $formdata['admin'] = [ + 'title' => $this->_lng['install']['admin_account'], + 'fields' => [ + $this->_getSectionItemString('admin_user', true), + $this->_getSectionItemString('admin_pass1', true, (!empty($_POST['installstep']) && ($this->_data['admin_pass1'] == '' || $this->_data['admin_pass1'] != $this->_data['admin_pass2'])) ? 'red' : '', 'password'), + $this->_getSectionItemString('admin_pass2', true, (!empty($_POST['installstep']) && ($this->_data['admin_pass2'] == '' || $this->_data['admin_pass1'] != $this->_data['admin_pass2'])) ? 'red' : '', 'password'), + $this->_getSectionItemYesNo('activate_newsfeed', true) + ] + ]; /** * Server data */ - $section = $this->_lng['install']['serversettings']; - eval("\$formdata .= \"" . $this->_getTemplate("datasection") . "\";"); - // distribution - if (! empty($_POST['installstep']) && $this->_data['distribution'] == '') { - $diststyle = 'color:red;'; - } else { - $diststyle = ''; - } // show list of available distro's $distributions_select_data = []; @@ -948,73 +977,48 @@ class FroxlorInstall foreach ($distros as $_distribution) { $dist = new \Froxlor\Config\ConfigParser($_distribution); $dist_display = $dist->distributionName . " " . $dist->distributionCodename . " (" . $dist->distributionVersion . ")"; - if (!array_key_exists($dist_display, $distributions_select_data)) { - $distributions_select_data[$dist_display] = ''; - } - $distributions_select_data[$dist_display] .= str_replace(".xml", "", strtolower(basename($_distribution))); + $distributions_select_data[] = [ + 'label' => $dist_display, + 'value' => str_replace(".xml", "", strtolower(basename($_distribution))), + 'selected' => (str_replace(".xml", "", strtolower(basename($_distribution))) == ($this->_data['distribution'] ?? "")) ? true : false + ]; } // sort by distribution name - ksort($distributions_select_data); + sort($distributions_select_data); - $distributions_select = ''; - foreach ($distributions_select_data as $dist_display => $dist_index) { - // create select-box-option - $distributions_select .= \Froxlor\UI\HTML::makeoption($dist_display, $dist_index, $this->_data['distribution'] ?? ''); - // $this->_data['distribution'] - } - - $formdata .= $this->_getSectionItemSelectbox('distribution', $distributions_select, $diststyle); - - // servername - if (! empty($_POST['installstep']) && $this->_data['servername'] == '') { - $style = 'color:red;'; - } else { - $style = ''; - } - $formdata .= $this->_getSectionItemString('servername', true, $style); - // serverip - if (! empty($_POST['installstep']) && ($this->_data['serverip'] == '' || $this->_validate_ip($this->_data['serverip']) == false)) { - $style = 'color:red;'; - } else { - $style = ''; - } - $formdata .= $this->_getSectionItemString('serverip', true, $style); - // webserver - if (! empty($_POST['installstep']) && $this->_data['webserver'] == '') { - $websrvstyle = 'color:red;'; - } else { - $websrvstyle = ''; - } - // apache - $formdata .= $this->_getSectionItemCheckbox('webserver', 'apache2', ($this->_data['webserver'] == 'apache2'), $websrvstyle); - $formdata .= $this->_getSectionItemCheckbox('webserver', 'apache24', ($this->_data['webserver'] == 'apache24'), $websrvstyle); - // lighttpd - $formdata .= $this->_getSectionItemCheckbox('webserver', 'lighttpd', ($this->_data['webserver'] == 'lighttpd'), $websrvstyle); - // nginx - $formdata .= $this->_getSectionItemCheckbox('webserver', 'nginx', ($this->_data['webserver'] == 'nginx'), $websrvstyle); - // webserver-user - if (! empty($_POST['installstep']) && $this->_data['httpuser'] == '') { - $style = 'color:red;'; - } else { - $style = ''; - } - $formdata .= $this->_getSectionItemString('httpuser', true, $style); - // webserver-group - if (! empty($_POST['installstep']) && $this->_data['httpgroup'] == '') { - $style = 'color:red;'; - } else { - $style = ''; - } - $formdata .= $this->_getSectionItemString('httpgroup', true, $style); - - // get data-form-template - $language = htmlspecialchars($this->_activelng); - eval("\$content .= \"" . $this->_getTemplate("dataform2") . "\";"); + $formdata['server'] = [ + 'title' => $this->_lng['install']['serversettings'], + 'fields' => [ + $this->_getSectionItemSelectbox('distribution', $distributions_select_data, (!empty($_POST['installstep']) && $this->_data['distribution'] == '') ? 'red' : ''), + $this->_getSectionItemString('servername', true, (!empty($_POST['installstep']) && $this->_data['servername'] == '') ? 'red' : ''), + $this->_getSectionItemString('serverip', true, (!empty($_POST['installstep']) && ($this->_data['serverip'] == '' || $this->_validate_ip($this->_data['serverip']) == false)) ? 'red' : ''), + $this->_getSectionItemYesNo('use_ssl', true), + [ + 'label' => $this->_lng['install']['webserver'], + 'fields' => [ + $this->_getSectionItemCheckbox('webserver', 'apache2', (isset($this->_data['webserver']) && $this->_data['webserver'] == 'apache2'), (!empty($_POST['installstep']) && $this->_data['webserver'] == '') ? 'red' : ''), + $this->_getSectionItemCheckbox('webserver', 'apache24', (isset($this->_data['webserver']) && $this->_data['webserver'] == 'apache24'), (!empty($_POST['installstep']) && $this->_data['webserver'] == '') ? 'red' : ''), + $this->_getSectionItemCheckbox('webserver', 'lighttpd', (isset($this->_data['webserver']) && $this->_data['webserver'] == 'lighttpd'), (!empty($_POST['installstep']) && $this->_data['webserver'] == '') ? 'red' : ''), + $this->_getSectionItemCheckbox('webserver', 'nginx', (isset($this->_data['webserver']) && $this->_data['webserver'] == 'nginx'), (!empty($_POST['installstep']) && $this->_data['webserver'] == '') ? 'red' : '') + ] + ], + $this->_getSectionItemString('httpuser', true, (!empty($_POST['installstep']) && $this->_data['httpuser'] == '') ? 'red' : ''), + $this->_getSectionItemString('httpgroup', true, (!empty($_POST['installstep']) && $this->_data['httpgroup'] == '') ? 'red' : '') + ] + ]; $navigation = ''; return array( - 'pagecontent' => $content, + 'pagecontent' => [ + 'form' => [ + 'formaction' => $formaction, + 'languages' => $this->_languages, + 'activelang' => $this->_activelng, + 'data' => $formdata, + 'result' => $check_result + ] + ], 'pagenavigation' => $navigation ); } @@ -1028,19 +1032,20 @@ class FroxlorInstall * optional css * @param string $type * optional type of input-box (default: text) - * - * @return string + * + * @return array */ private function _getSectionItemString($fieldname = null, $required = false, $style = "", $type = 'text') { - $fieldlabel = $this->_lng['install'][$fieldname]; - $fieldvalue = htmlspecialchars($this->_data[$fieldname]); - if ($required) { - $required = ' required="required"'; - } - $sectionitem = ""; - eval("\$sectionitem .= \"" . $this->_getTemplate("dataitem") . "\";"); - return $sectionitem; + return [ + 'type' => $type, + 'id' => $fieldname, + 'name' => $fieldname, + 'value' => htmlspecialchars(($this->_data[$fieldname] ?? "")), + 'label' => $this->_lng['install'][$fieldname], + 'required' => $required, + 'style' => $style + ]; } /** @@ -1050,18 +1055,19 @@ class FroxlorInstall * @param boolean $checked * @param string $style * - * @return string + * @return array */ private function _getSectionItemCheckbox($groupname = null, $fieldname = null, $checked = false, $style = "") { - $groupname = $this->_lng['install'][$groupname]; - $fieldlabel = $this->_lng['install'][$fieldname]; - if ($checked) { - $checked = 'checked="checked"'; - } - $sectionitem = ""; - eval("\$sectionitem .= \"" . $this->_getTemplate("dataitemchk") . "\";"); - return $sectionitem; + return [ + 'type' => 'radio', + 'id' => $fieldname, + 'name' => $groupname, + 'value' => $fieldname, + 'label' => $this->_lng['install'][$fieldname], + 'checked' => $checked, + 'style' => $style + ]; } /** @@ -1071,15 +1077,18 @@ class FroxlorInstall * @param boolean $options * @param string $style * - * @return string + * @return array */ - private function _getSectionItemSelectbox($fieldname = null, $options = null, $style = "") + private function _getSectionItemSelectbox($fieldname = null, array $options = [], $style = "") { - $fieldlabel = $this->_lng['install'][$fieldname]; - - $sectionitem = ""; - eval("\$sectionitem .= \"" . $this->_getTemplate("dataitemselect") . "\";"); - return $sectionitem; + return [ + 'type' => 'select', + 'id' => $fieldname, + 'name' => $fieldname, + 'label' => $this->_lng['install'][$fieldname], + 'options' => $options, + 'style' => $style + ]; } /** @@ -1089,17 +1098,19 @@ class FroxlorInstall * @param boolean $checked * @param string $style * - * @return string + * @return array */ private function _getSectionItemYesNo($fieldname = null, $checked = false, $style = "") { - $fieldlabel = $this->_lng['install'][$fieldname]; - if ($checked) { - $checked = 'checked="checked"'; - } - $sectionitem = ""; - eval("\$sectionitem .= \"" . $this->_getTemplate("dataitemyesno") . "\";"); - return $sectionitem; + return [ + 'type' => 'checkbox', + 'id' => $fieldname, + 'name' => $fieldname, + 'label' => $this->_lng['install'][$fieldname], + 'value' => 1, + 'checked' => $checked, + 'style' => $style + ]; } /** @@ -1107,35 +1118,46 @@ class FroxlorInstall */ private function _requirementCheck() { - // indicator whether we need to abort or not $_die = false; - $content = ""; + // check results + $content = []; // check for correct php version - $content .= $this->_status_message('begin', $this->_lng['requirements']['phpversion']); + $check = [ + 'title' => $this->_lng['requirements']['phpversion'], + 'result' => 0 + ]; if (version_compare("7.1.0", PHP_VERSION, ">=")) { - $content .= $this->_status_message('red', $this->_lng['requirements']['notfound'] . ' (' . PHP_VERSION . ')'); + $check['result'] = 1; + $check['result_txt'] = $this->_lng['requirements']['notfound'] . ' (' . PHP_VERSION . ')'; $_die = true; } else { if (version_compare("7.4.0", PHP_VERSION, ">=")) { - $content .= $this->_status_message('orange', $this->_lng['requirements']['newerphpprefered'] . ' (' . PHP_VERSION . ')'); + $check['result'] = 2; + $check['result_txt'] = $this->_lng['requirements']['newerphpprefered'] . ' (' . PHP_VERSION . ')'; } else { - $content .= $this->_status_message('green', PHP_VERSION); + $check['result_txt'] = PHP_VERSION; } } + $content[] = $check; // check for php_pdo and pdo_mysql - $content .= $this->_status_message('begin', $this->_lng['requirements']['phppdo']); + $check = [ + 'title' => $this->_lng['requirements']['phppdo'], + 'result' => 0 + ]; - if (! extension_loaded('pdo') || in_array("mysql", PDO::getAvailableDrivers()) == false) { - $content .= $this->_status_message('red', $this->_lng['requirements']['notinstalled']); + if (!extension_loaded('pdo') || in_array("mysql", PDO::getAvailableDrivers()) == false) { + $check['result'] = 1; + $check['result_txt'] = $this->_lng['requirements']['notinstalled']; $_die = true; } else { - $content .= $this->_status_message('green', $this->_lng['requirements']['installed']); + $check['result_txt'] = $this->_lng['requirements']['installed']; } + $content[] = $check; // check for session-extension $this->_requirementCheckFor($content, $_die, 'session', false, 'phpsession'); @@ -1171,78 +1193,83 @@ class FroxlorInstall $this->_requirementCheckFor($content, $_die, 'zip', true, 'phpzip', 'zipdescription'); // check for open_basedir - $content .= $this->_status_message('begin', $this->_lng['requirements']['openbasedir']); + $check = [ + 'title' => $this->_lng['requirements']['openbasedir'], + 'result' => 0 + ]; $php_ob = @ini_get("open_basedir"); - if (! empty($php_ob) && $php_ob != '') { - $content .= $this->_status_message('orange', $this->_lng['requirements']['activated'] . "
" . $this->_lng['requirements']['openbasedirenabled']); + if (!empty($php_ob) && $php_ob != '') { + $check['result'] = 2; + $check['result_txt'] = $this->_lng['requirements']['activated']; + $check['result_desc'] = $this->_lng['requirements']['openbasedirenabled']; } else { - $content .= $this->_status_message('green', 'off'); + $check['result_txt'] = 'off'; } + $content[] = $check; // check for mysqldump binary in order to backup existing database - $content .= $this->_status_message('begin', $this->_lng['requirements']['mysqldump']); - + $check = [ + 'title' => $this->_lng['requirements']['mysqldump'], + 'result' => 0 + ]; if (file_exists("/usr/bin/mysqldump") || file_exists("/usr/local/bin/mysqldump")) { - $content .= $this->_status_message('green', $this->_lng['requirements']['installed']); + $check['result_txt'] = $this->_lng['requirements']['installed']; } else { - $content .= $this->_status_message('orange', $this->_lng['requirements']['notinstalled'] . "
" . $this->_lng['requirements']['mysqldumpmissing']); + $check['result'] = 2; + $check['result_txt'] = $this->_lng['requirements']['notinstalled']; + $check['result_desc'] = $this->_lng['requirements']['mysqldumpmissing']; } - - $content .= "
"; + $content[] = $check; // check if we have unrecoverable errors $navigation = ''; if ($_die) { - $msgcolor = 'red'; $message = $this->_lng['requirements']['diedbecauseofrequirements']; $link = htmlspecialchars($_SERVER['PHP_SELF']); $linktext = $this->_lng['click_here_to_refresh']; } else { - $msgcolor = 'green'; $message = $this->_lng['requirements']['froxlor_succ_checks']; $link = htmlspecialchars($_SERVER['PHP_SELF']) . '?check=1'; $linktext = $this->_lng['click_here_to_continue']; } - eval("\$navigation .= \"" . $this->_getTemplate("pagebottom") . "\";"); return array( - 'pagecontent' => $content, - 'pagenavigation' => $navigation + 'pagecontent' => [ + 'checks' => $content + ], + 'pagenavigation' => [ + 'bad' => $_die, + 'message' => $message, + 'link' => $link, + 'linktext' => $linktext + ] ); } - private function _requirementCheckFor(&$content, &$_die, $ext = '', $optional = false, $lng_txt = "", $lng_desc = "") + private function _requirementCheckFor(array &$content, bool &$_die, string $ext = "", bool $optional = false, string $lng_txt = "", string $lng_desc = "") { - $content .= $this->_status_message('begin', $this->_lng['requirements'][$lng_txt]); + $check = [ + 'title' => $this->_lng['requirements'][$lng_txt], + 'result' => 0, + 'result_txt' => '', + 'result_desc' => '' + ]; - if (! extension_loaded($ext)) { - if (! $optional) { - $content .= $this->_status_message('red', $this->_lng['requirements']['notinstalled']); + if (!extension_loaded($ext)) { + if (!$optional) { + $check['result'] = 1; + $check['result_txt'] = $this->_lng['requirements']['notinstalled']; $_die = true; } else { - $content .= $this->_status_message('orange', $this->_lng['requirements']['notinstalled'] . "
" . $this->_lng['requirements'][$lng_desc]); + $check['result'] = 2; + $check['result_txt'] = $this->_lng['requirements']['notinstalled']; + $check['result_desc'] = $this->_lng['requirements'][$lng_desc]; } } else { - $content .= $this->_status_message('green', $this->_lng['requirements']['installed']); + $check['result_txt'] = $this->_lng['requirements']['installed']; } - } - /** - * send no-caching headers and set the default timezone - */ - private function _sendHeaders() - { - if (@php_sapi_name() !== 'cli') { - // no caching - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Pragma: no-cache"); - header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', time())); - header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time())); - } - // ensure that default timezone is set - if (function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get")) { - @date_default_timezone_set(@date_default_timezone_get()); - } + $content[] = $check; } /** @@ -1258,10 +1285,9 @@ class FroxlorInstall require_once $this->_basepath . '/lib/userdata.inc.php'; if (isset($sql) && is_array($sql)) { - // use sparkle theme for the notice - $installed_hint = file_get_contents($this->_basepath . '/templates/Sparkle/misc/alreadyinstalledhint.tpl'); - $installed_hint = str_replace("", date('Y', time()), $installed_hint); - die($installed_hint); + // installation not necessary - redirect to login + header("Location: ../index.php"); + exit(); } } } @@ -1312,49 +1338,8 @@ class FroxlorInstall $this->_lng = $lng; } } - } - /** - * Get template from filesystem - * - * @param string $template - * name of the template including subdirectory - * - * @return string - */ - private function _getTemplate($template = null) - { - // build filename - $filename = $this->_basepath . '/install/templates/' . $template . '.tpl'; - // check existence - if (file_exists($filename) && is_readable($filename)) { - $templatefile = addcslashes(file_get_contents($filename), '"\\'); - // loop through template more than once in case we have an "if"-statement in another one - while (preg_match('/(.*)(<\/if>|(.*)<\/if>)/Uis', $templatefile)) { - $templatefile = preg_replace('/(.*)(<\/if>|(.*)<\/if>)/Uis', '".( ($1) ? ("$2") : ("$4") )."', $templatefile); - } - } else { - $templatefile = 'TEMPLATE NOT FOUND: ' . $filename; - } - - return $templatefile; - } - - /** - * output status - * - * @param string $case - * @param string $text - * - * @return string - */ - private function _status_message($case, $text) - { - if ($case == 'begin') { - return '' . $text; - } else { - return '' . $text . ''; - } + UI::setLng($lng); } /** @@ -1363,11 +1348,11 @@ class FroxlorInstall private function _guessServerName() { // from form? - if (! empty($_POST['servername'])) { + if (!empty($_POST['servername'])) { $this->_data['servername'] = $_POST['servername']; return; // from $_SERVER - } else if (! empty($_SERVER['SERVER_NAME'])) { + } else if (!empty($_SERVER['SERVER_NAME'])) { // no ips if ($this->_validate_ip($_SERVER['SERVER_NAME']) == false) { $this->_data['servername'] = $_SERVER['SERVER_NAME']; @@ -1384,12 +1369,12 @@ class FroxlorInstall private function _guessServerIP() { // from form - if (! empty($_POST['serverip'])) { + if (!empty($_POST['serverip'])) { $this->_data['serverip'] = $_POST['serverip']; $this->_data['serverip'] = inet_ntop(inet_pton($this->_data['serverip'])); return; // from $_SERVER - } elseif (! empty($_SERVER['SERVER_ADDR'])) { + } elseif (!empty($_SERVER['SERVER_ADDR'])) { $this->_data['serverip'] = $_SERVER['SERVER_ADDR']; $this->_data['serverip'] = inet_ntop(inet_pton($this->_data['serverip'])); return; @@ -1404,7 +1389,7 @@ class FroxlorInstall private function _guessWebserver() { // post - if (! empty($_POST['webserver'])) { + if (!empty($_POST['webserver'])) { $this->_data['webserver'] = $_POST['webserver']; } else { if (strtoupper(@php_sapi_name()) == "APACHE2HANDLER" || stristr($_SERVER['SERVER_SOFTWARE'], "apache/2")) { @@ -1426,15 +1411,15 @@ class FroxlorInstall private function _guessDistribution() { // post - if (! empty($_POST['distribution'])) { + if (!empty($_POST['distribution'])) { $this->_data['distribution'] = $_POST['distribution']; } else { // set default os. $os_dist = array( - 'ID' => 'buster' + 'ID' => 'bullseye' ); $os_version = array( - '0' => '10' + '0' => '11' ); // read os-release @@ -1443,7 +1428,8 @@ class FroxlorInstall $os_dist_arr = explode("\n", $os_dist_content); $os_dist = []; foreach ($os_dist_arr as $os_dist_line) { - if (empty(trim($os_dist_line))) continue; + if (empty(trim($os_dist_line))) + continue; $tmp = explode("=", $os_dist_line); $os_dist[$tmp[0]] = str_replace('"', "", trim($tmp[1])); } @@ -1480,7 +1466,7 @@ class FroxlorInstall $this->_data[$fieldname] = $default; } // check field - if (! empty($_POST[$fieldname])) { + if (!empty($_POST[$fieldname])) { $this->_data[$fieldname] = $_POST[$fieldname]; } } @@ -1514,7 +1500,7 @@ class FroxlorInstall $sql = ""; $linecount = count($lines); $output = ""; - for ($i = 0; $i < $linecount; $i ++) { + for ($i = 0; $i < $linecount; $i++) { if ($i != ($linecount - 1) || strlen($lines[$i]) > 0) { if (substr($lines[$i], 0, 1) != "#") { $output .= $lines[$i] . "\n"; @@ -1550,7 +1536,7 @@ class FroxlorInstall // this is faster than calling count($tokens) every time through the loop. $token_count = count($tokens); - for ($i = 0; $i < $token_count; $i ++) { + for ($i = 0; $i < $token_count; $i++) { // Don't want to add an empty string as the last thing in the array. if (($i != ($token_count - 1)) || (strlen($tokens[$i] > 0))) { // This is the total number of single quotes in the token. @@ -1576,7 +1562,7 @@ class FroxlorInstall $tokens[$i] = ""; // Do we have a complete statement yet? $complete_stmt = false; - for ($j = $i + 1; (! $complete_stmt && ($j < $token_count)); $j ++) { + for ($j = $i + 1; (!$complete_stmt && ($j < $token_count)); $j++) { // This is the total number of single quotes in the token. $total_quotes = preg_match_all("/'/", $tokens[$j], $matches); // Counts single quotes that are preceded by an odd number of backslashes, diff --git a/install/lng/english.lng.php b/install/lng/english.lng.php index 081de41b..98629ad7 100644 --- a/install/lng/english.lng.php +++ b/install/lng/english.lng.php @@ -58,7 +58,7 @@ $lng['install']['mysql_unpriv_user'] = 'Username for the unprivileged MySQL-acco $lng['install']['mysql_unpriv_pass'] = 'Password for the unprivileged MySQL-account'; $lng['install']['mysql_root_user'] = 'Username for the MySQL-root-account'; $lng['install']['mysql_root_pass'] = 'Password for the MySQL-root-account'; -$lng['install']['mysql_ssl_ca_file'] = 'MySQL server certificate file path'; +$lng['install']['mysql_ssl_ca_file'] = 'MySQL server certificate file path
(optional)'; $lng['install']['mysql_ssl_verify_server_certificate'] = 'Verify MySQL TLS certificate'; $lng['install']['admin_account'] = 'Administrator Account'; $lng['install']['admin_user'] = 'Administrator Username'; @@ -76,6 +76,7 @@ $lng['install']['lighttpd'] = 'LigHTTPd'; $lng['install']['nginx'] = 'NGINX'; $lng['install']['httpuser'] = 'HTTP username'; $lng['install']['httpgroup'] = 'HTTP groupname'; +$lng['install']['use_ssl'] = 'Enable SSL via port 443'; $lng['install']['testing_mysql'] = 'Checking MySQL-root access...'; $lng['install']['testing_mysql_fail'] = 'There seems to be a problem with the database-connection. Cannot continue. Please go back and check your credentials.'; @@ -95,6 +96,7 @@ $lng['install']['creating_configfile'] = 'Creating configfile...'; $lng['install']['creating_configfile_temp'] = 'File was saved in %s, please move to ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php'; $lng['install']['creating_configfile_failed'] = 'Could not create ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php, please create it manually with the following content:'; $lng['install']['froxlor_succ_installed'] = 'Froxlor was installed successfully.'; +$lng['install']['failed'] = 'failed'; $lng['click_here_to_refresh'] = 'Click here to check again'; $lng['click_here_to_goback'] = 'Click here to go back'; diff --git a/install/lng/german.lng.php b/install/lng/german.lng.php index 86c97d3c..52455512 100644 --- a/install/lng/german.lng.php +++ b/install/lng/german.lng.php @@ -58,7 +58,7 @@ $lng['install']['mysql_unpriv_user'] = 'Benutzername für den unprivilegierten M $lng['install']['mysql_unpriv_pass'] = 'Passwort für den unprivilegierten MySQL-Account'; $lng['install']['mysql_root_user'] = 'Benutzername für den MySQL-Root-Account'; $lng['install']['mysql_root_pass'] = 'Passwort für den MySQL-Root-Account'; -$lng['install']['mysql_ssl_ca_file'] = 'MySQL-Server Zertifikatspfad'; +$lng['install']['mysql_ssl_ca_file'] = 'MySQL-Server Zertifikatspfad
(optional)'; $lng['install']['mysql_ssl_verify_server_certificate'] = 'Validieren des MySQL-Server Zertifikats'; $lng['install']['admin_account'] = 'Admin-Zugang'; $lng['install']['admin_user'] = 'Administrator-Benutzername'; @@ -76,6 +76,7 @@ $lng['install']['lighttpd'] = 'LigHTTPd'; $lng['install']['nginx'] = 'NGINX'; $lng['install']['httpuser'] = 'HTTP Username'; $lng['install']['httpgroup'] = 'HTTP Gruppenname'; +$lng['install']['use_ssl'] = 'Aktiviere SSL via Port 443'; $lng['install']['testing_mysql'] = 'Teste MySQL-Root Zugang...'; $lng['install']['testing_mysql_fail'] = 'Bei der Verwendung der Datenbank gibt es scheinbar Probleme. Installation kann nicht fortgesetzt werden. Bitte Zugangsdaten prüfen und erneut versuchen.'; @@ -95,6 +96,7 @@ $lng['install']['creating_configfile'] = 'Erstelle Konfigurationsdatei...'; $lng['install']['creating_configfile_temp'] = 'Datei wurde in %s gespeichert, bitte nach ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php verschieben.'; $lng['install']['creating_configfile_failed'] = 'Konnte ' . dirname(dirname(__DIR__)) . '/lib/userdata.inc.php nicht erstellen, bitte manuell mit folgendem Inhalt anlegen:'; $lng['install']['froxlor_succ_installed'] = 'Froxlor wurde erfolgreich installiert.'; +$lng['install']['failed'] = 'fehlgeschlagen'; $lng['click_here_to_refresh'] = 'Hier klicken, um erneut zu prüfen'; $lng['click_here_to_goback'] = 'Einen Schritt zurück'; diff --git a/install/templates/assets/css/install.css b/install/templates/assets/css/install.css deleted file mode 100644 index ccc8ccba..00000000 --- a/install/templates/assets/css/install.css +++ /dev/null @@ -1,637 +0,0 @@ -@charset "UTF-8"; -/* RESET */ -html, body, div, ul, ol, li, dl, dt, dd, h1, h2, h3, h4, h5, h6, pre, - form, p, blockquote, fieldset, input { - margin: 0; - padding: 0; -} - -h1, h2, h3, h4, h5, h6, pre, code, address, caption, cite, code, em, - strong, th { - font-size: 1em; - font-weight: 400; - font-style: normal; -} - -ul, ol { - list-style: none; -} - -fieldset, img { - border: none; -} - -caption, th { - text-align: left; -} - -table { - border-collapse: collapse; - border-spacing: 0; -} - -article, aside, details, figcaption, figure, footer, header, hgroup, - menu, nav, section { - display: block; -} - -/* TYPE */ -html, body { - font: 12px/18px 'Lucida Grande', 'Lucida Sans Unicode', Helvetica, Arial, - Verdana, sans-serif; - background-color: #f5f5f5; - color: #444; - -webkit-font-smoothing: subpixel-antialiased; -} - -body { - margin: 0; - padding: 0; -} - -.dark { - background-color: #e9edf0; - border-bottom: 1px solid #d1d5d8; -} - -header img { - padding: 10px 0 10px 10px; -} - -h1 { - display: none; -} - -h2, h3 { - margin: 0 0 1em 0; - padding: 0; - font-weight: bold; -} - -h2 { - font-size: 17px; -} - -h3 { - font-size: 15px; -} - -img { - border: 0; - vertical-align: middle; -} - -td a { - text-decoration: none; -} - -.bradius { - border-radius: 5px 5px 5px 5px; - box-shadow: rgba(0, 0, 0, 0.34902) 0 1px 3px 0; -} - -/* FOOTER */ -footer { - clear: both; - text-align: center; - color: #888; - font-size: 10px !important; - margin: 10px 0; -} - -footer a, footer a:active, footer a:visited { - color: #888; -} - -.install { - background-color: #fff; - margin: 20px auto 12px; - width: 800px; -} - -p { - margin: 0 10px !important; -} - -.installsec { - margin-top: 10px; - padding: 0; - text-align: left; -} - -.installsec table { - width: 100%; - padding: 0 10px; - margin: 15px 0 15px 0; -} - -.installsec h2 { - display: block; - border-bottom: 1px solid #d1d5d8; - margin: 0; - padding: 5px 15px 15px 15px; -} - -.installsec form { - width: 800px; - margin: 0 auto; - padding: 10px 0 0; - text-align: left; -} - -.installsec fieldset { - border: 0; - float: left; - clear: left; - width: 600px; - margin: 0 100px 10px; - padding: 0; -} - -.installsec fieldset p, .installsec fieldset h3 { - clear: both; -} - -.installsec legend { - display: none; -} - -.installsec label { - float: left; - margin-right: 0; - margin-top: 8px; - text-align: left; -} - -p.submit { - text-align: right; - padding-right: 46px; -} - -.installsec aside { - border-top: 1px solid #d1d5d8; - clear: both; - float: none; - width: auto; - text-align: right; - padding: 10px; -} - -.line { - border: 0; - width: 800px; - border-bottom: 1px solid #d1d5d8; -} - -.messagewrapper { - width: 650px; - margin: 0 auto; - padding: 120px 0 0; - overflow: hidden; -} - -.messagewrapperfull { - width: 100%; - margin: 0 auto; - padding: 0; - overflow: hidden; -} - -.overviewsearch { - position: absolute; - top: 155px; - right: 36px; - font-size: 80%; -} - -.overviewadd { - padding: 10px; - font-weight: 700; -} - -/* - * error message display - */ -.errorcontainer { - background: url(../img/icons/error_big.png) 10px center no-repeat - #ffedef; - border: 1px solid #ffc2ca; - padding: 10px 10px 10px 68px !important; - margin: 10px 0 10px 0 !important; - text-align: left !important; - overflow: hidden; - box-shadow: 0 0 0 black; -} - -.errortitle { - font-weight: 700; - color: #c00 !important; -} - -.error { - font-weight: 400 !important; - color: #c00 !important; -} - -/* - * warning message display - */ -.warningcontainer, .ui-dialog { - background: url(../img/icons/warning_big.png) 10px center no-repeat - #fffecc; - border: 1px solid #f3c37e; - padding: 10px 10px 10px 68px !important; - margin: 10px 0 10px 0 !important; - text-align: left !important; - overflow: hidden; - box-shadow: 0 0 0 black; -} - -.ui-dialog { - padding: 10px !important; -} - -.warningtitle, .ui-dialog-titlebar { - font-weight: 700; - color: #D57D00; -} - -.warning, .ui-dialog-content { - color: #D57D00 !important; -} - -/* - * success message display - */ -.successcontainer { - background: url(../img/icons/ok_big.png) 10px center no-repeat #E2F9E3; - border: 1px solid #9C9; - padding: 10px 10px 10px 68px !important; - margin: 10px 0 10px 0 !important; - text-align: left !important; - overflow: hidden; - box-shadow: 0 0 0 black; -} - -.successtitle { - font-weight: 700; - color: #060 !important; -} - -.success { - font-weight: 400 !important; -} - -/* - * neutral/info message display - */ -.neutralcontainer { - background: url(../img/icons/info_big.png) 10px center no-repeat #d2eaf6; - border: 1px solid #b7d8ed; - padding: 10px 10px 10px 68px !important; - margin: 10px 0 10px 0 !important; - text-align: left !important; - overflow: hidden; - box-shadow: 0 0 0 black; -} - -.neutraltitle { - font-weight: 700; - color: #3188c1 !important; -} - -.neutral { - font-weight: 400 !important; - color: #3188c1 !important; -} - -/* std hyperlink */ -a, a:active, a:visited { - color: #176fa1; - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -.infotext { - font-size: 11px; -} - -/* - * main container - */ -.main { - margin: 105px 10px 0 240px; - background-color: #fff; - padding: 30px 30px 30px 30px; - min-height: 400px; -} - -.noborder { - width: 100%; - border-spacing: 0; - border-collapse: separate; - border: 0; -} - -.noborder td { - border: 0; -} - -table { - width: 100%; - border-spacing: 0; - border: 1px solid #d1d5d8; - border-collapse: separate; - box-shadow: 0 0 0 black !important; -} - -table thead th, table th { - border-top: 1px solid #d1d5d8; - border-bottom: 1px solid #d1d5d8; - height: 25px !important; - padding: 5px 0 5px 8px; - background-color: #e9edf0; - font-weight: bold; -} - -table thead:first-child th, table:first-child th { - border-top: none !important; -} - -table th { - border-top: 0; -} - -th a:hover { - text-decoration: none; -} - -th a img { - -} - -th a:nth-child(odd) img { - position: relative; - top: -5px; - left: 4px; -} - -th a:nth-child(even) img { - position: relative; - top: 3px; - left: -7px; -} - -table thead:first-child th { - border-top: 0; -} - -.disabled td, .disabled td a { - color: #cfcfcf; -} - -table tbody td { - border-bottom: 1px dotted #ccc; -} - -table tbody tr:last-child td { - border-bottom: 0; -} - -.formtable { - width: 100%; - border-spacing: 0; - border: 0; - border-collapse: separate; - margin: 0 0 0; -} - -.formtable tbody td { - border: 0; - border-bottom: 1px dotted #ccc; - min-height: 20px; -} - -.formtable label { - float: none; - display: block; - padding: 0; - margin: 0; - width: 100%; - text-align: left; -} - -td { - padding: 5px 10px; - min-height: 20px; -} - -table tfoot td { - height: 25px; - border-top: 1px solid #d1d5d8; - background-color: #f2f8fa; -} - -.tfootleft { - text-align: left; -} - -.maintitle { - padding-top: 20px; -} - -/* input elements */ -input { - background: #fff url(../img/text_align_left.png) no-repeat 5px 4px; - color: #333; - padding: 2px 4px 2px 24px; - height: 22px; - border: 1px solid #d9d9d9; - margin-bottom: 5px; - border-radius: 3px; -} - -textarea { - background: #fff url(../img/text_align_left.png) no-repeat 5px 4px; - color: #333; - padding: 4px 4px 2px 24px; - border: 1px solid #d9d9d9; - margin-bottom: 5px; - border-radius: 3px; -} - -input[type="password"] { - background: #fff url(../img/password.png) no-repeat 5px 4px; -} - -/* - * BUTTONS - */ -input[type="button"], input[type="submit"], input[type="reset"] { - margin: 0 5px; - padding: 5px 14px; - outline: 0; - border: 0; - background-color: #eee; - min-width: 80px; - height: 26px; - background-image: none; -} - -.loginsec input[type="button"], .loginsec input[type="submit"], - .loginsec input[type="reset"] { - margin: 0 1px; -} - -input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover - { - color: #333; - background-color: #dcdcdc; -} - -input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active - { - -webkit-box-shadow: inset 0 1px 8px rgba(0, 0, 0, 0.25); - -moz-box-shadow: inset 0 1px 8px rgba(0, 0, 0, 0.25); - box-shadow: inset 0 1px 8px rgba(0, 0, 0, 0.25); - color: white !important; -} - -input[type="submit"], input[class="yesbutton"] { - color: white; - background-color: #35aa47; -} - -input[type="submit"]:hover, input[class="yesbutton"]:hover { - color: white; - background-color: #1d943b; -} - -input[class="submit"]:active, input[class="yesbutton"]:active { - background-color: #35aa47; -} - -input[class="nobutton"], input[type="reset"] { - color: white; - background-color: #d84a38; -} - -input[class="nobutton"]:hover, input[type="reset"]:hover { - color: white; - background-color: #c53727; -} - -input[class="nobutton"]:active, input[type="reset"]:active { - background-color: #dd4b39; -} - -input[type="checkbox"] { - background: #dae7ee; - padding: 0; - margin: 0 5px 0 0; - vertical-align: middle; - height: 26px; -} - -input[type="radio"] { - vertical-align: middle; - margin: 0 10px 0 10px; - height: 22px; -} - -select { - background: #fff; - padding: 4px; - color: #333; - border: 1px solid #d9d9d9; - margin-bottom: 5px; - min-width: 100px; -} - -select.dropdown { - padding: 2px 4px 2px 24px; - height: 26px; - border: 1px solid #d9d9d9; - margin-bottom: 5px; - border-radius: 3px; - background: url(../../../../templates/Sparkle/assets/img/icons/down.png) - no-repeat 9px; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; -} - -.maintable { - width: 90%; -} - -.update_progess { - padding: 2em; - text-align: left; -} - -.preconfig { - text-align: left; - margin-top: 20px; - margin-bottom: 5px; - margin-right: 15px; - margin-left: 15px; -} - -.preconfigitem { - padding: .15em; - border-bottom: 1px solid #ccc; -} - -.preconfdesc { - display: block; - margin-bottom: .5em; - font-size: 120%; -} - -.installprogress { - width: 100%; - background-color: #e4e4e4; - height: 5px; - border-bottom: 1px solid #d1d5d8; -} - -.installprogress .bar { - background-color: #35aa47; - height: 5px; -} - -.red { - color: #ff0000; -} - -.green { - color: green; -} - -.orange { - color: orange; -} - -.blue { - color: blue; -} - -.install-block { - width: 65%; -} - -.install-step { - width: 250px; -} - -.install-h3 { - text-align: center; -} - -.install-text { - margin: 20px 20px 0 !important; -} \ No newline at end of file diff --git a/install/templates/assets/img/favicon.ico b/install/templates/assets/img/favicon.ico deleted file mode 100644 index 84b71747595196de1917abc084423bd8d8af5638..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1386 zcmeHENlz0{5dJ_>)C#!af-J>iv5FfYf+C<6TtIyl3zbEYq5^_Qyr5BH0>p?1gG3V# z3Lbzqra4gK50JY=JXhD7hznIfRC@^F*!C2N#0%bRwZJ3v>p9rd^G0^FvLKhs@w2rQ-QC@2D+q^7Cd0(9F7%6EQjMl4M>gdkfK)1_9GU3+oQBbcCv-*z zy>^1?!PBTU%C<& zBCz8H^7-ezT^$^JO6F`UO&1}_5YDPO3AT2vAwqK5!hl>*BKSO^2{Jb@Q diff --git a/install/templates/assets/img/logo.png b/install/templates/assets/img/logo.png deleted file mode 100644 index 58ced30f53b6437c8c27cea3246e26f031a8edbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2606 zcmV+}3eok6P)Fd|u;ZU{W-Q?z3zUr31)^)kr?eX$cxa7Ck z=%cl}Tfyx`YIZ%I&GYs4GLgd7>hmRmv{-qB_4xTAeXxa{rEJFRT$#J;_4#|nvknZcKrJuV(c0bn{QXy~)JmbtNvzsjqQ#J= ztvh0Ga*mgw&En(m_DHMPzs%4ngR>${T=@F?L8H<>k-R8|xMr-+MWxdD`}|C=-O%Ih zMW@zGsnndXw&wEqOs&~>uFPM!->uv4QFDJxZ+kwU&qt}(PqW}luG}k%yEBu+JebA2 z-|w)`-$SL;F_yeSaefw zW^{L9a%BKPWN%_+AW3auXJt}lVPtu6$z?nM00=HgL_t(|+U1=4PZ~=U$9G-94n~L~ z#z=ewi%C&QTTw)#5+8sOiB{t))(WClt+rR=tG({ueqmvD=bSye`07nuzCYnS&dz*x z=FFMdT_sjiC*P*0zcI&4s#Tyd)Z5$puD3TdUDqT|LL={VjWpITiAI5g#$vioN%SHR z&K?%hQ$RQxh4ds4B^05$BSC|BH`3l%XC!(@tkfQ=D-wh4BlU(tdNK&7qL641_G$^$ z35mg$_Buo%Q6OrQmO~`DSavBQB z1j0gE$3v|+#a7u!G!rkWCn6``7zt|-Q>}a2KE2r}(b{Z_!mmiGptR@jbt0RqT%+mL zNPKQ?t*W_M|H)OX99a~Fq-LL`-KJk-Dpcz4k!Y%3LU}C`0*FBt!YGQ1TA`4DqS+Ef z0CRX#Bt93Lxn@pS%=oLKVs$PIiy1{4#pEyb4U?FiG5R-L_8AC8anDSw#Ee2An@5DI z`ritP?TwIIc0Ho z25Og|=lTvo^03J$=O9J?p9SzWNvzLr7^?IwcCZ1p%NNbqHb`H>qr%UuS0wRRb8dH)#LuNeLG#{9;`|}d?kun81H})we00NdZgjnPpsc*+G31`S7H=30 zbw`6a-lfTufXJWMs!fU`ED_fd15ry7C36aCjq4PvliJZsdIsh^e_ronwHfO`2d=I!}X{ zxXe6p{ySeL;rp}%RPC{M3nnl9)F1o|AHbY}HnGS1+&Ci9!y7D58cnQ{2%8rhiHD2{ zJt@pbiJsC#lgJR}bf4|!kRm%dJzFDDH~`w(uC5X5F#X_@e(M)e*48XVB4|NE%Bh${ zUZupxKwM9eD>s!7do@7&iGZy+H^08vjxq_~`WDdHT6GQ#Y@rO@AH-HrR-ug`p~Sfo zfCNyFIG?aGcv((^>8DC=lEl7+xh6zHMI>&{J^|?+o<$ieULy=cSpza&`N?S*GQ>7@L=4mvsR4Ho|*QXyOVa%NrHkUV($VdH&NGcU6t)h!p zD;6YN1u?lWcVcwbH-IYr*nAR+IJKq-@kbmD3d3f=m>W4do=Dl4lMx9eD@0bVs{y13 z?hS4VJgLwz2ZDy-0;==lXxcQa?5~Mjj5(6as zki^69E2#5@nqhj|cU0$!B4HIzAQC&gm10D!4*@r^!{x4%B;kiEEHan0A>n#|j`Y1I ziHDE4&cCr|lSqm8OOKZM7|)uMG)1j;VB8!ymy}h(oE3@10ARHAt+zH&t1EK8dL9m=H)P7Lx;#h*Biv z$BRuUkflJU_CI-dwyn(JXTNt94rLLIHr>&6i-H({DcPbOhF0aa4c zifM0QjJ%~4!x*~?x`0tM2>aZYvXkXNma=W-tE z^e#c0Q#_9%!G`W9puP~Hrgs^YAwWEX1d|n_<$)wR_tssiaV(W5Pjqd~)g-~Lm%l(Q zo1==MdsKv4WAaZYK^*EzVY~$qA_QX)rRe7!lakdlgGZ2HLtXbkU0=;^0+sMmol1@U zDr*cs6wXSTgaA*&^|#H3A$s<}8aXVDJ$p4D|1 z&?ufBr`=+9w~IMQ=-s<((A6#+Ub)2VZZC5%35cQ_$4o;;Znv{W1o4jUb+;gV*H?u+ zhk+p8+rG9Tv8?AbI1L2#E`MKx-d#+h!MPyF?>lr9n8ao^qrrh7=x=_m8yZLwu}Zol zL0EhT*4I!GBJro1>_iY&-v;)PT|U(k?;Huj@_W%fYD|nf7=-mV#C>h?Ecq4-`yRGw!L@G1!4RDC$90BaNT)XU6Nqqf6yxW$GITbe|zJ^nN5N= QKmY&$07*qoM6N<$f@qcZ*Z=?k diff --git a/install/templates/assets/img/password.png b/install/templates/assets/img/password.png deleted file mode 100644 index b71c6afcfc1325656cd896ace429fd02b9796885..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3395 zcmV-J4ZQM+P)4Tx065E?lXp~8*%rpny*Is3k`U>HUPDtLfb=dPMY<@&BtR%3gai<=A)*2! zii$KFGAiJJqeGFgB8r7UvG)lw2q@#=D59eB5?OC_&6@Y#y!rk(>$mpZ``mN(w+{d$ z{~*2~6IKEsLm(D~`*|{AV&fRtegFeJzyKQn*qm%(@FL#`AX9*k7b9Di1ilCY;LUCM z3cwAfe<*_i{y!;mgd(wQn@}0g`-K{77R;q!83d{f2->5>e-jNi&@GkEN5 z08k`(T+HL7$k zi2rfnU!TJwoR`EC@dUDpDA|y!e^~Y>&Caz<)P_%hmS72# zuF?SVYac*Si2#Y;EqDD7--7T_K>qTgbw+0A{@-u<&w|V4OEy3GbDdXs1cM_H<;;GQ zKTCiH1fU3LKn-XEeP9BZz!o?FXW$Nezyc5gB0wxy3OFDIWB?J!1qEO&C_R#~5QAF#ecWOe$st zrVO(S(~3ER8Ndu-Cb3wo8rB@^f(^m4v0`j7wiP6*H z*HIg&=c&Uq49%DpKue{S(!Qhh(fTIQx8+mRo|_C zUVU7Hrs1r?(J0Y4s&QWv)-=-$*Ic2wU$akhQcGLQPfMs(t#wXoT$`@#uAQpAUHg>w zm=0CPRfn&$UFWpUGlmMogOSdtV)QU3bTxJTbtSs{bo+Iu^^El*^$PV`^&aUH^jZ2z z`rGxp^(PE;41x^`44Mt@8{!RFhADydM8V4BX8#fz2G$EU~ znPi#No7^v1&90im=Jw`%^Ihfx7HA7c3xP$w#T_Pz>A}ol zHZun;>6Ss3g_a$bFRTo#;;gn>^;&(hwzE#RZm@n}L$O(4Q)ts=^SiB?EyuRj_U2sj zT;I8?=XTD0InR6^Z{F^CckQTl!FC($y6ryNJJ^ftTkOXi3>*?2>KyK{Xsl3H8SA1W z+R@W-wc`oLcTVjEZT6k;v-4Zwcg7#>ALzf;|4x8b04Ja^U}Ay8f|Uz;0!e|30&4=F1epbig1Um? z;03|kf*&q4Tqs!B5duO2LbioG3N;SR3jHw*6BZg)8}>BZCcGfLcM)|_!lI@{Zz4P+ z$|D{`nnX$>yQ37N;-ea)rlP&0E25<_RxvAMuEeUx@?$&WuyIjw2jV6d`z+qEcsSlJ zzBvB&65}O#OD-){Uz)!3WP)M>JKO9pdXb82(m z=0@cn%Tvx1y7Fw_ha_w?0?!2)zJGb>)XZy>IX^>d^{*PC_NN@sHf4P zv9U?Bsk|9(mNbtYjz4_uJMZs0TbM2TTIsE&N5B!uk!Rm0et-LD;L+}5tYa-d82(V# zMr|u;huW97PjsYoNIPRY2aYc|-reQg)%K(1j|Wfao~S*ka=QYP`T?6w6PF;7qe)fjy@YcZX$lG`C#NUzL<=!2= zmwxZ%{ha&L57s+Z?W$;WRp-b_!Gyj6R9=pE}_@B8TYBh$Gbupg>Entts16!_`kOvcR2zW@W6 z^Zb*Q-U0vs010qNS#tmY3ljhU3ljkVnw%H_00O&7L_t(I%Vm+0(2+mjmiaL)q)a;7&nHoh}6+u7OCt*xyjNfO)J+p}h~`I?!rwzlRU0h}e9&E~rY z2M4yjz5U1X^76|-ab;!Y^IorKtyXL6{{tf?ad>#>fKaJamWst9w{PA0vfXa~2p}S# zwp!aC=5qPxM5JV9_a_kC8K73H0g#(1sHvhp9`GQ7strY41Oxz?TucF-T1^3DcvukU z2ub%Gz>6YfU|vw~9Rd^pt~DAmea8f7zudff{q({+SG979VfW{g#V5+ACQgzhk$<#$ zu2eqn?5}U`>hB-FS^LO-qS0{vnuw!bw{Jg@7oMuU_jMc#$A@?ALPg`ptMSZS+2^A; z%MS-fLcg0WU4CqCFshc$Kl8>->OV-tm30T7X?5|fS1wi;VBy*9$&f}N9as=gP|s{} zmZe1%iRZkxA+yDWDt7a#IT@fcCgfOl@?Gs<&|3GacSTd=A_gfCg}pWj-gSnOy_}aGk#|je#znkz4^U z8pWtYAxNZ|L|H0PNXJ?SF6R{I^ZDfL5AGb@@ggGMfAM<%&)W%R{l1v1zN002ovPDHLkV1lAHjrjlo diff --git a/install/templates/assets/img/text_align_left.png b/install/templates/assets/img/text_align_left.png deleted file mode 100644 index 37caa3ed3b15d6bab5aa58145875e7eec5ecf189..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-%M@N{tu(Kw&{=X`^_L6E!S&;Rv2 z^#?wfOZ;Pc9M4lN*=f4)fxVBu%X9s<*q$Xj6~EeVI?GYfonh|s?|N@{qxaN_eLy=HJYD@<);T3K0RSTpNpb)H diff --git a/install/templates/dataform.tpl b/install/templates/dataform.tpl deleted file mode 100644 index 143eceda..00000000 --- a/install/templates/dataform.tpl +++ /dev/null @@ -1,10 +0,0 @@ -

{$this->_lng['install']['title']}

-
-
- {$formdata} -

- - -

-
-
diff --git a/install/templates/dataform2.tpl b/install/templates/dataform2.tpl deleted file mode 100644 index fc139019..00000000 --- a/install/templates/dataform2.tpl +++ /dev/null @@ -1,13 +0,0 @@ -

{$this->_lng['install']['welcometext']}

-
-
-
- {$formdata} -
- -
\ No newline at end of file diff --git a/install/templates/dataitem.tpl b/install/templates/dataitem.tpl deleted file mode 100644 index 845aeb11..00000000 --- a/install/templates/dataitem.tpl +++ /dev/null @@ -1,4 +0,0 @@ -

- - -

diff --git a/install/templates/dataitemchk.tpl b/install/templates/dataitemchk.tpl deleted file mode 100644 index 46c90d1c..00000000 --- a/install/templates/dataitemchk.tpl +++ /dev/null @@ -1,4 +0,0 @@ -

- - {$fieldlabel} -

diff --git a/install/templates/dataitemselect.tpl b/install/templates/dataitemselect.tpl deleted file mode 100644 index 91701bc6..00000000 --- a/install/templates/dataitemselect.tpl +++ /dev/null @@ -1,6 +0,0 @@ -

- - -

diff --git a/install/templates/dataitemyesno.tpl b/install/templates/dataitemyesno.tpl deleted file mode 100644 index 0f370820..00000000 --- a/install/templates/dataitemyesno.tpl +++ /dev/null @@ -1,4 +0,0 @@ -

- - -

diff --git a/install/templates/datasection.tpl b/install/templates/datasection.tpl deleted file mode 100644 index 380e92dd..00000000 --- a/install/templates/datasection.tpl +++ /dev/null @@ -1,2 +0,0 @@ -
-

{$section}

diff --git a/install/templates/footer.tpl b/install/templates/footer.tpl deleted file mode 100644 index 8d43a17b..00000000 --- a/install/templates/footer.tpl +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/install/templates/header.tpl b/install/templates/header.tpl deleted file mode 100644 index b06e6422..00000000 --- a/install/templates/header.tpl +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - Froxlor Server Management Panel - Installation - - -
diff --git a/install/templates/lngform.tpl b/install/templates/lngform.tpl deleted file mode 100644 index c1e52ceb..00000000 --- a/install/templates/lngform.tpl +++ /dev/null @@ -1,20 +0,0 @@ -
-
- {$this->_lng['install']['lngtitle']} - - - - - -
- - - - - -
-
-
-
\ No newline at end of file diff --git a/install/templates/page.tpl b/install/templates/page.tpl deleted file mode 100644 index 65aad877..00000000 --- a/install/templates/page.tpl +++ /dev/null @@ -1,11 +0,0 @@ -
-
- Froxlor Server Management Panel -
- -
-

{$pagetitle}

- {$pagecontent} - {$pagenavigation} -
-
diff --git a/install/templates/pagebottom.tpl b/install/templates/pagebottom.tpl deleted file mode 100644 index 604a9f8a..00000000 --- a/install/templates/pagebottom.tpl +++ /dev/null @@ -1,4 +0,0 @@ -

{$message}

- diff --git a/install/templates/textarea.tpl b/install/templates/textarea.tpl deleted file mode 100644 index 1a5661c2..00000000 --- a/install/templates/textarea.tpl +++ /dev/null @@ -1,5 +0,0 @@ - - -

{$escpduserdata}

- - diff --git a/lib/Froxlor/PhpHelper.php b/lib/Froxlor/PhpHelper.php index 5b7c0b14..9555ef79 100644 --- a/lib/Froxlor/PhpHelper.php +++ b/lib/Froxlor/PhpHelper.php @@ -47,7 +47,7 @@ class PhpHelper * @param string $charset * See php documentation about this * - * @return array The array with htmlentitie'd strings + * @return array|string The string or an array with htmlentities converted strings * @author Florian Lippert */ public static function htmlentitiesArray($subject, $fields = '', $quote_style = ENT_QUOTES, $charset = 'UTF-8') @@ -64,7 +64,7 @@ class PhpHelper } } } else { - $subject = htmlentities($subject, $quote_style, $charset); + $subject = empty($subject) ? "" : htmlentities($subject, $quote_style, $charset); } return $subject; @@ -120,22 +120,30 @@ class PhpHelper } if (! isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) { - global $theme; - - // fallback - if (empty($theme)) { - $theme = "Sparkle"; - } // prevent possible file-path-disclosure $errfile = str_replace(\Froxlor\Froxlor::getInstallDir(), "", $errfile); - // if we're not on the shell, output a nicer error-message - $err_hint = file_get_contents(\Froxlor\Froxlor::getInstallDir() . '/templates/' . $theme . '/misc/phperrornice.tpl'); - // replace values - $err_hint = str_replace("", '#' . $errno . ' ' . $errstr, $err_hint); - $err_hint = str_replace("", $errfile . ':' . $errline, $err_hint); - - // show - echo $err_hint; + // build alert + $type = 'danger'; + if ($errno == E_NOTICE || $errno == E_DEPRECATED || $errno == E_STRICT) { + $type = 'info'; + } elseif ($errno = E_WARNING) { + $type = 'warning'; + } + $err_display = ''; + // check for more existing errors + $errors = isset(\Froxlor\UI\Panel\UI::Twig()->getGlobals()['global_errors']) ? \Froxlor\UI\Panel\UI::Twig()->getGlobals()['global_errors'] : ""; + \Froxlor\UI\Panel\UI::Twig()->addGlobal('global_errors', $errors . $err_display); // return true to ignore php standard error-handler return true; } @@ -144,6 +152,28 @@ class PhpHelper return false; } + public static function phpExceptionHandler(\Exception $exception) + { + if (! isset($_SERVER['SHELL']) || (isset($_SERVER['SHELL']) && $_SERVER['SHELL'] == '')) { + $err_display = ''; + // check for more existing errors + $errors = isset(\Froxlor\UI\Panel\UI::Twig()->getGlobals()['global_errors']) ? \Froxlor\UI\Panel\UI::Twig()->getGlobals()['global_errors'] : ""; + \Froxlor\UI\Panel\UI::Twig()->addGlobal('global_errors', $errors . $err_display); + // return true to ignore php standard error-handler + return true; + } + } + public static function loadConfigArrayDir() { // Workaround until we use gettext diff --git a/lib/Froxlor/UI/Panel/CustomReflection.php b/lib/Froxlor/UI/Panel/CustomReflection.php new file mode 100644 index 00000000..28a45c5f --- /dev/null +++ b/lib/Froxlor/UI/Panel/CustomReflection.php @@ -0,0 +1,54 @@ +hasMethod($method) && $refl->getMethod($method)->isStatic() && $refl->getMethod($method)->isPublic()) { + return call_user_func_array($class . '::' . $method, $args); + } + throw new \RuntimeException(sprintf('Invalid static method call for class %s and method %s', $class, $method)); + } + + public function getStaticProperty($class, $property) + { + $refl = new \reflectionClass($class); + // Check that property is static AND public + if ($refl->hasProperty($property) && $refl->getProperty($property)->isStatic() && $refl->getProperty($property)->isPublic()) { + return $refl->getProperty($property)->getValue(); + } + throw new \RuntimeException(sprintf('Invalid static property get for class %s and property %s', $class, $property)); + } + + /** + * + * {@inheritdoc} + */ + public function getName() + { + return 'customreflection'; + } +} diff --git a/lib/Froxlor/UI/Panel/FroxlorTwig.php b/lib/Froxlor/UI/Panel/FroxlorTwig.php new file mode 100644 index 00000000..4a4f47b1 --- /dev/null +++ b/lib/Froxlor/UI/Panel/FroxlorTwig.php @@ -0,0 +1,102 @@ + 0 ? floor(log($size, 1024)) : 0; + if ($power < 0) { + $size = 0.00; + $power = 0; + } + return number_format($size / pow(1024, $power), 2, '.', ',') . ' ' . $units[$power] . $suffix; + } + + public function formatIPFilter($addr) + { + return inet_ntop(inet_pton($addr)); + } + + public function idnDecodeFilter($entity) + { + $idna_convert = new \Froxlor\Idna\IdnaWrapper(); + return $idna_convert->decode($entity); + } + + public function getSetting($setting = null) + { + return \Froxlor\Settings::Get($setting); + } + + public function getLang($identifier = null) + { + return \Froxlor\UI\Panel\UI::getLng($identifier); + } + + /** + * + * {@inheritdoc} + */ + public function getName() + { + return 'froxlortwig'; + } +} diff --git a/lib/Froxlor/UI/Panel/UI.php b/lib/Froxlor/UI/Panel/UI.php new file mode 100644 index 00000000..93662b63 --- /dev/null +++ b/lib/Froxlor/UI/Panel/UI.php @@ -0,0 +1,274 @@ + enforce it for the next time by settings HSTS header according to settings + */ + if (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) { + $maxage = \Froxlor\Settings::Get('system.hsts_maxage'); + if (empty($maxage)) { + $maxage = 0; + } + $hsts_header = "Strict-Transport-Security: max-age=" . $maxage; + if (\Froxlor\Settings::Get('system.hsts_incsub') == '1') { + $hsts_header .= "; includeSubDomains"; + } + if (\Froxlor\Settings::Get('system.hsts_preload') == '1') { + $hsts_header .= "; preload"; + } + header($hsts_header); + } + } + + /** + * initialize Twig template engine + */ + public static function initTwig(bool $install_mode = false) + { + self::$install_mode = $install_mode; + // init twig template engine + $loader = new \Twig\Loader\FilesystemLoader(\Froxlor\Froxlor::getInstallDir() . '/templates/'); + self::$twig = new \Twig\Environment($loader, array( + 'debug' => true, + 'cache' => \Froxlor\Froxlor::getInstallDir() . '/cache', + 'auto_reload' => true + )); + self::$twig->addExtension(new \Twig\Extension\DebugExtension()); + self::$twig->addExtension(new CustomReflection()); + self::$twig->addExtension(new FroxlorTwig()); + // empty buffer + self::$twigbuf = []; + } + + /** + * twig wrapper + * + * @return \Twig\Environment + */ + public static function Twig() + { + return self::$twig; + } + + /** + * wrapper for twig's "render" function to buffer the output + * + * @see \Twig\Environment::render() + */ + public static function TwigBuffer($name, array $context = []) + { + self::$twigbuf[] = [ + self::getTheme() . '/' . $name => $context + ]; + } + + public static function getTheme() + { + // fallback + $theme = self::$default_theme; + if (!self::$install_mode) { + // system default + if (\Froxlor\Froxlor::DBVERSION <= 201909150) { + \Froxlor\Settings::Set('panel.default_theme', 'Sparkle2'); + } + $theme = (\Froxlor\Settings::Get('panel.default_theme') !== null) ? \Froxlor\Settings::Get('panel.default_theme') : $theme; + // customer theme + /* + if (\Froxlor\CurrentUser::hasSession() && \Froxlor\CurrentUser::getField('theme') != $theme) { + $theme = \Froxlor\CurrentUser::getField('theme'); + } + */ + } + if (!file_exists(\Froxlor\Froxlor::getInstallDir() . '/templates/' . $theme)) { + \Froxlor\PhpHelper::phpErrHandler(E_USER_WARNING, "Theme '" . $theme . "' could not be found.", __FILE__, __LINE__, null); + $theme = self::$default_theme; + } + return $theme; + } + + /** + * echo output buffer and empty buffer-content + */ + public static function TwigOutputBuffer() + { + $output = ""; + foreach (self::$twigbuf as $buf) { + foreach ($buf as $name => $context) { + try { + $output .= self::$twig->render($name, $context); + } catch (\Exception $e) { + // whoops, template error + $errtpl = 'alert_nosession.html.twig'; + /* + if (\Froxlor\CurrentUser::hasSession()) { + $errtpl = 'alert.html.twig'; + } + */ + $edata = array( + 'type' => "danger", + 'heading' => "Template error", + 'alert_msg' => $e->getMessage(), + 'alert_info' => $e->getTraceAsString() + ); + try { + // try with user theme if set + $output .= self::$twig->render(self::getTheme() . '/misc/' . $errtpl, $edata); + } catch (\Exception $e) { + // try with default theme if different from user theme + if (self::getTheme() != self::$default_theme) { + $output .= self::$twig->render(self::$default_theme . '/misc/' . $errtpl, $edata); + } else { + throw $e; + } + } + } + } + } + echo $output; + // empty buffer + self::$twigbuf = []; + } + + public static function setLng($lng = array()) + { + self::$lng = $lng; + } + + public static function getLng($identifier, $context = null) + { + $id = explode(".", $identifier); + if (is_null($context)) { + $id_first = array_shift($id); + if (!isset(self::$lng[$id_first])) { + return null; + } + if (empty($id)) { + return self::$lng[$id_first]; + } else { + return self::getLng(implode(".", $id), self::$lng[$id_first]); + } + } else { + $id_first = array_shift($id); + if (empty($id)) { + return isset($context[$id_first]) ? $context[$id_first] : null; + } else { + return self::getLng(implode(".", $id), $context[$id_first]); + } + } + } + + /** + * returns an array of available themes + * + * @return array + */ + public static function getThemes() + { + $themespath = \Froxlor\FileDir::makeCorrectDir(\Froxlor\Froxlor::getInstallDir() . '/templates/'); + $themes_available = array(); + + if (is_dir($themespath)) { + $its = new \DirectoryIterator($themespath); + + foreach ($its as $it) { + if ($it->isDir() && $it->getFilename() != '.' && $it->getFilename() != '..' && $it->getFilename() != 'misc') { + $theme = $themespath . $it->getFilename(); + if (file_exists($theme . '/config.json')) { + $themeconfig = json_decode(file_get_contents($theme . '/config.json'), true); + if (array_key_exists('variants', $themeconfig) && is_array($themeconfig['variants'])) { + foreach ($themeconfig['variants'] as $variant => $data) { + if ($variant == "default") { + $themes_available[$it->getFilename()] = $it->getFilename(); + } elseif (array_key_exists('description', $data)) { + $themes_available[$it->getFilename() . '_' . $variant] = $data['description']; + } else { + $themes_available[$it->getFilename() . '_' . $variant] = $it->getFilename() . ' (' . $variant . ')'; + } + } + } else { + $themes_available[$it->getFilename()] = $it->getFilename(); + } + } + } + } + } + return $themes_available; + } +} diff --git a/lib/init.php b/lib/init.php index 0448a244..a7577153 100644 --- a/lib/init.php +++ b/lib/init.php @@ -18,22 +18,22 @@ */ // define default theme for configurehint, etc. -$_deftheme = 'Sparkle'; +$_deftheme = 'Froxlor'; // validate correct php version if (version_compare("7.1.0", PHP_VERSION, ">=")) { // get hint-template - $vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/phprequirementfailed.tpl'); + $wrongphp_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/phprequirementfailed.html.twig'); // replace values - $vendor_hint = str_replace("", "7.1.0", $vendor_hint); - $vendor_hint = str_replace("", PHP_VERSION, $vendor_hint); - $vendor_hint = str_replace("", date('Y', time()), $vendor_hint); - die($vendor_hint); + $wrongphp_hint = str_replace("", "7.1.0", $wrongphp_hint); + $wrongphp_hint = str_replace("", PHP_VERSION, $wrongphp_hint); + $wrongphp_hint = str_replace("", date('Y', time()), $wrongphp_hint); + die($wrongphp_hint); } -if (! file_exists(dirname(__DIR__) . '/vendor/autoload.php')) { +if (!file_exists(dirname(__DIR__) . '/vendor/autoload.php')) { // get hint-template - $vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/vendormissinghint.tpl'); + $vendor_hint = file_get_contents(dirname(__DIR__) . '/templates/' . $_deftheme . '/misc/vendormissinghint.html.twig'); // replace values $vendor_hint = str_replace("", dirname(__DIR__), $vendor_hint); $vendor_hint = str_replace("", date('Y', time()), $vendor_hint); @@ -46,37 +46,11 @@ use Froxlor\Database\Database; use Froxlor\Settings; use voku\helper\AntiXSS; use Froxlor\PhpHelper; +use Froxlor\UI\Panel\UI; -header("Content-Type: text/html; charset=UTF-8"); +UI::sendHeaders(); +UI::initTwig(); -// prevent Froxlor pages from being cached -header("Cache-Control: no-store, no-cache, must-revalidate"); -header("Pragma: no-cache"); -header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', time())); -header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time())); - -// Prevent inline - JS to be executed (i.e. XSS) in browsers which support this, -// Inline-JS is no longer allowed and used -// See: http://people.mozilla.org/~bsterne/content-security-policy/index.html -// New stuff see: https://www.owasp.org/index.php/List_of_useful_HTTP_headers and https://www.owasp.org/index.php/Content_Security_Policy -$csp_content = "default-src 'self'; script-src 'self'; connect-src 'self'; img-src 'self' data:; style-src 'self';"; -header("Content-Security-Policy: " . $csp_content); -header("X-Content-Security-Policy: " . $csp_content); -header("X-WebKit-CSP: " . $csp_content); - -header("X-XSS-Protection: 1; mode=block"); - -// Don't allow to load Froxlor in an iframe to prevent i.e. clickjacking -header("X-Frame-Options: DENY"); - -// Internet Explorer shall not guess the Content-Type, see: -// http://blogs.msdn.com/ie/archive/2008/07/02/ie8-security-part-v-comprehensive-protection.aspx -header("X-Content-Type-Options: nosniff"); - -// ensure that default timezone is set -if (function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get")) { - @date_default_timezone_set(@date_default_timezone_get()); -} /** * Register Globals Security Fix @@ -106,81 +80,51 @@ unset($key); $filename = htmlentities(basename($_SERVER['SCRIPT_NAME'])); // check whether the userdata file exists -if (! file_exists(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php')) { - $config_hint = file_get_contents(\Froxlor\Froxlor::getInstallDir() . '/templates/' . $_deftheme . '/misc/configurehint.tpl'); - $config_hint = str_replace("", date('Y', time()), $config_hint); - die($config_hint); +if (!file_exists(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php')) { + UI::Twig()->addGlobal('install_mode', '1'); + echo UI::Twig()->render($_deftheme . '/misc/configurehint.html.twig'); + die(); } // check whether we can read the userdata file -if (! is_readable(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php')) { +if (!is_readable(\Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php')) { // get possible owner $posixusername = posix_getpwuid(posix_getuid()); $posixgroup = posix_getgrgid(posix_getgid()); - // get hint-template - $owner_hint = file_get_contents(\Froxlor\Froxlor::getInstallDir() . '/templates/' . $_deftheme . '/misc/ownershiphint.tpl'); - // replace values - $owner_hint = str_replace("", $posixusername['name'], $owner_hint); - $owner_hint = str_replace("", $posixgroup['name'], $owner_hint); - $owner_hint = str_replace("", \Froxlor\Froxlor::getInstallDir(), $owner_hint); - $owner_hint = str_replace("", date('Y', time()), $owner_hint); - // show - die($owner_hint); + UI::Twig()->addGlobal('install_mode', '1'); + echo UI::Twig()->render($_deftheme . '/misc/ownershiphint.html.twig', [ + 'user' => $posixusername['name'], + 'group' => $posixgroup['name'], + 'installdir' => \Froxlor\Froxlor::getInstallDir() + ]); + die(); } -/** - * Includes the Usersettings eg. - * MySQL-Username/Passwort etc. - */ +// include MySQL-Username/Passwort etc. require \Froxlor\Froxlor::getInstallDir() . '/lib/userdata.inc.php'; - -if (! isset($sql) || ! is_array($sql)) { - $config_hint = file_get_contents(\Froxlor\Froxlor::getInstallDir() . '/templates/' . $_deftheme . '/misc/configurehint.tpl'); - $config_hint = str_replace("", date('Y', time()), $config_hint); - die($config_hint); +if (!isset($sql) || !is_array($sql)) { + UI::Twig()->addGlobal('install_mode', '1'); + echo UI::Twig()->render($_deftheme . '/misc/configurehint.html.twig'); + die(); } -/** - * Includes the Functions - */ -@set_error_handler(array( +// set error-handler +@set_error_handler([ '\\Froxlor\\PhpHelper', 'phpErrHandler' -)); +]); +@set_exception_handler([ + '\\Froxlor\\PhpHelper', + 'phpExceptionHandler' +]); -/** - * Includes the MySQL-Tabledefinitions etc. - */ +// include MySQL-tabledefinitions require \Froxlor\Froxlor::getInstallDir() . '/lib/tables.inc.php'; -/** - * Create a new idna converter - */ +// create a new idna converter $idna_convert = new \Froxlor\Idna\IdnaWrapper(); -/** - * If Froxlor was called via HTTPS -> enforce it for the next time by settings HSTS header according to settings - */ -$is_ssl = false; -if (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) { - $is_ssl = true; - $maxage = Settings::Get('system.hsts_maxage'); - if (empty($maxage)) { - $maxage = 0; - } - $hsts_header = "Strict-Transport-Security: max-age=" . $maxage; - if (Settings::Get('system.hsts_incsub') == '1') { - $hsts_header .= "; includeSubDomains"; - } - if (Settings::Get('system.hsts_preload') == '1') { - $hsts_header .= "; preload"; - } - header($hsts_header); -} - -/** - * SESSION MANAGEMENT - */ +// SESSION MANAGEMENT $remote_addr = $_SERVER['REMOTE_ADDR']; if (empty($_SERVER['HTTP_USER_AGENT'])) { @@ -248,7 +192,7 @@ if (isset($s) && $s != "" && $nosession != 1) { $userinfo_stmt = Database::prepare($query); $userinfo = Database::pexecute_first($userinfo_stmt, $userinfo_data); - if ($userinfo && (($userinfo['adminsession'] == '1' && AREA == 'admin' && isset($userinfo['adminid'])) || ($userinfo['adminsession'] == '0' && (AREA == 'customer' || AREA == 'login') && isset($userinfo['customerid']))) && (! isset($userinfo['deactivated']) || $userinfo['deactivated'] != '1')) { + if ($userinfo && (($userinfo['adminsession'] == '1' && AREA == 'admin' && isset($userinfo['adminid'])) || ($userinfo['adminsession'] == '0' && (AREA == 'customer' || AREA == 'login') && isset($userinfo['customerid']))) && (!isset($userinfo['deactivated']) || $userinfo['deactivated'] != '1')) { $upd_stmt = Database::prepare(" UPDATE `" . TABLE_PANEL_SESSIONS . "` SET `lastactivity` = :lastactive @@ -303,14 +247,14 @@ if (isset($userinfo['language']) && isset($languages[$userinfo['language']])) { // default: use language from session, #277 $language = $userinfo['language']; } else { - if (! isset($userinfo['def_language']) || ! isset($languages[$userinfo['def_language']])) // this will always evaluat true, since it is the above statement inverted. @todo remove + if (!isset($userinfo['def_language']) || !isset($languages[$userinfo['def_language']])) // this will always evaluat true, since it is the above statement inverted. @todo remove { if (isset($_GET['language']) && isset($languages[$_GET['language']])) { $language = $_GET['language']; } else { if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { $accept_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); - for ($i = 0; $i < count($accept_langs); $i ++) { + for ($i = 0; $i < count($accept_langs); $i++) { // this only works for most common languages. some (uncommon) languages have a 3 letter iso-code. // to be able to use these also, we would have to depend on the intl extension for php (using Locale::lookup or similar) // as long as froxlor does not support any of these languages, we can leave it like that. @@ -322,7 +266,7 @@ if (isset($userinfo['language']) && isset($languages[$userinfo['language']])) { unset($iso); // if HTTP_ACCEPT_LANGUAGES has no valid langs, use default (very unlikely) - if (! strlen($language) > 0) { + if (!strlen($language) > 0) { $language = Settings::Get('panel.standardlanguage'); } } @@ -370,7 +314,7 @@ if (preg_match("/([a-z0-9\.\-]+)_([a-z0-9\.\-]+)/i", $theme, $matches)) { } // check for existence of the theme -if (! file_exists('templates/' . $theme . '/config.json')) { +if (!file_exists('templates/' . $theme . '/config.json')) { // Fallback $theme = $_deftheme; } @@ -378,7 +322,7 @@ if (! file_exists('templates/' . $theme . '/config.json')) { $_themeoptions = json_decode(file_get_contents('templates/' . $theme . '/config.json'), true); // check for existence of variant in theme -if (! array_key_exists('variants', $_themeoptions) || ! array_key_exists($themevariant, $_themeoptions['variants'])) { +if (!array_key_exists('variants', $_themeoptions) || !array_key_exists($themevariant, $_themeoptions['variants'])) { $themevariant = "default"; } @@ -494,25 +438,28 @@ if (array_key_exists('css', $_themeoptions['variants'][$themevariant]) && is_arr } } } -eval("\$header = \"" . \Froxlor\UI\Template::getTemplate('header', '1') . "\";"); -$current_year = date('Y', time()); +UI::Twig()->addGlobal('theme_js', $js); +UI::Twig()->addGlobal('theme_css', $css); +unset($js); +unset($css); + +/** + * @TODO + * $panel_imprint_url = Settings::Get('panel.imprint_url'); if (!empty($panel_imprint_url) && strtolower(substr($panel_imprint_url, 0, 4)) != 'http') { - $panel_imprint_url = 'https://'.$panel_imprint_url; + $panel_imprint_url = 'https://' . $panel_imprint_url; } $panel_terms_url = Settings::Get('panel.terms_url'); if (!empty($panel_terms_url) && strtolower(substr($panel_terms_url, 0, 4)) != 'http') { - $panel_terms_url = 'https://'.$panel_terms_url; + $panel_terms_url = 'https://' . $panel_terms_url; } $panel_privacy_url = Settings::Get('panel.privacy_url'); if (!empty($panel_privacy_url) && strtolower(substr($panel_privacy_url, 0, 4)) != 'http') { - $panel_privacy_url = 'https://'.$panel_privacy_url; + $panel_privacy_url = 'https://' . $panel_privacy_url; } -eval("\$footer = \"" . \Froxlor\UI\Template::getTemplate('footer', '1') . "\";"); - -unset($js); -unset($css); +*/ if (isset($_POST['action'])) { $action = trim(strip_tags($_POST['action'])); diff --git a/templates/Froxlor/assets/css/main.css b/templates/Froxlor/assets/css/main.css new file mode 100644 index 00000000..89d871f2 --- /dev/null +++ b/templates/Froxlor/assets/css/main.css @@ -0,0 +1,12 @@ +@charset "UTF-8"; + +footer { + color: #888; + font-size: 0.75rem !important; +} + +footer a, +footer a:active, +footer a:visited { + color: #888; +} diff --git a/templates/Froxlor/base.html.twig b/templates/Froxlor/base.html.twig new file mode 100644 index 00000000..35c4a2b5 --- /dev/null +++ b/templates/Froxlor/base.html.twig @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + {{ theme_css|raw }} + {% block custom_css %}{% endblock %} + + + + + {{ theme_js|raw }} + {% block custom_js %}{% endblock %} + Froxlor + {% if page_title %} + | + {{ page_title }} + {% endif %} + + + + + +
{% block navigation %}{% endblock %} + + {{ global_errors|raw }} + + {% block body %}{% endblock %} + +
+ Froxlor + {% if install_mode is not defined %} + {% if (get_setting('admin.show_version_login') == + '1' and module == 'Login') or (module != 'Login' + and get_setting('admin.show_version_footer') == '1') %}{% endif %} + {{ call_static('\\Froxlor\\Froxlor', 'getFullVersion') }} + {% endif %} + © 2009-{{ "now"|date("Y") }} + by + the Froxlor Team
+ {% if install_mode is not defined %} + {% if (get_setting('panel.imprint_url') != '') %} + {{ lng('imprint') }} + {% endif %} + {% if (get_setting('panel.terms_url') != '') %} + {{ lng('terms') }} + {% endif %} + {% if (get_setting('panel.privacy_url') != '') %} + {{ lng('privacy') }} + {% endif %} + {% endif %} +
+ {% if lng('translator') %} +
+ {{ lng('panel.translator') }}: + {{ lng('translator') }} + {% endif %} +
+
+ + + diff --git a/templates/Froxlor/install/form.html.twig b/templates/Froxlor/install/form.html.twig new file mode 100644 index 00000000..e6f80a9c --- /dev/null +++ b/templates/Froxlor/install/form.html.twig @@ -0,0 +1,88 @@ + +
+
+ +
+ +
+
+ +
+ + +{% if pagecontent.form.result is not empty %} + +{% endif %} +
+ {% for fdata in pagecontent.form.data %} +
+ {{ fdata.title }} + {% for field in fdata.fields %} + {% if field is iterable %} + {% if field.type is defined %} + {% if field.type == 'text' or field.type == 'password' %} +
+ +
+ +
+
+ {% elseif field.type == 'select' %} +
+ +
+ +
+
+ {% elseif field.type == 'checkbox' %} +
+ +
+
+ +
+
+
+ {% endif %} + {% else %} +
+ +
+ {% for radios in field.fields %} +
+ + +
+ {% endfor %} +
+
+ {% endif %} + {% endif %} + {% endfor %} +
+ {% endfor %} + +
diff --git a/templates/Froxlor/install/index.html.twig b/templates/Froxlor/install/index.html.twig new file mode 100644 index 00000000..e828e3d6 --- /dev/null +++ b/templates/Froxlor/install/index.html.twig @@ -0,0 +1,53 @@ +{% extends "Froxlor/base.html.twig" %} + +{% block body %} +
+ Froxlor Server Management Panel +
+

{{ pagetitle }}

+ {% if pagecontent.checks is defined or pagecontent.installprocess is defined %} + + {% if pagecontent.checks is defined %} + {% set checks = pagecontent.checks %} + {% else %} + {% set checks = pagecontent.installprocess %} + {% endif %} + {% for check in checks %} + + + + + {% if check.result_desc is not empty %} + + + + + + + {% endif %} + {% endfor %} +
{{ check.title }} + {{ check.result_txt }} + {% if check.result == 0 %} ✓{% elseif check.result == 2 %} ???{% elseif check.result == 1 %} !!! + {% endif %} +
+ {{ check.result_desc|raw }} +
+{% elseif pagecontent.form is defined %} + {% include "Froxlor/install/form.html.twig" %} +{% else %} + +{% endif %} +{% if pagenavigation is not empty %} +
+
+ +
+ +
+{% endif %}
{% endblock %} diff --git a/templates/Froxlor/misc/alert_nosession.html.twig b/templates/Froxlor/misc/alert_nosession.html.twig new file mode 100644 index 00000000..862f1e2a --- /dev/null +++ b/templates/Froxlor/misc/alert_nosession.html.twig @@ -0,0 +1,23 @@ +{% extends "Froxlor/base.html.twig" %} + +{% block body %} + +{% endblock %} diff --git a/templates/Froxlor/misc/configurehint.html.twig b/templates/Froxlor/misc/configurehint.html.twig new file mode 100644 index 00000000..fe7949c6 --- /dev/null +++ b/templates/Froxlor/misc/configurehint.html.twig @@ -0,0 +1,17 @@ +{% extends "Froxlor/base.html.twig" %} + +{% block body %} +
+ +
+{% endblock %} diff --git a/templates/Froxlor/misc/ownershiphint.html.twig b/templates/Froxlor/misc/ownershiphint.html.twig new file mode 100644 index 00000000..5215531e --- /dev/null +++ b/templates/Froxlor/misc/ownershiphint.html.twig @@ -0,0 +1,20 @@ +{% extends "Froxlor/base.html.twig" %} + +{% block body %} +
+ +
+{% endblock %} diff --git a/templates/Froxlor/misc/phprequirementfailed.html.twig b/templates/Froxlor/misc/phprequirementfailed.html.twig new file mode 100644 index 00000000..767b2a5c --- /dev/null +++ b/templates/Froxlor/misc/phprequirementfailed.html.twig @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + Froxlor - Error + + + + +
+
+ +
+ +
+ + + + + diff --git a/templates/Froxlor/misc/vendormissinghint.html.twig b/templates/Froxlor/misc/vendormissinghint.html.twig new file mode 100644 index 00000000..d55ef46f --- /dev/null +++ b/templates/Froxlor/misc/vendormissinghint.html.twig @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + Froxlor - Error + + + + +
+
+ +
+ +
+ + + + +