diff --git a/api_keys.php b/api_keys.php
index 1a110ce4..f1bec666 100644
--- a/api_keys.php
+++ b/api_keys.php
@@ -1,5 +1,5 @@
0) {
- $chk = (AREA == 'admin' && $userinfo['customers_see_all'] == '1') ? true : false;
- if (AREA == 'customer') {
- $chk_stmt = Database::prepare("
- SELECT c.customerid FROM `" . TABLE_PANEL_CUSTOMERS . "` c
- LEFT JOIN `" . TABLE_API_KEYS . "` ak ON ak.customerid = c.customerid
- WHERE ak.`id` = :id AND c.`customerid` = :cid
- ");
- $chk = Database::pexecute_first($chk_stmt, array(
- 'id' => $id,
- 'cid' => $userinfo['customerid']
- ));
- } elseif (AREA == 'admin' && $userinfo['customers_see_all'] == '0') {
- $chk_stmt = Database::prepare("
- SELECT a.adminid FROM `" . TABLE_PANEL_ADMINS . "` a
- LEFT JOIN `" . TABLE_API_KEYS . "` ak ON ak.adminid = a.adminid
- WHERE ak.`id` = :id AND a.`adminid` = :aid
- ");
- $chk = Database::pexecute_first($chk_stmt, array(
- 'id' => $id,
- 'aid' => $userinfo['adminid']
- ));
- }
- if ($chk !== false) {
- Database::pexecute($del_stmt, array(
+ if (isset($_POST['send']) && $_POST['send'] == 'send') {
+ $chk = (AREA == 'admin' && $userinfo['customers_see_all'] == '1') ? true : false;
+ if (AREA == 'customer') {
+ $chk_stmt = Database::prepare("
+ SELECT c.customerid FROM `" . TABLE_PANEL_CUSTOMERS . "` c
+ LEFT JOIN `" . TABLE_API_KEYS . "` ak ON ak.customerid = c.customerid
+ WHERE ak.`id` = :id AND c.`customerid` = :cid
+ ");
+ $chk = Database::pexecute_first($chk_stmt, array(
+ 'id' => $id,
+ 'cid' => $userinfo['customerid']
+ ));
+ } elseif (AREA == 'admin' && $userinfo['customers_see_all'] == '0') {
+ $chk_stmt = Database::prepare("
+ SELECT a.adminid FROM `" . TABLE_PANEL_ADMINS . "` a
+ LEFT JOIN `" . TABLE_API_KEYS . "` ak ON ak.adminid = a.adminid
+ WHERE ak.`id` = :id AND a.`adminid` = :aid
+ ");
+ $chk = Database::pexecute_first($chk_stmt, array(
+ 'id' => $id,
+ 'aid' => $userinfo['adminid']
+ ));
+ }
+ if ($chk !== false) {
+ Database::pexecute($del_stmt, array(
+ 'id' => $id
+ ));
+ $success_message = sprintf($lng['apikeys']['apikey_removed'], $id);
+ }
+ } else {
+ \Froxlor\UI\HTML::askYesNo('api_reallydelete', $filename, array(
+ 'page' => $page,
+ 'action' => $action,
'id' => $id
- ));
- $success_message = sprintf($lng['apikeys']['apikey_removed'], $id);
+ ), $id);
}
}
} elseif ($action == 'add') {
- $ins_stmt = Database::prepare("
- INSERT INTO `" . TABLE_API_KEYS . "` SET
- `apikey` = :key, `secret` = :secret, `adminid` = :aid, `customerid` = :cid, `valid_until` = '-1', `allowed_from` = ''
- ");
- // customer generates for himself, admins will see a customer-select-box later
- if (AREA == 'admin') {
- $cid = 0;
- } elseif (AREA == 'customer') {
- $cid = $userinfo['customerid'];
+
+ if (isset($_POST['send']) && $_POST['send'] == 'send') {
+ $ins_stmt = Database::prepare("
+ INSERT INTO `" . TABLE_API_KEYS . "` SET
+ `apikey` = :key, `secret` = :secret, `adminid` = :aid, `customerid` = :cid, `valid_until` = '-1', `allowed_from` = ''
+ ");
+ // customer generates for himself, admins will see a customer-select-box later
+ if (AREA == 'admin') {
+ $cid = 0;
+ } elseif (AREA == 'customer') {
+ $cid = $userinfo['customerid'];
+ }
+ $key = hash('sha256', openssl_random_pseudo_bytes(64 * 64));
+ $secret = hash('sha512', openssl_random_pseudo_bytes(64 * 64 * 4));
+ Database::pexecute($ins_stmt, array(
+ 'key' => $key,
+ 'secret' => $secret,
+ 'aid' => $userinfo['adminid'],
+ 'cid' => $cid
+ ));
+ $success_message = $lng['apikeys']['apikey_added'];
+ } else {
+ \Froxlor\UI\HTML::askYesNo('api_reallyadd', $filename, array(
+ 'page' => $page,
+ 'action' => $action
+ ), $id);
}
- $key = hash('sha256', openssl_random_pseudo_bytes(64 * 64));
- $secret = hash('sha512', openssl_random_pseudo_bytes(64 * 64 * 4));
- Database::pexecute($ins_stmt, array(
- 'key' => $key,
- 'secret' => $secret,
- 'aid' => $userinfo['adminid'],
- 'cid' => $cid
- ));
- $success_message = $lng['apikeys']['apikey_added'];
} elseif ($action == 'jqEditApiKey') {
$keyid = isset($_POST['id']) ? (int) $_POST['id'] : 0;
+ if (empty($keyid)) {
+ echo json_encode(false);
+ exit;
+ }
$allowed_from = isset($_POST['allowed_from']) ? $_POST['allowed_from'] : "";
- $valid_until = isset($_POST['valid_until']) ? (int) $_POST['valid_until'] : - 1;
+ $valid_until = isset($_POST['valid_until']) ? (int) $_POST['valid_until'] : -1;
// validate allowed_from
- if (! empty($allowed_from)) {
+ if (!empty($allowed_from)) {
$ip_list = array_map('trim', explode(",", $allowed_from));
$_check_list = $ip_list;
foreach ($_check_list as $idx => $ip) {
@@ -100,8 +120,8 @@ if ($action == 'delete') {
$allowed_from = implode(",", array_unique($ip_list));
}
- if ($valid_until <= 0 || ! is_numeric($valid_until)) {
- $valid_until = - 1;
+ if ($valid_until <= 0 || !is_numeric($valid_until)) {
+ $valid_until = -1;
}
$upd_stmt = Database::prepare("
diff --git a/dns_editor.php b/dns_editor.php
index a5d25eac..da10f5cd 100644
--- a/dns_editor.php
+++ b/dns_editor.php
@@ -24,7 +24,7 @@ use Froxlor\Api\Commands\DomainZones as DomainZones;
// This file is being included in admin_domains and customer_domains
// and therefore does not need to require lib/init.php
-$domain_id = isset($_GET['domain_id']) ? (int) $_GET['domain_id'] : null;
+$domain_id = isset($_GET['domain_id']) ? (int) $_GET['domain_id'] : (isset($_POST['domain_id']) ? (int)$_POST['domain_id'] : null);
$record = isset($_POST['record']['record']) ? trim($_POST['record']['record']) : null;
$type = isset($_POST['record']['type']) ? $_POST['record']['type'] : 'A';
@@ -56,17 +56,25 @@ if ($action == 'add_record' && ! empty($_POST)) {
}
} elseif ($action == 'delete') {
// remove entry
- $entry_id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
- if ($entry_id > 0) {
- try {
- DomainZones::getLocal($userinfo, array(
- 'entry_id' => $entry_id,
- 'id' => $domain_id
- ))->delete();
- // success message (inline)
- $success_message = $lng['success']['dns_record_deleted'];
- } catch (Exception $e) {
- $errors = str_replace("\n", "
", $e->getMessage());
+ if ($id > 0) {
+ if (isset($_POST['send']) && $_POST['send'] == 'send') {
+ try {
+ DomainZones::getLocal($userinfo, array(
+ 'entry_id' => $id,
+ 'id' => $domain_id
+ ))->delete();
+ // success message (inline)
+ $success_message = $lng['success']['dns_record_deleted'];
+ } catch (Exception $e) {
+ $errors = str_replace("\n", "
", $e->getMessage());
+ }
+ } else {
+ \Froxlor\UI\HTML::askYesNo('dnsentry_reallydelete', $filename, array(
+ 'page' => $page,
+ 'action' => $action,
+ 'id' => $id,
+ 'domain_id' => $domain_id
+ ), $id);
}
}
}
diff --git a/index.php b/index.php
index 07a96e82..6e2caa5b 100644
--- a/index.php
+++ b/index.php
@@ -22,6 +22,7 @@ require './lib/init.php';
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\FroxlorLogger;
+use Froxlor\Validate\Validate;
if ($action == '') {
$action = 'login';
@@ -352,8 +353,7 @@ if ($action == '2fa_entercode') {
$message = sprintf($lng['error']['login_blocked'], Settings::Get('login.deactivatetime'));
break;
case 4:
- $cmail = isset($_GET['customermail']) ? $_GET['customermail'] : 'unknown';
- $message = str_replace('%s', $cmail, $lng['error']['errorsendingmail']);
+ $message = $lng['error']['errorsendingmailpub'];
break;
case 5:
$message = $lng['error']['user_banned'];
@@ -425,159 +425,162 @@ if ($action == 'forgotpwd') {
}
}
- if ($result_stmt !== null) {
- $user = $result_stmt->fetch(PDO::FETCH_ASSOC);
-
- /* Check whether user is banned */
- if ($user['deactivated']) {
- \Froxlor\UI\Response::redirectTo('index.php', array(
- 'showmessage' => '8'
- ));
- exit();
+ $no_action = false;
+ if ($adminchecked) {
+ if (Settings::Get('panel.allow_preset_admin') != '1') {
+ $message = $lng['pwdreminder']['notallowed'];
+ unset($adminchecked);
}
+ } else {
+ if (Settings::Get('panel.allow_preset') != '1') {
+ $message = $lng['pwdreminder']['notallowed'];
+ }
+ }
- if (($adminchecked && Settings::Get('panel.allow_preset_admin') == '1') || $adminchecked == false) {
- if ($user !== false) {
- // build a activation code
- $timestamp = time();
- $first = substr(md5($user['loginname'] . $timestamp . \Froxlor\PhpHelper::randomStr(16)), 0, 15);
- $third = substr(md5($user['email'] . $timestamp . \Froxlor\PhpHelper::randomStr(16)), - 15);
- $activationcode = $first . $timestamp . $third . substr(md5($third . $timestamp), 0, 10);
+ if (empty($message)) {
+ if ($result_stmt !== null) {
+ $user = $result_stmt->fetch(PDO::FETCH_ASSOC);
- // Drop all existing activation codes for this user
- $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_ACTIVATION . "`
- WHERE `userid` = :userid
- AND `admin` = :admin");
- $params = array(
- "userid" => $adminchecked ? $user['adminid'] : $user['customerid'],
- "admin" => $adminchecked ? 1 : 0
- );
- Database::pexecute($stmt, $params);
-
- // Add new activation code to database
- $stmt = Database::prepare("INSERT INTO `" . TABLE_PANEL_ACTIVATION . "`
- (userid, admin, creation, activationcode)
- VALUES (:userid, :admin, :creation, :activationcode)");
- $params = array(
- "userid" => $adminchecked ? $user['adminid'] : $user['customerid'],
- "admin" => $adminchecked ? 1 : 0,
- "creation" => $timestamp,
- "activationcode" => $activationcode
- );
- Database::pexecute($stmt, $params);
-
- $rstlog = FroxlorLogger::getInstanceOf(array(
- 'loginname' => 'password_reset'
+ /* Check whether user is banned */
+ if ($user['deactivated']) {
+ \Froxlor\UI\Response::redirectTo('index.php', array(
+ 'showmessage' => '8'
));
- $rstlog->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $user['loginname'] . "' requested a link for setting a new password.");
+ exit();
+ }
- // Set together our activation link
- $protocol = empty($_SERVER['HTTPS']) ? 'http' : 'https';
- // this can be a fixed value to avoid potential exploiting by modifying headers
- $host = Settings::Get('system.hostname'); // $_SERVER['HTTP_HOST'];
- $port = $_SERVER['SERVER_PORT'] != 80 ? ':' . $_SERVER['SERVER_PORT'] : '';
- // don't add :443 when https is used, as it is default (and just looks weird!)
- if ($protocol == 'https' && $_SERVER['SERVER_PORT'] == '443') {
- $port = '';
- }
- // there can be only one script to handle this so we can use a fixed value here
- $script = "/index.php"; // $_SERVER['SCRIPT_NAME'];
- if (Settings::Get('system.froxlordirectlyviahostname') == 0) {
- $script = \Froxlor\FileDir::makeCorrectFile("/" . basename(__DIR__) . "/" . $script);
- }
- $activationlink = $protocol . '://' . $host . $port . $script . '?action=resetpwd&resetcode=' . $activationcode;
+ if (($adminchecked && Settings::Get('panel.allow_preset_admin') == '1') || $adminchecked == false) {
+ if ($user !== false) {
+ // build a activation code
+ $timestamp = time();
+ $first = substr(md5($user['loginname'] . $timestamp . \Froxlor\PhpHelper::randomStr(16)), 0, 15);
+ $third = substr(md5($user['email'] . $timestamp . \Froxlor\PhpHelper::randomStr(16)), - 15);
+ $activationcode = $first . $timestamp . $third . substr(md5($third . $timestamp), 0, 10);
- $replace_arr = array(
- 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($user),
- 'NAME' => $user['name'],
- 'FIRSTNAME' => $user['firstname'] ?? "",
- 'COMPANY' => $user['company'] ?? "",
- 'CUSTOMER_NO' => $user['customernumber'] ?? 0,
- 'USERNAME' => $loginname,
- 'LINK' => $activationlink
- );
+ // Drop all existing activation codes for this user
+ $stmt = Database::prepare("DELETE FROM `" . TABLE_PANEL_ACTIVATION . "`
+ WHERE `userid` = :userid
+ AND `admin` = :admin");
+ $params = array(
+ "userid" => $adminchecked ? $user['adminid'] : $user['customerid'],
+ "admin" => $adminchecked ? 1 : 0
+ );
+ Database::pexecute($stmt, $params);
- $def_language = ($user['def_language'] != '') ? $user['def_language'] : Settings::Get('panel.standardlanguage');
- $result_stmt = Database::prepare('SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . '`
- WHERE `adminid`= :adminid
- AND `language`= :lang
- AND `templategroup`=\'mails\'
- AND `varname`=\'password_reset_subject\'');
- Database::pexecute($result_stmt, array(
- "adminid" => $user['adminid'],
- "lang" => $def_language
- ));
- $result = $result_stmt->fetch(PDO::FETCH_ASSOC);
- $mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : $lng['mails']['password_reset']['subject']), $replace_arr));
+ // Add new activation code to database
+ $stmt = Database::prepare("INSERT INTO `" . TABLE_PANEL_ACTIVATION . "`
+ (userid, admin, creation, activationcode)
+ VALUES (:userid, :admin, :creation, :activationcode)");
+ $params = array(
+ "userid" => $adminchecked ? $user['adminid'] : $user['customerid'],
+ "admin" => $adminchecked ? 1 : 0,
+ "creation" => $timestamp,
+ "activationcode" => $activationcode
+ );
+ Database::pexecute($stmt, $params);
- $result_stmt = Database::prepare('SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . '`
- WHERE `adminid`= :adminid
- AND `language`= :lang
- AND `templategroup`=\'mails\'
- AND `varname`=\'password_reset_mailbody\'');
- Database::pexecute($result_stmt, array(
- "adminid" => $user['adminid'],
- "lang" => $def_language
- ));
- $result = $result_stmt->fetch(PDO::FETCH_ASSOC);
- $mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : $lng['mails']['password_reset']['mailbody']), $replace_arr));
-
- $_mailerror = false;
- $mailerr_msg = "";
- try {
- $mail->Subject = $mail_subject;
- $mail->AltBody = $mail_body;
- $mail->MsgHTML(str_replace("\n", "
", $mail_body));
- $mail->AddAddress($user['email'], \Froxlor\User::getCorrectUserSalutation($user));
- $mail->Send();
- } catch (\PHPMailer\PHPMailer\Exception $e) {
- $mailerr_msg = $e->errorMessage();
- $_mailerror = true;
- } catch (Exception $e) {
- $mailerr_msg = $e->getMessage();
- $_mailerror = true;
- }
-
- if ($_mailerror) {
$rstlog = FroxlorLogger::getInstanceOf(array(
'loginname' => 'password_reset'
));
- $rstlog->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
+ $rstlog->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $user['loginname'] . "' requested a link for setting a new password.");
+
+ // Set together our activation link
+ $protocol = empty($_SERVER['HTTPS']) ? 'http' : 'https';
+ // this can be a fixed value to avoid potential exploiting by modifying headers
+ $host = Settings::Get('system.hostname'); // $_SERVER['HTTP_HOST'];
+ $port = $_SERVER['SERVER_PORT'] != 80 ? ':' . $_SERVER['SERVER_PORT'] : '';
+ // don't add :443 when https is used, as it is default (and just looks weird!)
+ if ($protocol == 'https' && $_SERVER['SERVER_PORT'] == '443') {
+ $port = '';
+ }
+ // there can be only one script to handle this so we can use a fixed value here
+ $script = "/index.php"; // $_SERVER['SCRIPT_NAME'];
+ if (Settings::Get('system.froxlordirectlyviahostname') == 0) {
+ $script = \Froxlor\FileDir::makeCorrectFile("/" . basename(__DIR__) . "/" . $script);
+ }
+ $activationlink = $protocol . '://' . $host . $port . $script . '?action=resetpwd&resetcode=' . $activationcode;
+
+ $replace_arr = array(
+ 'SALUTATION' => \Froxlor\User::getCorrectUserSalutation($user),
+ 'NAME' => $user['name'],
+ 'FIRSTNAME' => $user['firstname'] ?? "",
+ 'COMPANY' => $user['company'] ?? "",
+ 'CUSTOMER_NO' => $user['customernumber'] ?? 0,
+ 'USERNAME' => $loginname,
+ 'LINK' => $activationlink
+ );
+
+ $def_language = ($user['def_language'] != '') ? $user['def_language'] : Settings::Get('panel.standardlanguage');
+ $result_stmt = Database::prepare('SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . '`
+ WHERE `adminid`= :adminid
+ AND `language`= :lang
+ AND `templategroup`=\'mails\'
+ AND `varname`=\'password_reset_subject\'');
+ Database::pexecute($result_stmt, array(
+ "adminid" => $user['adminid'],
+ "lang" => $def_language
+ ));
+ $result = $result_stmt->fetch(PDO::FETCH_ASSOC);
+ $mail_subject = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : $lng['mails']['password_reset']['subject']), $replace_arr));
+
+ $result_stmt = Database::prepare('SELECT `value` FROM `' . TABLE_PANEL_TEMPLATES . '`
+ WHERE `adminid`= :adminid
+ AND `language`= :lang
+ AND `templategroup`=\'mails\'
+ AND `varname`=\'password_reset_mailbody\'');
+ Database::pexecute($result_stmt, array(
+ "adminid" => $user['adminid'],
+ "lang" => $def_language
+ ));
+ $result = $result_stmt->fetch(PDO::FETCH_ASSOC);
+ $mail_body = html_entity_decode(\Froxlor\PhpHelper::replaceVariables((($result['value'] != '') ? $result['value'] : $lng['mails']['password_reset']['mailbody']), $replace_arr));
+
+ $_mailerror = false;
+ $mailerr_msg = "";
+ try {
+ $mail->Subject = $mail_subject;
+ $mail->AltBody = $mail_body;
+ $mail->MsgHTML(str_replace("\n", "
", $mail_body));
+ $mail->AddAddress($user['email'], \Froxlor\User::getCorrectUserSalutation($user));
+ $mail->Send();
+ } catch (\PHPMailer\PHPMailer\Exception $e) {
+ $mailerr_msg = $e->errorMessage();
+ $_mailerror = true;
+ } catch (Exception $e) {
+ $mailerr_msg = $e->getMessage();
+ $_mailerror = true;
+ }
+
+ if ($_mailerror) {
+ $rstlog = FroxlorLogger::getInstanceOf(array(
+ 'loginname' => 'password_reset'
+ ));
+ $rstlog->logAction(\Froxlor\FroxlorLogger::ADM_ACTION, LOG_ERR, "Error sending mail: " . $mailerr_msg);
+ \Froxlor\UI\Response::redirectTo('index.php', array(
+ 'showmessage' => '4',
+ 'customermail' => $user['email']
+ ));
+ exit();
+ }
+
+ $mail->ClearAddresses();
\Froxlor\UI\Response::redirectTo('index.php', array(
- 'showmessage' => '4',
- 'customermail' => $user['email']
+ 'showmessage' => '1'
));
exit();
+ } else {
+ $rstlog = FroxlorLogger::getInstanceOf(array(
+ 'loginname' => 'password_reset'
+ ));
+ $rstlog->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $loginname . "' requested to set a new password, but was not found in database!");
+ $message = $lng['login']['combination_not_found'];
}
- $mail->ClearAddresses();
- \Froxlor\UI\Response::redirectTo('index.php', array(
- 'showmessage' => '1'
- ));
- exit();
- } else {
- $rstlog = FroxlorLogger::getInstanceOf(array(
- 'loginname' => 'password_reset'
- ));
- $rstlog->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $loginname . "' requested to set a new password, but was not found in database!");
- $message = $lng['login']['combination_not_found'];
+ unset($user);
}
-
- unset($user);
+ } else {
+ $message = $lng['pwdreminder']['notallowed'];
}
- } else {
- $message = $lng['login']['usernotfound'];
- }
- }
-
- if ($adminchecked) {
- if (Settings::Get('panel.allow_preset_admin') != '1') {
- $message = $lng['pwdreminder']['notallowed'];
- unset($adminchecked);
- }
- } else {
- if (Settings::Get('panel.allow_preset') != '1') {
- $message = $lng['pwdreminder']['notallowed'];
}
}
diff --git a/install/froxlor.sql b/install/froxlor.sql
index c8aef3e6..02f56721 100644
--- a/install/froxlor.sql
+++ b/install/froxlor.sql
@@ -723,7 +723,7 @@ opcache.validate_timestamps'),
('panel', 'logo_image_login', ''),
('panel', 'logo_overridetheme', '0'),
('panel', 'logo_overridecustom', '0'),
- ('panel', 'version', '0.10.35.1'),
+ ('panel', 'version', '0.10.38.3'),
('panel', 'db_version', '202112310');
diff --git a/install/updates/froxlor/0.10/update_0.10.inc.php b/install/updates/froxlor/0.10/update_0.10.inc.php
index 04f30612..8fe7e91a 100644
--- a/install/updates/froxlor/0.10/update_0.10.inc.php
+++ b/install/updates/froxlor/0.10/update_0.10.inc.php
@@ -991,3 +991,33 @@ if (\Froxlor\Froxlor::isFroxlorVersion('0.10.35')) {
showUpdateStep("Updating from 0.10.35 to 0.10.35.1", false);
\Froxlor\Froxlor::updateToVersion('0.10.35.1');
}
+
+if (\Froxlor\Froxlor::isFroxlorVersion('0.10.35.1')) {
+ showUpdateStep("Updating from 0.10.35.1 to 0.10.36", false);
+ \Froxlor\Froxlor::updateToVersion('0.10.36');
+}
+
+if (\Froxlor\Froxlor::isFroxlorVersion('0.10.36')) {
+ showUpdateStep("Updating from 0.10.36 to 0.10.37", false);
+ \Froxlor\Froxlor::updateToVersion('0.10.37');
+}
+
+if (\Froxlor\Froxlor::isFroxlorVersion('0.10.37')) {
+ showUpdateStep("Updating from 0.10.37 to 0.10.38", false);
+ \Froxlor\Froxlor::updateToVersion('0.10.38');
+}
+
+if (\Froxlor\Froxlor::isFroxlorVersion('0.10.38')) {
+ showUpdateStep("Updating from 0.10.38 to 0.10.38.1", false);
+ \Froxlor\Froxlor::updateToVersion('0.10.38.1');
+}
+
+if (\Froxlor\Froxlor::isFroxlorVersion('0.10.38.1')) {
+ showUpdateStep("Updating from 0.10.38.1 to 0.10.38.2", false);
+ \Froxlor\Froxlor::updateToVersion('0.10.38.2');
+}
+
+if (\Froxlor\Froxlor::isFroxlorVersion('0.10.38.2')) {
+ showUpdateStep("Updating from 0.10.38.2 to 0.10.38.3", false);
+ \Froxlor\Froxlor::updateToVersion('0.10.38.3');
+}
diff --git a/lib/Froxlor/Api/ApiParameter.php b/lib/Froxlor/Api/ApiParameter.php
index 6acb2309..7c4b3dee 100644
--- a/lib/Froxlor/Api/ApiParameter.php
+++ b/lib/Froxlor/Api/ApiParameter.php
@@ -180,12 +180,18 @@ abstract class ApiParameter
*/
private function trimArray($input)
{
- if (! is_array($input)) {
+ if ($input === '') {
+ return "";
+ }
+ if (is_numeric($input) || is_null($input)) {
+ return $input;
+ }
+ if (!is_array($input)) {
return trim($input);
}
- return array_map(array(
+ return array_map([
$this,
'trimArray'
- ), $input);
+ ], $input);
}
}
diff --git a/lib/Froxlor/Api/Commands/Admins.php b/lib/Froxlor/Api/Commands/Admins.php
index 0d39e53c..c3bef132 100644
--- a/lib/Froxlor/Api/Commands/Admins.php
+++ b/lib/Froxlor/Api/Commands/Admins.php
@@ -227,7 +227,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$ipaddress = $this->getParam('ipaddress', true, - 1);
// validation
- $name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
+ $name = \Froxlor\Validate\Validate::validate($name, 'name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true);
@@ -475,7 +475,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
$email = $this->getParam('email', true, $idna_convert->decode($result['email'] ?? ''));
$password = $this->getParam('admin_password', true, '');
$def_language = $this->getParam('def_language', true, $result['def_language']);
- $custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']);
+ $custom_notes = $this->getParam('custom_notes', true, ($result['custom_notes'] ?? ""));
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, $result['custom_notes_show']);
$theme = $this->getParam('theme', true, $result['theme']);
@@ -527,7 +527,7 @@ class Admins extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\ResourceEnt
}
// validation
- $name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
+ $name = \Froxlor\Validate\Validate::validate($name, 'name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
$def_language = \Froxlor\Validate\Validate::validate($def_language, 'default language', '', '', array(), true);
diff --git a/lib/Froxlor/Api/Commands/Customers.php b/lib/Froxlor/Api/Commands/Customers.php
index b4e7e4aa..3cde007d 100644
--- a/lib/Froxlor/Api/Commands/Customers.php
+++ b/lib/Froxlor/Api/Commands/Customers.php
@@ -406,12 +406,12 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
}
// validation
- $name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
- $firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', '', '', array(), true);
- $company = \Froxlor\Validate\Validate::validate($company, 'company', '', '', array(), true);
- $street = \Froxlor\Validate\Validate::validate($street, 'street', '', '', array(), true);
+ $name = \Froxlor\Validate\Validate::validate($name, 'name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
+ $firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
+ $company = \Froxlor\Validate\Validate::validate($company, 'company', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
+ $street = \Froxlor\Validate\Validate::validate($street, 'street', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$zipcode = \Froxlor\Validate\Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', array(), true);
- $city = \Froxlor\Validate\Validate::validate($city, 'city', '', '', array(), true);
+ $city = \Froxlor\Validate\Validate::validate($city, 'city', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$phone = \Froxlor\Validate\Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$fax = \Froxlor\Validate\Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
@@ -1003,12 +1003,12 @@ class Customers extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resource
// validation
if ($this->isAdmin()) {
$idna_convert = new \Froxlor\Idna\IdnaWrapper();
- $name = \Froxlor\Validate\Validate::validate($name, 'name', '', '', array(), true);
- $firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', '', '', array(), true);
- $company = \Froxlor\Validate\Validate::validate($company, 'company', '', '', array(), true);
- $street = \Froxlor\Validate\Validate::validate($street, 'street', '', '', array(), true);
+ $name = \Froxlor\Validate\Validate::validate($name, 'name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
+ $firstname = \Froxlor\Validate\Validate::validate($firstname, 'first name', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
+ $company = \Froxlor\Validate\Validate::validate($company, 'company', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
+ $street = \Froxlor\Validate\Validate::validate($street, 'street', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$zipcode = \Froxlor\Validate\Validate::validate($zipcode, 'zipcode', '/^[0-9 \-A-Z]*$/', '', array(), true);
- $city = \Froxlor\Validate\Validate::validate($city, 'city', '', '', array(), true);
+ $city = \Froxlor\Validate\Validate::validate($city, 'city', \Froxlor\Validate\Validate::REGEX_DESC_TEXT, '', array(), true);
$phone = \Froxlor\Validate\Validate::validate($phone, 'phone', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$fax = \Froxlor\Validate\Validate::validate($fax, 'fax', '/^[0-9\- \+\(\)\/]*$/', '', array(), true);
$email = $idna_convert->encode(\Froxlor\Validate\Validate::validate($email, 'email', '', '', array(), true));
diff --git a/lib/Froxlor/Api/Commands/EmailForwarders.php b/lib/Froxlor/Api/Commands/EmailForwarders.php
index 847bf9f6..48f37378 100644
--- a/lib/Froxlor/Api/Commands/EmailForwarders.php
+++ b/lib/Froxlor/Api/Commands/EmailForwarders.php
@@ -65,7 +65,7 @@ class EmailForwarders extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Re
$id = $result['id'];
// current destination array
- $result['destination_array'] = explode(' ', $result['destination']);
+ $result['destination_array'] = explode(' ', ($result['destination'] ?? ''));
// prepare destination
$destination = trim($destination);
diff --git a/lib/Froxlor/Api/Commands/IpsAndPorts.php b/lib/Froxlor/Api/Commands/IpsAndPorts.php
index 71d836fb..5afdf8a7 100644
--- a/lib/Froxlor/Api/Commands/IpsAndPorts.php
+++ b/lib/Froxlor/Api/Commands/IpsAndPorts.php
@@ -378,9 +378,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$listen_statement = $this->getBoolParam('listen_statement', true, $result['listen_statement']);
$namevirtualhost_statement = $this->getBoolParam('namevirtualhost_statement', true, $result['namevirtualhost_statement']);
$vhostcontainer = $this->getBoolParam('vhostcontainer', true, $result['vhostcontainer']);
- $specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, $result['specialsettings'])), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
+ $specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('specialsettings', true, ($result['specialsettings'] ?? ""))), 'specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$vhostcontainer_servername_statement = $this->getParam('vhostcontainer_servername_statement', true, $result['vhostcontainer_servername_statement']);
- $default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, $result['default_vhostconf_domain'])), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
+ $default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('default_vhostconf_domain', true, ($result['default_vhostconf_domain'] ?? ""))), 'default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$docroot = \Froxlor\Validate\Validate::validate($this->getParam('docroot', true, $result['docroot']), 'docroot', \Froxlor\Validate\Validate::REGEX_DIR, '', array(), true);
if ((int) Settings::Get('system.use_ssl') == 1) {
@@ -389,9 +389,9 @@ class IpsAndPorts extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
$ssl_key_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_key_file', $ssl, $result['ssl_key_file']), 'ssl_key_file', '', '', array(), true);
$ssl_ca_file = \Froxlor\Validate\Validate::validate($this->getParam('ssl_ca_file', true, $result['ssl_ca_file']), 'ssl_ca_file', '', '', array(), true);
$ssl_cert_chainfile = \Froxlor\Validate\Validate::validate($this->getParam('ssl_cert_chainfile', true, $result['ssl_cert_chainfile']), 'ssl_cert_chainfile', '', '', array(), true);
- $ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, $result['ssl_specialsettings'])), 'ssl_specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
+ $ssl_specialsettings = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_specialsettings', true, ($result['ssl_specialsettings'] ?? ""))), 'ssl_specialsettings', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_specialsettings = $this->getBoolParam('include_specialsettings', true, $result['include_specialsettings']);
- $ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, $result['ssl_default_vhostconf_domain'])), 'ssl_default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
+ $ssl_default_vhostconf_domain = \Froxlor\Validate\Validate::validate(str_replace("\r\n", "\n", $this->getParam('ssl_default_vhostconf_domain', true, ($result['ssl_default_vhostconf_domain'] ?? ""))), 'ssl_default_vhostconf_domain', \Froxlor\Validate\Validate::REGEX_CONF_TEXT, '', array(), true);
$include_default_vhostconf_domain = $this->getBoolParam('include_default_vhostconf_domain', true, $result['include_default_vhostconf_domain']);
} else {
$ssl = 0;
diff --git a/lib/Froxlor/Api/Commands/PhpSettings.php b/lib/Froxlor/Api/Commands/PhpSettings.php
index ae59726f..78299b5c 100644
--- a/lib/Froxlor/Api/Commands/PhpSettings.php
+++ b/lib/Froxlor/Api/Commands/PhpSettings.php
@@ -99,7 +99,7 @@ class PhpSettings extends \Froxlor\Api\ApiCommand implements \Froxlor\Api\Resour
}
// check whether we use that config as froxor-vhost config
- if (Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $row['id'] || Settings::Get('phpfpm.vhost_defaultini') == $row['id']) {
+ if ((Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_defaultini_ownvhost') == $row['id']) || (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.vhost_defaultini') == $row['id'])) {
$domains[] = Settings::Get('system.hostname');
}
diff --git a/lib/Froxlor/Cron/System/BackupCron.php b/lib/Froxlor/Cron/System/BackupCron.php
index 899e7717..b58de0a6 100644
--- a/lib/Froxlor/Cron/System/BackupCron.php
+++ b/lib/Froxlor/Cron/System/BackupCron.php
@@ -4,6 +4,7 @@ namespace Froxlor\Cron\System;
use Froxlor\Database\Database;
use Froxlor\Settings;
use Froxlor\FroxlorLogger;
+use Froxlor\FileDir;
/**
* This file is part of the Froxlor project.
@@ -150,13 +151,17 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
$sql_root = Database::getSqlData();
Database::needRoot(false);
+ $mysqlcnf_file = tempnam("/tmp", "frx");
+ $mysqlcnf = "[mysqldump]\npassword=".$sql_root['passwd']."\n";
+ file_put_contents($mysqlcnf_file, $mysqlcnf);
+
$has_dbs = false;
while ($row = $sel_stmt->fetch()) {
$cronlog->logAction(\Froxlor\FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> mysqldump -u ' . escapeshellarg($sql_root['user']) . ' -pXXXXX ' . $row['databasename'] . ' > ' . \Froxlor\FileDir::makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'));
$bool_false = false;
- \Froxlor\FileDir::safe_exec('mysqldump -u ' . escapeshellarg($sql_root['user']) . ' -p' . $sql_root['passwd'] . ' ' . $row['databasename'] . ' > ' . \Froxlor\FileDir::makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'), $bool_false, array(
+ \Froxlor\FileDir::safe_exec('mysqldump --defaults-file=' . escapeshellarg($mysqlcnf_file) .' -u ' . escapeshellarg($sql_root['user']) . ' ' . $row['databasename'] . ' > ' . FileDir::makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'), $bool_false, [
'>'
- ));
+ ]);
$has_dbs = true;
}
@@ -164,6 +169,8 @@ class BackupCron extends \Froxlor\Cron\FroxlorCron
$create_backup_tar_data .= './mysql ';
}
+ unlink($mysqlcnf_file);
+
unset($sql_root);
}
diff --git a/lib/Froxlor/Cron/Traffic/ReportsCron.php b/lib/Froxlor/Cron/Traffic/ReportsCron.php
index 852c26f7..c46c5d83 100644
--- a/lib/Froxlor/Cron/Traffic/ReportsCron.php
+++ b/lib/Froxlor/Cron/Traffic/ReportsCron.php
@@ -60,6 +60,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
'name' => $row['name'],
'firstname' => $row['firstname'],
'company' => $row['company'],
+ 'loginname' => $row['loginname'],
'customernumber' => $row['customernumber']
);
$replace_arr = array(
@@ -374,6 +375,7 @@ class ReportsCron extends \Froxlor\Cron\FroxlorCron
'name' => $row['name'],
'firstname' => $row['firstname'],
'company' => $row['company'],
+ 'loginname' => $row['loginname'],
'customernumber' => $row['customernumber']
);
$replace_arr = array(
diff --git a/lib/Froxlor/Database/Database.php b/lib/Froxlor/Database/Database.php
index 5235cf11..5580144f 100644
--- a/lib/Froxlor/Database/Database.php
+++ b/lib/Froxlor/Database/Database.php
@@ -190,10 +190,16 @@ class Database
*/
public static function getSqlUsernameLength()
{
- // MySQL user names can be up to 32 characters long (16 characters before MySQL 5.7.8).
- $mysql_max = 32;
- if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.8', '<')) {
- $mysql_max = 16;
+ // MariaDB supports up to 80 characters but only 64 for databases and as we use the loginname also for
+ // database names, we set the limit to 64 here
+ if (strpos(strtolower(Database::getAttribute(\PDO::ATTR_SERVER_VERSION)), "mariadb") !== false) {
+ $mysql_max = 64;
+ } else {
+ // MySQL user names can be up to 32 characters long (16 characters before MySQL 5.7.8).
+ $mysql_max = 32;
+ if (version_compare(Database::getAttribute(\PDO::ATTR_SERVER_VERSION), '5.7.8', '<')) {
+ $mysql_max = 16;
+ }
}
return $mysql_max;
}
diff --git a/lib/Froxlor/Database/DbManager.php b/lib/Froxlor/Database/DbManager.php
index dc0f3d1b..970c0216 100644
--- a/lib/Froxlor/Database/DbManager.php
+++ b/lib/Froxlor/Database/DbManager.php
@@ -173,7 +173,10 @@ class DbManager
if (isset($users[$username]) && is_array($users[$username]) && isset($users[$username]['hosts']) && is_array($users[$username]['hosts'])) {
- $password = $users[$username]['password'];
+ $password = [
+ 'password' => $users[$username]['password'],
+ 'plugin' => $users[$username]['plugin']
+ ];
foreach ($mysql_access_host_array as $mysql_access_host) {
diff --git a/lib/Froxlor/Database/Manager/DbManagerMySQL.php b/lib/Froxlor/Database/Manager/DbManagerMySQL.php
index bf2f01ca..a93d5ef1 100644
--- a/lib/Froxlor/Database/Manager/DbManagerMySQL.php
+++ b/lib/Froxlor/Database/Manager/DbManagerMySQL.php
@@ -1,4 +1,5 @@
fetch(\PDO::FETCH_ASSOC)) {
if ($user_only == false) {
- if (! isset($allsqlusers[$row['User']]) || ! is_array($allsqlusers[$row['User']])) {
+ if (!isset($allsqlusers[$row['User']]) || !is_array($allsqlusers[$row['User']])) {
$allsqlusers[$row['User']] = array(
'password' => $row['Password'] ?? $row['authentication_string'],
+ 'plugin' => $row['plugin'] ?? 'mysql_native_password',
'hosts' => array()
);
}
diff --git a/lib/Froxlor/FileDir.php b/lib/Froxlor/FileDir.php
index f71e5b7c..d258835d 100644
--- a/lib/Froxlor/FileDir.php
+++ b/lib/Froxlor/FileDir.php
@@ -1,4 +1,5 @@
0) {
$dir = trim($dir);
- if (substr($dir, - 1, 1) != '/') {
+ if (substr($dir, -1, 1) != '/') {
$dir .= '/';
}
if (substr($dir, 0, 1) != '/') {
@@ -355,7 +356,7 @@ class FileDir
$destination = substr($destination, 1);
}
- if (substr($destination, - 1, 1) == ' ') {
+ if (substr($destination, -1, 1) == ' ') {
$destination = substr($destination, 0, strlen($destination) - 1);
}
@@ -390,7 +391,7 @@ 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;
}
@@ -408,34 +409,22 @@ class FileDir
natcasesort($dirList);
if (sizeof($dirList) > 0) {
- if (sizeof($dirList) <= 100) {
- $_field = '';
- foreach ($dirList as $dir) {
- if (strpos($dir, $path) === 0) {
- $dir = substr($dir, strlen($path));
- // docroot cut off of current directory == empty -> directory is the docroot
- if (empty($dir)) {
- $dir = '/';
- }
- $dir = self::makeCorrectDir($dir);
+ $_field = '';
+ foreach ($dirList as $dir) {
+ if (strpos($dir, $path) === 0) {
+ $dir = substr($dir, strlen($path));
+ // docroot cut off of current directory == empty -> directory is the docroot
+ if (empty($dir)) {
+ $dir = '/';
}
- $_field .= \Froxlor\UI\HTML::makeoption($dir, $dir, $value);
+ $dir = self::makeCorrectDir($dir);
}
- $field = array(
- 'type' => 'select',
- 'value' => $_field
- );
- } else {
- // remove starting slash we added
- // for the Dropdown, #225
- $value = substr($value, 1);
- // $field = $lng['panel']['toomanydirs'];
- $field = array(
- 'type' => 'text',
- 'value' => htmlspecialchars($value),
- 'note' => $lng['panel']['toomanydirs']
- );
+ $_field .= \Froxlor\UI\HTML::makeoption($dir, $dir, $value);
}
+ $field = array(
+ 'type' => 'select',
+ 'value' => $_field
+ );
} else {
// $field = $lng['panel']['dirsmissing'];
// $field = '';
@@ -489,22 +478,31 @@ class FileDir
$filter = function ($file, $key, $iterator) use ($exclude) {
if (in_array($file->getFilename(), $exclude)) {
return false;
+ } elseif (substr($file->getFilename(), 0, 1) == '.') {
+ // also hide hidden folders
+ return false;
}
return true;
};
// 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
+ ),
+ \RecursiveIteratorIterator::SELF_FIRST,
+ \RecursiveIteratorIterator::CATCH_GET_CHILD
+ );
// 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
- // @TODO
- // $its->setMaxDepth(2);
+ $its->setMaxDepth(2);
// check every file
foreach ($its as $fullFileName => $it) {
if ($it->isDir() && (fileowner($fullFileName) == $uid || filegroup($fullFileName) == $gid)) {
- $_fileList[] = self::makeCorrectDir(dirname($fullFileName));
+ $_fileList[] = self::makeCorrectDir($fullFileName);
}
}
$_fileList[] = $path;
@@ -525,7 +523,7 @@ class FileDir
*/
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;
diff --git a/lib/Froxlor/Froxlor.php b/lib/Froxlor/Froxlor.php
index f2e37a79..0e6fab40 100644
--- a/lib/Froxlor/Froxlor.php
+++ b/lib/Froxlor/Froxlor.php
@@ -7,7 +7,7 @@ final class Froxlor
{
// Main version variable
- const VERSION = '0.10.35.1';
+ const VERSION = '0.10.38.3';
// Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '202112310';
diff --git a/lib/Froxlor/Settings/Store.php b/lib/Froxlor/Settings/Store.php
index d19328f1..0b595aa3 100644
--- a/lib/Froxlor/Settings/Store.php
+++ b/lib/Froxlor/Settings/Store.php
@@ -1,4 +1,5 @@
0) {
$defaultips_new = explode(',', $newfieldvalue);
- if (! empty($defaultips_old) && ! empty($newfieldvalue)) {
+ if (!empty($defaultips_old) && !empty($newfieldvalue)) {
$in_value = $defaultips_old . ", " . $newfieldvalue;
- } elseif (! empty($defaultips_old) && empty($newfieldvalue)) {
+ } elseif (!empty($defaultips_old) && empty($newfieldvalue)) {
$in_value = $defaultips_old;
} else {
$in_value = $newfieldvalue;
@@ -280,11 +281,11 @@ class Store
if ($returnvalue !== false && is_array($fielddata) && isset($fielddata['settinggroup']) && $fielddata['settinggroup'] == 'system' && isset($fielddata['varname']) && $fielddata['varname'] == 'mysql_access_host') {
$mysql_access_host_array = array_map('trim', explode(',', $newfieldvalue));
- 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';
}
@@ -306,8 +307,8 @@ class Store
private static function cleanMySQLAccessHost($value)
{
- if (substr($value, 0, 1) == '[' && substr($value, - 1) == ']') {
- return substr($value, 1, - 1);
+ if (substr($value, 0, 1) == '[' && substr($value, -1) == ']') {
+ return substr($value, 1, -1);
}
return $value;
}
@@ -370,66 +371,85 @@ class Store
}
public static function storeSettingImage($fieldname, $fielddata)
- {
- if (isset($fielddata['settinggroup'], $fielddata['varname']) && is_array($fielddata) && $fielddata['settinggroup'] !== '' && $fielddata['varname'] !== '') {
- $save_to = null;
- $path = \Froxlor\Froxlor::getInstallDir().'/img/';
- $path = \Froxlor\FileDir::makeCorrectDir($path);
+ {
+ if (isset($fielddata['settinggroup'], $fielddata['varname']) && is_array($fielddata) && $fielddata['settinggroup'] !== '' && $fielddata['varname'] !== '') {
+ $save_to = null;
+ $path = \Froxlor\Froxlor::getInstallDir() . '/img/';
+ $path = \Froxlor\FileDir::makeCorrectDir($path);
- // New file?
- if (isset($_FILES[$fieldname]) && $_FILES[$fieldname]['tmp_name']) {
- // Make sure upload directory exists
- if (!is_dir($path) && !mkdir($path, 0775)) {
- throw new \Exception("img directory does not exist and cannot be created");
- }
+ // New file?
+ if (isset($_FILES[$fieldname]) && $_FILES[$fieldname]['tmp_name']) {
+ // Make sure upload directory exists
+ if (!is_dir($path) && !mkdir($path, 0775)) {
+ throw new \Exception("img directory does not exist and cannot be created");
+ }
- // Make sure we can write to the upload directory
- if (!is_writable($path)) {
- if (!chmod($path, 0775)) {
- throw new \Exception("Cannot write to img directory");
- }
- }
+ // Make sure we can write to the upload directory
+ if (!is_writable($path)) {
+ if (!chmod($path, 0775)) {
+ throw new \Exception("Cannot write to img directory");
+ }
+ }
- // Make sure mime-type matches an image
- if (!in_array(mime_content_type($_FILES[$fieldname]['tmp_name']), ['image/jpeg','image/jpg','image/png','image/gif'])) {
- throw new \Exception("Uploaded file not a valid image");
- }
+ // Make sure mime-type matches an image
+ if (function_exists('finfo_open')) {
+ $finfo = finfo_open(FILEINFO_MIME_TYPE);
+ $mimetype = finfo_file($finfo, $_FILES[$fieldname]['tmp_name']);
+ finfo_close($finfo);
+ } else {
+ $mimetype = mime_content_type($_FILES[$fieldname]['tmp_name']);
+ }
+ if (empty($mimetype)) {
+ $mimetype = 'application/octet-stream';
+ }
+ if (!in_array($mimetype, ['image/jpeg', 'image/jpg', 'image/png', 'image/gif'])) {
+ throw new \Exception("Uploaded file is not a valid image");
+ }
- // Determine file extension
- $spl = explode('.', $_FILES[$fieldname]['name']);
- $file_extension = strtolower(array_pop($spl));
- unset($spl);
+ // Determine file extension
+ $spl = explode('.', $_FILES[$fieldname]['name']);
+ $file_extension = strtolower(array_pop($spl));
+ unset($spl);
- // Move file
- if (!move_uploaded_file($_FILES[$fieldname]['tmp_name'], $path.$fielddata['image_name'].'.'.$file_extension)) {
- throw new \Exception("Unable to save image to img folder");
- }
+ if (!in_array($file_extension, [
+ 'jpeg',
+ 'jpg',
+ 'png',
+ 'gif'
+ ])) {
+ throw new Exception("Invalid file-extension, use one of: jpeg, jpg, png, gif");
+ }
- $save_to = 'img/'.$fielddata['image_name'].'.'.$file_extension.'?v='.time();
- }
+ // Move file
+ if (!move_uploaded_file($_FILES[$fieldname]['tmp_name'], $path . $fielddata['image_name'] . '.' . $file_extension)) {
+ throw new \Exception("Unable to save image to img folder");
+ }
- // Delete file?
- if ($fielddata['value'] !== "" && array_key_exists($fieldname.'_delete', $_POST) && $_POST[$fieldname.'_delete']) {
- @unlink(\Froxlor\Froxlor::getInstallDir() . '/' . explode('?', $fielddata['value'], 2)[0]);
- $save_to = '';
- }
+ $save_to = 'img/' . $fielddata['image_name'] . '.' . $file_extension . '?v=' . time();
+ }
- // Nothing changed
- if ($save_to === null) {
- return array(
- $fielddata['settinggroup'] . '.' . $fielddata['varname'] => $fielddata['value']
- );
- }
+ // Delete file?
+ if ($fielddata['value'] !== "" && array_key_exists($fieldname . '_delete', $_POST) && $_POST[$fieldname . '_delete']) {
+ @unlink(\Froxlor\Froxlor::getInstallDir() . '/' . explode('?', $fielddata['value'], 2)[0]);
+ $save_to = '';
+ }
- if (Settings::Set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $save_to) === false) {
- return false;
- }
+ // Nothing changed
+ if ($save_to === null) {
+ return array(
+ $fielddata['settinggroup'] . '.' . $fielddata['varname'] => $fielddata['value']
+ );
+ }
- return array(
- $fielddata['settinggroup'] . '.' . $fielddata['varname'] => $save_to
- );
- }
+ if (Settings::Set($fielddata['settinggroup'] . '.' . $fielddata['varname'], $save_to) === false) {
+ return false;
+ }
- return false;
- }
+ return array(
+ $fielddata['settinggroup'] . '.' . $fielddata['varname'] => $save_to
+ );
+ }
+
+ return false;
+ }
}
diff --git a/lib/configfiles/bullseye.xml b/lib/configfiles/bullseye.xml
index 45bcc26e..c24b3b45 100644
--- a/lib/configfiles/bullseye.xml
+++ b/lib/configfiles/bullseye.xml
@@ -3561,7 +3561,7 @@ postmaster_address = postmaster@
protocol lda {
# Space separated list of plugins to load (default is global mail_plugins).
- #mail_plugins = $mail_plugins
+ mail_plugins = $mail_plugins quota sieve
}
]]>
diff --git a/lib/configfiles/buster.xml b/lib/configfiles/buster.xml
index 176e17b7..b976de04 100644
--- a/lib/configfiles/buster.xml
+++ b/lib/configfiles/buster.xml
@@ -3557,7 +3557,7 @@ postmaster_address = postmaster@
protocol lda {
# Space separated list of plugins to load (default is global mail_plugins).
- #mail_plugins = $mail_plugins
+ mail_plugins = $mail_plugins quota sieve
}
]]>
diff --git a/lib/init.php b/lib/init.php
index 0448a244..83af9d66 100644
--- a/lib/init.php
+++ b/lib/init.php
@@ -59,7 +59,7 @@ header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time()));
// 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';";
+$csp_content = "default-src 'self'; script-src 'self'; connect-src 'self'; img-src 'self' data:; style-src 'self'; object-src 'self'; frame-src 'self'; frame-ancestors 'self';";
header("Content-Security-Policy: " . $csp_content);
header("X-Content-Security-Policy: " . $csp_content);
header("X-WebKit-CSP: " . $csp_content);
diff --git a/lng/english.lng.php b/lng/english.lng.php
index 60e2aeeb..7c73fef9 100644
--- a/lng/english.lng.php
+++ b/lng/english.lng.php
@@ -678,6 +678,7 @@ $lng['admin']['message'] = 'Write a Message';
$lng['admin']['text'] = 'Message';
$lng['menu']['message'] = 'Messages';
$lng['error']['errorsendingmail'] = 'The message to "%s" failed';
+$lng['error']['errorsendingmailpub'] = 'The message to the given email-address failed';
$lng['error']['cannotreaddir'] = 'Unable to read directory "%s"';
$lng['message']['success'] = 'Successfully sent message to %s recipients';
$lng['message']['norecipients'] = 'No e-mail has been sent because there are no recipients in the database';
@@ -765,7 +766,7 @@ $lng['pwdreminder']['success'] = 'Password reset successfully requested. Please
// ADDED IN 1.2.19-svn18
$lng['serversettings']['allow_password_reset']['title'] = 'Allow password reset by customers';
-$lng['pwdreminder']['notallowed'] = 'Password reset is disabled';
+$lng['pwdreminder']['notallowed'] = 'Unknown user or password reset is disabled';
// ADDED IN 1.2.19-svn21
@@ -2143,3 +2144,8 @@ $lng['serversettings']['phpfpm_settings']['allow_all_customers']['description']
$lng['error']['pathmustberelative'] = 'The user does not have the permission to specify directories outside the customers home-directory. Please specify a relative path (no leading /).';
$lng['serversettings']['acmeshpath']['title'] = 'Path to acme.sh';
$lng['serversettings']['acmeshpath']['description'] = 'Set this to where acme.sh is installed to, including the acme.sh script
Default is /root/.acme.sh/acme.sh';
+
+$lng['question']['api_reallydelete'] = 'Do you really want to delete the api-key?';
+$lng['question']['api_reallyadd'] = 'Do you really want to create a new api-key?';
+$lng['question']['dnsentry_reallydelete'] = 'Do you really want to delete the dns entry?';
+$lng['question']['certificate_reallydelete'] = 'Do you really want to delete the certificate?';
diff --git a/lng/german.lng.php b/lng/german.lng.php
index 5eefbdef..74d08e3f 100644
--- a/lng/german.lng.php
+++ b/lng/german.lng.php
@@ -671,6 +671,7 @@ $lng['admin']['message'] = 'Rundmail senden';
$lng['admin']['text'] = 'Nachricht';
$lng['menu']['message'] = 'Nachrichten';
$lng['error']['errorsendingmail'] = 'Das Versenden der Nachricht an "%s" schlug fehl.';
+$lng['error']['errorsendingmailpub'] = 'Das Versenden der Nachricht an die angegebene E-Mail Adresse schlug fehl.';
$lng['error']['cannotreaddir'] = 'Der Ordner "%s" kann nicht gelesen werden';
$lng['message']['success'] = 'Nachricht erfolgreich an "%s" Empfänger gesendet';
$lng['message']['norecipients'] = 'Es wurde keine E-Mail versendet, da sich keine Empfänger in der Datenbank befinden';
@@ -758,7 +759,7 @@ $lng['pwdreminder']['success'] = 'Das Zurücksetzen des Passworts wurde erfolgre
// ADDED IN 1.2.19-svn18
$lng['serversettings']['allow_password_reset']['title'] = 'Erlaube das Zurücksetzen des Kundenpassworts.';
-$lng['pwdreminder']['notallowed'] = 'Das Zurücksetzen des Passworts ist deaktiviert.';
+$lng['pwdreminder']['notallowed'] = 'Unbekannter Benutzer oder Zurücksetzen des Passworts ist deaktiviert.';
// ADDED IN 1.2.19-svn21
@@ -1789,3 +1790,8 @@ $lng['serversettings']['phpfpm_settings']['allow_all_customers']['description']
$lng['error']['pathmustberelative'] = 'Der Benutzer hat nicht die benötigten Berechtigungen, um Pfade außerhalb des Kunden-Heimatverzeichnisses anzugeben. Bitte einen relativen Pfad angeben (kein führendes /).';
$lng['serversettings']['acmeshpath']['title'] = 'Pfad zu acme.sh';
$lng['serversettings']['acmeshpath']['description'] = 'Installationspfad zu acme.sh, inklusive acme.sh Script
Standard ist /root/.acme.sh/acme.sh';
+
+$lng['question']['api_reallydelete'] = 'Api-Key wirklich löschen?';
+$lng['question']['api_reallyadd'] = 'Einen neuen Api-Key erstellen?';
+$lng['question']['dnsentry_reallydelete'] = 'Zonen-Eintrag wirklich löschen?';
+$lng['question']['certificate_reallydelete'] = 'Zertifikat wirklich löschen?';
diff --git a/ssl_certificates.php b/ssl_certificates.php
index cdc0b67d..4469e240 100644
--- a/ssl_certificates.php
+++ b/ssl_certificates.php
@@ -29,15 +29,23 @@ $success_message = "";
// do the delete and then just show a success-message and the certificates list again
if ($action == 'delete') {
- $id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
+ $id = isset($_POST['id']) ? (int) $_POST['id'] : (isset($_GET['id']) ? (int) $_GET['id'] : 0);
if ($id > 0) {
- try {
- $json_result = Certificates::getLocal($userinfo, array(
+ if (isset($_POST['send']) && $_POST['send'] == 'send') {
+ try {
+ $json_result = Certificates::getLocal($userinfo, array(
+ 'id' => $id
+ ))->delete();
+ $success_message = sprintf($lng['domains']['ssl_certificate_removed'], $id);
+ } catch (Exception $e) {
+ \Froxlor\UI\Response::dynamic_error($e->getMessage());
+ }
+ } else {
+ \Froxlor\UI\HTML::askYesNo('certificate_reallydelete', $filename, array(
+ 'page' => $page,
+ 'action' => $action,
'id' => $id
- ))->delete();
- $success_message = sprintf($lng['domains']['ssl_certificate_removed'], $id);
- } catch (Exception $e) {
- \Froxlor\UI\Response::dynamic_error($e->getMessage());
+ ), $id);
}
}
}
diff --git a/templates/Sparkle/assets/css/main.css b/templates/Sparkle/assets/css/main.css
index 8d6f7726..c571776c 100644
--- a/templates/Sparkle/assets/css/main.css
+++ b/templates/Sparkle/assets/css/main.css
@@ -82,6 +82,7 @@ header img {
.login header img {
margin: 0 auto;
display: block;
+ max-width: calc(100% - 20px);
}
img.small {
diff --git a/tests/Froxlor/ValidateTest.php b/tests/Froxlor/ValidateTest.php
index d973154a..3d116ade 100644
--- a/tests/Froxlor/ValidateTest.php
+++ b/tests/Froxlor/ValidateTest.php
@@ -198,7 +198,7 @@ class ValidateTest extends TestCase
$result = Validate::validateUsername('web123sql2', true, $mysql_max);
$this->assertTrue($result);
// too long
- $result = Validate::validateUsername('myperfectsuperduperwebuser123sql2', true, $mysql_max);
+ $result = Validate::validateUsername('myperfectsuperduperwebuserwhosnameisenormouslylongandprettyandshouldinnowaybeaccepted123sql2', true, $mysql_max);
$this->assertFalse($result);
// not unix-conform
$result = Validate::validateUsername('web123-sql2', true, $mysql_max);
diff --git a/tests/Mysqls/MysqlsTest.php b/tests/Mysqls/MysqlsTest.php
index 5673a474..da762ef1 100644
--- a/tests/Mysqls/MysqlsTest.php
+++ b/tests/Mysqls/MysqlsTest.php
@@ -286,8 +286,8 @@ class MysqlsTest extends TestCase
$dbm = new \Froxlor\Database\DbManager(\Froxlor\FroxlorLogger::getInstanceOf());
$users = $dbm->getManager()->getAllSqlUsers(false);
foreach ($users as $user => $data) {
- if (TRAVIS_CI == 1 && strtolower($user) == 'mariadb.sys') {
- // travis seems to have a user for mariadb on version 10.4
+ if (strtolower($user) == 'mariadb.sys') {
+ // some systems seem to have a user for mariadb on version 10.4
// we do not want to test that one
continue;
}
@@ -302,7 +302,11 @@ class MysqlsTest extends TestCase
// grant privileges to another host
$testdata = $users['froxlor010'];
- $dbm->getManager()->grantPrivilegesTo('froxlor010', $testdata['password'], '10.0.0.10', true);
+ $password = [
+ 'password' => $testdata['password'],
+ 'plugin' => $testdata['plugin']
+ ];
+ $dbm->getManager()->grantPrivilegesTo('froxlor010', $password, '10.0.0.10', true);
// select all entries from mysql.user for froxlor010 to compare password-hashes
$sel_stmt = Database::prepare("SELECT * FROM mysql.user WHERE `User` = :usr");