Compare commits

..

29 Commits

Author SHA1 Message Date
Michael Kaufmann
f4183b020b set version to 2.1.8 for bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-03-29 11:27:32 +01:00
Michael Kaufmann
9a3d88e8c9 fix domains speciallogfile ajax-check/note; improve ajax ip check in admin_ipsandports
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-03-27 11:08:45 +01:00
Michael Kaufmann
c9460fd58f also add logfiles to virtual-host if it's a redirect
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-03-27 10:17:48 +01:00
Michael Kaufmann
6ef532b470 fix missing csrf tokens for some ajax requests
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-03-27 10:17:37 +01:00
Wiebe Cazemier
5909401cdd Fix "expires" option cannot have a year greater than 9999 (#1246)
This fixes the exception: '"expires" option cannot have a year greater
than 9999', which happens on upgrade from Debian 11 to 12. The session
timeout in the DB is 9999999999999, so we constrain the value.
2024-03-25 08:22:00 +01:00
Michael Kaufmann
809e8ef45b set version to 2.1.7 for maintenance release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-03-17 08:30:38 +01:00
Michael Kaufmann
0a091a99e8 wrap SetHandler to php-fpm in file-exists check, as we do for customer-domains already
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-03-17 08:24:56 +01:00
dependabot[bot]
e299fbe665 Bump follow-redirects from 1.15.4 to 1.15.6 (#1244)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.4 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.4...v1.15.6)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-17 08:15:09 +01:00
Michael Kaufmann
67e8b622d8 correctly save pass_authorizationheader flag for php-configs if FCGID is used; correctly add 'FcgidPassHeader' for froxlor-vhost itself if set
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-03-17 08:13:24 +01:00
Michael Kaufmann
ce509273d4 correctly validate if a symlink is within the customers home-directory if it's not an absolute path; fixes #1242
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-03-08 09:23:58 +01:00
Michael Kaufmann
bcf588a2e4 correctly disabled ssl-related settings when domain update sets ssl-enbled flag to false; fixes #1241
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-03-04 16:49:20 +01:00
Michael Kaufmann
f08d540e66 dont escape panel_password_special_char field
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-03-03 10:37:42 +01:00
Michael Kaufmann
e06db3d8c5 re-trigger vhost regeneration on tmp. ssl-redirect
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-03-03 10:36:41 +01:00
Michael Kaufmann
c5c04ebe9c fix adding/editing domains as customer when php is not enabled for the domain; don't add custom-vhost-content to deactivated domain-vhosts
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-02-05 22:10:33 +01:00
Michael Kaufmann
c9faa38f6c fix regression bug in 'incorrect top-5 customers' sorting in traffic-overview which leads to incorrect customer-links due to wrong indexing in the array; fixes #1236
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-02-04 20:34:48 +01:00
Michael Kaufmann
c188f047dc backport UI/Callback fixes from 2.2-dev (main); fixes #1235
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-02-04 18:53:12 +01:00
Michael Kaufmann
775d50306c set version to 2.1.6 for bugfix/regression release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-02-03 14:22:33 +01:00
Michael Kaufmann
3821144c3b also fix unittests accordingly
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-02-03 14:08:23 +01:00
Michael Kaufmann
a1da70c221 fix password crypt hash being always evaluated to argon2i as the case always returns true if PASSWORD_ARGON2I is defined but the froxlor setting might be set to another hash leading to a useless password
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-02-03 13:49:43 +01:00
Michael Kaufmann
bb2db0fed0 set version to 2.1.5 for bugfix release
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-02-02 11:18:48 +01:00
Michael Kaufmann
9680f24640 fix check for allowed_phpconfigs if using mod_php when adding/editing a customer
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-30 19:32:10 +01:00
Michael Kaufmann
c732fbd81b set correct channel for update-check if switching from apt-installed stable/testing to nightly
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-26 13:57:51 +01:00
Michael Kaufmann
7980b8d14d create empty dns-server config if no (dns-enabled) domain is determined; fixes #1230
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-24 08:39:16 +01:00
Michael Kaufmann
13e88f5b47 fix incorrect top-5 customers in traffic overview for admins; show manual update command if webupdate is disabled
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-19 09:22:12 +01:00
sro0
031596301b Check for argon2 support before using constant PASSWORD_ARGON2X (#1228) 2024-01-16 21:40:03 +01:00
Michael Kaufmann
b34ab45746 disable pam auth in dovecot for debian bookworm (like the other distros do it)
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-07 09:06:15 +01:00
Michael Kaufmann
dbf83c6f24 build nightly only from main branch #2
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-06 15:01:52 +01:00
Michael Kaufmann
4cb974839c build nightly only from main branch
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-06 14:54:23 +01:00
Michael Kaufmann
1fa714ef2c add v2.1 branch to security md as currently supported as well as update main-branch version; add field.disabled attribute to formfield-input-template
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
2024-01-06 14:48:41 +01:00
146 changed files with 3135 additions and 6680 deletions

View File

@@ -12,7 +12,7 @@ jobs:
mariadb-version: [ 10.11, 10.5 ] mariadb-version: [ 10.11, 10.5 ]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Setup PHP, with composer and extensions - name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2 uses: shivammathur/setup-php@v2
@@ -57,7 +57,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Setup PHP with PECL extension - name: Setup PHP with PECL extension
uses: shivammathur/setup-php@v2 uses: shivammathur/setup-php@v2
@@ -70,7 +70,7 @@ jobs:
run: composer install --no-dev run: composer install --no-dev
- name: Install Node.js - name: Install Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v3
with: with:
node-version: '20.x' node-version: '20.x'
@@ -119,7 +119,7 @@ jobs:
mv froxlor-nightly.${{steps.vars.outputs.sha_short}}.zip.sha256 dist/ mv froxlor-nightly.${{steps.vars.outputs.sha_short}}.zip.sha256 dist/
- name: Deploy nightly to server - name: Deploy nightly to server
uses: easingthemes/ssh-deploy@main uses: easingthemes/ssh-deploy@v3.4.3
env: env:
ARGS: "-rltDzvO --chown=${{ secrets.WEB_USER }}:${{ secrets.WEB_USER }}" ARGS: "-rltDzvO --chown=${{ secrets.WEB_USER }}:${{ secrets.WEB_USER }}"
SOURCE: "dist/" SOURCE: "dist/"

View File

@@ -12,7 +12,7 @@ jobs:
mysql-version: [8.0, 5.7] mysql-version: [8.0, 5.7]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Setup PHP, with composer and extensions - name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2 uses: shivammathur/setup-php@v2
@@ -39,7 +39,16 @@ jobs:
- name: Wait for database - name: Wait for database
run: sleep 15 run: sleep 15
- name: Setup database - name: Setup database (8.0)
if: matrix.mysql-version == '8.0'
run: |
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'%' IDENTIFIED WITH mysql_native_password BY 'fr0xl0r.TravisCI';"
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%';"
php -r "echo include('install/froxlor.sql.php');" > /tmp/froxlor.sql
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI froxlor010 < /tmp/froxlor.sql
- name: Setup database (5.7)
if: matrix.mysql-version == '5.7'
run: | run: |
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'%' IDENTIFIED BY 'fr0xl0r.TravisCI';" mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "CREATE USER 'froxlor010'@'%' IDENTIFIED BY 'fr0xl0r.TravisCI';"
mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%';" mysql -h 127.0.0.1 --protocol=TCP -u root -pfr0xl0r.TravisCI -e "GRANT ALL ON froxlor010.* TO 'froxlor010'@'%';"

View File

@@ -33,7 +33,6 @@ use Froxlor\FroxlorLogger;
use Froxlor\FroxlorTwoFactorAuth; use Froxlor\FroxlorTwoFactorAuth;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\UI\Panel\UI; use Froxlor\UI\Panel\UI;
use Froxlor\UI\Request;
use Froxlor\UI\Response; use Froxlor\UI\Response;
use Froxlor\PhpHelper; use Froxlor\PhpHelper;
use Froxlor\User; use Froxlor\User;
@@ -64,7 +63,7 @@ if ($action == 'delete') {
]); ]);
Response::standardSuccess('2fa.2fa_removed'); Response::standardSuccess('2fa.2fa_removed');
} elseif ($action == 'preadd') { } elseif ($action == 'preadd') {
$type = Request::post('type_2fa', '0'); $type = isset($_POST['type_2fa']) ? $_POST['type_2fa'] : '0';
$data = ""; $data = "";
if ($type > 0) { if ($type > 0) {
@@ -108,9 +107,9 @@ if ($action == 'delete') {
Response::dynamicError('Select one of the possible values for 2FA'); Response::dynamicError('Select one of the possible values for 2FA');
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
$type = Request::post('type_2fa', '0'); $type = isset($_POST['type_2fa']) ? $_POST['type_2fa'] : '0';
$data = Request::post('data_2fa', ''); $data = isset($_POST['data_2fa']) ? $_POST['data_2fa'] : '';
$code = Request::post('codevalidation', ''); $code = isset($_POST['codevalidation']) ? $_POST['codevalidation'] : '';
// validate // validate
$result = $tfa->verifyCode($data, $code, 3); $result = $tfa->verifyCode($data, $code, 3);

View File

@@ -58,17 +58,17 @@ https://files.froxlor.org/releases/froxlor-latest.tar.gz [MD5](https://files.fro
#### Debian #### Debian
``` ```
apt -y install apt-transport-https lsb-release ca-certificates curl gnupg apt-get -y install apt-transport-https lsb-release ca-certificates curl
curl -sSLo /usr/share/keyrings/deb.froxlor.org-froxlor.gpg https://deb.froxlor.org/froxlor.gpg curl -sSLo /usr/share/keyrings/deb.froxlor.org-froxlor.gpg https://deb.froxlor.org/froxlor.gpg
sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.froxlor.org-froxlor.gpg] https://deb.froxlor.org/debian $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list' echo sh -c '"deb [signed-by=/usr/share/keyrings/deb.froxlor.org-froxlor.gpg] https://deb.froxlor.org/debian $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list'
``` ```
#### Ubuntu #### Ubuntu
``` ```
apt -y install apt-transport-https lsb-release ca-certificates curl gnupg apt-get -y install apt-transport-https lsb-release ca-certificates curl
curl -sSLo /usr/share/keyrings/deb.froxlor.org-froxlor.gpg https://deb.froxlor.org/froxlor.gpg curl -sSLo /usr/share/keyrings/deb.froxlor.org-froxlor.gpg https://deb.froxlor.org/froxlor.gpg
sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.froxlor.org-froxlor.gpg] https://deb.froxlor.org/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list' echo sh -c '"deb [signed-by=/usr/share/keyrings/deb.froxlor.org-froxlor.gpg] https://deb.froxlor.org/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/froxlor.list'
``` ```
## Contributing ## Contributing

View File

@@ -180,6 +180,18 @@ return [
'default' => true, 'default' => true,
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField'
], ],
'system_httpuser' => [
'settinggroup' => 'system',
'varname' => 'httpuser',
'type' => 'hidden',
'default' => 'www-data'
],
'system_httpgroup' => [
'settinggroup' => 'system',
'varname' => 'httpgroup',
'type' => 'hidden',
'default' => 'www-data'
],
'system_report_enable' => [ 'system_report_enable' => [
'label' => lng('serversettings.report.report'), 'label' => lng('serversettings.report.report'),
'settinggroup' => 'system', 'settinggroup' => 'system',

View File

@@ -176,7 +176,6 @@ return [
'varname' => 'mod_fcgid_httpuser', 'varname' => 'mod_fcgid_httpuser',
'type' => 'text', 'type' => 'text',
'default' => 'froxlorlocal', 'default' => 'froxlorlocal',
'string_emptyallowed' => false,
'save_method' => 'storeSettingWebserverFcgidFpmUser', 'save_method' => 'storeSettingWebserverFcgidFpmUser',
'websrv_avail' => [ 'websrv_avail' => [
'apache2' 'apache2'
@@ -194,7 +193,6 @@ return [
'type' => 'text', 'type' => 'text',
'default' => 'froxlorlocal', 'default' => 'froxlorlocal',
'save_method' => 'storeSettingField', 'save_method' => 'storeSettingField',
'string_emptyallowed' => false,
'websrv_avail' => [ 'websrv_avail' => [
'apache2' 'apache2'
], ],
@@ -245,7 +243,6 @@ return [
'varname' => 'vhost_httpuser', 'varname' => 'vhost_httpuser',
'type' => 'text', 'type' => 'text',
'default' => 'froxlorlocal', 'default' => 'froxlorlocal',
'string_emptyallowed' => false,
'save_method' => 'storeSettingWebserverFcgidFpmUser', 'save_method' => 'storeSettingWebserverFcgidFpmUser',
'visible' => Settings::Get('phpfpm.enabled') && call_user_func([ 'visible' => Settings::Get('phpfpm.enabled') && call_user_func([
'\Froxlor\Settings\FroxlorVhostSettings', '\Froxlor\Settings\FroxlorVhostSettings',
@@ -259,7 +256,6 @@ return [
'varname' => 'vhost_httpgroup', 'varname' => 'vhost_httpgroup',
'type' => 'text', 'type' => 'text',
'default' => 'froxlorlocal', 'default' => 'froxlorlocal',
'string_emptyallowed' => false,
'save_method' => 'storeSettingField', 'save_method' => 'storeSettingField',
'visible' => Settings::Get('phpfpm.enabled') && call_user_func([ 'visible' => Settings::Get('phpfpm.enabled') && call_user_func([
'\Froxlor\Settings\FroxlorVhostSettings', '\Froxlor\Settings\FroxlorVhostSettings',

View File

@@ -251,37 +251,8 @@ return [
'string_type' => 'validate_ip', 'string_type' => 'validate_ip',
'string_emptyallowed' => true, 'string_emptyallowed' => true,
'default' => '', 'default' => '',
'save_method' => 'storeSettingField', 'save_method' => 'storeSettingField'
'advanced_mode' => true ]
],
'system_le_renew_services' => [
'label' => lng('serversettings.le_renew_services'),
'settinggroup' => 'system',
'varname' => 'le_renew_services',
'type' => 'select',
'default' => '',
'select_mode' => 'multiple',
'option_emptyallowed' => true,
'select_var' => [
'' => lng('panel.none_value'),
'postfix' => 'postfix (smtp)',
'dovecot' => 'dovecot (imap/pop3)',
'proftpd' => 'proftpd (ftp)',
],
'save_method' => 'storeSettingField',
'advanced_mode' => true
],
'system_le_renew_hook' => [
'label' => lng('serversettings.le_renew_hook'),
'settinggroup' => 'system',
'varname' => 'le_renew_hook',
'type' => 'text',
'string_regexp' => '/^[a-z0-9\/\._\- ]+$/i',
'default' => 'systemctl restart postfix dovecot proftpd',
'save_method' => 'storeSettingField',
'advanced_mode' => true,
'required_otp' => true
],
] ]
] ]
] ]

View File

@@ -1,111 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can also view it online at
* https://files.froxlor.org/misc/COPYING.txt
*
* @copyright the authors
* @author Froxlor team <team@froxlor.org>
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
*/
return [
'groups' => [
'antispam' => [
'title' => lng('admin.antispam_settings'),
'icon' => 'fa-solid fa-clipboard-check',
'fields' => [
'antispam_activated' => [
'label' => lng('antispam.activated'),
'settinggroup' => 'antispam',
'varname' => 'activated',
'type' => 'checkbox',
'default' => true,
'overview_option' => true,
'save_method' => 'storeSettingFieldInsertAntispamTask',
],
'antispam_config_file' => [
'label' => lng('antispam.config_file'),
'settinggroup' => 'antispam',
'varname' => 'config_file',
'type' => 'text',
'string_type' => 'file',
'default' => '/etc/rspamd/local.d/froxlor_settings.conf',
'save_method' => 'storeSettingFieldInsertAntispamTask',
'requires_reconf' => ['antispam']
],
'antispam_reload_command' => [
'label' => lng('antispam.reload_command'),
'settinggroup' => 'antispam',
'varname' => 'reload_command',
'type' => 'text',
'string_regexp' => '/^[a-z0-9\/\._\- ]+$/i',
'default' => 'service rspamd restart',
'save_method' => 'storeSettingField',
'required_otp' => true
],
'antispam_dkim_keylength' => [
'label' => lng('antispam.dkim_keylength'),
'settinggroup' => 'antispam',
'varname' => 'dkim_keylength',
'type' => 'select',
'default' => '1024',
'select_var' => [
'1024' => '1024 Bit',
'2048' => '2048 Bit'
],
'save_method' => 'storeSettingFieldInsertBindTask',
'advanced_mode' => true,
],
'spf_use_spf' => [
'label' => lng('spf.use_spf'),
'settinggroup' => 'spf',
'varname' => 'use_spf',
'type' => 'checkbox',
'default' => false,
'save_method' => 'storeSettingField',
],
'spf_spf_entry' => [
'label' => lng('spf.spf_entry'),
'settinggroup' => 'spf',
'varname' => 'spf_entry',
'type' => 'text',
'string_regexp' => '/^v=spf[a-z0-9:~?\s.-]+$/i',
'default' => 'v=spf1 a mx -all',
'save_method' => 'storeSettingField'
],
'dmarc_use_dmarc' => [
'label' => lng('dmarc.use_dmarc'),
'settinggroup' => 'dmarc',
'varname' => 'use_dmarc',
'type' => 'checkbox',
'default' => false,
'save_method' => 'storeSettingField',
],
'dmarc_dmarc_entry' => [
'label' => lng('dmarc.dmarc_entry'),
'settinggroup' => 'dmarc',
'varname' => 'dmarc_entry',
'type' => 'text',
'string_regexp' => '/^v=dmarc1(.+)$/i',
'default' => 'v=DMARC1; p=none;',
'save_method' => 'storeSettingField'
]
]
]
]
];

View File

@@ -0,0 +1,146 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can also view it online at
* https://files.froxlor.org/misc/COPYING.txt
*
* @copyright the authors
* @author Froxlor team <team@froxlor.org>
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
*/
use Froxlor\Settings;
return [
'groups' => [
'dkim' => [
'title' => lng('admin.dkimsettings'),
'icon' => 'fa-solid fa-fingerprint',
'fields' => [
'dkim_use_dkim' => [
'label' => lng('dkim.use_dkim'),
'settinggroup' => 'dkim',
'varname' => 'use_dkim',
'type' => 'checkbox',
'default' => false,
'save_method' => 'storeSettingFieldInsertBindTask',
'overview_option' => true
],
'dkim_dkim_prefix' => [
'label' => lng('dkim.dkim_prefix'),
'settinggroup' => 'dkim',
'varname' => 'dkim_prefix',
'type' => 'text',
'string_type' => 'dir',
'default' => '/etc/postfix/dkim/',
'save_method' => 'storeSettingField'
],
'dkim_privkeysuffix' => [
'label' => lng('dkim.privkeysuffix'),
'settinggroup' => 'dkim',
'varname' => 'privkeysuffix',
'type' => 'text',
'string_regexp' => '/^[a-z0-9\._]+$/i',
'default' => '.priv',
'save_method' => 'storeSettingField',
'advanced_mode' => true
],
'dkim_dkim_domains' => [
'label' => lng('dkim.dkim_domains'),
'settinggroup' => 'dkim',
'varname' => 'dkim_domains',
'type' => 'text',
'string_regexp' => '/^[a-z0-9\._]+$/i',
'default' => 'domains',
'save_method' => 'storeSettingField'
],
'dkim_dkim_dkimkeys' => [
'label' => lng('dkim.dkim_dkimkeys'),
'settinggroup' => 'dkim',
'varname' => 'dkim_dkimkeys',
'type' => 'text',
'string_regexp' => '/^[a-z0-9\._]+$/i',
'default' => 'dkim-keys.conf',
'save_method' => 'storeSettingField'
],
'dkim_dkim_algorithm' => [
'label' => lng('dkim.dkim_algorithm'),
'settinggroup' => 'dkim',
'varname' => 'dkim_algorithm',
'type' => 'select',
'default' => 'all',
'select_mode' => 'multiple',
'select_var' => [
'all' => 'All',
'sha1' => 'SHA1',
'sha256' => 'SHA256'
],
'save_method' => 'storeSettingFieldInsertBindTask',
'advanced_mode' => true
],
'dkim_dkim_servicetype' => [
'label' => lng('dkim.dkim_servicetype'),
'settinggroup' => 'dkim',
'varname' => 'dkim_servicetype',
'type' => 'select',
'default' => '0',
'select_var' => [
'0' => 'All',
'1' => 'E-Mail'
],
'save_method' => 'storeSettingFieldInsertBindTask',
'advanced_mode' => true
],
'dkim_dkim_keylength' => [
'label' => [
'title' => lng('dkim.dkim_keylength.title'),
'description' => lng('dkim.dkim_keylength.description', [Settings::Get('dkim.dkim_prefix')])
],
'settinggroup' => 'dkim',
'varname' => 'dkim_keylength',
'type' => 'select',
'default' => '1024',
'select_var' => [
'1024' => '1024 Bit',
'2048' => '2048 Bit'
],
'save_method' => 'storeSettingFieldInsertBindTask'
],
'dkim_dkim_notes' => [
'label' => lng('dkim.dkim_notes'),
'settinggroup' => 'dkim',
'varname' => 'dkim_notes',
'type' => 'text',
'string_regexp' => '/^[a-z0-9\._]+$/i',
'default' => '',
'save_method' => 'storeSettingFieldInsertBindTask',
'advanced_mode' => true
],
'dkim_dkimrestart_command' => [
'label' => lng('dkim.dkimrestart_command'),
'settinggroup' => 'dkim',
'varname' => 'dkimrestart_command',
'type' => 'text',
'string_regexp' => '/^[a-z0-9\/\._\- ]+$/i',
'default' => '/etc/init.d/dkim-filter restart',
'save_method' => 'storeSettingField',
'required_otp' => true
]
]
]
]
];

View File

@@ -23,26 +23,31 @@
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2 * @license https://files.froxlor.org/misc/COPYING.txt GPLv2
*/ */
use Froxlor\Install\Update; return [
'groups' => [
$preconfig = [ 'spf' => [
'title' => '2.2.x updates', 'title' => lng('admin.spfsettings'),
'fields' => [] 'icon' => 'fa-solid fa-clipboard-check',
'fields' => [
'spf_use_spf' => [
'label' => lng('spf.use_spf'),
'settinggroup' => 'spf',
'varname' => 'use_spf',
'type' => 'checkbox',
'default' => false,
'save_method' => 'storeSettingField',
'overview_option' => true
],
'spf_spf_entry' => [
'label' => lng('spf.spf_entry'),
'settinggroup' => 'spf',
'varname' => 'spf_entry',
'type' => 'text',
'string_regexp' => '/^v=spf[a-z0-9:~?\s.-]+$/i',
'default' => 'v=spf1 a mx -all',
'save_method' => 'storeSettingField'
]
]
]
]
]; ];
$return = [];
if (Update::versionInUpdate($current_version, '2.2.0-dev1')) {
$has_preconfig = true;
$description = 'Froxlor now features antispam configurations using rspamd. Would you like to enable the antispam feature (required re-configuration of services)?<br><strong>ATTENTION:</strong> When not enabled and the former DomainKey feature was used, keep in mind that all existing domainkeys for all domain are being removed and the dkim-flag disabled for the domains.';
$question = '<strong>Enable antispam (recommended)</strong>&nbsp;';
$return['antispam_activated'] = [
'type' => 'checkbox',
'value' => 1,
'checked' => 0,
'label' => $question,
'prior_infotext' => $description
];
}
$preconfig['fields'] = $return;
return $preconfig;

View File

@@ -106,7 +106,7 @@ if (($page == 'admins' || $page == 'overview') && $userinfo['change_serversettin
Response::standardError('youcantdeleteyourself'); Response::standardError('youcantdeleteyourself');
} }
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
Admins::getLocal($userinfo, [ Admins::getLocal($userinfo, [
'id' => $id 'id' => $id
])->delete(); ])->delete();
@@ -122,9 +122,9 @@ if (($page == 'admins' || $page == 'overview') && $userinfo['change_serversettin
} }
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Admins::getLocal($userinfo, Request::postAll())->add(); Admins::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -159,9 +159,9 @@ if (($page == 'admins' || $page == 'overview') && $userinfo['change_serversettin
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if ($result['loginname'] != '') { if ($result['loginname'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Admins::getLocal($userinfo, Request::postAll())->update(); Admins::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }

View File

@@ -33,7 +33,6 @@
use Froxlor\FroxlorLogger; use Froxlor\FroxlorLogger;
use Froxlor\UI\Panel\UI; use Froxlor\UI\Panel\UI;
use Froxlor\UI\Request;
use Froxlor\UI\Response; use Froxlor\UI\Response;
use Froxlor\UI\HTML; use Froxlor\UI\HTML;
@@ -43,7 +42,7 @@ require __DIR__ . '/lib/init.php';
$horizontal_bar_size = 950; // 1280px window width $horizontal_bar_size = 950; // 1280px window width
if ($action == 'delete' && function_exists('apcu_clear_cache') && $userinfo['change_serversettings'] == '1') { if ($action == 'delete' && function_exists('apcu_clear_cache') && $userinfo['change_serversettings'] == '1') {
if (Request::post('send') == 'send') { if ($_POST['send'] == 'send') {
apcu_clear_cache(); apcu_clear_cache();
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "cleared APCu cache"); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "cleared APCu cache");
header('Location: ' . $linker->getLink([ header('Location: ' . $linker->getLink([

View File

@@ -32,7 +32,6 @@ 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;
use Froxlor\UI\Request;
use Froxlor\UI\Response; use Froxlor\UI\Response;
if ($page != 'error') { if ($page != 'error') {
@@ -111,7 +110,7 @@ if ($page == 'overview') {
} // download the new archive } // download the new archive
elseif ($page == 'getdownload') { elseif ($page == 'getdownload') {
// retrieve the new version from the form // retrieve the new version from the form
$newversion = Request::post('newversion'); $newversion = isset($_POST['newversion']) ? $_POST['newversion'] : null;
$result = 6; $result = 6;
// valid? // valid?
@@ -131,8 +130,8 @@ elseif ($page == 'getdownload') {
]); ]);
} // extract and install new version } // extract and install new version
elseif ($page == 'extract') { elseif ($page == 'extract') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$toExtract = Request::post('archive'); $toExtract = isset($_POST['archive']) ? $_POST['archive'] : null;
$localArchive = FileDir::makeCorrectFile(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);
@@ -146,7 +145,7 @@ elseif ($page == 'extract') {
// redirect to update-page // redirect to update-page
Response::redirectTo('admin_updates.php'); Response::redirectTo('admin_updates.php');
} else { } else {
$toExtract = Request::get('archive'); $toExtract = isset($_GET['archive']) ? $_GET['archive'] : null;
$localArchive = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/updates/' . $toExtract); $localArchive = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/updates/' . $toExtract);
} }
@@ -193,7 +192,7 @@ elseif ($page == 'extract') {
} // display error } // display error
elseif ($page == 'error') { elseif ($page == 'error') {
// retrieve error-number via url-parameter // retrieve error-number via url-parameter
$errno = Request::get('errno', 0); $errno = isset($_GET['errno']) ? (int)$_GET['errno'] : 0;
// 2 = no Zlib // 2 = no Zlib
// 3 = custom version detected // 3 = custom version detected

View File

@@ -93,14 +93,14 @@ if ($userinfo['change_serversettings'] == '1') {
asort($distributions_select); asort($distributions_select);
} }
if ($distribution != "" && !empty(Request::post('finish'))) { if ($distribution != "" && isset($_POST['finish'])) {
$valid_keys = ['http', 'dns', 'smtp', 'mail', 'antispam', 'ftp', 'system', 'distro']; $valid_keys = ['http', 'dns', 'smtp', 'mail', 'ftp', 'system', 'distro'];
unset($_POST['finish']); unset($_POST['finish']);
unset($_POST['csrf_token']); unset($_POST['csrf_token']);
$params = Request::postAll(); $params = $_POST;
$params['distro'] = $distribution; $params['distro'] = $distribution;
$params['system'] = []; $params['system'] = [];
foreach (Request::post('system', []) as $sysdaemon) { foreach ($_POST['system'] as $sysdaemon) {
$params['system'][] = $sysdaemon; $params['system'][] = $sysdaemon;
} }
// validate params // validate params

View File

@@ -68,9 +68,9 @@ if (($page == 'cronjobs' || $page == 'overview') && $userinfo['change_serversett
} }
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if ($result['cronfile'] != '') { if ($result['cronfile'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Cronjobs::getLocal($userinfo, Request::postAll())->update(); Cronjobs::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }

View File

@@ -98,7 +98,7 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "switched user and is now '" . $destination_user . "'"); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "switched user and is now '" . $destination_user . "'");
$target = Request::get('target', 'index'); $target = (isset($_GET['target']) ? $_GET['target'] : 'index');
$redirect = "customer_" . $target . ".php"; $redirect = "customer_" . $target . ".php";
if (!file_exists(Froxlor::getInstallDir() . "/" . $redirect)) { if (!file_exists(Froxlor::getInstallDir() . "/" . $redirect)) {
$redirect = "customer_index.php"; $redirect = "customer_index.php";
@@ -119,7 +119,7 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
} }
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
$json_result = Customers::getLocal($userinfo, [ $json_result = Customers::getLocal($userinfo, [
'id' => $id 'id' => $id
@@ -147,11 +147,11 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
} }
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
$json_result = Customers::getLocal($userinfo, [ $json_result = Customers::getLocal($userinfo, [
'id' => $id, 'id' => $id,
'delete_userfiles' => Request::post('delete_userfiles', 0) 'delete_userfiles' => (isset($_POST['delete_userfiles']) ? (int)$_POST['delete_userfiles'] : 0)
])->delete(); ])->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
@@ -167,9 +167,9 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
], $result['loginname']); ], $result['loginname']);
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Customers::getLocal($userinfo, Request::postAll())->add(); Customers::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -243,9 +243,9 @@ if (($page == 'customers' || $page == 'overview') && $userinfo['customers'] != '
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if ($result['loginname'] != '') { if ($result['loginname'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Customers::getLocal($userinfo, Request::postAll())->update(); Customers::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }

View File

@@ -100,9 +100,9 @@ if ($page == 'domains' || $page == 'overview') {
]); ]);
if ($result['domain'] != '') { if ($result['domain'] != '') {
if (Request::post('send') == 'send' && $alias_check['count'] == 0) { if (isset($_POST['send']) && $_POST['send'] == 'send' && $alias_check['count'] == 0) {
try { try {
Domains::getLocal($userinfo, Request::postAll())->delete(); Domains::getLocal($userinfo, $_POST)->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -113,7 +113,7 @@ if ($page == 'domains' || $page == 'overview') {
} elseif ($alias_check['count'] > 0) { } elseif ($alias_check['count'] > 0) {
Response::standardError('domains_cantdeletedomainwithaliases'); Response::standardError('domains_cantdeletedomainwithaliases');
} else { } else {
HTML::askYesNoWithCheckbox('admin_domain_reallydelete', 'admin_customer_alsoremovemail', $filename, [ HTML::askYesNo('admin_domain_reallydelete', $filename, [
'id' => $id, 'id' => $id,
'page' => $page, 'page' => $page,
'action' => $action 'action' => $action
@@ -121,9 +121,9 @@ if ($page == 'domains' || $page == 'overview') {
} }
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Domains::getLocal($userinfo, Request::postAll())->add(); Domains::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -355,13 +355,13 @@ if ($page == 'domains' || $page == 'overview') {
$usedips[] = $ipsresultrow['id_ipandports']; $usedips[] = $ipsresultrow['id_ipandports'];
} }
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
// remove ssl ip/ports if set is empty // remove ssl ip/ports if set is empty
if (empty(Request::post('ssl_ipandport'))) { if (!isset($_POST['ssl_ipandport']) || empty($_POST['ssl_ipandport'])) {
$_POST['remove_ssl_ipandport'] = true; $_POST['remove_ssl_ipandport'] = true;
} }
Domains::getLocal($userinfo, Request::postAll())->update(); Domains::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -572,13 +572,13 @@ if ($page == 'domains' || $page == 'overview') {
} }
} }
} elseif ($action == 'jqGetCustomerPHPConfigs') { } elseif ($action == 'jqGetCustomerPHPConfigs') {
$customerid = intval(Request::post('customerid')); $customerid = intval($_POST['customerid']);
$allowed_phpconfigs = Customer::getCustomerDetail($customerid, 'allowed_phpconfigs'); $allowed_phpconfigs = Customer::getCustomerDetail($customerid, 'allowed_phpconfigs');
echo !empty($allowed_phpconfigs) ? $allowed_phpconfigs : json_encode([]); echo !empty($allowed_phpconfigs) ? $allowed_phpconfigs : json_encode([]);
exit(); exit();
} elseif ($action == 'jqSpeciallogfileNote') { } elseif ($action == 'jqSpeciallogfileNote') {
$domainid = intval(Request::post('id')); $domainid = intval($_POST['id']);
$newval = intval(Request::post('newval')); $newval = intval($_POST['newval']);
try { try {
$json_result = Domains::getLocal($userinfo, [ $json_result = Domains::getLocal($userinfo, [
'id' => $domainid 'id' => $domainid
@@ -594,9 +594,9 @@ if ($page == 'domains' || $page == 'overview') {
echo 0; echo 0;
exit(); exit();
} elseif ($action == 'import') { } elseif ($action == 'import') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$separator = Validate::validate(Request::post('separator'), 'separator'); $separator = Validate::validate($_POST['separator'], 'separator');
$offset = (int)Validate::validate(Request::post('offset'), 'offset', "/[0-9]/i"); $offset = (int)Validate::validate($_POST['offset'], 'offset', "/[0-9]/i");
$file_name = $_FILES['file']['tmp_name']; $file_name = $_FILES['file']['tmp_name'];
@@ -636,9 +636,9 @@ if ($page == 'domains' || $page == 'overview') {
]); ]);
} }
} elseif ($action == 'duplicate') { } elseif ($action == 'duplicate') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Domains::getLocal($userinfo, Request::postAll())->duplicate(); Domains::getLocal($userinfo, $_POST)->duplicate();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }

View File

@@ -55,7 +55,7 @@ if ($action == 'logout') {
$result = $result['switched_user']; $result = $result['switched_user'];
session_regenerate_id(true); session_regenerate_id(true);
CurrentUser::setData($result); CurrentUser::setData($result);
$target = Request::get('target', 'index'); $target = (isset($_GET['target']) ? $_GET['target'] : 'index');
$redirect = "admin_" . $target . ".php"; $redirect = "admin_" . $target . ".php";
if (!file_exists(\Froxlor\Froxlor::getInstallDir() . "/" . $redirect)) { if (!file_exists(\Froxlor\Froxlor::getInstallDir() . "/" . $redirect)) {
$redirect = "admin_index.php"; $redirect = "admin_index.php";
@@ -111,7 +111,7 @@ if ($page == 'overview') {
$overview['number_domains'] = $number_domains['number_domains']; $overview['number_domains'] = $number_domains['number_domains'];
if (Request::get('lookfornewversion') == 'yes' || (isset($lookfornewversion) && $lookfornewversion == 'yes')) { if ((isset($_GET['lookfornewversion']) && $_GET['lookfornewversion'] == 'yes') || (isset($lookfornewversion) && $lookfornewversion == 'yes')) {
try { try {
$json_result = Froxlor::getLocal($userinfo)->checkUpdate(); $json_result = Froxlor::getLocal($userinfo)->checkUpdate();
} catch (Exception $e) { } catch (Exception $e) {
@@ -201,16 +201,16 @@ if ($page == 'overview') {
$languages = Language::getLanguages(); $languages = Language::getLanguages();
if (!empty($_POST)) { if (!empty($_POST)) {
if (Request::post('send') == 'changepassword') { if ($_POST['send'] == 'changepassword') {
$old_password = Validate::validate(Request::post('old_password'), 'old password'); $old_password = Validate::validate($_POST['old_password'], 'old password');
if (!Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_ADMINS, 'adminid')) { if (!Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_ADMINS, 'adminid')) {
Response::standardError('oldpasswordnotcorrect'); Response::standardError('oldpasswordnotcorrect');
} }
try { try {
$new_password = Crypt::validatePassword(Request::post('new_password'), 'new password'); $new_password = Crypt::validatePassword($_POST['new_password'], 'new password');
$new_password_confirm = Crypt::validatePassword(Request::post('new_password_confirm'), 'new password confirm'); $new_password_confirm = Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm');
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -244,9 +244,9 @@ if ($page == 'overview') {
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'changed password'); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'changed password');
Response::redirectTo($filename); Response::redirectTo($filename);
} }
} elseif (Request::post('send') == 'changetheme') { } elseif ($_POST['send'] == 'changetheme') {
if (Settings::Get('panel.allow_theme_change_admin') == 1) { if (Settings::Get('panel.allow_theme_change_admin') == 1) {
$theme = Validate::validate(Request::post('theme'), 'theme'); $theme = Validate::validate($_POST['theme'], 'theme');
try { try {
Admins::getLocal($userinfo, [ Admins::getLocal($userinfo, [
'id' => $userinfo['adminid'], 'id' => $userinfo['adminid'],
@@ -259,8 +259,8 @@ if ($page == 'overview') {
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "changed his/her theme to '" . $theme . "'"); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, "changed his/her theme to '" . $theme . "'");
} }
Response::redirectTo($filename); Response::redirectTo($filename);
} elseif (Request::post('send') == 'changelanguage') { } elseif ($_POST['send'] == 'changelanguage') {
$def_language = Validate::validate(Request::post('def_language'), 'default language'); $def_language = Validate::validate($_POST['def_language'], 'default language');
if (isset($languages[$def_language])) { if (isset($languages[$def_language])) {
try { try {

View File

@@ -70,7 +70,7 @@ if (($page == 'ipsandports' || $page == 'overview') && $userinfo['change_servers
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['id']) && $result['id'] == $id) { if (isset($result['id']) && $result['id'] == $id) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
IpsAndPorts::getLocal($userinfo, [ IpsAndPorts::getLocal($userinfo, [
'id' => $id 'id' => $id
@@ -91,9 +91,9 @@ if (($page == 'ipsandports' || $page == 'overview') && $userinfo['change_servers
} }
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
IpsAndPorts::getLocal($userinfo, Request::postAll())->add(); IpsAndPorts::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -119,9 +119,9 @@ if (($page == 'ipsandports' || $page == 'overview') && $userinfo['change_servers
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if ($result['ip'] != '') { if ($result['ip'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
IpsAndPorts::getLocal($userinfo, Request::postAll())->update(); IpsAndPorts::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -141,7 +141,7 @@ if (($page == 'ipsandports' || $page == 'overview') && $userinfo['change_servers
} }
} }
} elseif ($action == 'jqCheckIP') { } elseif ($action == 'jqCheckIP') {
$ip = Request::post('ip', ''); $ip = $_POST['ip'] ?? "";
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) { if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
echo json_encode('<div id="ipnote" class="invalid-feedback">'.lng('error.invalidip', [$ip]).'</div>'); echo json_encode('<div id="ipnote" class="invalid-feedback">'.lng('error.invalidip', [$ip]).'</div>');
} elseif (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE)) { } elseif (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE)) {

View File

@@ -31,7 +31,6 @@ use Froxlor\UI\Collection;
use Froxlor\UI\HTML; use Froxlor\UI\HTML;
use Froxlor\UI\Listing; use Froxlor\UI\Listing;
use Froxlor\UI\Panel\UI; use Froxlor\UI\Panel\UI;
use Froxlor\UI\Request;
use Froxlor\UI\Response; use Froxlor\UI\Response;
if ($page == 'log' && $userinfo['change_serversettings'] == '1') { if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
@@ -56,7 +55,7 @@ if ($page == 'log' && $userinfo['change_serversettings'] == '1') {
] ]
]); ]);
} elseif ($action == 'truncate') { } elseif ($action == 'truncate') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
SysLog::getLocal($userinfo, [ SysLog::getLocal($userinfo, [
'min_to_keep' => 10 'min_to_keep' => 10

View File

@@ -42,11 +42,11 @@ if ($page == 'message') {
if ($action == '') { if ($action == '') {
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed panel_message'); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'viewed panel_message');
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
if (Request::post('recipient', -1) == 0 && $userinfo['customers_see_all'] == '1') { if ($_POST['recipient'] == 0 && $userinfo['customers_see_all'] == '1') {
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to admins'); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to admins');
$result = Database::query('SELECT `name`, `email` FROM `' . TABLE_PANEL_ADMINS . "`"); $result = Database::query('SELECT `name`, `email` FROM `' . TABLE_PANEL_ADMINS . "`");
} elseif (Request::post('recipient', -1) == 1) { } elseif ($_POST['recipient'] == 1) {
if ($userinfo['customers_see_all'] == '1') { if ($userinfo['customers_see_all'] == '1') {
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to ALL customers'); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_NOTICE, 'sending messages to ALL customers');
$result = Database::query('SELECT `firstname`, `name`, `company`, `email` FROM `' . TABLE_PANEL_CUSTOMERS . "`"); $result = Database::query('SELECT `firstname`, `name`, `company`, `email` FROM `' . TABLE_PANEL_CUSTOMERS . "`");
@@ -63,8 +63,8 @@ if ($page == 'message') {
Response::standardError('norecipientsgiven'); Response::standardError('norecipientsgiven');
} }
$subject = Request::post('subject'); $subject = $_POST['subject'];
$message = wordwrap(Request::post('message'), 70); $message = wordwrap($_POST['message'], 70);
if (!empty($message)) { if (!empty($message)) {
$mailcounter = 0; $mailcounter = 0;
@@ -107,7 +107,7 @@ if ($page == 'message') {
} }
} }
} elseif ($action == 'showsuccess') { } elseif ($action == 'showsuccess') {
$sentitems = Request::get('sentitems', 0); $sentitems = isset($_GET['sentitems']) ? (int)$_GET['sentitems'] : 0;
if ($sentitems == 0) { if ($sentitems == 0) {
$note_type = 'info'; $note_type = 'info';

View File

@@ -70,7 +70,7 @@ if (($page == 'mysqlserver' || $page == 'overview') && $userinfo['change_servers
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['id']) && $result['id'] == $id) { if (isset($result['id']) && $result['id'] == $id) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
MysqlServer::getLocal($userinfo, [ MysqlServer::getLocal($userinfo, [
'id' => $id 'id' => $id
@@ -91,9 +91,9 @@ if (($page == 'mysqlserver' || $page == 'overview') && $userinfo['change_servers
} }
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
MysqlServer::getLocal($userinfo, Request::postAll())->add(); MysqlServer::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -119,9 +119,9 @@ if (($page == 'mysqlserver' || $page == 'overview') && $userinfo['change_servers
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['id']) && $result['id'] == $id) { if (isset($result['id']) && $result['id'] == $id) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
MysqlServer::getLocal($userinfo, Request::postAll())->update(); MysqlServer::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }

View File

@@ -38,7 +38,7 @@ use Froxlor\UI\Panel\UI;
use Froxlor\UI\Response; use Froxlor\UI\Response;
if ($action == 'reset' && function_exists('opcache_reset') && $userinfo['change_serversettings'] == '1') { if ($action == 'reset' && function_exists('opcache_reset') && $userinfo['change_serversettings'] == '1') {
if (Request::post('send') == 'send') { if ($_POST['send'] == 'send') {
opcache_reset(); opcache_reset();
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache"); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "reset OPcache");
header('Location: ' . $linker->getLink([ header('Location: ' . $linker->getLink([

View File

@@ -62,9 +62,9 @@ if ($page == 'overview') {
if ($action == 'add') { if ($action == 'add') {
if ((int)$userinfo['change_serversettings'] == 1) { if ((int)$userinfo['change_serversettings'] == 1) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
PhpSettings::getLocal($userinfo, Request::postAll())->add(); PhpSettings::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -114,7 +114,7 @@ if ($page == 'overview') {
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config
{ {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
PhpSettings::getLocal($userinfo, [ PhpSettings::getLocal($userinfo, [
'id' => $id 'id' => $id
@@ -148,9 +148,9 @@ if ($page == 'overview') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1) { if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
PhpSettings::getLocal($userinfo, Request::postAll())->update(); PhpSettings::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -200,9 +200,9 @@ if ($page == 'overview') {
if ($action == 'add') { if ($action == 'add') {
if ((int)$userinfo['change_serversettings'] == 1) { if ((int)$userinfo['change_serversettings'] == 1) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
FpmDaemons::getLocal($userinfo, Request::postAll())->add(); FpmDaemons::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -239,9 +239,9 @@ if ($page == 'overview') {
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1 && $id != 1) // cannot delete the default php.config
{ {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
FpmDaemons::getLocal($userinfo, Request::postAll())->delete(); FpmDaemons::getLocal($userinfo, $_POST)->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -271,9 +271,9 @@ if ($page == 'overview') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1) { if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['change_serversettings'] == 1) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
FpmDaemons::getLocal($userinfo, Request::postAll())->update(); FpmDaemons::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }

View File

@@ -73,7 +73,7 @@ if ($page == '' || $page == 'overview') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['adminid'] == $result['adminid']) { if ($result['id'] != 0 && $result['id'] == $id && (int)$userinfo['adminid'] == $result['adminid']) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
HostingPlans::getLocal($userinfo, [ HostingPlans::getLocal($userinfo, [
'id' => $id 'id' => $id
@@ -96,9 +96,9 @@ if ($page == '' || $page == 'overview') {
Response::standardError('nopermissionsorinvalidid'); Response::standardError('nopermissionsorinvalidid');
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
HostingPlans::getLocal($userinfo, Request::postAll())->add(); HostingPlans::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -176,9 +176,9 @@ if ($page == '' || $page == 'overview') {
} }
$result['allowed_phpconfigs'] = json_encode($result['allowed_phpconfigs']); $result['allowed_phpconfigs'] = json_encode($result['allowed_phpconfigs']);
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
HostingPlans::getLocal($userinfo, Request::postAll())->update(); HostingPlans::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }

View File

@@ -47,10 +47,10 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
$settings_data = PhpHelper::loadConfigArrayDir('./actions/admin/settings/'); $settings_data = PhpHelper::loadConfigArrayDir('./actions/admin/settings/');
Settings::loadSettingsInto($settings_data); Settings::loadSettingsInto($settings_data);
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$_part = Request::get('part', ''); $_part = isset($_GET['part']) ? $_GET['part'] : '';
if ($_part == '') { if ($_part == '') {
$_part = Request::post('part', ''); $_part = isset($_POST['part']) ? $_POST['part'] : '';
} }
if ($_part != '') { if ($_part != '') {
@@ -69,12 +69,12 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
} }
// check if the session timeout is too low #815 // check if the session timeout is too low #815
if (!empty(Request::post('session_sessiontimeout')) && intval(Request::post('session_sessiontimeout', 0)) < 60) { if (isset($_POST['session_sessiontimeout']) && $_POST['session_sessiontimeout'] < 60) {
Response::standardError(['session_timeout', 'session_timeout_desc']); Response::standardError(['session_timeout', 'session_timeout_desc']);
} }
try { try {
if (Form::processForm($settings_data, Request::postAll(), [ if (Form::processForm($settings_data, $_POST, [
'filename' => $filename, 'filename' => $filename,
'action' => $action, 'action' => $action,
'page' => $page, 'page' => $page,
@@ -97,9 +97,9 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
Response::dynamicError($e->getMessage(), $e->getCode()); Response::dynamicError($e->getMessage(), $e->getCode());
} }
} else { } else {
$_part = Request::get('part', ''); $_part = isset($_GET['part']) ? $_GET['part'] : '';
if ($_part == '') { if ($_part == '') {
$_part = Request::post('part', ''); $_part = isset($_POST['part']) ? $_POST['part'] : '';
} }
$fields = Form::buildForm($settings_data, $_part); $fields = Form::buildForm($settings_data, $_part);
@@ -140,7 +140,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
'phpinfo' => $phpinfo 'phpinfo' => $phpinfo
]); ]);
} elseif ($page == 'rebuildconfigs' && $userinfo['change_serversettings'] == '1') { } elseif ($page == 'rebuildconfigs' && $userinfo['change_serversettings'] == '1') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "rebuild configfiles"); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "rebuild configfiles");
Cronjob::inserttask(TaskId::REBUILD_VHOST); Cronjob::inserttask(TaskId::REBUILD_VHOST);
Cronjob::inserttask(TaskId::CREATE_QUOTA); Cronjob::inserttask(TaskId::CREATE_QUOTA);
@@ -158,7 +158,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
]); ]);
} }
} elseif ($page == 'updatecounters' && $userinfo['change_serversettings'] == '1') { } elseif ($page == 'updatecounters' && $userinfo['change_serversettings'] == '1') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "updated resource-counters"); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_INFO, "updated resource-counters");
$updatecounters = User::updateCounters(true); $updatecounters = User::updateCounters(true);
UI::view('user/resource-counter.html.twig', [ UI::view('user/resource-counter.html.twig', [
@@ -170,7 +170,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
]); ]);
} }
} elseif ($page == 'wipecleartextmailpws' && $userinfo['change_serversettings'] == '1') { } elseif ($page == 'wipecleartextmailpws' && $userinfo['change_serversettings'] == '1') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all cleartext mail passwords"); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all cleartext mail passwords");
Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = '';"); Database::query("UPDATE `" . TABLE_MAIL_USERS . "` SET `password` = '';");
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `value` = '0' WHERE `settinggroup` = 'system' AND `varname` = 'mailpwcleartext'"); Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `value` = '0' WHERE `settinggroup` = 'system' AND `varname` = 'mailpwcleartext'");
@@ -181,7 +181,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
]); ]);
} }
} elseif ($page == 'wipequotas' && $userinfo['change_serversettings'] == '1') { } elseif ($page == 'wipequotas' && $userinfo['change_serversettings'] == '1') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all mailquotas"); $log->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "wiped all mailquotas");
// Set the quota to 0 which means unlimited // Set the quota to 0 which means unlimited
@@ -194,7 +194,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
]); ]);
} }
} elseif ($page == 'enforcequotas' && $userinfo['change_serversettings'] == '1') { } elseif ($page == 'enforcequotas' && $userinfo['change_serversettings'] == '1') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
// Fetch all accounts // Fetch all accounts
$result_stmt = Database::query("SELECT `quota`, `customerid` FROM `" . TABLE_MAIL_USERS . "`"); $result_stmt = Database::query("SELECT `quota`, `customerid` FROM `" . TABLE_MAIL_USERS . "`");
@@ -233,9 +233,9 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
} }
} elseif ($page == 'integritycheck' && $userinfo['change_serversettings'] == '1') { } elseif ($page == 'integritycheck' && $userinfo['change_serversettings'] == '1') {
$integrity = new IntegrityCheck(); $integrity = new IntegrityCheck();
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$integrity->fixAll(); $integrity->fixAll();
} elseif (Request::get('action') == "fix") { } elseif (isset($_GET['action']) && $_GET['action'] == "fix") {
HTML::askYesNo('admin_integritycheck_reallyfix', $filename, [ HTML::askYesNo('admin_integritycheck_reallyfix', $filename, [
'page' => $page 'page' => $page
]); ]);
@@ -273,7 +273,7 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
Response::standardError('jsonextensionnotfound'); Response::standardError('jsonextensionnotfound');
} }
if (Request::get('action') == "export") { if (isset($_GET['action']) && $_GET['action'] == "export") {
// export // export
try { try {
$json_result = Froxlor::getLocal($userinfo)->exportSettings(); $json_result = Froxlor::getLocal($userinfo)->exportSettings();
@@ -285,9 +285,9 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
header('Content-type: application/json'); header('Content-type: application/json');
echo $json_export; echo $json_export;
exit(); exit();
} elseif (Request::get('action') == "import") { } elseif (isset($_GET['action']) && $_GET['action'] == "import") {
// import // import
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
// get uploaded file // get uploaded file
if (isset($_FILES["import_file"]["tmp_name"])) { if (isset($_FILES["import_file"]["tmp_name"])) {
$imp_content = file_get_contents($_FILES["import_file"]["tmp_name"]); $imp_content = file_get_contents($_FILES["import_file"]["tmp_name"]);
@@ -330,8 +330,8 @@ if ($page == 'overview' && $userinfo['change_serversettings'] == '1') {
$note_type = 'info'; $note_type = 'info';
$note_msg = lng('admin.smtptestnote'); $note_msg = lng('admin.smtptestnote');
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$test_addr = Request::post('test_addr'); $test_addr = isset($_POST['test_addr']) ? $_POST['test_addr'] : null;
// Initialize the mailingsystem // Initialize the mailingsystem
$testmail = new PHPMailer(true); $testmail = new PHPMailer(true);

View File

@@ -192,7 +192,7 @@ if ($action == '') {
$result = $result_stmt->fetch(PDO::FETCH_ASSOC); $result = $result_stmt->fetch(PDO::FETCH_ASSOC);
if ($result['varname'] != '') { if ($result['varname'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$del_stmt = Database::prepare(" $del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_TEMPLATES . "` DELETE FROM `" . TABLE_PANEL_TEMPLATES . "`
WHERE `adminid` = :adminid WHERE `adminid` = :adminid
@@ -228,7 +228,7 @@ if ($action == '') {
if (Database::num_rows() > 0) { if (Database::num_rows() > 0) {
$row = $result_stmt->fetch(PDO::FETCH_ASSOC); $row = $result_stmt->fetch(PDO::FETCH_ASSOC);
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$del_stmt = Database::prepare(" $del_stmt = Database::prepare("
DELETE FROM `" . TABLE_PANEL_TEMPLATES . "` DELETE FROM `" . TABLE_PANEL_TEMPLATES . "`
WHERE `adminid` = :adminid AND `id` = :id"); WHERE `adminid` = :adminid AND `id` = :id");
@@ -251,13 +251,13 @@ if ($action == '') {
Response::standardError('templatenotfound'); Response::standardError('templatenotfound');
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if (Request::post('prepare') == 'prepare') { if (isset($_POST['prepare']) && $_POST['prepare'] == 'prepare') {
// email templates // email templates
$language = htmlentities(Validate::validate(Request::post('language'), 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect')); $language = htmlentities(Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect'));
if (!array_key_exists($language, $languages)) { if (!array_key_exists($language, $languages)) {
Response::standardError('templatelanguageinvalid'); Response::standardError('templatelanguageinvalid');
} }
$template = Validate::validate(Request::post('template'), 'template'); $template = Validate::validate($_POST['template'], 'template');
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT COUNT(*) as def FROM `" . TABLE_PANEL_TEMPLATES . "` SELECT COUNT(*) as def FROM `" . TABLE_PANEL_TEMPLATES . "`
@@ -289,15 +289,15 @@ if ($action == '') {
'formdata' => $template_add_data['template_add'], 'formdata' => $template_add_data['template_add'],
'replacers' => $template_add_data['template_replacers'] 'replacers' => $template_add_data['template_replacers']
]); ]);
} elseif (Request::post('send') == 'send' && empty(Request::post('filesend'))) { } elseif (isset($_POST['send']) && $_POST['send'] == 'send' && !isset($_POST['filesend'])) {
// email templates // email templates
$language = htmlentities(Validate::validate(Request::post('language'), 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect')); $language = htmlentities(Validate::validate($_POST['language'], 'language', '/^[^\r\n\0"\']+$/', 'nolanguageselect'));
if (!array_key_exists($language, $languages)) { if (!array_key_exists($language, $languages)) {
Response::standardError('templatelanguageinvalid'); Response::standardError('templatelanguageinvalid');
} }
$template = Validate::validate(Request::post('template'), 'template'); $template = Validate::validate($_POST['template'], 'template');
$subject = Validate::validate(Request::post('subject'), 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate'); $subject = Validate::validate($_POST['subject'], 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate');
$mailbody = Validate::validate(Request::post('mailbody'), 'mailbody', '/^[^\0]+$/', 'nomailbodycreate'); $mailbody = Validate::validate($_POST['mailbody'], 'mailbody', '/^[^\0]+$/', 'nomailbodycreate');
$templates = []; $templates = [];
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT `varname` FROM `" . TABLE_PANEL_TEMPLATES . "` SELECT `varname` FROM `" . TABLE_PANEL_TEMPLATES . "`
@@ -347,10 +347,10 @@ if ($action == '') {
'page' => $page 'page' => $page
]); ]);
} }
} elseif (Request::post('filesend') == 'filesend') { } elseif (isset($_POST['filesend']) && $_POST['filesend'] == 'filesend') {
// file templates // file templates
$template = Validate::validate(Request::post('template'), 'template'); $template = Validate::validate($_POST['template'], 'template');
$filecontent = Validate::validate(Request::post('filecontent'), 'filecontent', '/^[^\0]+$/', 'filecontentnotset'); $filecontent = Validate::validate($_POST['filecontent'], 'filecontent', '/^[^\0]+$/', 'filecontentnotset');
$ins_stmt = Database::prepare(" $ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_PANEL_TEMPLATES . "` SET INSERT INTO `" . TABLE_PANEL_TEMPLATES . "` SET
@@ -371,7 +371,7 @@ if ($action == '') {
Response::redirectTo($filename, [ Response::redirectTo($filename, [
'page' => $page 'page' => $page
]); ]);
} elseif (empty(Request::get('files'))) { } elseif (!isset($_GET['files'])) {
// email templates // email templates
$add = false; $add = false;
$language_options = []; $language_options = [];
@@ -483,9 +483,9 @@ if ($action == '') {
$result = $result_stmt->fetch(PDO::FETCH_ASSOC); $result = $result_stmt->fetch(PDO::FETCH_ASSOC);
if ($result['varname'] != '') { if ($result['varname'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$subject = Validate::validate(Request::post('subject'), 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate'); $subject = Validate::validate($_POST['subject'], 'subject', '/^[^\r\n\0]+$/', 'nosubjectcreate');
$mailbody = Validate::validate(Request::post('mailbody'), 'mailbody', '/^[^\0]+$/', 'nomailbodycreate'); $mailbody = Validate::validate($_POST['mailbody'], 'mailbody', '/^[^\0]+$/', 'nomailbodycreate');
$upd_stmt = Database::prepare(" $upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET
@@ -551,8 +551,8 @@ if ($action == '') {
$row = $result_stmt->fetch(PDO::FETCH_ASSOC); $row = $result_stmt->fetch(PDO::FETCH_ASSOC);
// filetemplates // filetemplates
if (Request::post('filesend') == 'filesend') { if (isset($_POST['filesend']) && $_POST['filesend'] == 'filesend') {
$filecontent = Validate::validate(Request::post('filecontent'), 'filecontent', '/^[^\0]+$/', 'filecontentnotset'); $filecontent = Validate::validate($_POST['filecontent'], 'filecontent', '/^[^\0]+$/', 'filecontentnotset');
$upd_stmt = Database::prepare(" $upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET UPDATE `" . TABLE_PANEL_TEMPLATES . "` SET
`value` = :value `value` = :value

View File

@@ -34,7 +34,6 @@ use Froxlor\Install\Update;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\System\Cronjob; use Froxlor\System\Cronjob;
use Froxlor\UI\Panel\UI; use Froxlor\UI\Panel\UI;
use Froxlor\UI\Request;
use Froxlor\UI\Response; use Froxlor\UI\Response;
use Froxlor\User; use Froxlor\User;
@@ -49,8 +48,8 @@ if ($page == 'overview') {
$successful_update = false; $successful_update = false;
$message = ''; $message = '';
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
if ((!empty(Request::post('update_preconfig')) && intval(Request::post('update_changesagreed', 0)) != 0) || empty(Request::post('update_preconfig'))) { if ((isset($_POST['update_preconfig']) && isset($_POST['update_changesagreed']) && intval($_POST['update_changesagreed']) != 0) || !isset($_POST['update_preconfig'])) {
include_once Froxlor::getInstallDir() . 'install/updatesql.php'; include_once Froxlor::getInstallDir() . 'install/updatesql.php';
User::updateCounters(); User::updateCounters();

View File

@@ -61,7 +61,7 @@ if ($action == 'delete' && $id > 0) {
'section' => 'index', 'section' => 'index',
'page' => $page 'page' => $page
]); ]);
} elseif (Request::post('send') == 'send' && $action == 'deletesure' && $id > 0) { } elseif (isset($_POST['send']) && $_POST['send'] == 'send' && $action == 'deletesure' && $id > 0) {
$chk = (AREA == 'admin' && $userinfo['customers_see_all'] == '1') ? true : false; $chk = (AREA == 'admin' && $userinfo['customers_see_all'] == '1') ? true : false;
if (AREA == 'customer') { if (AREA == 'customer') {
$chk_stmt = Database::prepare(" $chk_stmt = Database::prepare("
@@ -94,7 +94,7 @@ if ($action == 'delete' && $id > 0) {
]); ]);
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$ins_stmt = Database::prepare(" $ins_stmt = Database::prepare("
INSERT INTO `" . TABLE_API_KEYS . "` SET INSERT INTO `" . TABLE_API_KEYS . "` SET
`apikey` = :key, `secret` = :secret, `adminid` = :aid, `customerid` = :cid, `valid_until` = '-1', `allowed_from` = '' `apikey` = :key, `secret` = :secret, `adminid` = :aid, `customerid` = :cid, `valid_until` = '-1', `allowed_from` = ''

567
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,7 @@
const AREA = 'customer'; const AREA = 'customer';
require __DIR__ . '/lib/init.php'; require __DIR__ . '/lib/init.php';
use Froxlor\Api\Commands\SubDomains; use Froxlor\Api\Commands\SubDomains as SubDomains;
use Froxlor\CurrentUser; use Froxlor\CurrentUser;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Domain\Domain; use Froxlor\Domain\Domain;
@@ -72,7 +72,7 @@ if ($page == 'overview' || $page == 'domains') {
} }
$actions_links[] = [ $actions_links[] = [
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/domains/', 'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/domains/',
'target' => '_blank', 'target' => '_blank',
'icon' => 'fa-solid fa-circle-info', 'icon' => 'fa-solid fa-circle-info',
'class' => 'btn-outline-secondary' 'class' => 'btn-outline-secondary'
@@ -106,9 +106,9 @@ if ($page == 'overview' || $page == 'domains') {
]); ]);
if (isset($result['parentdomainid']) && $result['parentdomainid'] != '0' && $alias_check['count'] == 0) { if (isset($result['parentdomainid']) && $result['parentdomainid'] != '0' && $alias_check['count'] == 0) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
SubDomains::getLocal($userinfo, Request::postAll())->delete(); SubDomains::getLocal($userinfo, $_POST)->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -127,9 +127,9 @@ if ($page == 'overview' || $page == 'domains') {
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if ($userinfo['subdomains_used'] < $userinfo['subdomains'] || $userinfo['subdomains'] == '-1') { if ($userinfo['subdomains_used'] < $userinfo['subdomains'] || $userinfo['subdomains'] == '-1') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
SubDomains::getLocal($userinfo, Request::postAll())->add(); SubDomains::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -248,9 +248,9 @@ if ($page == 'overview' || $page == 'domains') {
Response::standardError('domaincannotbeedited', $result['domain']); Response::standardError('domaincannotbeedited', $result['domain']);
} }
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
SubDomains::getLocal($userinfo, Request::postAll())->update(); SubDomains::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -395,8 +395,8 @@ if ($page == 'overview' || $page == 'domains') {
Response::standardError('domains_canteditdomain'); Response::standardError('domains_canteditdomain');
} }
} elseif ($action == 'jqSpeciallogfileNote') { } elseif ($action == 'jqSpeciallogfileNote') {
$domainid = intval(Request::post('id')); $domainid = intval($_POST['id']);
$newval = intval(Request::post('newval')); $newval = intval($_POST['newval']);
try { try {
$json_result = SubDomains::getLocal($userinfo, [ $json_result = SubDomains::getLocal($userinfo, [
'id' => $domainid 'id' => $domainid

View File

@@ -30,7 +30,6 @@ use Froxlor\Api\Commands\EmailAccounts;
use Froxlor\Api\Commands\EmailDomains; use Froxlor\Api\Commands\EmailDomains;
use Froxlor\Api\Commands\EmailForwarders; use Froxlor\Api\Commands\EmailForwarders;
use Froxlor\Api\Commands\Emails; use Froxlor\Api\Commands\Emails;
use Froxlor\Cron\Mail\Rspamd;
use Froxlor\CurrentUser; use Froxlor\CurrentUser;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\FroxlorLogger; use Froxlor\FroxlorLogger;
@@ -77,7 +76,7 @@ if ($page == 'overview' || $page == 'emails') {
} }
$actions_links[] = [ $actions_links[] = [
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/emails/', 'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/emails/',
'target' => '_blank', 'target' => '_blank',
'icon' => 'fa-solid fa-circle-info', 'icon' => 'fa-solid fa-circle-info',
'class' => 'btn-outline-secondary' 'class' => 'btn-outline-secondary'
@@ -139,7 +138,7 @@ if ($page == 'email_domain') {
]; ];
} }
$actions_links[] = [ $actions_links[] = [
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/emails/', 'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/emails/',
'target' => '_blank', 'target' => '_blank',
'icon' => 'fa-solid fa-circle-info', 'icon' => 'fa-solid fa-circle-info',
'class' => 'btn-outline-secondary' 'class' => 'btn-outline-secondary'
@@ -161,11 +160,11 @@ if ($page == 'email_domain') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['email']) && $result['email'] != '') { if (isset($result['email']) && $result['email'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Emails::getLocal($userinfo, [ Emails::getLocal($userinfo, [
'id' => $id, 'id' => $id,
'delete_userfiles' => Request::post('delete_userfiles', 0) 'delete_userfiles' => ($_POST['delete_userfiles'] ?? 0)
])->delete(); ])->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
@@ -188,9 +187,9 @@ if ($page == 'email_domain') {
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if ($userinfo['emails_used'] < $userinfo['emails'] || $userinfo['emails'] == '-1') { if ($userinfo['emails_used'] < $userinfo['emails'] || $userinfo['emails'] == '-1') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
$json_result = Emails::getLocal($userinfo, Request::postAll())->add(); $json_result = Emails::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -245,16 +244,7 @@ if ($page == 'email_domain') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['email']) && $result['email'] != '') { if (isset($result['email']) && $result['email'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try {
Emails::getLocal($userinfo, [
'id' => $id,
'spam_tag_level' => Request::post('spam_tag_level', Rspamd::DEFAULT_MARK_LVL),
'spam_kill_level' => Request::post('spam_kill_level', Rspamd::DEFAULT_REJECT_LVL)
])->update();
} catch (Exception $e) {
Response::dynamicError($e->getMessage());
}
Response::redirectTo($filename, [ Response::redirectTo($filename, [
'page' => $page 'page' => $page
]); ]);
@@ -301,54 +291,6 @@ if ($page == 'email_domain') {
'editid' => $id 'editid' => $id
]); ]);
} }
} elseif ($action == 'togglebypass' && $id != 0) {
try {
$json_result = Emails::getLocal($userinfo, [
'id' => $id
])->get();
} catch (Exception $e) {
Response::dynamicError($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
try {
Emails::getLocal($userinfo, [
'id' => $id,
'bypass_spam' => ($result['bypass_spam'] == '1' ? 0 : 1)
])->update();
} catch (Exception $e) {
Response::dynamicError($e->getMessage());
}
Response::redirectTo($filename, [
'page' => $page,
'domainid' => $email_domainid,
'action' => 'edit',
'id' => $id,
]);
} elseif ($action == 'togglegreylist' && $id != 0) {
try {
$json_result = Emails::getLocal($userinfo, [
'id' => $id
])->get();
} catch (Exception $e) {
Response::dynamicError($e->getMessage());
}
$result = json_decode($json_result, true)['data'];
try {
Emails::getLocal($userinfo, [
'id' => $id,
'policy_greylist' => ($result['policy_greylist'] == '1' ? 0 : 1)
])->update();
} catch (Exception $e) {
Response::dynamicError($e->getMessage());
}
Response::redirectTo($filename, [
'page' => $page,
'domainid' => $email_domainid,
'action' => 'edit',
'id' => $id,
]);
} elseif ($action == 'togglecatchall' && $id != 0) { } elseif ($action == 'togglecatchall' && $id != 0) {
try { try {
$json_result = Emails::getLocal($userinfo, [ $json_result = Emails::getLocal($userinfo, [
@@ -387,9 +329,9 @@ if ($page == 'email_domain') {
} }
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
EmailAccounts::getLocal($userinfo, Request::postAll())->add(); EmailAccounts::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -458,9 +400,9 @@ if ($page == 'email_domain') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['popaccountid']) && $result['popaccountid'] != '') { if (isset($result['popaccountid']) && $result['popaccountid'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
EmailAccounts::getLocal($userinfo, Request::postAll())->update(); EmailAccounts::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -517,9 +459,9 @@ if ($page == 'email_domain') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['popaccountid']) && $result['popaccountid'] != '') { if (isset($result['popaccountid']) && $result['popaccountid'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
EmailAccounts::getLocal($userinfo, Request::postAll())->update(); EmailAccounts::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -576,9 +518,9 @@ if ($page == 'email_domain') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['popaccountid']) && $result['popaccountid'] != '') { if (isset($result['popaccountid']) && $result['popaccountid'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
EmailAccounts::getLocal($userinfo, Request::postAll())->delete(); EmailAccounts::getLocal($userinfo, $_POST)->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -612,9 +554,9 @@ if ($page == 'email_domain') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['email']) && $result['email'] != '') { if (isset($result['email']) && $result['email'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
EmailForwarders::getLocal($userinfo, Request::postAll())->add(); EmailForwarders::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -674,15 +616,22 @@ if ($page == 'email_domain') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['destination']) && $result['destination'] != '') { if (isset($result['destination']) && $result['destination'] != '') {
$forwarderid = Request::any('forwarderid', 0); if (isset($_POST['forwarderid'])) {
$forwarderid = intval($_POST['forwarderid']);
} elseif (isset($_GET['forwarderid'])) {
$forwarderid = intval($_GET['forwarderid']);
} else {
$forwarderid = 0;
}
$result['destination'] = explode(' ', $result['destination']); $result['destination'] = explode(' ', $result['destination']);
if (isset($result['destination'][$forwarderid]) && $result['email'] != $result['destination'][$forwarderid]) { if (isset($result['destination'][$forwarderid]) && $result['email'] != $result['destination'][$forwarderid]) {
$forwarder = $result['destination'][$forwarderid]; $forwarder = $result['destination'][$forwarderid];
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
EmailForwarders::getLocal($userinfo, Request::postAll())->delete(); EmailForwarders::getLocal($userinfo, $_POST)->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }

View File

@@ -75,7 +75,7 @@ if ($page == 'overview' || $page == 'htpasswds') {
]; ];
$actions_links[] = [ $actions_links[] = [
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/extras/', 'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/extras/',
'target' => '_blank', 'target' => '_blank',
'icon' => 'fa-solid fa-circle-info', 'icon' => 'fa-solid fa-circle-info',
'class' => 'btn-outline-secondary' 'class' => 'btn-outline-secondary'
@@ -97,9 +97,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['username']) && $result['username'] != '') { if (isset($result['username']) && $result['username'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
DirProtections::getLocal($userinfo, Request::postAll())->delete(); DirProtections::getLocal($userinfo, $_POST)->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -119,9 +119,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
} }
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
DirProtections::getLocal($userinfo, Request::postAll())->add(); DirProtections::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -149,9 +149,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['username']) && $result['username'] != '') { if (isset($result['username']) && $result['username'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
DirProtections::getLocal($userinfo, Request::postAll())->update(); DirProtections::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -200,7 +200,7 @@ if ($page == 'overview' || $page == 'htpasswds') {
]; ];
$actions_links[] = [ $actions_links[] = [
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/extras/', 'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/extras/',
'target' => '_blank', 'target' => '_blank',
'icon' => 'fa-solid fa-circle-info', 'icon' => 'fa-solid fa-circle-info',
'class' => 'btn-outline-secondary' 'class' => 'btn-outline-secondary'
@@ -222,9 +222,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['customerid']) && $result['customerid'] != '' && $result['customerid'] == $userinfo['customerid']) { if (isset($result['customerid']) && $result['customerid'] != '' && $result['customerid'] == $userinfo['customerid']) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
DirOptions::getLocal($userinfo, Request::postAll())->delete(); DirOptions::getLocal($userinfo, $_POST)->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -240,9 +240,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
} }
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
DirOptions::getLocal($userinfo, Request::postAll())->add(); DirOptions::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -271,9 +271,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if ((isset($result['customerid'])) && ($result['customerid'] != '') && ($result['customerid'] == $userinfo['customerid'])) { if ((isset($result['customerid'])) && ($result['customerid'] != '') && ($result['customerid'] == $userinfo['customerid'])) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
DirOptions::getLocal($userinfo, Request::postAll())->update(); DirOptions::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -306,10 +306,10 @@ if ($page == 'overview' || $page == 'htpasswds') {
if (Settings::Get('system.exportenabled') == 1) { if (Settings::Get('system.exportenabled') == 1) {
if ($action == 'abort') { if ($action == 'abort') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "customer_extras::export - aborted scheduled data export job"); $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "customer_extras::export - aborted scheduled data export job");
try { try {
DataDump::getLocal($userinfo, Request::postAll())->delete(); DataDump::getLocal($userinfo, $_POST)->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -336,9 +336,9 @@ if ($page == 'overview' || $page == 'htpasswds') {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
DataDump::getLocal($userinfo, Request::postAll())->add(); DataDump::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -349,7 +349,7 @@ if ($page == 'overview' || $page == 'htpasswds') {
$actions_links = [ $actions_links = [
[ [
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/extras/', 'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/extras/',
'target' => '_blank', 'target' => '_blank',
'icon' => 'fa-solid fa-circle-info', 'icon' => 'fa-solid fa-circle-info',
'class' => 'btn-outline-secondary' 'class' => 'btn-outline-secondary'

View File

@@ -65,7 +65,7 @@ if ($page == 'overview' || $page == 'accounts') {
]; ];
} }
$actions_links[] = [ $actions_links[] = [
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/ftp-accounts/', 'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/ftp-accounts/',
'target' => '_blank', 'target' => '_blank',
'icon' => 'fa-solid fa-circle-info', 'icon' => 'fa-solid fa-circle-info',
'class' => 'btn-outline-secondary' 'class' => 'btn-outline-secondary'
@@ -87,9 +87,9 @@ if ($page == 'overview' || $page == 'accounts') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['username']) && $result['username'] != $userinfo['loginname']) { if (isset($result['username']) && $result['username'] != $userinfo['loginname']) {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Ftps::getLocal($userinfo, Request::postAll())->delete(); Ftps::getLocal($userinfo, $_POST)->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -108,9 +108,9 @@ if ($page == 'overview' || $page == 'accounts') {
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if ($userinfo['ftps_used'] < $userinfo['ftps'] || $userinfo['ftps'] == '-1') { if ($userinfo['ftps_used'] < $userinfo['ftps'] || $userinfo['ftps'] == '-1') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Ftps::getLocal($userinfo, Request::postAll())->add(); Ftps::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -164,9 +164,9 @@ if ($page == 'overview' || $page == 'accounts') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['username']) && $result['username'] != '') { if (isset($result['username']) && $result['username'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Ftps::getLocal($userinfo, Request::postAll())->update(); Ftps::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }

View File

@@ -30,7 +30,6 @@ use Froxlor\Api\Commands\Customers as Customers;
use Froxlor\Cron\TaskId; use Froxlor\Cron\TaskId;
use Froxlor\CurrentUser; use Froxlor\CurrentUser;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Database\DbManager;
use Froxlor\Froxlor; use Froxlor\Froxlor;
use Froxlor\FroxlorLogger; use Froxlor\FroxlorLogger;
use Froxlor\Language; use Froxlor\Language;
@@ -38,7 +37,6 @@ use Froxlor\Settings;
use Froxlor\System\Cronjob; use Froxlor\System\Cronjob;
use Froxlor\System\Crypt; use Froxlor\System\Crypt;
use Froxlor\UI\Panel\UI; use Froxlor\UI\Panel\UI;
use Froxlor\UI\Request;
use Froxlor\UI\Response; use Froxlor\UI\Response;
use Froxlor\Validate\Validate; use Froxlor\Validate\Validate;
@@ -56,7 +54,7 @@ if ($action == 'logout') {
$result = $result['switched_user']; $result = $result['switched_user'];
session_regenerate_id(true); session_regenerate_id(true);
CurrentUser::setData($result); CurrentUser::setData($result);
$target = Request::get('target', 'index'); $target = (isset($_GET['target']) ? $_GET['target'] : 'index');
$redirect = "admin_" . $target . ".php"; $redirect = "admin_" . $target . ".php";
if (!file_exists(Froxlor::getInstallDir() . "/" . $redirect)) { if (!file_exists(Froxlor::getInstallDir() . "/" . $redirect)) {
$redirect = "admin_index.php"; $redirect = "admin_index.php";
@@ -142,16 +140,16 @@ if ($page == 'overview') {
$languages = Language::getLanguages(); $languages = Language::getLanguages();
if (!empty($_POST)) { if (!empty($_POST)) {
if (Request::post('send') == 'changepassword') { if ($_POST['send'] == 'changepassword') {
$old_password = Validate::validate(Request::post('old_password'), 'old password'); $old_password = Validate::validate($_POST['old_password'], 'old password');
if (!Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_CUSTOMERS, 'customerid')) { if (!Crypt::validatePasswordLogin($userinfo, $old_password, TABLE_PANEL_CUSTOMERS, 'customerid')) {
Response::standardError('oldpasswordnotcorrect'); Response::standardError('oldpasswordnotcorrect');
} }
try { try {
$new_password = Crypt::validatePassword(Request::post('new_password'), 'new password'); $new_password = Crypt::validatePassword($_POST['new_password'], 'new password');
$new_password_confirm = Crypt::validatePassword(Request::post('new_password_confirm'), 'new password confirm'); $new_password_confirm = Crypt::validatePassword($_POST['new_password_confirm'], 'new password confirm');
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -186,7 +184,7 @@ if ($page == 'overview') {
$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, 'changed password'); $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, 'changed password');
// Update ftp password // Update ftp password
if (Request::post('change_main_ftp') == 'true') { if (isset($_POST['change_main_ftp']) && $_POST['change_main_ftp'] == 'true') {
$cryptPassword = Crypt::makeCryptPassword($new_password); $cryptPassword = Crypt::makeCryptPassword($new_password);
$stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "` $stmt = Database::prepare("UPDATE `" . TABLE_FTP_USERS . "`
SET `password` = :password SET `password` = :password
@@ -202,7 +200,7 @@ if ($page == 'overview') {
} }
// Update statistics password // Update statistics password
if (Request::post('change_stats') == 'true') { if (isset($_POST['change_stats']) && $_POST['change_stats'] == 'true') {
$new_stats_password = Crypt::makeCryptPassword($new_password, true); $new_stats_password = Crypt::makeCryptPassword($new_password, true);
$stmt = Database::prepare("UPDATE `" . TABLE_PANEL_HTPASSWDS . "` $stmt = Database::prepare("UPDATE `" . TABLE_PANEL_HTPASSWDS . "`
@@ -218,32 +216,11 @@ if ($page == 'overview') {
Cronjob::inserttask(TaskId::REBUILD_VHOST); Cronjob::inserttask(TaskId::REBUILD_VHOST);
} }
// Update global myqsl user password
if ($userinfo['mysqls'] != 0 && Request::post('change_global_mysql') == 'true') {
$allowed_mysqlservers = json_decode($userinfo['allowed_mysqlserver'] ?? '[]', true);
foreach ($allowed_mysqlservers as $dbserver) {
// require privileged access for target db-server
Database::needRoot(true, $dbserver, false);
// get DbManager
$dbm = new DbManager($log);
// give permission to the user on every access-host we have
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
if ($dbm->getManager()->userExistsOnHost($userinfo['loginname'], $mysql_access_host)) {
$dbm->getManager()->grantPrivilegesTo($userinfo['loginname'], $new_password, $mysql_access_host, false, true);
} else {
// create global mysql user if not exists
$dbm->getManager()->grantPrivilegesTo($userinfo['loginname'], $new_password, $mysql_access_host, false, false, true);
}
}
$dbm->getManager()->flushPrivileges();
}
}
Response::redirectTo($filename); Response::redirectTo($filename);
} }
} elseif (Request::post('send') == 'changetheme') { } elseif ($_POST['send'] == 'changetheme') {
if (Settings::Get('panel.allow_theme_change_customer') == 1) { if (Settings::Get('panel.allow_theme_change_customer') == 1) {
$theme = Validate::validate(Request::post('theme'), 'theme'); $theme = Validate::validate($_POST['theme'], 'theme');
try { try {
Customers::getLocal($userinfo, [ Customers::getLocal($userinfo, [
'id' => $userinfo['customerid'], 'id' => $userinfo['customerid'],
@@ -256,8 +233,8 @@ if ($page == 'overview') {
$log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "changed default theme to '" . $theme . "'"); $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "changed default theme to '" . $theme . "'");
} }
Response::redirectTo($filename); Response::redirectTo($filename);
} elseif (Request::post('send') == 'changelanguage') { } elseif ($_POST['send'] == 'changelanguage') {
$def_language = Validate::validate(Request::post('def_language'), 'default language'); $def_language = Validate::validate($_POST['def_language'], 'default language');
if (isset($languages[$def_language])) { if (isset($languages[$def_language])) {
try { try {
Customers::getLocal($userinfo, [ Customers::getLocal($userinfo, [

View File

@@ -30,10 +30,8 @@ use Froxlor\Api\Commands\Mysqls;
use Froxlor\Api\Commands\MysqlServer; use Froxlor\Api\Commands\MysqlServer;
use Froxlor\CurrentUser; use Froxlor\CurrentUser;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Database\DbManager;
use Froxlor\FroxlorLogger; use Froxlor\FroxlorLogger;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\System\Crypt;
use Froxlor\UI\Collection; use Froxlor\UI\Collection;
use Froxlor\UI\HTML; use Froxlor\UI\HTML;
use Froxlor\UI\Listing; use Froxlor\UI\Listing;
@@ -76,32 +74,17 @@ if ($page == 'overview' || $page == 'mysqls') {
]; ];
} }
$view = 'user/table.html.twig';
if ($collection->count() > 0) {
$view = 'user/table-note.html.twig';
$actions_links[] = [
'href' => $linker->getLink(['section' => 'mysql', 'page' => 'mysqls', 'action' => 'global_user']),
'label' => lng('mysql.edit_global_user'),
'icon' => 'fa-solid fa-user-tie',
'class' => 'btn-outline-secondary'
];
}
$actions_links[] = [ $actions_links[] = [
'href' => \Froxlor\Froxlor::getDocsUrl() . 'user-guide/databases/', 'href' => \Froxlor\Froxlor::DOCS_URL . 'user-guide/databases/',
'target' => '_blank', 'target' => '_blank',
'icon' => 'fa-solid fa-circle-info', 'icon' => 'fa-solid fa-circle-info',
'class' => 'btn-outline-secondary' 'class' => 'btn-outline-secondary'
]; ];
UI::view($view, [ UI::view('user/table.html.twig', [
'listing' => Listing::format($collection, $mysql_list_data, 'mysql_list'), 'listing' => Listing::format($collection, $mysql_list_data, 'mysql_list'),
'actions_links' => $actions_links, 'actions_links' => $actions_links,
'entity_info' => lng('mysql.description'), 'entity_info' => lng('mysql.description')
// alert-box
'type' => 'info',
'alert_msg' => lng('mysql.globaluserinfo', [$userinfo['loginname']]),
]); ]);
} elseif ($action == 'delete' && $id != 0) { } elseif ($action == 'delete' && $id != 0) {
try { try {
@@ -123,9 +106,9 @@ if ($page == 'overview' || $page == 'mysqls') {
$result['dbserver'] = 0; $result['dbserver'] = 0;
} }
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Mysqls::getLocal($userinfo, Request::postAll())->delete(); Mysqls::getLocal($userinfo, $_POST)->delete();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -146,9 +129,9 @@ if ($page == 'overview' || $page == 'mysqls') {
} }
} elseif ($action == 'add') { } elseif ($action == 'add') {
if ($userinfo['mysqls_used'] < $userinfo['mysqls'] || $userinfo['mysqls'] == '-1') { if ($userinfo['mysqls_used'] < $userinfo['mysqls'] || $userinfo['mysqls'] == '-1') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
Mysqls::getLocal($userinfo, Request::postAll())->add(); Mysqls::getLocal($userinfo, $_POST)->add();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -186,9 +169,9 @@ if ($page == 'overview' || $page == 'mysqls') {
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
if (isset($result['databasename']) && $result['databasename'] != '') { if (isset($result['databasename']) && $result['databasename'] != '') {
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
try { try {
$json_result = Mysqls::getLocal($userinfo, Request::postAll())->update(); $json_result = Mysqls::getLocal($userinfo, $_POST)->update();
} catch (Exception $e) { } catch (Exception $e) {
Response::dynamicError($e->getMessage()); Response::dynamicError($e->getMessage());
} }
@@ -216,45 +199,5 @@ if ($page == 'overview' || $page == 'mysqls') {
]); ]);
} }
} }
} elseif ($action == 'global_user') {
$allowed_mysqlservers = json_decode($userinfo['allowed_mysqlserver'] ?? '[]', true);
if ($userinfo['mysqls'] == 0 || empty($allowed_mysqlservers)) {
Response::dynamicError('No permission');
}
if (Request::post('send') == 'send') {
$new_password = Crypt::validatePassword(Request::post('mysql_password'));
foreach ($allowed_mysqlservers as $dbserver) {
// require privileged access for target db-server
Database::needRoot(true, $dbserver, false);
// get DbManager
$dbm = new DbManager($log);
// give permission to the user on every access-host we have
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
if ($dbm->getManager()->userExistsOnHost($userinfo['loginname'], $mysql_access_host)) {
// update password
$dbm->getManager()->grantPrivilegesTo($userinfo['loginname'], $new_password, $mysql_access_host, false, true, true);
} else {
// create missing user
$dbm->getManager()->grantPrivilegesTo($userinfo['loginname'], $new_password, $mysql_access_host, false, false, true);
}
}
$dbm->getManager()->flushPrivileges();
}
Response::redirectTo($filename, [
'page' => 'overview'
]);
} else {
$mysql_global_user_data = include_once dirname(__FILE__) . '/lib/formfields/customer/mysql/formfield.mysql_global_user.php';
UI::view('user/form.html.twig', [
'formaction' => $linker->getLink(['section' => 'mysql', 'page' => 'mysqls', 'action' => 'global_user']),
'formdata' => $mysql_global_user_data['mysql_global_user'],
'editid' => $id
]);
}
} }
} }

View File

@@ -30,7 +30,6 @@ if (!defined('AREA')) {
use Froxlor\Api\Commands\DomainZones; use Froxlor\Api\Commands\DomainZones;
use Froxlor\Dns\Dns; use Froxlor\Dns\Dns;
use Froxlor\Settings;
use Froxlor\UI\Collection; use Froxlor\UI\Collection;
use Froxlor\UI\HTML; use Froxlor\UI\HTML;
use Froxlor\UI\Listing; use Froxlor\UI\Listing;
@@ -43,11 +42,11 @@ use Froxlor\UI\Response;
$domain_id = (int)Request::any('domain_id'); $domain_id = (int)Request::any('domain_id');
$record = Request::post('dns_record'); $record = isset($_POST['dns_record']) ? trim($_POST['dns_record']) : null;
$type = Request::post('dns_type', 'A'); $type = isset($_POST['dns_type']) ? $_POST['dns_type'] : 'A';
$prio = Request::post('dns_mxp'); $prio = isset($_POST['dns_mxp']) ? (int)$_POST['dns_mxp'] : null;
$content = Request::post('dns_content'); $content = isset($_POST['dns_content']) ? trim($_POST['dns_content']) : null;
$ttl = (int)Request::post('dns_ttl', Settings::get('system.defaultttl')); $ttl = isset($_POST['dns_ttl']) ? (int)$_POST['dns_ttl'] : 18000;
// get domain-name // get domain-name
$domain = Dns::getAllowedDomainEntry($domain_id, AREA, $userinfo); $domain = Dns::getAllowedDomainEntry($domain_id, AREA, $userinfo);
@@ -72,7 +71,7 @@ if ($action == 'add_record' && !empty($_POST)) {
$errors = str_replace("\n", "<br>", $e->getMessage()); $errors = str_replace("\n", "<br>", $e->getMessage());
} }
} elseif ($action == 'delete') { } elseif ($action == 'delete') {
$entry_id = (int)Request::get('id', 0); $entry_id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
HTML::askYesNo('dnsentry_reallydelete', $filename, [ HTML::askYesNo('dnsentry_reallydelete', $filename, [
'id' => $entry_id, 'id' => $entry_id,
'domain_id' => $domain_id, 'domain_id' => $domain_id,
@@ -83,9 +82,9 @@ if ($action == 'add_record' && !empty($_POST)) {
'page' => $page, 'page' => $page,
'domain_id' => $domain_id 'domain_id' => $domain_id
]); ]);
} elseif (Request::post('send') == 'send' && $action == 'deletesure' && !empty($_POST)) { } elseif (isset($_POST['send']) && $_POST['send'] == 'send' && $action == 'deletesure' && !empty($_POST)) {
$entry_id = (int)Request::post('id', 0); $entry_id = isset($_POST['id']) ? (int)$_POST['id'] : 0;
$domain_id = (int)Request::post('domain_id', 0); $domain_id = isset($_POST['domain_id']) ? (int)$_POST['domain_id'] : 0;
// remove entry // remove entry
if ($entry_id > 0 && $domain_id > 0) { if ($entry_id > 0 && $domain_id > 0) {
try { try {

View File

@@ -77,7 +77,7 @@ if (!empty($errid)) {
$mail_html = nl2br($mail_body); $mail_html = nl2br($mail_body);
// send actual report to dev-team // send actual report to dev-team
if (Request::post('send') == 'send') { if (isset($_POST['send']) && $_POST['send'] == 'send') {
// send mail and say thanks // send mail and say thanks
$_mailerror = false; $_mailerror = false;
try { try {

182
index.php
View File

@@ -54,7 +54,7 @@ if ($action == '2fa_entercode') {
Response::redirectTo('index.php'); Response::redirectTo('index.php');
exit(); exit();
} }
$smessage = (int)Request::get('showmessage', 0); $smessage = isset($_GET['showmessage']) ? (int)$_GET['showmessage'] : 0;
$message = ""; $message = "";
if ($smessage > 0) { if ($smessage > 0) {
$message = lng('error.2fa_wrongcode'); $message = lng('error.2fa_wrongcode');
@@ -71,8 +71,7 @@ if ($action == '2fa_entercode') {
Response::redirectTo('index.php'); Response::redirectTo('index.php');
exit(); exit();
} }
$code = Request::post('2fa_code'); $code = isset($_POST['2fa_code']) ? $_POST['2fa_code'] : null;
$remember = Request::post('2fa_remember');
// verify entered code // verify entered code
$tfa = new FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname')); $tfa = new FroxlorTwoFactorAuth('Froxlor ' . Settings::Get('system.hostname'));
// get user-data // get user-data
@@ -106,6 +105,13 @@ if ($action == '2fa_entercode') {
$userinfo['adminsession'] = $isadmin; $userinfo['adminsession'] = $isadmin;
$userinfo['userid'] = $uid; $userinfo['userid'] = $uid;
// if not successful somehow - start again
if (!finishLogin($userinfo)) {
Response::redirectTo('index.php', [
'showmessage' => '2'
]);
}
// 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");
@@ -113,42 +119,6 @@ if ($action == '2fa_entercode') {
'uid' => $uid 'uid' => $uid
]); ]);
} }
// when remember is activated, set the cookie
if ($remember) {
$selector = base64_encode(Froxlor::genSessionId(9));
$authenticator = Froxlor::genSessionId(33);
$valid_until = time()+60*60*24*30;
$ins_stmt = Database::prepare("
INSERT INTO `".TABLE_PANEL_2FA_TOKENS."` SET
`selector` = :selector,
`token` = :authenticator,
`userid` = :userid,
`valid_until` = :valid_until
");
Database::pexecute($ins_stmt, [
'selector' => $selector,
'authenticator' => hash('sha256', $authenticator),
'userid' => $uid,
'valid_until' => $valid_until
]);
$cookie_params = [
'expires' => $valid_until, // 30 days
'path' => '/',
'domain' => UI::getCookieHost(),
'secure' => UI::requestIsHttps(),
'httponly' => true,
'samesite' => 'Strict'
];
setcookie('frx_2fa_remember', $selector.':'.base64_encode($authenticator), $cookie_params);
}
// if not successful somehow - start again
if (!finishLogin($userinfo)) {
Response::redirectTo('index.php', [
'showmessage' => '2'
]);
}
exit(); exit();
} }
// wrong 2fa code - treat like "wrong password" // wrong 2fa code - treat like "wrong password"
@@ -192,41 +162,30 @@ if ($action == '2fa_entercode') {
exit(); exit();
} elseif ($action == 'login') { } elseif ($action == 'login') {
if (!empty($_POST)) { if (!empty($_POST)) {
$loginname = Validate::validate(Request::post('loginname'), 'loginname'); $loginname = Validate::validate($_POST['loginname'], 'loginname');
$password = Validate::validate(Request::post('password'), 'password'); $password = Validate::validate($_POST['password'], 'password');
$select_additional = ''; $stmt = Database::prepare("SELECT `loginname` AS `customer` FROM `" . TABLE_PANEL_CUSTOMERS . "`
if (Settings::Get('panel.db_version') >= 202312230) { WHERE `loginname`= :loginname");
$select_additional = ' AND `gui_access` = 1';
}
$stmt = Database::prepare("
SELECT `loginname` AS `customer`
FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `loginname`= :loginname" .
$select_additional
);
Database::pexecute($stmt, [ Database::pexecute($stmt, [
"loginname" => $loginname "loginname" => $loginname
]); ]);
$row = $stmt->fetch(PDO::FETCH_ASSOC); $row = $stmt->fetch(PDO::FETCH_ASSOC);
$is_admin = false;
$table = "";
if ($row && $row['customer'] == $loginname) { if ($row && $row['customer'] == $loginname) {
$table = "`" . TABLE_PANEL_CUSTOMERS . "`"; $table = "`" . TABLE_PANEL_CUSTOMERS . "`";
$uid = 'customerid'; $uid = 'customerid';
$adminsession = '0'; $adminsession = '0';
$is_admin = false;
} else { } else {
$is_admin = true;
if ((int)Settings::Get('login.domain_login') == 1) { if ((int)Settings::Get('login.domain_login') == 1) {
$domainname = $idna_convert->encode(preg_replace([ $domainname = $idna_convert->encode(preg_replace([
'/\:(\d)+$/', '/\:(\d)+$/',
'/^https?\:\/\//' '/^https?\:\/\//'
], '', $loginname)); ], '', $loginname));
$stmt = Database::prepare(" $stmt = Database::prepare("SELECT `customerid` FROM `" . TABLE_PANEL_DOMAINS . "`
SELECT `customerid` WHERE `domain` = :domain");
FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `domain` = :domain
");
Database::pexecute($stmt, [ Database::pexecute($stmt, [
"domain" => $domainname "domain" => $domainname
]); ]);
@@ -235,11 +194,8 @@ if ($action == '2fa_entercode') {
if (isset($row2['customerid']) && $row2['customerid'] > 0) { if (isset($row2['customerid']) && $row2['customerid'] > 0) {
$loginname = Customer::getCustomerDetail($row2['customerid'], 'loginname'); $loginname = Customer::getCustomerDetail($row2['customerid'], 'loginname');
if ($loginname !== false) { if ($loginname !== false) {
$stmt = Database::prepare(" $stmt = Database::prepare("SELECT `loginname` AS `customer` FROM `" . TABLE_PANEL_CUSTOMERS . "`
SELECT `loginname` AS `customer` WHERE `loginname`= :loginname");
FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `loginname`= :loginname
");
Database::pexecute($stmt, [ Database::pexecute($stmt, [
"loginname" => $loginname "loginname" => $loginname
]); ]);
@@ -248,17 +204,13 @@ if ($action == '2fa_entercode') {
$table = "`" . TABLE_PANEL_CUSTOMERS . "`"; $table = "`" . TABLE_PANEL_CUSTOMERS . "`";
$uid = 'customerid'; $uid = 'customerid';
$adminsession = '0'; $adminsession = '0';
$is_admin = false;
} }
} }
} }
} }
} }
if (empty($table)) {
// try login as admin of no customer-login method worked
$is_admin = true;
}
if ((Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) && $is_admin == false) { if ((Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) && $is_admin == false) {
Response::redirectTo('index.php'); Response::redirectTo('index.php');
exit(); exit();
@@ -266,11 +218,9 @@ if ($action == '2fa_entercode') {
if ($is_admin) { if ($is_admin) {
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) { if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
$stmt = Database::prepare(" $stmt = Database::prepare("SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
WHERE `loginname`= :loginname WHERE `loginname`= :loginname
AND `change_serversettings` = '1' AND `change_serversettings` = '1'");
");
Database::pexecute($stmt, [ Database::pexecute($stmt, [
"loginname" => $loginname "loginname" => $loginname
]); ]);
@@ -281,16 +231,8 @@ if ($action == '2fa_entercode') {
exit(); exit();
} }
} else { } else {
$select_additional = ''; $stmt = Database::prepare("SELECT `loginname` AS `admin` FROM `" . TABLE_PANEL_ADMINS . "`
if (Settings::Get('panel.db_version') >= 202312230) { WHERE `loginname`= :loginname");
$select_additional = ' AND `gui_access` = 1';
}
$stmt = Database::prepare("
SELECT `loginname` AS `admin`
FROM `" . TABLE_PANEL_ADMINS . "`
WHERE `loginname`= :loginname" .
$select_additional
);
Database::pexecute($stmt, [ Database::pexecute($stmt, [
"loginname" => $loginname "loginname" => $loginname
]); ]);
@@ -306,7 +248,7 @@ if ($action == '2fa_entercode') {
$rstlog = FroxlorLogger::getInstanceOf([ $rstlog = FroxlorLogger::getInstanceOf([
'loginname' => $_SERVER['REMOTE_ADDR'] 'loginname' => $_SERVER['REMOTE_ADDR']
]); ]);
$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "Unknown user tried to login."); $rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "Unknown user '" . $loginname . "' tried to login.");
Response::redirectTo('index.php', [ Response::redirectTo('index.php', [
'showmessage' => '2' 'showmessage' => '2'
@@ -315,9 +257,8 @@ if ($action == '2fa_entercode') {
} }
} }
$userinfo_stmt = Database::prepare(" $userinfo_stmt = Database::prepare("SELECT * FROM $table
SELECT * FROM $table WHERE `loginname`= :loginname WHERE `loginname`= :loginname");
");
Database::pexecute($userinfo_stmt, [ Database::pexecute($userinfo_stmt, [
"loginname" => $loginname "loginname" => $loginname
]); ]);
@@ -340,11 +281,9 @@ if ($action == '2fa_entercode') {
} else { } else {
// login correct // login correct
// reset loginfail_counter, set lastlogin_succ // reset loginfail_counter, set lastlogin_succ
$stmt = Database::prepare(" $stmt = Database::prepare("UPDATE $table
UPDATE $table SET `lastlogin_succ`= :lastlogin_succ, `loginfail_count`='0'
SET `lastlogin_succ`= :lastlogin_succ, `loginfail_count`='0' WHERE `$uid`= :uid");
WHERE `$uid`= :uid
");
Database::pexecute($stmt, [ Database::pexecute($stmt, [
"lastlogin_succ" => time(), "lastlogin_succ" => time(),
"uid" => $userinfo[$uid] "uid" => $userinfo[$uid]
@@ -354,11 +293,9 @@ if ($action == '2fa_entercode') {
} }
} else { } else {
// login incorrect // login incorrect
$stmt = Database::prepare(" $stmt = Database::prepare("UPDATE $table
UPDATE $table
SET `lastlogin_fail`= :lastlogin_fail, `loginfail_count`=`loginfail_count`+1 SET `lastlogin_fail`= :lastlogin_fail, `loginfail_count`=`loginfail_count`+1
WHERE `$uid`= :uid WHERE `$uid`= :uid");
");
Database::pexecute($stmt, [ Database::pexecute($stmt, [
"lastlogin_fail" => time(), "lastlogin_fail" => time(),
"uid" => $userinfo[$uid] "uid" => $userinfo[$uid]
@@ -368,7 +305,7 @@ if ($action == '2fa_entercode') {
$rstlog = FroxlorLogger::getInstanceOf([ $rstlog = FroxlorLogger::getInstanceOf([
'loginname' => $_SERVER['REMOTE_ADDR'] 'loginname' => $_SERVER['REMOTE_ADDR']
]); ]);
$rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User tried to login with wrong password."); $rstlog->logAction(FroxlorLogger::LOGIN_ACTION, LOG_WARNING, "User '" . $loginname . "' tried to login with wrong password.");
unset($userinfo); unset($userinfo);
Response::redirectTo('index.php', [ Response::redirectTo('index.php', [
@@ -379,22 +316,6 @@ if ($action == '2fa_entercode') {
// 2FA activated // 2FA activated
if (Settings::Get('2fa.enabled') == '1' && $userinfo['type_2fa'] > 0) { if (Settings::Get('2fa.enabled') == '1' && $userinfo['type_2fa'] > 0) {
// check for remember cookie
if (!empty($_COOKIE['frx_2fa_remember'])) {
list($selector, $authenticator) = explode(':', $_COOKIE['frx_2fa_remember']);
$sel_stmt = Database::prepare("SELECT `token` FROM `".TABLE_PANEL_2FA_TOKENS."` WHERE `selector` = :selector AND `userid` = :uid AND `valid_until` >= UNIX_TIMESTAMP()");
$token_check = Database::pexecute_first($sel_stmt, ['selector' => $selector, 'uid' => $userinfo[$uid]]);
if ($token_check && hash_equals($token_check['token'], hash('sha256', base64_decode($authenticator)))) {
if (!finishLogin($userinfo)) {
Response::redirectTo('index.php', [
'showmessage' => '2'
]);
}
exit();
}
}
// redirect to code-enter-page // redirect to code-enter-page
$_SESSION['secret_2fa'] = ($userinfo['type_2fa'] == 2 ? $userinfo['data_2fa'] : 'email'); $_SESSION['secret_2fa'] = ($userinfo['type_2fa'] == 2 ? $userinfo['data_2fa'] : 'email');
$_SESSION['uid_2fa'] = $userinfo[$uid]; $_SESSION['uid_2fa'] = $userinfo[$uid];
@@ -462,7 +383,7 @@ if ($action == '2fa_entercode') {
} }
exit(); exit();
} else { } else {
$smessage = (int)Request::get('showmessage', 0); $smessage = isset($_GET['showmessage']) ? (int)$_GET['showmessage'] : 0;
$message = ''; $message = '';
$successmessage = ''; $successmessage = '';
@@ -499,20 +420,25 @@ if ($action == '2fa_entercode') {
} }
// Pass the last used page if needed // Pass the last used page if needed
$lastscript = Request::any('script', ''); $lastscript = "";
if (!empty($lastscript)) { if (isset($_REQUEST['script']) && $_REQUEST['script'] != "") {
$lastscript = $_REQUEST['script'];
$lastscript = str_replace("..", "", $lastscript); $lastscript = str_replace("..", "", $lastscript);
$lastscript = htmlspecialchars($lastscript, ENT_QUOTES); $lastscript = htmlspecialchars($lastscript, ENT_QUOTES);
if (file_exists(__DIR__ . "/" . $lastscript)) { if (!file_exists(__DIR__ . "/" . $lastscript)) {
$_SESSION['lastscript'] = $lastscript;
} else {
$lastscript = ""; $lastscript = "";
} }
} }
$lastqrystr = Request::any('qrystr', ''); $lastqrystr = "";
if (isset($_REQUEST['qrystr']) && $_REQUEST['qrystr'] != "") {
$lastqrystr = urlencode($_REQUEST['qrystr']);
}
if (!empty($lastscript)) {
$_SESSION['lastscript'] = $lastscript;
}
if (!empty($lastqrystr)) { if (!empty($lastqrystr)) {
$lastqrystr = urlencode($lastqrystr);
$_SESSION['lastqrystr'] = $lastqrystr; $_SESSION['lastqrystr'] = $lastqrystr;
} }
@@ -530,8 +456,8 @@ if ($action == 'forgotpwd') {
$message = ''; $message = '';
if (!empty($_POST)) { if (!empty($_POST)) {
$loginname = Validate::validate(Request::post('loginname'), 'loginname'); $loginname = Validate::validate($_POST['loginname'], 'loginname');
$email = Validate::validateEmail(Request::post('loginemail')); $email = Validate::validateEmail($_POST['loginemail']);
$result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "` $result_stmt = Database::prepare("SELECT `adminid`, `customerid`, `customernumber`, `firstname`, `name`, `company`, `email`, `loginname`, `def_language`, `deactivated` FROM `" . TABLE_PANEL_CUSTOMERS . "`
WHERE `loginname`= :loginname WHERE `loginname`= :loginname
AND `email`= :email"); AND `email`= :email");
@@ -698,7 +624,7 @@ if ($action == 'forgotpwd') {
$rstlog = FroxlorLogger::getInstanceOf([ $rstlog = FroxlorLogger::getInstanceOf([
'loginname' => 'password_reset' 'loginname' => 'password_reset'
]); ]);
$rstlog->logAction(FroxlorLogger::USR_ACTION, LOG_WARNING, "Unknown user requested to set a new password, but was not found in database!"); $rstlog->logAction(FroxlorLogger::USR_ACTION, LOG_WARNING, "User '" . $loginname . "' requested to set a new password, but was not found in database!");
$message = lng('login.usernotfound'); $message = lng('login.usernotfound');
} }
@@ -728,9 +654,9 @@ if ($action == 'resetpwd') {
"oldest" => time() - 86400 "oldest" => time() - 86400
]); ]);
$activationcode = Request::get('resetcode'); if (isset($_GET['resetcode']) && strlen($_GET['resetcode']) == 50) {
if (!empty($activationcode) && strlen($activationcode) == 50) {
// Check if activation code is valid // Check if activation code is valid
$activationcode = $_GET['resetcode'];
$timestamp = substr($activationcode, 15, 10); $timestamp = substr($activationcode, 15, 10);
$third = substr($activationcode, 25, 15); $third = substr($activationcode, 25, 15);
$check = substr($activationcode, 40, 10); $check = substr($activationcode, 40, 10);
@@ -745,8 +671,8 @@ if ($action == 'resetpwd') {
if ($result !== false) { if ($result !== false) {
try { try {
$new_password = Crypt::validatePassword(Request::post('new_password'), true); $new_password = Crypt::validatePassword($_POST['new_password'], true);
$new_password_confirm = Crypt::validatePassword(Request::post('new_password_confirm'), true); $new_password_confirm = Crypt::validatePassword($_POST['new_password_confirm'], true);
} catch (Exception $e) { } catch (Exception $e) {
$message = $e->getMessage(); $message = $e->getMessage();
} }
@@ -875,8 +801,8 @@ function finishLogin($userinfo)
$theme = $userinfo['theme']; $theme = $userinfo['theme'];
} else { } else {
$theme = Settings::Get('panel.default_theme'); $theme = Settings::Get('panel.default_theme');
CurrentUser::setField('theme', $theme);
} }
CurrentUser::setField('theme', $theme);
$qryparams = []; $qryparams = [];
if (!empty($_SESSION['lastqrystr'])) { if (!empty($_SESSION['lastqrystr'])) {

View File

@@ -94,10 +94,6 @@ CREATE TABLE `mail_virtual` (
`popaccountid` int(11) NOT NULL default '0', `popaccountid` int(11) NOT NULL default '0',
`iscatchall` tinyint(1) unsigned NOT NULL default '0', `iscatchall` tinyint(1) unsigned NOT NULL default '0',
`description` varchar(255) NOT NULL DEFAULT '', `description` varchar(255) NOT NULL DEFAULT '',
`spam_tag_level` float(4,1) NOT NULL DEFAULT 7.0,
`spam_kill_level` float(4,1) NOT NULL DEFAULT 14.0,
`bypass_spam` tinyint(1) NOT NULL default '0',
`policy_greylist` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `email` (`email`) KEY `email` (`email`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci; ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;
@@ -159,7 +155,6 @@ CREATE TABLE `panel_admins` (
`type_2fa` tinyint(1) NOT NULL default '0', `type_2fa` tinyint(1) NOT NULL default '0',
`data_2fa` varchar(25) NOT NULL default '', `data_2fa` varchar(25) NOT NULL default '',
`api_allowed` tinyint(1) NOT NULL default '1', `api_allowed` tinyint(1) NOT NULL default '1',
`gui_access` 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 ROW_FORMAT=DYNAMIC; ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC;
@@ -228,7 +223,6 @@ CREATE TABLE `panel_customers` (
`api_allowed` tinyint(1) NOT NULL default '1', `api_allowed` tinyint(1) NOT NULL default '1',
`logviewenabled` tinyint(1) NOT NULL default '0', `logviewenabled` tinyint(1) NOT NULL default '0',
`allowed_mysqlserver` text NOT NULL, `allowed_mysqlserver` text NOT NULL,
`gui_access` tinyint(1) NOT NULL default '1',
PRIMARY KEY (`customerid`), PRIMARY KEY (`customerid`),
UNIQUE KEY `loginname` (`loginname`) UNIQUE KEY `loginname` (`loginname`)
) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC; ) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=DYNAMIC;
@@ -386,18 +380,22 @@ INSERT INTO `panel_settings` (`settinggroup`, `varname`, `value`) VALUES
('logger', 'logfile', ''), ('logger', 'logfile', ''),
('logger', 'logtypes', 'syslog,mysql'), ('logger', 'logtypes', 'syslog,mysql'),
('logger', 'severity', '1'), ('logger', 'severity', '1'),
('antispam', 'activated', '0'), ('dkim', 'use_dkim', '0'),
('antispam', 'config_file', '/etc/rspamd/local.d/froxlor_settings.conf'), ('dkim', 'dkim_prefix', '/etc/postfix/dkim/'),
('antispam', 'reload_command', 'service rspamd restart'), ('dkim', 'dkim_domains', 'domains'),
('antispam', 'dkim_keylength', '1024'), ('dkim', 'dkim_dkimkeys', 'dkim-keys.conf'),
('dkim', 'dkimrestart_command', 'service dkim-filter restart'),
('dkim', 'privkeysuffix', '.priv'),
('admin', 'show_news_feed', '0'), ('admin', 'show_news_feed', '0'),
('admin', 'show_version_login', '0'), ('admin', 'show_version_login', '0'),
('admin', 'show_version_footer', '0'), ('admin', 'show_version_footer', '0'),
('caa', 'caa_entry', ''), ('caa', 'caa_entry', ''),
('spf', 'use_spf', '0'), ('spf', 'use_spf', '0'),
('spf', 'spf_entry', 'v=spf1 a mx -all'), ('spf', 'spf_entry', 'v=spf1 a mx -all'),
('dmarc', 'use_dmarc', '0'), ('dkim', 'dkim_algorithm', 'all'),
('dmarc', 'dmarc_entry', 'v=DMARC1; p=none;'), ('dkim', 'dkim_keylength', '1024'),
('dkim', 'dkim_servicetype', '0'),
('dkim', 'dkim_notes', ''),
('defaultwebsrverrhandler', 'enabled', '0'), ('defaultwebsrverrhandler', 'enabled', '0'),
('defaultwebsrverrhandler', 'err401', ''), ('defaultwebsrverrhandler', 'err401', ''),
('defaultwebsrverrhandler', 'err403', ''), ('defaultwebsrverrhandler', 'err403', ''),
@@ -638,8 +636,6 @@ opcache.validate_timestamps'),
('system', 'available_shells', ''), ('system', 'available_shells', ''),
('system', 'le_froxlor_enabled', '0'), ('system', 'le_froxlor_enabled', '0'),
('system', 'le_froxlor_redirect', '0'), ('system', 'le_froxlor_redirect', '0'),
('system', 'le_renew_hook', 'systemctl restart postfix dovecot proftpd'),
('system', 'le_renew_services', ''),
('system', 'letsencryptacmeconf', '/etc/apache2/conf-enabled/acme.conf'), ('system', 'letsencryptacmeconf', '/etc/apache2/conf-enabled/acme.conf'),
('system', 'mail_use_smtp', '0'), ('system', 'mail_use_smtp', '0'),
('system', 'mail_smtp_host', 'localhost'), ('system', 'mail_smtp_host', 'localhost'),
@@ -730,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.2.0-rc2'), ('panel', 'version', '2.1.8'),
('panel', 'db_version', '202407200'); ('panel', 'db_version', '202312120');
DROP TABLE IF EXISTS `panel_tasks`; DROP TABLE IF EXISTS `panel_tasks`;
@@ -1049,15 +1045,4 @@ CREATE TABLE `panel_loginlinks` (
`allowed_from` text NOT NULL, `allowed_from` text NOT NULL,
UNIQUE KEY `loginname` (`loginname`) UNIQUE KEY `loginname` (`loginname`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
DROP TABLE IF EXISTS `panel_2fa_tokens`;
CREATE TABLE `panel_2fa_tokens` (
`id` int(11) NOT NULL auto_increment,
`selector` varchar(20) NOT NULL,
`token` varchar(200) NOT NULL,
`userid` int(11) NOT NULL default '0',
`valid_until` int(15) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;
FROXLORSQL; FROXLORSQL;

View File

@@ -99,6 +99,7 @@ if (Froxlor::isFroxlorVersion('0.10.38.3')) {
} }
Update::lastStepStatus(0); Update::lastStepStatus(0);
Update::showUpdateStep("Cleaning up old files");
$to_clean = array( $to_clean = array(
"install/lib", "install/lib",
"install/lng", "install/lng",
@@ -120,7 +121,30 @@ if (Froxlor::isFroxlorVersion('0.10.38.3')) {
"lng/swedish.lng.php", "lng/swedish.lng.php",
"scripts", "scripts",
); );
Update::cleanOldFiles($to_clean); $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>');
}
}
Update::showUpdateStep("Adding new settings"); Update::showUpdateStep("Adding new settings");
$panel_settings_mode = isset($_POST['panel_settings_mode']) ? (int)$_POST['panel_settings_mode'] : 0; $panel_settings_mode = isset($_POST['panel_settings_mode']) ? (int)$_POST['panel_settings_mode'] : 0;

View File

@@ -149,6 +149,7 @@ if (Froxlor::isFroxlorVersion('2.1.0-rc2')) {
} }
if (Froxlor::isDatabaseVersion('202311260')) { if (Froxlor::isDatabaseVersion('202311260')) {
Update::showUpdateStep("Cleaning up old files");
$to_clean = array( $to_clean = array(
"install/updates/froxlor/update_2.x.inc.php", "install/updates/froxlor/update_2.x.inc.php",
"install/updates/preconfig/preconfig_2.x.inc.php", "install/updates/preconfig/preconfig_2.x.inc.php",
@@ -174,8 +175,33 @@ if (Froxlor::isDatabaseVersion('202311260')) {
"templates/Froxlor/user/change_theme.html.twig", "templates/Froxlor/user/change_theme.html.twig",
"tests/Backup/CustomerBackupsTest.php" "tests/Backup/CustomerBackupsTest.php"
); );
Update::cleanOldFiles($to_clean); $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('202312050'); Froxlor::updateToDbVersion('202312050');
} }
@@ -190,6 +216,7 @@ if (Froxlor::isFroxlorVersion('2.1.0')) {
} }
if (Froxlor::isDatabaseVersion('202312050')) { if (Froxlor::isDatabaseVersion('202312050')) {
Update::showUpdateStep("Cleaning up old files");
$to_clean = array( $to_clean = array(
"lib/configfiles/centos7.xml", "lib/configfiles/centos7.xml",
"lib/configfiles/centos8.xml", "lib/configfiles/centos8.xml",
@@ -198,8 +225,33 @@ if (Froxlor::isDatabaseVersion('202312050')) {
"lib/configfiles/buster.xml", "lib/configfiles/buster.xml",
"lib/configfiles/bionic.xml", "lib/configfiles/bionic.xml",
); );
Update::cleanOldFiles($to_clean); $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'); Froxlor::updateToDbVersion('202312100');
} }
@@ -247,8 +299,3 @@ if (Froxlor::isFroxlorVersion('2.1.7')) {
Update::showUpdateStep("Updating from 2.1.7 to 2.1.8", false); Update::showUpdateStep("Updating from 2.1.7 to 2.1.8", false);
Froxlor::updateToVersion('2.1.8'); Froxlor::updateToVersion('2.1.8');
} }
if (Froxlor::isFroxlorVersion('2.1.8')) {
Update::showUpdateStep("Updating from 2.1.8 to 2.1.9", false);
Froxlor::updateToVersion('2.1.9');
}

View File

@@ -1,147 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can also view it online at
* https://files.froxlor.org/misc/COPYING.txt
*
* @copyright the authors
* @author Froxlor team <team@froxlor.org>
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
*/
use Froxlor\Database\Database;
use Froxlor\Froxlor;
use Froxlor\Install\Update;
use Froxlor\Settings;
if (!defined('_CRON_UPDATE')) {
if (!defined('AREA') || (defined('AREA') && AREA != 'admin') || !isset($userinfo['loginname']) || (isset($userinfo['loginname']) && $userinfo['loginname'] == '')) {
header('Location: ../../../../index.php');
exit();
}
}
if (Froxlor::isFroxlorVersion('2.1.9')) {
Update::showUpdateStep("Enhancing virtual email table");
Database::query("ALTER TABLE `" . TABLE_MAIL_VIRTUAL . "` ADD `spam_tag_level` float(4,1) NOT NULL DEFAULT 7.0;");
Database::query("ALTER TABLE `" . TABLE_MAIL_VIRTUAL . "` ADD `spam_kill_level` float(4,1) NOT NULL DEFAULT 14.0;");
Database::query("ALTER TABLE `" . TABLE_MAIL_VIRTUAL . "` ADD `bypass_spam` tinyint(1) NOT NULL default '0';");
Database::query("ALTER TABLE `" . TABLE_MAIL_VIRTUAL . "` ADD `policy_greylist` tinyint(1) NOT NULL default '1';");
Update::lastStepStatus(0);
Update::showUpdateStep("Adjusting settings");
$antispam_activated = $_POST['antispam_activated'] ?? 0;
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `settinggroup` = 'antispam', `varname` = 'activated', `value` = '" . (int)$antispam_activated . "' WHERE `settinggroup` = 'dkim' AND `varname` = 'use_dkim';");
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `settinggroup` = 'antispam', `varname` = 'reload_command', `value` = 'service rspamd restart' WHERE `settinggroup` = 'dkim' AND `varname` = 'dkimrestart_command';");
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `settinggroup` = 'antispam', `varname` = 'config_file', `value` = '/etc/rspamd/local.d/froxlor_settings.conf' WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_prefix';");
Database::query("UPDATE `" . TABLE_PANEL_SETTINGS . "` SET `settinggroup` = 'antispam' WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_keylength';");
Settings::AddNew("dmarc.use_dmarc", "0");
Settings::AddNew("dmarc.dmarc_entry", "v=DMARC1; p=none;");
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'privkeysuffix';");
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_domains';");
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_algorithm';");
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_notes';");
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_add_adsp';");
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_dkimkeys';");
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_servicetype';");
Database::query("DELETE FROM `" . TABLE_PANEL_SETTINGS . "` WHERE `settinggroup` = 'dkim' AND `varname` = 'dkim_add_adsppolicy';");
Update::lastStepStatus(0);
if ($antispam_activated) {
Update::showUpdateStep("Converting existing domainkeys");
$sel_stmt = Database::prepare("SELECT * FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `dkim` = '1' AND `dkim_pubkey` <> ''");
Database::pexecute($sel_stmt);
$upd_stmt = Database::prepare("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `dkim_pubkey` = :pkey WHERE `id` = :did");
while ($domain = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
$pubkey = trim(preg_replace(
'/-----BEGIN PUBLIC KEY-----(.+)-----END PUBLIC KEY-----/s',
'$1',
str_replace("\n", '', $domain['dkim_pubkey'])
));
Database::pexecute($upd_stmt, ['pkey' => $pubkey, 'did' => $domain['id']]);
}
Update::lastStepStatus(0);
Update::showUpdateStep("Configure antispam services");
$froxlorCliBin = Froxlor::getInstallDir() . '/bin/froxlor-cli';
$currentDistro = Settings::Get('system.distribution');
$manual_command = <<<EOC
{$froxlorCliBin} froxlor:config-services -a '{"http":"x","dns":"x","smtp":"x","mail":"x","antispam":"rspamd","ftp":"x","distro":"{$currentDistro}","system":[]}'
EOC;
Update::lastStepStatus(
1,
'manual action needed',
"Please run the following command manually as root:<br><pre>" . $manual_command . "</pre>"
);
} else {
Update::showUpdateStep("Removing existing domainkeys because antispam is disabled");
Database::query("UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `dkim` = '0', `dkim_id` = '0', `dkim_privkey` = '', `dkim_pubkey` = '' WHERE `dkim` = '1';");
Update::lastStepStatus(1, '!!!');
}
Update::showUpdateStep("Enhancing admin and user table");
Database::query("ALTER TABLE `" . TABLE_PANEL_ADMINS . "` ADD `gui_access` tinyint(1) NOT NULL default '1';");
Database::query("ALTER TABLE `" . TABLE_PANEL_CUSTOMERS . "` ADD `gui_access` tinyint(1) NOT NULL default '1';");
Update::lastStepStatus(0);
$to_clean = [
'actions/admin/settings/180.dkim.php',
'actions/admin/settings/185.spf.php',
];
Update::cleanOldFiles($to_clean);
Froxlor::updateToDbVersion('202312230');
Froxlor::updateToVersion('2.2.0-dev1');
}
if (Froxlor::isDatabaseVersion('202312230')) {
Update::showUpdateStep("Adding new settings");
Settings::AddNew("system.le_renew_services", "");
Settings::AddNew("system.le_renew_hook", "systemctl restart postfix dovecot proftpd");
Update::lastStepStatus(0);
Froxlor::updateToDbVersion('202401090');
}
if (Froxlor::isFroxlorVersion('2.2.0-dev1')) {
Update::showUpdateStep("Updating from 2.2.0-dev1 to 2.2.0-rc1", false);
Froxlor::updateToVersion('2.2.0-rc1');
}
if (Froxlor::isDatabaseVersion('202401090')) {
Update::showUpdateStep("Adding new table for 2fa tokens");
Database::query("DROP TABLE IF EXISTS `panel_2fa_tokens`;");
$sql = "CREATE TABLE `panel_2fa_tokens` (
`id` int(11) NOT NULL auto_increment,
`selector` varchar(20) NOT NULL,
`token` varchar(200) NOT NULL,
`userid` int(11) NOT NULL default '0',
`valid_until` int(15) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;";
Database::query($sql);
Update::lastStepStatus(0);
Froxlor::updateToDbVersion('202407200');
}
if (Froxlor::isFroxlorVersion('2.2.0-rc1')) {
Update::showUpdateStep("Updating from 2.2.0-rc1 to 2.2.0-rc2", false);
Froxlor::updateToVersion('2.2.0-rc2');
}

View File

@@ -55,7 +55,6 @@ if (Froxlor::isFroxlor()) {
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_0.10.inc.php')); include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_0.10.inc.php'));
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_2.0.inc.php')); include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_2.0.inc.php'));
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_2.1.inc.php')); include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_2.1.inc.php'));
include_once(FileDir::makeCorrectFile(dirname(__FILE__) . '/updates/froxlor/update_2.2.inc.php'));
// Check Froxlor - database integrity (only happens after all updates are done, so we know the db-layout is okay) // Check Froxlor - database integrity (only happens after all updates are done, so we know the db-layout is okay)
Update::showUpdateStep("Checking database integrity"); Update::showUpdateStep("Checking database integrity");

View File

@@ -193,8 +193,7 @@ class Ajax
UI::initTwig(); UI::initTwig();
try { try {
$force = Request::get('force', 0); $json_result = \Froxlor\Api\Commands\Froxlor::getLocal($this->userinfo)->checkUpdate();
$json_result = \Froxlor\Api\Commands\Froxlor::getLocal($this->userinfo, ['force' => $force])->checkUpdate();
$result = json_decode($json_result, true)['data']; $result = json_decode($json_result, true)['data'];
$result['full_version'] = Froxlor::getFullVersion(); $result['full_version'] = Froxlor::getFullVersion();
$result['dbversion'] = Froxlor::DBVERSION; $result['dbversion'] = Froxlor::DBVERSION;

View File

@@ -156,7 +156,7 @@ class GlobalSearch
], ],
'result_key' => 'domain_ace', 'result_key' => 'domain_ace',
'result_format' => [ 'result_format' => [
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'], 'title' => ['self', 'getFieldFromResult'],
'title_args' => 'domain_ace', 'title_args' => 'domain_ace',
'href' => 'admin_domains.php?page=domains&searchfield=d.domain_ace&searchtext=' 'href' => 'admin_domains.php?page=domains&searchfield=d.domain_ace&searchtext='
] ]
@@ -172,7 +172,7 @@ class GlobalSearch
'result_key' => 'ip', 'result_key' => 'ip',
'result_groupkey' => 'ip', 'result_groupkey' => 'ip',
'result_format' => [ 'result_format' => [
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'], 'title' => ['self', 'getFieldFromResult'],
'title_args' => 'ip', 'title_args' => 'ip',
'href' => 'admin_ipsandports.php?page=ipsandports&searchfield=ip&searchtext=' 'href' => 'admin_ipsandports.php?page=ipsandports&searchfield=ip&searchtext='
] ]
@@ -186,7 +186,7 @@ class GlobalSearch
], ],
'result_key' => 'id', 'result_key' => 'id',
'result_format' => [ 'result_format' => [
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'], 'title' => ['self', 'getFieldFromResult'],
'title_args' => 'name', 'title_args' => 'name',
'href' => 'admin_plans.php?page=overview&searchfield=id&searchtext=' 'href' => 'admin_plans.php?page=overview&searchfield=id&searchtext='
] ]
@@ -201,7 +201,7 @@ class GlobalSearch
], ],
'result_key' => 'id', 'result_key' => 'id',
'result_format' => [ 'result_format' => [
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'], 'title' => ['self', 'getFieldFromResult'],
'title_args' => 'description', 'title_args' => 'description',
'href' => 'admin_phpsettings.php?page=overview&searchfield=id&searchtext=' 'href' => 'admin_phpsettings.php?page=overview&searchfield=id&searchtext='
] ]
@@ -215,7 +215,7 @@ class GlobalSearch
], ],
'result_key' => 'id', 'result_key' => 'id',
'result_format' => [ 'result_format' => [
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'], 'title' => ['self', 'getFieldFromResult'],
'title_args' => 'description', 'title_args' => 'description',
'href' => 'admin_phpsettings.php?page=fpmdaemons&searchfield=id&searchtext=' 'href' => 'admin_phpsettings.php?page=fpmdaemons&searchfield=id&searchtext='
] ]
@@ -234,7 +234,7 @@ class GlobalSearch
], ],
'result_key' => 'loginname', 'result_key' => 'loginname',
'result_format' => [ 'result_format' => [
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'], 'title' => ['self', 'getFieldFromResult'],
'title_args' => 'name', 'title_args' => 'name',
'href' => 'admin_admins.php?page=admins&searchfield=loginname&searchtext=' 'href' => 'admin_admins.php?page=admins&searchfield=loginname&searchtext='
] ]
@@ -252,7 +252,7 @@ class GlobalSearch
], ],
'result_key' => 'domain_ace', 'result_key' => 'domain_ace',
'result_format' => [ 'result_format' => [
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'], 'title' => ['self', 'getFieldFromResult'],
'title_args' => 'domain_ace', 'title_args' => 'domain_ace',
'href' => 'customer_domains.php?page=domains&searchfield=d.domain_ace&searchtext=' 'href' => 'customer_domains.php?page=domains&searchfield=d.domain_ace&searchtext='
] ]
@@ -266,7 +266,7 @@ class GlobalSearch
], ],
'result_key' => 'email', 'result_key' => 'email',
'result_format' => [ 'result_format' => [
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'], 'title' => ['self', 'getFieldFromResult'],
'title_args' => 'email', 'title_args' => 'email',
'href' => 'customer_email.php?page=email_domain&domainid={domainid}&searchfield=m.email&searchtext=' 'href' => 'customer_email.php?page=email_domain&domainid={domainid}&searchfield=m.email&searchtext='
] ]
@@ -279,7 +279,7 @@ class GlobalSearch
], ],
'result_key' => 'domain', 'result_key' => 'domain',
'result_format' => [ 'result_format' => [
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'], 'title' => ['self', 'getFieldFromResult'],
'title_args' => 'domain', 'title_args' => 'domain',
'href' => 'customer_email.php?page=emails&searchfield=d.domain&searchtext=' 'href' => 'customer_email.php?page=emails&searchfield=d.domain&searchtext='
] ]
@@ -293,7 +293,7 @@ class GlobalSearch
], ],
'result_key' => 'databasename', 'result_key' => 'databasename',
'result_format' => [ 'result_format' => [
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'], 'title' => ['self', 'getFieldFromResult'],
'title_args' => 'databasename', 'title_args' => 'databasename',
'href' => 'customer_mysql.php?page=mysqls&searchfield=databasename&searchtext=' 'href' => 'customer_mysql.php?page=mysqls&searchfield=databasename&searchtext='
] ]
@@ -307,7 +307,7 @@ class GlobalSearch
], ],
'result_key' => 'username', 'result_key' => 'username',
'result_format' => [ 'result_format' => [
'title' => ['\\Froxlor\\Ajax\\GlobalSearch', 'getFieldFromResult'], 'title' => ['self', 'getFieldFromResult'],
'title_args' => 'username', 'title_args' => 'username',
'href' => 'customer_ftp.php?page=accounts&searchfield=username&searchtext=' 'href' => 'customer_ftp.php?page=accounts&searchfield=username&searchtext='
] ]

View File

@@ -140,18 +140,12 @@ class Admins extends ApiCommand implements ResourceEntity
* create a new admin user * create a new admin user
* *
* @param string $name * @param string $name
* required, name of the adminstrator
* @param string $email * @param string $email
* required, email address of the administrator
* @param string $new_loginname * @param string $new_loginname
* required, loginname/username of the administrator
* @param string $admin_password * @param string $admin_password
* optional, default auto-generated * optional, default auto-generated
* @param string $def_language * @param string $def_language
* * optional, ISO 639-1 language code (e.g. 'en', 'de', see lng-folder for supported languages), * optional, default is system-default language
* * default is system-default language
* @param bool $gui_access
* optional, allow login via webui, if false ONLY the login via webui is disallowed; default true
* @param bool $api_allowed * @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false * optional, default is true if system setting api.enabled is true, else false
* @param string $custom_notes * @param string $custom_notes
@@ -225,7 +219,6 @@ class Admins extends ApiCommand implements ResourceEntity
// parameters // parameters
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage')); $def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
$gui_access = $this->getBoolParam('gui_access', true, true);
$api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled')); $api_allowed = $this->getBoolParam('api_allowed', true, Settings::Get('api.enabled'));
$custom_notes = $this->getParam('custom_notes', true, ''); $custom_notes = $this->getParam('custom_notes', true, '');
$custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0); $custom_notes_show = $this->getBoolParam('custom_notes_show', true, 0);
@@ -323,7 +316,6 @@ class Admins extends ApiCommand implements ResourceEntity
'name' => $name, 'name' => $name,
'email' => $email, 'email' => $email,
'lang' => $def_language, 'lang' => $def_language,
'gui_access' => $gui_access,
'api_allowed' => $api_allowed, 'api_allowed' => $api_allowed,
'change_serversettings' => $change_serversettings, 'change_serversettings' => $change_serversettings,
'customers' => $customers, 'customers' => $customers,
@@ -352,7 +344,6 @@ class Admins extends ApiCommand implements ResourceEntity
`name` = :name, `name` = :name,
`email` = :email, `email` = :email,
`def_language` = :lang, `def_language` = :lang,
`gui_access` = :gui_access,
`api_allowed` = :api_allowed, `api_allowed` = :api_allowed,
`change_serversettings` = :change_serversettings, `change_serversettings` = :change_serversettings,
`customers` = :customers, `customers` = :customers,
@@ -439,10 +430,7 @@ class Admins extends ApiCommand implements ResourceEntity
* @param string $admin_password * @param string $admin_password
* optional, default auto-generated * optional, default auto-generated
* @param string $def_language * @param string $def_language
* * optional, ISO 639-1 language code (e.g. 'en', 'de', see lng-folder for supported languages), * optional, default is system-default language
* * default is system-default language
* @param bool $gui_access
* * optional, allow login via webui, if false ONLY the login via webui is disallowed; default true
* @param bool $api_allowed * @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false * optional, default is true if system setting api.enabled is true, else false
* @param string $custom_notes * @param string $custom_notes
@@ -536,7 +524,6 @@ class Admins extends ApiCommand implements ResourceEntity
// you cannot edit some of the details of yourself // you cannot edit some of the details of yourself
if ($result['adminid'] == $this->getUserDetail('adminid')) { if ($result['adminid'] == $this->getUserDetail('adminid')) {
$gui_access = $result['gui_access'];
$api_allowed = $result['api_allowed']; $api_allowed = $result['api_allowed'];
$deactivated = $result['deactivated']; $deactivated = $result['deactivated'];
$customers = $result['customers']; $customers = $result['customers'];
@@ -555,7 +542,6 @@ class Admins extends ApiCommand implements ResourceEntity
$traffic = $result['traffic']; $traffic = $result['traffic'];
$ipaddress = ($result['ip'] != -1 ? json_decode($result['ip'], true) : -1); $ipaddress = ($result['ip'] != -1 ? json_decode($result['ip'], true) : -1);
} else { } else {
$gui_access = $this->getBoolParam('gui_access', true, $result['gui_access']);
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']); $api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
$deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']); $deactivated = $this->getBoolParam('deactivated', true, $result['deactivated']);
@@ -679,7 +665,6 @@ class Admins extends ApiCommand implements ResourceEntity
'name' => $name, 'name' => $name,
'email' => $email, 'email' => $email,
'lang' => $def_language, 'lang' => $def_language,
'gui_access' => $gui_access,
'api_allowed' => $api_allowed, 'api_allowed' => $api_allowed,
'change_serversettings' => $change_serversettings, 'change_serversettings' => $change_serversettings,
'customers' => $customers, 'customers' => $customers,
@@ -709,7 +694,6 @@ class Admins extends ApiCommand implements ResourceEntity
`name` = :name, `name` = :name,
`email` = :email, `email` = :email,
`def_language` = :lang, `def_language` = :lang,
`gui_access` = :gui_access,
`api_allowed` = :api_allowed, `api_allowed` = :api_allowed,
`change_serversettings` = :change_serversettings, `change_serversettings` = :change_serversettings,
`customers` = :customers, `customers` = :customers,

View File

@@ -171,7 +171,6 @@ class Customers extends ApiCommand implements ResourceEntity
* create a new customer with default ftp-user and standard-subdomain (if wanted) * create a new customer with default ftp-user and standard-subdomain (if wanted)
* *
* @param string $email * @param string $email
* required, email address of new customer
* @param string $name * @param string $name
* optional if company is set, else required * optional if company is set, else required
* @param string $firstname * @param string $firstname
@@ -190,11 +189,8 @@ class Customers extends ApiCommand implements ResourceEntity
* optional * optional
* @param int $customernumber * @param int $customernumber
* optional * optional
* @param string $def_language * @param string $def_language ,
* optional, ISO 639-1 language code (e.g. 'en', 'de', see lng-folder for supported languages), * optional, default is system-default language
* default is system-default language
* @param bool $gui_access
* optional, allow login via webui, if false ONLY the login via webui is disallowed; default true
* @param bool $api_allowed * @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false * optional, default is true if system setting api.enabled is true, else false
* @param int $gender * @param int $gender
@@ -275,7 +271,7 @@ class Customers extends ApiCommand implements ResourceEntity
* optional, specify a hosting-plan to set certain resource-values from the plan * optional, specify a hosting-plan to set certain resource-values from the plan
* instead of specifying them * instead of specifying them
* @param array $allowed_mysqlserver * @param array $allowed_mysqlserver
* optional, array of IDs of defined mysql-servers the customer is allowed to use, * optional, array of IDs of defined mysql-servers the customer is allowed to use,
* default is to allow the default dbserver (id=0) * default is to allow the default dbserver (id=0)
* *
* @access admin * @access admin
@@ -301,7 +297,6 @@ class Customers extends ApiCommand implements ResourceEntity
$fax = $this->getParam('fax', true, ''); $fax = $this->getParam('fax', true, '');
$customernumber = $this->getParam('customernumber', true, ''); $customernumber = $this->getParam('customernumber', true, '');
$def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage')); $def_language = $this->getParam('def_language', true, Settings::Get('panel.standardlanguage'));
$gui_access = $this->getBoolParam('gui_access', true, 1);
$api_allowed = $this->getBoolParam('api_allowed', true, (Settings::Get('api.enabled') && Settings::Get('api.customer_default'))); $api_allowed = $this->getBoolParam('api_allowed', true, (Settings::Get('api.enabled') && Settings::Get('api.customer_default')));
$gender = (int)$this->getParam('gender', true, 0); $gender = (int)$this->getParam('gender', true, 0);
$custom_notes = $this->getParam('custom_notes', true, ''); $custom_notes = $this->getParam('custom_notes', true, '');
@@ -412,7 +407,7 @@ class Customers extends ApiCommand implements ResourceEntity
} }
$allowed_mysqlserver = array(); $allowed_mysqlserver = array();
if (!empty($p_allowed_mysqlserver) && is_array($p_allowed_mysqlserver)) { if (! empty($p_allowed_mysqlserver) && is_array($p_allowed_mysqlserver)) {
foreach ($p_allowed_mysqlserver as $allowed_ms) { foreach ($p_allowed_mysqlserver as $allowed_ms) {
$allowed_ms = intval($allowed_ms); $allowed_ms = intval($allowed_ms);
$allowed_mysqlserver[] = $allowed_ms; $allowed_mysqlserver[] = $allowed_ms;
@@ -460,28 +455,6 @@ class Customers extends ApiCommand implements ResourceEntity
if (function_exists('posix_getpwnam') && !in_array("posix_getpwnam", explode(",", ini_get('disable_functions'))) && posix_getpwnam($loginname)) { if (function_exists('posix_getpwnam') && !in_array("posix_getpwnam", explode(",", ini_get('disable_functions'))) && posix_getpwnam($loginname)) {
Response::standardError('loginnameissystemaccount', $loginname, true); Response::standardError('loginnameissystemaccount', $loginname, true);
} }
// blacklist some system-internal names that might lead to issues
Database::needSqlData();
$sqldata = Database::getSqlData();
Database::needRoot(true);
Database::needSqlData();
$sqlrdata = Database::getSqlData();
$login_blacklist = [
'root',
'admin',
'froxroot',
'froxlor',
$sqldata['user'],
$sqldata['db'],
$sqlrdata['user'],
];
unset($sqldata);
unset($sqlrdata);
$login_blacklist = array_unique($login_blacklist);
if (in_array($loginname, $login_blacklist)) {
Response::standardError('loginnameisreservedname', $loginname, true);
}
} else { } else {
$accountnumber = intval(Settings::Get('system.lastaccountnumber')) + 1; $accountnumber = intval(Settings::Get('system.lastaccountnumber')) + 1;
$loginname = Settings::Get('customer.accountprefix') . $accountnumber; $loginname = Settings::Get('customer.accountprefix') . $accountnumber;
@@ -545,7 +518,6 @@ class Customers extends ApiCommand implements ResourceEntity
'email' => $email, 'email' => $email,
'customerno' => $customernumber, 'customerno' => $customernumber,
'lang' => $def_language, 'lang' => $def_language,
'gui_access' => $gui_access,
'api_allowed' => $api_allowed, 'api_allowed' => $api_allowed,
'docroot' => $documentroot, 'docroot' => $documentroot,
'guid' => $guid, 'guid' => $guid,
@@ -588,7 +560,6 @@ class Customers extends ApiCommand implements ResourceEntity
`email` = :email, `email` = :email,
`customernumber` = :customerno, `customernumber` = :customerno,
`def_language` = :lang, `def_language` = :lang,
`gui_access` = :gui_access,
`api_allowed` = :api_allowed, `api_allowed` = :api_allowed,
`documentroot` = :docroot, `documentroot` = :docroot,
`guid` = :guid, `guid` = :guid,
@@ -761,22 +732,6 @@ class Customers extends ApiCommand implements ResourceEntity
} }
} }
// Create default mysql-user if enabled
if ($mysqls != 0) {
foreach ($allowed_mysqlserver as $dbserver) {
// require privileged access for target db-server
Database::needRoot(true, $dbserver, false);
// get DbManager
$dbm = new DbManager($this->logger());
// give permission to the user on every access-host we have
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
$dbm->getManager()->grantPrivilegesTo($loginname, $password, $mysql_access_host, false, false, true);
}
$dbm->getManager()->flushPrivileges();
Database::needRoot(false);
}
}
if ($sendpassword == '1') { if ($sendpassword == '1') {
$srv_hostname = Settings::Get('system.hostname'); $srv_hostname = Settings::Get('system.hostname');
if (Settings::Get('system.froxlordirectlyviahostname') == '0') { if (Settings::Get('system.froxlordirectlyviahostname') == '0') {
@@ -976,7 +931,6 @@ class Customers extends ApiCommand implements ResourceEntity
* @param string $loginname * @param string $loginname
* optional, the loginname * optional, the loginname
* @param string $email * @param string $email
* optional
* @param string $name * @param string $name
* optional if company is set, else required * optional if company is set, else required
* @param string $firstname * @param string $firstname
@@ -995,11 +949,8 @@ class Customers extends ApiCommand implements ResourceEntity
* optional * optional
* @param int $customernumber * @param int $customernumber
* optional * optional
* @param string $def_language * @param string $def_language ,
* * optional, ISO 639-1 language code (e.g. 'en', 'de', see lng-folder for supported languages), * optional, default is system-default language
* * default is system-default language
* @param bool $gui_access
* optional, allow login via webui, if false ONLY the login via webui is disallowed; default true
* @param bool $api_allowed * @param bool $api_allowed
* optional, default is true if system setting api.enabled is true, else false * optional, default is true if system setting api.enabled is true, else false
* @param int $gender * @param int $gender
@@ -1010,7 +961,7 @@ class Customers extends ApiCommand implements ResourceEntity
* optional, whether to show the content of custom_notes to the customer, default 0 * optional, whether to show the content of custom_notes to the customer, default 0
* (false) * (false)
* @param string $new_customer_password * @param string $new_customer_password
* optional, set new password * optional, iset new password
* @param bool $sendpassword * @param bool $sendpassword
* optional, whether to send the password to the customer after creation, default 0 * optional, whether to send the password to the customer after creation, default 0
* (false) * (false)
@@ -1078,7 +1029,7 @@ class Customers extends ApiCommand implements ResourceEntity
* @param string $theme * @param string $theme
* optional, change theme * optional, change theme
* @param array $allowed_mysqlserver * @param array $allowed_mysqlserver
* optional, array of IDs of defined mysql-servers the customer is allowed to use, * optional, array of IDs of defined mysql-servers the customer is allowed to use,
* default is to allow the default dbserver (id=0) * default is to allow the default dbserver (id=0)
* *
* @access admin, customer * @access admin, customer
@@ -1114,7 +1065,6 @@ class Customers extends ApiCommand implements ResourceEntity
$fax = $this->getParam('fax', true, $result['fax']); $fax = $this->getParam('fax', true, $result['fax']);
$customernumber = $this->getParam('customernumber', true, $result['customernumber']); $customernumber = $this->getParam('customernumber', true, $result['customernumber']);
$def_language = $this->getParam('def_language', true, $result['def_language']); $def_language = $this->getParam('def_language', true, $result['def_language']);
$gui_access = $this->getBoolParam('gui_access', true, $result['gui_access']);
$api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']); $api_allowed = $this->getBoolParam('api_allowed', true, $result['api_allowed']);
$gender = (int)$this->getParam('gender', true, $result['gender']); $gender = (int)$this->getParam('gender', true, $result['gender']);
$custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']); $custom_notes = $this->getParam('custom_notes', true, $result['custom_notes']);
@@ -1177,7 +1127,7 @@ class Customers extends ApiCommand implements ResourceEntity
if ($result['mysqls'] == 0 && ($mysqls == -1 || $mysqls > 0)) { if ($result['mysqls'] == 0 && ($mysqls == -1 || $mysqls > 0)) {
$allowed_mysqlserver = $this->getParam('allowed_mysqlserver', true, [0]); $allowed_mysqlserver = $this->getParam('allowed_mysqlserver', true, [0]);
} }
if (!empty($allowed_mysqlserver)) { if (! empty($allowed_mysqlserver)) {
$allowed_mysqlserver = array_map('intval', $allowed_mysqlserver); $allowed_mysqlserver = array_map('intval', $allowed_mysqlserver);
} }
@@ -1335,34 +1285,12 @@ class Customers extends ApiCommand implements ResourceEntity
]); ]);
$upd_stmt = Database::prepare(" $upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `deactivated`= :deactivated WHERE `customerid` = :customerid UPDATE `" . TABLE_PANEL_DOMAINS . "` SET `deactivated`= :deactivated WHERE `customerid` = :customerid");
");
Database::pexecute($upd_stmt, [ Database::pexecute($upd_stmt, [
'deactivated' => $deactivated, 'deactivated' => $deactivated,
'customerid' => $id 'customerid' => $id
]); ]);
// enable/disable global mysql-user (loginname)
$current_allowed_mysqlserver = isset($result['allowed_mysqlserver']) && !empty($result['allowed_mysqlserver']) ? json_decode($result['allowed_mysqlserver'], true) : [];
foreach ($current_allowed_mysqlserver as $dbserver) {
// require privileged access for target db-server
Database::needRoot(true, $dbserver, false);
// get DbManager
$dbm = new DbManager($this->logger());
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
// Prevent access, if deactivated
if ($deactivated) {
// failsafe if user has been deleted manually (requires MySQL 4.1.2+)
$dbm->getManager()->disableUser($result['loginname'], $mysql_access_host);
} else {
// Otherwise grant access
$dbm->getManager()->enableUser($result['loginname'], $mysql_access_host, true);
}
}
$dbm->getManager()->flushPrivileges();
Database::needRoot(false);
}
// Retrieve customer's databases // Retrieve customer's databases
$databases_stmt = Database::prepare("SELECT * FROM " . TABLE_PANEL_DATABASES . " WHERE customerid = :customerid ORDER BY `dbserver`"); $databases_stmt = Database::prepare("SELECT * FROM " . TABLE_PANEL_DATABASES . " WHERE customerid = :customerid ORDER BY `dbserver`");
Database::pexecute($databases_stmt, [ Database::pexecute($databases_stmt, [
@@ -1383,7 +1311,9 @@ class Customers extends ApiCommand implements ResourceEntity
$last_dbserver = $row_database['dbserver']; $last_dbserver = $row_database['dbserver'];
} }
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) { foreach (array_unique(explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
$mysql_access_host = trim($mysql_access_host);
// Prevent access, if deactivated // Prevent access, if deactivated
if ($deactivated) { if ($deactivated) {
// failsafe if user has been deleted manually (requires MySQL 4.1.2+) // failsafe if user has been deleted manually (requires MySQL 4.1.2+)
@@ -1472,7 +1402,6 @@ class Customers extends ApiCommand implements ResourceEntity
'logviewenabled' => $logviewenabled, 'logviewenabled' => $logviewenabled,
'custom_notes' => $custom_notes, 'custom_notes' => $custom_notes,
'custom_notes_show' => $custom_notes_show, 'custom_notes_show' => $custom_notes_show,
'gui_access' => $gui_access,
'api_allowed' => $api_allowed, 'api_allowed' => $api_allowed,
'allowed_mysqlserver' => empty($allowed_mysqlserver) ? "" : json_encode($allowed_mysqlserver) 'allowed_mysqlserver' => empty($allowed_mysqlserver) ? "" : json_encode($allowed_mysqlserver)
]; ];
@@ -1516,7 +1445,6 @@ class Customers extends ApiCommand implements ResourceEntity
`logviewenabled` = :logviewenabled, `logviewenabled` = :logviewenabled,
`custom_notes` = :custom_notes, `custom_notes` = :custom_notes,
`custom_notes_show` = :custom_notes_show, `custom_notes_show` = :custom_notes_show,
`gui_access` = :gui_access,
`api_allowed` = :api_allowed, `api_allowed` = :api_allowed,
`allowed_mysqlserver` = :allowed_mysqlserver"; `allowed_mysqlserver` = :allowed_mysqlserver";
$upd_query .= $admin_upd_query; $upd_query .= $admin_upd_query;
@@ -1674,21 +1602,6 @@ class Customers extends ApiCommand implements ResourceEntity
]); ]);
$id = $result['customerid']; $id = $result['customerid'];
// remove global mysql-user (loginname)
$current_allowed_mysqlserver = isset($result['allowed_mysqlserver']) && !empty($result['allowed_mysqlserver']) ? json_decode($result['allowed_mysqlserver'], true) : [];
foreach ($current_allowed_mysqlserver as $dbserver) {
// require privileged access for target db-server
Database::needRoot(true, $dbserver, false);
// get DbManager
$dbm = new DbManager($this->logger());
foreach (array_map('trim', explode(',', Settings::Get('system.mysql_access_host'))) as $mysql_access_host) {
$dbm->getManager()->deleteUser($result['loginname'], $mysql_access_host);
}
$dbm->getManager()->flushPrivileges();
Database::needRoot(false);
}
// remove all databases
$databases_stmt = Database::prepare(" $databases_stmt = Database::prepare("
SELECT * FROM `" . TABLE_PANEL_DATABASES . "` SELECT * FROM `" . TABLE_PANEL_DATABASES . "`
WHERE `customerid` = :id ORDER BY `dbserver` WHERE `customerid` = :id ORDER BY `dbserver`
@@ -1704,8 +1617,8 @@ class Customers extends ApiCommand implements ResourceEntity
$priv_changed = false; $priv_changed = false;
while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) { while ($row_database = $databases_stmt->fetch(PDO::FETCH_ASSOC)) {
if ($last_dbserver != $row_database['dbserver']) { if ($last_dbserver != $row_database['dbserver']) {
$dbm->getManager()->flushPrivileges();
Database::needRoot(true, $row_database['dbserver']); Database::needRoot(true, $row_database['dbserver']);
$dbm->getManager()->flushPrivileges();
$last_dbserver = $row_database['dbserver']; $last_dbserver = $row_database['dbserver'];
} }
$dbm->getManager()->deleteDatabase($row_database['databasename']); $dbm->getManager()->deleteDatabase($row_database['databasename']);

View File

@@ -115,7 +115,7 @@ class DomainZones extends ApiCommand implements ResourceEntity
// validation // validation
$errors = []; $errors = [];
if (empty(trim($record))) { if (empty($record)) {
$record = "@"; $record = "@";
} }

View File

@@ -831,9 +831,6 @@ class Domains extends ApiCommand implements ResourceEntity
Cronjob::inserttask(TaskId::REBUILD_VHOST); Cronjob::inserttask(TaskId::REBUILD_VHOST);
// Using nameserver, insert a task which rebuilds the server config // Using nameserver, insert a task which rebuilds the server config
Cronjob::inserttask(TaskId::REBUILD_DNS); Cronjob::inserttask(TaskId::REBUILD_DNS);
if ($dkim == '1') {
Cronjob::inserttask(TaskId::REBUILD_RSPAMD);
}
$this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added domain '" . $domain . "'"); $this->logger()->logAction(FroxlorLogger::ADM_ACTION, LOG_WARNING, "[API] added domain '" . $domain . "'");
@@ -1411,7 +1408,7 @@ class Domains extends ApiCommand implements ResourceEntity
$zonefile = $result['zonefile']; $zonefile = $result['zonefile'];
} }
if (Settings::Get('antispam.activated') != '1') { if (Settings::Get('dkim.use_dkim') != '1') {
$dkim = $result['dkim']; $dkim = $result['dkim'];
} }
@@ -1678,10 +1675,6 @@ class Domains extends ApiCommand implements ResourceEntity
Cronjob::inserttask(TaskId::REBUILD_VHOST); Cronjob::inserttask(TaskId::REBUILD_VHOST);
} }
if ($dkim != $result['dkim']) {
Cronjob::inserttask(TaskId::REBUILD_RSPAMD);
}
if ($speciallogfile != $result['speciallogfile'] && $speciallogverified != '1') { if ($speciallogfile != $result['speciallogfile'] && $speciallogverified != '1') {
$speciallogfile = $result['speciallogfile']; $speciallogfile = $result['speciallogfile'];
} }
@@ -2105,8 +2098,6 @@ class Domains extends ApiCommand implements ResourceEntity
* @param bool $is_stdsubdomain * @param bool $is_stdsubdomain
* optional, default false, specify whether it's a std-subdomain you are deleting as it does not count * optional, default false, specify whether it's a std-subdomain you are deleting as it does not count
* as subdomain-resource * as subdomain-resource
* @param bool $delete_userfiles
* optional, delete email account files on filesystem (if any), default false
* *
* @access admin * @access admin
* @return string json-encoded array * @return string json-encoded array
@@ -2118,8 +2109,7 @@ class Domains extends ApiCommand implements ResourceEntity
$id = $this->getParam('id', true, 0); $id = $this->getParam('id', true, 0);
$dn_optional = $id > 0; $dn_optional = $id > 0;
$domainname = $this->getParam('domainname', $dn_optional, ''); $domainname = $this->getParam('domainname', $dn_optional, '');
$is_stdsubdomain = $this->getBoolParam('is_stdsubdomain', true, 0); $is_stdsubdomain = $this->getParam('is_stdsubdomain', true, 0);
$delete_user_emailfiles = $this->getBoolParam('delete_userfiles', true, 0);
$result = $this->apiCall('Domains.get', [ $result = $this->apiCall('Domains.get', [
'id' => $id, 'id' => $id,
@@ -2143,14 +2133,6 @@ class Domains extends ApiCommand implements ResourceEntity
$idString = implode(' OR ', $idString); $idString = implode(' OR ', $idString);
if ($idString != '') { if ($idString != '') {
if ($delete_user_emailfiles) {
// determine all connected email-accounts
$emailaccount_sel = Database::prepare("SELECT `email`, `homedir`, `maildir` FROM `" . TABLE_MAIL_USERS . "` WHERE " . $idString);
Database::pexecute($emailaccount_sel, $paramString, true, true);
while ($emailacc_row = $emailaccount_sel->fetch(PDO::FETCH_ASSOC)) {
Cronjob::inserttask(TaskId::DELETE_EMAIL_DATA, $emailacc_row['email'], FileDir::makeCorrectDir($emailacc_row['homedir'] . '/' . $emailacc_row['maildir']));
}
}
$del_stmt = Database::prepare(" $del_stmt = Database::prepare("
DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE " . $idString); DELETE FROM `" . TABLE_MAIL_USERS . "` WHERE " . $idString);
Database::pexecute($del_stmt, $paramString, true, true); Database::pexecute($del_stmt, $paramString, true, true);

View File

@@ -523,7 +523,7 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
$result = $this->apiCall('Emails.get', [ $result = $this->apiCall('Emails.get', [
'id' => $id, 'id' => $id,
'emailaddr' => $emailaddr 'emailaddr' => $emailaddr
], true); ]);
$id = $result['id']; $id = $result['id'];
if (empty($result['popaccountid']) || $result['popaccountid'] == 0) { if (empty($result['popaccountid']) || $result['popaccountid'] == 0) {
@@ -563,7 +563,7 @@ class EmailAccounts extends ApiCommand implements ResourceEntity
} }
if ($delete_userfiles) { if ($delete_userfiles) {
Cronjob::inserttask(TaskId::DELETE_EMAIL_DATA, $customer['loginname'], FileDir::makeCorrectDir($result['homedir'] . '/' . $result['maildir'])); Cronjob::inserttask(TaskId::DELETE_EMAIL_DATA, $customer['loginname'], $result['email_full']);
} }
// decrease usage for customer // decrease usage for customer

View File

@@ -28,12 +28,10 @@ namespace Froxlor\Api\Commands;
use Exception; use Exception;
use Froxlor\Api\ApiCommand; use Froxlor\Api\ApiCommand;
use Froxlor\Api\ResourceEntity; use Froxlor\Api\ResourceEntity;
use Froxlor\Cron\TaskId;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\FroxlorLogger; use Froxlor\FroxlorLogger;
use Froxlor\Idna\IdnaWrapper; use Froxlor\Idna\IdnaWrapper;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\System\Cronjob;
use Froxlor\UI\Response; use Froxlor\UI\Response;
use Froxlor\Validate\Validate; use Froxlor\Validate\Validate;
use PDO; use PDO;
@@ -51,14 +49,6 @@ class Emails extends ApiCommand implements ResourceEntity
* name of the address before @ * name of the address before @
* @param string $domain * @param string $domain
* domain-name for the email-address * domain-name for the email-address
* @param float $spam_tag_level
* optional, score which is required to tag emails as spam, default: 7.0
* @param float $spam_kill_level
* optional, score which is required to discard emails, default: 14.0
* @param boolean $bypass_spam
* optional, disable spam-filter entirely, default: no
* @param boolean $policy_greylist
* optional, enable grey-listing, default: yes
* @param boolean $iscatchall * @param boolean $iscatchall
* optional, make this address a catchall address, default: no * optional, make this address a catchall address, default: no
* @param int $customerid * @param int $customerid
@@ -84,10 +74,6 @@ class Emails extends ApiCommand implements ResourceEntity
$domain = $this->getParam('domain'); $domain = $this->getParam('domain');
// parameters // parameters
$spam_tag_level = $this->getParam('spam_tag_level', true, '7.0');
$spam_kill_level = $this->getParam('spam_kill_level', true, '14.0');
$bypass_spam = $this->getBoolParam('bypass_spam', true, 0);
$policy_greylist = $this->getBoolParam('policy_greylist', true, 1);
$iscatchall = $this->getBoolParam('iscatchall', true, 0); $iscatchall = $this->getBoolParam('iscatchall', true, 0);
$description = $this->getParam('description', true, ''); $description = $this->getParam('description', true, '');
@@ -154,19 +140,11 @@ class Emails extends ApiCommand implements ResourceEntity
} }
} }
$spam_tag_level = Validate::validate($spam_tag_level, 'spam_tag_level', '/^\d{1,}(\.\d{1,2})?$/', '', [7.0], true);
$spam_kill_level = Validate::validate($spam_kill_level, 'spam_kill_level', '/^\d{1,}(\.\d{1,2})?$/', '', [14.0], true);
$description = Validate::validate(trim($description), 'description', Validate::REGEX_DESC_TEXT, '', [], true);
$stmt = Database::prepare(" $stmt = Database::prepare("
INSERT INTO `" . TABLE_MAIL_VIRTUAL . "` SET INSERT INTO `" . TABLE_MAIL_VIRTUAL . "` SET
`customerid` = :cid, `customerid` = :cid,
`email` = :email, `email` = :email,
`email_full` = :email_full, `email_full` = :email_full,
`spam_tag_level` = :spam_tag_level,
`spam_kill_level` = :spam_kill_level,
`bypass_spam` = :bypass_spam,
`policy_greylist` = :policy_greylist,
`iscatchall` = :iscatchall, `iscatchall` = :iscatchall,
`domainid` = :domainid, `domainid` = :domainid,
`description` = :description `description` = :description
@@ -175,10 +153,6 @@ class Emails extends ApiCommand implements ResourceEntity
"cid" => $customer['customerid'], "cid" => $customer['customerid'],
"email" => $email, "email" => $email,
"email_full" => $email_full, "email_full" => $email_full,
"spam_tag_level" => $spam_tag_level,
"spam_kill_level" => $spam_kill_level,
"bypass_spam" => $bypass_spam,
"policy_greylist" => $policy_greylist,
"iscatchall" => $iscatchall, "iscatchall" => $iscatchall,
"domainid" => $domain_check['id'], "domainid" => $domain_check['id'],
"description" => $description "description" => $description
@@ -188,7 +162,6 @@ class Emails extends ApiCommand implements ResourceEntity
// update customer usage // update customer usage
Customers::increaseUsage($customer['customerid'], 'emails_used'); Customers::increaseUsage($customer['customerid'], 'emails_used');
Cronjob::inserttask(TaskId::REBUILD_RSPAMD);
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added email address '" . $email_full . "'"); $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] added email address '" . $email_full . "'");
$result = $this->apiCall('Emails.get', [ $result = $this->apiCall('Emails.get', [
@@ -221,12 +194,12 @@ class Emails extends ApiCommand implements ResourceEntity
$customer_ids = $this->getAllowedCustomerIds('email'); $customer_ids = $this->getAllowedCustomerIds('email');
$params['idea'] = ($id <= 0 ? $emailaddr : $id); $params['idea'] = ($id <= 0 ? $emailaddr : $id);
$result_stmt = Database::prepare("SELECT v.*, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize` " . ($this->isInternal() ? ", `u`.`homedir`, `u`.`maildir`" : "") . " $result_stmt = Database::prepare("SELECT v.`id`, v.`email`, v.`email_full`, v.`iscatchall`, v.`destination`, v.`customerid`, v.`popaccountid`, v.`domainid`, v.`description`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`
FROM `" . TABLE_MAIL_VIRTUAL . "` v FROM `" . TABLE_MAIL_VIRTUAL . "` v
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id` LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id`
WHERE v.`customerid` IN (" . implode(", ", $customer_ids) . ") WHERE v.`customerid` IN (" . implode(", ", $customer_ids) . ")
AND " . (is_numeric($params['idea']) ? "v.`id`= :idea" : "(v.`email` = :idea OR v.`email_full` = :idea)" AND " . (is_numeric($params['idea']) ? "v.`id`= :idea" : "(v.`email` = :idea OR v.`email_full` = :idea)")
)); );
$result = Database::pexecute_first($result_stmt, $params, true, true); $result = Database::pexecute_first($result_stmt, $params, true, true);
if ($result) { if ($result) {
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get email address '" . $result['email_full'] . "'"); $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] get email address '" . $result['email_full'] . "'");
@@ -247,14 +220,6 @@ class Emails extends ApiCommand implements ResourceEntity
* optional, required when called as admin (if $loginname is not specified) * optional, required when called as admin (if $loginname is not specified)
* @param string $loginname * @param string $loginname
* optional, required when called as admin (if $customerid is not specified) * optional, required when called as admin (if $customerid is not specified)
* @param float $spam_tag_level
* optional, score which is required to tag emails as spam, default: 7.0
* @param float $spam_kill_level
* optional, score which is required to discard emails, default: 14.0
* @param boolean $bypass_spam
* optional, disable spam-filter entirely, default: no
* @param boolean $policy_greylist
* optional, enable grey-listing, default: yes
* @param boolean $iscatchall * @param boolean $iscatchall
* optional * optional
* @param string $description * @param string $description
@@ -270,6 +235,15 @@ class Emails extends ApiCommand implements ResourceEntity
throw new Exception("You cannot access this resource", 405); throw new Exception("You cannot access this resource", 405);
} }
// if enabling catchall is not allowed by settings, we do not need
// to run update()
if (Settings::Get('catchall.catchall_enabled') != '1') {
Response::standardError([
'operationnotpermitted',
'featureisdisabled'
], 'catchall', true);
}
$id = $this->getParam('id', true, 0); $id = $this->getParam('id', true, 0);
$ea_optional = $id > 0; $ea_optional = $id > 0;
$emailaddr = $this->getParam('emailaddr', $ea_optional, ''); $emailaddr = $this->getParam('emailaddr', $ea_optional, '');
@@ -281,78 +255,48 @@ class Emails extends ApiCommand implements ResourceEntity
$id = $result['id']; $id = $result['id'];
// parameters // parameters
$spam_tag_level = $this->getParam('spam_tag_level', true, $result['spam_tag_level']);
$spam_kill_level = $this->getParam('spam_kill_level', true, $result['spam_kill_level']);
$bypass_spam = $this->getBoolParam('bypass_spam', true, $result['bypass_spam']);
$policy_greylist = $this->getBoolParam('policy_greylist', true, $result['policy_greylist']);
$iscatchall = $this->getBoolParam('iscatchall', true, $result['iscatchall']); $iscatchall = $this->getBoolParam('iscatchall', true, $result['iscatchall']);
$description = $this->getParam('description', true, $result['description']); $description = $this->getParam('description', true, $result['description']);
// if enabling catchall is not allowed by settings, we do not need
// to run update()
if ($iscatchall && $result['iscatchall'] == 0 && Settings::Get('catchall.catchall_enabled') != '1') {
Response::standardError([
'operationnotpermitted',
'featureisdisabled'
], 'catchall', true);
}
// get needed customer info to reduce the email-address-counter by one // get needed customer info to reduce the email-address-counter by one
$customer = $this->getCustomerData(); $customer = $this->getCustomerData();
// check for catchall-flag // check for catchall-flag
$email = $result['email_full'];
if ($iscatchall) { if ($iscatchall) {
$iscatchall = '1'; $iscatchall = '1';
$email = $result['email']; $email_parts = explode('@', $result['email_full']);
// update only required if it was not a catchall before $email = '@' . $email_parts[1];
if ($result['iscatchall'] == 0) { // catchall check
$email_parts = explode('@', $result['email_full']); $stmt = Database::prepare("
$email = '@' . $email_parts[1]; SELECT `email_full` FROM `" . TABLE_MAIL_VIRTUAL . "`
// catchall check WHERE `email` = :email AND `customerid` = :cid AND `iscatchall` = '1'
$stmt = Database::prepare(" ");
SELECT `email_full` FROM `" . TABLE_MAIL_VIRTUAL . "` $params = [
WHERE `email` = :email AND `customerid` = :cid AND `iscatchall` = '1' "email" => $email,
"); "cid" => $customer['customerid']
$params = [ ];
"email" => $email, $email_check = Database::pexecute_first($stmt, $params, true, true);
"cid" => $customer['customerid'] if ($email_check) {
]; Response::standardError('youhavealreadyacatchallforthisdomain', '', true);
$email_check = Database::pexecute_first($stmt, $params, true, true);
if ($email_check) {
Response::standardError('youhavealreadyacatchallforthisdomain', '', true);
}
} }
} else {
$iscatchall = '0';
$email = $result['email_full'];
} }
$spam_tag_level = Validate::validate($spam_tag_level, 'spam_tag_level', '/^\d{1,}(\.\d{1,2})?$/', '', [7.0], true);
$spam_kill_level = Validate::validate($spam_kill_level, 'spam_kill_level', '/^\d{1,}(\.\d{1,2})?$/', '', [14.0], true);
$description = Validate::validate(trim($description), 'description', Validate::REGEX_DESC_TEXT, '', [], true);
$stmt = Database::prepare(" $stmt = Database::prepare("
UPDATE `" . TABLE_MAIL_VIRTUAL . "` SET UPDATE `" . TABLE_MAIL_VIRTUAL . "`
`email` = :email , SET `email` = :email , `iscatchall` = :caflag, `description` = :description
`spam_tag_level` = :spam_tag_level,
`spam_kill_level` = :spam_kill_level,
`bypass_spam` = :bypass_spam,
`policy_greylist` = :policy_greylist,
`iscatchall` = :caflag,
`description` = :description
WHERE `customerid`= :cid AND `id`= :id WHERE `customerid`= :cid AND `id`= :id
"); ");
$params = [ $params = [
"email" => $email, "email" => $email,
"spam_tag_level" => $spam_tag_level,
"spam_kill_level" => $spam_kill_level,
"bypass_spam" => $bypass_spam,
"policy_greylist" => $policy_greylist,
"caflag" => $iscatchall, "caflag" => $iscatchall,
"description" => $description, "description" => $description,
"cid" => $customer['customerid'], "cid" => $customer['customerid'],
"id" => $id "id" => $id
]; ];
Database::pexecute($stmt, $params, true, true); Database::pexecute($stmt, $params, true, true);
Cronjob::inserttask(TaskId::REBUILD_RSPAMD);
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] toggled catchall-flag for email address '" . $result['email_full'] . "'"); $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] toggled catchall-flag for email address '" . $result['email_full'] . "'");
$result = $this->apiCall('Emails.get', [ $result = $this->apiCall('Emails.get', [
@@ -390,7 +334,7 @@ class Emails extends ApiCommand implements ResourceEntity
$result = []; $result = [];
$query_fields = []; $query_fields = [];
$result_stmt = Database::prepare(" $result_stmt = Database::prepare("
SELECT m.*, d.`domain`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize` SELECT m.`id`, m.`domainid`, m.`email`, m.`email_full`, m.`iscatchall`, m.`destination`, m.`popaccountid`, d.`domain`, u.`quota`, u.`imap`, u.`pop3`, u.`postfix`, u.`mboxsize`
FROM `" . TABLE_MAIL_VIRTUAL . "` m FROM `" . TABLE_MAIL_VIRTUAL . "` m
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`) LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`)
LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`) LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`)

View File

@@ -54,7 +54,7 @@ class Mysqls extends ApiCommand implements ResourceEntity
* @param string $description * @param string $description
* optional, description for database * optional, description for database
* @param string $custom_suffix * @param string $custom_suffix
* optional, name for database if customer.mysqlprefix setting is set to "DBNAME" * optional, name for database
* @param bool $sendinfomail * @param bool $sendinfomail
* optional, send created resource-information to customer, default: false * optional, send created resource-information to customer, default: false
* @param int $customerid * @param int $customerid
@@ -110,9 +110,6 @@ class Mysqls extends ApiCommand implements ResourceEntity
$dbm = new DbManager($this->logger()); $dbm = new DbManager($this->logger());
if (strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME' && !empty($databasename)) { if (strtoupper(Settings::Get('customer.mysqlprefix')) == 'DBNAME' && !empty($databasename)) {
if (strlen($newdb_params['loginname'] . '_' . $databasename) > Database::getSqlUsernameLength()) {
throw new Exception("Database name cannot be longer than " . (Database::getSqlUsernameLength() - strlen($newdb_params['loginname'] . '_')) . " characters.", 406);
}
$username = $dbm->createDatabase($newdb_params['loginname'] . '_' . $databasename, $password, $dbserver); $username = $dbm->createDatabase($newdb_params['loginname'] . '_' . $databasename, $password, $dbserver);
} else { } else {
$username = $dbm->createDatabase($newdb_params['loginname'], $password, $dbserver, $newdb_params['mysql_lastaccountnumber']); $username = $dbm->createDatabase($newdb_params['loginname'], $password, $dbserver, $newdb_params['mysql_lastaccountnumber']);

View File

@@ -983,11 +983,9 @@ class SubDomains extends ApiCommand implements ResourceEntity
'`d`.`letsencrypt`', '`d`.`letsencrypt`',
'`d`.`registration_date`', '`d`.`registration_date`',
'`d`.`termination_date`', '`d`.`termination_date`',
'`d`.`deactivated`', '`d`.`deactivated`'
'`d`.`email_only`',
]; ];
} }
$query_fields = []; $query_fields = [];
// prepare select statement // prepare select statement
@@ -998,6 +996,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id` LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `da` ON `da`.`aliasdomain`=`d`.`id`
LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `pd` ON `pd`.`id`=`d`.`parentdomainid` LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` `pd` ON `pd`.`id`=`d`.`parentdomainid`
WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ") WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
AND `d`.`email_only` = '0'
" . $this->getSearchWhere($query_fields, true) . " GROUP BY `d`.`id` ORDER BY `parentdomainname` ASC, `d`.`parentdomainid` ASC " . $this->getOrderBy(true) . $this->getLimit()); " . $this->getSearchWhere($query_fields, true) . " GROUP BY `d`.`id` ORDER BY `parentdomainname` ASC, `d`.`parentdomainid` ASC " . $this->getOrderBy(true) . $this->getLimit());
$result = []; $result = [];
@@ -1093,13 +1092,13 @@ class SubDomains extends ApiCommand implements ResourceEntity
$this->getUserDetail('customerid') $this->getUserDetail('customerid')
]; ];
} }
if (!empty($customer_ids)) { if (!empty($customer_ids)) {
// prepare select statement // prepare select statement
$domains_stmt = Database::prepare(" $domains_stmt = Database::prepare("
SELECT COUNT(*) as num_subdom SELECT COUNT(*) as num_subdom
FROM `" . TABLE_PANEL_DOMAINS . "` `d` FROM `" . TABLE_PANEL_DOMAINS . "` `d`
WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ") WHERE `d`.`customerid` IN (" . implode(', ', $customer_ids) . ")
AND `d`.`email_only` = '0'
"); ");
$result = Database::pexecute_first($domains_stmt, null, true, true); $result = Database::pexecute_first($domains_stmt, null, true, true);
if ($result) { if ($result) {

View File

@@ -90,8 +90,6 @@ class SysLog extends ApiCommand implements ResourceEntity
} }
Database::pexecute($result_stmt, $query_fields, true, true); Database::pexecute($result_stmt, $query_fields, true, true);
while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
// clean log-text
$row['text'] = preg_replace("/[^\w @#\"':.,()\[\]+\-_\/\\\!]/i", "_", $row['text']);
$result[] = $row; $result[] = $row;
} }
$this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list log-entries"); $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_INFO, "[API] list log-entries");

View File

@@ -43,10 +43,11 @@ final class ConfigServices extends CliCommand
{ {
private $yes_to_all_supported = [ private $yes_to_all_supported = [
'bookworm', 'bookworm',
'bionic',
'bullseye', 'bullseye',
'buster',
'focal', 'focal',
'jammy', 'jammy',
'noble',
]; ];
protected function configure() protected function configure()
@@ -171,8 +172,8 @@ final class ConfigServices extends CliCommand
$distributions_select_data = []; $distributions_select_data = [];
//set default os. //set default os.
$os_dist = ['ID' => 'bookworm']; $os_dist = ['ID' => 'bullseye'];
$os_version = ['0' => '12']; $os_version = ['0' => '11'];
$os_default = $os_dist['ID']; $os_default = $os_dist['ID'];
//read os-release //read os-release

View File

@@ -27,13 +27,10 @@ namespace Froxlor\Cli;
use Exception; use Exception;
use Froxlor\Config\ConfigParser; use Froxlor\Config\ConfigParser;
use Froxlor\Database\Database;
use Froxlor\Froxlor; use Froxlor\Froxlor;
use Froxlor\Install\Install; use Froxlor\Install\Install;
use Froxlor\Install\Install\Core; use Froxlor\Install\Install\Core;
use Froxlor\Settings;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputOption;
@@ -53,8 +50,7 @@ final class InstallCommand extends Command
$this->setDescription('Installation process to use instead of web-ui'); $this->setDescription('Installation process to use instead of web-ui');
$this->addArgument('input-file', InputArgument::OPTIONAL, 'Optional JSON array file to use for unattended installations'); $this->addArgument('input-file', InputArgument::OPTIONAL, 'Optional JSON array file to use for unattended installations');
$this->addOption('print-example-file', 'p', InputOption::VALUE_NONE, 'Outputs an example JSON content to be used with the input file parameter') $this->addOption('print-example-file', 'p', InputOption::VALUE_NONE, 'Outputs an example JSON content to be used with the input file parameter')
->addOption('create-userdata-from-str', 'c', InputOption::VALUE_REQUIRED, 'Creates lib/userdata.inc.php file from string created by web-install process') ->addOption('create-userdata-from-str', 'c', InputOption::VALUE_REQUIRED, 'Creates lib/userdata.inc.php file from string created by web-install process');
->addOption('show-sysinfo', 's', InputOption::VALUE_NONE, 'Outputs system information about your froxlor installation');
} }
/** /**
@@ -76,15 +72,6 @@ final class InstallCommand extends Command
return self::INVALID; return self::INVALID;
} }
if ($input->getOption('show-sysinfo') !== false) {
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
$output->writeln("<error>Could not find froxlor's userdata.inc.php file. You can use this parameter only with an installed froxlor system.</>");
return self::INVALID;
}
$this->printSysInfo($output);
return self::SUCCESS;
}
session_start(); session_start();
require __DIR__ . '/install.functions.php'; require __DIR__ . '/install.functions.php';
@@ -362,57 +349,6 @@ final class InstallCommand extends Command
fclose($fp); fclose($fp);
} }
private function printSysInfo(OutputInterface $output)
{
$php_sapi = 'mod_php';
$php_version = phpversion();
if (Settings::Get('system.mod_fcgid') == '1') {
$php_sapi = 'FCGID';
if (Settings::Get('system.mod_fcgid_ownvhost') == '1') {
$php_sapi .= ' (+ froxlor)';
}
} elseif (Settings::Get('phpfpm.enabled') == '1') {
$php_sapi = 'PHP-FPM';
if (Settings::Get('phpfpm.enabled_ownvhost') == '1') {
$php_sapi .= ' (+ froxlor)';
}
}
$kernel = 'unknown';
if (function_exists('posix_uname')) {
$kernel_nfo = posix_uname();
$kernel = $kernel_nfo['release'] . ' (' . $kernel_nfo['machine'] . ')';
}
$ips = [];
$ips_stmt = Database::query("SELECT CONCAT(`ip`, ' (', `port`, ')') as ipaddr FROM `" . TABLE_PANEL_IPSANDPORTS . "` ORDER BY `id`");
while ($ip = $ips_stmt->fetch(\PDO::FETCH_ASSOC)) {
$ips[] = $ip['ipaddr'];
}
$table = new Table($output);
$table
->setHeaders([
'Key', 'Value'
])
->setRows([
['Froxlor', Froxlor::getVersionString()],
['Update-channel', Settings::Get('system.update_channel')],
['Hostname', Settings::Get('system.hostname')],
['Install-dir', Froxlor::getInstallDir()],
['PHP CLI', $php_version],
['PHP SAPI', $php_sapi],
['Webserver', Settings::Get('system.webserver')],
['Kernel', $kernel],
['Database', Database::getAttribute(\PDO::ATTR_SERVER_VERSION)],
['Distro config', Settings::Get('system.distribution')],
['IP addresses', implode("\n", $ips)],
]);
$table->setStyle('box');
$table->render();
}
private function cliTextFormat(string $text, string $nl_char = "\n"): string private function cliTextFormat(string $text, string $nl_char = "\n"): string
{ {
$text = str_replace(['<br>', '<br/>', '<br />'], [$nl_char, $nl_char, $nl_char], $text); $text = str_replace(['<br>', '<br/>', '<br />'], [$nl_char, $nl_char, $nl_char], $text);

View File

@@ -52,7 +52,7 @@ final class MasterCron extends CliCommand
$this->setName('froxlor:cron'); $this->setName('froxlor:cron');
$this->setDescription('Regulary perform tasks created by froxlor'); $this->setDescription('Regulary perform tasks created by froxlor');
$this->addArgument('job', InputArgument::IS_ARRAY, 'Job(s) to run'); $this->addArgument('job', InputArgument::IS_ARRAY, 'Job(s) to run');
$this->addOption('run-task', 'r', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Run a specific task [1 = re-generate configs, 4 = re-generate dns zones, 9 = re-generate rspamd configs, 10 = re-set quotas, 99 = re-create cron.d-file]') $this->addOption('run-task', 'r', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Run a specific task [1 = re-generate configs, 4 = re-generate dns zones, 10 = re-set quotas, 99 = re-create cron.d-file]')
->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces given job or, if none given, forces re-generating of config-files (webserver, nameserver, etc.)') ->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces given job or, if none given, forces re-generating of config-files (webserver, nameserver, etc.)')
->addOption('debug', 'd', InputOption::VALUE_NONE, 'Output debug information about what is going on to STDOUT.') ->addOption('debug', 'd', InputOption::VALUE_NONE, 'Output debug information about what is going on to STDOUT.')
->addOption('no-fork', 'N', InputOption::VALUE_NONE, 'Do not fork to background (traffic cron only).'); ->addOption('no-fork', 'N', InputOption::VALUE_NONE, 'Do not fork to background (traffic cron only).');
@@ -77,7 +77,6 @@ final class MasterCron extends CliCommand
if (empty($jobs) || in_array('tasks', $jobs)) { if (empty($jobs) || in_array('tasks', $jobs)) {
Cronjob::inserttask(TaskId::REBUILD_VHOST); Cronjob::inserttask(TaskId::REBUILD_VHOST);
Cronjob::inserttask(TaskId::REBUILD_DNS); Cronjob::inserttask(TaskId::REBUILD_DNS);
Cronjob::inserttask(TaskId::REBUILD_RSPAMD);
Cronjob::inserttask(TaskId::CREATE_QUOTA); Cronjob::inserttask(TaskId::CREATE_QUOTA);
Cronjob::inserttask(TaskId::REBUILD_CRON); Cronjob::inserttask(TaskId::REBUILD_CRON);
$jobs[] = 'tasks'; $jobs[] = 'tasks';
@@ -96,7 +95,7 @@ final class MasterCron extends CliCommand
if ($input->getOption('run-task')) { if ($input->getOption('run-task')) {
$tasks_to_run = $input->getOption('run-task'); $tasks_to_run = $input->getOption('run-task');
foreach ($tasks_to_run as $ttr) { foreach ($tasks_to_run as $ttr) {
if (in_array($ttr, [TaskId::REBUILD_VHOST, TaskId::REBUILD_DNS, TaskId::REBUILD_RSPAMD, TaskId::CREATE_QUOTA, TaskId::REBUILD_CRON])) { if (in_array($ttr, [TaskId::REBUILD_VHOST, TaskId::REBUILD_DNS, TaskId::CREATE_QUOTA, TaskId::REBUILD_CRON])) {
Cronjob::inserttask($ttr); Cronjob::inserttask($ttr);
$jobs[] = 'tasks'; $jobs[] = 'tasks';
} else { } else {
@@ -171,9 +170,8 @@ final class MasterCron extends CliCommand
FroxlorLogger::getInstanceOf()->setCronLog(0); FroxlorLogger::getInstanceOf()->setCronLog(0);
} }
// clean up possible old login-links and 2fa tokens // clean up possible old login-links
Database::query("DELETE FROM `" . TABLE_PANEL_LOGINLINKS . "` WHERE `valid_until` < UNIX_TIMESTAMP()"); Database::query("DELETE FROM `" . TABLE_PANEL_LOGINLINKS . "` WHERE `valid_until` < UNIX_TIMESTAMP()");
Database::query("DELETE FROM `" . TABLE_PANEL_2FA_TOKENS . "` WHERE `valid_until` < UNIX_TIMESTAMP()");
return $result; return $result;
} }

View File

@@ -58,9 +58,8 @@ final class UpdateCommand extends CliCommand
if ($input->getOption('database')) { if ($input->getOption('database')) {
$result = $this->validateRequirements($output, true); $result = $this->validateRequirements($output, true);
if ($result == self::SUCCESS) { if ($result == self::SUCCESS) {
require Froxlor::getInstallDir() . '/lib/functions.php';
if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) { if (Froxlor::hasUpdates() || Froxlor::hasDbUpdates()) {
$output->writeln('<info>' . lng('update.dbupdate_required') . '</>'); $output->writeln('<info>' . lng('updates.dbupdate_required') . '</>');
if ($input->getOption('check-only')) { if ($input->getOption('check-only')) {
$output->writeln('<comment>Doing nothing because of "check-only" flag.</>'); $output->writeln('<comment>Doing nothing because of "check-only" flag.</>');
} else { } else {

View File

@@ -91,9 +91,6 @@ class ConfigDaemon
$this->fullxml = $xml; $this->fullxml = $xml;
$this->xpath = $xpath; $this->xpath = $xpath;
$this->daemon = $this->fullxml->xpath($this->xpath); $this->daemon = $this->fullxml->xpath($this->xpath);
if (count($this->daemon) !== 1) {
throw new Exception('XPath "' . $this->xpath . '" didn\'t return exactly one element');
}
$attributes = $this->daemon[0]->attributes(); $attributes = $this->daemon[0]->attributes();
if ($attributes['title'] != '') { if ($attributes['title'] != '') {
$this->title = $this->parseContent((string)$attributes['title']); $this->title = $this->parseContent((string)$attributes['title']);
@@ -412,7 +409,7 @@ class ConfigDaemon
} }
$return[] = [ $return[] = [
'type' => 'command', 'type' => 'command',
'content' => '[ -f ' . $this->parseContent($attributes['name']) . ' ] && ' . $cmd . ' "' . $this->parseContent($attributes['name']) . '" "' . $this->parseContent($attributes['name']) . '.frx.bak"', 'content' => $cmd . ' "' . $this->parseContent($attributes['name']) . '" "' . $this->parseContent($attributes['name']) . '.frx.bak"',
'execute' => "pre" 'execute' => "pre"
]; ];
} }

View File

@@ -117,6 +117,85 @@ abstract class DnsBase
} }
} }
public function writeDKIMconfigs()
{
if (Settings::Get('dkim.use_dkim') == '1') {
if (!file_exists(FileDir::makeCorrectDir(Settings::Get('dkim.dkim_prefix')))) {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('dkim.dkim_prefix'))));
FileDir::safe_exec('mkdir -p ' . escapeshellarg(FileDir::makeCorrectDir(Settings::Get('dkim.dkim_prefix'))));
}
$dkimdomains = '';
$dkimkeys = '';
$result_domains_stmt = Database::query("
SELECT `id`, `domain`, `dkim`, `dkim_id`, `dkim_pubkey`, `dkim_privkey`
FROM `" . TABLE_PANEL_DOMAINS . "` WHERE `dkim` = '1' ORDER BY `id` ASC
");
while ($domain = $result_domains_stmt->fetch(PDO::FETCH_ASSOC)) {
$privkey_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . Settings::Get('dkim.privkeysuffix'));
$pubkey_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . '.public');
if ($domain['dkim_privkey'] == '' || $domain['dkim_pubkey'] == '') {
$max_dkim_id_stmt = Database::query("SELECT MAX(`dkim_id`) as `max_dkim_id` FROM `" . TABLE_PANEL_DOMAINS . "`");
$max_dkim_id = $max_dkim_id_stmt->fetch(PDO::FETCH_ASSOC);
$domain['dkim_id'] = (int)$max_dkim_id['max_dkim_id'] + 1;
$privkey_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . Settings::Get('dkim.privkeysuffix'));
FileDir::safe_exec('openssl genrsa -out ' . escapeshellarg($privkey_filename) . ' ' . Settings::Get('dkim.dkim_keylength'));
$domain['dkim_privkey'] = file_get_contents($privkey_filename);
FileDir::safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));
$pubkey_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/dkim' . $domain['dkim_id'] . '.public');
FileDir::safe_exec('openssl rsa -in ' . escapeshellarg($privkey_filename) . ' -pubout -outform pem -out ' . escapeshellarg($pubkey_filename));
$domain['dkim_pubkey'] = file_get_contents($pubkey_filename);
FileDir::safe_exec("chmod 0664 " . escapeshellarg($pubkey_filename));
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
`dkim_id` = :dkimid,
`dkim_privkey` = :privkey,
`dkim_pubkey` = :pubkey
WHERE `id` = :id
");
$upd_data = [
'dkimid' => $domain['dkim_id'],
'privkey' => $domain['dkim_privkey'],
'pubkey' => $domain['dkim_pubkey'],
'id' => $domain['id']
];
Database::pexecute($upd_stmt, $upd_data);
}
if (!file_exists($privkey_filename) && $domain['dkim_privkey'] != '') {
$privkey_file_handler = fopen($privkey_filename, "w");
fwrite($privkey_file_handler, $domain['dkim_privkey']);
fclose($privkey_file_handler);
FileDir::safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));
}
if (!file_exists($pubkey_filename) && $domain['dkim_pubkey'] != '') {
$pubkey_file_handler = fopen($pubkey_filename, "w");
fwrite($pubkey_file_handler, $domain['dkim_pubkey']);
fclose($pubkey_file_handler);
FileDir::safe_exec("chmod 0644 " . escapeshellarg($pubkey_filename));
}
$dkimdomains .= $domain['domain'] . "\n";
$dkimkeys .= "*@" . $domain['domain'] . ":" . $domain['domain'] . ":" . $privkey_filename . "\n";
}
$dkimdomains_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/' . Settings::Get('dkim.dkim_domains'));
$dkimdomains_file_handler = fopen($dkimdomains_filename, "w");
fwrite($dkimdomains_file_handler, $dkimdomains);
fclose($dkimdomains_file_handler);
$dkimkeys_filename = FileDir::makeCorrectFile(Settings::Get('dkim.dkim_prefix') . '/' . Settings::Get('dkim.dkim_dkimkeys'));
$dkimkeys_file_handler = fopen($dkimkeys_filename, "w");
fwrite($dkimkeys_file_handler, $dkimkeys);
fclose($dkimkeys_file_handler);
FileDir::safe_exec(escapeshellcmd(Settings::Get('dkim.dkimrestart_command')));
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Dkim-milter reloaded');
}
}
protected function getDomainList() protected function getDomainList()
{ {
$result_domains_stmt = Database::query(" $result_domains_stmt = Database::query("

View File

@@ -321,7 +321,6 @@ EOC;
WHERE WHERE
dom.`customerid` = cust.`customerid` dom.`customerid` = cust.`customerid`
AND cust.deactivated = 0 AND cust.deactivated = 0
AND dom.`ssl_enabled` = 1
AND dom.`letsencrypt` = 1 AND dom.`letsencrypt` = 1
AND dom.`aliasdomain` IS NULL AND dom.`aliasdomain` IS NULL
AND dom.`iswildcarddomain` = 0 AND dom.`iswildcarddomain` = 0
@@ -383,7 +382,6 @@ EOC;
WHERE WHERE
dom.`customerid` = cust.`customerid` dom.`customerid` = cust.`customerid`
AND cust.deactivated = 0 AND cust.deactivated = 0
AND dom.`ssl_enabled` = 1
AND dom.`letsencrypt` = 1 AND dom.`letsencrypt` = 1
AND dom.`aliasdomain` IS NULL AND dom.`aliasdomain` IS NULL
AND dom.`iswildcarddomain` = 0 AND dom.`iswildcarddomain` = 0
@@ -520,7 +518,7 @@ EOC;
self::validateDns($domains, $certrow['domainid'], $cronlog); self::validateDns($domains, $certrow['domainid'], $cronlog);
self::runAcmeSh($certrow, $domains, $cronlog, $do_force, $certrow['domainid'] == 0); self::runAcmeSh($certrow, $domains, $cronlog, $do_force);
} else { } else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect"); $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Skipping Let's Encrypt generation for " . $certrow['domain'] . " due to an enabled ssl_redirect");
// we need another reconfigure in order to get the certificate // we need another reconfigure in order to get the certificate
@@ -570,7 +568,7 @@ EOC;
} }
} }
private static function runAcmeSh(array $certrow, array $domains, &$cronlog = null, bool $force = false, bool $renew_hook = false) private static function runAcmeSh(array $certrow, array $domains, &$cronlog = null, $force = false)
{ {
if (!empty($domains)) { if (!empty($domains)) {
$acmesh_cmd = self::getAcmeSh() . " --server " . self::$apiserver . " --issue -d " . implode(" -d ", $domains); $acmesh_cmd = self::getAcmeSh() . " --server " . self::$apiserver . " --issue -d " . implode(" -d ", $domains);
@@ -591,12 +589,6 @@ EOC;
if ($force) { if ($force) {
$acmesh_cmd .= " --force"; $acmesh_cmd .= " --force";
} }
if ($renew_hook
&& !empty(trim(Settings::Get('system.le_renew_services') ?? ""))
&& !empty(trim(Settings::Get('system.le_renew_hook') ?? ""))
) {
$acmesh_cmd .= " --renew-hook '" . Settings::Get('system.le_renew_hook') . "'";
}
if (defined('CRON_DEBUG_FLAG')) { if (defined('CRON_DEBUG_FLAG')) {
$acmesh_cmd .= " --debug"; $acmesh_cmd .= " --debug";
} }
@@ -613,67 +605,12 @@ EOC;
} }
} else { } else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, "Successful exit-code returned - storing certificate"); $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, "Successful exit-code returned - storing certificate");
$cert_stored = self::certToDb($certrow, $cronlog, $acme_result); self::certToDb($certrow, $cronlog, $acme_result);
if ($cert_stored
&& $renew_hook
&& !empty(trim(Settings::Get('system.le_renew_services') ?? ""))
&& !empty(trim(Settings::Get('system.le_renew_hook') ?? ""))
) {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, "Renew-hook is enabled - adjusting configurations");
$certificate_folder = self::getCertificateFolder(strtolower(Settings::Get('system.hostname')));
$fullchain = FileDir::makeCorrectFile($certificate_folder . '/fullchain.cer');
$keyfile = FileDir::makeCorrectFile($certificate_folder . '/' . strtolower(Settings::Get('system.hostname')) . '.key');
$ca_file = FileDir::makeCorrectFile($certificate_folder . '/ca.cer');
if (Settings::IsInList('system.le_renew_services', 'postfix')) {
// "postconf -e" for postfix
FileDir::safe_exec('postconf -e smtpd_tls_cert_file=' . escapeshellarg($fullchain));
FileDir::safe_exec('postconf -e smtpd_tls_key_file=' . escapeshellarg($keyfile));
}
if (Settings::IsInList('system.le_renew_services', 'dovecot')) {
// custom config for dovecot
$dovecot_conf = '/etc/dovecot/conf.d/99-froxlor.ssl.conf'; // @fixme setting?
$ssl_content = <<<EOSSL
# Autogenerated configuration by froxlor.
# Do not manually edit this file as it will be overwritten.
ssl = yes
ssl_cert = <{$fullchain}
ssl_key = <{$keyfile}
EOSSL;
file_put_contents($dovecot_conf, $ssl_content);
}
if (Settings::IsInList('system.le_renew_services', 'proftpd')) {
$proftpd_conf = '/etc/proftpd/tls.conf'; // @fixme setting?
$rval = false;
// ECC certificate or not?
if (strpos($certificate_folder, '_ecc') === false) {
// comment out ECC related settings
FileDir::safe_exec("sed -i.bak 's|^TLSECCertificateFile|# TLSECCertificateFile|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']);
FileDir::safe_exec("sed -i.bak 's|^TLSECCertificateKeyFile|# TLSECCertificateKeyFile|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']);
// add RSA directives
FileDir::safe_exec("sed -i.bak 's|^#\?\s\?TLSRSACertificateFile.*|TLSRSACertificateFile " . $fullchain . "|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']);
FileDir::safe_exec("sed -i.bak 's|^#\?\s\?TLSRSACertificateKeyFile.*|TLSRSACertificateKeyFile " . $keyfile . "|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']);
} else {
// comment out RSA related settings
FileDir::safe_exec("sed -i.bak 's|^TLSRSACertificateFile|# TLSRSACertificateFile|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']);
FileDir::safe_exec("sed -i.bak 's|^TLSRSACertificateKeyFile|# TLSRSACertificateKeyFile|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']);
// add ECC directives
FileDir::safe_exec("sed -i.bak 's|^#\?\s\?TLSECCertificateFile.*|TLSECCertificateFile " . $fullchain . "|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']);
FileDir::safe_exec("sed -i.bak 's|^#\?\s\?TLSECCertificateKeyFile.*|TLSECCertificateKeyFile " . $keyfile . "|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']);
}
FileDir::safe_exec("sed -i.bak 's|^#\?\s\?TLSCACertificateFile.*|TLSCACertificateFile " . $ca_file . "|' " . escapeshellarg($proftpd_conf), $rval, ['|', '?']);
}
// reload the services
FileDir::safe_exec(Settings::Get('system.le_renew_hook'));
}
} }
} }
} }
private static function certToDb($certrow, &$cronlog, $acme_result): bool private static function certToDb($certrow, &$cronlog, $acme_result)
{ {
$return = []; $return = [];
self::readCertificateToVar(strtolower($certrow['domain']), $return, $cronlog); self::readCertificateToVar(strtolower($certrow['domain']), $return, $cronlog);
@@ -704,14 +641,12 @@ EOSSL;
} }
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']); $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, "Updated Let's Encrypt certificate for " . $certrow['domain']);
return true;
} else { } else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Got non-successful Let's Encrypt response for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result)); $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Got non-successful Let's Encrypt response for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result));
} }
} else { } else {
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result)); $cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, "Could not get Let's Encrypt certificate for " . $certrow['domain'] . ":\n" . implode("\n", $acme_result));
} }
return false;
} }
/** /**

View File

@@ -46,9 +46,10 @@ class Nginx extends HttpConfigBase
// protected // protected
protected $needed_htpasswds = []; protected $needed_htpasswds = [];
protected $http2_on_directive = false; protected $auth_backend_loaded = false;
protected $htpasswds_data = []; protected $htpasswds_data = [];
protected $known_htpasswdsfilenames = []; protected $known_htpasswdsfilenames = [];
protected $mod_accesslog_loaded = '0';
protected $vhost_root_autoindex = false; protected $vhost_root_autoindex = false;
/** /**
@@ -59,18 +60,6 @@ class Nginx extends HttpConfigBase
*/ */
private $deactivated = false; private $deactivated = false;
public function __construct()
{
$nores = false;
$res = FileDir::safe_exec('nginx -v 2>&1', $nores, ['>', '&']);
$ver_str = array_shift($res);
$cNginxVer = substr($ver_str, strrpos($ver_str, "/") + 1);
if (version_compare($cNginxVer, '1.25.1', '>=')) {
// at least 1.25.1
$this->http2_on_directive = true;
}
}
public function createVirtualHosts() public function createVirtualHosts()
{ {
return; return;
@@ -173,10 +162,8 @@ class Nginx extends HttpConfigBase
/** /**
* this HAS to be set for the default host in nginx or else no vhost will work * this HAS to be set for the default host in nginx or else no vhost will work
*/ */
$this->nginx_data[$vhost_filename] .= "\t" . 'listen ' . $ip . ':' . $port . ' default_server' . ($ssl_vhost == true ? ' ssl' : '') . ($http2 && !$this->http2_on_directive ? ' http2' : '') . ';' . "\n"; $this->nginx_data[$vhost_filename] .= "\t" . 'listen ' . $ip . ':' . $port . ' default_server' . ($ssl_vhost == true ? ' ssl' : '') . ($http2 == true ? ' http2' : '') . ';' . "\n";
if ($http2 && $this->http2_on_directive) {
$this->nginx_data[$vhost_filename] .= "\t" . 'http2 on;' . "\n";
}
$this->nginx_data[$vhost_filename] .= "\t" . '# Froxlor default vhost' . "\n"; $this->nginx_data[$vhost_filename] .= "\t" . '# Froxlor default vhost' . "\n";
$aliases = ""; $aliases = "";
@@ -494,7 +481,6 @@ class Nginx extends HttpConfigBase
$vhost_content = ''; $vhost_content = '';
$_vhost_content = ''; $_vhost_content = '';
$has_http2_on = false;
$query = "SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` `i`, `" . TABLE_DOMAINTOIP . "` `dip` $query = "SELECT * FROM `" . TABLE_PANEL_IPSANDPORTS . "` `i`, `" . TABLE_DOMAINTOIP . "` `dip`
WHERE dip.id_domain = :domainid AND i.id = dip.id_ipandports "; WHERE dip.id_domain = :domainid AND i.id = dip.id_ipandports ";
@@ -545,11 +531,7 @@ class Nginx extends HttpConfigBase
} }
$http2 = $ssl_vhost == true && (isset($domain['http2']) && $domain['http2'] == '1' && Settings::Get('system.http2_support') == '1'); $http2 = $ssl_vhost == true && (isset($domain['http2']) && $domain['http2'] == '1' && Settings::Get('system.http2_support') == '1');
$vhost_content .= "\t" . 'listen ' . $ipport . ($ssl_vhost == true ? ' ssl' : '') . ($http2 && !$this->http2_on_directive ? ' http2' : '') . ';' . "\n"; $vhost_content .= "\t" . 'listen ' . $ipport . ($ssl_vhost == true ? ' ssl' : '') . ($http2 == true ? ' http2' : '') . ';' . "\n";
if ($http2 && $this->http2_on_directive && !$has_http2_on) {
$vhost_content .= "\t" . 'http2 on;' . "\n";
$has_http2_on = true;
}
} }
// get all server-names // get all server-names

View File

@@ -1,216 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can also view it online at
* https://files.froxlor.org/misc/COPYING.txt
*
* @copyright the authors
* @author Froxlor team <team@froxlor.org>
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
*/
namespace Froxlor\Cron\Mail;
use Exception;
use Froxlor\Database\Database;
use Froxlor\FileDir;
use Froxlor\FroxlorLogger;
use Froxlor\Settings;
class Rspamd
{
const DEFAULT_MARK_LVL = 7.0;
const DEFAULT_REJECT_LVL = 14.0;
private string $frx_settings_file = "";
protected FroxlorLogger $logger;
public function __construct(FroxlorLogger $logger)
{
$this->logger = $logger;
}
/**
* @throws Exception
*/
public function writeConfigs()
{
// tell the world what we are doing
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task9 started - Rebuilding antispam configuration');
// get all email addresses
$antispam_stmt = Database::prepare("
SELECT email, spam_tag_level, spam_kill_level, bypass_spam, policy_greylist, iscatchall
FROM `" . TABLE_MAIL_VIRTUAL . "`
ORDER BY email
");
Database::pexecute($antispam_stmt);
$this->frx_settings_file = "#\n# Automatically generated file by froxlor. DO NOT EDIT manually as it will be overwritten!\n# Generated: " . date('d.m.Y H:i') . "\n#\n\n";
while ($email = $antispam_stmt->fetch(\PDO::FETCH_ASSOC)) {
$this->generateEmailAddrConfig($email);
}
$antispam_cfg_file = FileDir::makeCorrectFile(Settings::Get('antispam.config_file'));
file_put_contents($antispam_cfg_file, $this->frx_settings_file);
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, $antispam_cfg_file . ' written');
$this->writeDkimConfigs();
$this->reloadDaemon();
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task9 finished');
}
/**
* # local.d/dkim_signing.conf
* try_fallback = true;
* path = "/var/lib/rspamd/dkim/$domain.$selector.key";
* selector_map = "/etc/rspamd/dkim_selectors.map";
*
* @return void
* @throws Exception
*/
public function writeDkimConfigs()
{
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Writing DKIM key-pairs');
$dkim_selector_map = "";
$result_domains_stmt = Database::query("
SELECT `id`, `domain`, `dkim`, `dkim_id`, `dkim_pubkey`, `dkim_privkey`
FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `dkim` = '1'
ORDER BY `id` ASC
");
while ($domain = $result_domains_stmt->fetch(\PDO::FETCH_ASSOC)) {
if ($domain['dkim_privkey'] == '' || $domain['dkim_pubkey'] == '') {
$max_dkim_id_stmt = Database::query("SELECT MAX(`dkim_id`) as `max_dkim_id` FROM `" . TABLE_PANEL_DOMAINS . "`");
$max_dkim_id = $max_dkim_id_stmt->fetch(\PDO::FETCH_ASSOC);
$domain['dkim_id'] = (int)$max_dkim_id['max_dkim_id'] + 1;
$privkey_filename = FileDir::makeCorrectFile('/var/lib/rspamd/dkim/' . $domain['domain'] . '.dkim' . $domain['dkim_id'] . '.key');
$pubkey_filename = FileDir::makeCorrectFile('/var/lib/rspamd/dkim/' . $domain['domain'] . '.dkim' . $domain['dkim_id'] . '.txt');
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Generating DKIM keys for "' . $domain['domain'] . '"');
$rsret = [];
FileDir::safe_exec(
'rspamadm dkim_keygen -d ' . escapeshellarg($domain['domain']) . ' -k ' . $privkey_filename . ' -s dkim' . $domain['dkim_id'] . ' -b ' . Settings::Get('antispam.dkim_keylength') . ' -o plain > ' . escapeshellarg($pubkey_filename),
$rsret,
['>']
);
if (!file_exists($privkey_filename) || !file_exists($pubkey_filename)) {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, 'DKIM Keypair for domain "' . $domain['domain'] . '" was not generated successfully.');
continue;
}
$domain['dkim_privkey'] = file_get_contents($privkey_filename);
FileDir::safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));
FileDir::safe_exec("chown _rspamd:_rspamd " . escapeshellarg($privkey_filename));
$domain['dkim_pubkey'] = file_get_contents($pubkey_filename);
FileDir::safe_exec("chmod 0664 " . escapeshellarg($pubkey_filename));
FileDir::safe_exec("chown _rspamd:_rspamd " . escapeshellarg($pubkey_filename));
$upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
`dkim_id` = :dkimid,
`dkim_privkey` = :privkey,
`dkim_pubkey` = :pubkey
WHERE `id` = :id
");
$upd_data = [
'dkimid' => $domain['dkim_id'],
'privkey' => $domain['dkim_privkey'],
'pubkey' => $domain['dkim_pubkey'],
'id' => $domain['id']
];
Database::pexecute($upd_stmt, $upd_data);
} else {
$privkey_filename = FileDir::makeCorrectFile('/var/lib/rspamd/dkim/' . $domain['domain'] . '.dkim' . $domain['dkim_id'] . '.key');
$pubkey_filename = FileDir::makeCorrectFile('/var/lib/rspamd/dkim/' . $domain['domain'] . '.dkim' . $domain['dkim_id'] . '.txt');
}
if (!file_exists($privkey_filename) && $domain['dkim_privkey'] != '') {
file_put_contents($privkey_filename, $domain['dkim_privkey']);
FileDir::safe_exec("chmod 0640 " . escapeshellarg($privkey_filename));
FileDir::safe_exec("chown _rspamd:_rspamd " . escapeshellarg($privkey_filename));
}
if (!file_exists($pubkey_filename) && $domain['dkim_pubkey'] != '') {
file_put_contents($pubkey_filename, $domain['dkim_pubkey']);
FileDir::safe_exec("chmod 0644 " . escapeshellarg($pubkey_filename));
FileDir::safe_exec("chown _rspamd:_rspamd " . escapeshellarg($pubkey_filename));
}
$dkim_selector_map .= $domain['domain'] . " dkim" . $domain['dkim_id'] . "\n";
}
$dkim_selector_file = FileDir::makeCorrectFile('/etc/rspamd/dkim_selectors.map');
file_put_contents($dkim_selector_file, $dkim_selector_map);
}
private function generateEmailAddrConfig(array $email): void
{
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'Generating antispam config for ' . $email['email']);
$email['spam_tag_level'] = floatval($email['spam_tag_level']);
$email['spam_kill_level'] = floatval($email['spam_kill_level']);
$email_id = md5($email['email']);
$this->frx_settings_file .= '# Email: ' . $email['email'] . "\n";
foreach (['rcpt', 'from'] as $type) {
$this->frx_settings_file .= 'frx_' . $email_id . '_' . $type . ' {' . "\n";
$this->frx_settings_file .= ' id = "frx_' . $email_id . '_' . $type . '";' . "\n";
if ($email['iscatchall']) {
$this->frx_settings_file .= ' priority = low;' . "\n";
$this->frx_settings_file .= ' ' . $type . ' = "' . substr($email['email'], strpos($email['email'], '@')) . '";' . "\n";
} else {
$this->frx_settings_file .= ' priority = medium;' . "\n";
$this->frx_settings_file .= ' ' . $type . ' = "' . $email['email'] . '";' . "\n";
}
if ((int)$email['bypass_spam'] == 1) {
$this->frx_settings_file .= ' want_spam = yes;' . "\n";
} else {
$this->frx_settings_file .= ' apply {' . "\n";
$this->frx_settings_file .= ' actions {' . "\n";
$this->frx_settings_file .= ' "add header" = ' . $email['spam_tag_level'] . ';' . "\n";
$this->frx_settings_file .= ' rewrite_subject = ' . $email['spam_tag_level'] . ';' . "\n";
$this->frx_settings_file .= ' reject = ' . $email['spam_kill_level'] . ';' . "\n";
if ($type == 'rcpt' && (int)$email['policy_greylist'] == 0) {
$this->frx_settings_file .= ' greylist = null;' . "\n";
}
$this->frx_settings_file .= ' }' . "\n";
$this->frx_settings_file .= ' }' . "\n";
if ($type == 'rcpt' && (int)$email['policy_greylist'] == 0) {
$this->frx_settings_file .= ' symbols [ "DONT_GREYLIST" ]' . "\n";
}
}
$this->frx_settings_file .= '}' . "\n";
}
$this->frx_settings_file .= "\n";
}
public function reloadDaemon()
{
// reload DNS daemon
$cmd = Settings::Get('antispam.reload_command');
$cmdStatus = 1;
FileDir::safe_exec(escapeshellcmd($cmd), $cmdStatus);
if ($cmdStatus === 0) {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Antispam daemon reloaded');
} else {
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, 'Error while running `' . $cmd . '`: exit code (' . $cmdStatus . ') - please check your system logs');
}
}
}

View File

@@ -115,46 +115,30 @@ class ExportCron extends FroxlorCron
$has_dbs = false; $has_dbs = false;
$current_dbserver = -1; $current_dbserver = -1;
while ($row = $sel_stmt->fetch()) {
// look for mysqldump // Get sql_root data for the specific database-server the database resides on
$section = 'mysqldump'; if ($current_dbserver != $row['dbserver']) {
if (file_exists("/usr/bin/mysqldump")) { Database::needRoot(true, $row['dbserver']);
$mysql_dump = '/usr/bin/mysqldump'; Database::needSqlData();
} elseif (file_exists("/usr/local/bin/mysqldump")) { $sql_root = Database::getSqlData();
$mysql_dump = '/usr/local/bin/mysqldump'; Database::needRoot(false);
} elseif (file_exists("/usr/bin/mariadb-dump")) { // create temporary mysql-defaults file for the connection-credentials/details
$mysql_dump = '/usr/bin/mariadb-dump'; $mysqlcnf_file = tempnam("/tmp", "frx");
$section = 'mariadb-dump'; $mysqlcnf = "[mysqldump]\npassword=" . $sql_root['passwd'] . "\nhost=" . $sql_root['host'] . "\n";
} if (!empty($sql_root['port'])) {
if (!isset($mysql_dump)) { $mysqlcnf .= "port=" . $sql_root['port'] . "\n";
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, 'mysqldump/mariadb-dump executable could not be found. Please install mysql-client/mariadb-client package.'); } elseif (!empty($sql_root['socket'])) {
} else { $mysqlcnf .= "socket=" . $sql_root['socket'] . "\n";
while ($row = $sel_stmt->fetch()) {
// Get sql_root data for the specific database-server the database resides on
if ($current_dbserver != $row['dbserver']) {
Database::needRoot(true, $row['dbserver']);
Database::needSqlData();
$sql_root = Database::getSqlData();
Database::needRoot(false);
// create temporary mysql-defaults file for the connection-credentials/details
$mysqlcnf_file = tempnam("/tmp", "frx");
$mysqlcnf = "[".$section."]\npassword=" . $sql_root['passwd'] . "\nhost=" . $sql_root['host'] . "\n";
if (!empty($sql_root['port'])) {
$mysqlcnf .= "port=" . $sql_root['port'] . "\n";
} elseif (!empty($sql_root['socket'])) {
$mysqlcnf .= "socket=" . $sql_root['socket'] . "\n";
}
file_put_contents($mysqlcnf_file, $mysqlcnf);
} }
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> '.basename($mysql_dump) . ' -u ' . escapeshellarg($sql_root['user']) . ' -pXXXXX ' . $row['databasename'] . ' > ' . FileDir::makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql')); file_put_contents($mysqlcnf_file, $mysqlcnf);
$bool_false = false;
FileDir::safe_exec($mysql_dump . ' --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;
$current_dbserver = $row['dbserver'];
} }
$cronlog->logAction(FroxlorLogger::CRON_ACTION, LOG_DEBUG, 'shell> mysqldump -u ' . escapeshellarg($sql_root['user']) . ' -pXXXXX ' . $row['databasename'] . ' > ' . FileDir::makeCorrectFile($tmpdir . '/mysql/' . $row['databasename'] . '_' . date('YmdHi', time()) . '.sql'));
$bool_false = false;
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;
$current_dbserver = $row['dbserver'];
} }
if ($has_dbs) { if ($has_dbs) {

View File

@@ -25,11 +25,9 @@
namespace Froxlor\Cron\System; namespace Froxlor\Cron\System;
use Exception;
use Froxlor\Cron\FroxlorCron; use Froxlor\Cron\FroxlorCron;
use Froxlor\Cron\Http\ConfigIO; use Froxlor\Cron\Http\ConfigIO;
use Froxlor\Cron\Http\HttpConfigBase; use Froxlor\Cron\Http\HttpConfigBase;
use Froxlor\Cron\Mail\Rspamd;
use Froxlor\Cron\TaskId; use Froxlor\Cron\TaskId;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Dns\PowerDNS; use Froxlor\Dns\PowerDNS;
@@ -42,9 +40,6 @@ use PDO;
class TasksCron extends FroxlorCron class TasksCron extends FroxlorCron
{ {
/**
* @throws Exception
*/
public static function run() public static function run()
{ {
/** /**
@@ -103,11 +98,6 @@ class TasksCron extends FroxlorCron
* refs #293 * refs #293
*/ */
self::deleteFtpData($row); self::deleteFtpData($row);
} elseif ($row['type'] == TaskId::REBUILD_RSPAMD && (int)Settings::Get('antispam.activated') != 0) {
/**
* TYPE=9 Rebuild antispam config
*/
self::rebuildAntiSpamConfigs();
} elseif ($row['type'] == TaskId::CREATE_QUOTA && (int)Settings::Get('system.diskquota_enabled') != 0) { } elseif ($row['type'] == TaskId::CREATE_QUOTA && (int)Settings::Get('system.diskquota_enabled') != 0) {
/** /**
* TYPE=10 Set the filesystem - quota * TYPE=10 Set the filesystem - quota
@@ -276,7 +266,13 @@ class TasksCron extends FroxlorCron
private static function rebuildDnsConfigs() private static function rebuildDnsConfigs()
{ {
$dnssrv = '\\Froxlor\\Cron\\Dns\\' . Settings::Get('system.dns_server'); $dnssrv = '\\Froxlor\\Cron\\Dns\\' . Settings::Get('system.dns_server');
$nameserver = new $dnssrv(FroxlorLogger::getInstanceOf()); $nameserver = new $dnssrv(FroxlorLogger::getInstanceOf());
if (Settings::Get('dkim.use_dkim') == '1') {
$nameserver->writeDKIMconfigs();
}
$nameserver->writeConfigs(); $nameserver->writeConfigs();
} }
@@ -348,16 +344,24 @@ class TasksCron extends FroxlorCron
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'TasksCron: Task7 started - deleting customer e-mail data'); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'TasksCron: Task7 started - deleting customer e-mail data');
if (is_array($row['data'])) { if (is_array($row['data'])) {
if (isset($row['data']['loginname']) && isset($row['data']['emailpath'])) { if (isset($row['data']['loginname']) && isset($row['data']['email'])) {
// remove specific maildir // remove specific maildir
$email_full = $row['data']['emailpath']; $email_full = $row['data']['email'];
if (empty($email_full)) { if (empty($email_full)) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, 'FATAL: Task7 asks to delete a email account but emailpath field is empty!'); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, 'FATAL: Task7 asks to delete a email account but email field is empty!');
}
$email_user = substr($email_full, 0, strrpos($email_full, "@"));
$email_domain = substr($email_full, strrpos($email_full, "@") + 1);
$maildirname = trim(Settings::Get('system.vmail_maildirname'));
// Add trailing slash to Maildir if needed
$maildirpath = $maildirname;
if (!empty($maildirname) and substr($maildirname, -1) != "/") {
$maildirpath .= "/";
} }
$maildir = FileDir::makeCorrectDir($email_full); $maildir = FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . '/' . $row['data']['loginname'] . '/' . $email_domain . '/' . $email_user);
if ($maildir != '/' && !empty($maildir) && $maildir != Settings::Get('system.vmail_homedir') && substr($maildir, 0, strlen(Settings::Get('system.vmail_homedir'))) == Settings::Get('system.vmail_homedir') && is_dir($maildir) && fileowner($maildir) == Settings::Get('system.vmail_uid') && filegroup($maildir) == Settings::Get('system.vmail_gid')) { if ($maildir != '/' && !empty($maildir) && !empty($email_full) && $maildir != Settings::Get('system.vmail_homedir') && substr($maildir, 0, strlen(Settings::Get('system.vmail_homedir'))) == Settings::Get('system.vmail_homedir') && is_dir($maildir) && is_dir(FileDir::makeCorrectDir($maildir . '/' . $maildirpath)) && fileowner($maildir) == Settings::Get('system.vmail_uid') && filegroup($maildir) == Settings::Get('system.vmail_gid')) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($maildir)); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($maildir));
// mail-address allows many special characters, see http://en.wikipedia.org/wiki/Email_address#Local_part // mail-address allows many special characters, see http://en.wikipedia.org/wiki/Email_address#Local_part
$return = false; $return = false;
@@ -369,6 +373,23 @@ class TasksCron extends FroxlorCron
'~', '~',
'?' '?'
]); ]);
} else {
// backward-compatibility for old folder-structure
$maildir_old = FileDir::makeCorrectDir(Settings::Get('system.vmail_homedir') . '/' . $row['data']['loginname'] . '/' . $row['data']['email']);
if ($maildir_old != '/' && !empty($maildir_old) && $maildir_old != Settings::Get('system.vmail_homedir') && substr($maildir_old, 0, strlen(Settings::Get('system.vmail_homedir'))) == Settings::Get('system.vmail_homedir') && is_dir($maildir_old) && fileowner($maildir_old) == Settings::Get('system.vmail_uid') && filegroup($maildir_old) == Settings::Get('system.vmail_gid')) {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, 'Running: rm -rf ' . escapeshellarg($maildir_old));
// mail-address allows many special characters, see http://en.wikipedia.org/wiki/Email_address#Local_part
$return = false;
FileDir::safe_exec('rm -rf ' . escapeshellarg($maildir_old), $return, [
'|',
'&',
'`',
'$',
'~',
'?'
]);
}
} }
} }
} }
@@ -427,13 +448,4 @@ class TasksCron extends FroxlorCron
} }
} }
} }
/**
* @throws Exception
*/
private static function rebuildAntiSpamConfigs()
{
$antispam = new Rspamd(FroxlorLogger::getInstanceOf());
$antispam->writeConfigs();
}
} }

View File

@@ -66,12 +66,6 @@ final class TaskId
*/ */
const DELETE_FTP_DATA = 8; const DELETE_FTP_DATA = 8;
/**
* TYPE=9 MEANS THAT SOMETHING ANTISPAM RELATED HAS CHANGED.
* REBUILD froxlor_settings.conf IF ANTISPAM IS ENABLED
*/
const REBUILD_RSPAMD = 9;
/** /**
* TYPE=10 Set the filesystem - quota * TYPE=10 Set the filesystem - quota
*/ */

View File

@@ -211,7 +211,7 @@ class ReportsCron extends FroxlorCron
$_mailerror = false; $_mailerror = false;
$mailerr_msg = ""; $mailerr_msg = "";
try { try {
$mail->SetFrom(Settings::Get('panel.adminmail'), Settings::Get('panel.adminmail_defname')); $mail->SetFrom($row['email'], $row['name']);
$mail->Subject = $mail_subject; $mail->Subject = $mail_subject;
$mail->AltBody = $mail_body; $mail->AltBody = $mail_body;
$mail->MsgHTML(nl2br($mail_body)); $mail->MsgHTML(nl2br($mail_body));
@@ -297,7 +297,7 @@ class ReportsCron extends FroxlorCron
$_mailerror = false; $_mailerror = false;
$mailerr_msg = ""; $mailerr_msg = "";
try { try {
$mail->SetFrom(Settings::Get('panel.adminmail'), Settings::Get('panel.adminmail_defname')); $mail->SetFrom($row['email'], $row['name']);
$mail->Subject = $mail_subject; $mail->Subject = $mail_subject;
$mail->Body = $mail_body; $mail->Body = $mail_body;
$mail->MsgHTML(nl2br($mail_body)); $mail->MsgHTML(nl2br($mail_body));
@@ -472,7 +472,7 @@ class ReportsCron extends FroxlorCron
$_mailerror = false; $_mailerror = false;
$mailerr_msg = ""; $mailerr_msg = "";
try { try {
$mail->SetFrom(Settings::Get('panel.adminmail'), Settings::Get('panel.adminmail_defname')); $mail->SetFrom($row['email'], $row['name']);
$mail->Subject = $mail_subject; $mail->Subject = $mail_subject;
$mail->AltBody = $mail_body; $mail->AltBody = $mail_body;
$mail->MsgHTML(nl2br($mail_body)); $mail->MsgHTML(nl2br($mail_body));

View File

@@ -122,7 +122,7 @@ class TrafficCron extends FroxlorCron
if ($mysql_usage_row) { if ($mysql_usage_row) {
$mysqlusage_all[$row_database['customerid']] += floatval($mysql_usage_row['customerusage']); $mysqlusage_all[$row_database['customerid']] += floatval($mysql_usage_row['customerusage']);
} else { } else {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_NOTICE, "Cannot get usage for database " . $row_database['databasename'] . "."); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Cannot get usage for database " . $row_database['databasename'] . ".");
} }
} else { } else {
FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Seems like the database " . $row_database['databasename'] . " had been removed manually."); FroxlorLogger::getInstanceOf()->logAction(FroxlorLogger::CRON_ACTION, LOG_WARNING, "Seems like the database " . $row_database['databasename'] . " had been removed manually.");

View File

@@ -46,7 +46,7 @@ class CurrentUser
*/ */
public static function hasSession(): bool public static function hasSession(): bool
{ {
return !empty($_SESSION) && !empty($_SESSION['userinfo']); return !empty($_SESSION) && isset($_SESSION['userinfo']) && !empty($_SESSION['userinfo']);
} }
/** /**

View File

@@ -32,7 +32,7 @@ class Customer
{ {
/** /**
* Get value of a specific field from a given customer * Get value of a a specific field from a given customer
* *
* @param int $customerid * @param int $customerid
* @param string $varname * @param string $varname

View File

@@ -25,7 +25,6 @@
namespace Froxlor\Database; namespace Froxlor\Database;
use Exception;
use Froxlor\Database\Manager\DbManagerMySQL; use Froxlor\Database\Manager\DbManagerMySQL;
use Froxlor\Froxlor; use Froxlor\Froxlor;
use Froxlor\FroxlorLogger; use Froxlor\FroxlorLogger;
@@ -84,7 +83,7 @@ class DbManager
* @param array $mysql_access_host_array * @param array $mysql_access_host_array
* *
* @return void * @return void
* @throws Exception * @throws \Exception
*/ */
public static function correctMysqlUsers(array $mysql_access_host_array) public static function correctMysqlUsers(array $mysql_access_host_array)
{ {
@@ -111,7 +110,7 @@ class DbManager
$users = $dbm->getManager()->getAllSqlUsers(false); $users = $dbm->getManager()->getAllSqlUsers(false);
foreach ($databases[$dbserver['dbserver']] as $username) { foreach ($databases[$dbserver['dbserver']] as $username) {
if (isset($users[$username]['hosts']) && is_array($users[$username]['hosts'])) { if (isset($users[$username]) && is_array($users[$username]) && isset($users[$username]['hosts']) && is_array($users[$username]['hosts'])) {
$password = [ $password = [
'password' => $users[$username]['password'], 'password' => $users[$username]['password'],
@@ -151,7 +150,6 @@ class DbManager
* @param int $last_accnumber * @param int $last_accnumber
* *
* @return string|bool $username if successful or false of username is equal to the password * @return string|bool $username if successful or false of username is equal to the password
* @throws Exception
*/ */
public function createDatabase(string $loginname = null, string $password = null, int $dbserver = 0, int $last_accnumber = 0) public function createDatabase(string $loginname = null, string $password = null, int $dbserver = 0, int $last_accnumber = 0)
{ {

View File

@@ -76,14 +76,11 @@ class DbManagerMySQL
* optional, whether the password is encrypted or not, default false * optional, whether the password is encrypted or not, default false
* @param bool $update * @param bool $update
* optional, whether to update the password only (not create user) * optional, whether to update the password only (not create user)
* @param bool $grant_access_prefix
* optional, whether the given user will have access to all databases starting with the username, default false
* @throws \Exception * @throws \Exception
*/ */
public function grantPrivilegesTo(string $username, $password, string $access_host = null, bool $p_encrypted = false, bool $update = false, bool $grant_access_prefix = false) public function grantPrivilegesTo(string $username, $password, string $access_host = null, bool $p_encrypted = false, bool $update = false)
{ {
// this is required for mysql8 $pwd_plugin = 'mysql_native_password';
$pwd_plugin = 'caching_sha2_password';
if (is_array($password) && count($password) == 2) { if (is_array($password) && count($password) == 2) {
$pwd_plugin = $password['plugin']; $pwd_plugin = $password['plugin'];
$password = $password['password']; $password = $password['password'];
@@ -111,7 +108,7 @@ class DbManagerMySQL
]); ]);
// grant privileges // grant privileges
$stmt = Database::prepare(" $stmt = Database::prepare("
GRANT ALL ON `" . $username . ($grant_access_prefix ? '%' : '') . "`.* TO :username@:host GRANT ALL ON `" . $username . "`.* TO :username@:host
"); ");
Database::pexecute($stmt, [ Database::pexecute($stmt, [
"username" => $username, "username" => $username,
@@ -222,31 +219,17 @@ class DbManagerMySQL
* *
* @param string $username * @param string $username
* @param string $host * @param string $host
* @param bool $grant_access_prefix
* @throws \Exception * @throws \Exception
*/ */
public function enableUser(string $username, string $host, bool $grant_access_prefix = false) public function enableUser(string $username, string $host)
{ {
// check whether user exists to avoid errors // check whether user exists to avoid errors
if ($this->userExistsOnHost($username, $host)) {
Database::query('GRANT ALL PRIVILEGES ON `' . $username . ($grant_access_prefix ? '%' : '') . '`.* TO `' . $username . '`@`' . $host . '`');
Database::query('GRANT ALL PRIVILEGES ON `' . str_replace('_', '\_', $username) . ($grant_access_prefix ? '%' : '') . '` . * TO `' . $username . '`@`' . $host . '`');
}
}
/**
* Check whether a given username exists for the given host
*
* @param string $username
* @param string $host
* @return bool
* @throws \Exception
*/
public function userExistsOnHost(string $username, string $host): bool
{
$exist_check_stmt = Database::prepare("SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = '" . $username . "' AND host = '" . $host . "')"); $exist_check_stmt = Database::prepare("SELECT EXISTS(SELECT 1 FROM mysql.user WHERE user = '" . $username . "' AND host = '" . $host . "')");
$exist_check = Database::pexecute_first($exist_check_stmt); $exist_check = Database::pexecute_first($exist_check_stmt);
return ($exist_check && array_pop($exist_check) == '1'); if ($exist_check && array_pop($exist_check) == '1') {
Database::query('GRANT ALL PRIVILEGES ON `' . $username . '`.* TO `' . $username . '`@`' . $host . '`');
Database::query('GRANT ALL PRIVILEGES ON `' . str_replace('_', '\_', $username) . '` . * TO `' . $username . '`@`' . $host . '`');
}
} }
/** /**
@@ -279,7 +262,7 @@ class DbManagerMySQL
if (!isset($allsqlusers[$row['User']]) || !is_array($allsqlusers[$row['User']])) { if (!isset($allsqlusers[$row['User']]) || !is_array($allsqlusers[$row['User']])) {
$allsqlusers[$row['User']] = [ $allsqlusers[$row['User']] = [
'password' => $row['Password'] ?? $row['authentication_string'], 'password' => $row['Password'] ?? $row['authentication_string'],
'plugin' => $row['plugin'] ?? 'caching_sha2_password', 'plugin' => $row['plugin'] ?? 'mysql_native_password',
'hosts' => [] 'hosts' => []
]; ];
} }

View File

@@ -54,7 +54,7 @@ class Dns
$dom_data['uid'] = $userinfo['userid']; $dom_data['uid'] = $userinfo['userid'];
} }
} else { } else {
$where_clause = '`customerid` = :uid AND `email_only` = "0" AND '; $where_clause = '`customerid` = :uid AND ';
$dom_data['uid'] = $userinfo['userid']; $dom_data['uid'] = $userinfo['userid'];
} }
@@ -120,8 +120,20 @@ class Dns
if ($domain['isemaildomain'] == '1') { if ($domain['isemaildomain'] == '1') {
self::addRequiredEntry('@', 'MX', $required_entries); self::addRequiredEntry('@', 'MX', $required_entries);
if (Settings::Get('system.dns_createmailentry')) { if (Settings::Get('system.dns_createmailentry')) {
foreach (['imap', 'pop3', 'mail', 'smtp' ] as $record ) { foreach (
foreach (['AAAA', 'A' ] as $type ) { [
'imap',
'pop3',
'mail',
'smtp'
] as $record
) {
foreach (
[
'AAAA',
'A'
] as $type
) {
self::addRequiredEntry($record, $type, $required_entries); self::addRequiredEntry($record, $type, $required_entries);
} }
} }
@@ -140,9 +152,9 @@ class Dns
if (!$froxlorhostname) { if (!$froxlorhostname) {
// additional required records for subdomains // additional required records for subdomains
$subdomains_stmt = Database::prepare(" $subdomains_stmt = Database::prepare("
SELECT `domain`, `iswildcarddomain`, `wwwserveralias`, `isemaildomain` FROM `" . TABLE_PANEL_DOMAINS . "` SELECT `domain`, `iswildcarddomain`, `wwwserveralias`, `isemaildomain` FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `parentdomainid` = :domainid WHERE `parentdomainid` = :domainid
"); ");
Database::pexecute($subdomains_stmt, [ Database::pexecute($subdomains_stmt, [
'domainid' => $domain_id 'domainid' => $domain_id
]); ]);
@@ -151,7 +163,7 @@ class Dns
$sub_record = str_replace('.' . $domain['domain'], '', $subdomain['domain']); $sub_record = str_replace('.' . $domain['domain'], '', $subdomain['domain']);
// Listing domains is enough as there currently is no support for choosing // Listing domains is enough as there currently is no support for choosing
// different ips for a subdomain => use same IPs as toplevel // different ips for a subdomain => use same IPs as toplevel
self::addRequiredEntry($sub_record, 'A', $required_entries); self::addRequiredEntry($sub_record, 'A',$required_entries);
self::addRequiredEntry($sub_record, 'AAAA', $required_entries); self::addRequiredEntry($sub_record, 'AAAA', $required_entries);
// Check whether to add a www.-prefix // Check whether to add a www.-prefix
@@ -169,11 +181,7 @@ class Dns
// check for SPF content later // check for SPF content later
self::addRequiredEntry('@SPF@.' . $sub_record, 'TXT', $required_entries); self::addRequiredEntry('@SPF@.' . $sub_record, 'TXT', $required_entries);
} }
if (Settings::Get('dmarc.use_dmarc') == '1') { if (Settings::Get('dkim.use_dkim') == '1') {
// check for DMARC content later
self::addRequiredEntry('@DMARC@.' . $sub_record, 'TXT', $required_entries);
}
if (Settings::Get('antispam.activated') == '1' && $domain['dkim'] == '1') {
// check for DKIM content later // check for DKIM content later
self::addRequiredEntry('dkim' . $domain['dkim_id'] . '._domainkey.' . $sub_record, 'TXT', $required_entries); self::addRequiredEntry('dkim' . $domain['dkim_id'] . '._domainkey.' . $sub_record, 'TXT', $required_entries);
} }
@@ -210,11 +218,7 @@ class Dns
// check for SPF content later // check for SPF content later
self::addRequiredEntry('@SPF@', 'TXT', $required_entries); self::addRequiredEntry('@SPF@', 'TXT', $required_entries);
} }
if (Settings::Get('dmarc.use_dmarc') == '1') { if (Settings::Get('dkim.use_dkim') == '1') {
// check for DMARC content later
self::addRequiredEntry('@DMARC@', 'TXT', $required_entries);
}
if (Settings::Get('antispam.activated') == '1' && $domain['dkim'] == '1') {
// check for DKIM content later // check for DKIM content later
self::addRequiredEntry('dkim' . $domain['dkim_id'] . '._domainkey', 'TXT', $required_entries); self::addRequiredEntry('dkim' . $domain['dkim_id'] . '._domainkey', 'TXT', $required_entries);
} }
@@ -225,64 +229,51 @@ class Dns
// now generate all records and unset the required entries we have // now generate all records and unset the required entries we have
foreach ($dom_entries as $entry) { foreach ($dom_entries as $entry) {
if (array_key_exists($entry['type'], $required_entries) if (array_key_exists($entry['type'], $required_entries) && array_key_exists(md5($entry['record']),
&& array_key_exists( md5($entry['record']), $required_entries[$entry['type']]) $required_entries[$entry['type']])) {
) {
unset($required_entries[$entry['type']][md5($entry['record'])]); unset($required_entries[$entry['type']][md5($entry['record'])]);
} }
if (Settings::Get('system.dns_createcaaentry') == '1' if (Settings::Get('system.dns_createcaaentry') == '1' && $entry['type'] == 'CAA' && strtolower(substr($entry['content'],
&& $entry['type'] == 'CAA' 0, 7)) == '"v=caa1') {
&& strtolower(substr($entry['content'], 0, 7 )) == '"v=caa1'
) {
// unset special CAA required-entry // unset special CAA required-entry
unset($required_entries[$entry['type']][md5("@CAA@")]); unset($required_entries[$entry['type']][md5("@CAA@")]);
} }
if (Settings::Get('spf.use_spf') == '1' if (Settings::Get('spf.use_spf') == '1' && $entry['type'] == 'TXT' && $entry['record'] == '@' && (strtolower(substr($entry['content'],
&& $entry['type'] == 'TXT' 0, 7)) == '"v=spf1' || strtolower(substr($entry['content'], 0, 6)) == 'v=spf1')) {
&& (strtolower(substr($entry['content'], 0, 7)) == '"v=spf1' || strtolower(substr($entry['content'], 0, 6)) == 'v=spf1')
) {
// unset special spf required-entry // unset special spf required-entry
if ($entry['record'] == '@') { unset($required_entries[$entry['type']][md5("@SPF@")]);
unset($required_entries[$entry['type']][md5("@SPF@")]);
} else {
// subdomain
unset($required_entries[$entry['type']][md5("@SPF@." . $entry['record'])]);
}
}
if (Settings::Get('dmarc.use_dmarc') == '1'
&& $entry['type'] == 'TXT'
&& ($entry['record'] == '_dmarc' || substr($entry['record'], 0, 7) == '_dmarc.')
&& (strtolower(substr($entry['content'], 0, 9)) == '"v=dmarc1' || strtolower(substr($entry['content'], 0, 8)) == 'v=dmarc1')
) {
// unset special dmarc required-entry
if ($entry['record'] == '_dmarc') {
unset($required_entries[$entry['type']][md5("@DMARC@")]);
} else {
// subdomain
unset($required_entries[$entry['type']][md5("@DMARC@" . substr($entry['record'], 6))]);
}
} }
if (empty($primary_ns) && $entry['record'] == '@' && $entry['type'] == 'NS') { if (empty($primary_ns) && $entry['record'] == '@' && $entry['type'] == 'NS') {
// use the first NS entry pertaining to the current domain as primary ns // use the first NS entry pertaining to the current domain as primary ns
$primary_ns = $entry['content']; $primary_ns = $entry['content'];
} }
// check for CNAME on @, www- or wildcard-Alias and remove A/AAAA record accordingly // check for CNAME on @, www- or wildcard-Alias and remove A/AAAA record accordingly
foreach (['@', 'www', '*'] as $crecord) { foreach (
if ($entry['type'] == 'CNAME' [
&& $entry['record'] == '@' '@',
&& (array_key_exists(md5($crecord), $required_entries['A']) || array_key_exists(md5($crecord), $required_entries['AAAA'])) 'www',
) { '*'
] as $crecord
) {
if ($entry['type'] == 'CNAME' && $entry['record'] == '@' && (array_key_exists(md5($crecord),
$required_entries['A']) || array_key_exists(md5($crecord), $required_entries['AAAA']))) {
unset($required_entries['A'][md5($crecord)]); unset($required_entries['A'][md5($crecord)]);
unset($required_entries['AAAA'][md5($crecord)]); unset($required_entries['AAAA'][md5($crecord)]);
} }
} }
// also allow overriding of auto-generated values (imap,pop3,mail,smtp) if enabled in the settings // also allow overriding of auto-generated values (imap,pop3,mail,smtp) if enabled in the settings
if (Settings::Get('system.dns_createmailentry')) { if (Settings::Get('system.dns_createmailentry')) {
foreach (['imap', 'pop3', 'mail', 'smtp'] as $crecord) { foreach (
if ($entry['type'] == 'CNAME' [
&& $entry['record'] == $crecord 'imap',
&& (array_key_exists(md5($crecord), $required_entries['A']) || array_key_exists(md5($crecord), $required_entries['AAAA'])) 'pop3',
) { 'mail',
'smtp'
] as $crecord
) {
if ($entry['type'] == 'CNAME' && $entry['record'] == $crecord && (array_key_exists(md5($crecord),
$required_entries['A']) || array_key_exists(md5($crecord),
$required_entries['AAAA']))) {
unset($required_entries['A'][md5($crecord)]); unset($required_entries['A'][md5($crecord)]);
unset($required_entries['AAAA'][md5($crecord)]); unset($required_entries['AAAA'][md5($crecord)]);
} }
@@ -319,7 +310,8 @@ class Dns
foreach ($records as $record) { foreach ($records as $record) {
if ($type == 'A' && filter_var($ip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) { if ($type == 'A' && filter_var($ip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false) {
$zonerecords[] = new DnsEntry($record, 'A', $ip['ip']); $zonerecords[] = new DnsEntry($record, 'A', $ip['ip']);
} elseif ($type == 'AAAA' && filter_var($ip['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) !== false) { } elseif ($type == 'AAAA' && filter_var($ip['ip'], FILTER_VALIDATE_IP,
FILTER_FLAG_IPV6) !== false) {
$zonerecords[] = new DnsEntry($record, 'AAAA', $ip['ip']); $zonerecords[] = new DnsEntry($record, 'AAAA', $ip['ip']);
} }
} }
@@ -384,7 +376,9 @@ class Dns
// TXT (SPF and DKIM) // TXT (SPF and DKIM)
if (array_key_exists("TXT", $required_entries)) { if (array_key_exists("TXT", $required_entries)) {
$dkim_entries = self::generateDkimEntries($domain); if (Settings::Get('dkim.use_dkim') == '1') {
$dkim_entries = self::generateDkimEntries($domain);
}
foreach ($required_entries as $type => $records) { foreach ($required_entries as $type => $records) {
if ($type == 'TXT') { if ($type == 'TXT') {
@@ -398,15 +392,6 @@ class Dns
$txt_content = Settings::Get('spf.spf_entry'); $txt_content = Settings::Get('spf.spf_entry');
$sub_record = substr($record, 6); $sub_record = substr($record, 6);
$zonerecords[] = new DnsEntry($sub_record, 'TXT', self::encloseTXTContent($txt_content)); $zonerecords[] = new DnsEntry($sub_record, 'TXT', self::encloseTXTContent($txt_content));
} elseif ($record == '@DMARC@') {
// dmarc for main-domain
$txt_content = Settings::Get('dmarc.dmarc_entry');
$zonerecords[] = new DnsEntry('_dmarc', 'TXT', self::encloseTXTContent($txt_content));
} elseif (strlen($record) > 8 && substr($record, 0, 8) == '@DMARC@.') {
// dmarc for subdomain
$txt_content = Settings::Get('dmarc.dmarc_entry');
$sub_record = substr($record, 8);
$zonerecords[] = new DnsEntry('_dmarc.' . $sub_record, 'TXT', self::encloseTXTContent($txt_content));
} elseif (!empty($dkim_entries)) { } elseif (!empty($dkim_entries)) {
// DKIM entries // DKIM entries
$dkim_record = 'dkim' . $domain['dkim_id'] . '._domainkey'; $dkim_record = 'dkim' . $domain['dkim_id'] . '._domainkey';
@@ -418,7 +403,7 @@ class Dns
$multiline = true; $multiline = true;
} }
$zonerecords[] = new DnsEntry($record, 'TXT', self::encloseTXTContent($dkim_entries[0], $multiline)); $zonerecords[] = new DnsEntry($record, 'TXT', self::encloseTXTContent($dkim_entries[0], $multiline));
} elseif (strlen($record) > strlen($dkim_record) && substr($record, 0, strlen($dkim_record) + 1) == $dkim_record . '.') { } elseif (strlen($record) > strlen($dkim_record) && substr($record, 0, strlen($dkim_record)+1) == $dkim_record . '.') {
// dkim for subdomain-domain // dkim for subdomain-domain
// check for multiline entry // check for multiline entry
$multiline = false; $multiline = false;
@@ -486,7 +471,8 @@ class Dns
if (!$isMainButSubTo) { if (!$isMainButSubTo) {
$date = date('Ymd'); $date = date('Ymd');
$domain['bindserial'] = (preg_match('/^' . $date . '/', $domain['bindserial']) ? $domain['bindserial'] + 1 : $date . '00'); $domain['bindserial'] = (preg_match('/^' . $date . '/',
$domain['bindserial']) ? $domain['bindserial'] + 1 : $date . '00');
if (!$froxlorhostname) { if (!$froxlorhostname) {
$upd_stmt = Database::prepare(" $upd_stmt = Database::prepare("
UPDATE `" . TABLE_PANEL_DOMAINS . "` SET UPDATE `" . TABLE_PANEL_DOMAINS . "` SET
@@ -513,12 +499,8 @@ class Dns
array_unshift($zonerecords, $soa_record); array_unshift($zonerecords, $soa_record);
} }
$zone = new DnsZone( $zone = new DnsZone((int)Settings::Get('system.defaultttl'), $domain['domain'], $domain['bindserial'],
(int)Settings::Get('system.defaultttl'), $zonerecords);
$domain['domain'],
$domain['bindserial'],
$zonerecords
);
return $zone; return $zone;
} }
@@ -545,11 +527,43 @@ class Dns
{ {
$zone_dkim = []; $zone_dkim = [];
if (Settings::Get('antispam.activated') == '1' && $domain['dkim'] == '1' && $domain['dkim_pubkey'] != '') { if (Settings::Get('dkim.use_dkim') == '1' && $domain['dkim'] == '1' && $domain['dkim_pubkey'] != '') {
// start // start
$dkim_txt = 'v=DKIM1;'; $dkim_txt = 'v=DKIM1;';
// algorithm
$algorithm = explode(',', Settings::Get('dkim.dkim_algorithm'));
$alg = '';
foreach ($algorithm as $a) {
if ($a == 'all') {
break;
} else {
$alg .= $a . ':';
}
}
if ($alg != '') {
$alg = substr($alg, 0, -1);
$dkim_txt .= 'h=' . $alg . ';';
}
// notes
if (trim(Settings::Get('dkim.dkim_notes') != '')) {
$dkim_txt .= 'n=' . trim(Settings::Get('dkim.dkim_notes')) . ';';
}
// key // key
$dkim_txt .= 'k=rsa;p=' . trim($domain['dkim_pubkey']) . ';'; $dkim_txt .= 'k=rsa;p=' . trim(preg_replace('/-----BEGIN PUBLIC KEY-----(.+)-----END PUBLIC KEY-----/s',
'$1', str_replace("\n", '', $domain['dkim_pubkey']))) . ';';
// service-type
if (Settings::Get('dkim.dkim_servicetype') == '1') {
$dkim_txt .= 's=email;';
}
// end-part
$dkim_txt .= 't=s';
// dkim-entry // dkim-entry
$zone_dkim[] = $dkim_txt; $zone_dkim[] = $dkim_txt;
} }

View File

@@ -1,77 +0,0 @@
<?php
/**
* This file is part of the Froxlor project.
* Copyright (c) 2010 the Froxlor Team (see authors).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can also view it online at
* https://files.froxlor.org/misc/COPYING.txt
*
* @copyright the authors
* @author Froxlor team <team@froxlor.org>
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
*/
namespace Froxlor;
use Exception;
/**
* Class to manage the current user / session
*/
class ErrorBag
{
/**
* returns whether there are errors stored
*
* @return bool
*/
public static function hasErrors(): bool
{
return !empty($_SESSION) && !empty($_SESSION['_errors']);
}
/**
* add error
*
* @param string $data
*
* @return void
*/
public static function addError(string $data): void
{
if (!isset($_SESSION['_errors']) || !is_array($_SESSION['_errors'])) {
$_SESSION['_errors'] = [];
}
$_SESSION['_errors'][] = $data;
}
/**
* Return errors and clear session
*
* @return array
* @throws Exception
*/
public static function getErrors(): array
{
$errors = $_SESSION['_errors'] ?? [];
unset($_SESSION['_errors']);
if (Settings::Config('display_php_errors')) {
return $errors;
}
return [];
}
}

View File

@@ -31,15 +31,15 @@ final class Froxlor
{ {
// Main version variable // Main version variable
const VERSION = '2.2.0-rc2'; const VERSION = '2.1.8';
// Database version (YYYYMMDDC where C is a daily counter) // Database version (YYYYMMDDC where C is a daily counter)
const DBVERSION = '202407200'; const DBVERSION = '202312120';
// Distribution branding-tag (used for Debian etc.) // Distribution branding-tag (used for Debian etc.)
const BRANDING = ''; const BRANDING = '';
const DOCS_URL = 'https://docs.froxlor.org'; const DOCS_URL = 'https://docs.froxlor.org/v2.1/';
/** /**
* return path to where froxlor is installed, e.g. * return path to where froxlor is installed, e.g.
@@ -52,14 +52,6 @@ final class Froxlor
return dirname(__DIR__, 2) . '/'; return dirname(__DIR__, 2) . '/';
} }
public static function getDocsUrl(): string
{
if (preg_match('/(.+)-(dev|beta|rc)\d+$/', self::VERSION)) {
return self::DOCS_URL . '/dev/';
}
return self::DOCS_URL . '/v' . self::getShortVersion() . '/';
}
/** /**
* return basic version * return basic version
* *
@@ -70,16 +62,6 @@ final class Froxlor
return self::VERSION; return self::VERSION;
} }
/**
* return short basic version
*
* @return string
*/
public static function getShortVersion(): string
{
return explode(".", self::VERSION)[0] . '.' . explode(".", self::VERSION)[1];
}
/** /**
* return version + branding and database-version * return version + branding and database-version
* *

View File

@@ -175,9 +175,6 @@ class FroxlorLogger
$this->initMonolog(); $this->initMonolog();
} }
// clean log-text
$text = preg_replace("/[^\w @#\"':.,()\[\]+\-_\/\\\!]/i", "_", $text);
if (self::$crondebug_flag || ($action == FroxlorLogger::CRON_ACTION && $type <= LOG_WARNING)) { if (self::$crondebug_flag || ($action == FroxlorLogger::CRON_ACTION && $type <= LOG_WARNING)) {
echo "[" . $this->getLogLevelDesc($type) . "] " . $text . PHP_EOL; echo "[" . $this->getLogLevelDesc($type) . "] " . $text . PHP_EOL;
} }

View File

@@ -327,7 +327,7 @@ class Install
if (!preg_match('/^[^\r\n\t\f\0]*$/D', $name)) { if (!preg_match('/^[^\r\n\t\f\0]*$/D', $name)) {
throw new Exception(lng('error.stringformaterror', ['admin_name'])); throw new Exception(lng('error.stringformaterror', ['admin_name']));
} elseif (empty(trim($loginname)) || !preg_match('/^[a-z][a-z0-9]+$/Di', $loginname)) { } elseif (empty(trim($loginname)) || !preg_match('/^[a-z][a-z0-9]+$/', $loginname)) {
throw new Exception(lng('error.loginnameiswrong', [$loginname])); throw new Exception(lng('error.loginnameiswrong', [$loginname]));
} elseif (empty(trim($email)) || !Validate::validateEmail($email)) { } elseif (empty(trim($email)) || !Validate::validateEmail($email)) {
throw new Exception(lng('error.emailiswrong', [$email])); throw new Exception(lng('error.emailiswrong', [$email]));

View File

@@ -115,7 +115,7 @@ class Core
// create entries // create entries
$this->doDataEntries($pdo); $this->doDataEntries($pdo);
// create JSON array for config-services // create JSON array for config-services
$this->createJsonArray($pdo); $this->createJsonArray();
if ($create_ud_str) { if ($create_ud_str) {
$this->createUserdataParamStr(); $this->createUserdataParamStr();
} }
@@ -176,19 +176,15 @@ class Core
$filename = "/tmp/froxlor_backup_" . date('YmdHi') . ".sql"; $filename = "/tmp/froxlor_backup_" . date('YmdHi') . ".sql";
// look for mysqldump // look for mysqldump
$section = 'mysqldump';
if (file_exists("/usr/bin/mysqldump")) { if (file_exists("/usr/bin/mysqldump")) {
$mysql_dump = '/usr/bin/mysqldump'; $mysql_dump = '/usr/bin/mysqldump';
} elseif (file_exists("/usr/local/bin/mysqldump")) { } elseif (file_exists("/usr/local/bin/mysqldump")) {
$mysql_dump = '/usr/local/bin/mysqldump'; $mysql_dump = '/usr/local/bin/mysqldump';
} elseif (file_exists("/usr/bin/mariadb-dump")) {
$mysql_dump = '/usr/bin/mariadb-dump';
$section = 'mariadb-dump';
} }
// create temporary .cnf file // create temporary .cnf file
$cnffilename = "/tmp/froxlor_dump.cnf"; $cnffilename = "/tmp/froxlor_dump.cnf";
$dumpcnf = "[".$section."]" . PHP_EOL . "password=\"" . $this->validatedData['mysql_root_pass'] . "\"" . PHP_EOL; $dumpcnf = "[mysqldump]" . PHP_EOL . "password=\"" . $this->validatedData['mysql_root_pass'] . "\"" . PHP_EOL;
file_put_contents($cnffilename, $dumpcnf); file_put_contents($cnffilename, $dumpcnf);
// make the backup // make the backup
@@ -199,7 +195,7 @@ class Core
@unlink($cnffilename); @unlink($cnffilename);
if (stristr(implode(" ", $output), "error")) { if (stristr(implode(" ", $output), "error")) {
throw new Exception(lng('install.errors.mysqldump_backup_failed')); throw new Exception(lng('install.errors.mysqldump_backup_failed'));
} elseif (!file_exists($filename)) { } else if (!file_exists($filename)) {
throw new Exception(lng('install.errors.sql_backup_file_missing')); throw new Exception(lng('install.errors.sql_backup_file_missing'));
} }
} else { } else {
@@ -383,7 +379,7 @@ class Core
$this->updateSetting($upd_stmt, 1, 'system', 'leenabled'); $this->updateSetting($upd_stmt, 1, 'system', 'leenabled');
$this->updateSetting($upd_stmt, 1, 'system', 'le_froxlor_enabled'); $this->updateSetting($upd_stmt, 1, 'system', 'le_froxlor_enabled');
} }
$this->updateSetting($upd_stmt, strtolower($this->validatedData['servername']), 'system', 'hostname'); $this->updateSetting($upd_stmt, $this->validatedData['servername'], 'system', 'hostname');
$this->updateSetting($upd_stmt, 'en', 'panel', 'standardlanguage'); // TODO: set language $this->updateSetting($upd_stmt, 'en', 'panel', 'standardlanguage'); // TODO: set language
$this->updateSetting($upd_stmt, $this->validatedData['mysql_access_host'], 'system', 'mysql_access_host'); $this->updateSetting($upd_stmt, $this->validatedData['mysql_access_host'], 'system', 'mysql_access_host');
$this->updateSetting($upd_stmt, $this->validatedData['webserver'], 'system', 'webserver'); $this->updateSetting($upd_stmt, $this->validatedData['webserver'], 'system', 'webserver');
@@ -435,14 +431,23 @@ class Core
// check currently used php version and set values of fpm/fcgid accordingly // check currently used php version and set values of fpm/fcgid accordingly
if (defined('PHP_MAJOR_VERSION') && defined('PHP_MINOR_VERSION')) { if (defined('PHP_MAJOR_VERSION') && defined('PHP_MINOR_VERSION')) {
// php-fpm // gentoo specific
$reload = "service php" . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION . "-fpm restart"; if ($this->validatedData['distribution'] == 'gentoo') {
$config_dir = "/etc/php/" . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION . "/fpm/pool.d/"; // php-fpm
// fcgid $reload = "/etc/init.d/php-fpm restart";
if ($this->validatedData['distribution'] == 'bookworm') { $config_dir = "/etc/php/fpm-php" . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION . "/fpm.d/";
$binary = "/usr/bin/php-cgi" . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION; // fcgid
$binary = "/usr/bin/php-cgi";
} else { } else {
$binary = "/usr/bin/php" . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION . "-cgi"; // php-fpm
$reload = "service php" . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION . "-fpm restart";
$config_dir = "/etc/php/" . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION . "/fpm/pool.d/";
// fcgid
if ($this->validatedData['distribution'] == 'bookworm') {
$binary = "/usr/bin/php-cgi" . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION;
} else {
$binary = "/usr/bin/php" . PHP_MAJOR_VERSION . "." . PHP_MINOR_VERSION . "-cgi";
}
} }
$db_user->query("UPDATE `" . TABLE_PANEL_FPMDAEMONS . "` SET `reload_cmd` = '" . $reload . "', `config_dir` = '" . $config_dir . "' WHERE `id` ='1';"); $db_user->query("UPDATE `" . TABLE_PANEL_FPMDAEMONS . "` SET `reload_cmd` = '" . $reload . "', `config_dir` = '" . $config_dir . "' WHERE `id` ='1';");
$db_user->query("UPDATE `" . TABLE_PANEL_PHPCONFIGS . "` SET `binary` = '" . $binary . "';"); $db_user->query("UPDATE `" . TABLE_PANEL_PHPCONFIGS . "` SET `binary` = '" . $binary . "';");
@@ -655,20 +660,9 @@ class Core
@umask($umask); @umask($umask);
} }
private function createJsonArray(&$db_user) private function createJsonArray()
{ {
// use traffic analyzer and ftpserver from settings as we could define defaults in the lib/configfiles/*.xml templates $system_params = ["cron", "libnssextrausers", "logrotate", "goaccess"];
// which can be useful for third-party package-maintainer (e.g. other distros) to have more control
// over the installation defaults (less hardcoded values)
$custom_dependency = $db_user->query("
SELECT `varname`, `value` FROM `" . TABLE_PANEL_SETTINGS . "`
WHERE `settinggroup` = 'system' AND (`varname` = 'traffictool' OR `varname` = 'ftpserver')
");
$cd_result = $custom_dependency->fetchAll(\PDO::FETCH_KEY_PAIR);
$system_params = ["cron", "libnssextrausers", "logrotate"];
if (isset($cd_result['traffictool'])) {
$system_params[] = $cd_result['traffictool'];
}
if ($this->validatedData['webserver_backend'] == 'php-fpm') { if ($this->validatedData['webserver_backend'] == 'php-fpm') {
$system_params[] = 'php-fpm'; $system_params[] = 'php-fpm';
} elseif ($this->validatedData['webserver_backend'] == 'fcgid') { } elseif ($this->validatedData['webserver_backend'] == 'fcgid') {
@@ -680,8 +674,7 @@ class Core
'http' => $this->validatedData['webserver'], 'http' => $this->validatedData['webserver'],
'smtp' => 'postfix_dovecot', 'smtp' => 'postfix_dovecot',
'mail' => 'dovecot_postfix2', 'mail' => 'dovecot_postfix2',
'antispam' => 'rspamd', 'ftp' => 'proftpd',
'ftp' => $cd_result['ftpserver'] ?? 'x',
'system' => $system_params 'system' => $system_params
]; ];
$_SESSION['installation']['json_params'] = json_encode($json_params); $_SESSION['installation']['json_params'] = json_encode($json_params);

View File

@@ -25,7 +25,6 @@
namespace Froxlor\Install; namespace Froxlor\Install;
use Froxlor\FileDir;
use Froxlor\Froxlor; use Froxlor\Froxlor;
use Froxlor\FroxlorLogger; use Froxlor\FroxlorLogger;
use Froxlor\Settings; use Froxlor\Settings;
@@ -86,7 +85,7 @@ class Update
self::$update_tasks[self::$task_counter]['result'] = 1; self::$update_tasks[self::$task_counter]['result'] = 1;
break; break;
default: default:
self::$update_tasks[self::$task_counter]['result'] = -1; self::$update_tasks[self::$task_counter]['result'] = -1;
break; break;
} }
@@ -137,36 +136,4 @@ class Update
{ {
return self::$task_counter; return self::$task_counter;
} }
public static function cleanOldFiles(array $to_clean)
{
self::showUpdateStep("Cleaning up old files");
$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) {
self::lastStepStatus(0);
} else {
if (empty($del_list)) {
// none of the files existed
self::lastStepStatus(0);
} else {
self::lastStepStatus(
1,
'manual commands needed',
'Please run the following commands manually:<br><pre>' . $del_list . '</pre>'
);
}
}
}
} }

View File

@@ -34,6 +34,27 @@ use voku\helper\AntiXSS;
class PhpHelper class PhpHelper
{ {
private static $sort_key = 'id';
private static $sort_type = SORT_STRING;
/**
* sort an array by either natural or string sort and a given index where the value for comparison is found
*
* @param array $list
* @param string $key
*
* @return bool
*/
public static function sortListBy(array &$list, string $key = 'id'): bool
{
self::$sort_type = Settings::Get('panel.natsorting') == 1 ? SORT_NATURAL : SORT_STRING;
self::$sort_key = $key;
return usort($list, [
'self',
'sortListByGivenKey'
]);
}
/** /**
* Wrapper around htmlentities to handle arrays, with the advantage that you * Wrapper around htmlentities to handle arrays, with the advantage that you
* can select which fields should be handled by htmlentities * can select which fields should be handled by htmlentities
@@ -80,6 +101,35 @@ class PhpHelper
}); });
} }
/**
* Replaces Strings in an array, with the advantage that you
* can select which fields should be str_replace'd
*
* @param string|array $search String or array of strings to search for
* @param string|array $replace String or array to replace with
* @param string|array $subject String or array The subject array
* @param string|array $fields string The fields which should be checked for, separated by spaces
*
* @return string|array The str_replace'd array
*/
public static function strReplaceArray($search, $replace, $subject, $fields = '')
{
if (is_array($subject)) {
if (!is_array($fields)) {
$fields = self::arrayTrim(explode(' ', $fields));
}
foreach ($subject as $field => $value) {
if ((!is_array($fields) || empty($fields)) || (in_array($field, $fields))) {
$subject[$field] = str_replace($search, $replace, $value);
}
}
} else {
$subject = str_replace($search, $replace, $subject);
}
return $subject;
}
/** /**
* froxlor php error handler * froxlor php error handler
* *
@@ -120,8 +170,9 @@ class PhpHelper
$err_display .= '</pre></p>'; $err_display .= '</pre></p>';
// end later // end later
$err_display .= '</div>'; $err_display .= '</div>';
// set errors to session // check for more existing errors
ErrorBag::addError($err_display); $errors = isset(UI::twig()->getGlobals()['global_errors']) ? UI::twig()->getGlobals()['global_errors'] : "";
UI::twig()->addGlobal('global_errors', $errors . $err_display);
// return true to ignore php standard error-handler // return true to ignore php standard error-handler
return true; return true;
} }
@@ -287,8 +338,7 @@ class PhpHelper
?string $max = '', ?string $max = '',
string $system = 'si', string $system = 'si',
string $retstring = '%01.2f %s' string $retstring = '%01.2f %s'
): string ): string {
{
// Pick units // Pick units
$systems = [ $systems = [
'si' => [ 'si' => [
@@ -371,12 +421,8 @@ class PhpHelper
array $haystack, array $haystack,
array &$keys = [], array &$keys = [],
string $currentKey = '' string $currentKey = ''
): bool ): bool {
{
foreach ($haystack as $key => $value) { foreach ($haystack as $key => $value) {
if (empty($value)) {
continue;
}
$pathkey = empty($currentKey) ? $key : $currentKey . '.' . $key; $pathkey = empty($currentKey) ? $key : $currentKey . '.' . $key;
if (is_array($value)) { if (is_array($value)) {
self::recursive_array_search($needle, $value, $keys, $pathkey); self::recursive_array_search($needle, $value, $keys, $pathkey);
@@ -420,9 +466,6 @@ class PhpHelper
'admin_pass', 'admin_pass',
'admin_pass_confirm', 'admin_pass_confirm',
'panel_password_special_char', 'panel_password_special_char',
'old_password',
'new_password',
'new_password_confirm',
]; ];
if (!empty($global)) { if (!empty($global)) {
$tmp = $global; $tmp = $global;
@@ -434,6 +477,19 @@ class PhpHelper
} }
} }
/**
* @param array $a
* @param array $b
* @return int
*/
private static function sortListByGivenKey(array $a, array $b): int
{
if (self::$sort_type == SORT_NATURAL) {
return strnatcasecmp($a[self::$sort_key], $b[self::$sort_key]);
}
return strcasecmp($a[self::$sort_key], $b[self::$sort_key]);
}
/** /**
* Generate php file from array. * Generate php file from array.
* *

View File

@@ -25,7 +25,6 @@
namespace Froxlor; namespace Froxlor;
use Exception;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use PDO; use PDO;
use PDOStatement; use PDOStatement;
@@ -132,12 +131,11 @@ class Settings
self::$conf = [ self::$conf = [
'enable_webupdate' => false, 'enable_webupdate' => false,
'disable_otp_security_check' => false, 'disable_otp_security_check' => false,
'display_php_errors' => false,
]; ];
$configfile = Froxlor::getInstallDir() . '/lib/config.inc.php'; $configfile = Froxlor::getInstallDir() . '/lib/config.inc.php';
if (@file_exists($configfile) && is_readable($configfile)) { if (@file_exists($configfile) && is_readable($configfile)) {
self::$conf = array_merge(self::$conf, include $configfile); self::$conf = include $configfile;
} }
return true; return true;
} }
@@ -332,7 +330,7 @@ class Settings
} }
} }
public static function getAll(): array public static function getAll() : array
{ {
self::init(); self::init();
return self::$data; return self::$data;
@@ -340,14 +338,17 @@ class Settings
/** /**
* get value from config by identifier * get value from config by identifier
* @throws Exception
*/ */
public static function Config(string $config) public static function Config(string $config)
{ {
self::init(); self::init();
$result = self::$conf[$config] ?? null; $sstr = explode(".", $config);
if (is_null($result)) { $result = self::$conf;
throw new Exception('Unknown local config name "' . $config . '"'); foreach ($sstr as $key) {
$result = $result[$key] ?? null;
if (empty($result)) {
break;
}
} }
return $result; return $result;
} }

View File

@@ -36,7 +36,6 @@ use Froxlor\PhpHelper;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\System\Cronjob; use Froxlor\System\Cronjob;
use Froxlor\System\IPTools; use Froxlor\System\IPTools;
use Froxlor\UI\Request;
use Froxlor\Validate\Validate; use Froxlor\Validate\Validate;
use PDO; use PDO;
@@ -226,17 +225,6 @@ class Store
return $returnvalue; return $returnvalue;
} }
public static function storeSettingFieldInsertAntispamTask($fieldname, $fielddata, $newfieldvalue)
{
// first save the setting itself
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
if ($returnvalue !== false) {
Cronjob::inserttask(TaskId::REBUILD_RSPAMD);
}
return $returnvalue;
}
public static function storeSettingHostname($fieldname, $fielddata, $newfieldvalue) public static function storeSettingHostname($fieldname, $fielddata, $newfieldvalue)
{ {
$returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue); $returnvalue = self::storeSettingField($fieldname, $fielddata, $newfieldvalue);
@@ -466,7 +454,7 @@ class Store
} }
// Delete file? // Delete file?
if ($fielddata['value'] !== "" && array_key_exists($fieldname . '_delete', $_POST) && Request::post($fieldname . '_delete')) { if ($fielddata['value'] !== "" && array_key_exists($fieldname . '_delete', $_POST) && $_POST[$fieldname . '_delete']) {
@unlink(Froxlor::getInstallDir() . '/' . explode('?', $fielddata['value'], 2)[0]); @unlink(Froxlor::getInstallDir() . '/' . explode('?', $fielddata['value'], 2)[0]);
$save_to = ''; $save_to = '';
} }

View File

@@ -134,15 +134,11 @@ class Cronjob
INSERT INTO `" . TABLE_PANEL_TASKS . "` SET `type` = :type, `data` = :data INSERT INTO `" . TABLE_PANEL_TASKS . "` SET `type` = :type, `data` = :data
"); ");
if ($type == TaskId::REBUILD_VHOST || $type == TaskId::REBUILD_DNS || $type == TaskId::CREATE_FTP || $type == TaskId::REBUILD_RSPAMD || $type == TaskId::CREATE_QUOTA || $type == TaskId::REBUILD_CRON) { if ($type == TaskId::REBUILD_VHOST || $type == TaskId::REBUILD_DNS || $type == TaskId::CREATE_FTP || $type == TaskId::CREATE_QUOTA || $type == TaskId::REBUILD_CRON) {
// 4 = bind -> if bind disabled -> no task // 4 = bind -> if bind disabled -> no task
if ($type == TaskId::REBUILD_DNS && Settings::Get('system.bind_enable') == '0') { if ($type == TaskId::REBUILD_DNS && Settings::Get('system.bind_enable') == '0') {
return; return;
} }
// 9 = rspamd -> if antispam disabled -> no task
if ($type == TaskId::REBUILD_RSPAMD && Settings::Get('antispam.activated') == '0') {
return;
}
// 10 = quota -> if quota disabled -> no task // 10 = quota -> if quota disabled -> no task
if ($type == TaskId::CREATE_QUOTA && Settings::Get('system.diskquota_enabled') == '0') { if ($type == TaskId::CREATE_QUOTA && Settings::Get('system.diskquota_enabled') == '0') {
return; return;
@@ -183,7 +179,7 @@ class Cronjob
} elseif ($type == TaskId::DELETE_EMAIL_DATA && count($params) == 2 && $params[0] != '' && $params[1] != '') { } elseif ($type == TaskId::DELETE_EMAIL_DATA && count($params) == 2 && $params[0] != '' && $params[1] != '') {
$data = []; $data = [];
$data['loginname'] = $params[0]; $data['loginname'] = $params[0];
$data['emailpath'] = $params[1]; $data['email'] = $params[1];
$data = json_encode($data); $data = json_encode($data);
Database::pexecute($ins_stmt, [ Database::pexecute($ins_stmt, [
'type' => TaskId::DELETE_EMAIL_DATA, 'type' => TaskId::DELETE_EMAIL_DATA,

View File

@@ -42,7 +42,7 @@ class Traffic
{ {
$trafficCollectionObj = (new Collection(TrafficAPI::class, $userinfo, $trafficCollectionObj = (new Collection(TrafficAPI::class, $userinfo,
self::getParamsByRange($range, ['customer_traffic' => true]))); self::getParamsByRange($range, ['customer_traffic' => true])));
if (($userinfo['adminsession'] ?? 0) == 1) { if ($userinfo['adminsession'] == 1) {
$trafficCollectionObj->has('customer', Customers::class, 'customerid', 'customerid'); $trafficCollectionObj->has('customer', Customers::class, 'customerid', 'customerid');
} }
$trafficCollection = $trafficCollectionObj->get(); $trafficCollection = $trafficCollectionObj->get();
@@ -58,17 +58,8 @@ class Traffic
$mail = $item['mail']; $mail = $item['mail'];
$total = $http + $ftp + $mail; $total = $http + $ftp + $mail;
if (empty($users[$item['customerid']])) {
$users[$item['customerid']] = [
'total' => 0.00,
'http' => 0.00,
'ftp' => 0.00,
'mail' => 0.00,
];
}
// per user total // per user total
if (($userinfo['adminsession'] ?? 0) == 1) { if ($userinfo['adminsession'] == 1) {
$users[$item['customerid']]['loginname'] = $item['customer']['loginname']; $users[$item['customerid']]['loginname'] = $item['customer']['loginname'];
} }
$users[$item['customerid']]['total'] += $total; $users[$item['customerid']]['total'] += $total;
@@ -76,30 +67,6 @@ class Traffic
$users[$item['customerid']]['ftp'] += $ftp; $users[$item['customerid']]['ftp'] += $ftp;
$users[$item['customerid']]['mail'] += $mail; $users[$item['customerid']]['mail'] += $mail;
if (!$overview) { if (!$overview) {
if (empty($years[$item['year']])) {
$years[$item['year']] = [
'total' => 0.00,
'http' => 0.00,
'ftp' => 0.00,
'mail' => 0.00,
];
}
if (empty($months[$item['month'] . '/' . $item['year']])) {
$months[$item['month'] . '/' . $item['year']] = [
'total' => 0.00,
'http' => 0.00,
'ftp' => 0.00,
'mail' => 0.00,
];
}
if (empty($days[$item['day'] . '.' . $item['month'] . '.' . $item['year']])) {
$days[$item['day'] . '.' . $item['month'] . '.' . $item['year']] = [
'total' => 0.00,
'http' => 0.00,
'ftp' => 0.00,
'mail' => 0.00,
];
}
// per year // per year
$years[$item['year']]['total'] += $total; $years[$item['year']]['total'] += $total;
$years[$item['year']]['http'] += $http; $years[$item['year']]['http'] += $http;
@@ -119,12 +86,7 @@ class Traffic
} }
// calculate overview for given range from users // calculate overview for given range from users
$metrics = [ $metrics = [];
'total' => 0.00,
'http' => 0.00,
'ftp' => 0.00,
'mail' => 0.00,
];
foreach ($users as $user) { foreach ($users as $user) {
$metrics['total'] += $user['total']; $metrics['total'] += $user['total'];
$metrics['http'] += $user['http']; $metrics['http'] += $user['http'];

View File

@@ -34,36 +34,23 @@ use Froxlor\UI\Panel\UI;
class Domain class Domain
{ {
public static function domainEditLink(array $attributes): array public static function domainLink(array $attributes)
{ {
$linker = UI::getLinker(); return '<a href="https://' . $attributes['data'] . '" target="_blank">' . $attributes['data'] . '</a>';
return [
'macro' => 'link',
'data' => [
'text' => $attributes['data'],
'href' => $linker->getLink([
'section' => 'domains',
'page' => 'domains',
'action' => 'edit',
'id' => $attributes['fields']['id'],
]),
'target' => '_blank'
]
];
} }
public static function domainWithCustomerLink(array $attributes): string public static function domainWithCustomerLink(array $attributes)
{ {
$linker = UI::getLinker(); $linker = UI::getLinker();
$result = '<a href="https://' . $attributes['data'] . '" target="_blank">' . $attributes['data'] . '</a>'; $result = '<a href="https://' . $attributes['data'] . '" target="_blank">' . $attributes['data'] . '</a>';
if ((int)UI::getCurrentUser()['adminsession'] == 1 && $attributes['fields']['customerid']) { if ((int)UI::getCurrentUser()['adminsession'] == 1 && $attributes['fields']['customerid']) {
$result .= ' (<a href="' . $linker->getLink([ $result .= ' (<a href="' . $linker->getLink([
'section' => 'customers', 'section' => 'customers',
'page' => 'customers', 'page' => 'customers',
'action' => 'su', 'action' => 'su',
'sort' => $attributes['fields']['loginname'], 'sort' => $attributes['fields']['loginname'],
'id' => $attributes['fields']['customerid'], 'id' => $attributes['fields']['customerid'],
]) . '">' . $attributes['fields']['loginname'] . '</a>)'; ]) . '">' . $attributes['fields']['loginname'] . '</a>)';
} }
return $result; return $result;
} }
@@ -74,9 +61,6 @@ class Domain
if ($attributes['fields']['deactivated']) { if ($attributes['fields']['deactivated']) {
return lng('admin.deactivated'); return lng('admin.deactivated');
} }
if ($attributes['fields']['email_only']) {
return lng('domains.email_only');
}
// path or redirect // path or redirect
if (preg_match('/^https?\:\/\//', $attributes['fields']['documentroot'])) { if (preg_match('/^https?\:\/\//', $attributes['fields']['documentroot'])) {
return [ return [
@@ -125,12 +109,12 @@ class Domain
public static function canEdit(array $attributes): bool public static function canEdit(array $attributes): bool
{ {
return $attributes['fields']['caneditdomain'] && !$attributes['fields']['deactivated']; return (bool)($attributes['fields']['caneditdomain'] && !$attributes['fields']['deactivated']);
} }
public static function canViewLogs(array $attributes): bool public static function canViewLogs(array $attributes): bool
{ {
if ((int)$attributes['fields']['email_only'] == 0 && !$attributes['fields']['deactivated']) { if ((!CurrentUser::isAdmin() || (CurrentUser::isAdmin() && (int)$attributes['fields']['email_only'] == 0)) && !$attributes['fields']['deactivated']) {
if ((int)UI::getCurrentUser()['adminsession'] == 0 && (bool)UI::getCurrentUser()['logviewenabled']) { if ((int)UI::getCurrentUser()['adminsession'] == 0 && (bool)UI::getCurrentUser()['logviewenabled']) {
return true; return true;
} elseif ((int)UI::getCurrentUser()['adminsession'] == 1) { } elseif ((int)UI::getCurrentUser()['adminsession'] == 1) {
@@ -160,7 +144,6 @@ class Domain
&& $attributes['fields']['caneditdomain'] == '1' && $attributes['fields']['caneditdomain'] == '1'
&& Settings::Get('system.bind_enable') == '1' && Settings::Get('system.bind_enable') == '1'
&& Settings::Get('system.dnsenabled') == '1' && Settings::Get('system.dnsenabled') == '1'
&& !$attributes['fields']['email_only']
&& !$attributes['fields']['deactivated']; && !$attributes['fields']['deactivated'];
} }
@@ -173,19 +156,17 @@ class Domain
public static function hasLetsEncryptActivated(array $attributes): bool public static function hasLetsEncryptActivated(array $attributes): bool
{ {
return ((bool)$attributes['fields']['letsencrypt'] && (int)$attributes['fields']['email_only'] == 0); return ((bool)$attributes['fields']['letsencrypt'] && (!CurrentUser::isAdmin() || (CurrentUser::isAdmin() && (int)$attributes['fields']['email_only'] == 0)));
} }
/**
* @throws \Exception
*/
public static function canEditSSL(array $attributes): bool public static function canEditSSL(array $attributes): bool
{ {
if (Settings::Get('system.use_ssl') == '1' if (
Settings::Get('system.use_ssl') == '1'
&& DDomain::domainHasSslIpPort($attributes['fields']['id']) && DDomain::domainHasSslIpPort($attributes['fields']['id'])
&& (CurrentUser::isAdmin() || (!CurrentUser::isAdmin() && (int)$attributes['fields']['caneditdomain'] == 1)) && (int)$attributes['fields']['caneditdomain'] == 1
&& (int)$attributes['fields']['letsencrypt'] == 0 && (int)$attributes['fields']['letsencrypt'] == 0
&& !(int)$attributes['fields']['email_only'] && (!CurrentUser::isAdmin() || (CurrentUser::isAdmin() && (int)$attributes['fields']['email_only'] == 0))
&& !$attributes['fields']['deactivated'] && !$attributes['fields']['deactivated']
) { ) {
return true; return true;
@@ -216,15 +197,15 @@ class Domain
], ],
]; ];
// specified certificate for domain
if ($attributes['fields']['domain_hascert'] == 1) { if ($attributes['fields']['domain_hascert'] == 1) {
// specified certificate for domain
$result['icon'] .= ' text-success'; $result['icon'] .= ' text-success';
} elseif ($attributes['fields']['domain_hascert'] == 2) { } // shared certificates (e.g. subdomain of domain where certificate is specified)
// shared certificates (e.g. subdomain of domain where certificate is specified) elseif ($attributes['fields']['domain_hascert'] == 2) {
$result['icon'] .= ' text-warning'; $result['icon'] .= ' text-warning';
$result['title'] .= "\n" . lng('panel.ssleditor_infoshared'); $result['title'] .= "\n" . lng('panel.ssleditor_infoshared');
} elseif ($attributes['fields']['domain_hascert'] == 0) { } // no certificate specified, using global fallbacks (IPs and Ports or if empty SSL settings)
// no certificate specified, using global fallbacks (IPs and Ports or if empty SSL settings) elseif ($attributes['fields']['domain_hascert'] == 0) {
$result['icon'] .= ' text-danger'; $result['icon'] .= ' text-danger';
$result['title'] .= "\n" . lng('panel.ssleditor_infoglobal'); $result['title'] .= "\n" . lng('panel.ssleditor_infoglobal');
} }
@@ -236,19 +217,16 @@ class Domain
public static function listIPs(array $attributes): string public static function listIPs(array $attributes): string
{ {
if (!empty($attributes['fields']['ipsandports'])) { if (isset($attributes['fields']['ipsandports']) && !empty($attributes['fields']['ipsandports'])) {
$iplist = ""; $iplist = "";
foreach ($attributes['fields']['ipsandports'] as $ipport) { foreach ($attributes['fields']['ipsandports'] as $ipport) {
$iplist .= $ipport['ip'] . ':' . $ipport['port'] . '<br>'; $iplist .= $ipport['ip'] . ':' . $ipport['port'] . '<br>';
} }
return $iplist; return $iplist;
} }
return lng('panel.listing_empty'); return lng('panel.empty');
} }
/**
* @throws \Exception
*/
public static function getPhpConfigName(array $attributes): string public static function getPhpConfigName(array $attributes): string
{ {
$sel_stmt = Database::prepare("SELECT `description` FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id"); $sel_stmt = Database::prepare("SELECT `description` FROM `" . TABLE_PANEL_PHPCONFIGS . "` WHERE `id` = :id");
@@ -256,11 +234,11 @@ class Domain
if ((int)UI::getCurrentUser()['adminsession'] == 1) { if ((int)UI::getCurrentUser()['adminsession'] == 1) {
$linker = UI::getLinker(); $linker = UI::getLinker();
$result = '<a href="' . $linker->getLink([ $result = '<a href="' . $linker->getLink([
'section' => 'phpsettings', 'section' => 'phpsettings',
'page' => 'overview', 'page' => 'overview',
'searchfield' => 'c.id', 'searchfield' => 'c.id',
'searchtext' => $attributes['data'], 'searchtext' => $attributes['data'],
]) . '">' . $phpconfig['description'] . '</a>'; ]) . '">' . $phpconfig['description'] . '</a>';
} else { } else {
$result = $phpconfig['description']; $result = $phpconfig['description'];
} }

View File

@@ -52,14 +52,6 @@ class Text
]; ];
} }
public static function type2fa(array $attributes): array
{
return [
'macro' => 'type2fa',
'data' => (int)$attributes['data']
];
}
public static function customerfullname(array $attributes): string public static function customerfullname(array $attributes): string
{ {
return User::getCorrectFullUserDetails($attributes['fields'], true); return User::getCorrectFullUserDetails($attributes['fields'], true);

View File

@@ -273,10 +273,6 @@ class Form
if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) { if (\Froxlor\Validate\Form::validateFieldDefinition($groupdetails)) {
// Check fields for plausibility // Check fields for plausibility
foreach ($groupdetails['fields'] as $fieldname => $fielddetails) { foreach ($groupdetails['fields'] as $fieldname => $fielddetails) {
if (!isset($submitted_fields[$fieldname])) {
// skip unset fields due to unavailability for this system/settings-set
continue;
}
if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) { if (!$only_enabledisable || ($only_enabledisable && isset($fielddetails['overview_option']))) {
if (($plausibility_check = self::checkPlausibilityFormField($fieldname, $fielddetails, $submitted_fields[$fieldname], $submitted_fields)) !== false) { if (($plausibility_check = self::checkPlausibilityFormField($fieldname, $fielddetails, $submitted_fields[$fieldname], $submitted_fields)) !== false) {
if (is_array($plausibility_check) && isset($plausibility_check[0])) { if (is_array($plausibility_check) && isset($plausibility_check[0])) {

View File

@@ -33,9 +33,10 @@ class HTML
/** /**
* Build Navigation Sidebar * Build Navigation Sidebar
* *
* @param array $navigation data * @param
* @param array $userinfo the userinfo of the user * array navigation data
* * @param
* array userinfo the userinfo of the user
* @return array the content of the navigation bar according to user-permissions * @return array the content of the navigation bar according to user-permissions
*/ */
public static function buildNavigation(array $navigation, array $userinfo) public static function buildNavigation(array $navigation, array $userinfo)
@@ -43,19 +44,12 @@ class HTML
$returnvalue = []; $returnvalue = [];
// sanitize user-given input (url-manipulation) // sanitize user-given input (url-manipulation)
$req_page = Request::get('page'); if (isset($_GET['page']) && is_array($_GET['page'])) {
if (!empty($req_page) && is_array($req_page)) { $_GET['page'] = (string)$_GET['page'][0];
$req_page = (string)array_shift($req_page);
} }
// need to preserve this if (isset($_GET['action']) && is_array($_GET['action'])) {
$_GET['page'] = $req_page; $_GET['action'] = (string)$_GET['action'][0];
$req_action = Request::get('action');
if (!empty($req_action) && is_array($req_action)) {
$req_action = (string)array_shift($req_action);
} }
// need to preserve this
$_GET['action'] = $req_action;
foreach ($navigation as $box) { foreach ($navigation as $box) {
if ((!isset($box['show_element']) || $box['show_element'] === true) && (!isset($box['required_resources']) || $box['required_resources'] == '' || (isset($userinfo[$box['required_resources']]) && ((int)$userinfo[$box['required_resources']] > 0 || $userinfo[$box['required_resources']] == '-1')))) { if ((!isset($box['show_element']) || $box['show_element'] === true) && (!isset($box['required_resources']) || $box['required_resources'] == '' || (isset($userinfo[$box['required_resources']]) && ((int)$userinfo[$box['required_resources']] > 0 || $userinfo[$box['required_resources']] == '-1')))) {
@@ -75,7 +69,7 @@ class HTML
} }
if ( if (
((empty($req_page) && substr_count($element['url'], "page=") == 0) || (!empty($req_page) && substr_count($element['url'], "page=" . $req_page) > 0)) ((empty($_GET['page']) && substr_count($element['url'], "page=") == 0) || (isset($_GET['page']) && substr_count($element['url'], "page=" . $_GET['page']) > 0))
&& substr_count($element['url'], basename($_SERVER["SCRIPT_FILENAME"])) > 0 && substr_count($element['url'], basename($_SERVER["SCRIPT_FILENAME"])) > 0
) { ) {
$active = true; $active = true;

View File

@@ -61,12 +61,11 @@ class Pagination
*/ */
public function __construct( public function __construct(
array $fields = [], array $fields = [],
int $total_entries = 0, int $total_entries = 0,
int $perPage = 20, int $perPage = 20,
array $default_sorting = [], array $default_sorting = [],
array $pagination_additional_params = [] array $pagination_additional_params = []
) ) {
{
$this->fields = $fields; $this->fields = $fields;
$this->entries = $total_entries; $this->entries = $total_entries;
$this->perPage = $perPage; $this->perPage = $perPage;
@@ -81,13 +80,12 @@ class Pagination
$orderfields = array_keys($fields); $orderfields = array_keys($fields);
$this->searchfield = $orderfields[0]; $this->searchfield = $orderfields[0];
} }
$searchtext = Request::any('searchtext'); if (isset($_REQUEST['searchtext']) && (preg_match('/[-_@\p{L}\p{N}*.]+$/u',
if (isset($searchtext) && (preg_match('/[-_@\p{L}\p{N}*.]+$/u', $searchtext) || $searchtext === '')) { $_REQUEST['searchtext']) || $_REQUEST['searchtext'] === '')) {
$this->searchtext = trim($searchtext); $this->searchtext = trim($_REQUEST['searchtext']);
} }
$searchfield = Request::any('searchfield'); if (isset($_REQUEST['searchfield']) && isset($fields[$_REQUEST['searchfield']])) {
if (isset($searchfield) && isset($fields[$searchfield])) { $this->searchfield = $_REQUEST['searchfield'];
$this->searchfield = $searchfield;
} }
if (!empty($this->searchtext) && !empty($this->searchfield)) { if (!empty($this->searchtext) && !empty($this->searchfield)) {
$this->addSearch($this->searchtext, $this->searchfield); $this->addSearch($this->searchtext, $this->searchfield);
@@ -96,13 +94,11 @@ class Pagination
} }
// check other ordering requests // check other ordering requests
$sortorder = Request::any('sortorder'); if (isset($_REQUEST['sortorder']) && (strtolower($_REQUEST['sortorder']) == 'desc' || strtolower($_REQUEST['sortorder']) == 'asc')) {
if (!empty($sortorder) && (strtolower($sortorder) == 'desc' || strtolower($sortorder) == 'asc')) { $this->sortorder = strtoupper($_REQUEST['sortorder']);
$this->sortorder = strtoupper($sortorder);
} }
$sortfield = Request::any('sortfield'); if (isset($_REQUEST['sortfield']) && isset($fields[$_REQUEST['sortfield']])) {
if (!empty($sortfield) && isset($fields[$sortfield])) { $this->sortfield = $_REQUEST['sortfield'];
$this->sortfield = $sortfield;
$this->addOrderBy($this->sortfield, $this->sortorder); $this->addOrderBy($this->sortfield, $this->sortorder);
} else { } else {
// add default ordering by given order // add default ordering by given order
@@ -122,9 +118,8 @@ class Pagination
} }
// check current page / pages // check current page / pages
$pageno = Request::any('pageno'); if (isset($_REQUEST['pageno']) && intval($_REQUEST['pageno']) != 0) {
if (!empty($pageno) && intval($pageno) != 0) { $this->pageno = intval($_REQUEST['pageno']);
$this->pageno = intval($pageno);
} }
if (($this->pageno - 1) * Settings::Get('panel.paging') > $this->entries) { if (($this->pageno - 1) * Settings::Get('panel.paging') > $this->entries) {
$this->pageno = 1; $this->pageno = 1;

View File

@@ -30,16 +30,14 @@ use voku\helper\AntiXSS;
class Request class Request
{ {
private static $cleaned = false;
/** /**
* Get key from current $_GET or $_POST request. * Get key from current $_GET or $_POST request.
* *
* @param $key * @param $key
* @param mixed|null $default * @param string|null $default
* @return mixed|string|null * @return mixed|string|null
*/ */
public static function any($key, $default = null) public static function any($key, string $default = null)
{ {
self::cleanAll(); self::cleanAll();
@@ -50,10 +48,10 @@ class Request
* Get key from current $_GET request. * Get key from current $_GET request.
* *
* @param $key * @param $key
* @param mixed|null $default * @param string|null $default
* @return mixed|string|null * @return mixed|string|null
*/ */
public static function get($key, $default = null) public static function get($key, string $default = null)
{ {
self::cleanAll(); self::cleanAll();
@@ -64,56 +62,37 @@ class Request
* Get key from current $_POST request. * Get key from current $_POST request.
* *
* @param $key * @param $key
* @param mixed|null $default * @param string|null $default
* @return mixed|string|null * @return mixed|string|null
*/ */
public static function post($key, $default = null) public static function post($key, string $default = null)
{ {
self::cleanAll(); self::cleanAll();
return $_POST[$key] ?? $default; return $_POST[$key] ?? $default;
} }
/**
* return complete $_POST array
*
* @return array
*/
public static function postAll()
{
self::cleanAll();
return $_POST ?? [];
}
/** /**
* Check for xss attempts and clean important globals and * Check for xss attempts and clean important globals and
* unsetting every variable registered in $_REQUEST and as variable itself * unsetting every variable registered in $_REQUEST and as variable itself
*/ */
public static function cleanAll() public static function cleanAll()
{ {
if (!self::$cleaned) { foreach ($_REQUEST as $key => $value) {
foreach ($_REQUEST as $key => $value) { if (isset($$key)) {
if (isset($$key)) { unset($$key);
unset($$key);
}
} }
unset($value);
$antiXss = new AntiXSS();
$antiXss->addNeverAllowedRegex([
'{{(.*)}}' => ''
]);
// check $_GET
PhpHelper::cleanGlobal($_GET, $antiXss);
// check $_POST
PhpHelper::cleanGlobal($_POST, $antiXss);
// check $_COOKIE
PhpHelper::cleanGlobal($_COOKIE, $antiXss);
self::$cleaned = true;
} }
unset($value);
$antiXss = new AntiXSS();
// check $_GET
PhpHelper::cleanGlobal($_GET, $antiXss);
// check $_POST
PhpHelper::cleanGlobal($_POST, $antiXss);
// check $_COOKIE
PhpHelper::cleanGlobal($_COOKIE, $antiXss);
} }
/** /**

View File

@@ -139,7 +139,7 @@ class Response
exit; exit;
} }
public static function dynamicError($message, bool $nosession = false) public static function dynamicError($message)
{ {
$_SESSION['requestData'] = $_POST; $_SESSION['requestData'] = $_POST;
$link_ref = ''; $link_ref = '';
@@ -147,8 +147,7 @@ class Response
$link_ref = htmlentities($_SERVER['HTTP_REFERER']); $link_ref = htmlentities($_SERVER['HTTP_REFERER']);
} }
$tpl = $nosession ? 'misc/alert_nosession.html.twig' : 'misc/alert.html.twig'; UI::view('misc/alert.html.twig', [
UI::view($tpl, [
'type' => 'danger', 'type' => 'danger',
'btntype' => 'light', 'btntype' => 'light',
'heading' => lng('error.error'), 'heading' => lng('error.error'),

View File

@@ -28,7 +28,6 @@ namespace Froxlor\Validate;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\FileDir; use Froxlor\FileDir;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\UI\Request;
class Check class Check
{ {
@@ -74,7 +73,7 @@ class Check
// interface is to be enabled // interface is to be enabled
if ((int)$newfieldvalue == 1) { if ((int)$newfieldvalue == 1) {
// check for POST value of the other field == 1 (active) // check for POST value of the other field == 1 (active)
if ((int)Request::post($check_array[$fieldname]['other_post_field'], 0) == 1) { if (isset($_POST[$check_array[$fieldname]['other_post_field']]) && (int)$_POST[$check_array[$fieldname]['other_post_field']] == 1) {
// the other interface is activated already and STAYS activated // the other interface is activated already and STAYS activated
if ((int)Settings::Get($check_array[$fieldname]['other_enabled']) == 1) { if ((int)Settings::Get($check_array[$fieldname]['other_enabled']) == 1) {
$returnvalue = [ $returnvalue = [
@@ -84,12 +83,8 @@ class Check
} else { } else {
// fcgid is being validated before fpm -> "ask" fpm about its state // fcgid is being validated before fpm -> "ask" fpm about its state
if ($fieldname == 'system_mod_fcgid_enabled') { if ($fieldname == 'system_mod_fcgid_enabled') {
$returnvalue = self::checkFcgidPhpFpm( $returnvalue = self::checkFcgidPhpFpm('system_phpfpm_enabled', null,
'system_phpfpm_enabled', $check_array[$fieldname]['other_post_field'], null);
null,
$check_array[$fieldname]['other_post_field'],
null
);
} else { } else {
// not, bot are nogo // not, bot are nogo
$returnvalue = $returnvalue = [ $returnvalue = $returnvalue = [
@@ -122,16 +117,8 @@ class Check
$mysql_access_host_array = array_unique(array_map('trim', explode(',', $newfieldvalue))); $mysql_access_host_array = array_unique(array_map('trim', explode(',', $newfieldvalue)));
foreach ($mysql_access_host_array as $host_entry) { foreach ($mysql_access_host_array as $host_entry) {
if (Validate::validate_ip2( if (Validate::validate_ip2($host_entry, true, 'invalidip', true, true, true, true,
$host_entry, false) == false && Validate::validateDomain($host_entry) == false && Validate::validateLocalHostname($host_entry) == false && $host_entry != '%') {
true,
'invalidip',
true,
true,
true,
true,
false
) == false && Validate::validateDomain($host_entry) == false && Validate::validateLocalHostname($host_entry) == false && $host_entry != '%') {
return [ return [
self::FORMFIELDS_PLAUSIBILITY_CHECK_ERROR, self::FORMFIELDS_PLAUSIBILITY_CHECK_ERROR,
'invalidmysqlhost', 'invalidmysqlhost',
@@ -217,11 +204,8 @@ class Check
} }
// neither dir can be within the other nor can they be equal // neither dir can be within the other nor can they be equal
if (substr($newdir, 0, strlen($cdir)) == $cdir || substr( if (substr($newdir, 0, strlen($cdir)) == $cdir || substr($cdir, 0,
$cdir, strlen($newdir)) == $newdir || $newdir == $cdir) {
0,
strlen($newdir)
) == $newdir || $newdir == $cdir) {
$returnvalue = [ $returnvalue = [
self::FORMFIELDS_PLAUSIBILITY_CHECK_ERROR, self::FORMFIELDS_PLAUSIBILITY_CHECK_ERROR,
'fcgidpathcannotbeincustomerdoc' 'fcgidpathcannotbeincustomerdoc'
@@ -280,11 +264,8 @@ class Check
} }
$returnvalue = []; $returnvalue = [];
if (Validate::validateUsername( if (Validate::validateUsername($newfieldvalue, Settings::Get('panel.unix_names'),
$newfieldvalue, Database::getSqlUsernameLength() - strlen($allnewfieldvalues['customer_mysqlprefix'])) === true) {
Settings::Get('panel.unix_names'),
Database::getSqlUsernameLength() - strlen($allnewfieldvalues['customer_mysqlprefix'])
) === true) {
$returnvalue = [ $returnvalue = [
self::FORMFIELDS_PLAUSIBILITY_CHECK_OK self::FORMFIELDS_PLAUSIBILITY_CHECK_OK
]; ];
@@ -349,7 +330,7 @@ class Check
]; ];
} }
// check if the pgp public key is a valid key // check if the pgp public key is a valid key
putenv('GNUPGHOME=' . sys_get_temp_dir()); putenv('GNUPGHOME='.sys_get_temp_dir());
if (gnupg_import(gnupg_init(), $newfieldvalue) === false) { if (gnupg_import(gnupg_init(), $newfieldvalue) === false) {
return [ return [
self::FORMFIELDS_PLAUSIBILITY_CHECK_ERROR, self::FORMFIELDS_PLAUSIBILITY_CHECK_ERROR,

View File

@@ -241,7 +241,7 @@ class Data
$returnvalue = isset($fielddata['select_var'][$newfieldvalue]); $returnvalue = isset($fielddata['select_var'][$newfieldvalue]);
} }
if ($returnvalue === true || (isset($fielddata['visible']) && $fielddata['visible'] == false)) { if ($returnvalue === true || $fielddata['visible'] == false) {
return true; return true;
} else { } else {
if (isset($fielddata['option_emptyallowed']) && $fielddata['option_emptyallowed']) { if (isset($fielddata['option_emptyallowed']) && $fielddata['option_emptyallowed']) {

View File

@@ -23,12 +23,4 @@ return [
* Default: false * Default: false
*/ */
'disable_otp_security_check' => false, 'disable_otp_security_check' => false,
/**
* For debugging/development purposes only.
* Enable to display all php related issue (notices, warnings, etc.; depending on php.ini) for froxlor itself
*
* Default: false
*/
'display_php_errors' => false,
]; ];

View File

@@ -168,9 +168,8 @@ include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
<file name="/etc/nginx/nginx.conf" backup="true"> <file name="/etc/nginx/nginx.conf" backup="true">
<content><![CDATA[ <content><![CDATA[
user www-data; user www-data;
worker_processes auto; worker_processes 4;
pid /var/run/nginx.pid; pid /var/run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events { events {
worker_connections 768; worker_connections 768;
@@ -1658,7 +1657,7 @@ data_directory = /var/lib/postfix
# for the case of a subdomain, $mydomain *must* be equal to $myhostname, # for the case of a subdomain, $mydomain *must* be equal to $myhostname,
# otherwise you cannot use the main domain for virtual transport. # otherwise you cannot use the main domain for virtual transport.
# also check the note about $mydomain below. # also check the note about $mydomain below.
myhostname = $mydomain myhostname = mail.$mydomain
#myhostname = virtual.domain.tld #myhostname = virtual.domain.tld
# The mydomain parameter specifies the local internet domain name. # The mydomain parameter specifies the local internet domain name.
@@ -1752,8 +1751,8 @@ inet_interfaces = all
# #
# See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS". # See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS".
# #
mydestination = $myhostname, localhost.$mydomain, localhost #mydestination = $myhostname, localhost.$mydomain, localhost
#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain,
# mail.$mydomain, www.$mydomain, ftp.$mydomain # mail.$mydomain, www.$mydomain, ftp.$mydomain
@@ -2563,106 +2562,6 @@ plugin {
</include> </include>
</daemon> </daemon>
</service> </service>
<!-- Antispam services -->
<service type="antispam" title="Antispam">
<!-- general RSpamd commands -->
<general>
<commands index="1">
<command><![CDATA[mkdir -p /etc/apt/keyrings]]></command>
<command><![CDATA[wget -O- https://rspamd.com/apt-stable/gpg.key | gpg --dearmor | tee /etc/apt/keyrings/rspamd.gpg > /dev/null]]></command>
<command><![CDATA[echo "deb [signed-by=/etc/apt/keyrings/rspamd.gpg] http://rspamd.com/apt-stable/ bookworm main" > /etc/apt/sources.list.d/rspamd.list]]></command>
<command><![CDATA[echo "deb-src [signed-by=/etc/apt/keyrings/rspamd.gpg] http://rspamd.com/apt-stable/ bookworm main" >> /etc/apt/sources.list.d/rspamd.list]]></command>
<command><![CDATA[apt-get update]]></command>
</commands>
<installs index="1">
<install><![CDATA[DEBIAN_FRONTEND=noninteractive apt-get -yq --no-install-recommends install rspamd]]></install>
</installs>
<commands index="2">
<command><![CDATA[mkdir -p /etc/rspamd/local.d/]]></command>
<command><![CDATA[mkdir -p /etc/rspamd/override.d/]]></command>
<command><![CDATA[mkdir -p /var/lib/rspamd/dkim/]]></command>
</commands>
<files index="1">
<file name="/etc/rspamd/local.d/actions.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
# Set rewrite subject to this value (%s is replaced by the original subject)
subject = "***SPAM*** %s"
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/arc.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
try_fallback = true;
### Enable DKIM signing for alias sender addresses
allow_username_mismatch = true;
path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector_map = "/etc/rspamd/dkim_selectors.map";
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/milter_headers.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
use = ["x-spamd-bar", "x-spam-level", "authentication-results"];
authenticated_headers = ["authentication-results"];
extended_spam_headers = true
skip_local = false
skip_authenticated = false
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/replies.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
## If a user has replied to an email, dont mark other emails in the same thread as spam
action = "no action";
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/settings.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
## Feel free to include your own settings or adjustments here, for example:
#whitelist {
# priority = low;
# rcpt = "postmaster@example.com";
# want_spam = yes;
#}
## Include froxlor generated settings
.include(try=true,priority=1,duplicate=merge) "{{settings.antispam.config_file}}"
]]>
</content>
</file>
</files>
<commands index="3">
<command><![CDATA[cp /etc/rspamd/local.d/arc.conf /etc/rspamd/local.d/dkim_signing.conf]]></command>
<command><![CDATA[postconf -e "milter_protocol = 6"]]></command>
<command><![CDATA[postconf -e "milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}"]]></command>
<command><![CDATA[postconf -e "milter_default_action = accept"]]></command>
<command><![CDATA[postconf -e "smtpd_milters = inet:127.0.0.1:11332"]]></command>
<command><![CDATA[postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"]]></command>
<command><![CDATA[chown -R _rspamd:_rspamd /var/lib/rspamd/dkim]]></command>
<command><![CDATA[service rspamd restart]]></command>
<command><![CDATA[service postfix restart]]></command>
</commands>
</general>
<!-- rspamd -->
<daemon name="rspamd" title="Rspamd" default="true">
<include>//service[@type='antispam']/general/commands[@index=1]
</include>
<include>//service[@type='antispam']/general/installs[@index=1]
</include>
<include>//service[@type='antispam']/general/commands[@index=2]
</include>
<include>//service[@type='antispam']/general/files[@index=1]
</include>
<include>//service[@type='antispam']/general/commands[@index=3]
</include>
</daemon>
</service>
<!-- FTP services --> <!-- FTP services -->
<service type="ftp" title="{{lng.admin.configfiles.ftp}}"> <service type="ftp" title="{{lng.admin.configfiles.ftp}}">
<!-- Proftpd --> <!-- Proftpd -->
@@ -3057,7 +2956,6 @@ TLSRSACertificateFile /etc/ssl/certs/proftpd.crt
TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key
TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt
TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key
# TLSCACertificateFile
TLSOptions NoSessionReuseRequired TLSOptions NoSessionReuseRequired
TLSVerifyClient off TLSVerifyClient off
@@ -3499,7 +3397,7 @@ aliases: files
<daemon name="cron" title="Cronjob for froxlor" <daemon name="cron" title="Cronjob for froxlor"
mandatory="true"> mandatory="true">
<install><![CDATA[apt-get install cron gnupg]]></install> <install><![CDATA[apt-get install cron gnupg]]></install>
<command><![CDATA[[ ! -e /usr/local/bin/froxlor-cli ] && ln -s <BASE_PATH>bin/froxlor-cli /usr/local/bin/froxlor-cli]]></command> <command><![CDATA[ln -s <BASE_PATH>bin/froxlor-cli /usr/local/bin/froxlor-cli]]></command>
<command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command> <command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command> <command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon> </daemon>

View File

@@ -168,9 +168,8 @@ include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
<file name="/etc/nginx/nginx.conf" backup="true"> <file name="/etc/nginx/nginx.conf" backup="true">
<content><![CDATA[ <content><![CDATA[
user www-data; user www-data;
worker_processes auto; worker_processes 4;
pid /var/run/nginx.pid; pid /var/run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events { events {
worker_connections 768; worker_connections 768;
@@ -1658,7 +1657,7 @@ data_directory = /var/lib/postfix
# for the case of a subdomain, $mydomain *must* be equal to $myhostname, # for the case of a subdomain, $mydomain *must* be equal to $myhostname,
# otherwise you cannot use the main domain for virtual transport. # otherwise you cannot use the main domain for virtual transport.
# also check the note about $mydomain below. # also check the note about $mydomain below.
myhostname = $mydomain myhostname = mail.$mydomain
#myhostname = virtual.domain.tld #myhostname = virtual.domain.tld
# The mydomain parameter specifies the local internet domain name. # The mydomain parameter specifies the local internet domain name.
@@ -1752,8 +1751,8 @@ inet_interfaces = all
# #
# See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS". # See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS".
# #
mydestination = $myhostname, localhost.$mydomain, localhost #mydestination = $myhostname, localhost.$mydomain, localhost
#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain,
# mail.$mydomain, www.$mydomain, ftp.$mydomain # mail.$mydomain, www.$mydomain, ftp.$mydomain
@@ -4132,105 +4131,6 @@ plugin {
</include> </include>
</daemon> </daemon>
</service> </service>
<!-- Antispam services -->
<service type="antispam" title="Antispam">
<!-- general RSpamd commands -->
<general>
<commands index="1">
<command><![CDATA[mkdir -p /etc/apt/keyrings]]></command>
<command><![CDATA[wget -O- https://rspamd.com/apt-stable/gpg.key | gpg --dearmor | tee /etc/apt/keyrings/rspamd.gpg > /dev/null]]></command>
<command><![CDATA[echo "deb [signed-by=/etc/apt/keyrings/rspamd.gpg] http://rspamd.com/apt-stable/ bullseye main" > /etc/apt/sources.list.d/rspamd.list]]></command>
<command><![CDATA[echo "deb-src [signed-by=/etc/apt/keyrings/rspamd.gpg] http://rspamd.com/apt-stable/ bullseye main" >> /etc/apt/sources.list.d/rspamd.list]]></command>
<command><![CDATA[apt-get update]]></command>
</commands>
<installs index="1">
<install><![CDATA[DEBIAN_FRONTEND=noninteractive apt-get -yq --no-install-recommends install rspamd]]></install>
</installs>
<commands index="2">
<command><![CDATA[mkdir -p /etc/rspamd/local.d/]]></command>
<command><![CDATA[mkdir -p /etc/rspamd/override.d/]]></command>
<command><![CDATA[mkdir -p /var/lib/rspamd/dkim/]]></command>
</commands>
<files index="1">
<file name="/etc/rspamd/local.d/actions.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
# Set rewrite subject to this value (%s is replaced by the original subject)
subject = "***SPAM*** %s"
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/arc.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
try_fallback = true;
### Enable DKIM signing for alias sender addresses
allow_username_mismatch = true;
path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector_map = "/etc/rspamd/dkim_selectors.map";
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/milter_headers.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
use = ["x-spamd-bar", "x-spam-level", "authentication-results"];
authenticated_headers = ["authentication-results"];
extended_spam_headers = true
skip_local = false
skip_authenticated = false
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/replies.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
## If a user has replied to an email, dont mark other emails in the same thread as spam
action = "no action";
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/settings.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
## Feel free to include your own settings or adjustments here, for example:
#whitelist {
# priority = low;
# rcpt = "postmaster@example.com";
# want_spam = yes;
#}
## Include froxlor generated settings
.include(try=true,priority=1,duplicate=merge) "{{settings.antispam.config_file}}"
]]>
</content>
</file>
</files>
<commands index="3">
<command><![CDATA[cp /etc/rspamd/local.d/arc.conf /etc/rspamd/local.d/dkim_signing.conf]]></command>
<command><![CDATA[postconf -e "milter_protocol = 6"]]></command>
<command><![CDATA[postconf -e "milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}"]]></command>
<command><![CDATA[postconf -e "milter_default_action = accept"]]></command>
<command><![CDATA[postconf -e "smtpd_milters = inet:127.0.0.1:11332"]]></command>
<command><![CDATA[postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"]]></command>
<command><![CDATA[chown -R _rspamd:_rspamd /var/lib/rspamd/dkim]]></command>
<command><![CDATA[service rspamd restart]]></command>
</commands>
</general>
<!-- rspamd -->
<daemon name="rspamd" title="Rspamd" default="true">
<include>//service[@type='antispam']/general/commands[@index=1]
</include>
<include>//service[@type='antispam']/general/installs[@index=1]
</include>
<include>//service[@type='antispam']/general/commands[@index=2]
</include>
<include>//service[@type='antispam']/general/files[@index=1]
</include>
<include>//service[@type='antispam']/general/commands[@index=3]
</include>
</daemon>
</service>
<!-- FTP services --> <!-- FTP services -->
<service type="ftp" title="{{lng.admin.configfiles.ftp}}"> <service type="ftp" title="{{lng.admin.configfiles.ftp}}">
<!-- Proftpd --> <!-- Proftpd -->
@@ -4625,7 +4525,6 @@ TLSRSACertificateFile /etc/ssl/certs/proftpd.crt
TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key
TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt
TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key
# TLSCACertificateFile
TLSOptions NoSessionReuseRequired TLSOptions NoSessionReuseRequired
TLSVerifyClient off TLSVerifyClient off
@@ -5062,7 +4961,7 @@ aliases: files
<daemon name="cron" title="Cronjob for froxlor" <daemon name="cron" title="Cronjob for froxlor"
mandatory="true"> mandatory="true">
<install><![CDATA[apt-get install cron gnupg]]></install> <install><![CDATA[apt-get install cron gnupg]]></install>
<command><![CDATA[[ ! -e /usr/local/bin/froxlor-cli ] && ln -s <BASE_PATH>bin/froxlor-cli /usr/local/bin/froxlor-cli]]></command> <command><![CDATA[ln -s <BASE_PATH>bin/froxlor-cli /usr/local/bin/froxlor-cli]]></command>
<command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command> <command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command> <command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon> </daemon>

View File

@@ -167,9 +167,8 @@ include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
<file name="/etc/nginx/nginx.conf" backup="true"> <file name="/etc/nginx/nginx.conf" backup="true">
<content><![CDATA[ <content><![CDATA[
user www-data; user www-data;
worker_processes auto; worker_processes 4;
pid /var/run/nginx.pid; pid /var/run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events { events {
worker_connections 768; worker_connections 768;
@@ -1643,7 +1642,7 @@ compatibility_level = 2
# for the case of a subdomain, $mydomain *must* be equal to $myhostname, # for the case of a subdomain, $mydomain *must* be equal to $myhostname,
# otherwise you cannot use the main domain for virtual transport. # otherwise you cannot use the main domain for virtual transport.
# also check the note about $mydomain below. # also check the note about $mydomain below.
myhostname = $mydomain myhostname = mail.$mydomain
#myhostname = virtual.domain.tld #myhostname = virtual.domain.tld
# The mydomain parameter specifies the local internet domain name. # The mydomain parameter specifies the local internet domain name.
@@ -1657,8 +1656,8 @@ myhostname = $mydomain
# FQDN from Froxlor # FQDN from Froxlor
mydomain = <SERVERNAME> mydomain = <SERVERNAME>
mydestination = $myhostname, localhost.$mydomain, localhost #mydestination = $myhostname, localhost.$mydomain, localhost
#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain,
# mail.$mydomain, www.$mydomain, ftp.$mydomain # mail.$mydomain, www.$mydomain, ftp.$mydomain
@@ -3355,105 +3354,6 @@ plugin {
</include> </include>
</daemon> </daemon>
</service> </service>
<!-- Antispam services -->
<service type="antispam" title="Antispam">
<!-- general RSpamd commands -->
<general>
<commands index="1">
<command><![CDATA[mkdir -p /etc/apt/keyrings]]></command>
<command><![CDATA[wget -O- https://rspamd.com/apt-stable/gpg.key | gpg --dearmor | tee /etc/apt/keyrings/rspamd.gpg > /dev/null]]></command>
<command><![CDATA[echo "deb [signed-by=/etc/apt/keyrings/rspamd.gpg] http://rspamd.com/apt-stable/ focal main" > /etc/apt/sources.list.d/rspamd.list]]></command>
<command><![CDATA[echo "deb-src [signed-by=/etc/apt/keyrings/rspamd.gpg] http://rspamd.com/apt-stable/ focal main" >> /etc/apt/sources.list.d/rspamd.list]]></command>
<command><![CDATA[apt-get update]]></command>
</commands>
<installs index="1">
<install><![CDATA[DEBIAN_FRONTEND=noninteractive apt-get -yq --no-install-recommends install rspamd]]></install>
</installs>
<commands index="2">
<command><![CDATA[mkdir -p /etc/rspamd/local.d/]]></command>
<command><![CDATA[mkdir -p /etc/rspamd/override.d/]]></command>
<command><![CDATA[mkdir -p /var/lib/rspamd/dkim/]]></command>
</commands>
<files index="1">
<file name="/etc/rspamd/local.d/actions.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
# Set rewrite subject to this value (%s is replaced by the original subject)
subject = "***SPAM*** %s"
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/arc.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
try_fallback = true;
### Enable DKIM signing for alias sender addresses
allow_username_mismatch = true;
path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector_map = "/etc/rspamd/dkim_selectors.map";
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/milter_headers.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
use = ["x-spamd-bar", "x-spam-level", "authentication-results"];
authenticated_headers = ["authentication-results"];
extended_spam_headers = true
skip_local = false
skip_authenticated = false
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/replies.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
## If a user has replied to an email, dont mark other emails in the same thread as spam
action = "no action";
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/settings.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
## Feel free to include your own settings or adjustments here, for example:
#whitelist {
# priority = low;
# rcpt = "postmaster@example.com";
# want_spam = yes;
#}
## Include froxlor generated settings
.include(try=true,priority=1,duplicate=merge) "{{settings.antispam.config_file}}"
]]>
</content>
</file>
</files>
<commands index="3">
<command><![CDATA[cp /etc/rspamd/local.d/arc.conf /etc/rspamd/local.d/dkim_signing.conf]]></command>
<command><![CDATA[postconf -e "milter_protocol = 6"]]></command>
<command><![CDATA[postconf -e "milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}"]]></command>
<command><![CDATA[postconf -e "milter_default_action = accept"]]></command>
<command><![CDATA[postconf -e "smtpd_milters = inet:127.0.0.1:11332"]]></command>
<command><![CDATA[postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"]]></command>
<command><![CDATA[chown -R _rspamd:_rspamd /var/lib/rspamd/dkim]]></command>
<command><![CDATA[service rspamd restart]]></command>
</commands>
</general>
<!-- rspamd -->
<daemon name="rspamd" title="Rspamd" default="true">
<include>//service[@type='antispam']/general/commands[@index=1]
</include>
<include>//service[@type='antispam']/general/installs[@index=1]
</include>
<include>//service[@type='antispam']/general/commands[@index=2]
</include>
<include>//service[@type='antispam']/general/files[@index=1]
</include>
<include>//service[@type='antispam']/general/commands[@index=3]
</include>
</daemon>
</service>
<!-- FTP services --> <!-- FTP services -->
<service type="ftp" title="{{lng.admin.configfiles.ftp}}"> <service type="ftp" title="{{lng.admin.configfiles.ftp}}">
<!-- Proftpd --> <!-- Proftpd -->
@@ -3844,7 +3744,6 @@ TLSRSACertificateFile /etc/ssl/certs/proftpd.crt
TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key
TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt
TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key
# TLSCACertificateFile
TLSOptions NoSessionReuseRequired TLSOptions NoSessionReuseRequired
TLSVerifyClient off TLSVerifyClient off
@@ -4289,7 +4188,7 @@ aliases: files
<daemon name="cron" title="Cronjob for froxlor" <daemon name="cron" title="Cronjob for froxlor"
mandatory="true"> mandatory="true">
<install><![CDATA[apt-get install cron gnupg]]></install> <install><![CDATA[apt-get install cron gnupg]]></install>
<command><![CDATA[[ ! -e /usr/local/bin/froxlor-cli ] && ln -s <BASE_PATH>bin/froxlor-cli /usr/local/bin/froxlor-cli]]></command> <command><![CDATA[ln -s <BASE_PATH>bin/froxlor-cli /usr/local/bin/froxlor-cli]]></command>
<command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command> <command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command> <command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon> </daemon>

File diff suppressed because it is too large Load Diff

View File

@@ -167,9 +167,8 @@ include_shell "/usr/share/lighttpd/include-conf-enabled.pl"
<file name="/etc/nginx/nginx.conf" backup="true"> <file name="/etc/nginx/nginx.conf" backup="true">
<content><![CDATA[ <content><![CDATA[
user www-data; user www-data;
worker_processes auto; worker_processes 4;
pid /var/run/nginx.pid; pid /var/run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events { events {
worker_connections 768; worker_connections 768;
@@ -1643,7 +1642,7 @@ compatibility_level = 2
# for the case of a subdomain, $mydomain *must* be equal to $myhostname, # for the case of a subdomain, $mydomain *must* be equal to $myhostname,
# otherwise you cannot use the main domain for virtual transport. # otherwise you cannot use the main domain for virtual transport.
# also check the note about $mydomain below. # also check the note about $mydomain below.
myhostname = $mydomain myhostname = mail.$mydomain
#myhostname = virtual.domain.tld #myhostname = virtual.domain.tld
# The mydomain parameter specifies the local internet domain name. # The mydomain parameter specifies the local internet domain name.
@@ -1657,8 +1656,8 @@ myhostname = $mydomain
# FQDN from Froxlor # FQDN from Froxlor
mydomain = <SERVERNAME> mydomain = <SERVERNAME>
mydestination = $myhostname, localhost.$mydomain, localhost #mydestination = $myhostname, localhost.$mydomain, localhost
#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain, #mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain,
# mail.$mydomain, www.$mydomain, ftp.$mydomain # mail.$mydomain, www.$mydomain, ftp.$mydomain
@@ -3345,105 +3344,6 @@ plugin {
</include> </include>
</daemon> </daemon>
</service> </service>
<!-- Antispam services -->
<service type="antispam" title="Antispam">
<!-- general RSpamd commands -->
<general>
<commands index="1">
<command><![CDATA[mkdir -p /etc/apt/keyrings]]></command>
<command><![CDATA[wget -O- https://rspamd.com/apt-stable/gpg.key | gpg --dearmor | tee /etc/apt/keyrings/rspamd.gpg > /dev/null]]></command>
<command><![CDATA[echo "deb [signed-by=/etc/apt/keyrings/rspamd.gpg] http://rspamd.com/apt-stable/ jammy main" > /etc/apt/sources.list.d/rspamd.list]]></command>
<command><![CDATA[echo "deb-src [signed-by=/etc/apt/keyrings/rspamd.gpg] http://rspamd.com/apt-stable/ jammy main" >> /etc/apt/sources.list.d/rspamd.list]]></command>
<command><![CDATA[apt-get update]]></command>
</commands>
<installs index="1">
<install><![CDATA[DEBIAN_FRONTEND=noninteractive apt-get -yq --no-install-recommends install rspamd]]></install>
</installs>
<commands index="2">
<command><![CDATA[mkdir -p /etc/rspamd/local.d/]]></command>
<command><![CDATA[mkdir -p /etc/rspamd/override.d/]]></command>
<command><![CDATA[mkdir -p /var/lib/rspamd/dkim/]]></command>
</commands>
<files index="1">
<file name="/etc/rspamd/local.d/actions.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
# Set rewrite subject to this value (%s is replaced by the original subject)
subject = "***SPAM*** %s"
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/arc.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
try_fallback = true;
### Enable DKIM signing for alias sender addresses
allow_username_mismatch = true;
path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector_map = "/etc/rspamd/dkim_selectors.map";
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/milter_headers.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
use = ["x-spamd-bar", "x-spam-level", "authentication-results"];
authenticated_headers = ["authentication-results"];
extended_spam_headers = true
skip_local = false
skip_authenticated = false
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/replies.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
## If a user has replied to an email, dont mark other emails in the same thread as spam
action = "no action";
]]>
</content>
</file>
<file name="/etc/rspamd/local.d/settings.conf"
chown="root:root" chmod="0644" backup="true">
<content><![CDATA[
## Feel free to include your own settings or adjustments here, for example:
#whitelist {
# priority = low;
# rcpt = "postmaster@example.com";
# want_spam = yes;
#}
## Include froxlor generated settings
.include(try=true,priority=1,duplicate=merge) "{{settings.antispam.config_file}}"
]]>
</content>
</file>
</files>
<commands index="3">
<command><![CDATA[cp /etc/rspamd/local.d/arc.conf /etc/rspamd/local.d/dkim_signing.conf]]></command>
<command><![CDATA[postconf -e "milter_protocol = 6"]]></command>
<command><![CDATA[postconf -e "milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}"]]></command>
<command><![CDATA[postconf -e "milter_default_action = accept"]]></command>
<command><![CDATA[postconf -e "smtpd_milters = inet:127.0.0.1:11332"]]></command>
<command><![CDATA[postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"]]></command>
<command><![CDATA[chown -R _rspamd:_rspamd /var/lib/rspamd/dkim]]></command>
<command><![CDATA[service rspamd restart]]></command>
</commands>
</general>
<!-- rspamd -->
<daemon name="rspamd" title="Rspamd" default="true">
<include>//service[@type='antispam']/general/commands[@index=1]
</include>
<include>//service[@type='antispam']/general/installs[@index=1]
</include>
<include>//service[@type='antispam']/general/commands[@index=2]
</include>
<include>//service[@type='antispam']/general/files[@index=1]
</include>
<include>//service[@type='antispam']/general/commands[@index=3]
</include>
</daemon>
</service>
<!-- FTP services --> <!-- FTP services -->
<service type="ftp" title="{{lng.admin.configfiles.ftp}}"> <service type="ftp" title="{{lng.admin.configfiles.ftp}}">
<!-- Proftpd --> <!-- Proftpd -->
@@ -3836,7 +3736,6 @@ TLSRSACertificateFile /etc/ssl/certs/proftpd.crt
TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key TLSRSACertificateKeyFile /etc/ssl/private/proftpd.key
TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt TLSECCertificateFile /etc/ssl/certs/proftpd_ec.crt
TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key TLSECCertificateKeyFile /etc/ssl/private/proftpd_ec.key
# TLSCACertificateFile
TLSOptions NoSessionReuseRequired TLSOptions NoSessionReuseRequired
TLSVerifyClient off TLSVerifyClient off
@@ -4286,7 +4185,7 @@ aliases: files
<daemon name="cron" title="Cronjob for froxlor" <daemon name="cron" title="Cronjob for froxlor"
mandatory="true"> mandatory="true">
<install><![CDATA[apt-get install cron gnupg]]></install> <install><![CDATA[apt-get install cron gnupg]]></install>
<command><![CDATA[[ ! -e /usr/local/bin/froxlor-cli ] && ln -s <BASE_PATH>bin/froxlor-cli /usr/local/bin/froxlor-cli]]></command> <command><![CDATA[ln -s <BASE_PATH>bin/froxlor-cli /usr/local/bin/froxlor-cli]]></command>
<command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command> <command><![CDATA[/usr/bin/php <BASE_PATH>bin/froxlor-cli froxlor:cron --run-task 99]]></command>
<command><![CDATA[{{settings.system.crondreload}}]]></command> <command><![CDATA[{{settings.system.crondreload}}]]></command>
</daemon> </daemon>

Some files were not shown because too many files have changed in this diff Show More