Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c236d9eaab | ||
|
|
688994e40c | ||
|
|
9facaee809 | ||
|
|
a7dd5f4685 | ||
|
|
da810ea953 | ||
|
|
51b6e067e8 | ||
|
|
34cf6698bc | ||
|
|
4642160724 | ||
|
|
78a259ef3b | ||
|
|
68cf4ab69a | ||
|
|
d5661d492d | ||
|
|
6900898ae1 | ||
|
|
d90fb7fa68 |
@@ -28,7 +28,7 @@ require __DIR__ . '/lib/init.php';
|
|||||||
|
|
||||||
use Froxlor\Froxlor;
|
use Froxlor\Froxlor;
|
||||||
use Froxlor\FroxlorLogger;
|
use Froxlor\FroxlorLogger;
|
||||||
use Froxlor\Http\HttpClient;
|
use Froxlor\FileDir;
|
||||||
use Froxlor\Install\AutoUpdate;
|
use Froxlor\Install\AutoUpdate;
|
||||||
use Froxlor\Settings;
|
use Froxlor\Settings;
|
||||||
use Froxlor\UI\Panel\UI;
|
use Froxlor\UI\Panel\UI;
|
||||||
@@ -132,7 +132,7 @@ elseif ($page == 'getdownload') {
|
|||||||
elseif ($page == 'extract') {
|
elseif ($page == 'extract') {
|
||||||
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
if (isset($_POST['send']) && $_POST['send'] == 'send') {
|
||||||
$toExtract = isset($_POST['archive']) ? $_POST['archive'] : null;
|
$toExtract = isset($_POST['archive']) ? $_POST['archive'] : null;
|
||||||
$localArchive = Froxlor::getInstallDir() . '/updates/' . $toExtract;
|
$localArchive = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/updates/' . $toExtract);
|
||||||
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Extracting " . $localArchive . " to " . Froxlor::getInstallDir());
|
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "Extracting " . $localArchive . " to " . Froxlor::getInstallDir());
|
||||||
$result = AutoUpdate::extractZip($localArchive);
|
$result = AutoUpdate::extractZip($localArchive);
|
||||||
if ($result > 0) {
|
if ($result > 0) {
|
||||||
@@ -146,7 +146,7 @@ elseif ($page == 'extract') {
|
|||||||
Response::redirectTo('admin_updates.php');
|
Response::redirectTo('admin_updates.php');
|
||||||
} else {
|
} else {
|
||||||
$toExtract = isset($_GET['archive']) ? $_GET['archive'] : null;
|
$toExtract = isset($_GET['archive']) ? $_GET['archive'] : null;
|
||||||
$localArchive = Froxlor::getInstallDir() . '/updates/' . $toExtract;
|
$localArchive = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/updates/' . $toExtract);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file_exists($localArchive)) {
|
if (!file_exists($localArchive)) {
|
||||||
|
|||||||
61
index.php
61
index.php
@@ -53,9 +53,15 @@ if ($action == '2fa_entercode') {
|
|||||||
Response::redirectTo('index.php');
|
Response::redirectTo('index.php');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
$smessage = isset($_GET['showmessage']) ? (int)$_GET['showmessage'] : 0;
|
||||||
|
$message = "";
|
||||||
|
if ($smessage > 0) {
|
||||||
|
$message = lng('error.2fa_wrongcode');
|
||||||
|
}
|
||||||
// show template to enter code
|
// show template to enter code
|
||||||
UI::view('login/enter2fa.html.twig', [
|
UI::view('login/enter2fa.html.twig', [
|
||||||
'pagetitle' => lng('login.2fa')
|
'pagetitle' => lng('login.2fa'),
|
||||||
|
'message' => $message
|
||||||
]);
|
]);
|
||||||
} elseif ($action == '2fa_verify') {
|
} elseif ($action == '2fa_verify') {
|
||||||
// verify code from 2fa code-enter form
|
// verify code from 2fa code-enter form
|
||||||
@@ -68,25 +74,25 @@ if ($action == '2fa_entercode') {
|
|||||||
// verify entered code
|
// verify entered code
|
||||||
$tfa = new FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
|
$tfa = new FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
|
||||||
$result = ($_SESSION['secret_2fa'] == 'email' ? true : $tfa->verifyCode($_SESSION['secret_2fa'], $code, 3));
|
$result = ($_SESSION['secret_2fa'] == 'email' ? true : $tfa->verifyCode($_SESSION['secret_2fa'], $code, 3));
|
||||||
|
// get user-data
|
||||||
|
$table = $_SESSION['uidtable_2fa'];
|
||||||
|
$field = $_SESSION['uidfield_2fa'];
|
||||||
|
$uid = $_SESSION['uid_2fa'];
|
||||||
|
$isadmin = $_SESSION['unfo_2fa'];
|
||||||
// either the code is valid when using authenticator-app, or we will select userdata by id and entered code
|
// either the code is valid when using authenticator-app, or we will select userdata by id and entered code
|
||||||
// which is temporarily stored for the customer when using email-2fa
|
// which is temporarily stored for the customer when using email-2fa
|
||||||
if ($result) {
|
if ($result) {
|
||||||
// get user-data
|
|
||||||
$table = $_SESSION['uidtable_2fa'];
|
|
||||||
$field = $_SESSION['uidfield_2fa'];
|
|
||||||
$uid = $_SESSION['uid_2fa'];
|
|
||||||
$isadmin = $_SESSION['unfo_2fa'];
|
|
||||||
$sel_param = [
|
$sel_param = [
|
||||||
'uid' => $uid
|
'uid' => $uid
|
||||||
];
|
];
|
||||||
if ($_SESSION['secret_2fa'] == 'email') {
|
if ($_SESSION['secret_2fa'] == 'email') {
|
||||||
// verify code by selecting user by id and the temp. stored code,
|
// verify code by selecting user by id and the temp. stored code,
|
||||||
// so only if it's the correct code, we get the user-data
|
// so only if it's the correct code, we get the user-data
|
||||||
$sel_stmt = Database::prepare("SELECT * FROM $table WHERE `" . $field . "` = :uid AND `data_2fa` = :code");
|
$sel_stmt = Database::prepare("SELECT * FROM " . $table . " WHERE `" . $field . "` = :uid AND `data_2fa` = :code");
|
||||||
$sel_param['code'] = $code;
|
$sel_param['code'] = $code;
|
||||||
} else {
|
} else {
|
||||||
// Authenticator-verification has already happened at this point, so just get the user-data
|
// Authenticator-verification has already happened at this point, so just get the user-data
|
||||||
$sel_stmt = Database::prepare("SELECT * FROM $table WHERE `" . $field . "` = :uid");
|
$sel_stmt = Database::prepare("SELECT * FROM " . $table . " WHERE `" . $field . "` = :uid");
|
||||||
}
|
}
|
||||||
$userinfo = Database::pexecute_first($sel_stmt, $sel_param);
|
$userinfo = Database::pexecute_first($sel_stmt, $sel_param);
|
||||||
// whoops, no (valid) user? Start again
|
// whoops, no (valid) user? Start again
|
||||||
@@ -108,15 +114,50 @@ if ($action == '2fa_entercode') {
|
|||||||
|
|
||||||
// when using email-2fa, remove the one-time-code
|
// when using email-2fa, remove the one-time-code
|
||||||
if ($userinfo['type_2fa'] == '1') {
|
if ($userinfo['type_2fa'] == '1') {
|
||||||
$del_stmt = Database::prepare("UPDATE $table SET `data_2fa` = '' WHERE `" . $field . "` = :uid");
|
$del_stmt = Database::prepare("UPDATE " . $table . " SET `data_2fa` = '' WHERE `" . $field . "` = :uid");
|
||||||
$userinfo = Database::pexecute_first($del_stmt, [
|
$userinfo = Database::pexecute_first($del_stmt, [
|
||||||
'uid' => $uid
|
'uid' => $uid
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
// wrong 2fa code - treat like "wrong password"
|
||||||
|
$stmt = Database::prepare("
|
||||||
|
UPDATE " . $table . "
|
||||||
|
SET `lastlogin_fail`= :lastlogin_fail, `loginfail_count`=`loginfail_count`+1
|
||||||
|
WHERE `" . $field . "`= :uid
|
||||||
|
");
|
||||||
|
Database::pexecute($stmt, [
|
||||||
|
"lastlogin_fail" => time(),
|
||||||
|
"uid" => $uid
|
||||||
|
]);
|
||||||
|
|
||||||
|
// get data for processing further
|
||||||
|
$stmt = Database::prepare("
|
||||||
|
SELECT `loginname`, `loginfail_count`, `lastlogin_fail` FROM " . $table . "
|
||||||
|
WHERE `" . $field . "`= :uid
|
||||||
|
");
|
||||||
|
$fail_user = Database::pexecute_first($stmt, [
|
||||||
|
"uid" => $uid
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ($fail_user['loginfail_count'] >= Settings::Get('login.maxloginattempts') && $fail_user['lastlogin_fail'] > (time() - Settings::Get('login.deactivatetime'))) {
|
||||||
|
// Log failed login
|
||||||
|
$rstlog = FroxlorLogger::getInstanceOf([
|
||||||
|
'loginname' => $_SERVER['REMOTE_ADDR']
|
||||||
|
]);
|
||||||
|
$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User '" . $fail_user['loginname'] . "' entered wrong 2fa code too often.");
|
||||||
|
unset($fail_user);
|
||||||
|
Response::redirectTo('index.php', [
|
||||||
|
'showmessage' => '3'
|
||||||
|
]);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
unset($fail_user);
|
||||||
|
// back to form
|
||||||
Response::redirectTo('index.php', [
|
Response::redirectTo('index.php', [
|
||||||
'showmessage' => '2'
|
'action' => '2fa_entercode',
|
||||||
|
'showmessage' => '1'
|
||||||
]);
|
]);
|
||||||
exit();
|
exit();
|
||||||
} elseif ($action == 'login') {
|
} elseif ($action == 'login') {
|
||||||
|
|||||||
@@ -697,7 +697,7 @@ opcache.validate_timestamps'),
|
|||||||
('system', 'distribution', ''),
|
('system', 'distribution', ''),
|
||||||
('system', 'update_channel', 'stable'),
|
('system', 'update_channel', 'stable'),
|
||||||
('system', 'updatecheck_data', ''),
|
('system', 'updatecheck_data', ''),
|
||||||
('system', 'update_notify_last', '2.0.17'),
|
('system', 'update_notify_last', '2.0.20'),
|
||||||
('system', 'traffictool', 'goaccess'),
|
('system', 'traffictool', 'goaccess'),
|
||||||
('system', 'req_limit_per_interval', 60),
|
('system', 'req_limit_per_interval', 60),
|
||||||
('system', 'req_limit_interval', 60),
|
('system', 'req_limit_interval', 60),
|
||||||
@@ -744,7 +744,7 @@ opcache.validate_timestamps'),
|
|||||||
('panel', 'logo_overridetheme', '0'),
|
('panel', 'logo_overridetheme', '0'),
|
||||||
('panel', 'logo_overridecustom', '0'),
|
('panel', 'logo_overridecustom', '0'),
|
||||||
('panel', 'settings_mode', '0'),
|
('panel', 'settings_mode', '0'),
|
||||||
('panel', 'version', '2.0.17'),
|
('panel', 'version', '2.0.20'),
|
||||||
('panel', 'db_version', '202304260');
|
('panel', 'db_version', '202304260');
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -482,3 +482,18 @@ if (Froxlor::isFroxlorVersion('2.0.16')) {
|
|||||||
Update::showUpdateStep("Updating from 2.0.16 to 2.0.17", false);
|
Update::showUpdateStep("Updating from 2.0.16 to 2.0.17", false);
|
||||||
Froxlor::updateToVersion('2.0.17');
|
Froxlor::updateToVersion('2.0.17');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.17')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.17 to 2.0.18", false);
|
||||||
|
Froxlor::updateToVersion('2.0.18');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.18')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.18 to 2.0.19", false);
|
||||||
|
Froxlor::updateToVersion('2.0.19');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Froxlor::isFroxlorVersion('2.0.19')) {
|
||||||
|
Update::showUpdateStep("Updating from 2.0.19 to 2.0.20", false);
|
||||||
|
Froxlor::updateToVersion('2.0.20');
|
||||||
|
}
|
||||||
|
|||||||
@@ -99,6 +99,11 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
Response::standardError('notallowedtouseaccounts', '', true);
|
Response::standardError('notallowedtouseaccounts', '', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($emailaddr)) {
|
||||||
|
$idna_convert = new IdnaWrapper();
|
||||||
|
$emailaddr = $idna_convert->encode($emailaddr);
|
||||||
|
}
|
||||||
|
|
||||||
// get email address
|
// get email address
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
@@ -357,6 +362,11 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
|
|||||||
$ea_optional = $id > 0;
|
$ea_optional = $id > 0;
|
||||||
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
|
$emailaddr = $this->getParam('emailaddr', $ea_optional, '');
|
||||||
|
|
||||||
|
if (!empty($emailaddr)) {
|
||||||
|
$idna_convert = new IdnaWrapper();
|
||||||
|
$emailaddr = $idna_convert->encode($emailaddr);
|
||||||
|
}
|
||||||
|
|
||||||
// validation
|
// validation
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
|
|||||||
@@ -77,6 +77,11 @@ class EmailForwarders extends ApiCommand implements ResourceEntity
|
|||||||
$idna_convert = new IdnaWrapper();
|
$idna_convert = new IdnaWrapper();
|
||||||
$destination = $idna_convert->encode($destination);
|
$destination = $idna_convert->encode($destination);
|
||||||
|
|
||||||
|
if (!empty($emailaddr)) {
|
||||||
|
$idna_convert = new IdnaWrapper();
|
||||||
|
$emailaddr = $idna_convert->encode($emailaddr);
|
||||||
|
}
|
||||||
|
|
||||||
$result = $this->apiCall('Emails.get', [
|
$result = $this->apiCall('Emails.get', [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'emailaddr' => $emailaddr
|
'emailaddr' => $emailaddr
|
||||||
|
|||||||
@@ -1171,7 +1171,6 @@ class Nginx extends HttpConfigBase
|
|||||||
$phpopts .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n";
|
$phpopts .= "\t\tinclude " . Settings::Get('nginx.fastcgiparams') . ";\n";
|
||||||
$phpopts .= "\t\tfastcgi_param SCRIPT_FILENAME \$request_filename;\n";
|
$phpopts .= "\t\tfastcgi_param SCRIPT_FILENAME \$request_filename;\n";
|
||||||
$phpopts .= "\t\tfastcgi_param PATH_INFO \$fastcgi_path_info;\n";
|
$phpopts .= "\t\tfastcgi_param PATH_INFO \$fastcgi_path_info;\n";
|
||||||
$phpopts .= "\t\ttry_files \$fastcgi_script_name =404;\n";
|
|
||||||
$phpopts .= "\t\tfastcgi_pass " . Settings::Get('system.nginx_php_backend') . ";\n";
|
$phpopts .= "\t\tfastcgi_pass " . Settings::Get('system.nginx_php_backend') . ";\n";
|
||||||
$phpopts .= "\t\tfastcgi_index index.php;\n";
|
$phpopts .= "\t\tfastcgi_index index.php;\n";
|
||||||
if ($domain['ssl'] == '1' && $ssl_vhost) {
|
if ($domain['ssl'] == '1' && $ssl_vhost) {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ final class Froxlor
|
|||||||
{
|
{
|
||||||
|
|
||||||
// Main version variable
|
// Main version variable
|
||||||
const VERSION = '2.0.17';
|
const VERSION = '2.0.20';
|
||||||
|
|
||||||
// Database version (YYYYMMDDC where C is a daily counter)
|
// Database version (YYYYMMDDC where C is a daily counter)
|
||||||
const DBVERSION = '202304260';
|
const DBVERSION = '202304260';
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class Install
|
|||||||
public $phpVersion;
|
public $phpVersion;
|
||||||
public $formfield;
|
public $formfield;
|
||||||
public string $requiredVersion = '7.4.0';
|
public string $requiredVersion = '7.4.0';
|
||||||
public array $requiredExtensions = ['session', 'ctype', 'mysql', 'xml', 'filter', 'posix', 'mbstring', 'curl', 'gmp', 'json', 'gd'];
|
public array $requiredExtensions = ['session', 'ctype', 'xml', 'filter', 'posix', 'mbstring', 'curl', 'gmp', 'json', 'gd'];
|
||||||
public array $suggestedExtensions = ['bcmath', 'zip'];
|
public array $suggestedExtensions = ['bcmath', 'zip'];
|
||||||
public array $suggestions = [];
|
public array $suggestions = [];
|
||||||
public array $criticals = [];
|
public array $criticals = [];
|
||||||
|
|||||||
@@ -87,16 +87,38 @@ class UI
|
|||||||
|
|
||||||
return $isHttps && (strcasecmp('on', $isHttps) == 0 || strcasecmp('https', $isHttps) == 0);
|
return $isHttps && (strcasecmp('on', $isHttps) == 0 || strcasecmp('https', $isHttps) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the cookie host from HTTP_HOST, stripping the port.
|
||||||
|
*/
|
||||||
|
public static function getCookieHost(): ?string
|
||||||
|
{
|
||||||
|
if (empty($_SERVER['HTTP_HOST']))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
$colonPosition = strrpos($_SERVER['HTTP_HOST'], ':');
|
||||||
|
// There's no port in the host
|
||||||
|
if ($colonPosition === false)
|
||||||
|
return $_SERVER['HTTP_HOST'];
|
||||||
|
|
||||||
|
$closingSquareBracketPosition = strrpos($_SERVER['HTTP_HOST'], ']');
|
||||||
|
// The host is an IPv4 address or hostname with port
|
||||||
|
if ($closingSquareBracketPosition === false)
|
||||||
|
return substr($_SERVER['HTTP_HOST'], 0, $colonPosition);
|
||||||
|
|
||||||
|
// The host is an IPv6 address with port
|
||||||
|
return substr($_SERVER['HTTP_HOST'], 0, $closingSquareBracketPosition + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* send various security related headers
|
* send various security related headers
|
||||||
*/
|
*/
|
||||||
public static function sendHeaders()
|
public static function sendHeaders()
|
||||||
{
|
{
|
||||||
$cookie_host = empty($_SERVER['HTTP_HOST']) ? null : explode (':', $_SERVER['HTTP_HOST'])[0];
|
|
||||||
session_set_cookie_params([
|
session_set_cookie_params([
|
||||||
'lifetime' => self::$install_mode ? 7200 : 600, // will be renewed based on settings in lib/init.php
|
'lifetime' => self::$install_mode ? 7200 : 600, // will be renewed based on settings in lib/init.php
|
||||||
'path' => '/',
|
'path' => '/',
|
||||||
'domain' => $cookie_host,
|
'domain' => self::getCookieHost(),
|
||||||
'secure' => self::requestIsHttps(),
|
'secure' => self::requestIsHttps(),
|
||||||
'httponly' => true,
|
'httponly' => true,
|
||||||
'samesite' => 'Strict'
|
'samesite' => 'Strict'
|
||||||
|
|||||||
@@ -52,16 +52,16 @@ class Check
|
|||||||
];
|
];
|
||||||
|
|
||||||
$check_array = [
|
$check_array = [
|
||||||
'system_mod_fcgid_enabled' => [
|
'system_mod_fcgid' => [
|
||||||
'other_post_field' => 'system_phpfpm_enabled',
|
'other_post_field' => 'phpfpm_enabled',
|
||||||
'other_enabled' => 'phpfpm.enabled',
|
'other_enabled' => 'phpfpm.enabled',
|
||||||
'other_enabled_lng' => 'phpfpmstillenabled',
|
'other_enabled_lng' => 'phpfpmstillenabled',
|
||||||
'deactivate' => [
|
'deactivate' => [
|
||||||
'phpfpm.enabled_ownvhost' => 0
|
'phpfpm.enabled_ownvhost' => 0
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'system_phpfpm_enabled' => [
|
'phpfpm_enabled' => [
|
||||||
'other_post_field' => 'system_mod_fcgid_enabled',
|
'other_post_field' => 'system_mod_fcgid',
|
||||||
'other_enabled' => 'system.mod_fcgid',
|
'other_enabled' => 'system.mod_fcgid',
|
||||||
'other_enabled_lng' => 'fcgidstillenabled',
|
'other_enabled_lng' => 'fcgidstillenabled',
|
||||||
'deactivate' => [
|
'deactivate' => [
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ return [
|
|||||||
'customers' => [
|
'customers' => [
|
||||||
'label' => lng('admin.customers'),
|
'label' => lng('admin.customers'),
|
||||||
'type' => 'textul',
|
'type' => 'textul',
|
||||||
'value' => $result['customers'],
|
'value' => empty($result['customers']) ? '0' : $result['customers'],
|
||||||
'maxlength' => 9,
|
'maxlength' => 9,
|
||||||
'mandatory' => true
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
@@ -146,7 +146,7 @@ return [
|
|||||||
'domains' => [
|
'domains' => [
|
||||||
'label' => lng('admin.domains'),
|
'label' => lng('admin.domains'),
|
||||||
'type' => 'textul',
|
'type' => 'textul',
|
||||||
'value' => $result['domains'],
|
'value' => empty($result['domains']) ? '0' : $result['domains'],
|
||||||
'maxlength' => 9,
|
'maxlength' => 9,
|
||||||
'mandatory' => true
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
@@ -159,49 +159,49 @@ return [
|
|||||||
'diskspace' => [
|
'diskspace' => [
|
||||||
'label' => lng('customer.diskspace') . ' (' . lng('customer.mib') . ')',
|
'label' => lng('customer.diskspace') . ' (' . lng('customer.mib') . ')',
|
||||||
'type' => 'textul',
|
'type' => 'textul',
|
||||||
'value' => $result['diskspace'],
|
'value' => empty($result['diskspace']) ? '0' : $result['diskspace'],
|
||||||
'maxlength' => 6,
|
'maxlength' => 6,
|
||||||
'mandatory' => true
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
'traffic' => [
|
'traffic' => [
|
||||||
'label' => lng('customer.traffic') . ' (' . lng('customer.gib') . ')',
|
'label' => lng('customer.traffic') . ' (' . lng('customer.gib') . ')',
|
||||||
'type' => 'textul',
|
'type' => 'textul',
|
||||||
'value' => $result['traffic'],
|
'value' => empty($result['traffic']) ? '0' : $result['traffic'],
|
||||||
'maxlength' => 4,
|
'maxlength' => 4,
|
||||||
'mandatory' => true
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
'subdomains' => [
|
'subdomains' => [
|
||||||
'label' => lng('customer.subdomains'),
|
'label' => lng('customer.subdomains'),
|
||||||
'type' => 'textul',
|
'type' => 'textul',
|
||||||
'value' => $result['subdomains'],
|
'value' => empty($result['subdomains']) ? '0' : $result['subdomains'],
|
||||||
'maxlength' => 9,
|
'maxlength' => 9,
|
||||||
'mandatory' => true
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
'emails' => [
|
'emails' => [
|
||||||
'label' => lng('customer.emails'),
|
'label' => lng('customer.emails'),
|
||||||
'type' => 'textul',
|
'type' => 'textul',
|
||||||
'value' => $result['emails'],
|
'value' => empty($result['emails']) ? '0' : $result['emails'],
|
||||||
'maxlength' => 9,
|
'maxlength' => 9,
|
||||||
'mandatory' => true
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
'email_accounts' => [
|
'email_accounts' => [
|
||||||
'label' => lng('customer.accounts'),
|
'label' => lng('customer.accounts'),
|
||||||
'type' => 'textul',
|
'type' => 'textul',
|
||||||
'value' => $result['email_accounts'],
|
'value' => empty($result['email_accounts']) ? '0' : $result['email_accounts'],
|
||||||
'maxlength' => 9,
|
'maxlength' => 9,
|
||||||
'mandatory' => true
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
'email_forwarders' => [
|
'email_forwarders' => [
|
||||||
'label' => lng('customer.forwarders'),
|
'label' => lng('customer.forwarders'),
|
||||||
'type' => 'textul',
|
'type' => 'textul',
|
||||||
'value' => $result['email_forwarders'],
|
'value' => empty($result['email_forwarders']) ? '0' : $result['email_forwarders'],
|
||||||
'maxlength' => 9,
|
'maxlength' => 9,
|
||||||
'mandatory' => true
|
'mandatory' => true
|
||||||
],
|
],
|
||||||
'email_quota' => [
|
'email_quota' => [
|
||||||
'label' => lng('customer.email_quota') . ' (' . lng('customer.mib') . ')',
|
'label' => lng('customer.email_quota') . ' (' . lng('customer.mib') . ')',
|
||||||
'type' => 'textul',
|
'type' => 'textul',
|
||||||
'value' => $result['email_quota'],
|
'value' => empty($result['email_quota']) ? '0' : $result['email_quota'],
|
||||||
'maxlength' => 9,
|
'maxlength' => 9,
|
||||||
'visible' => Settings::Get('system.mail_quota_enabled') == '1',
|
'visible' => Settings::Get('system.mail_quota_enabled') == '1',
|
||||||
'mandatory' => true
|
'mandatory' => true
|
||||||
@@ -209,13 +209,13 @@ return [
|
|||||||
'ftps' => [
|
'ftps' => [
|
||||||
'label' => lng('customer.ftps'),
|
'label' => lng('customer.ftps'),
|
||||||
'type' => 'textul',
|
'type' => 'textul',
|
||||||
'value' => $result['ftps'],
|
'value' => empty($result['ftps']) ? '0' : $result['ftps'],
|
||||||
'maxlength' => 9
|
'maxlength' => 9
|
||||||
],
|
],
|
||||||
'mysqls' => [
|
'mysqls' => [
|
||||||
'label' => lng('customer.mysqls'),
|
'label' => lng('customer.mysqls'),
|
||||||
'type' => 'textul',
|
'type' => 'textul',
|
||||||
'value' => $result['mysqls'],
|
'value' => empty($result['mysqls']) ? '0' : $result['mysqls'],
|
||||||
'maxlength' => 9,
|
'maxlength' => 9,
|
||||||
'mandatory' => true
|
'mandatory' => true
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -43,13 +43,16 @@ return [
|
|||||||
'email_password' => [
|
'email_password' => [
|
||||||
'label' => lng('login.password'),
|
'label' => lng('login.password'),
|
||||||
'type' => 'password',
|
'type' => 'password',
|
||||||
'autocomplete' => 'off'
|
'autocomplete' => 'off',
|
||||||
],
|
'next_to' => [
|
||||||
'email_password_suggestion' => [
|
'email_password_suggestion' => [
|
||||||
'label' => lng('customer.generated_pwd'),
|
'next_to_prefix' => lng('customer.generated_pwd') . ':',
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'visible' => (Settings::Get('panel.password_regex') == ''),
|
'visible' => (Settings::Get('panel.password_regex') == ''),
|
||||||
'value' => Crypt::generatePassword()
|
'value' => Crypt::generatePassword(),
|
||||||
|
'readonly' => true
|
||||||
|
]
|
||||||
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ return [
|
|||||||
'autocomplete' => 'off',
|
'autocomplete' => 'off',
|
||||||
'mandatory' => true,
|
'mandatory' => true,
|
||||||
'next_to' => [
|
'next_to' => [
|
||||||
'admin_password_suggestion' => [
|
'email_password_suggestion' => [
|
||||||
'next_to_prefix' => lng('customer.generated_pwd') . ':',
|
'next_to_prefix' => lng('customer.generated_pwd') . ':',
|
||||||
'type' => 'text',
|
'type' => 'text',
|
||||||
'visible' => (Settings::Get('panel.password_regex') == ''),
|
'visible' => (Settings::Get('panel.password_regex') == ''),
|
||||||
|
|||||||
@@ -331,11 +331,10 @@ if (CurrentUser::hasSession()) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// update cookie lifetime
|
// update cookie lifetime
|
||||||
$cookie_host = empty($_SERVER['HTTP_HOST']) ? null : explode (':', $_SERVER['HTTP_HOST'])[0];
|
|
||||||
$cookie_params = [
|
$cookie_params = [
|
||||||
'expires' => time() + Settings::Get('session.sessiontimeout'),
|
'expires' => time() + Settings::Get('session.sessiontimeout'),
|
||||||
'path' => '/',
|
'path' => '/',
|
||||||
'domain' => $cookie_host,
|
'domain' => UI::getCookieHost(),
|
||||||
'secure' => UI::requestIsHttps(),
|
'secure' => UI::requestIsHttps(),
|
||||||
'httponly' => true,
|
'httponly' => true,
|
||||||
'samesite' => 'Strict'
|
'samesite' => 'Strict'
|
||||||
|
|||||||
@@ -926,6 +926,7 @@ return [
|
|||||||
'domaincannotbeedited' => 'Keine Berechtigung, um die Domain %s zu bearbeiten',
|
'domaincannotbeedited' => 'Keine Berechtigung, um die Domain %s zu bearbeiten',
|
||||||
'invalidcronjobintervalvalue' => 'Cronjob Intervall muss einer der folgenden Werte sein: %s',
|
'invalidcronjobintervalvalue' => 'Cronjob Intervall muss einer der folgenden Werte sein: %s',
|
||||||
'phpgdextensionnotavailable' => 'Die PHP GD Extension ist nicht verfügbar. Bild-Daten können nicht validiert werden.',
|
'phpgdextensionnotavailable' => 'Die PHP GD Extension ist nicht verfügbar. Bild-Daten können nicht validiert werden.',
|
||||||
|
'2fa_wrongcode' => 'Der angegebene Code ist nicht korrekt',
|
||||||
],
|
],
|
||||||
'extras' => [
|
'extras' => [
|
||||||
'description' => 'Hier können Sie zusätzliche Extras einrichten, wie zum Beispiel einen Verzeichnisschutz.<br />Die Änderungen sind erst nach einer kurzen Zeit wirksam.',
|
'description' => 'Hier können Sie zusätzliche Extras einrichten, wie zum Beispiel einen Verzeichnisschutz.<br />Die Änderungen sind erst nach einer kurzen Zeit wirksam.',
|
||||||
|
|||||||
@@ -995,6 +995,7 @@ return [
|
|||||||
'domaincannotbeedited' => 'You are not permitted to edit the domain %s',
|
'domaincannotbeedited' => 'You are not permitted to edit the domain %s',
|
||||||
'invalidcronjobintervalvalue' => 'Cronjob interval must be one of: %s',
|
'invalidcronjobintervalvalue' => 'Cronjob interval must be one of: %s',
|
||||||
'phpgdextensionnotavailable' => 'The PHP GD extension is not available. Unable to validate image-data',
|
'phpgdextensionnotavailable' => 'The PHP GD extension is not available. Unable to validate image-data',
|
||||||
|
'2fa_wrongcode' => 'The code entered is not valid',
|
||||||
],
|
],
|
||||||
'extras' => [
|
'extras' => [
|
||||||
'description' => 'Here you can add some extras, for example directory protection.<br />The system will need some time to apply the new settings after every change.',
|
'description' => 'Here you can add some extras, for example directory protection.<br />The system will need some time to apply the new settings after every change.',
|
||||||
@@ -1193,7 +1194,7 @@ Yours sincerely, your administrator',
|
|||||||
'database_edit' => 'Edit database',
|
'database_edit' => 'Edit database',
|
||||||
'size' => 'Size',
|
'size' => 'Size',
|
||||||
'privileged_user' => 'Privileged database user',
|
'privileged_user' => 'Privileged database user',
|
||||||
'privileged_passwd' => 'Password for priviliged user',
|
'privileged_passwd' => 'Password for privileged user',
|
||||||
'unprivileged_passwd' => 'Password for unprivileged user',
|
'unprivileged_passwd' => 'Password for unprivileged user',
|
||||||
'mysql_ssl_ca_file' => 'SSL server certificate',
|
'mysql_ssl_ca_file' => 'SSL server certificate',
|
||||||
'mysql_ssl_verify_server_certificate' => 'Verify SSL server certificate'
|
'mysql_ssl_verify_server_certificate' => 'Verify SSL server certificate'
|
||||||
|
|||||||
@@ -10,6 +10,13 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">{{ pagetitle }}</h5>
|
<h5 class="card-title">{{ pagetitle }}</h5>
|
||||||
|
|
||||||
|
{% if message is not empty %}
|
||||||
|
<div class="alert alert-danger" role="alert">
|
||||||
|
<h4 class="alert-heading">{{ lng('error.error') }}</h4>
|
||||||
|
<p>{{ message|raw }}</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="2fa_code" class="col-form-label">{{ lng('login.2facode') }}</label>
|
<label for="2fa_code" class="col-form-label">{{ lng('login.2facode') }}</label>
|
||||||
<input class="form-control" type="text" name="2fa_code" id="2fa_code" value="" autocomplete="off" autofocus required/>
|
<input class="form-control" type="text" name="2fa_code" id="2fa_code" value="" autocomplete="off" autofocus required/>
|
||||||
|
|||||||
Reference in New Issue
Block a user