major changes in language management and installer
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Froxlor;
|
||||
|
||||
use Froxlor\Database\Database;
|
||||
@@ -10,12 +11,12 @@ class FileDir
|
||||
* Wrapper around the exec command.
|
||||
*
|
||||
* @param string $exec_string
|
||||
* command to be executed
|
||||
* command to be executed
|
||||
* @param string $return_value
|
||||
* referenced variable where the output is stored
|
||||
* referenced variable where the output is stored
|
||||
* @param array $allowedChars
|
||||
* optional array of allowed characters in path/command
|
||||
*
|
||||
* optional array of allowed characters in path/command
|
||||
*
|
||||
* @return array result of exec()
|
||||
*/
|
||||
public static function safe_exec($exec_string, &$return_value = false, $allowedChars = null)
|
||||
@@ -38,8 +39,9 @@ class FileDir
|
||||
}
|
||||
|
||||
foreach ($disallowed as $dc) {
|
||||
if ($acheck && in_array($dc, $allowedChars))
|
||||
if ($acheck && in_array($dc, $allowedChars)) {
|
||||
continue;
|
||||
}
|
||||
// check for bad signs in execute command
|
||||
if (stristr($exec_string, $dc)) {
|
||||
die("SECURITY CHECK FAILED!\nThe execute string '" . $exec_string . "' is a possible security risk!\nPlease check your whole server for security problems by hand!\n");
|
||||
@@ -65,22 +67,28 @@ class FileDir
|
||||
* (Copied from cron_tasks.php:rev1189 as we'll need this more often in future)
|
||||
*
|
||||
* @param string $homeDir
|
||||
* The homedir of the user
|
||||
* The homedir of the user
|
||||
* @param string $dirToCreate
|
||||
* The dir which should be created
|
||||
* The dir which should be created
|
||||
* @param int $uid
|
||||
* The uid of the user
|
||||
* The uid of the user
|
||||
* @param int $gid
|
||||
* The gid of the user
|
||||
* The gid of the user
|
||||
* @param bool $placeindex
|
||||
* Place standard-index.html into the new folder
|
||||
* Place standard-index.html into the new folder
|
||||
* @param bool $allow_notwithinhomedir
|
||||
* Allow creating a directory out of the customers docroot
|
||||
*
|
||||
* Allow creating a directory out of the customers docroot
|
||||
*
|
||||
* @return bool true if everything went okay, false if something went wrong
|
||||
*/
|
||||
public static function mkDirWithCorrectOwnership($homeDir, $dirToCreate, $uid, $gid, $placeindex = false, $allow_notwithinhomedir = false)
|
||||
{
|
||||
public static function mkDirWithCorrectOwnership(
|
||||
$homeDir,
|
||||
$dirToCreate,
|
||||
$uid,
|
||||
$gid,
|
||||
$placeindex = false,
|
||||
$allow_notwithinhomedir = false
|
||||
) {
|
||||
if ($homeDir != '' && $dirToCreate != '') {
|
||||
$homeDir = self::makeCorrectDir($homeDir);
|
||||
$dirToCreate = self::makeCorrectDir($dirToCreate);
|
||||
@@ -96,14 +104,14 @@ class FileDir
|
||||
$subdir = self::makeCorrectDir($subdir);
|
||||
$subdirs = array();
|
||||
|
||||
if ($within_homedir || ! $allow_notwithinhomedir) {
|
||||
if ($within_homedir || !$allow_notwithinhomedir) {
|
||||
$subdirlen = strlen($subdir);
|
||||
$offset = 0;
|
||||
|
||||
while ($offset < $subdirlen) {
|
||||
$offset = strpos($subdir, '/', $offset);
|
||||
$subdirelem = substr($subdir, 0, $offset);
|
||||
$offset ++;
|
||||
$offset++;
|
||||
array_push($subdirs, self::makeCorrectDir($homeDir . $subdirelem));
|
||||
}
|
||||
} else {
|
||||
@@ -113,7 +121,7 @@ class FileDir
|
||||
$subdirs = array_unique($subdirs);
|
||||
sort($subdirs);
|
||||
foreach ($subdirs as $sdir) {
|
||||
if (! is_dir($sdir)) {
|
||||
if (!is_dir($sdir)) {
|
||||
$sdir = self::makeCorrectDir($sdir);
|
||||
self::safe_exec('mkdir -p ' . escapeshellarg($sdir));
|
||||
// place index
|
||||
@@ -123,7 +131,7 @@ class FileDir
|
||||
self::storeDefaultIndex($loginname, $sdir, null);
|
||||
}
|
||||
}
|
||||
self::safe_exec('chown -R ' . (int) $uid . ':' . (int) $gid . ' ' . escapeshellarg($sdir));
|
||||
self::safe_exec('chown -R ' . (int)$uid . ':' . (int)$gid . ' ' . escapeshellarg($sdir));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -143,7 +151,6 @@ class FileDir
|
||||
*/
|
||||
public static function checkDisallowedPaths($path = null)
|
||||
{
|
||||
|
||||
/*
|
||||
* disallow base-directories and /
|
||||
*/
|
||||
@@ -181,19 +188,19 @@ class FileDir
|
||||
* store the default index-file in a given destination folder
|
||||
*
|
||||
* @param string $loginname
|
||||
* customers loginname
|
||||
* customers loginname
|
||||
* @param string $destination
|
||||
* path where to create the file
|
||||
* path where to create the file
|
||||
* @param object $logger
|
||||
* FroxlorLogger object
|
||||
* FroxlorLogger object
|
||||
* @param boolean $force
|
||||
* force creation whatever the settings say (needed for task #2, create new user)
|
||||
*
|
||||
* force creation whatever the settings say (needed for task #2, create new user)
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public static function storeDefaultIndex($loginname = null, $destination = null, $logger = null, $force = false)
|
||||
{
|
||||
if ($force || (int) Settings::Get('system.store_index_file_subs') == 1) {
|
||||
if ($force || (int)Settings::Get('system.store_index_file_subs') == 1) {
|
||||
$result_stmt = Database::prepare("
|
||||
SELECT `t`.`value`, `c`.`email` AS `customer_email`, `a`.`email` AS `admin_email`, `c`.`loginname` AS `customer_login`, `a`.`loginname` AS `admin_login`
|
||||
FROM `" . TABLE_PANEL_CUSTOMERS . "` AS `c` INNER JOIN `" . TABLE_PANEL_ADMINS . "` AS `a`
|
||||
@@ -206,7 +213,6 @@ class FileDir
|
||||
));
|
||||
|
||||
if (Database::num_rows() > 0) {
|
||||
|
||||
$template = $result_stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
$replace_arr = array(
|
||||
@@ -224,12 +230,14 @@ class FileDir
|
||||
fwrite($index_html_handler, $htmlcontent);
|
||||
fclose($index_html_handler);
|
||||
if ($logger !== null) {
|
||||
$logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Creating \'index.' . Settings::Get('system.index_file_extension') . '\' for Customer \'' . $template['customer_login'] . '\' based on template in directory ' . escapeshellarg($indexhtmlpath));
|
||||
$logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE,
|
||||
'Creating \'index.' . Settings::Get('system.index_file_extension') . '\' for Customer \'' . $template['customer_login'] . '\' based on template in directory ' . escapeshellarg($indexhtmlpath));
|
||||
}
|
||||
} else {
|
||||
$destination = self::makeCorrectDir($destination);
|
||||
if ($logger !== null) {
|
||||
$logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: cp -a ' . \Froxlor\Froxlor::getInstallDir() . '/templates/misc/standardcustomer/* ' . escapeshellarg($destination));
|
||||
$logger->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_NOTICE,
|
||||
'Running: cp -a ' . \Froxlor\Froxlor::getInstallDir() . '/templates/misc/standardcustomer/* ' . escapeshellarg($destination));
|
||||
}
|
||||
self::safe_exec('cp -a ' . \Froxlor\Froxlor::getInstallDir() . '/templates/misc/standardcustomer/* ' . escapeshellarg($destination));
|
||||
}
|
||||
@@ -241,13 +249,13 @@ class FileDir
|
||||
* Function which returns a correct filename, means to add a slash at the beginning if there wasn't one
|
||||
*
|
||||
* @param string $filename
|
||||
* the filename
|
||||
*
|
||||
* the filename
|
||||
*
|
||||
* @return string the corrected filename
|
||||
*/
|
||||
public static function makeCorrectFile($filename)
|
||||
{
|
||||
if (! isset($filename) || trim($filename) == '') {
|
||||
if (!isset($filename) || trim($filename) == '') {
|
||||
$error = 'Given filename for function ' . __FUNCTION__ . ' is empty.' . "\n";
|
||||
$error .= 'This is very dangerous and should not happen.' . "\n";
|
||||
$error .= 'Please inform the Froxlor team about this issue so they can fix it.';
|
||||
@@ -266,19 +274,20 @@ class FileDir
|
||||
}
|
||||
|
||||
/**
|
||||
* Function which returns a correct dirname, means to add slashes at the beginning and at the end if there weren't some
|
||||
* Function which returns a correct dirname, means to add slashes at the beginning and at the end if there weren't
|
||||
* some
|
||||
*
|
||||
* @param string $path
|
||||
* the path to correct
|
||||
*
|
||||
* @throws \Exception
|
||||
* the path to correct
|
||||
*
|
||||
* @return string the corrected path
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function makeCorrectDir($dir)
|
||||
{
|
||||
if (is_string($dir) && strlen($dir) > 0) {
|
||||
$dir = trim($dir);
|
||||
if (substr($dir, - 1, 1) != '/') {
|
||||
if (substr($dir, -1, 1) != '/') {
|
||||
$dir .= '/';
|
||||
}
|
||||
if (substr($dir, 0, 1) != '/') {
|
||||
@@ -293,13 +302,12 @@ class FileDir
|
||||
* Function which returns a secure path, means to remove all multiple dots and slashes
|
||||
*
|
||||
* @param string $path
|
||||
* the path to secure
|
||||
*
|
||||
* the path to secure
|
||||
*
|
||||
* @return string the corrected path
|
||||
*/
|
||||
public static function makeSecurePath($path)
|
||||
{
|
||||
|
||||
// check for bad characters, some are allowed with escaping
|
||||
// but we generally don't want them in our directory-names,
|
||||
// thx to aaronmueller for this snipped
|
||||
@@ -341,7 +349,7 @@ class FileDir
|
||||
* Function which returns a correct destination for Postfix Virtual Table
|
||||
*
|
||||
* @param
|
||||
* string The destinations
|
||||
* string The destinations
|
||||
* @return string the corrected destinations
|
||||
* @author Florian Lippert <flo@syscp.org>
|
||||
*/
|
||||
@@ -355,7 +363,7 @@ class FileDir
|
||||
$destination = substr($destination, 1);
|
||||
}
|
||||
|
||||
if (substr($destination, - 1, 1) == ' ') {
|
||||
if (substr($destination, -1, 1) == ' ') {
|
||||
$destination = substr($destination, 0, strlen($destination) - 1);
|
||||
}
|
||||
|
||||
@@ -366,16 +374,16 @@ class FileDir
|
||||
* Returns a valid html tag for the chosen $fieldType for paths
|
||||
*
|
||||
* @param
|
||||
* string path The path to start searching in
|
||||
* string path The path to start searching in
|
||||
* @param
|
||||
* integer uid The uid which must match the found directories
|
||||
* integer uid The uid which must match the found directories
|
||||
* @param
|
||||
* integer gid The gid which must match the found directories
|
||||
* integer gid The gid which must match the found directories
|
||||
* @param
|
||||
* string value the value for the input-field
|
||||
*
|
||||
* string value the value for the input-field
|
||||
*
|
||||
* @return string The html tag for the chosen $fieldType
|
||||
*
|
||||
*
|
||||
* @author Martin Burchert <martin.burchert@syscp.de>
|
||||
* @author Manuel Bernhardt <manuel.bernhardt@syscp.de>
|
||||
*/
|
||||
@@ -390,21 +398,18 @@ class FileDir
|
||||
// but dirList holds the paths with starting slash
|
||||
// so we just add one here to get the correct
|
||||
// default path selected, #225
|
||||
if (substr($value, 0, 1) != '/' && ! $dom) {
|
||||
if (substr($value, 0, 1) != '/' && !$dom) {
|
||||
$value = '/' . $value;
|
||||
}
|
||||
|
||||
$fieldType = strtolower(\Froxlor\Settings::Get('panel.pathedit'));
|
||||
|
||||
if ($fieldType == 'manual') {
|
||||
|
||||
$field = array(
|
||||
'type' => 'text',
|
||||
'value' => htmlspecialchars($value)
|
||||
);
|
||||
|
||||
} elseif ($fieldType == 'dropdown') {
|
||||
|
||||
$dirList = self::findDirs($path, $uid, $gid);
|
||||
natcasesort($dirList);
|
||||
|
||||
@@ -459,12 +464,12 @@ class FileDir
|
||||
* the found directory is valid. It uses recursive-iterators to find subdirectories.
|
||||
*
|
||||
* @param string $path
|
||||
* the path to start searching in
|
||||
* the path to start searching in
|
||||
* @param int $uid
|
||||
* the uid which must match the found directories
|
||||
* the uid which must match the found directories
|
||||
* @param int $gid
|
||||
* the gid which must match the found directories
|
||||
*
|
||||
* the gid which must match the found directories
|
||||
*
|
||||
* @return array Array of found valid paths
|
||||
*/
|
||||
private static function findDirs($path, $uid, $gid)
|
||||
@@ -474,7 +479,6 @@ class FileDir
|
||||
|
||||
// valid directory?
|
||||
if (is_dir($path)) {
|
||||
|
||||
// Will exclude everything under these directories
|
||||
$exclude = array(
|
||||
'awstats',
|
||||
@@ -496,7 +500,8 @@ class FileDir
|
||||
};
|
||||
|
||||
// create RecursiveIteratorIterator
|
||||
$its = new \RecursiveIteratorIterator(new \RecursiveCallbackFilterIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), $filter));
|
||||
$its = new \RecursiveIteratorIterator(new \RecursiveCallbackFilterIterator(new \RecursiveDirectoryIterator($path,
|
||||
\RecursiveDirectoryIterator::SKIP_DOTS), $filter));
|
||||
// we can limit the recursion-depth, but will it be helpful or
|
||||
// will people start asking "why do I only see 2 subdirectories, i want to use /a/b/c"
|
||||
// let's keep this in mind and see whether it will be useful
|
||||
@@ -521,13 +526,13 @@ class FileDir
|
||||
* if exact = false [default])
|
||||
*
|
||||
* @param boolean $exact
|
||||
* whether to check explicitly for FreeBSD or *BSD
|
||||
*
|
||||
* whether to check explicitly for FreeBSD or *BSD
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isFreeBSD($exact = false)
|
||||
{
|
||||
if (($exact && PHP_OS == 'FreeBSD') || (! $exact && stristr(PHP_OS, 'BSD'))) {
|
||||
if (($exact && PHP_OS == 'FreeBSD') || (!$exact && stristr(PHP_OS, 'BSD'))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -537,8 +542,8 @@ class FileDir
|
||||
* set the immutable flag for a file
|
||||
*
|
||||
* @param string $filename
|
||||
* the file to set the flag for
|
||||
*
|
||||
* the file to set the flag for
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function setImmutable($filename = null)
|
||||
@@ -550,8 +555,8 @@ class FileDir
|
||||
* removes the immutable flag for a file
|
||||
*
|
||||
* @param string $filename
|
||||
* the file to set the flag for
|
||||
*
|
||||
* the file to set the flag for
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function removeImmutable($filename = null)
|
||||
@@ -564,8 +569,8 @@ class FileDir
|
||||
* to use chattr (Linux) or chflags (FreeBSD)
|
||||
*
|
||||
* @param boolean $remove
|
||||
* whether to use +i|schg (false) or -i|noschg (true)
|
||||
*
|
||||
* whether to use +i|schg (false) or -i|noschg (true)
|
||||
*
|
||||
* @return string functionname + parameter (not the file)
|
||||
*/
|
||||
private static function getImmutableFunction($remove = false)
|
||||
@@ -581,10 +586,8 @@ class FileDir
|
||||
|
||||
public static function getFilesystemQuota()
|
||||
{
|
||||
|
||||
// enabled at all?
|
||||
if (Settings::Get('system.diskquota_enabled')) {
|
||||
|
||||
// set linux defaults
|
||||
$repquota_params = "-np";
|
||||
// $quota_line_regex = "/^#([0-9]+)\s*[+-]{2}\s*(\d+)\s*(\d+)\s*(\d+)\s*(\d+)\s*(\d+)\s*(\d+)\s*(\d+)\s*(\d+)/i";
|
||||
@@ -598,14 +601,14 @@ class FileDir
|
||||
|
||||
// Fetch all quota in the desired partition
|
||||
$repquota = array();
|
||||
exec(Settings::Get('system.diskquota_repquota_path') . " " . $repquota_params . " " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')), $repquota);
|
||||
exec(Settings::Get('system.diskquota_repquota_path') . " " . $repquota_params . " " . escapeshellarg(Settings::Get('system.diskquota_customer_partition')),
|
||||
$repquota);
|
||||
|
||||
$usedquota = array();
|
||||
foreach ($repquota as $tmpquota) {
|
||||
$matches = null;
|
||||
// Let's see if the line matches a quota - line
|
||||
if (preg_match($quota_line_regex, $tmpquota, $matches)) {
|
||||
|
||||
// It matches - put it into an array with userid as key (for easy lookup later)
|
||||
$usedquota[$matches[1]] = array(
|
||||
'block' => array(
|
||||
|
||||
109
lib/Froxlor/Install/Install.php
Normal file
109
lib/Froxlor/Install/Install.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you can also view it online at
|
||||
* http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright the authors
|
||||
* @author Froxlor team <team@froxlor.org>
|
||||
* @license http://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||
*/
|
||||
|
||||
namespace Froxlor\Install;
|
||||
|
||||
use Froxlor\UI\Panel\UI;
|
||||
|
||||
class Install
|
||||
{
|
||||
public $step = 0;
|
||||
public $phpVersion;
|
||||
public string $requiredVersion = '7.4.0';
|
||||
public array $requiredExtensions = ['libxml', 'zip'];
|
||||
public array $suggestedExtensions = ['curl'];
|
||||
public array $suggestions;
|
||||
public array $criticals;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->step = \Froxlor\UI\Request::get('step');
|
||||
|
||||
$this->phpVersion = phpversion();
|
||||
$this->loadedExtensions = get_loaded_extensions();
|
||||
|
||||
$this->checkExtensions();
|
||||
}
|
||||
|
||||
public function checkExtensions()
|
||||
{
|
||||
// check for required extensions
|
||||
foreach ($this->requiredExtensions as $requiredExtension) {
|
||||
if (in_array($requiredExtension, $this->loadedExtensions)) continue;
|
||||
$this->criticals['missing_extensions'][] = $requiredExtension;
|
||||
}
|
||||
|
||||
// check for suggested extensions
|
||||
foreach ($this->suggestedExtensions as $suggestedExtension) {
|
||||
if (in_array($suggestedExtension, $this->loadedExtensions)) continue;
|
||||
$this->suggestions['missing_extensions'][] = $suggestedExtension;
|
||||
}
|
||||
}
|
||||
|
||||
public function getPreflightText(): string
|
||||
{
|
||||
if (version_compare($this->requiredVersion, PHP_VERSION, "<")) {
|
||||
$text = 'Your system is running with PHP ' . $this->phpVersion;
|
||||
} else {
|
||||
$text = 'Your system is running a lower version than PHP ' . $this->requiredVersion;
|
||||
$this->criticals[] = 'Update your current PHP Version from ' . $this->phpVersion . ' to ' . $this->requiredVersion . ' or higher';
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$formfield = require dirname(__DIR__) . '/lib/formfields/install/formfield.install.php';
|
||||
|
||||
// init twig
|
||||
UI::initTwig(true);
|
||||
UI::sendHeaders();
|
||||
|
||||
// set global variables
|
||||
UI::twig()->addGlobal('install_mode', true);
|
||||
UI::twig()->addGlobal('basehref', '../');
|
||||
|
||||
// load template
|
||||
UI::twigBuffer('/install/index.html.twig', [
|
||||
'setup' => [
|
||||
'step' => $this->step,
|
||||
],
|
||||
'preflight' => [
|
||||
'text' => $this->getPreflightText(),
|
||||
'suggestions' => $this->suggestions,
|
||||
'criticals' => $this->criticals,
|
||||
],
|
||||
'page' => [
|
||||
'title' => 'Database',
|
||||
'description' => 'Test',
|
||||
],
|
||||
'section' => $formfield['install']['sections'][sprintf('step%s', $this->step)] ?? [],
|
||||
]);
|
||||
|
||||
// output view
|
||||
UI::twigOutputBuffer();
|
||||
}
|
||||
}
|
||||
117
lib/Froxlor/Language.php
Normal file
117
lib/Froxlor/Language.php
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you can also view it online at
|
||||
* http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright the authors
|
||||
* @author Froxlor team <team@froxlor.org>
|
||||
* @license http://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||
*/
|
||||
|
||||
namespace Froxlor;
|
||||
|
||||
use RecursiveArrayIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
|
||||
class Language
|
||||
{
|
||||
protected static ?array $lng = null;
|
||||
protected static string $defaultLanguage = 'en';
|
||||
protected static ?string $requestedLanguage = null;
|
||||
|
||||
/**
|
||||
* @TODO: Possible iso: de, de-DE, de-AT (fallback to de)
|
||||
*
|
||||
* @param $iso
|
||||
* @return array
|
||||
*/
|
||||
private static function loadLanguage($iso): array
|
||||
{
|
||||
$languageFile = dirname(__DIR__, 2) . sprintf('/lng/%s.lng.php', $iso);
|
||||
|
||||
if (!file_exists($languageFile)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// load default language
|
||||
$lng = require $languageFile;
|
||||
|
||||
// multidimensional array to dot notation keys
|
||||
$reItIt = new RecursiveIteratorIterator(new RecursiveArrayIterator($lng));
|
||||
$result = [];
|
||||
foreach ($reItIt as $leafValue) {
|
||||
$keys = [];
|
||||
foreach (range(0, $reItIt->getDepth()) as $depth) {
|
||||
$keys[] = $reItIt->getSubIterator($depth)->key();
|
||||
}
|
||||
$result[join('.', $keys)] = $leafValue;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @fixme iso seems to be not used in froxlor?
|
||||
*/
|
||||
public static function getLanguages(): array
|
||||
{
|
||||
$languages = [];
|
||||
$directory = dirname(__DIR__, 2) . '/lng';
|
||||
|
||||
foreach (array_diff(scandir($directory), array('..', '.', 'index.html')) as $language) {
|
||||
$iso = explode('.', $language)[0];
|
||||
$languages[$iso] = self::getTranslation('languages.' . $iso);
|
||||
}
|
||||
|
||||
return $languages;
|
||||
}
|
||||
|
||||
public static function getTranslation(string $identifier, array $arguments = [])
|
||||
{
|
||||
// initialize
|
||||
if (is_null(self::$lng)) {
|
||||
// load fallback language
|
||||
self::$lng = self::loadLanguage(self::$defaultLanguage);
|
||||
|
||||
// load user requested language
|
||||
if (self::$requestedLanguage) {
|
||||
self::$lng = array_merge(self::$lng, self::loadLanguage(self::$requestedLanguage));
|
||||
}
|
||||
|
||||
// load fallback from browser if nothing requested
|
||||
$iso = trim(substr(strtok(strtok($_SERVER['HTTP_ACCEPT_LANGUAGE'], ','), ';'), 0, 5));
|
||||
if (!self::$requestedLanguage && strlen($iso) == 2 && $iso !== self::$defaultLanguage) {
|
||||
self::$lng = array_merge(self::$lng, self::loadLanguage($iso));
|
||||
}
|
||||
}
|
||||
|
||||
// search by identifier
|
||||
return vsprintf(self::$lng[$identifier] ?? $identifier, $arguments);
|
||||
}
|
||||
|
||||
public static function setDefaultLanguage(string $string)
|
||||
{
|
||||
self::$defaultLanguage = $string;
|
||||
}
|
||||
|
||||
public static function setLanguage(string $string)
|
||||
{
|
||||
self::$requestedLanguage = $string;
|
||||
}
|
||||
}
|
||||
178
lib/formfields/install/formfield.install.php
Normal file
178
lib/formfields/install/formfield.install.php
Normal file
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Froxlor team <team@froxlor.org> (2010-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Formfields
|
||||
*
|
||||
*/
|
||||
|
||||
use Froxlor\Settings;
|
||||
|
||||
return array(
|
||||
'install' => [
|
||||
'title' => lng('admin.admin_add'),
|
||||
'image' => 'fa-solid fa-user-plus',
|
||||
'self_overview' => ['section' => 'admins', 'page' => 'admins'],
|
||||
'sections' => [
|
||||
'step1' => [
|
||||
'title' => lng('install.dabatase'),
|
||||
'fields' => [
|
||||
'sql_hostname' => [
|
||||
'label' => lng('sql_hostname'),
|
||||
'type' => 'text',
|
||||
'mandatory' => true,
|
||||
'value' => 'localhost'
|
||||
],
|
||||
'sql_root_username' => [
|
||||
'label' => lng('sql_root_username'),
|
||||
'type' => 'password',
|
||||
'mandatory' => true,
|
||||
'next_to' => [
|
||||
'sql_root_password' => [
|
||||
'label' => lng('sql_root_password'),
|
||||
'type' => 'password',
|
||||
'mandatory' => true
|
||||
],
|
||||
]
|
||||
],
|
||||
'sql_username' => [
|
||||
'label' => lng('sql_username'),
|
||||
'type' => 'password',
|
||||
'mandatory' => true,
|
||||
'next_to' => [
|
||||
'sql_password' => [
|
||||
'label' => lng('sql_password'),
|
||||
'type' => 'password',
|
||||
'mandatory' => true
|
||||
],
|
||||
]
|
||||
],
|
||||
]
|
||||
],
|
||||
'step2' => [
|
||||
'title' => lng('admin.contactdata'),
|
||||
'image' => 'icons/user_add.png',
|
||||
'fields' => [
|
||||
'name' => [
|
||||
'label' => lng('name'),
|
||||
'type' => 'text',
|
||||
'mandatory' => true
|
||||
],
|
||||
'username' => [
|
||||
'label' => lng('username'),
|
||||
'type' => 'text',
|
||||
'mandatory' => true
|
||||
],
|
||||
'password' => [
|
||||
'label' => lng('password'),
|
||||
'type' => 'password',
|
||||
'mandatory' => true
|
||||
],
|
||||
'email' => [
|
||||
'label' => lng('email'),
|
||||
'type' => 'text',
|
||||
'mandatory' => true
|
||||
],
|
||||
]
|
||||
],
|
||||
'step3' => [
|
||||
'title' => lng('admin.servicedata'),
|
||||
'image' => 'icons/user_add.png',
|
||||
'fields' => [
|
||||
'ipaddress' => [
|
||||
'label' => lng('serversettings.ipaddress.title'),
|
||||
'type' => 'select'
|
||||
],
|
||||
'change_serversettings' => [
|
||||
'label' => lng('admin.change_serversettings'),
|
||||
'type' => 'checkbox',
|
||||
'value' => '1',
|
||||
'checked' => false
|
||||
],
|
||||
'customers' => [
|
||||
'label' => lng('admin.customers'),
|
||||
'type' => 'textul',
|
||||
'value' => 0,
|
||||
'maxlength' => 9,
|
||||
'mandatory' => true
|
||||
],
|
||||
'customers_see_all' => [
|
||||
'label' => lng('admin.customers_see_all'),
|
||||
'type' => 'checkbox',
|
||||
'value' => '1',
|
||||
'checked' => false
|
||||
],
|
||||
'domains' => [
|
||||
'label' => lng('admin.domains'),
|
||||
'type' => 'textul',
|
||||
'value' => 0,
|
||||
'maxlength' => 9,
|
||||
'mandatory' => true
|
||||
],
|
||||
'domains_see_all' => [
|
||||
'label' => lng('admin.domains_see_all'),
|
||||
'type' => 'checkbox',
|
||||
'value' => '1',
|
||||
'checked' => false
|
||||
],
|
||||
'caneditphpsettings' => [
|
||||
'label' => lng('admin.caneditphpsettings'),
|
||||
'type' => 'checkbox',
|
||||
'value' => '1',
|
||||
'checked' => false
|
||||
],
|
||||
'subdomains' => [
|
||||
'label' => lng('customer.subdomains'),
|
||||
'type' => 'textul',
|
||||
'value' => 0,
|
||||
'maxlength' => 9,
|
||||
'mandatory' => true
|
||||
],
|
||||
'emails' => [
|
||||
'label' => lng('customer.emails'),
|
||||
'type' => 'textul',
|
||||
'value' => 0,
|
||||
'maxlength' => 9,
|
||||
'mandatory' => true
|
||||
],
|
||||
'email_accounts' => [
|
||||
'label' => lng('customer.accounts'),
|
||||
'type' => 'textul',
|
||||
'value' => 0,
|
||||
'maxlength' => 9,
|
||||
'mandatory' => true
|
||||
],
|
||||
'email_forwarders' => [
|
||||
'label' => lng('customer.forwarders'),
|
||||
'type' => 'textul',
|
||||
'value' => 0,
|
||||
'maxlength' => 9,
|
||||
'mandatory' => true
|
||||
],
|
||||
'ftps' => [
|
||||
'label' => lng('customer.ftps'),
|
||||
'type' => 'textul',
|
||||
'value' => 0,
|
||||
'maxlength' => 9
|
||||
],
|
||||
'mysqls' => [
|
||||
'label' => lng('customer.mysqls'),
|
||||
'type' => 'textul',
|
||||
'value' => 0,
|
||||
'maxlength' => 9,
|
||||
'mandatory' => true
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
);
|
||||
36
lib/functions.php
Normal file
36
lib/functions.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you can also view it online at
|
||||
* http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright the authors
|
||||
* @author Froxlor team <team@froxlor.org>
|
||||
* @license http://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||
*/
|
||||
|
||||
function view($template, $attributes)
|
||||
{
|
||||
$view = file_get_contents(dirname(__DIR__) . '/templates/' . $template);
|
||||
|
||||
return str_replace(array_keys($attributes), array_values($attributes), $view);
|
||||
}
|
||||
|
||||
function lng(string $identifier, array $arguments = [])
|
||||
{
|
||||
return \Froxlor\Language::getTranslation($identifier, $arguments);
|
||||
}
|
||||
105
lib/init.php
105
lib/init.php
@@ -2,19 +2,25 @@
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2003-2009 the SysCP Team (see authors).
|
||||
* Copyright (c) 2010 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Florian Lippert <flo@syscp.org> (2003-2009)
|
||||
* @author Froxlor team <team@froxlor.org> (2010-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package System
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you can also view it online at
|
||||
* http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright the authors
|
||||
* @author Froxlor team <team@froxlor.org>
|
||||
* @license http://files.froxlor.org/misc/COPYING.txt GPLv2
|
||||
*/
|
||||
|
||||
// define default theme for configurehint, etc.
|
||||
@@ -47,8 +53,10 @@ if (!file_exists(dirname(__DIR__) . '/vendor/autoload.php')) {
|
||||
}
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
require dirname(__DIR__) . '/lib/functions.php';
|
||||
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\Language;
|
||||
use Froxlor\Settings;
|
||||
use Froxlor\UI\Panel\UI;
|
||||
use Froxlor\UI\Request;
|
||||
@@ -120,91 +128,34 @@ if (CurrentUser::hasSession()) {
|
||||
CurrentUser::reReadUserData();
|
||||
}
|
||||
|
||||
// Language Management
|
||||
$langs = array();
|
||||
$languages = array();
|
||||
$iso = array();
|
||||
|
||||
// query the whole table
|
||||
$result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_LANGUAGE . "`");
|
||||
|
||||
// presort languages
|
||||
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$langs[$row['language']][] = $row;
|
||||
// check for row[iso] cause older froxlor
|
||||
// versions didn't have that and it will
|
||||
// lead to a lot of undefined variables
|
||||
// before the admin can even update
|
||||
if (isset($row['iso'])) {
|
||||
$iso[$row['iso']] = $row['language'];
|
||||
}
|
||||
}
|
||||
|
||||
// buildup $languages for the login screen
|
||||
foreach ($langs as $key => $value) {
|
||||
$languages[$key] = $key;
|
||||
}
|
||||
/**
|
||||
* Language management
|
||||
*/
|
||||
|
||||
// set default language before anything else to
|
||||
// ensure that we can display messages
|
||||
$language = Settings::Get('panel.standardlanguage');
|
||||
Language::setLanguage(Settings::Get('panel.standardlanguage'));
|
||||
|
||||
if (CurrentUser::hasSession() && !empty(CurrentUser::getField('language')) && isset($languages[CurrentUser::getField('language')])) {
|
||||
// default: use language from session, #277
|
||||
$language = CurrentUser::getField('language');
|
||||
} else {
|
||||
if (!CurrentUser::hasSession()) {
|
||||
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
||||
$accept_langs = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
|
||||
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.
|
||||
if (isset($iso[substr($accept_langs[$i], 0, 2)])) {
|
||||
$language = $iso[substr($accept_langs[$i], 0, 2)];
|
||||
break;
|
||||
}
|
||||
}
|
||||
unset($iso);
|
||||
|
||||
// if HTTP_ACCEPT_LANGUAGES has no valid langs, use default (very unlikely)
|
||||
if (!strlen($language) > 0) {
|
||||
$language = Settings::Get('panel.standardlanguage');
|
||||
}
|
||||
}
|
||||
// set language by given user
|
||||
if (CurrentUser::hasSession()) {
|
||||
if (!empty(CurrentUser::getField('language')) && isset(Language::getLanguages()[CurrentUser::getField('language')])) {
|
||||
Language::setLanguage(CurrentUser::getField('language'));
|
||||
} else {
|
||||
$language = CurrentUser::getField('def_language');
|
||||
Language::setLanguage(CurrentUser::getField('def_language'));
|
||||
}
|
||||
}
|
||||
|
||||
// include every english language file we can get
|
||||
foreach ($langs['English'] as $key => $value) {
|
||||
include_once \Froxlor\FileDir::makeSecurePath($value['file']);
|
||||
}
|
||||
|
||||
// now include the selected language if its not english
|
||||
if ($language != 'English') {
|
||||
foreach ($langs[$language] as $key => $value) {
|
||||
include_once \Froxlor\FileDir::makeSecurePath($value['file']);
|
||||
}
|
||||
}
|
||||
|
||||
// last but not least include language references file
|
||||
include_once \Froxlor\FileDir::makeSecurePath('lng/lng_references.php');
|
||||
|
||||
UI::setLng($lng);
|
||||
|
||||
// Initialize our link - class
|
||||
$linker = new \Froxlor\UI\Linker('index.php');
|
||||
UI::setLinker($linker);
|
||||
|
||||
/**
|
||||
* global Theme-variable
|
||||
* Global Theme-variable
|
||||
*/
|
||||
$theme = (Settings::Get('panel.default_theme') !== null) ? Settings::Get('panel.default_theme') : $_deftheme;
|
||||
|
||||
/**
|
||||
* overwrite with customer/admin theme if defined
|
||||
* Overwrite with customer/admin theme if defined
|
||||
*/
|
||||
if (CurrentUser::hasSession() && CurrentUser::getField('theme') != $theme) {
|
||||
$theme = CurrentUser::getField('theme');
|
||||
|
||||
Reference in New Issue
Block a user