Compare commits

...

16 Commits
2.1.6 ... 2.1.8

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
26 changed files with 121 additions and 72 deletions

View File

@@ -35,6 +35,7 @@ return [
'varname' => 'sessiontimeout', 'varname' => 'sessiontimeout',
'type' => 'number', 'type' => 'number',
'min' => 60, 'min' => 60,
'max' => 31536000,
'default' => 600, 'default' => 600,
'save_method' => 'storeSettingField' 'save_method' => 'storeSettingField'
], ],

View File

@@ -142,8 +142,10 @@ if (($page == 'ipsandports' || $page == 'overview') && $userinfo['change_servers
} }
} elseif ($action == 'jqCheckIP') { } elseif ($action == 'jqCheckIP') {
$ip = $_POST['ip'] ?? ""; $ip = $_POST['ip'] ?? "";
if ((filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) || filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE | FILTER_FLAG_NO_PRIV_RANGE) == false) { if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
// returns notice if private network detected so we can display it 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)) {
// returns notice if private network detected, so we can display it
echo json_encode(lng('admin.ipsandports.ipnote')); echo json_encode(lng('admin.ipsandports.ipnote'));
} else { } else {
echo 0; echo 0;

View File

@@ -726,7 +726,7 @@ opcache.validate_timestamps'),
('panel', 'logo_overridecustom', '0'), ('panel', 'logo_overridecustom', '0'),
('panel', 'settings_mode', '0'), ('panel', 'settings_mode', '0'),
('panel', 'menu_collapsed', '1'), ('panel', 'menu_collapsed', '1'),
('panel', 'version', '2.1.6'), ('panel', 'version', '2.1.8'),
('panel', 'db_version', '202312120'); ('panel', 'db_version', '202312120');

View File

@@ -289,3 +289,13 @@ if (Froxlor::isFroxlorVersion('2.1.5')) {
Update::showUpdateStep("Updating from 2.1.5 to 2.1.6", false); Update::showUpdateStep("Updating from 2.1.5 to 2.1.6", false);
Froxlor::updateToVersion('2.1.6'); Froxlor::updateToVersion('2.1.6');
} }
if (Froxlor::isFroxlorVersion('2.1.6')) {
Update::showUpdateStep("Updating from 2.1.6 to 2.1.7", false);
Froxlor::updateToVersion('2.1.7');
}
if (Froxlor::isFroxlorVersion('2.1.7')) {
Update::showUpdateStep("Updating from 2.1.7 to 2.1.8", false);
Froxlor::updateToVersion('2.1.8');
}

View File

@@ -519,7 +519,8 @@ class Domains extends ApiCommand implements ResourceEntity
$mod_fcgid_maxrequests = '-1'; $mod_fcgid_maxrequests = '-1';
} }
} else { } else {
$phpenabled = '1'; // set default to whether the customer has php enabled or not
$phpenabled = $customer['phpenabled'];
$openbasedir = '1'; $openbasedir = '1';
if ((int)Settings::Get('phpfpm.enabled') == 1) { if ((int)Settings::Get('phpfpm.enabled') == 1) {
@@ -1527,13 +1528,12 @@ class Domains extends ApiCommand implements ResourceEntity
// enabled ssl for the domain but no ssl ip/port is selected // enabled ssl for the domain but no ssl ip/port is selected
Response::standardError('nosslippportgiven', '', true); Response::standardError('nosslippportgiven', '', true);
} }
if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports)) { if (Settings::Get('system.use_ssl') == "0" || empty($ssl_ipandports) || !$sslenabled) {
$ssl_redirect = 0; $ssl_redirect = 0;
$letsencrypt = 0; $letsencrypt = 0;
$http2 = 0; $http2 = 0;
// we need this for the json_encode // act like $remove_ssl_ipandport
// if ssl is disabled or no ssl-ip/port exists $ssl_ipandports = [];
$ssl_ipandports[] = -1;
// HSTS // HSTS
$hsts_maxage = 0; $hsts_maxage = 0;

View File

@@ -222,8 +222,8 @@ class PhpSettings extends ApiCommand implements ResourceEntity
* optional request terminate timeout if FPM is used, default is '60s' * optional request terminate timeout if FPM is used, default is '60s'
* @param string $phpfpm_reqslowtimeout * @param string $phpfpm_reqslowtimeout
* optional request slowlog timeout if FPM is used, default is '5s' * optional request slowlog timeout if FPM is used, default is '5s'
* @param bool $phpfpm_pass_authorizationheader * @param bool $pass_authorizationheader
* optional whether to pass authorization header to webserver if FPM is used, default is 0 (false) * optional whether to pass authorization header to webserver if FPM/FCGID is used, default is 0 (false)
* @param bool $override_fpmconfig * @param bool $override_fpmconfig
* optional whether to override fpm-daemon-config value for the following settings if FPM is used, * optional whether to override fpm-daemon-config value for the following settings if FPM is used,
* default is 0 (false) * default is 0 (false)
@@ -276,7 +276,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
$fpm_enableslowlog = $this->getBoolParam('phpfpm_enable_slowlog', true, 0); $fpm_enableslowlog = $this->getBoolParam('phpfpm_enable_slowlog', true, 0);
$fpm_reqtermtimeout = $this->getParam('phpfpm_reqtermtimeout', true, "60s"); $fpm_reqtermtimeout = $this->getParam('phpfpm_reqtermtimeout', true, "60s");
$fpm_reqslowtimeout = $this->getParam('phpfpm_reqslowtimeout', true, "5s"); $fpm_reqslowtimeout = $this->getParam('phpfpm_reqslowtimeout', true, "5s");
$fpm_pass_authorizationheader = $this->getBoolParam('phpfpm_pass_authorizationheader', true, 0); $pass_authorizationheader = $this->getBoolParam('pass_authorizationheader', true, 0);
$override_fpmconfig = $this->getBoolParam('override_fpmconfig', true, 0); $override_fpmconfig = $this->getBoolParam('override_fpmconfig', true, 0);
$def_fpmconfig = $this->apiCall('FpmDaemons.get', [ $def_fpmconfig = $this->apiCall('FpmDaemons.get', [
@@ -312,7 +312,6 @@ class PhpSettings extends ApiCommand implements ResourceEntity
$fpm_enableslowlog = 0; $fpm_enableslowlog = 0;
$fpm_reqtermtimeout = 0; $fpm_reqtermtimeout = 0;
$fpm_reqslowtimeout = 0; $fpm_reqslowtimeout = 0;
$fpm_pass_authorizationheader = 0;
$override_fpmconfig = 0; $override_fpmconfig = 0;
} elseif (Settings::Get('phpfpm.enabled') == 1) { } elseif (Settings::Get('phpfpm.enabled') == 1) {
$fpm_reqtermtimeout = Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true); $fpm_reqtermtimeout = Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true);
@@ -377,7 +376,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
'fpmreqslow' => $fpm_reqslowtimeout, 'fpmreqslow' => $fpm_reqslowtimeout,
'phpsettings' => $phpsettings, 'phpsettings' => $phpsettings,
'fpmsettingid' => $fpm_config_id, 'fpmsettingid' => $fpm_config_id,
'fpmpassauth' => $fpm_pass_authorizationheader, 'fpmpassauth' => $pass_authorizationheader,
'ofc' => $override_fpmconfig, 'ofc' => $override_fpmconfig,
'pm' => $pmanager, 'pm' => $pmanager,
'max_children' => $max_children, 'max_children' => $max_children,
@@ -464,7 +463,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
* optional request terminate timeout if FPM is used, default is '60s' * optional request terminate timeout if FPM is used, default is '60s'
* @param string $phpfpm_reqslowtimeout * @param string $phpfpm_reqslowtimeout
* optional request slowlog timeout if FPM is used, default is '5s' * optional request slowlog timeout if FPM is used, default is '5s'
* @param bool $phpfpm_pass_authorizationheader * @param bool $pass_authorizationheader
* optional whether to pass authorization header to webserver if FPM is used, default is 0 (false) * optional whether to pass authorization header to webserver if FPM is used, default is 0 (false)
* @param bool $override_fpmconfig * @param bool $override_fpmconfig
* optional whether to override fpm-daemon-config value for the following settings if FPM is used, * optional whether to override fpm-daemon-config value for the following settings if FPM is used,
@@ -516,7 +515,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
$fpm_enableslowlog = $this->getBoolParam('phpfpm_enable_slowlog', true, $result['fpm_slowlog']); $fpm_enableslowlog = $this->getBoolParam('phpfpm_enable_slowlog', true, $result['fpm_slowlog']);
$fpm_reqtermtimeout = $this->getParam('phpfpm_reqtermtimeout', true, $result['fpm_reqterm']); $fpm_reqtermtimeout = $this->getParam('phpfpm_reqtermtimeout', true, $result['fpm_reqterm']);
$fpm_reqslowtimeout = $this->getParam('phpfpm_reqslowtimeout', true, $result['fpm_reqslow']); $fpm_reqslowtimeout = $this->getParam('phpfpm_reqslowtimeout', true, $result['fpm_reqslow']);
$fpm_pass_authorizationheader = $this->getBoolParam('phpfpm_pass_authorizationheader', true, $result['pass_authorizationheader']); $pass_authorizationheader = $this->getBoolParam('pass_authorizationheader', true, $result['pass_authorizationheader']);
$override_fpmconfig = $this->getBoolParam('override_fpmconfig', true, $result['override_fpmconfig']); $override_fpmconfig = $this->getBoolParam('override_fpmconfig', true, $result['override_fpmconfig']);
$pmanager = $this->getParam('pm', true, $result['pm']); $pmanager = $this->getParam('pm', true, $result['pm']);
$max_children = $this->getParam('max_children', true, $result['max_children']); $max_children = $this->getParam('max_children', true, $result['max_children']);
@@ -548,7 +547,6 @@ class PhpSettings extends ApiCommand implements ResourceEntity
$fpm_enableslowlog = 0; $fpm_enableslowlog = 0;
$fpm_reqtermtimeout = 0; $fpm_reqtermtimeout = 0;
$fpm_reqslowtimeout = 0; $fpm_reqslowtimeout = 0;
$fpm_pass_authorizationheader = 0;
$override_fpmconfig = 0; $override_fpmconfig = 0;
} elseif (Settings::Get('phpfpm.enabled') == 1) { } elseif (Settings::Get('phpfpm.enabled') == 1) {
$fpm_reqtermtimeout = Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true); $fpm_reqtermtimeout = Validate::validate($fpm_reqtermtimeout, 'phpfpm_reqtermtimeout', '/^([0-9]+)(|s|m|h|d)$/', '', [], true);
@@ -614,7 +612,7 @@ class PhpSettings extends ApiCommand implements ResourceEntity
'fpmreqslow' => $fpm_reqslowtimeout, 'fpmreqslow' => $fpm_reqslowtimeout,
'phpsettings' => $phpsettings, 'phpsettings' => $phpsettings,
'fpmsettingid' => $fpm_config_id, 'fpmsettingid' => $fpm_config_id,
'fpmpassauth' => $fpm_pass_authorizationheader, 'fpmpassauth' => $pass_authorizationheader,
'ofc' => $override_fpmconfig, 'ofc' => $override_fpmconfig,
'pm' => $pmanager, 'pm' => $pmanager,
'max_children' => $max_children, 'max_children' => $max_children,

View File

@@ -296,21 +296,24 @@ class SubDomains extends ApiCommand implements ResourceEntity
// assign default config // assign default config
$phpsid_result['phpsettingid'] = 1; $phpsid_result['phpsettingid'] = 1;
} }
// check whether the customer has chosen its own php-config
if ($phpsettingid > 0 && $phpsettingid != $phpsid_result['phpsettingid']) {
$phpsid_result['phpsettingid'] = intval($phpsettingid);
}
$allowed_phpconfigs = $customer['allowed_phpconfigs']; if ($domain_check['phpenabled'] == 1) {
if (!empty($allowed_phpconfigs)) { // check whether the customer has chosen its own php-config
$allowed_phpconfigs = json_decode($allowed_phpconfigs, true); if ($phpsettingid > 0 && $phpsettingid != $phpsid_result['phpsettingid']) {
} else { $phpsid_result['phpsettingid'] = intval($phpsettingid);
$allowed_phpconfigs = []; }
}
// only with fcgid/fpm enabled will it be possible to select a php-setting $allowed_phpconfigs = $customer['allowed_phpconfigs'];
if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) { if (!empty($allowed_phpconfigs)) {
if (!in_array($phpsid_result['phpsettingid'], $allowed_phpconfigs)) { $allowed_phpconfigs = json_decode($allowed_phpconfigs, true);
Response::standardError('notallowedphpconfigused', '', true); } else {
$allowed_phpconfigs = [];
}
// only with fcgid/fpm enabled will it be possible to select a php-setting
if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) {
if (!in_array($phpsid_result['phpsettingid'], $allowed_phpconfigs)) {
Response::standardError('notallowedphpconfigused', '', true);
}
} }
} }
@@ -797,7 +800,7 @@ class SubDomains extends ApiCommand implements ResourceEntity
$allowed_phpconfigs = []; $allowed_phpconfigs = [];
} }
// only with fcgid/fpm enabled will it be possible to select a php-setting // only with fcgid/fpm enabled will it be possible to select a php-setting
if ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1) { if ((int)$result['phpenabled'] == 1 && ((int)Settings::Get('system.mod_fcgid') == 1 || (int)Settings::Get('phpfpm.enabled') == 1)) {
if (!in_array($phpsettingid, $allowed_phpconfigs)) { if (!in_array($phpsettingid, $allowed_phpconfigs)) {
Response::standardError('notallowedphpconfigused', '', true); Response::standardError('notallowedphpconfigused', '', true);
} }

View File

@@ -25,19 +25,21 @@
namespace Froxlor\Cron\Http; namespace Froxlor\Cron\Http;
use Froxlor\Froxlor;
use Froxlor\Cron\Http\Php\PhpInterface; use Froxlor\Cron\Http\Php\PhpInterface;
use Froxlor\Cron\TaskId;
use Froxlor\Customer\Customer; use Froxlor\Customer\Customer;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Domain\Domain; use Froxlor\Domain\Domain;
use Froxlor\FileDir; use Froxlor\FileDir;
use Froxlor\Froxlor;
use Froxlor\FroxlorLogger; use Froxlor\FroxlorLogger;
use Froxlor\Http\Directory; use Froxlor\Http\Directory;
use Froxlor\Http\Statistics; use Froxlor\Http\Statistics;
use Froxlor\PhpHelper; use Froxlor\PhpHelper;
use Froxlor\Settings; use Froxlor\Settings;
use Froxlor\Validate\Validate; use Froxlor\System\Cronjob;
use Froxlor\System\Crypt; use Froxlor\System\Crypt;
use Froxlor\Validate\Validate;
use PDO; use PDO;
class Apache extends HttpConfigBase class Apache extends HttpConfigBase
@@ -133,6 +135,7 @@ class Apache extends HttpConfigBase
if (Settings::Get('system.le_froxlor_enabled') && ($this->froxlorVhostHasLetsEncryptCert() == false || $this->froxlorVhostLetsEncryptNeedsRenew())) { if (Settings::Get('system.le_froxlor_enabled') && ($this->froxlorVhostHasLetsEncryptCert() == false || $this->froxlorVhostLetsEncryptNeedsRenew())) {
$this->virtualhosts_data[$vhosts_filename] .= '# temp. disabled ssl-redirect due to Let\'s Encrypt certificate generation.' . PHP_EOL; $this->virtualhosts_data[$vhosts_filename] .= '# temp. disabled ssl-redirect due to Let\'s Encrypt certificate generation.' . PHP_EOL;
$is_redirect = false; $is_redirect = false;
Cronjob::inserttask(TaskId::REBUILD_VHOST);
} else { } else {
$_sslport = $this->checkAlternativeSslPort(); $_sslport = $this->checkAlternativeSslPort();
@@ -159,7 +162,7 @@ class Apache extends HttpConfigBase
if (Settings::Get('system.froxlordirectlyviahostname')) { if (Settings::Get('system.froxlordirectlyviahostname')) {
$relpath = "/"; $relpath = "/";
} else { } else {
$relpath = "/".basename(Froxlor::getInstallDir()); $relpath = "/" . basename(Froxlor::getInstallDir());
} }
// protect lib/userdata.inc.php // protect lib/userdata.inc.php
$this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . rtrim($relpath, "/") . '/lib/">' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . rtrim($relpath, "/") . '/lib/">' . "\n";
@@ -205,7 +208,9 @@ class Apache extends HttpConfigBase
]; ];
$php = new PhpInterface($domain); $php = new PhpInterface($domain);
$phpconfig = $php->getPhpConfig(Settings::Get('system.mod_fcgid_defaultini_ownvhost')); $phpconfig = $php->getPhpConfig(Settings::Get('system.mod_fcgid_defaultini_ownvhost'));
if ($phpconfig['pass_authorizationheader'] == '1') {
$this->virtualhosts_data[$vhosts_filename] .= ' FcgidPassHeader Authorization' . "\n";
}
$starter_filename = FileDir::makeCorrectFile($configdir . '/php-fcgi-starter'); $starter_filename = FileDir::makeCorrectFile($configdir . '/php-fcgi-starter');
$this->virtualhosts_data[$vhosts_filename] .= ' SuexecUserGroup "' . Settings::Get('system.mod_fcgid_httpuser') . '" "' . Settings::Get('system.mod_fcgid_httpgroup') . '"' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' SuexecUserGroup "' . Settings::Get('system.mod_fcgid_httpuser') . '" "' . Settings::Get('system.mod_fcgid_httpgroup') . '"' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . $mypath . '">' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . $mypath . '">' . "\n";
@@ -276,7 +281,9 @@ class Apache extends HttpConfigBase
// start block, cut off last pipe and close block // start block, cut off last pipe and close block
$filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, -1)) . ')'; $filesmatch = '(' . str_replace(".", "\.", substr($filesmatch, 0, -1)) . ')';
$this->virtualhosts_data[$vhosts_filename] .= ' <FilesMatch \.' . $filesmatch . '$>' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' <FilesMatch \.' . $filesmatch . '$>' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' SetHandler proxy:unix:' . $php->getInterface()->getSocketFile() . '|fcgi://localhost' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' <If "-f %{SCRIPT_FILENAME}">' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' SetHandler proxy:unix:' . $php->getInterface()->getSocketFile() . '|fcgi://localhost' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' </If>' . "\n";
$this->virtualhosts_data[$vhosts_filename] .= ' </FilesMatch>' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' </FilesMatch>' . "\n";
if ($phpconfig['pass_authorizationheader'] == '1') { if ($phpconfig['pass_authorizationheader'] == '1') {
$this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . $mypath . '">' . "\n"; $this->virtualhosts_data[$vhosts_filename] .= ' <Directory "' . $mypath . '">' . "\n";
@@ -816,6 +823,7 @@ class Apache extends HttpConfigBase
$modrew_red = ' [R=' . $code . ';L,NE]'; $modrew_red = ' [R=' . $code . ';L,NE]';
} }
$vhost_content .= $this->getLogfiles($domain);
// redirect everything, not only root-directory, #541 // redirect everything, not only root-directory, #541
$vhost_content .= ' <IfModule mod_rewrite.c>' . "\n"; $vhost_content .= ' <IfModule mod_rewrite.c>' . "\n";
$vhost_content .= ' RewriteEngine On' . "\n"; $vhost_content .= ' RewriteEngine On' . "\n";
@@ -842,24 +850,26 @@ class Apache extends HttpConfigBase
} }
$vhost_content .= $this->getLogfiles($domain); $vhost_content .= $this->getLogfiles($domain);
if ($domain['specialsettings'] != '' && ($ssl_vhost == false || ($ssl_vhost == true && $domain['include_specialsettings'] == 1))) { if ($this->deactivated == false) {
$vhost_content .= $this->processSpecialConfigTemplate($domain['specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; if ($domain['specialsettings'] != '' && ($ssl_vhost == false || ($ssl_vhost == true && $domain['include_specialsettings'] == 1))) {
} $vhost_content .= $this->processSpecialConfigTemplate($domain['specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
if ($domain['ssl_specialsettings'] != '' && $ssl_vhost == true) { if ($domain['ssl_specialsettings'] != '' && $ssl_vhost == true) {
$vhost_content .= $this->processSpecialConfigTemplate($domain['ssl_specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; $vhost_content .= $this->processSpecialConfigTemplate($domain['ssl_specialsettings'], $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
} }
if ($_vhost_content != '') { if ($_vhost_content != '') {
$vhost_content .= $_vhost_content; $vhost_content .= $_vhost_content;
} }
if (Settings::Get('system.default_vhostconf') != '' && ($ssl_vhost == false || ($ssl_vhost == true && Settings::Get('system.include_default_vhostconf') == 1))) { if (Settings::Get('system.default_vhostconf') != '' && ($ssl_vhost == false || ($ssl_vhost == true && Settings::Get('system.include_default_vhostconf') == 1))) {
$vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_vhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; $vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_vhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
} }
if (Settings::Get('system.default_sslvhostconf') != '' && $ssl_vhost == true) { if (Settings::Get('system.default_sslvhostconf') != '' && $ssl_vhost == true) {
$vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n"; $vhost_content .= $this->processSpecialConfigTemplate(Settings::Get('system.default_sslvhostconf'), $domain, $domain['ip'], $domain['port'], $ssl_vhost) . "\n";
}
} }
} }
@@ -964,8 +974,8 @@ class Apache extends HttpConfigBase
if ($domain['openbasedir'] == '1') { if ($domain['openbasedir'] == '1') {
if ($domain['openbasedir_path'] == '1' || strstr($domain['documentroot'], ":") !== false) { if ($domain['openbasedir_path'] == '1' || strstr($domain['documentroot'], ":") !== false) {
$_phpappendopenbasedir = Domain::appendOpenBasedirPath($domain['customerroot'], true); $_phpappendopenbasedir = Domain::appendOpenBasedirPath($domain['customerroot'], true);
} else if ($domain['openbasedir_path'] == '2' && strpos(dirname($domain['documentroot']).'/', $domain['customerroot']) !== false) { } else if ($domain['openbasedir_path'] == '2' && strpos(dirname($domain['documentroot']) . '/', $domain['customerroot']) !== false) {
$_phpappendopenbasedir = Domain::appendOpenBasedirPath(dirname($domain['documentroot']).'/', true); $_phpappendopenbasedir = Domain::appendOpenBasedirPath(dirname($domain['documentroot']) . '/', true);
} else { } else {
$_phpappendopenbasedir = Domain::appendOpenBasedirPath($domain['documentroot'], true); $_phpappendopenbasedir = Domain::appendOpenBasedirPath($domain['documentroot'], true);
} }
@@ -1013,10 +1023,10 @@ class Apache extends HttpConfigBase
} }
$statDocroot = FileDir::makeCorrectFile($domain['customerroot'] . '/' . $statTool . $statDomain); $statDocroot = FileDir::makeCorrectFile($domain['customerroot'] . '/' . $statTool . $statDomain);
$stats_text .= ' Alias /'.$statTool.' "' . $statDocroot . '"' . "\n"; $stats_text .= ' Alias /' . $statTool . ' "' . $statDocroot . '"' . "\n";
// awstats special requirement for icons // awstats special requirement for icons
if ($statTool == 'awstats') { if ($statTool == 'awstats') {
$stats_text .= ' Alias /awstats-icon "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n"; $stats_text .= ' Alias /awstats-icon "' . FileDir::makeCorrectDir(Settings::Get('system.awstats_icons')) . '"' . "\n";
} }
return $stats_text; return $stats_text;

View File

@@ -521,6 +521,8 @@ EOC;
self::runAcmeSh($certrow, $domains, $cronlog, $do_force); 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
Cronjob::inserttask(TaskId::REBUILD_VHOST);
} }
} }
} }

View File

@@ -406,6 +406,7 @@ class Lighttpd extends HttpConfigBase
// Get domain's redirect code // Get domain's redirect code
$code = Domain::getDomainRedirectCode($domain['id']); $code = Domain::getDomainRedirectCode($domain['id']);
$vhost_content .= $this->getLogFiles($domain);
$vhost_content .= ' url.redirect-code = ' . $code . "\n"; $vhost_content .= ' url.redirect-code = ' . $code . "\n";
$vhost_content .= ' url.redirect = (' . "\n"; $vhost_content .= ' url.redirect = (' . "\n";
$vhost_content .= ' "^/(.*)$" => "' . $uri . '$1"' . "\n"; $vhost_content .= ' "^/(.*)$" => "' . $uri . '$1"' . "\n";

View File

@@ -586,6 +586,7 @@ class Nginx extends HttpConfigBase
// Get domain's redirect code // Get domain's redirect code
$code = Domain::getDomainRedirectCode($domain['id']); $code = Domain::getDomainRedirectCode($domain['id']);
$vhost_content .= $this->getLogFiles($domain);
$vhost_content .= "\t" . 'location / {' . "\n"; $vhost_content .= "\t" . 'location / {' . "\n";
$vhost_content .= "\t\t" . 'return ' . $code . ' ' . $uri . '$request_uri;' . "\n"; $vhost_content .= "\t\t" . 'return ' . $code . ' ' . $uri . '$request_uri;' . "\n";
$vhost_content .= "\t" . '}' . "\n"; $vhost_content .= "\t" . '}' . "\n";

View File

@@ -140,6 +140,12 @@ class FileDir
if (is_link($check_dir)) { if (is_link($check_dir)) {
$original_target = $check_dir; $original_target = $check_dir;
$check_dir = readlink($check_dir); $check_dir = readlink($check_dir);
$link_dir = dirname($original_target);
// check whether the link is relative or absolute
if (substr($check_dir, 0, 1) != '/') {
// relative directory, prepend link_dir
$check_dir = $link_dir . '/' . $check_dir;
}
if (substr($check_dir, 0, strlen($fixed_homedir)) != $fixed_homedir) { if (substr($check_dir, 0, strlen($fixed_homedir)) != $fixed_homedir) {
throw new Exception("Found symlink pointing outside of customer home directory: " . substr($original_target, strlen($fixed_homedir))); throw new Exception("Found symlink pointing outside of customer home directory: " . substr($original_target, strlen($fixed_homedir)));
} }
@@ -287,7 +293,7 @@ class FileDir
$tpl_content = lng('admin.templates.unconfigured_content_fallback'); $tpl_content = lng('admin.templates.unconfigured_content_fallback');
} }
} }
$redirect_file = FileDir::makeCorrectFile(Froxlor::getInstallDir().'/notice.'.$tpl_ext); $redirect_file = FileDir::makeCorrectFile(Froxlor::getInstallDir() . '/notice.' . $tpl_ext);
file_put_contents($redirect_file, $tpl_content); file_put_contents($redirect_file, $tpl_content);
return basename($redirect_file); return basename($redirect_file);
} }

View File

@@ -31,7 +31,7 @@ final class Froxlor
{ {
// Main version variable // Main version variable
const VERSION = '2.1.6'; 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 = '202312120'; const DBVERSION = '202312120';

View File

@@ -465,6 +465,7 @@ class PhpHelper
'mysql_unprivileged_pass', 'mysql_unprivileged_pass',
'admin_pass', 'admin_pass',
'admin_pass_confirm', 'admin_pass_confirm',
'panel_password_special_char',
]; ];
if (!empty($global)) { if (!empty($global)) {
$tmp = $global; $tmp = $global;

View File

@@ -103,7 +103,7 @@ class Traffic
} }
// sort users by total traffic // sort users by total traffic
usort($users, function ($user_a, $user_b) { uasort($users, function ($user_a, $user_b) {
if ($user_a['total'] == $user_b['total']) { if ($user_a['total'] == $user_b['total']) {
return 0; return 0;
} }

View File

@@ -25,6 +25,7 @@
namespace Froxlor\UI\Callbacks; namespace Froxlor\UI\Callbacks;
use Froxlor\CurrentUser;
use Froxlor\Database\Database; use Froxlor\Database\Database;
use Froxlor\Domain\Domain as DDomain; use Froxlor\Domain\Domain as DDomain;
use Froxlor\FileDir; use Froxlor\FileDir;
@@ -113,7 +114,7 @@ class Domain
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) {
@@ -155,7 +156,7 @@ 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)));
} }
public static function canEditSSL(array $attributes): bool public static function canEditSSL(array $attributes): bool
@@ -165,7 +166,7 @@ class Domain
&& DDomain::domainHasSslIpPort($attributes['fields']['id']) && DDomain::domainHasSslIpPort($attributes['fields']['id'])
&& (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'] == 0 && (!CurrentUser::isAdmin() || (CurrentUser::isAdmin() && (int)$attributes['fields']['email_only'] == 0))
&& !$attributes['fields']['deactivated'] && !$attributes['fields']['deactivated']
) { ) {
return true; return true;

View File

@@ -25,6 +25,7 @@
namespace Froxlor\UI\Callbacks; namespace Froxlor\UI\Callbacks;
use Froxlor\CurrentUser;
use Froxlor\Settings; use Froxlor\Settings;
class Style class Style
@@ -68,7 +69,7 @@ class Style
$termination_css = 'table-danger'; $termination_css = 'table-danger';
} }
} }
$deactivated = $attributes['fields']['deactivated'] || $attributes['fields']['customer_deactivated']; $deactivated = $attributes['fields']['deactivated'] || (CurrentUser::isAdmin() && $attributes['fields']['customer_deactivated']);
return $deactivated ? 'table-info' : $termination_css; return $deactivated ? 'table-info' : $termination_css;
} }

View File

@@ -90,9 +90,10 @@ class Text
public static function customerNoteDetailModal(array $attributes): array public static function customerNoteDetailModal(array $attributes): array
{ {
$note = $attributes['fields']['custom_notes'] ?? ''; $note = $attributes['fields']['custom_notes'] ?? '';
$key = $attributes['fields']['customerid'] ?? $attributes['fields']['adminid'];
return [ return [
'entry' => $attributes['fields']['id'], 'entry' => $key,
'id' => 'cnModal' . $attributes['fields']['id'], 'id' => 'cnModal' . $key,
'title' => lng('usersettings.custom_notes.title') . ': ' . ($attributes['fields']['loginname'] ?? $attributes['fields']['adminname']), 'title' => lng('usersettings.custom_notes.title') . ': ' . ($attributes['fields']['loginname'] ?? $attributes['fields']['adminname']),
'body' => nl2br(Markdown::cleanCustomNotes($note)) 'body' => nl2br(Markdown::cleanCustomNotes($note))
]; ];

View File

@@ -217,7 +217,8 @@ class Form
{ {
$returnvalue = []; $returnvalue = [];
if (is_array($fielddata) && isset($fielddata['type']) && $fielddata['type'] == 'select') { if (is_array($fielddata) && isset($fielddata['type']) && $fielddata['type'] == 'select') {
if ((!is_array($fielddata['select_var']) || empty($fielddata['select_var'])) && (isset($fielddata['option_options_method']))) { if ((empty($fielddata['select_var']) || !is_array($fielddata['select_var'])) && (isset($fielddata['option_options_method']))
) {
$returnvalue['select_var'] = call_user_func($fielddata['option_options_method']); $returnvalue['select_var'] = call_user_func($fielddata['option_options_method']);
} }
} }

View File

@@ -103,7 +103,7 @@ return [
'maxlength' => 10, 'maxlength' => 10,
'value' => '5s' 'value' => '5s'
], ],
'phpfpm_pass_authorizationheader' => [ 'pass_authorizationheader' => [
'visible' => Settings::Get('system.webserver') == "apache2", 'visible' => Settings::Get('system.webserver') == "apache2",
'label' => lng('admin.phpsettings.pass_authorizationheader'), 'label' => lng('admin.phpsettings.pass_authorizationheader'),
'type' => 'checkbox', 'type' => 'checkbox',

View File

@@ -106,7 +106,7 @@ return [
'maxlength' => 10, 'maxlength' => 10,
'value' => $result['fpm_reqslow'] 'value' => $result['fpm_reqslow']
], ],
'phpfpm_pass_authorizationheader' => [ 'pass_authorizationheader' => [
'visible' => Settings::Get('system.webserver') == "apache2", 'visible' => Settings::Get('system.webserver') == "apache2",
'label' => lng('admin.phpsettings.pass_authorizationheader'), 'label' => lng('admin.phpsettings.pass_authorizationheader'),
'type' => 'checkbox', 'type' => 'checkbox',

View File

@@ -369,7 +369,7 @@ if (CurrentUser::hasSession()) {
} }
// update cookie lifetime // update cookie lifetime
$cookie_params = [ $cookie_params = [
'expires' => time() + Settings::Get('session.sessiontimeout'), 'expires' => time() + min(Settings::Get('session.sessiontimeout'), 31536000),
'path' => '/', 'path' => '/',
'domain' => UI::getCookieHost(), 'domain' => UI::getCookieHost(),
'secure' => UI::requestIsHttps(), 'secure' => UI::requestIsHttps(),

6
package-lock.json generated
View File

@@ -776,9 +776,9 @@
} }
}, },
"node_modules/follow-redirects": { "node_modules/follow-redirects": {
"version": "1.15.3", "version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {

View File

@@ -31,7 +31,7 @@ export default function () {
planid: pid planid: pid
}, },
dataType: "json", dataType: "json",
beforeSend: function(request) { beforeSend: function (request) {
request.setRequestHeader('X-CSRF-TOKEN', document.querySelector('meta[name="csrf-token"]').getAttribute('content')); request.setRequestHeader('X-CSRF-TOKEN', document.querySelector('meta[name="csrf-token"]').getAttribute('content'));
}, },
success: function (json) { success: function (json) {

View File

@@ -13,6 +13,9 @@ export default function () {
customerid: cid customerid: cid
}, },
dataType: "json", dataType: "json",
beforeSend: function (request) {
request.setRequestHeader('X-CSRF-TOKEN', document.querySelector('meta[name="csrf-token"]').getAttribute('content'));
},
success: function (json) { success: function (json) {
if (json.length > 0) { if (json.length > 0) {
$('#phpsettingid option').each(function () { $('#phpsettingid option').each(function () {
@@ -45,6 +48,10 @@ export default function () {
id: $('input[name=id]').val(), newval: +$('#speciallogfile').is(':checked') id: $('input[name=id]').val(), newval: +$('#speciallogfile').is(':checked')
}, },
dataType: "json", dataType: "json",
async: false,
beforeSend: function (request) {
request.setRequestHeader('X-CSRF-TOKEN', document.querySelector('meta[name="csrf-token"]').getAttribute('content'));
},
success: function (json) { success: function (json) {
if (json.changed) { if (json.changed) {
$('#speciallogfile').addClass('is-invalid'); $('#speciallogfile').addClass('is-invalid');

View File

@@ -15,6 +15,9 @@ export default function () {
ip: ipval ip: ipval
}, },
dataType: "json", dataType: "json",
beforeSend: function (request) {
request.setRequestHeader('X-CSRF-TOKEN', document.querySelector('meta[name="csrf-token"]').getAttribute('content'));
},
success: function (json) { success: function (json) {
if (json != 0) { if (json != 0) {
$('#ip').addClass('is-invalid'); $('#ip').addClass('is-invalid');