Compare commits

..

10 Commits
2.1.1 ... 2.1.2

Author SHA1 Message Date
Michael Kaufmann
a3b0332d13 set version to 2.1.2 for bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-12-15 09:41:16 +01:00
Michael Kaufmann
4b1846883d Merge pull request from GHSA-625g-fm5w-w7w4
* fix possibility to have empty name/surname and empty company

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>

* let js validation for customer add/edit form also trim() entered data to avoid empty values pass the client-side validation

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>

---------

Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-12-15 09:36:06 +01:00
Michael Kaufmann
778fd3ba65 fix wrong size-unit for mailquota-dashboard-info; fixes #1207
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-12-15 09:32:02 +01:00
Michael Kaufmann
00456a35e5 fix 2fa login when using email validation, thx to wysiwtf; adjusting row-format of larger tables
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-12-13 16:20:28 +01:00
Michael Kaufmann
5958f0516b do not css-check/clean passwords of the installation process; fixes #1203
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-12-12 09:33:28 +01:00
Michael Kaufmann
166ffedf04 correctly merge themeoptions array to use correct image on login when using darkmode
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-12-12 08:59:56 +01:00
Michael Kaufmann
36dfee1263 fix non-empty value for file-input fields when using uploaded logos
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-12-12 08:58:33 +01:00
Michael Kaufmann
ec0026ecfd fix wrong type when dns zone for system-hostname is active
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-12-11 14:20:08 +01:00
Michael Kaufmann
a721bb3f21 remove old 0.10.x and 2.0.x distribution-config-xml's for updaters
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-12-10 20:47:31 +01:00
Michael Kaufmann
83de3dd719 handle unknown distribution if there's a now unsupported distribution selected for the config-templates
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2023-12-10 19:23:58 +01:00
12 changed files with 109 additions and 32 deletions

View File

@@ -60,7 +60,9 @@ if ($userinfo['change_serversettings'] == '1') {
if (!empty($distribution)) { if (!empty($distribution)) {
if (!file_exists($config_dir . '/' . $distribution . ".xml")) { if (!file_exists($config_dir . '/' . $distribution . ".xml")) {
Response::dynamicError("Unknown distribution"); // unknown distribution -> redirect to select a valid distribution for config-templates
Settings::Set('system.distribution', '');
Response::redirectTo('admin_configfiles.php', ['reselect' => 1]);
} }
// update setting if different // update setting if different

View File

@@ -115,8 +115,8 @@ if ($page == 'overview') {
$userinfo['traffic_bytes_used'] = $userinfo['traffic_used'] * 1024; $userinfo['traffic_bytes_used'] = $userinfo['traffic_used'] * 1024;
if (Settings::Get('system.mail_quota_enabled')) { if (Settings::Get('system.mail_quota_enabled')) {
$userinfo['email_quota_bytes'] = ($userinfo['email_quota'] > -1) ? $userinfo['email_quota'] * 1024 : -1; $userinfo['email_quota_bytes'] = ($userinfo['email_quota'] > -1) ? $userinfo['email_quota'] * 1024 * 1024 : -1;
$userinfo['email_quota_bytes_used'] = $userinfo['email_quota_used'] * 1024; $userinfo['email_quota_bytes_used'] = $userinfo['email_quota_used'] * 1024 * 1024;
} }
if ($usages) { if ($usages) {

View File

@@ -74,27 +74,26 @@ if ($action == '2fa_entercode') {
$code = isset($_POST['2fa_code']) ? $_POST['2fa_code'] : null; $code = isset($_POST['2fa_code']) ? $_POST['2fa_code'] : null;
// 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));
// get user-data // get user-data
$table = $_SESSION['uidtable_2fa']; $table = $_SESSION['uidtable_2fa'];
$field = $_SESSION['uidfield_2fa']; $field = $_SESSION['uidfield_2fa'];
$uid = $_SESSION['uid_2fa']; $uid = $_SESSION['uid_2fa'];
$isadmin = $_SESSION['unfo_2fa']; $isadmin = $_SESSION['unfo_2fa'];
if ($_SESSION['secret_2fa'] == 'email') {
// verify code set to user's data_2fa field
$sel_stmt = Database::prepare("SELECT `data_2fa` FROM " . $table . " WHERE `" . $field . "` = :uid");
$userinfo_code = Database::pexecute_first($sel_stmt, ['uid' => $uid]);
$result = $tfa->verifyCode($userinfo_code['data_2fa'], $code);
} else {
$result = $tfa->verifyCode($_SESSION['secret_2fa'], $code, 3);
}
// 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) {
$sel_param = [ $sel_param = [
'uid' => $uid 'uid' => $uid
]; ];
if ($_SESSION['secret_2fa'] == 'email') { $sel_stmt = Database::prepare("SELECT * FROM " . $table . " WHERE `" . $field . "` = :uid");
// 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
$sel_stmt = Database::prepare("SELECT * FROM " . $table . " WHERE `" . $field . "` = :uid AND `data_2fa` = :code");
$sel_param['code'] = $code;
} else {
// Authenticator-verification has already happened at this point, so just get the user-data
$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
if (empty($userinfo)) { if (empty($userinfo)) {

View File

@@ -157,7 +157,7 @@ CREATE TABLE `panel_admins` (
`api_allowed` tinyint(1) NOT NULL default '1', `api_allowed` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`adminid`), PRIMARY KEY (`adminid`),
UNIQUE KEY `loginname` (`loginname`) UNIQUE KEY `loginname` (`loginname`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC;
DROP TABLE IF EXISTS `panel_customers`; DROP TABLE IF EXISTS `panel_customers`;
@@ -299,7 +299,7 @@ CREATE TABLE `panel_domains` (
KEY `customerid` (`customerid`), KEY `customerid` (`customerid`),
KEY `parentdomain` (`parentdomainid`), KEY `parentdomain` (`parentdomainid`),
KEY `domain` (`domain`) KEY `domain` (`domain`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC;
DROP TABLE IF EXISTS `panel_ipsandports`; DROP TABLE IF EXISTS `panel_ipsandports`;
@@ -678,7 +678,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.1.1'), ('system', 'update_notify_last', ''),
('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),
@@ -726,8 +726,8 @@ opcache.validate_timestamps'),
('panel', 'logo_overridecustom', '0'), ('panel', 'logo_overridecustom', '0'),
('panel', 'settings_mode', '0'), ('panel', 'settings_mode', '0'),
('panel', 'menu_collapsed', '1'), ('panel', 'menu_collapsed', '1'),
('panel', 'version', '2.1.1'), ('panel', 'version', '2.1.2'),
('panel', 'db_version', '202312050'); ('panel', 'db_version', '202312120');
DROP TABLE IF EXISTS `panel_tasks`; DROP TABLE IF EXISTS `panel_tasks`;

View File

@@ -38,6 +38,7 @@ if (!defined('_CRON_UPDATE')) {
if (Froxlor::isFroxlorVersion('2.0.24')) { if (Froxlor::isFroxlorVersion('2.0.24')) {
Update::showUpdateStep("Cleaning domains table"); Update::showUpdateStep("Cleaning domains table");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ROW_FORMAT=DYNAMIC;");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` DROP COLUMN `ismainbutsubto`;"); Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` DROP COLUMN `ismainbutsubto`;");
Update::lastStepStatus(0); Update::lastStepStatus(0);
@@ -213,3 +214,58 @@ if (Froxlor::isFroxlorVersion('2.1.0')) {
Update::showUpdateStep("Updating from 2.1.0 to 2.1.1", false); Update::showUpdateStep("Updating from 2.1.0 to 2.1.1", false);
Froxlor::updateToVersion('2.1.1'); Froxlor::updateToVersion('2.1.1');
} }
if (Froxlor::isDatabaseVersion('202312050')) {
Update::showUpdateStep("Cleaning up old files");
$to_clean = array(
"lib/configfiles/centos7.xml",
"lib/configfiles/centos8.xml",
"lib/configfiles/stretch.xml",
"lib/configfiles/xenial.xml",
"lib/configfiles/buster.xml",
"lib/configfiles/bionic.xml",
);
$disabled = explode(',', ini_get('disable_functions'));
$exec_allowed = !in_array('exec', $disabled);
$del_list = "";
foreach ($to_clean as $filedir) {
$complete_filedir = Froxlor::getInstallDir() . $filedir;
if (file_exists($complete_filedir)) {
if ($exec_allowed) {
FileDir::safe_exec("rm -rf " . escapeshellarg($complete_filedir));
} else {
$del_list .= "rm -rf " . escapeshellarg($complete_filedir) . PHP_EOL;
}
}
}
if ($exec_allowed) {
Update::lastStepStatus(0);
} else {
if (empty($del_list)) {
// none of the files existed
Update::lastStepStatus(0);
} else {
Update::lastStepStatus(
1,
'manual commands needed',
'Please run the following commands manually:<br><pre>' . $del_list . '</pre>'
);
}
}
Froxlor::updateToDbVersion('202312100');
}
if (Froxlor::isDatabaseVersion('202312100')) {
Update::showUpdateStep("Adjusting table row format of larger tables");
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` ROW_FORMAT=DYNAMIC;");
Database::query("ALTER TABLE `" . TABLE_PANEL_DOMAINS . "` ROW_FORMAT=DYNAMIC;");
Update::lastStepStatus(0);
Froxlor::updateToDbVersion('202312120');
}
if (Froxlor::isFroxlorVersion('2.1.1')) {
Update::showUpdateStep("Updating from 2.1.1 to 2.1.2", false);
Froxlor::updateToVersion('2.1.2');
}

View File

@@ -1053,7 +1053,7 @@ class Customers extends ApiCommand implements ResourceEntity
$email = $this->getParam('email', true, $idna_convert->decode($result['email'])); $email = $this->getParam('email', true, $idna_convert->decode($result['email']));
$name = $this->getParam('name', true, $result['name']); $name = $this->getParam('name', true, $result['name']);
$firstname = $this->getParam('firstname', true, $result['firstname']); $firstname = $this->getParam('firstname', true, $result['firstname']);
$company_required = empty($result['company']) && ((!empty($name) && empty($firstname)) || (empty($name) && !empty($firstname)) || (empty($name) && empty($firstname))); $company_required = (!empty($name) && empty($firstname)) || (empty($name) && !empty($firstname)) || (empty($name) && empty($firstname));
$company = $this->getParam('company', !$company_required, $result['company']); $company = $this->getParam('company', !$company_required, $result['company']);
$street = $this->getParam('street', true, $result['street']); $street = $this->getParam('street', true, $result['street']);
$zipcode = $this->getParam('zipcode', true, $result['zipcode']); $zipcode = $this->getParam('zipcode', true, $result['zipcode']);

View File

@@ -244,7 +244,7 @@ abstract class DnsBase
'zonefile' => '', 'zonefile' => '',
'froxlorhost' => '1' 'froxlorhost' => '1'
]; ];
$domains['none'] = $hostname_arr; $domains[0] = $hostname_arr;
} }
if (empty($domains)) { if (empty($domains)) {

View File

@@ -31,10 +31,10 @@ final class Froxlor
{ {
// Main version variable // Main version variable
const VERSION = '2.1.1'; const VERSION = '2.1.2';
// Database version (YYYYMMDDC where C is a daily counter) // Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '202312050'; const DBVERSION = '202312120';
// Distribution branding-tag (used for Debian etc.) // Distribution branding-tag (used for Debian etc.)
const BRANDING = ''; const BRANDING = '';

View File

@@ -220,8 +220,11 @@ class PhpHelper
if (is_dir($data_dirname)) { if (is_dir($data_dirname)) {
$data_dirhandle = opendir($data_dirname); $data_dirhandle = opendir($data_dirname);
while (false !== ($data_filename = readdir($data_dirhandle))) { while (false !== ($data_filename = readdir($data_dirhandle))) {
if ($data_filename != '.' && $data_filename != '..' && $data_filename != '' && substr($data_filename, if ($data_filename != '.'
-4) == '.php') { && $data_filename != '..'
&& $data_filename != ''
&& substr($data_filename, -4) == '.php'
) {
$data_files[] = $data_dirname . $data_filename; $data_files[] = $data_dirname . $data_filename;
} }
} }
@@ -415,8 +418,8 @@ class PhpHelper
*/ */
public static function recursive_array_search( public static function recursive_array_search(
string $needle, string $needle,
array $haystack, array $haystack,
array &$keys = [], array &$keys = [],
string $currentKey = '' string $currentKey = ''
): bool { ): bool {
foreach ($haystack as $key => $value) { foreach ($haystack as $key => $value) {
@@ -458,6 +461,10 @@ class PhpHelper
'directory_password', 'directory_password',
'ftp_password', 'ftp_password',
'mysql_password', 'mysql_password',
'mysql_root_pass',
'mysql_unprivileged_pass',
'admin_pass',
'admin_pass_confirm',
]; ];
if (!empty($global)) { if (!empty($global)) {
$tmp = $global; $tmp = $global;
@@ -557,4 +564,17 @@ class PhpHelper
} }
return $tab . $str; return $tab . $str;
} }
public static function array_merge_recursive_distinct(array &$array1, array &$array2)
{
$merged = $array1;
foreach ($array2 as $key => &$value) {
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
$merged[$key] = self::array_merge_recursive_distinct($merged[$key], $value);
} else {
$merged[$key] = $value;
}
}
return $merged;
}
} }

View File

@@ -225,7 +225,7 @@ if (is_array($_themeoptions) && (!array_key_exists('variants', $_themeoptions) |
} }
if (array_key_exists('global', $_themeoptions)) { if (array_key_exists('global', $_themeoptions)) {
$_themeoptions['variants'][$themevariant] = array_merge_recursive($_themeoptions['variants'][$themevariant], $_themeoptions['global']); $_themeoptions['variants'][$themevariant] = PhpHelper::array_merge_recursive_distinct($_themeoptions['global'], $_themeoptions['variants'][$themevariant]);
} }
// check for custom header-graphic // check for custom header-graphic

View File

@@ -8,18 +8,18 @@ export default function () {
rules: { rules: {
'name': { 'name': {
required: function () { required: function () {
return $('#company').val().length === 0 || $('#firstname').val().length > 0; return $('#company').val().trim().length === 0 || $('#firstname').val().trim().length > 0;
} }
}, },
'firstname': { 'firstname': {
required: function () { required: function () {
return $('#company').val().length === 0 || $('#name').val().length > 0; return $('#company').val().trim().length === 0 || $('#name').val().trim().length > 0;
} }
}, },
'company': { 'company': {
required: function () { required: function () {
return $('#name').val().length === 0 return $('#name').val().trim().length === 0
&& $('#firstname').val().length === 0; && $('#firstname').val().trim().length === 0;
} }
} }
}, },

View File

@@ -184,7 +184,7 @@
</label> </label>
</div> </div>
{% endif %} {% endif %}
{% set field = field|merge({'type':'file'}) %} {% set field = field|merge({'type':'file'})|merge({'value':''}) %}
{{ _self.input(id, field) }} {{ _self.input(id, field) }}
{% endmacro %} {% endmacro %}